66 character(len=*),
intent(in) :: files(:)
76 open(
unitpar, file=trim(files(n)), status=
"old")
77 read(
unitpar, fld_list,
end=111)
92 double precision,
intent(in) :: r_gamma
103 call mpistop(
"please set the constant opacity to a reasonable value")
107 call mpistop(
"convergence tolerance for root solver too strict")
110 if(
mype==0) print *,
'Will do photon tiring explicit!!!'
115 call mpistop(
"convergence tolerance for MG solver too strict")
124 call mpistop(
"nth_for_diff_mg must be 1 or 2")
135 mg%operator_type = mg_vhelmholtz
137 mg%smoother_type = mg_smoother_gsrb
143 if(
si_unit)
call mpistop(
"adjust opal module with SI-cgs conversions for SI - or use cgs!")
161 mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
162 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
165 mg%bc(ib, mg_iphi)%bc_type = mg_bc_dirichlet
166 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
169 mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
170 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
175 print *,
'Special boundary for Erad needs specific user-set MG BC treatment'
176 print *,
' and this could be through usr_special_mg_bc call'
182 call mpistop(
"divE_multigrid warning: unknown b.c. ")
186 mg%bc(ib, mg_iveps)%bc_type = mg_bc_neumann
187 mg%bc(ib, mg_iveps)%bc_value = 0.0_dp
201 integer,
intent(in) :: ixi^
l, ixo^
l
202 double precision,
intent(in) :: qdt, x(ixi^s,1:
ndim)
203 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw)
204 double precision,
intent(inout) :: w(ixi^s,1:nw)
205 logical,
intent(in) :: qsourcesplit
206 logical,
intent(inout) :: active
208 integer :: idir,jdir,nth_for_fld,ix^
d
209 double precision,
dimension(ixI^S) :: a1,a2,a3,c0,c1,kappa
210 double precision,
dimension(ixI^S) :: e_gas,e_rad,tmp
211 double precision,
dimension(ixI^S,1:ndim,1:ndim) :: div_v,edd
225 call gradient(wctprim(ixi^s,iw_mom(jdir)),ixi^
l,ixo^
l,idir,tmp)
226 div_v(ixo^s,idir,jdir) = tmp(ixo^s)
231 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1)
234 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1) &
235 + div_v(ixo^s,1,2)*edd(ixo^s,1,2) &
236 + div_v(ixo^s,2,1)*edd(ixo^s,2,1) &
237 + div_v(ixo^s,2,2)*edd(ixo^s,2,2)
240 a3(ixo^s) = div_v(ixo^s,1,1)*edd(ixo^s,1,1) &
241 + div_v(ixo^s,1,2)*edd(ixo^s,1,2) &
242 + div_v(ixo^s,1,3)*edd(ixo^s,1,3) &
243 + div_v(ixo^s,2,1)*edd(ixo^s,2,1) &
244 + div_v(ixo^s,2,2)*edd(ixo^s,2,2) &
245 + div_v(ixo^s,2,3)*edd(ixo^s,2,3) &
246 + div_v(ixo^s,3,1)*edd(ixo^s,3,1) &
247 + div_v(ixo^s,3,2)*edd(ixo^s,3,2) &
248 + div_v(ixo^s,3,3)*edd(ixo^s,3,3)
252 call gradient(wctprim(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,tmp,nth_for_fld)
255 tmp(ixo^s) = -a1(ixo^s)*tmp(ixo^s)
257 w(ixo^s,iw_mom(idir)) = w(ixo^s,iw_mom(idir))+ qdt*tmp(ixo^s)
259 w(ixo^s,iw_e) = w(ixo^s,iw_e) + qdt*wctprim(ixo^s,iw_mom(idir))*tmp(ixo^s)
263 w(ixo^s,iw_r_e) = w(ixo^s,iw_r_e) - qdt*wctprim(ixo^s,iw_r_e)*a3(ixo^s)
274 a2(ixo^s) =
c_norm*kappa(ixo^s)*wct(ixo^s,iw_rho)*qdt
275 a3(ixo^s) = a3(ixo^s)*qdt
277 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))
278 c1(ixo^s) = (
one+a2(ixo^s)+a3(ixo^s))/a1(ixo^s)/(
one+a3(ixo^s))
281 {
do ix^
d = ixomin^
d,ixomax^
d\}
290 call mpistop(
'root-method not known')
294 e_rad(ixo^s) = (a1(ixo^s)*e_gas(ixo^s)**4.d0+e_rad(ixo^s))/(
one+a2(ixo^s)+a3(ixo^s))
297 {
do ix^db= ixomin^db,ixomax^db\}
299 write(*,*)
"Error in FLD add_fld_rad_force: small value"
300 write(*,*)
"of internal or radiation energy density after exchange"
302 write(*,*)
"Location: ", x(ix^
d,:)
303 write(*,*)
"Cell number: ", ix^
d
304 write(*,*)
"internal energy density is=",e_gas(ix^
d),
" versus small_e=",
small_e
305 write(*,*)
"radiation energy density is=",e_rad(ix^
d),
" versus small_r_e=",
small_r_e
306 call mpistop(
"FLD error:May need to turn on fixes")
311 if(fix_small_values)
then
312 {
do ix^d = ixomin^d,ixomax^d\ }
313 e_gas(ix^d) = max(e_gas(ix^d),small_e)
314 e_rad(ix^d) = max(e_rad(ix^d),small_r_e)
321 w(ixo^s,iw_e) = e_gas(ixo^s)
322 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)
323 if(
allocated(iw_mag))
then
324 w(ixo^s,iw_e) = w(ixo^s,iw_e)+half*sum(w(ixo^s,iw_mag(:))**2,dim=ndim+1)
327 w(ixo^s,iw_r_e) = e_rad(ixo^s)
339 integer,
intent(in) :: ixi^
l, ixo^
l
340 double precision,
intent(in) ::
dx^
d, x(ixi^s,1:
ndim), w(ixi^s,1:nw)
341 double precision,
intent(inout) :: dtnew
343 integer :: idim,idims,nth_for_fld
344 double precision :: dxinv(1:
ndim), max_grav
345 double precision :: lambda(ixi^s),fld_r(ixi^s)
346 double precision :: tmp(ixi^s),boostfactor
347 double precision :: max_diff,max_diff_coef,max_diff_dim,dtdifflimit
348 double precision :: cmax(ixi^s),cmaxtot(ixi^s),courantmaxtots
350 if(
fld_debug)print *,
'DT limit on entry to radforce_get_dt=',dtnew
354 ^
d&dxinv(^
d)=one/
dx^
d;
356 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idim,tmp,nth_for_fld)
357 max_grav = maxval(dabs(-lambda(ixo^s)*tmp(ixo^s)/w(ixo^s,iw_rho)))
358 max_grav = max(max_grav, epsilon(1.0d0))
359 dtnew = min(dtnew, 1.0d0 / dsqrt(max_grav * dxinv(idim)))
363 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idim,tmp,nth_for_fld)
364 max_grav = maxval(dabs(-lambda(ixo^s)*tmp(ixo^s)/w(ixo^s,iw_rho))/
block%ds(ixo^s,idim))
365 max_grav = max(max_grav, epsilon(1.0d0))
366 dtnew = min(dtnew, 1.0d0 / dsqrt(max_grav))
369 if(
fld_debug)print *,
'DT limit after RADFORCE eff grav=',dtnew
376 max_diff_coef = maxval(
c_norm*lambda(ixo^s)/(w(ixo^s,iw_rho)*tmp(ixo^s)))
377 ^
d&dxinv(^
d)=one/
dx^
d;
379 max_diff_dim = max(2.0d0*
ndim*max_diff_coef*dxinv(idim)**2, epsilon(1.0d0))
380 max_diff = max(max_diff,max_diff_dim)
384 max_diff_coef = maxval(
c_norm*lambda(ixo^s)/(w(ixo^s,iw_rho)*tmp(ixo^s))/
block%ds(ixo^s,idim)**2)
385 max_diff_dim = max(2.0d0*
ndim*max_diff_coef, epsilon(1.0d0))
386 max_diff = max(max_diff,max_diff_dim)
389 dtdifflimit=1.0d0/max_diff
390 if(
fld_debug) print *,
'DT limit from diffusion is actually=',dtdifflimit
396 dtdifflimit=dtdifflimit*boostfactor
397 if(
fld_debug) print *,
'DT limit from diffusion is boosted to=',dtdifflimit
398 dtnew=min(dtnew,dtdifflimit)
399 if(
fld_debug) print *,
'DT limit after diffusion is =',dtnew
405 ^
d&dxinv(^
d)=one/
dx^
d;
407 cmax(ixo^s)=dabs(w(ixo^s,iw_mom(idims)))+dsqrt(tmp(ixo^s))
409 cmaxtot(ixo^s)=cmax(ixo^s)*dxinv(idims)
411 cmaxtot(ixo^s)=cmaxtot(ixo^s)+cmax(ixo^s)*dxinv(idims)
416 cmax(ixo^s)=dabs(w(ixo^s,iw_mom(idims)))+dsqrt(tmp(ixo^s))
418 cmaxtot(ixo^s)=cmax(ixo^s)/
block%ds(ixo^s,idims)
420 cmaxtot(ixo^s)=cmaxtot(ixo^s)+cmax(ixo^s)/
block%ds(ixo^s,idims)
425 courantmaxtots=maxval(cmaxtot(ixo^s))
427 if(courantmaxtots>smalldouble) dtnew=min(dtnew,
courantpar/courantmaxtots)
428 if(
fld_debug)print *,
'DT limit FINALLY ENFORCED IS NOW=',dtnew
441 integer,
intent(in) :: ixi^
l, ixo^
l
442 double precision,
intent(in) :: w(ixi^s, 1:nw)
443 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
444 double precision,
intent(out) :: fld_kappa(ixi^s)
447 double precision :: rho0,temp0,kapp0
448 double precision :: temp(ixi^s)
457 {
do ix^
d=ixomin^
d,ixomax^
d\ }
465 call mpistop(
"special opacity not defined")
469 call mpistop(
"Doesn't know opacity law")
477 integer,
intent(in) :: ixi^
l, ixo^
l
478 double precision,
intent(in) :: w(ixi^s, 1:nw)
479 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
480 double precision,
intent(out):: rad_pressure(ixi^s,1:
ndim,1:
ndim)
482 double precision :: eddington_tensor(ixi^s,1:
ndim,1:
ndim)
483 double precision :: lambda(ixi^s),fld_r(ixi^s)
489 print *,
'In get_radPress with nth=',nth,
' on ixO=',ixo^
l
490 print *,
'Max and Min value of fe'
491 print *,maxval(eddington_tensor(ixo^s,1:
ndim,1:
ndim))
492 print *,minval(eddington_tensor(ixo^s,1:
ndim,1:
ndim))
493 print *,
'Max and Min value of Erad'
494 print *,maxval(w(ixo^s,iw_r_e))
495 print *,minval(w(ixo^s,iw_r_e))
496 print *,
'End get_radPress'
500 rad_pressure(ixo^s,i,j) = eddington_tensor(ixo^s,i,j)*w(ixo^s,iw_r_e)
513 integer,
intent(in) :: ixi^
l,ixo^
l,nth
514 double precision,
intent(in) :: w(ixi^s,1:nw)
515 double precision,
intent(in) :: x(ixi^s,1:
ndim)
516 double precision,
intent(out) :: fld_r(ixi^s),fld_lambda(ixi^s)
518 double precision :: wprim(ixi^s,1:nw)
520 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
534 integer,
intent(in) :: ixi^
l,ixo^
l,nth
535 double precision,
intent(in) :: w(ixi^s,1:nw)
536 double precision,
intent(in) :: x(ixi^s,1:
ndim)
537 double precision,
intent(out) :: fld_r(ixi^s),fld_lambda(ixi^s)
539 integer :: idir, ix^
d
540 double precision :: kappa(ixi^s),normgrad2(ixi^s)
541 double precision :: grad_r_e(ixi^s)
546 fld_lambda(ixo^s) = 1.d0/3.d0
550 normgrad2(ixo^s) = zero
552 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
553 normgrad2(ixo^s) = normgrad2(ixo^s)+grad_r_e(ixo^s)**2
558 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
559 where(normgrad2(ixo^s)<smalldouble**2)
562 fld_lambda(ixo^s) = 1.0d0/3.0d0
564 fld_lambda(ixo^s) = one/fld_r(ixo^s)
569 normgrad2(ixo^s) = zero
571 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
572 normgrad2(ixo^s) = normgrad2(ixo^s) + grad_r_e(ixo^s)**2
575 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
578 fld_lambda(ixo^s) = (2.d0+fld_r(ixo^s))/(6.d0+3*fld_r(ixo^s)+fld_r(ixo^s)**2)
582 normgrad2(ixo^s) = zero
584 call gradient(w(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth)
585 normgrad2(ixo^s) = normgrad2(ixo^s) + grad_r_e(ixo^s)**2
588 fld_r(ixo^s) = dsqrt(normgrad2(ixo^s))/(kappa(ixo^s)*w(ixo^s,iw_rho)*w(ixo^s,iw_r_e))
591 {
do ix^
d = ixomin^
d,ixomax^
d\ }
592 if(fld_r(ix^
d) .lt. 3.d0/2.d0)
then
593 fld_lambda(ix^
d) = 2.d0/(3.d0+dsqrt(9.d0+12.d0*fld_r(ix^
d)**2))
595 fld_lambda(ix^
d) = 1.d0/(1.d0+fld_r(ix^
d)+dsqrt(1.d0+2.d0*fld_r(ix^
d)))
600 call mpistop(
"special fluxlimiter not defined")
604 call mpistop(
'Fluxlimiter unknown')
616 integer,
intent(in) :: ixi^
l, ixo^
l
617 double precision,
intent(in) :: w(ixi^s, 1:nw)
618 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
619 double precision,
intent(out) :: rad_flux(ixi^s, 1:
ndim)
621 integer :: idir,nth_for_fld
622 double precision :: wprim(ixi^s,1:nw)
623 double precision :: grad_r_e(ixi^s)
624 double precision :: kappa(ixi^s), lambda(ixi^s), fld_r(ixi^s)
626 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
636 call gradient(wprim(ixi^s,iw_r_e),ixi^
l,ixo^
l,idir,grad_r_e,nth_for_fld)
637 rad_flux(ixo^s,idir)=-(
c_norm*lambda(ixo^s)/(kappa(ixo^s)*wprim(ixo^s,iw_rho)))*grad_r_e(ixo^s)
646 integer,
intent(in) :: ixI^L, ixO^L, nth
647 double precision,
intent(in) :: w(ixI^S, 1:nw)
648 double precision,
intent(in) :: x(ixI^S, 1:ndim)
649 double precision,
intent(out) :: eddington_tensor(ixI^S,1:ndim,1:ndim)
650 double precision,
intent(out) :: lambda(ixI^S),fld_R(ixI^S)
653 double precision :: normgrad2(ixI^S)
654 double precision :: tmp(ixI^S),grad_r_e(ixI^S,1:ndim)
655 double precision :: nn_regularized(ixI^S,1:ndim,1:ndim)
657 normgrad2(ixo^s) = zero
659 call gradient(w(ixi^s, iw_r_e),ixi^l,ixo^l,idir,tmp,nth)
660 grad_r_e(ixo^s,idir)=tmp(ixo^s)
661 normgrad2(ixo^s)=normgrad2(ixo^s)+tmp(ixo^s)**2
666 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)
668 nn_regularized(ixo^s,idir,jdir)=(grad_r_e(ixo^s,idir)*grad_r_e(ixo^s,jdir))/(normgrad2(ixo^s)+smalldouble**2)
675 tmp(ixo^s) = lambda(ixo^s)+(lambda(ixo^s)*fld_r(ixo^s))**2
678 eddington_tensor(ixo^s,idir,idir) = half*(one-tmp(ixo^s))
683 if(idir .ne. jdir) eddington_tensor(ixo^s,idir,jdir) = zero
685 eddington_tensor(ixo^s,idir,jdir) = eddington_tensor(ixo^s,idir,jdir)+&
686 half*(3.d0*tmp(ixo^s)-one)*nn_regularized(ixo^s,idir,jdir)
693 integer,
intent(in) :: ixI^L, ixO^L
694 double precision,
intent(in) :: w(ixI^S, 1:nw)
695 double precision,
intent(out) :: e_gas(ixI^S),E_rad(ixI^S)
699 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)
700 if(
allocated(iw_mag))
then
701 e_gas(ixo^s) = e_gas(ixo^s)-half*sum(w(ixo^s,iw_mag(:))**2,dim=
ndim+1)
703 e_rad(ixo^s) = w(ixo^s,iw_r_e)
706 {
do ix^db= ixomin^db,ixomax^db\}
708 write(*,*)
"Error in FLD get_egas_Erad: small value"
710 write(*,*)
"Cell number: ", ix^d
711 write(*,*)
"internal energy density is=",e_gas(ix^d),
" versus small_e=",
small_e
712 write(*,*)
"radiation energy density is=",e_rad(ix^d),
" versus small_r_e=",
small_r_e
713 call mpistop(
"FLD error:May need to turn on fixes")
718 if(fix_small_values)
then
719 {
do ix^d = ixomin^d,ixomax^d\ }
720 e_gas(ix^d) = max(e_gas(ix^d),small_e)
721 e_rad(ix^d) = max(e_rad(ix^d),small_r_e)
736 type(state),
target :: psa(max_blocks)
737 type(state),
target :: psb(max_blocks)
738 double precision,
intent(in) :: qdt
739 double precision,
intent(in) :: qtC
740 double precision,
intent(in) :: dtfactor
742 integer,
parameter :: max_its = 100
743 integer :: n,ixO^L,ix^D
744 double precision :: res, max_residual, mg_lambda, fac
745 double precision :: wmax(nw),wmin(nw)
746 double precision :: wmaxb(nw),wminb(nw)
747 integer :: iigrid, igrid
755 do iigrid=1,igridstail; igrid=igrids(iigrid);
756 {
do ix^d = ixomin^d,ixomax^d\ }
771 print *,
'Currently at time=',
global_time,
' time step=',qdt,
' dtfactor=',dtfactor
772 print *,
'at start of MG solver, we have fld_diff_tol =',
fld_diff_tol
773 print *,
'at start of MG solver, we have LHS E_rad range as :',wmax(iw_r_e),wmin(iw_r_e)
774 print *,
'at start of MG solver, we have Diff coeff range as:',wmax(
i_diff_mg),wmin(
i_diff_mg)
775 print *,
'at start of MG solver, we have density range as :',wmax(iw_rho),wmin(iw_rho)
776 print *,
'at start of MG solver, we have RHS E_rad range as :',wmaxb(iw_r_e),wminb(iw_r_e)
777 print *,
'at start of MG solver, we have qdt as',qdt,
' and max_residual=',max_residual
778 print *,
'at start of MG solver, ratio coeffs on level 1 =',wmax(
i_diff_mg)/(
dx(1,1)**2)
783 call mg_set_methods(
mg)
784 if(.not.
mg%is_allocated)
call mpistop(
"multigrid tree not allocated yet")
792 call vhelmholtz_set_lambda(fac)
802 call mg_restrict(
mg, mg_iveps)
803 call mg_fill_ghost_cells(
mg, mg_iveps)
805 call mg_fas_fmg(
mg, .true., max_res=res)
806 if(
fld_debug.and.
mype==0)print *,
'MG residual obtained with FMG is =',res
808 if(res < max_residual)
exit
809 call mg_fas_vcycle(
mg, max_res=res)
810 if(
fld_debug.and.
mype==0)print *,
'MG residual obtained with Vcycle =',res,
' at step =',n
812 if(
fld_debug.and.
mype==0)print *,
'FINAL MG residual obtained is =',res
813 if(res .ge. max_residual)
then
815 write(*,*)
it,
' residual from MG ', res
816 write(*,*)
it,
' max_residual in MG ', max_residual
817 write(*,*)
it,
' dtfactor*qdt in MG ', qdt*dtfactor
818 print *,
'Currently at time=',
global_time,
' time step=',qdt,
' dtfactor=',dtfactor
821 call mpistop(
"no convergence in MG")
823 if(
mype==0)
write(*,*)
'WARNING for it=',
it,
' NO CONVERGENCE IN MG but still carry on'
831 do iigrid=1,igridstail; igrid=igrids(iigrid);
832 {
do ix^db= ixomin^db,ixomax^db\}
833 if(psa(igrid)%w(ix^d,iw_r_e)<
small_r_e)
then
834 write(*,*)
"Error in FLD fld_implicit_update: small value"
835 write(*,*)
"of radiation energy density after MG"
837 write(*,*)
"Location: ", psa(igrid)%x(ix^d,:),
" on grid",igrid
838 write(*,*)
"Cell number: ", ix^d
839 write(*,*)
"radiation energy density is=",psa(igrid)%w(ix^d,iw_r_e),
" versus small_r_e=",
small_r_e
840 call mpistop(
"FLD error:May need to turn on fixes")
846 if(fix_small_values)
then
848 do iigrid=1,igridstail; igrid=igrids(iigrid);
849 {
do ix^d = ixomin^d,ixomax^d\ }
850 psa(igrid)%w(ix^d,iw_r_e)= max(psa(igrid)%w(ix^d,iw_r_e),small_r_e)
859 type(state),
target :: psa(max_blocks)
861 integer :: iigrid, igrid, ixO^L
866 do iigrid=1,igridstail; igrid=igrids(iigrid);
876 type(state),
target :: psa(max_blocks)
877 double precision,
intent(in) :: qtC
878 integer :: iigrid, igrid
885 do iigrid=1,igridstail; igrid=igrids(iigrid);
896 integer,
intent(in) :: ixI^L, ixO^L
897 double precision,
intent(inout) :: w(ixI^S, 1:nw)
898 double precision,
intent(in) :: x(ixI^S, 1:ndim)
900 double precision :: divF(ixI^S)
901 integer :: idir, jxO^L, hxO^L
903 if(.not.
slab)
call mpistop(
"laplacian coded up for uniform cartesian grid")
910 hxo^l=ixo^l-
kr(idir,^
d);
911 jxo^l=ixo^l+
kr(idir,^
d);
912 divf(ixo^s) = divf(ixo^s) + &
926 w(ixo^s,iw_r_e) = divf(ixo^s)
936 integer,
intent(in) :: ixi^
l, ixo^
l
937 double precision,
intent(in) :: x(ixi^s,1:
ndim)
938 double precision,
intent(inout) :: w(ixi^s,1:nw)
940 double precision :: wprim(ixi^s,1:nw)
941 double precision :: kappa(ixi^s),lambda(ixi^s),fld_r(ixi^s)
943 wprim(ixi^s,1:nw)=w(ixi^s,1:nw)
949 w(ixo^s,
i_diff_mg) =
c_norm*lambda(ixo^s)/(kappa(ixo^s)*wprim(ixo^s,iw_rho))
951 if(minval(w(ixo^s,
i_diff_mg))<smalldouble)
then
952 print *,
'min diffcoef=',minval(w(ixo^s,
i_diff_mg))
953 call mpistop(
"too small diffusion coefficient")
955 if(maxval(w(ixo^s,
i_diff_mg))>bigdouble)
call mpistop(
"too large diffusion coefficient")
958 print *,
'setting diffcoefs with data on',ixi^
l
959 print *,
'min diffcoef=',minval(w(ixo^s,
i_diff_mg))
960 print *,
'min lambda kappa rho fld_R'
961 print *,minval(lambda(ixo^s))
962 print *,minval(kappa(ixo^s))
963 print *,minval(wprim(ixo^s,iw_rho))
964 print *,minval(fld_r(ixo^s))
965 print *,
'max diffcoef=',maxval(w(ixo^s,
i_diff_mg))
966 print *,
'max lambda kappa rho fld_R'
967 print *,maxval(lambda(ixo^s))
968 print *,maxval(kappa(ixo^s))
969 print *,maxval(wprim(ixo^s,iw_rho))
970 print *,maxval(fld_r(ixo^s))
971 print *,
'done setting diffcoefs in slot',
i_diff_mg,
' on range',ixo^
l
980 double precision,
intent(in) :: c0, c1
981 double precision,
intent(inout) :: e_gas
982 double precision :: bisect_a, bisect_b, bisect_c
983 integer :: n, max_its
988 bisect_b = min(dabs(c0/c1),dabs(c0)**(1.d0/4.d0))+smalldouble
990 bisect_c = (bisect_a + bisect_b)/two
992 if(n .gt. max_its)
then
993 call mpistop(
'No convergece in bisection scheme')
1016 call mpistop(
"Problem with fld bisection method")
1024 if(
fld_debug)print*,
"IGNORING GAS-RAD ENERGY EXCHANGE ", c0, c1
1026 call mpistop(
'issues in bisection scheme')
1035 2435 e_gas = (bisect_a + bisect_b)/two
1041 double precision,
intent(in) :: c0, c1
1042 double precision,
intent(inout) :: e_gas
1043 double precision :: xval, yval, der, deltax
1056 xval = xval + deltax
1058 if(ii .gt. 1d3)
then
1059 if(
fld_debug)print*,
'skip to bisection algorithm'
1070 double precision,
intent(in) :: c0, c1
1071 double precision,
intent(inout) :: e_gas
1072 double precision :: xval, yval, der, dder, deltax
1086 deltax = -two*yval*der/(two*der**2 - yval*dder)
1087 xval = xval + deltax
1089 if(ii .gt. 1d3)
then
1090 if(
fld_debug)print*,
'skip to Newton algorithm'
1101 double precision,
intent(in) :: e_gas
1102 double precision,
intent(in) :: c0, c1
1103 double precision :: val
1105 val = e_gas**4.d0 + c1*e_gas - c0
1111 double precision,
intent(in) :: e_gas
1112 double precision,
intent(in) :: c0, c1
1113 double precision :: der
1115 der = 4.d0*e_gas**3.d0 + c1
1121 double precision,
intent(in) :: e_gas
1122 double precision,
intent(in) :: c0, c1
1123 double precision :: dder
1125 dder = 4.d0*3.d0*e_gas**2.d0
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, public fld_get_radpress(w, x, ixil, ixol, rad_pressure)
Returns Radiation Pressure as tensor NOTE: w is primitive on entry.
double precision, public fld_bisect_tol
Tolerance for bisection method for Energy sourceterms This is a percentage of the minimum of gas- and...
logical fld_force_mg_converged
switches for local debug purposes
double precision, public fld_diff_tol
Tolerance for radiative Energy diffusion.
double precision, public fld_gamma
A copy of (m)hd_gamma.
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
character(len=40) fld_opal_table
subroutine update_diffcoeff(psa)
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, public fld_get_diffcoef_central(w, x, ixil, ixol)
Calculates cell-centered diffusion coefficient to be used in multigrid.
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_radflux(w, x, ixil, ixol, rad_flux)
Calculate Radiation Flux NOTE: only for diagnostics purposes (w conservative on entry) This returns c...
double precision, public fld_kappa0
Opacity value when using constant opacity.
subroutine, public fld_get_fluxlimiter(w, x, ixil, ixol, fld_lambda, fld_r, nth)
This subroutine calculates flux limiter lambda according to fld_fluxlimiter It also calculates fld_R ...
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 fld_get_eddington(w, x, ixil, ixol, eddington_tensor, lambda, fld_r, nth)
Calculate Eddington-tensor (where w is primitive) also feeds back the flux limiter lambda and R.
subroutine, public fld_get_opacity_prim(w, x, ixil, ixol, fld_kappa)
Sets the opacity in the w-array by calling mod_opal_opacity NOTE: assumes primitives in w NOTE: assum...
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 fld_set_mg_bounds
Set the boundaries for the diffusion of E.
subroutine fld_evaluate_implicit(qtc, psa)
inplace update of psa==>F_im(psa)
subroutine, public add_fld_rad_force(qdt, ixil, ixol, wct, wctprim, w, x, qsourcesplit, active)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO This subroutine handles th...
logical fld_radforce_split
source split for energy interact and radforce:
double precision function dpolynomial_bisection(e_gas, c0, c1)
Evaluate first derivative of polynomial at argument e_gas.
subroutine, public fld_init(r_gamma)
Initialising FLD-module Read opacities Initialise Multigrid and adimensionalise kappa.
logical fld_tiring_explicit
switch to handle photon tiring explicit or implicit
subroutine, public fld_get_fluxlimiter_prim(w, x, ixil, ixol, fld_lambda, fld_r, nth)
This subroutine calculates flux limiter lambda according to fld_fluxlimiter It also calculates fld_R ...
subroutine, public fld_radforce_get_dt(w, ixil, ixol, dtnew, dxd, x)
get dt limit for radiation force and FLD explicit source additions NOTE: w is primitive on entry
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 fld_implicit_update(dtfactor, qdt, qtc, psa, psb)
Calling all subroutines to perform the multigrid method Communicates rad_e and diff_coeff to multigri...
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, dimension(:), allocatable, parameter d
double precision courantpar
The Courant (CFL) number used for the simulation.
integer ixm
the mesh range of a physical block without ghost cells
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.
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
procedure(sub_get_tgas), pointer phys_get_tgas
procedure(sub_evaluate_implicit), pointer phys_evaluate_implicit
procedure(sub_get_rfactor), pointer phys_get_rfactor
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_implicit_update), pointer phys_implicit_update
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...