53 integer,
intent(in) :: ixI^L, ixO^L
54 double precision,
intent(in) :: w(ixI^S,nw)
55 double precision,
intent(in) :: x(ixI^S,1:ndim)
56 double precision,
intent(out):: res(ixI^S)
65 double precision :: gamma
69 procedure(
fld_get_var),
pointer,
nopass :: get_rfactor => null()
96 character(len=*),
intent(in) :: files(:)
105 do n = 1,
size(files)
106 open(
unitpar, file=trim(files(n)), status=
"old")
107 read(
unitpar, fld_list,
end=111)
131 call mpistop(
"please set the constant opacity to a reasonable value")
135 call mpistop(
"convergence tolerance for root solver too strict")
138 if(
mype==0) print *,
'Will do photon tiring explicit!!!'
143 call mpistop(
"convergence tolerance for MG solver too strict")
152 call mpistop(
"nth_for_diff_mg must be 1 or 2")
164 mg%operator_type = mg_vhelmholtz
166 mg%smoother_type = mg_smoother_gsrb
170 if(
si_unit)
call mpistop(
"adjust opal module with SI-cgs conversions for SI - or use cgs!")
188 mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
189 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
192 mg%bc(ib, mg_iphi)%bc_type = mg_bc_dirichlet
193 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
196 mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
197 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
202 print *,
'Special boundary for Erad needs specific user-set MG BC treatment'
203 print *,
' and this could be through usr_special_mg_bc call'
209 call mpistop(
"divE_multigrid warning: unknown b.c. ")
213 mg%bc(ib, mg_iveps)%bc_type = mg_bc_neumann
214 mg%bc(ib, mg_iveps)%bc_value = 0.0_dp
227 integer,
intent(in) :: ixi^
l, ixo^
l
228 double precision,
intent(in) :: qdt, x(ixi^s,1:
ndim)
229 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw)
230 double precision,
intent(inout) :: w(ixi^s,1:nw)
231 logical,
intent(in) :: qsourcesplit
232 logical,
intent(inout) :: active
235 integer :: idir,jdir,nth_for_fld,ix^
d
236 double precision,
dimension(ixI^S) :: a1,a2,a3,c0,c1,kappa
237 double precision,
dimension(ixI^S) :: e_gas,e_rad,tmp
238 double precision,
dimension(ixI^S,1:ndim,1:ndim) :: div_v,edd
252 call gradient(wctprim(ixi^s,iw_mom(jdir)),ixi^
l,ixo^
l,idir,tmp)
253 div_v(ixo^s,idir,jdir) = tmp(ixo^s)
258 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1)
261 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1) &
262 + div_v(ixo^s,1,2)*edd(ixo^s,1,2) &
263 + div_v(ixo^s,2,1)*edd(ixo^s,2,1) &
264 + div_v(ixo^s,2,2)*edd(ixo^s,2,2)
267 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1) &
268 + div_v(ixo^s,1,2)*edd(ixo^s,1,2) &
269 + div_v(ixo^s,1,3)*edd(ixo^s,1,3) &
270 + div_v(ixo^s,2,1)*edd(ixo^s,2,1) &
271 + div_v(ixo^s,2,2)*edd(ixo^s,2,2) &
272 + div_v(ixo^s,2,3)*edd(ixo^s,2,3) &
273 + div_v(ixo^s,3,1)*edd(ixo^s,3,1) &
274 + div_v(ixo^s,3,2)*edd(ixo^s,3,2) &
275 + div_v(ixo^s,3,3)*edd(ixo^s,3,3)
279 call gradient(wctprim(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,tmp,nth_for_fld)
282 tmp(ixo^s) = -a1(ixo^s)*tmp(ixo^s)
284 w(ixo^s,iw_mom(idir)) = w(ixo^s,iw_mom(idir))+ qdt*tmp(ixo^s)
286 w(ixo^s,iw_e) = w(ixo^s,iw_e) + qdt*wctprim(ixo^s,iw_mom(idir))*tmp(ixo^s)
290 w(ixo^s,iw_r_e) = w(ixo^s,iw_r_e) - qdt*wctprim(ixo^s,iw_r_e)*a3(ixo^s)
300 call fl%get_Rfactor(wct,x,ixi^
l,ixo^
l,tmp)
301 a1(ixo^s) = qdt*kappa(ixo^s)*
c_norm*
arad_norm*(fl%gamma-
one)**4/(wct(ixo^s,iw_rho)**3*tmp(ixo^s)**4)
302 a2(ixo^s) =
c_norm*kappa(ixo^s)*wct(ixo^s,iw_rho)*qdt
303 a3(ixo^s) = a3(ixo^s)*qdt
305 c0(ixo^s) = ((
one+a2(ixo^s)+a3(ixo^s))*e_gas(ixo^s)+a2(ixo^s)*e_rad(ixo^s))/a1(ixo^s)/(
one+a3(ixo^s))
306 c1(ixo^s) = (
one+a2(ixo^s)+a3(ixo^s))/a1(ixo^s)/(
one+a3(ixo^s))
309 {
do ix^
d = ixomin^
d,ixomax^
d\}
318 call mpistop(
'root-method not known')
322 e_rad(ixo^s) = (a1(ixo^s)*e_gas(ixo^s)**4.d0+e_rad(ixo^s))/(
one+a2(ixo^s)+a3(ixo^s))
325 {
do ix^db= ixomin^db,ixomax^db\}
327 write(*,*)
"Error in FLD add_fld_rad_force: small value"
328 write(*,*)
"of internal or radiation energy density after exchange"
330 write(*,*)
"Location: ", x(ix^
d,:)
331 write(*,*)
"Cell number: ", ix^
d
332 write(*,*)
"internal energy density is=",e_gas(ix^
d),
" versus small_e=",
small_e
333 write(*,*)
"radiation energy density is=",e_rad(ix^
d),
" versus small_r_e=",
small_r_e
334 call mpistop(
"FLD error:May need to turn on fixes")
339 if(fix_small_values)
then
340 {
do ix^d = ixomin^d,ixomax^d\ }
341 e_gas(ix^d) = max(e_gas(ix^d),small_e)
342 e_rad(ix^d) = max(e_rad(ix^d),small_r_e)
349 w(ixo^s,iw_e) = e_gas(ixo^s)
350 w(ixo^s,iw_e) = w(ixo^s,iw_e)+half*sum(w(ixo^s,iw_mom(:))**2,dim=ndim+1)/w(ixo^s,iw_rho)
351 if(
allocated(iw_mag))
then
352 w(ixo^s,iw_e) = w(ixo^s,iw_e)+half*sum(w(ixo^s,iw_mag(:))**2,dim=ndim+1)
355 w(ixo^s,iw_r_e) = e_rad(ixo^s)
365 integer,
intent(in) :: ixi^
l, ixo^
l
366 double precision,
intent(in) ::
dx^
d, x(ixi^s,1:
ndim), w(ixi^s,1:nw)
367 double precision,
intent(out) :: invtauc(ixi^s)
370 double precision :: dxinv(1:
ndim)
371 double precision :: kappa(ixi^s)
374 ^
d&dxinv(^
d)=one/
dx^
d;
375 invtauc(ixo^s)=4.0d0*minval(dxinv(1:
ndim))/(3.0d0*kappa(ixo^s)*w(ixo^s,iw_rho))
386 integer,
intent(in) :: ixi^
l, ixo^
l
387 double precision,
intent(in) ::
dx^
d, x(ixi^s,1:
ndim), w(ixi^s,1:nw)
388 double precision,
intent(inout) :: dtnew
391 integer :: idim,idims,nth_for_fld
392 double precision :: dxinv(1:
ndim), max_grav
393 double precision :: lambda(ixi^s),fld_r(ixi^s)
394 double precision :: tmp(ixi^s),boostfactor
395 double precision :: max_diff,max_diff_coef,max_diff_dim,dtdifflimit
396 double precision :: cmax(ixi^s),cmaxtot(ixi^s),courantmaxtots
398 if(
fld_debug)print *,
'DT limit on entry to radforce_get_dt=',dtnew
402 ^
d&dxinv(^
d)=one/
dx^
d;
404 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idim,tmp,nth_for_fld)
405 max_grav = maxval(dabs(-lambda(ixo^s)*tmp(ixo^s)/w(ixo^s,iw_rho)))
406 max_grav = max(max_grav, epsilon(1.0d0))
407 dtnew = min(dtnew, 1.0d0 / dsqrt(max_grav * dxinv(idim)))
411 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idim,tmp,nth_for_fld)
412 max_grav = maxval(dabs(-lambda(ixo^s)*tmp(ixo^s)/w(ixo^s,iw_rho))/
block%ds(ixo^s,idim))
413 max_grav = max(max_grav, epsilon(1.0d0))
414 dtnew = min(dtnew, 1.0d0 / dsqrt(max_grav))
417 if(
fld_debug)print *,
'DT limit after RADFORCE eff grav=',dtnew
424 max_diff_coef = maxval(
c_norm*lambda(ixo^s)/(w(ixo^s,iw_rho)*tmp(ixo^s)))
425 ^
d&dxinv(^
d)=one/
dx^
d;
427 max_diff_dim = max(2.0d0*
ndim*max_diff_coef*dxinv(idim)**2, epsilon(1.0d0))
428 max_diff = max(max_diff,max_diff_dim)
432 max_diff_coef = maxval(
c_norm*lambda(ixo^s)/(w(ixo^s,iw_rho)*tmp(ixo^s))/
block%ds(ixo^s,idim)**2)
433 max_diff_dim = max(2.0d0*
ndim*max_diff_coef, epsilon(1.0d0))
434 max_diff = max(max_diff,max_diff_dim)
437 dtdifflimit=1.0d0/max_diff
438 if(
fld_debug) print *,
'DT limit from diffusion is actually=',dtdifflimit
444 dtdifflimit=dtdifflimit*boostfactor
445 if(
fld_debug) print *,
'DT limit from diffusion is boosted to=',dtdifflimit
446 dtnew=min(dtnew,dtdifflimit)
447 if(
fld_debug) print *,
'DT limit after diffusion is =',dtnew
453 ^
d&dxinv(^
d)=one/
dx^
d;
455 cmax(ixo^s)=dabs(w(ixo^s,iw_mom(idims)))+dsqrt(tmp(ixo^s))
457 cmaxtot(ixo^s)=cmax(ixo^s)*dxinv(idims)
459 cmaxtot(ixo^s)=cmaxtot(ixo^s)+cmax(ixo^s)*dxinv(idims)
464 cmax(ixo^s)=dabs(w(ixo^s,iw_mom(idims)))+dsqrt(tmp(ixo^s))
466 cmaxtot(ixo^s)=cmax(ixo^s)/
block%ds(ixo^s,idims)
468 cmaxtot(ixo^s)=cmaxtot(ixo^s)+cmax(ixo^s)/
block%ds(ixo^s,idims)
473 courantmaxtots=maxval(cmaxtot(ixo^s))
475 if(courantmaxtots>smalldouble) dtnew=min(dtnew,
courantpar/courantmaxtots)
476 if(
fld_debug)print *,
'DT limit FINALLY ENFORCED IS NOW=',dtnew
488 integer,
intent(in) :: ixi^
l, ixo^
l
489 double precision,
intent(in) :: w(ixi^s, 1:nw)
490 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
491 double precision,
intent(out) :: fld_kappa(ixi^s)
495 double precision :: rho0,temp0,kapp0
496 double precision :: temp(ixi^s)
504 call fl%get_tgas(w,x,ixi^
l,ixo^
l,temp)
505 {
do ix^
d=ixomin^
d,ixomax^
d\ }
513 call mpistop(
"special opacity not defined")
517 call mpistop(
"Doesn't know opacity law")
525 integer,
intent(in) :: ixi^
l, ixo^
l
526 double precision,
intent(in) :: w(ixi^s, 1:nw)
527 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
528 double precision,
intent(out):: rad_pressure(ixi^s,1:
ndim,1:
ndim)
531 double precision :: eddington_tensor(ixi^s,1:
ndim,1:
ndim)
532 double precision :: lambda(ixi^s),fld_r(ixi^s)
538 print *,
'In get_radPress with nth=',nth,
' on ixO=',ixo^
l
539 print *,
'Max and Min value of fe'
540 print *,maxval(eddington_tensor(ixo^s,1:
ndim,1:
ndim))
541 print *,minval(eddington_tensor(ixo^s,1:
ndim,1:
ndim))
542 print *,
'Max and Min value of Erad'
543 print *,maxval(w(ixo^s,iw_r_e))
544 print *,minval(w(ixo^s,iw_r_e))
545 print *,
'End get_radPress'
549 rad_pressure(ixo^s,i,j) = eddington_tensor(ixo^s,i,j)*w(ixo^s,iw_r_e)
562 integer,
intent(in) :: ixi^
l,ixo^
l,nth
563 double precision,
intent(in) :: w(ixi^s,1:nw)
564 double precision,
intent(in) :: x(ixi^s,1:
ndim)
565 double precision,
intent(out) :: fld_r(ixi^s),fld_lambda(ixi^s)
568 double precision :: wprim(ixi^s,1:nw)
570 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
584 integer,
intent(in) :: ixi^
l,ixo^
l,nth
585 double precision,
intent(in) :: w(ixi^s,1:nw)
586 double precision,
intent(in) :: x(ixi^s,1:
ndim)
587 double precision,
intent(out) :: fld_r(ixi^s),fld_lambda(ixi^s)
590 integer :: idir, ix^
d
591 double precision :: kappa(ixi^s),normgrad2(ixi^s)
592 double precision :: grad_r_e(ixi^s)
597 fld_lambda(ixo^s) = 1.d0/3.d0
601 normgrad2(ixo^s) = zero
603 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
604 normgrad2(ixo^s) = normgrad2(ixo^s)+grad_r_e(ixo^s)**2
609 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
610 where(normgrad2(ixo^s)<smalldouble**2)
613 fld_lambda(ixo^s) = 1.0d0/3.0d0
615 fld_lambda(ixo^s) = one/fld_r(ixo^s)
620 normgrad2(ixo^s) = zero
622 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
623 normgrad2(ixo^s) = normgrad2(ixo^s) + grad_r_e(ixo^s)**2
626 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
629 fld_lambda(ixo^s) = (2.d0+fld_r(ixo^s))/(6.d0+3*fld_r(ixo^s)+fld_r(ixo^s)**2)
633 normgrad2(ixo^s) = zero
635 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
636 normgrad2(ixo^s) = normgrad2(ixo^s) + grad_r_e(ixo^s)**2
639 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
642 {
do ix^
d = ixomin^
d,ixomax^
d\ }
643 if(fld_r(ix^
d) .lt. 3.d0/2.d0)
then
644 fld_lambda(ix^
d) = 2.d0/(3.d0+dsqrt(9.d0+12.d0*fld_r(ix^
d)**2))
646 fld_lambda(ix^
d) = 1.d0/(1.d0+fld_r(ix^
d)+dsqrt(1.d0+2.d0*fld_r(ix^
d)))
651 call mpistop(
"special fluxlimiter not defined")
655 call mpistop(
'Fluxlimiter unknown')
667 integer,
intent(in) :: ixi^
l, ixo^
l
668 double precision,
intent(in) :: w(ixi^s, 1:nw)
669 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
670 double precision,
intent(out) :: rad_flux(ixi^s, 1:
ndim)
673 integer :: idir,nth_for_fld
674 double precision :: wprim(ixi^s,1:nw)
675 double precision :: grad_r_e(ixi^s)
676 double precision :: kappa(ixi^s), lambda(ixi^s), fld_r(ixi^s)
678 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
688 call gradient(wprim(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth_for_fld)
689 rad_flux(ixo^s,idir)=-(
c_norm*lambda(ixo^s)/(kappa(ixo^s)*wprim(ixo^s,iw_rho)))*grad_r_e(ixo^s)
698 integer,
intent(in) :: ixI^L, ixO^L, nth
699 double precision,
intent(in) :: w(ixI^S, 1:nw)
700 double precision,
intent(in) :: x(ixI^S, 1:ndim)
701 double precision,
intent(out) :: eddington_tensor(ixI^S,1:ndim,1:ndim)
702 double precision,
intent(out) :: lambda(ixI^S),fld_R(ixI^S)
706 double precision :: normgrad2(ixI^S)
707 double precision :: tmp(ixI^S),grad_r_e(ixI^S,1:ndim)
708 double precision :: nn_regularized(ixI^S,1:ndim,1:ndim)
710 normgrad2(ixo^s) = zero
712 call gradient(w(ixi^s, iw_r_e),ixi^l,ixo^l,idir,tmp,nth)
713 grad_r_e(ixo^s,idir)=tmp(ixo^s)
714 normgrad2(ixo^s)=normgrad2(ixo^s)+tmp(ixo^s)**2
719 nn_regularized(ixo^s,idir,jdir)=(grad_r_e(ixo^s,idir)*grad_r_e(ixo^s,jdir)+smalldouble**2)/(normgrad2(ixo^s)+smalldouble**2)
721 nn_regularized(ixo^s,idir,jdir)=(grad_r_e(ixo^s,idir)*grad_r_e(ixo^s,jdir))/(normgrad2(ixo^s)+smalldouble**2)
728 tmp(ixo^s) = lambda(ixo^s)+(lambda(ixo^s)*fld_r(ixo^s))**2
731 eddington_tensor(ixo^s,idir,idir) = half*(one-tmp(ixo^s))
736 if(idir .ne. jdir) eddington_tensor(ixo^s,idir,jdir) = zero
738 eddington_tensor(ixo^s,idir,jdir) = eddington_tensor(ixo^s,idir,jdir)+&
739 half*(3.d0*tmp(ixo^s)-one)*nn_regularized(ixo^s,idir,jdir)
746 integer,
intent(in) :: ixI^L, ixO^L
747 double precision,
intent(in) :: w(ixI^S, 1:nw)
748 double precision,
intent(out) :: e_gas(ixI^S),E_rad(ixI^S)
752 e_gas(ixo^s) = w(ixo^s,iw_e)-half*sum(w(ixo^s,iw_mom(:))**2,dim=
ndim+1)/w(ixo^s,iw_rho)
753 if(
allocated(iw_mag))
then
754 e_gas(ixo^s) = e_gas(ixo^s)-half*sum(w(ixo^s,iw_mag(:))**2,dim=
ndim+1)
756 e_rad(ixo^s) = w(ixo^s,iw_r_e)
759 {
do ix^db= ixomin^db,ixomax^db\}
761 write(*,*)
"Error in FLD get_egas_Erad: small value"
763 write(*,*)
"Cell number: ", ix^d
764 write(*,*)
"internal energy density is=",e_gas(ix^d),
" versus small_e=",
small_e
765 write(*,*)
"radiation energy density is=",e_rad(ix^d),
" versus small_r_e=",
small_r_e
766 call mpistop(
"FLD error:May need to turn on fixes")
771 if(fix_small_values)
then
772 {
do ix^d = ixomin^d,ixomax^d\ }
773 e_gas(ix^d) = max(e_gas(ix^d),small_e)
774 e_rad(ix^d) = max(e_rad(ix^d),small_r_e)
791 double precision,
intent(in) :: qdt
792 double precision,
intent(in) :: qtc
793 double precision,
intent(in) :: dtfactor
796 integer,
parameter :: max_its = 100
797 integer :: n,ixo^
l,ix^
d
798 double precision :: res, max_residual, mg_lambda, fac
799 double precision :: wmax(nw),wmin(nw)
800 double precision :: wmaxb(nw),wminb(nw)
801 integer :: iigrid, igrid
811 do iigrid=1,igridstail; igrid=igrids(iigrid);
812 {
do ix^
d = ixomin^
d,ixomax^
d\ }
827 print *,
'Currently at time=',
global_time,
' time step=',qdt,
' dtfactor=',dtfactor
828 print *,
'at start of MG solver, we have fld_diff_tol =',
fld_diff_tol
829 print *,
'at start of MG solver, we have LHS E_rad range as :',wmax(iw_r_e),wmin(iw_r_e)
830 print *,
'at start of MG solver, we have Diff coeff range as:',wmax(
i_diff_mg),wmin(
i_diff_mg)
831 print *,
'at start of MG solver, we have density range as :',wmax(iw_rho),wmin(iw_rho)
832 print *,
'at start of MG solver, we have RHS E_rad range as :',wmaxb(iw_r_e),wminb(iw_r_e)
833 print *,
'at start of MG solver, we have qdt as',qdt,
' and max_residual=',max_residual
834 print *,
'at start of MG solver, ratio coeffs on level 1 =',wmax(
i_diff_mg)/(
dx(1,1)**2)
839 call mg_set_methods(
mg)
840 if(.not.
mg%is_allocated)
call mpistop(
"multigrid tree not allocated yet")
848 call vhelmholtz_set_lambda(fac)
858 call mg_restrict(
mg, mg_iveps)
859 call mg_fill_ghost_cells(
mg, mg_iveps)
861 call mg_fas_fmg(
mg, .true., max_res=res)
862 if(
fld_debug.and.
mype==0)print *,
'MG residual obtained with FMG is =',res
864 if(res < max_residual)
exit
865 call mg_fas_vcycle(
mg, max_res=res)
866 if(
fld_debug.and.
mype==0)print *,
'MG residual obtained with Vcycle =',res,
' at step =',n
868 if(
fld_debug.and.
mype==0)print *,
'FINAL MG residual obtained is =',res
869 if(res .ge. max_residual)
then
871 write(*,*)
it,
' residual from MG ', res
872 write(*,*)
it,
' max_residual in MG ', max_residual
873 write(*,*)
it,
' dtfactor*qdt in MG ', qdt*dtfactor
874 print *,
'Currently at time=',
global_time,
' time step=',qdt,
' dtfactor=',dtfactor
877 call mpistop(
"no convergence in MG")
879 if(
mype==0)
write(*,*)
'WARNING for it=',
it,
' NO CONVERGENCE IN MG but still carry on'
887 do iigrid=1,igridstail; igrid=igrids(iigrid);
888 {
do ix^db= ixomin^db,ixomax^db\}
890 write(*,*)
"Error in FLD fld_implicit_update: small value"
891 write(*,*)
"of radiation energy density after MG"
893 write(*,*)
"Location: ", psa(igrid)%x(ix^
d,:),
" on grid",igrid
894 write(*,*)
"Cell number: ", ix^
d
895 write(*,*)
"radiation energy density is=",psa(igrid)%w(ix^
d,iw_r_e),
" versus small_r_e=",
small_r_e
896 call mpistop(
"FLD error:May need to turn on fixes")
902 if(fix_small_values)
then
904 do iigrid=1,igridstail; igrid=igrids(iigrid);
905 {
do ix^d = ixomin^d,ixomax^d\ }
906 psa(igrid)%w(ix^d,iw_r_e)= max(psa(igrid)%w(ix^d,iw_r_e),small_r_e)
915 type(state),
target :: psa(max_blocks)
918 integer :: iigrid, igrid, ixO^L
923 do iigrid=1,igridstail; igrid=igrids(iigrid);
934 double precision,
intent(in) :: qtc
936 integer :: iigrid, igrid
945 do iigrid=1,igridstail; igrid=igrids(iigrid);
956 integer,
intent(in) :: ixI^L, ixO^L
957 double precision,
intent(inout) :: w(ixI^S, 1:nw)
958 double precision,
intent(in) :: x(ixI^S, 1:ndim)
960 double precision :: divF(ixI^S)
961 integer :: idir, jxO^L, hxO^L
963 if(.not.
slab)
call mpistop(
"laplacian coded up for uniform cartesian grid")
970 hxo^l=ixo^l-
kr(idir,^
d);
971 jxo^l=ixo^l+
kr(idir,^
d);
972 divf(ixo^s) = divf(ixo^s) + &
986 w(ixo^s,iw_r_e) = divf(ixo^s)
996 integer,
intent(in) :: ixi^
l, ixo^
l
997 double precision,
intent(in) :: x(ixi^s,1:
ndim)
998 double precision,
intent(inout) :: w(ixi^s,1:nw)
1001 double precision :: wprim(ixi^s,1:nw)
1002 double precision :: kappa(ixi^s),lambda(ixi^s),fld_r(ixi^s)
1004 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
1010 w(ixo^s,
i_diff_mg) =
c_norm*lambda(ixo^s)/(kappa(ixo^s)*wprim(ixo^s,iw_rho))
1012 if(minval(w(ixo^s,
i_diff_mg))<smalldouble)
then
1013 print *,
'min diffcoef=',minval(w(ixo^s,
i_diff_mg))
1014 call mpistop(
"too small diffusion coefficient")
1016 if(maxval(w(ixo^s,
i_diff_mg))>bigdouble)
call mpistop(
"too large diffusion coefficient")
1019 print *,
'setting diffcoefs with data on',ixi^
l
1020 print *,
'min diffcoef=',minval(w(ixo^s,
i_diff_mg))
1021 print *,
'min lambda kappa rho fld_R'
1022 print *,minval(lambda(ixo^s))
1023 print *,minval(kappa(ixo^s))
1024 print *,minval(wprim(ixo^s,iw_rho))
1025 print *,minval(fld_r(ixo^s))
1026 print *,
'max diffcoef=',maxval(w(ixo^s,
i_diff_mg))
1027 print *,
'max lambda kappa rho fld_R'
1028 print *,maxval(lambda(ixo^s))
1029 print *,maxval(kappa(ixo^s))
1030 print *,maxval(wprim(ixo^s,iw_rho))
1031 print *,maxval(fld_r(ixo^s))
1032 print *,
'done setting diffcoefs in slot',
i_diff_mg,
' on range',ixo^
l
1041 double precision,
intent(in) :: c0, c1
1042 double precision,
intent(inout) :: e_gas
1043 double precision :: bisect_a, bisect_b, bisect_c
1044 integer :: n, max_its
1049 bisect_b = min(dabs(c0/c1),dabs(c0)**(1.d0/4.d0))+smalldouble
1051 bisect_c = (bisect_a + bisect_b)/two
1053 if(n .gt. max_its)
then
1054 call mpistop(
'No convergece in bisection scheme')
1077 call mpistop(
"Problem with fld bisection method")
1085 if(
fld_debug)print*,
"IGNORING GAS-RAD ENERGY EXCHANGE ", c0, c1
1087 call mpistop(
'issues in bisection scheme')
1096 2435 e_gas = (bisect_a + bisect_b)/two
1102 double precision,
intent(in) :: c0, c1
1103 double precision,
intent(inout) :: e_gas
1104 double precision :: xval, yval, der, deltax
1117 xval = xval + deltax
1119 if(ii .gt. 1d3)
then
1120 if(
fld_debug)print*,
'skip to bisection algorithm'
1131 double precision,
intent(in) :: c0, c1
1132 double precision,
intent(inout) :: e_gas
1133 double precision :: xval, yval, der, dder, deltax
1147 deltax = -two*yval*der/(two*der**2 - yval*dder)
1148 xval = xval + deltax
1150 if(ii .gt. 1d3)
then
1151 if(
fld_debug)print*,
'skip to Newton algorithm'
1162 double precision,
intent(in) :: e_gas
1163 double precision,
intent(in) :: c0, c1
1164 double precision :: val
1166 val = e_gas**4.d0 + c1*e_gas - c0
1172 double precision,
intent(in) :: e_gas
1173 double precision,
intent(in) :: c0, c1
1174 double precision :: der
1176 der = 4.d0*e_gas**3.d0 + c1
1182 double precision,
intent(in) :: e_gas
1183 double precision,
intent(in) :: c0, c1
1184 double precision :: dder
1186 dder = 4.d0*3.d0*e_gas**2.d0
Abstract interface for the gas-EoS getters the radiation fluid needs (same shape as thermal_conductio...
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module for physical and numeric constants.
double precision, parameter one
Module for flux limited diffusion (FLD)-approximation in Radiation-(Magneto)hydrodynamics simulations...
subroutine fld_get_eddington(w, x, ixil, ixol, eddington_tensor, lambda, fld_r, nth, fl)
Calculate Eddington-tensor (where w is primitive) also feeds back the flux limiter lambda and R.
double precision, public fld_bisect_tol
Tolerance for bisection method for Energy sourceterms This is a percentage of the minimum of gas- and...
subroutine, public fld_radforce_get_dt(w, ixil, ixol, dtnew, dxd, x, fl)
get dt limit for radiation force and FLD explicit source additions NOTE: w is primitive on entry
logical fld_force_mg_converged
switches for local debug purposes
double precision, public fld_diff_tol
Tolerance for radiative Energy diffusion.
subroutine update_diffcoeff(psa, fl)
subroutine fld_params_read(files)
public methods these are called in mod_hd_phys or mod_mhd_phys
character(len=40) fld_fluxlimiter
flux limiter choice
subroutine, public fld_get_radflux(w, x, ixil, ixol, rad_flux, fl)
Calculate Radiation Flux NOTE: only for diagnostics purposes (w conservative on entry) This returns c...
character(len=40) fld_opal_table
subroutine, public fld_get_opacity_prim(w, x, ixil, ixol, fld_kappa, fl)
Sets the opacity in the w-array by calling mod_opal_opacity NOTE: assumes primitives in w NOTE: assum...
double precision, public fld_boost_dt
subroutine get_and_check_egas_erad_from_conserved(w, ixil, ixol, e_gas, e_rad)
logical fld_slowsteps
handling ramp-up phase with explicit diffusion dt limit, slowly boosted
double precision, public fld_cnorm
subroutine evaluate_diffterm_onegrid(ixil, ixol, w, x)
inplace update of psa==>F_im(psa)
double precision function ddpolynomial_bisection(e_gas, c0, c1)
Evaluate second derivative of polynomial at argument e_gas.
subroutine, public fld_get_fluxlimiter_prim(w, x, ixil, ixol, fld_lambda, fld_r, nth, fl)
This subroutine calculates flux limiter lambda according to fld_fluxlimiter It also calculates fld_R ...
double precision, public fld_kappa0
Opacity value when using constant opacity.
subroutine newton_method(e_gas, c0, c1)
Find the root of the 4th degree polynomial using the Newton method.
double precision function polynomial_bisection(e_gas, c0, c1)
Evaluate polynomial at argument e_gas.
subroutine, public add_fld_rad_force(qdt, ixil, ixol, wct, wctprim, w, x, qsourcesplit, active, fl)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO This subroutine handles th...
character(len=40) fld_opacity_law
switches for opacity
character(len=40) fld_interaction_method
Which method to find the root for the energy interaction polynomial.
subroutine, public fld_set_mg_bounds
Set the boundaries for the diffusion of E.
subroutine, public fld_get_radpress(w, x, ixil, ixol, rad_pressure, fl)
Returns Radiation Pressure as tensor NOTE: w is primitive on entry.
subroutine, public fld_get_local_invtauc(w, ixil, ixol, dxd, x, invtauc, fl)
maybe needed for restricting the cmax/cmin in diffusion limit CURRENTLY UNUSED NOTE: w is primitive o...
logical fld_radforce_split
source split for energy interact and radforce:
logical fld_bound_diff
switches for using changed cmax-cmin bounds
subroutine, public fld_implicit_update(dtfactor, qdt, qtc, psa, psb, fl)
Calling all subroutines to perform the multigrid method Communicates rad_e and diff_coeff to multigri...
subroutine, public fld_get_fluxlimiter(w, x, ixil, ixol, fld_lambda, fld_r, nth, fl)
This subroutine calculates flux limiter lambda according to fld_fluxlimiter It also calculates fld_R ...
double precision function dpolynomial_bisection(e_gas, c0, c1)
Evaluate first derivative of polynomial at argument e_gas.
logical fld_tiring_explicit
switch to handle photon tiring explicit or implicit
subroutine, public fld_get_diffcoef_central(w, x, ixil, ixol, fl)
Calculates cell-centered diffusion coefficient to be used in multigrid.
integer i_diff_mg
diffusion coefficient for multigrid method
subroutine bisection_method(e_gas, c0, c1)
Find the root of the 4th degree polynomial using the bisection method.
subroutine, public fld_evaluate_implicit(qtc, psa, fl)
inplace update of psa==>F_im(psa)
subroutine, public fld_init()
Initialising FLD-module Read opacities Initialise Multigrid and adimensionalise kappa.
subroutine halley_method(e_gas, c0, c1)
Find the root of the 4th degree polynomial using the Halley method.
integer nth_for_diff_mg
diffusion coefficient stencil control
Module with basic grid data structures.
Module with geometry-related routines (e.g., divergence, curl)
subroutine gradient(q, ixil, ixol, idir, gradq, nth_in)
This module contains definitions of global parameters and variables and some generic functions/subrou...
type(state), pointer block
Block pointer for using one block and its previous state.
double precision const_kappae
double precision arad_norm
Normalised radiation constant.
double precision unit_density
Physical scaling factor for density.
double precision unit_opacity
Physical scaling factor for Opacity.
integer, parameter unitpar
file handle for IO
integer, parameter bc_asymm
double precision global_time
The global simulation time.
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer it
Number of time steps taken.
integer it_init
initial iteration count
integer, dimension(:, :), allocatable typeboundary
Array indicating the type of boundary condition per variable and per physical boundary.
integer, parameter ndim
Number of spatial dimensions for grid variables.
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
integer mype
The rank of the current MPI task.
double precision courantpar
The Courant (CFL) number used for the simulation.
integer ixm
the mesh range of a physical block without ghost cells
double precision, dimension(:), allocatable, parameter d
logical slab
Cartesian geometry or not.
integer slowsteps
If > 1, then in the first slowsteps-1 time steps dt is reduced by a factor .
integer, parameter bc_periodic
integer, parameter bc_special
boundary condition types
double precision small_r_e
double precision c_norm
Normalised speed of light.
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision unit_temperature
Physical scaling factor for temperature.
integer, parameter bc_cont
logical si_unit
Use SI units (.true.) or use cgs units (.false.)
double precision, dimension(:,:), allocatable dx
spatial steps for all dimensions at all levels
integer, parameter bc_symm
logical fix_small_values
fix small values with average or replace methods
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
logical use_multigrid
Use multigrid (only available in 2D and 3D)
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
integer refine_max_level
Maximal number of AMR levels.
integer max_blocks
The maximum number of grid blocks in a processor.
logical check_small_values
check and optionally fix unphysical small values (density, gas pressure)
Module to couple the octree-mg library to AMRVAC. This file uses the VACPP preprocessor,...
type(mg_t) mg
Data structure containing the multigrid tree.
subroutine mg_copy_to_tree(iw_from, iw_to, restrict, restrict_gc, factor, state_from)
Copy a variable to the multigrid tree, including a layer of ghost cells.
subroutine mg_copy_from_tree_gc(iw_from, iw_to, state_to)
Copy from multigrid tree with one layer of ghost cells. Corner ghost cells are not used/set.
This module reads in Rosseland-mean opacities from OPAL tables. Table opacity values are given in bas...
subroutine, public init_opal_table(tabledir, set_custom_tabledir)
This subroutine is called when the FLD radiation module is initialised. The OPAL tables for different...
subroutine, public set_opal_opacity(rho, temp, kappa)
This subroutine calculates the opacity for a given temperature-density structure. Opacities are read ...
This module defines the procedures of a physics module. It contains function pointers for the various...
procedure(sub_convert), pointer phys_to_primitive
integer phys_wider_stencil
To use wider stencils in flux calculations. A value of 1 will extend it by one cell in both direction...
procedure(sub_set_mg_bounds), pointer phys_set_mg_bounds
procedure(sub_get_csrad2), pointer phys_get_csrad2
Module with all the methods that users can customize in AMRVAC.
procedure(special_opacity), pointer usr_special_opacity
procedure(special_diffcoef), pointer usr_special_diffcoef
procedure(special_fluxlimiter), pointer usr_special_fluxlimiter
procedure(special_mg_bc), pointer usr_special_mg_bc
integer function var_set_extravar(name_cons, name_prim, ix)
Set extra variable in w, which is not advected and has no boundary conditions. This has to be done af...
Radiation fluid object: gas-EoS callbacks the FLD module needs, wired by the physics module at link t...