50 integer,
intent(in) :: ixI^L, ixO^L
51 double precision,
intent(in) :: w(ixI^S,nw)
52 double precision,
intent(in) :: x(ixI^S,1:ndim)
53 double precision,
intent(out):: res(ixI^S)
62 double precision :: gamma
66 procedure(
fld_get_var),
pointer,
nopass :: get_rfactor => null()
92 character(len=*),
intent(in) :: files(:)
101 do n = 1,
size(files)
102 open(
unitpar, file=trim(files(n)), status=
"old")
103 read(
unitpar, fld_list,
end=111)
127 call mpistop(
"please set the constant opacity to a reasonable value")
131 call mpistop(
"convergence tolerance for root solver too strict")
134 if(
mype==0) print *,
'Will do photon tiring explicit!!!'
139 call mpistop(
"convergence tolerance for MG solver too strict")
148 call mpistop(
"nth_for_diff_mg must be 1 or 2")
160 mg%operator_type = mg_vhelmholtz
162 mg%smoother_type = mg_smoother_gsrb
166 if(
si_unit)
call mpistop(
"adjust opal module with SI-cgs conversions for SI - or use cgs!")
184 mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
185 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
188 mg%bc(ib, mg_iphi)%bc_type = mg_bc_dirichlet
189 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
192 mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
193 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
198 print *,
'Special boundary for Erad needs specific user-set MG BC treatment'
199 print *,
' and this could be through usr_special_mg_bc call'
205 call mpistop(
"divE_multigrid warning: unknown b.c. ")
209 mg%bc(ib, mg_iveps)%bc_type = mg_bc_neumann
210 mg%bc(ib, mg_iveps)%bc_value = 0.0_dp
223 integer,
intent(in) :: ixi^
l, ixo^
l
224 double precision,
intent(in) :: qdt, x(ixi^s,1:
ndim)
225 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw)
226 double precision,
intent(inout) :: w(ixi^s,1:nw)
227 logical,
intent(in) :: qsourcesplit
228 logical,
intent(inout) :: active
231 integer :: idir,jdir,nth_for_fld,ix^
d
232 double precision,
dimension(ixI^S) :: a1,a2,a3,c0,c1,kappa
233 double precision,
dimension(ixI^S) :: e_gas,e_rad,tmp
234 double precision,
dimension(ixI^S,1:ndim,1:ndim) :: div_v,edd
248 call gradient(wctprim(ixi^s,iw_mom(jdir)),ixi^
l,ixo^
l,idir,tmp)
249 div_v(ixo^s,idir,jdir) = tmp(ixo^s)
254 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1)
257 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1) &
258 + div_v(ixo^s,1,2)*edd(ixo^s,1,2) &
259 + div_v(ixo^s,2,1)*edd(ixo^s,2,1) &
260 + div_v(ixo^s,2,2)*edd(ixo^s,2,2)
263 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1) &
264 + div_v(ixo^s,1,2)*edd(ixo^s,1,2) &
265 + div_v(ixo^s,1,3)*edd(ixo^s,1,3) &
266 + div_v(ixo^s,2,1)*edd(ixo^s,2,1) &
267 + div_v(ixo^s,2,2)*edd(ixo^s,2,2) &
268 + div_v(ixo^s,2,3)*edd(ixo^s,2,3) &
269 + div_v(ixo^s,3,1)*edd(ixo^s,3,1) &
270 + div_v(ixo^s,3,2)*edd(ixo^s,3,2) &
271 + div_v(ixo^s,3,3)*edd(ixo^s,3,3)
275 call gradient(wctprim(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,tmp,nth_for_fld)
278 tmp(ixo^s) = -a1(ixo^s)*tmp(ixo^s)
280 w(ixo^s,iw_mom(idir)) = w(ixo^s,iw_mom(idir))+ qdt*tmp(ixo^s)
282 w(ixo^s,iw_e) = w(ixo^s,iw_e) + qdt*wctprim(ixo^s,iw_mom(idir))*tmp(ixo^s)
286 w(ixo^s,iw_r_e) = w(ixo^s,iw_r_e) - qdt*wctprim(ixo^s,iw_r_e)*a3(ixo^s)
296 call fl%get_Rfactor(wct,x,ixi^
l,ixo^
l,tmp)
297 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)
298 a2(ixo^s) =
c_norm*kappa(ixo^s)*wct(ixo^s,iw_rho)*qdt
299 a3(ixo^s) = a3(ixo^s)*qdt
301 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))
302 c1(ixo^s) = (
one+a2(ixo^s)+a3(ixo^s))/a1(ixo^s)/(
one+a3(ixo^s))
305 {
do ix^
d = ixomin^
d,ixomax^
d\}
314 call mpistop(
'root-method not known')
318 e_rad(ixo^s) = (a1(ixo^s)*e_gas(ixo^s)**4.d0+e_rad(ixo^s))/(
one+a2(ixo^s)+a3(ixo^s))
321 {
do ix^db= ixomin^db,ixomax^db\}
323 write(*,*)
"Error in FLD add_fld_rad_force: small value"
324 write(*,*)
"of internal or radiation energy density after exchange"
326 write(*,*)
"Location: ", x(ix^
d,:)
327 write(*,*)
"Cell number: ", ix^
d
328 write(*,*)
"internal energy density is=",e_gas(ix^
d),
" versus small_e=",
small_e
329 write(*,*)
"radiation energy density is=",e_rad(ix^
d),
" versus small_r_e=",
small_r_e
330 call mpistop(
"FLD error:May need to turn on fixes")
335 if(fix_small_values)
then
336 {
do ix^d = ixomin^d,ixomax^d\ }
337 e_gas(ix^d) = max(e_gas(ix^d),small_e)
338 e_rad(ix^d) = max(e_rad(ix^d),small_r_e)
345 w(ixo^s,iw_e) = e_gas(ixo^s)
346 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)
347 if(
allocated(iw_mag))
then
348 w(ixo^s,iw_e) = w(ixo^s,iw_e)+half*sum(w(ixo^s,iw_mag(:))**2,dim=ndim+1)
351 w(ixo^s,iw_r_e) = e_rad(ixo^s)
363 integer,
intent(in) :: ixi^
l, ixo^
l
364 double precision,
intent(in) ::
dx^
d, x(ixi^s,1:
ndim), w(ixi^s,1:nw)
365 double precision,
intent(inout) :: dtnew
368 integer :: idim,idims,nth_for_fld
369 double precision :: dxinv(1:
ndim), max_grav
370 double precision :: lambda(ixi^s),fld_r(ixi^s)
371 double precision :: tmp(ixi^s),boostfactor
372 double precision :: max_diff,max_diff_coef,max_diff_dim,dtdifflimit
373 double precision :: cmax(ixi^s),cmaxtot(ixi^s),courantmaxtots
375 if(
fld_debug)print *,
'DT limit on entry to radforce_get_dt=',dtnew
379 ^
d&dxinv(^
d)=one/
dx^
d;
381 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idim,tmp,nth_for_fld)
382 max_grav = maxval(dabs(-lambda(ixo^s)*tmp(ixo^s)/w(ixo^s,iw_rho)))
383 max_grav = max(max_grav, epsilon(1.0d0))
384 dtnew = min(dtnew, 1.0d0 / dsqrt(max_grav * dxinv(idim)))
388 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idim,tmp,nth_for_fld)
389 max_grav = maxval(dabs(-lambda(ixo^s)*tmp(ixo^s)/w(ixo^s,iw_rho))/
block%ds(ixo^s,idim))
390 max_grav = max(max_grav, epsilon(1.0d0))
391 dtnew = min(dtnew, 1.0d0 / dsqrt(max_grav))
394 if(
fld_debug)print *,
'DT limit after RADFORCE eff grav=',dtnew
401 max_diff_coef = maxval(
c_norm*lambda(ixo^s)/(w(ixo^s,iw_rho)*tmp(ixo^s)))
402 ^
d&dxinv(^
d)=one/
dx^
d;
404 max_diff_dim = max(2.0d0*
ndim*max_diff_coef*dxinv(idim)**2, epsilon(1.0d0))
405 max_diff = max(max_diff,max_diff_dim)
409 max_diff_coef = maxval(
c_norm*lambda(ixo^s)/(w(ixo^s,iw_rho)*tmp(ixo^s))/
block%ds(ixo^s,idim)**2)
410 max_diff_dim = max(2.0d0*
ndim*max_diff_coef, epsilon(1.0d0))
411 max_diff = max(max_diff,max_diff_dim)
414 dtdifflimit=1.0d0/max_diff
415 if(
fld_debug) print *,
'DT limit from diffusion is actually=',dtdifflimit
421 dtdifflimit=dtdifflimit*boostfactor
422 if(
fld_debug) print *,
'DT limit from diffusion is boosted to=',dtdifflimit
423 dtnew=min(dtnew,dtdifflimit)
424 if(
fld_debug) print *,
'DT limit after diffusion is =',dtnew
430 ^
d&dxinv(^
d)=one/
dx^
d;
432 cmax(ixo^s)=dabs(w(ixo^s,iw_mom(idims)))+dsqrt(tmp(ixo^s))
434 cmaxtot(ixo^s)=cmax(ixo^s)*dxinv(idims)
436 cmaxtot(ixo^s)=cmaxtot(ixo^s)+cmax(ixo^s)*dxinv(idims)
441 cmax(ixo^s)=dabs(w(ixo^s,iw_mom(idims)))+dsqrt(tmp(ixo^s))
443 cmaxtot(ixo^s)=cmax(ixo^s)/
block%ds(ixo^s,idims)
445 cmaxtot(ixo^s)=cmaxtot(ixo^s)+cmax(ixo^s)/
block%ds(ixo^s,idims)
450 courantmaxtots=maxval(cmaxtot(ixo^s))
452 if(courantmaxtots>smalldouble) dtnew=min(dtnew,
courantpar/courantmaxtots)
453 if(
fld_debug)print *,
'DT limit FINALLY ENFORCED IS NOW=',dtnew
465 integer,
intent(in) :: ixi^
l, ixo^
l
466 double precision,
intent(in) :: w(ixi^s, 1:nw)
467 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
468 double precision,
intent(out) :: fld_kappa(ixi^s)
472 double precision :: rho0,temp0,kapp0
473 double precision :: temp(ixi^s)
481 call fl%get_tgas(w,x,ixi^
l,ixo^
l,temp)
482 {
do ix^
d=ixomin^
d,ixomax^
d\ }
490 call mpistop(
"special opacity not defined")
494 call mpistop(
"Doesn't know opacity law")
502 integer,
intent(in) :: ixi^
l, ixo^
l
503 double precision,
intent(in) :: w(ixi^s, 1:nw)
504 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
505 double precision,
intent(out):: rad_pressure(ixi^s,1:
ndim,1:
ndim)
508 double precision :: eddington_tensor(ixi^s,1:
ndim,1:
ndim)
509 double precision :: lambda(ixi^s),fld_r(ixi^s)
515 print *,
'In get_radPress with nth=',nth,
' on ixO=',ixo^
l
516 print *,
'Max and Min value of fe'
517 print *,maxval(eddington_tensor(ixo^s,1:
ndim,1:
ndim))
518 print *,minval(eddington_tensor(ixo^s,1:
ndim,1:
ndim))
519 print *,
'Max and Min value of Erad'
520 print *,maxval(w(ixo^s,iw_r_e))
521 print *,minval(w(ixo^s,iw_r_e))
522 print *,
'End get_radPress'
526 rad_pressure(ixo^s,i,j) = eddington_tensor(ixo^s,i,j)*w(ixo^s,iw_r_e)
539 integer,
intent(in) :: ixi^
l,ixo^
l,nth
540 double precision,
intent(in) :: w(ixi^s,1:nw)
541 double precision,
intent(in) :: x(ixi^s,1:
ndim)
542 double precision,
intent(out) :: fld_r(ixi^s),fld_lambda(ixi^s)
545 double precision :: wprim(ixi^s,1:nw)
547 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
561 integer,
intent(in) :: ixi^
l,ixo^
l,nth
562 double precision,
intent(in) :: w(ixi^s,1:nw)
563 double precision,
intent(in) :: x(ixi^s,1:
ndim)
564 double precision,
intent(out) :: fld_r(ixi^s),fld_lambda(ixi^s)
567 integer :: idir, ix^
d
568 double precision :: kappa(ixi^s),normgrad2(ixi^s)
569 double precision :: grad_r_e(ixi^s)
574 fld_lambda(ixo^s) = 1.d0/3.d0
578 normgrad2(ixo^s) = zero
580 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
581 normgrad2(ixo^s) = normgrad2(ixo^s)+grad_r_e(ixo^s)**2
586 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
587 where(normgrad2(ixo^s)<smalldouble**2)
590 fld_lambda(ixo^s) = 1.0d0/3.0d0
592 fld_lambda(ixo^s) = one/fld_r(ixo^s)
597 normgrad2(ixo^s) = zero
599 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
600 normgrad2(ixo^s) = normgrad2(ixo^s) + grad_r_e(ixo^s)**2
603 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
606 fld_lambda(ixo^s) = (2.d0+fld_r(ixo^s))/(6.d0+3*fld_r(ixo^s)+fld_r(ixo^s)**2)
610 normgrad2(ixo^s) = zero
612 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
613 normgrad2(ixo^s) = normgrad2(ixo^s) + grad_r_e(ixo^s)**2
616 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
619 {
do ix^
d = ixomin^
d,ixomax^
d\ }
620 if(fld_r(ix^
d) .lt. 3.d0/2.d0)
then
621 fld_lambda(ix^
d) = 2.d0/(3.d0+dsqrt(9.d0+12.d0*fld_r(ix^
d)**2))
623 fld_lambda(ix^
d) = 1.d0/(1.d0+fld_r(ix^
d)+dsqrt(1.d0+2.d0*fld_r(ix^
d)))
628 call mpistop(
"special fluxlimiter not defined")
632 call mpistop(
'Fluxlimiter unknown')
644 integer,
intent(in) :: ixi^
l, ixo^
l
645 double precision,
intent(in) :: w(ixi^s, 1:nw)
646 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
647 double precision,
intent(out) :: rad_flux(ixi^s, 1:
ndim)
650 integer :: idir,nth_for_fld
651 double precision :: wprim(ixi^s,1:nw)
652 double precision :: grad_r_e(ixi^s)
653 double precision :: kappa(ixi^s), lambda(ixi^s), fld_r(ixi^s)
655 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
665 call gradient(wprim(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth_for_fld)
666 rad_flux(ixo^s,idir)=-(
c_norm*lambda(ixo^s)/(kappa(ixo^s)*wprim(ixo^s,iw_rho)))*grad_r_e(ixo^s)
675 integer,
intent(in) :: ixI^L, ixO^L, nth
676 double precision,
intent(in) :: w(ixI^S, 1:nw)
677 double precision,
intent(in) :: x(ixI^S, 1:ndim)
678 double precision,
intent(out) :: eddington_tensor(ixI^S,1:ndim,1:ndim)
679 double precision,
intent(out) :: lambda(ixI^S),fld_R(ixI^S)
683 double precision :: normgrad2(ixI^S)
684 double precision :: tmp(ixI^S),grad_r_e(ixI^S,1:ndim)
685 double precision :: nn_regularized(ixI^S,1:ndim,1:ndim)
687 normgrad2(ixo^s) = zero
689 call gradient(w(ixi^s, iw_r_e),ixi^l,ixo^l,idir,tmp,nth)
690 grad_r_e(ixo^s,idir)=tmp(ixo^s)
691 normgrad2(ixo^s)=normgrad2(ixo^s)+tmp(ixo^s)**2
696 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)
698 nn_regularized(ixo^s,idir,jdir)=(grad_r_e(ixo^s,idir)*grad_r_e(ixo^s,jdir))/(normgrad2(ixo^s)+smalldouble**2)
705 tmp(ixo^s) = lambda(ixo^s)+(lambda(ixo^s)*fld_r(ixo^s))**2
708 eddington_tensor(ixo^s,idir,idir) = half*(one-tmp(ixo^s))
713 if(idir .ne. jdir) eddington_tensor(ixo^s,idir,jdir) = zero
715 eddington_tensor(ixo^s,idir,jdir) = eddington_tensor(ixo^s,idir,jdir)+&
716 half*(3.d0*tmp(ixo^s)-one)*nn_regularized(ixo^s,idir,jdir)
723 integer,
intent(in) :: ixI^L, ixO^L
724 double precision,
intent(in) :: w(ixI^S, 1:nw)
725 double precision,
intent(out) :: e_gas(ixI^S),E_rad(ixI^S)
729 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)
730 if(
allocated(iw_mag))
then
731 e_gas(ixo^s) = e_gas(ixo^s)-half*sum(w(ixo^s,iw_mag(:))**2,dim=
ndim+1)
733 e_rad(ixo^s) = w(ixo^s,iw_r_e)
736 {
do ix^db= ixomin^db,ixomax^db\}
738 write(*,*)
"Error in FLD get_egas_Erad: small value"
740 write(*,*)
"Cell number: ", ix^d
741 write(*,*)
"internal energy density is=",e_gas(ix^d),
" versus small_e=",
small_e
742 write(*,*)
"radiation energy density is=",e_rad(ix^d),
" versus small_r_e=",
small_r_e
743 call mpistop(
"FLD error:May need to turn on fixes")
748 if(fix_small_values)
then
749 {
do ix^d = ixomin^d,ixomax^d\ }
750 e_gas(ix^d) = max(e_gas(ix^d),small_e)
751 e_rad(ix^d) = max(e_rad(ix^d),small_r_e)
768 double precision,
intent(in) :: qdt
769 double precision,
intent(in) :: qtc
770 double precision,
intent(in) :: dtfactor
773 integer,
parameter :: max_its = 100
774 integer :: n,ixo^
l,ix^
d
775 double precision :: res, max_residual, mg_lambda, fac
776 double precision :: wmax(nw),wmin(nw)
777 double precision :: wmaxb(nw),wminb(nw)
778 integer :: iigrid, igrid
786 do iigrid=1,igridstail; igrid=igrids(iigrid);
787 {
do ix^
d = ixomin^
d,ixomax^
d\ }
802 print *,
'Currently at time=',
global_time,
' time step=',qdt,
' dtfactor=',dtfactor
803 print *,
'at start of MG solver, we have fld_diff_tol =',
fld_diff_tol
804 print *,
'at start of MG solver, we have LHS E_rad range as :',wmax(iw_r_e),wmin(iw_r_e)
805 print *,
'at start of MG solver, we have Diff coeff range as:',wmax(
i_diff_mg),wmin(
i_diff_mg)
806 print *,
'at start of MG solver, we have density range as :',wmax(iw_rho),wmin(iw_rho)
807 print *,
'at start of MG solver, we have RHS E_rad range as :',wmaxb(iw_r_e),wminb(iw_r_e)
808 print *,
'at start of MG solver, we have qdt as',qdt,
' and max_residual=',max_residual
809 print *,
'at start of MG solver, ratio coeffs on level 1 =',wmax(
i_diff_mg)/(
dx(1,1)**2)
814 call mg_set_methods(
mg)
815 if(.not.
mg%is_allocated)
call mpistop(
"multigrid tree not allocated yet")
823 call vhelmholtz_set_lambda(fac)
833 call mg_restrict(
mg, mg_iveps)
834 call mg_fill_ghost_cells(
mg, mg_iveps)
836 call mg_fas_fmg(
mg, .true., max_res=res)
837 if(
fld_debug.and.
mype==0)print *,
'MG residual obtained with FMG is =',res
839 if(res < max_residual)
exit
840 call mg_fas_vcycle(
mg, max_res=res)
841 if(
fld_debug.and.
mype==0)print *,
'MG residual obtained with Vcycle =',res,
' at step =',n
843 if(
fld_debug.and.
mype==0)print *,
'FINAL MG residual obtained is =',res
844 if(res .ge. max_residual)
then
846 write(*,*)
it,
' residual from MG ', res
847 write(*,*)
it,
' max_residual in MG ', max_residual
848 write(*,*)
it,
' dtfactor*qdt in MG ', qdt*dtfactor
849 print *,
'Currently at time=',
global_time,
' time step=',qdt,
' dtfactor=',dtfactor
852 call mpistop(
"no convergence in MG")
854 if(
mype==0)
write(*,*)
'WARNING for it=',
it,
' NO CONVERGENCE IN MG but still carry on'
862 do iigrid=1,igridstail; igrid=igrids(iigrid);
863 {
do ix^db= ixomin^db,ixomax^db\}
865 write(*,*)
"Error in FLD fld_implicit_update: small value"
866 write(*,*)
"of radiation energy density after MG"
868 write(*,*)
"Location: ", psa(igrid)%x(ix^
d,:),
" on grid",igrid
869 write(*,*)
"Cell number: ", ix^
d
870 write(*,*)
"radiation energy density is=",psa(igrid)%w(ix^
d,iw_r_e),
" versus small_r_e=",
small_r_e
871 call mpistop(
"FLD error:May need to turn on fixes")
877 if(fix_small_values)
then
879 do iigrid=1,igridstail; igrid=igrids(iigrid);
880 {
do ix^d = ixomin^d,ixomax^d\ }
881 psa(igrid)%w(ix^d,iw_r_e)= max(psa(igrid)%w(ix^d,iw_r_e),small_r_e)
890 type(state),
target :: psa(max_blocks)
893 integer :: iigrid, igrid, ixO^L
898 do iigrid=1,igridstail; igrid=igrids(iigrid);
909 double precision,
intent(in) :: qtc
911 integer :: iigrid, igrid
918 do iigrid=1,igridstail; igrid=igrids(iigrid);
929 integer,
intent(in) :: ixI^L, ixO^L
930 double precision,
intent(inout) :: w(ixI^S, 1:nw)
931 double precision,
intent(in) :: x(ixI^S, 1:ndim)
933 double precision :: divF(ixI^S)
934 integer :: idir, jxO^L, hxO^L
936 if(.not.
slab)
call mpistop(
"laplacian coded up for uniform cartesian grid")
943 hxo^l=ixo^l-
kr(idir,^
d);
944 jxo^l=ixo^l+
kr(idir,^
d);
945 divf(ixo^s) = divf(ixo^s) + &
959 w(ixo^s,iw_r_e) = divf(ixo^s)
969 integer,
intent(in) :: ixi^
l, ixo^
l
970 double precision,
intent(in) :: x(ixi^s,1:
ndim)
971 double precision,
intent(inout) :: w(ixi^s,1:nw)
974 double precision :: wprim(ixi^s,1:nw)
975 double precision :: kappa(ixi^s),lambda(ixi^s),fld_r(ixi^s)
977 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
983 w(ixo^s,
i_diff_mg) =
c_norm*lambda(ixo^s)/(kappa(ixo^s)*wprim(ixo^s,iw_rho))
985 if(minval(w(ixo^s,
i_diff_mg))<smalldouble)
then
986 print *,
'min diffcoef=',minval(w(ixo^s,
i_diff_mg))
987 call mpistop(
"too small diffusion coefficient")
989 if(maxval(w(ixo^s,
i_diff_mg))>bigdouble)
call mpistop(
"too large diffusion coefficient")
992 print *,
'setting diffcoefs with data on',ixi^
l
993 print *,
'min diffcoef=',minval(w(ixo^s,
i_diff_mg))
994 print *,
'min lambda kappa rho fld_R'
995 print *,minval(lambda(ixo^s))
996 print *,minval(kappa(ixo^s))
997 print *,minval(wprim(ixo^s,iw_rho))
998 print *,minval(fld_r(ixo^s))
999 print *,
'max diffcoef=',maxval(w(ixo^s,
i_diff_mg))
1000 print *,
'max lambda kappa rho fld_R'
1001 print *,maxval(lambda(ixo^s))
1002 print *,maxval(kappa(ixo^s))
1003 print *,maxval(wprim(ixo^s,iw_rho))
1004 print *,maxval(fld_r(ixo^s))
1005 print *,
'done setting diffcoefs in slot',
i_diff_mg,
' on range',ixo^
l
1014 double precision,
intent(in) :: c0, c1
1015 double precision,
intent(inout) :: e_gas
1016 double precision :: bisect_a, bisect_b, bisect_c
1017 integer :: n, max_its
1022 bisect_b = min(dabs(c0/c1),dabs(c0)**(1.d0/4.d0))+smalldouble
1024 bisect_c = (bisect_a + bisect_b)/two
1026 if(n .gt. max_its)
then
1027 call mpistop(
'No convergece in bisection scheme')
1050 call mpistop(
"Problem with fld bisection method")
1058 if(
fld_debug)print*,
"IGNORING GAS-RAD ENERGY EXCHANGE ", c0, c1
1060 call mpistop(
'issues in bisection scheme')
1069 2435 e_gas = (bisect_a + bisect_b)/two
1075 double precision,
intent(in) :: c0, c1
1076 double precision,
intent(inout) :: e_gas
1077 double precision :: xval, yval, der, deltax
1090 xval = xval + deltax
1092 if(ii .gt. 1d3)
then
1093 if(
fld_debug)print*,
'skip to bisection algorithm'
1104 double precision,
intent(in) :: c0, c1
1105 double precision,
intent(inout) :: e_gas
1106 double precision :: xval, yval, der, dder, deltax
1120 deltax = -two*yval*der/(two*der**2 - yval*dder)
1121 xval = xval + deltax
1123 if(ii .gt. 1d3)
then
1124 if(
fld_debug)print*,
'skip to Newton algorithm'
1135 double precision,
intent(in) :: e_gas
1136 double precision,
intent(in) :: c0, c1
1137 double precision :: val
1139 val = e_gas**4.d0 + c1*e_gas - c0
1145 double precision,
intent(in) :: e_gas
1146 double precision,
intent(in) :: c0, c1
1147 double precision :: der
1149 der = 4.d0*e_gas**3.d0 + c1
1155 double precision,
intent(in) :: e_gas
1156 double precision,
intent(in) :: c0, c1
1157 double precision :: dder
1159 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
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.
logical fld_radforce_split
source split for energy interact and radforce:
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...