56 integer,
public,
protected ::
rho_
59 integer,
allocatable,
public,
protected ::
mom(:)
62 integer,
public,
protected ::
e_
65 integer,
public,
protected ::
p_
68 integer,
public,
protected ::
te_
69 integer,
public,
protected ::
ne_
74 integer,
public,
protected ::
q_
87 double precision,
public,
protected ::
h_ion_fr=1d0
90 double precision,
public,
protected ::
he_ion_fr=1d0
97 double precision,
public,
protected ::
rr=1d0
104 function fun_kin_en(w, ixI^L, ixO^L, inv_rho)
result(ke)
106 integer,
intent(in) :: ixi^
l, ixo^
l
107 double precision,
intent(in) :: w(ixi^s, nw)
108 double precision :: ke(ixo^s)
109 double precision,
intent(in),
optional :: inv_rho(ixo^s)
110 end function fun_kin_en
148 subroutine ffhd_read_params(files)
150 character(len=*),
intent(in) :: files(:)
159 do n = 1,
size(files)
160 open(
unitpar, file=trim(files(n)), status=
"old")
161 read(
unitpar, ffhd_list,
end=111)
164 end subroutine ffhd_read_params
167 subroutine ffhd_write_info(fh)
169 integer,
intent(in) :: fh
170 integer,
parameter :: n_par = 1
171 double precision :: values(n_par)
172 character(len=name_len) :: names(n_par)
173 integer,
dimension(MPI_STATUS_SIZE) :: st
176 call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
179 values(1) = eos%gamma
180 call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
181 call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
182 end subroutine ffhd_write_info
200 if(
mype==0)
write(*,*)
'WARNING: set ffhd_thermal_conduction=F when ffhd_energy=F'
204 if(
mype==0)
write(*,*)
'WARNING: set ffhd_hyperbolic_tc=F when ffhd_energy=F'
208 if(
mype==0)
write(*,*)
'WARNING: set ffhd_radiative_cooling=F when ffhd_energy=F'
212 if(
mype==0)
write(*,*)
'WARNING: set ffhd_trac=F when ffhd_energy=F'
216 if (eos%eos_type /=
'FI') &
217 call mpistop(
"eos_type "//trim(eos%eos_type)//
" requires ffhd_energy=T")
222 if(
mype==0)
write(*,*)
'WARNING: turn off parabolic TC when using hyperbolic TC'
225 physics_type =
"ffhd"
227 phys_internal_e=.false.
232 phys_gamma = eos%gamma
239 if(
mype==0)
write(*,*)
'WARNING: reset ffhd_trac_type=1 for 1D simulation'
244 if(
mype==0)
write(*,*)
'WARNING: set ffhd_trac_mask==bigdouble for global TRAC method'
248 allocate(start_indices(number_species),stop_indices(number_species))
254 mom(:) = var_set_momentum(1)
258 e_ = var_set_energy()
266 q_ = var_set_fluxvar(
'q',
'q', need_bc=.false.)
276 if (eos%eos_type ==
'LTE')
then
279 else if (eos%eos_type ==
'PI')
then
291 stop_indices(1)=nwflux
309 if(.not.
allocated(flux_type))
then
310 allocate(flux_type(
ndir, nwflux))
311 flux_type = flux_default
312 else if(any(shape(flux_type) /= [
ndir, nwflux]))
then
313 call mpistop(
"phys_check error: flux_type has wrong shape")
316 phys_get_dt => ffhd_get_dt
317 phys_get_cmax => ffhd_get_cmax_origin
318 phys_get_tcutoff => ffhd_get_tcutoff
319 phys_get_cbounds => ffhd_get_cbounds
324 phys_get_flux => ffhd_get_flux
325 phys_get_v => ffhd_get_v_origin
329 phys_add_source_geom => ffhd_add_source_geom
330 phys_add_source => ffhd_add_source
331 phys_check_params => ffhd_check_params
332 phys_write_info => ffhd_write_info
333 phys_handle_small_values => ffhd_handle_small_values_origin
335 phys_check_w => ffhd_check_w_origin
338 phys_get_pthermal => ffhd_get_pthermal_iso
348 call ffhd_physical_units()
360 call mpistop(
"thermal conduction needs ffhd_energy=T")
363 call mpistop(
"hyperbolic thermal conduction needs ffhd_energy=T")
366 call mpistop(
"radiative cooling needs ffhd_energy=T")
376 call add_sts_method(ffhd_get_tc_dt_ffhd,ffhd_sts_set_source_tc_ffhd,
e_,1,
e_,1,.false.)
391 rc_fl%subtract_equi = .false.
398 phys_te_images => ffhd_te_images
414 subroutine ffhd_te_images
419 case(
'EIvtiCCmpi',
'EIvtuCCmpi')
421 case(
'ESvtiCCmpi',
'ESvtuCCmpi')
423 case(
'SIvtiCCmpi',
'SIvtuCCmpi')
425 case(
'WIvtiCCmpi',
'WIvtuCCmpi')
428 call mpistop(
"Error in synthesize emission: Unknown convert_type")
430 end subroutine ffhd_te_images
433 subroutine ffhd_sts_set_source_tc_ffhd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
437 integer,
intent(in) :: ixi^
l, ixo^
l, igrid, nflux
438 double precision,
intent(in) :: x(ixi^s,1:
ndim)
439 double precision,
intent(inout) :: wres(ixi^s,1:nw), w(ixi^s,1:nw)
440 double precision,
intent(in) :: my_dt
441 logical,
intent(in) :: fix_conserve_at_step
443 end subroutine ffhd_sts_set_source_tc_ffhd
445 function ffhd_get_tc_dt_ffhd(w,ixI^L,ixO^L,dx^D,x)
result(dtnew)
452 integer,
intent(in) :: ixi^
l, ixo^
l
453 double precision,
intent(in) ::
dx^
d, x(ixi^s,1:
ndim)
454 double precision,
intent(in) :: w(ixi^s,1:nw)
455 double precision :: dtnew
458 end function ffhd_get_tc_dt_ffhd
460 subroutine ffhd_tc_handle_small_e(w, x, ixI^L, ixO^L, step)
463 integer,
intent(in) :: ixi^
l,ixo^
l
464 double precision,
intent(inout) :: w(ixi^s,1:nw)
465 double precision,
intent(in) :: x(ixi^s,1:
ndim)
466 integer,
intent(in) :: step
467 character(len=140) :: error_msg
469 write(error_msg,
"(a,i3)")
"Thermal conduction step ", step
470 call ffhd_handle_small_ei(w,x,ixi^
l,ixo^
l,
e_,error_msg)
471 end subroutine ffhd_tc_handle_small_e
473 subroutine tc_params_read_ffhd(fl)
475 type(tc_fluid),
intent(inout) :: fl
478 logical :: tc_saturate=.false.
479 double precision :: tc_k_para=0d0
480 character(len=std_len) :: tc_slope_limiter=
"MC"
482 namelist /tc_list/ tc_saturate, tc_slope_limiter, tc_k_para
486 read(
unitpar, tc_list,
end=111)
490 fl%tc_saturate = tc_saturate
491 fl%tc_k_para = tc_k_para
492 select case(tc_slope_limiter)
494 fl%tc_slope_limiter = 0
497 fl%tc_slope_limiter = 1
500 fl%tc_slope_limiter = 2
503 fl%tc_slope_limiter = 3
506 fl%tc_slope_limiter = 4
508 call mpistop(
"Unknown tc_slope_limiter, choose MC, minmod")
510 end subroutine tc_params_read_ffhd
512 subroutine rc_params_read(fl)
515 type(rc_fluid),
intent(inout) :: fl
517 integer :: ncool = 4000
520 character(len=std_len) :: coolcurve=
'JCcorona'
523 logical :: tfix=.false.
529 logical :: rc_split=.false.
530 logical :: rad_damp=.false.
531 double precision :: rad_damp_height=0.5d0
532 double precision :: rad_damp_scale=0.15d0
534 namelist /rc_list/ coolcurve, ncool, tlow, tfix, rc_split, rad_damp, rad_damp_height, rad_damp_scale
538 read(
unitpar, rc_list,
end=111)
543 fl%coolcurve=coolcurve
548 fl%rad_damp_height=rad_damp_height
549 fl%rad_damp_scale=rad_damp_scale
550 end subroutine rc_params_read
552 subroutine ffhd_check_params
560 if (eos%gamma <= 0.0d0)
call mpistop (
"Error: eos%gamma <= 0")
561 if (
ffhd_adiab < 0.0d0)
call mpistop (
"Error: ffhd_adiab < 0")
564 if (eos%gamma <= 0.0d0 .or. eos%gamma == 1.0d0) &
565 call mpistop (
"Error: eos%gamma <= 0 or eos%gamma == 1")
570 call mpistop(
"usr_set_equi_vars has to be implemented in the user file")
575 write(*,*)
'====FFHD run with settings===================='
576 write(*,*)
'Using mod_ffhd_phys with settings:'
578 write(*,*)
'Dimensionality :',
ndim
579 write(*,*)
'vector components:',
ndir
581 write(*,*)
'number of variables nw=',nw
582 write(*,*)
' start index iwstart=',iwstart
583 write(*,*)
'number of vector variables=',nvector
584 write(*,*)
'number of stagger variables nws=',nws
585 write(*,*)
'number of variables with BCs=',nwgc
586 write(*,*)
'number of vars with fluxes=',nwflux
587 write(*,*)
'number of vars with flux + BC=',nwfluxbc
588 write(*,*)
'number of auxiliary variables=',nwaux
589 write(*,*)
'number of extra vars without flux=',nwextra
590 write(*,*)
'number of extra vars for wextra=',nw_extra
591 write(*,*)
'number of auxiliary I/O variables=',
nwauxio
598 write(*,*)
'number due to phys_wider_stencil=',phys_wider_stencil
599 write(*,*)
'==========================================='
601 end subroutine ffhd_check_params
603 subroutine ffhd_physical_units()
605 double precision :: mp,kb
606 double precision :: a,b
619 if (eos%eos_type ==
'LTE')
then
623 eos%nH2rhoFactor = 1d0+4d0*eos%He_abundance
624 rr=(2d0+3d0*eos%He_abundance)/(1d0+4d0*eos%He_abundance)
629 a=1d0+4d0*eos%He_abundance
630 if(eos%eos_type==
'PI')
then
633 b=2d0+3d0*eos%He_abundance
702 end subroutine ffhd_physical_units
704 subroutine ffhd_check_w_origin(primitive,ixI^L,ixO^L,w,flag)
706 logical,
intent(in) :: primitive
707 integer,
intent(in) :: ixi^
l, ixo^
l
708 double precision,
intent(in) :: w(ixi^s,nw)
709 double precision :: tmp(ixi^s)
710 logical,
intent(inout) :: flag(ixi^s,1:nw)
720 where(tmp(ixo^s) <
small_e) flag(ixo^s,
e_) = .true.
723 end subroutine ffhd_check_w_origin
727 integer,
intent(in) :: ixi^
l, ixo^
l
728 double precision,
intent(inout) :: w(ixi^s, nw)
729 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
732 w(ixo^s,
e_)=w(ixo^s,
p_)*eos%inv_gamma_minus_1+half*w(ixo^s,
mom(1))**2*w(ixo^s,
rho_)
739 integer,
intent(in) :: ixi^
l, ixo^
l
740 double precision,
intent(inout) :: w(ixi^s, nw)
741 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
747 w(ixo^s,
mom(1)) = w(ixo^s,
mom(1))/w(ixo^s,
rho_)
749 w(ixo^s,
p_)=eos%gamma_minus_1*(w(ixo^s,
e_)-half*w(ixo^s,
rho_)*w(ixo^s,
mom(1))**2)
755 integer,
intent(in) :: ixi^
l, ixo^
l
756 double precision,
intent(inout) :: w(ixi^s, nw)
757 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
764 integer,
intent(in) :: ixi^
l, ixo^
l
765 double precision,
intent(inout) :: w(ixi^s, nw)
766 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
774 call ffhd_handle_small_ei(w,x,ixi^
l,ixo^
l,
e_,
'ffhd_e_to_ei')
783 integer,
intent(in) :: ixi^
l, ixo^
l
784 double precision,
intent(in) :: w(ixi^s, nw)
785 double precision :: ei(ixo^s)
790 subroutine ffhd_handle_small_values_origin(primitive, w, x, ixI^L, ixO^L, subname)
793 logical,
intent(in) :: primitive
794 integer,
intent(in) :: ixi^
l,ixo^
l
795 double precision,
intent(inout) :: w(ixi^s,1:nw)
796 double precision,
intent(in) :: x(ixi^s,1:
ndim)
797 character(len=*),
intent(in) :: subname
799 logical :: flag(ixi^s,1:nw)
800 double precision :: tmp2(ixi^s)
802 call phys_check_w(primitive, ixi^
l, ixi^
l, w, flag)
809 where(flag(ixo^s,
rho_)) w(ixo^s,
mom(1)) = 0.0d0
815 where(flag(ixo^s,
e_))
832 if(.not.primitive)
then
841 end subroutine ffhd_handle_small_values_origin
843 subroutine ffhd_get_v_origin(w,x,ixI^L,ixO^L,v)
845 integer,
intent(in) :: ixi^
l, ixo^
l
846 double precision,
intent(in) :: w(ixi^s,nw), x(ixi^s,1:
ndim)
847 double precision,
intent(out) :: v(ixi^s,
ndir)
848 double precision :: rho(ixi^s)
852 rho(ixo^s)=1.d0/rho(ixo^s)
854 v(ixo^s,
ndir) = w(ixo^s,
mom(1))*
block%B0(ixo^s,idir,0)*rho(ixo^s)
856 end subroutine ffhd_get_v_origin
860 integer,
intent(in) :: ixi^
l, ixo^
l, idim
861 double precision,
intent(in) :: w(ixi^s,nw), x(ixi^s,1:
ndim)
862 double precision,
intent(out) :: v(ixi^s)
863 double precision :: rho(ixi^s)
866 v(ixo^s) = (w(ixo^s,
mom(1))*
block%B0(ixo^s,idim,0)) / rho(ixo^s)
869 subroutine ffhd_get_cmax_origin(wprim,x,ixI^L,ixO^L,idim,cmax)
871 integer,
intent(in) :: ixi^
l, ixo^
l, idim
873 double precision,
intent(in) :: wprim(ixi^s, nw), x(ixi^s,1:
ndim)
874 double precision,
intent(inout) :: cmax(ixi^s)
879 call eos%get_csound2(wprim,x,ixi^
l,ixo^
l,cmax)
880 cmax(ixo^s)=dsqrt(cmax(ixo^s))
882 cmax(ixo^s)=dsqrt(eos%gamma*wprim(ixo^s,
p_)/wprim(ixo^s,
rho_))
885 cmax(ixo^s)=dsqrt(eos%gamma*
ffhd_adiab*wprim(ixo^s,
rho_)**eos%gamma_minus_1)
887 cmax(ixo^s)=dabs(wprim(ixo^s,
mom(1))*
block%B0(ixo^s,idim,0))+cmax(ixo^s)
889 end subroutine ffhd_get_cmax_origin
891 subroutine ffhd_get_tcutoff(ixI^L,ixO^L,w,x,Tco_local,Tmax_local)
894 integer,
intent(in) :: ixi^
l,ixo^
l
895 double precision,
intent(in) :: x(ixi^s,1:
ndim)
896 double precision,
intent(inout) :: w(ixi^s,1:nw)
897 double precision,
intent(out) :: tco_local,tmax_local
898 double precision,
parameter :: trac_delta=0.25d0
899 double precision :: te(ixi^s),lts(ixi^s)
900 double precision,
dimension(ixI^S,1:ndim) :: gradt
901 double precision :: bdir(
ndim)
902 double precision :: ltrc,ltrp,altr
903 integer :: idims,ix^
d,jxo^
l,hxo^
l,ixa^
d,ixb^
d
904 integer :: jxp^
l,hxp^
l,ixp^
l,ixq^
l
905 logical :: lrlt(ixi^s)
909 tmax_local=maxval(te(ixo^s))
919 lts(ixo^s)=0.5d0*dabs(te(jxo^s)-te(hxo^s))/te(ixo^s)
921 where(lts(ixo^s) > trac_delta)
924 if(any(lrlt(ixo^s)))
then
925 tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
936 lts(ixp^s)=0.5d0*dabs(te(jxp^s)-te(hxp^s))/te(ixp^s)
937 lts(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
938 lts(ixo^s)=0.25d0*(lts(jxo^s)+two*lts(ixo^s)+lts(hxo^s))
939 block%wextra(ixo^s,
tcoff_)=te(ixo^s)*lts(ixo^s)**0.4d0
941 call mpistop(
"ffhd_trac_type not allowed for 1D simulation")
956 call gradient(te,ixi^
l,ixo^
l,idims,gradt(ixi^s,idims))
962 ixb^
d=(ixomin^
d+ixomax^
d-1)/2+ixa^
d;
965 if(sum(bdir(:)**2) .gt. zero)
then
966 bdir(1:ndim)=bdir(1:ndim)/dsqrt(sum(bdir(:)**2))
968 block%special_values(3:ndim+2)=bdir(1:ndim)
970 {
do ix^db=ixomin^db,ixomax^db\}
973 lts(ix^d)=min(block%ds(ix^d,1),block%ds(ix^d,2))*&
974 abs(^d&gradt({ix^d},^d)*block%B0({ix^d},^d,0)+)/te(ix^d)
978 lts(ix^d)=min(block%ds(ix^d,1),block%ds(ix^d,2),block%ds(ix^d,3))*&
979 abs(^d&gradt({ix^d},^d)*block%B0({ix^d},^d,0)+)/te(ix^d)
981 if(lts(ix^d)>trac_delta)
then
982 block%special_values(1)=max(block%special_values(1),te(ix^d))
985 block%special_values(2)=tmax_local
1003 call gradient(te,ixi^l,ixq^l,idims,gradt(ixi^s,idims))
1004 call gradientf(te,x,ixi^l,hxp^l,idims,gradt(ixi^s,idims),nghostcells,.true.)
1005 call gradientf(te,x,ixi^l,jxp^l,idims,gradt(ixi^s,idims),nghostcells,.false.)
1007 {
do ix^db=ixpmin^db,ixpmax^db\}
1009 lts(ix^d)=abs(^d&gradt({ix^d},^d)*block%B0({ix^d},^d,0)+)/te(ix^d)
1011 lts(ix^d)=min(^d&block%ds({ix^d},^d))*lts(ix^d)
1012 lts(ix^d)=max(one,(exp(lts(ix^d))/ltrc)**ltrp)
1017 {
do ix^db=ixpmin^db,ixpmax^db\}
1019 altr=0.25d0*((lts(ix1-1,ix2)+two*lts(ix^d)+lts(ix1+1,ix2))*block%B0(ix^d,1,0)**2+&
1020 (lts(ix1,ix2-1)+two*lts(ix^d)+lts(ix1,ix2+1))*block%B0(ix^d,2,0)**2)
1021 block%wextra(ix^d,
tcoff_)=te(ix^d)*altr**0.4d0
1024 altr=0.25d0*((lts(ix1-1,ix2,ix3)+two*lts(ix^d)+lts(ix1+1,ix2,ix3))*block%B0(ix^d,1,0)**2+&
1025 (lts(ix1,ix2-1,ix3)+two*lts(ix^d)+lts(ix1,ix2+1,ix3))*block%B0(ix^d,2,0)**2+&
1026 (lts(ix1,ix2,ix3-1)+two*lts(ix^d)+lts(ix1,ix2,ix3+1))*block%B0(ix^d,3,0)**2)
1027 block%wextra(ix^d,
tcoff_)=te(ix^d)*altr**0.4d0
1033 call mpistop(
"unknown ffhd_trac_type")
1036 end subroutine ffhd_get_tcutoff
1038 subroutine ffhd_get_cbounds(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
1040 integer,
intent(in) :: ixi^
l, ixo^
l, idim
1041 double precision,
intent(in) :: wlc(ixi^s, nw), wrc(ixi^s, nw)
1042 double precision,
intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
1043 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1044 double precision,
intent(inout) :: cmax(ixi^s,1:number_species)
1045 double precision,
intent(inout),
optional :: cmin(ixi^s,1:number_species)
1046 double precision,
intent(in) :: hspeed(ixi^s,1:number_species)
1047 double precision :: wmean(ixi^s,nw), wmeanp(ixi^s,nw)
1048 double precision,
dimension(ixI^S) :: umean, dmean, csoundl, csoundr, tmp1,tmp2,tmp3
1054 tmp1(ixo^s)=dsqrt(wlp(ixo^s,
rho_))
1055 tmp2(ixo^s)=dsqrt(wrp(ixo^s,
rho_))
1056 tmp3(ixo^s)=1.d0/(tmp1(ixo^s)+tmp2(ixo^s))
1057 umean(ixo^s)=(wlp(ixo^s,
mom(1))*tmp1(ixo^s)&
1058 +wrp(ixo^s,
mom(1))*tmp2(ixo^s))*tmp3(ixo^s)
1059 umean(ixo^s)=umean(ixo^s)*
block%B0(ixo^s,idim,idim)
1060 call ffhd_csound2_cbounds(wlc,wlp,x,ixi^
l,ixo^
l,csoundl)
1061 call ffhd_csound2_cbounds(wrc,wrp,x,ixi^
l,ixo^
l,csoundr)
1062 dmean(ixo^s)=(tmp1(ixo^s)*csoundl(ixo^s)+tmp2(ixo^s)*csoundr(ixo^s)) * &
1063 tmp3(ixo^s) + 0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2 * &
1064 ((wrp(ixo^s,
mom(1))-wlp(ixo^s,
mom(1)))*
block%B0(ixo^s,idim,idim))**2
1065 dmean(ixo^s)=dsqrt(dmean(ixo^s))
1066 if(
present(cmin))
then
1067 cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
1068 cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
1070 cmax(ixo^s,1)=dabs(umean(ixo^s))+dmean(ixo^s)
1073 wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1074 tmp1(ixo^s)=wmean(ixo^s,
mom(1))*
block%B0(ixo^s,idim,idim)/wmean(ixo^s,
rho_)
1076 wmeanp(ixo^s,1:nwflux)=0.5d0*(wlp(ixo^s,1:nwflux)+wrp(ixo^s,1:nwflux))
1077 call eos%get_csound2(wmeanp,x,ixi^
l,ixo^
l,csoundr)
1081 csoundr(ixo^s) = dsqrt(csoundr(ixo^s))
1082 if(
present(cmin))
then
1083 cmax(ixo^s,1)=max(tmp1(ixo^s)+csoundr(ixo^s),zero)
1084 cmin(ixo^s,1)=min(tmp1(ixo^s)-csoundr(ixo^s),zero)
1086 cmax(ixo^s,1)=dabs(tmp1(ixo^s))+csoundr(ixo^s)
1090 call ffhd_csound2_cbounds(wlc,wlp,x,ixi^
l,ixo^
l,csoundl)
1091 call ffhd_csound2_cbounds(wrc,wrp,x,ixi^
l,ixo^
l,csoundr)
1092 csoundl(ixo^s)=max(dsqrt(csoundl(ixo^s)),dsqrt(csoundr(ixo^s)))
1093 if(
present(cmin))
then
1094 cmin(ixo^s,1)=min(wlp(ixo^s,
mom(1))*
block%B0(ixo^s,idim,idim),&
1095 wrp(ixo^s,
mom(1))*
block%B0(ixo^s,idim,idim))-csoundl(ixo^s)
1096 cmax(ixo^s,1)=max(wlp(ixo^s,
mom(1))*
block%B0(ixo^s,idim,idim),&
1097 wrp(ixo^s,
mom(1))*
block%B0(ixo^s,idim,idim))+csoundl(ixo^s)
1099 cmax(ixo^s,1)=max(wlp(ixo^s,
mom(1))*
block%B0(ixo^s,idim,idim),&
1100 wrp(ixo^s,
mom(1))*
block%B0(ixo^s,idim,idim))+csoundl(ixo^s)
1103 end subroutine ffhd_get_cbounds
1109 subroutine ffhd_csound2_cbounds(wC,wp,x,ixI^L,ixO^L,cs2)
1111 integer,
intent(in) :: ixi^
l, ixo^
l
1112 double precision,
intent(in) :: wc(ixi^s,nw), wp(ixi^s,nw), x(ixi^s,1:
ndim)
1113 double precision,
intent(out):: cs2(ixi^s)
1116 call eos%get_csound2(wp,x,ixi^
l,ixo^
l,cs2)
1120 end subroutine ffhd_csound2_cbounds
1122 subroutine ffhd_get_pthermal_iso(w,x,ixI^L,ixO^L,pth)
1125 integer,
intent(in) :: ixi^
l, ixo^
l
1126 double precision,
intent(in) :: w(ixi^s,nw)
1127 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1128 double precision,
intent(out):: pth(ixi^s)
1132 end subroutine ffhd_get_pthermal_iso
1137 integer,
intent(in) :: ixi^
l, ixo^
l
1138 double precision,
intent(in) :: w(ixi^s,nw)
1139 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1140 double precision,
intent(out):: pth(ixi^s)
1145 {
do ix^db= ixo^lim^db\}
1150 elseif(check_small_values)
then
1151 {
do ix^db= ixo^lim^db\}
1152 if(pth(ix^d)<small_pressure)
then
1153 write(*,*)
"Error: small value of gas pressure",pth(ix^d),&
1154 " encountered when call ffhd_get_pthermal"
1155 write(*,*)
"Iteration: ", it,
" Time: ", global_time
1156 write(*,*)
"Location: ", x(ix^d,:)
1157 write(*,*)
"Cell number: ", ix^d
1159 write(*,*) trim(cons_wnames(iw)),
": ",w(ix^d,iw)
1162 if(trace_small_values)
write(*,*) dsqrt(pth(ix^d)-bigdouble)
1163 write(*,*)
"Saving status at the previous time step"
1172 integer,
intent(in) :: ixi^
l, ixo^
l
1173 double precision,
intent(in) :: w(ixi^s, 1:nw)
1174 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
1175 double precision,
intent(out):: res(ixi^s)
1177 res(ixo^s) = w(ixo^s,
te_)
1182 integer,
intent(in) :: ixi^
l, ixo^
l
1183 double precision,
intent(in) :: w(ixi^s, 1:nw)
1184 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
1185 double precision,
intent(out):: res(ixi^s)
1186 double precision :: r(ixi^s)
1189 res(ixo^s) = eos%gamma_minus_1 * w(ixo^s,
e_)/(w(ixo^s,
rho_)*r(ixo^s))
1194 integer,
intent(in) :: ixi^
l, ixo^
l
1195 double precision,
intent(in) :: w(ixi^s, 1:nw)
1196 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
1197 double precision,
intent(out):: res(ixi^s)
1199 double precision :: r(ixi^s)
1203 res(ixo^s)=res(ixo^s)/(r(ixo^s)*w(ixo^s,
rho_))
1208 integer,
intent(in) :: ixi^
l, ixo^
l
1209 double precision,
intent(in) :: w(ixi^s,nw)
1210 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1211 double precision,
intent(out) :: csound2(ixi^s)
1212 double precision :: rho(ixi^s)
1217 csound2(ixo^s)=eos%gamma*csound2(ixo^s)/rho(ixo^s)
1219 csound2(ixo^s)=eos%gamma*
ffhd_adiab*rho(ixo^s)**eos%gamma_minus_1
1223 subroutine ffhd_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
1226 integer,
intent(in) :: ixi^
l, ixo^
l, idim
1228 double precision,
intent(in) :: wc(ixi^s,nw)
1230 double precision,
intent(in) :: w(ixi^s,nw)
1231 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1232 double precision,
intent(out) :: f(ixi^s,nwflux)
1233 double precision :: ptotal(ixo^s)
1238 ptotal(ixo^s)=w(ixo^s,
p_)
1244 f(ixo^s,
mom(1))=(wc(ixo^s,
mom(1))*w(ixo^s,
mom(1))+ptotal(ixo^s))*
block%B0(ixo^s,idim,idim)
1248 f(ixo^s,
e_)=w(ixo^s,
mom(1))*(wc(ixo^s,
e_)+ptotal(ixo^s))*
block%B0(ixo^s,idim,idim)
1250 f(ixo^s,
e_)=f(ixo^s,
e_)+w(ixo^s,
q_)*
block%B0(ixo^s,idim,idim)
1254 end subroutine ffhd_get_flux
1256 subroutine ffhd_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
1260 integer,
intent(in) :: ixi^
l, ixo^
l
1261 double precision,
intent(in) :: qdt,dtfactor
1262 double precision,
intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw), x(ixi^s,1:
ndim)
1263 double precision,
intent(inout) :: w(ixi^s,1:nw)
1264 logical,
intent(in) :: qsourcesplit
1265 logical,
intent(inout) :: active
1267 if (.not. qsourcesplit)
then
1269 call add_punitb(qdt,ixi^
l,ixo^
l,wct,w,x,wctprim)
1271 call add_hyperbolic_tc_source(qdt,ixi^
l,ixo^
l,wct,w,x,wctprim)
1277 w,x,qsourcesplit,active,
rc_fl)
1286 if(eos%eos_type ==
'PI')
then
1287 if(.not.qsourcesplit)
then
1289 call eos%update_eos(ixi^
l,ixo^
l,w,x)
1292 end subroutine ffhd_add_source
1294 subroutine add_punitb(qdt,ixI^L,ixO^L,wCT,w,x,wCTprim)
1297 integer,
intent(in) :: ixi^
l,ixo^
l
1298 double precision,
intent(in) :: qdt
1299 double precision,
intent(in) :: wct(ixi^s,1:nw),x(ixi^s,1:
ndim)
1300 double precision,
intent(in) :: wctprim(ixi^s,1:nw)
1301 double precision,
intent(inout) :: w(ixi^s,1:nw)
1303 integer :: idims,hxo^
l
1304 double precision :: divb(ixi^s)
1305 double precision :: rhovpar(ixi^s),gradrhov(ixi^s)
1310 hxo^
l=ixo^
l-
kr(idims,^
d);
1311 divb(ixo^s)=divb(ixo^s)+(
block%B0(ixo^s,idims,idims)-
block%B0(hxo^s,idims,idims))/
dxlevel(idims)
1316 w(ixo^s,
mom(1))=w(ixo^s,
mom(1))+qdt*wctprim(ixo^s,
p_)*divb(ixo^s)
1317 end subroutine add_punitb
1321 integer,
intent(in) :: ixi^
l, ixo^
l
1322 double precision,
intent(in) :: w(ixi^s,1:nw),x(ixi^s,1:
ndim)
1323 double precision,
intent(out) :: rho(ixi^s)
1325 rho(ixo^s) = w(ixo^s,
rho_)
1328 subroutine ffhd_handle_small_ei(w, x, ixI^L, ixO^L, ie, subname)
1331 integer,
intent(in) :: ixi^
l,ixo^
l, ie
1332 double precision,
intent(inout) :: w(ixi^s,1:nw)
1333 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1334 character(len=*),
intent(in) :: subname
1336 logical :: flag(ixi^s,1:nw)
1337 double precision :: rho(ixi^s)
1340 where(w(ixo^s,ie)<
small_e) flag(ixo^s,ie)=.true.
1341 if(any(flag(ixo^s,ie)))
then
1344 where(flag(ixo^s,ie)) w(ixo^s,ie)=
small_e
1348 w(ixo^s,
e_)=w(ixo^s,
e_)*eos%gamma_minus_1
1350 w(ixo^s,
mom(1)) = w(ixo^s,
mom(1))/rho(ixo^s)
1354 end subroutine ffhd_handle_small_ei
1357 subroutine ffhd_get_dt(wprim,ixI^L,ixO^L,dtnew,dx^D,x)
1361 integer,
intent(in) :: ixi^
l, ixo^
l
1362 double precision,
intent(inout) :: dtnew
1363 double precision,
intent(in) ::
dx^
d
1364 double precision,
intent(in) :: wprim(ixi^s,1:nw)
1365 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1372 end subroutine ffhd_get_dt
1374 subroutine ffhd_add_source_geom(qdt,dtfactor,ixI^L,ixO^L,wCT,wprim,w,x)
1376 integer,
intent(in) :: ixi^
l, ixo^
l
1377 double precision,
intent(in) :: qdt, dtfactor,x(ixi^s,1:
ndim)
1378 double precision,
intent(inout) :: wct(ixi^s,1:nw), wprim(ixi^s,1:nw),w(ixi^s,1:nw)
1381 end subroutine ffhd_add_source_geom
1383 function ffhd_kin_en_origin(w, ixI^L, ixO^L, inv_rho)
result(ke)
1385 integer,
intent(in) :: ixi^
l, ixo^
l
1386 double precision,
intent(in) :: w(ixi^s, nw)
1387 double precision :: ke(ixo^s)
1388 double precision,
intent(in),
optional :: inv_rho(ixo^s)
1390 if(
present(inv_rho))
then
1391 ke(ixo^s)=0.5d0*w(ixo^s,
mom(1))**2*inv_rho(ixo^s)
1393 ke(ixo^s)=0.5d0*w(ixo^s,
mom(1))**2/w(ixo^s,
rho_)
1395 end function ffhd_kin_en_origin
1400 integer,
intent(in) :: ixi^
l, ixo^
l
1401 double precision,
intent(in) :: w(ixi^s,1:nw)
1402 double precision,
intent(in) :: x(ixi^s,1:
ndim)
1403 double precision,
intent(out):: rfactor(ixi^s)
1408 subroutine add_hyperbolic_tc_source(qdt,ixI^L,ixO^L,wCT,w,x,wCTprim)
1411 integer,
intent(in) :: ixi^
l,ixo^
l
1412 double precision,
intent(in) :: qdt
1413 double precision,
dimension(ixI^S,1:ndim),
intent(in) :: x
1414 double precision,
dimension(ixI^S,1:nw),
intent(in) :: wct,wctprim
1415 double precision,
dimension(ixI^S,1:nw),
intent(inout) :: w
1417 double precision,
dimension(ixI^S) :: te, r
1418 double precision :: sigma_t5,sigma_t7,sigmat5_bgradt,f_sat,tau
1426 te(ixi^s)=wctprim(ixi^s,
p_)/(r(ixi^s)*wct(ixi^s,
rho_))
1430 do ix2=ixomin2,ixomax2
1431 do ix1=ixomin1,ixomax1
1438 sigma_t7=sigma_t5*te(ix^
d)
1442 sigma_t7=sigma_t5*te(ix^
d)
1444 sigmat5_bgradt=sigma_t5*(&
1445 block%B0(ix^
d,1,0)*((8.d0*(te(ix1+1,ix2)-te(ix1-1,ix2))-te(ix1+2,ix2)+te(ix1-2,ix2))/12.d0)/
block%ds(ix^
d,1)&
1446 +
block%B0(ix^
d,2,0)*((8.d0*(te(ix1,ix2+1)-te(ix1,ix2-1))-te(ix1,ix2+2)+te(ix1,ix2-2))/12.d0)/
block%ds(ix^
d,2))
1449 f_sat=one/(one+dabs(sigmat5_bgradt)/(1.5d0*wct(ix^
d,
rho_)*(wctprim(ix^
d,
p_)/wct(ix^
d,
rho_))**1.5d0))
1451 w(ix^
d,
q_)=w(ix^
d,
q_)-qdt*(f_sat*sigmat5_bgradt+wct(ix^
d,
q_))/tau
1453 w(ix^
d,
q_)=w(ix^
d,
q_)-qdt*(sigmat5_bgradt+wct(ix^
d,
q_))/&
1460 do ix3=ixomin3,ixomax3
1461 do ix2=ixomin2,ixomax2
1462 do ix1=ixomin1,ixomax1
1469 sigma_t7=sigma_t5*te(ix^
d)
1473 sigma_t7=sigma_t5*te(ix^
d)
1475 sigmat5_bgradt=sigma_t5*(&
1476 block%B0(ix^
d,1,0)*((8.d0*(te(ix1+1,ix2,ix3)-te(ix1-1,ix2,ix3))-te(ix1+2,ix2,ix3)+te(ix1-2,ix2,ix3))/12.d0)/
block%ds(ix^
d,1)&
1477 +
block%B0(ix^
d,2,0)*((8.d0*(te(ix1,ix2+1,ix3)-te(ix1,ix2-1,ix3))-te(ix1,ix2+2,ix3)+te(ix1,ix2-2,ix3))/12.d0)/
block%ds(ix^
d,2)&
1478 +
block%B0(ix^
d,3,0)*((8.d0*(te(ix1,ix2,ix3+1)-te(ix1,ix2,ix3-1))-te(ix1,ix2,ix3+2)+te(ix1,ix2,ix3-2))/12.d0)/
block%ds(ix^
d,3))
1481 f_sat=one/(one+dabs(sigmat5_bgradt)/(1.5d0*wct(ix^
d,
rho_)*(wctprim(ix^
d,
p_)/wct(ix^
d,
rho_))**1.5d0))
1483 w(ix^
d,
q_)=w(ix^
d,
q_)-qdt*(f_sat*sigmat5_bgradt+wct(ix^
d,
q_))/tau
1485 w(ix^
d,
q_)=w(ix^
d,
q_)-qdt*(sigmat5_bgradt+wct(ix^
d,
q_))/&
1492 end subroutine add_hyperbolic_tc_source
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module for physical and numeric constants.
double precision, parameter bigdouble
A very large real number.
subroutine add_convert_method(phys_convert_vars, nwc, dataset_names, file_suffix)
PI (partial-ionisation) ionisation-degree backend for the eos% family.
Equation of state for AMRVAC, handled through a single eos_container object.
Frozen-field hydrodynamics module.
integer, public, protected te_
Indices of temperature and electron number density (LTE stored aux state)
integer, public, protected ffhd_trac_type
Which TRAC method is used.
integer, public, protected e_
Index of the energy density (-1 if not present)
subroutine, public ffhd_to_primitive_origin(ixil, ixol, w, x)
double precision, public hyperbolic_tc_kappa
The thermal conductivity kappa in hyperbolic thermal conduction.
procedure(sub_get_pthermal), pointer, public ffhd_get_rfactor
double precision, public ffhd_adiab
The adiabatic index (now owned by eos%; use eosgamma)
procedure(sub_get_pthermal), pointer, public ffhd_get_temperature
type(rc_fluid), allocatable, public rc_fl
type of fluid for radiative cooling
integer, public, protected rho_
Whether plasma is partially ionized.
integer, public, protected tcoff_
Index of the cutoff temperature for the TRAC method.
procedure(sub_get_pthermal), pointer, public ffhd_get_pthermal
subroutine, public ffhd_get_rho(w, x, ixil, ixol, rho)
integer, public, protected ne_
procedure(sub_convert), pointer, public ffhd_to_conserved
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
subroutine, public ffhd_get_temperature_from_etot(w, x, ixil, ixol, res)
logical, public, protected ffhd_hyperbolic_tc_use_perp
Whether the perpendicular hyperbolic-TC channel is enabled.
double precision, public, protected h_ion_fr
Helium abundance over Hydrogen (now owned by eos%; use eosHe_abundance) Ionization fraction of H H_io...
procedure(fun_kin_en), pointer, public ffhd_kin_en
subroutine, public ffhd_phys_init()
procedure(sub_get_v), pointer, public ffhd_get_v
subroutine, public ffhd_get_csound2(w, x, ixil, ixol, csound2)
logical, public, protected ffhd_energy
Whether an energy equation is used.
double precision, public, protected rr
type(tc_fluid), allocatable, public tc_fl
type of fluid for thermal conduction
double precision function, dimension(ixo^s), public ffhd_get_ei(w, ixil, ixol)
Internal energy eint = E_total - E_kinetic (single field-aligned momentum). Wired to phys_get_ei; the...
type(te_fluid), allocatable, public te_fl_ffhd
type of fluid for thermal emission synthesis
logical, public, protected ffhd_hyperbolic_tc
Whether hyperbolic type thermal conduction is used.
logical, public, protected ffhd_radiative_cooling
Whether radiative cooling is added.
subroutine, public ffhd_get_v_idim(w, x, ixil, ixol, idim, v)
subroutine, public ffhd_get_pthermal_origin(w, x, ixil, ixol, pth)
integer, public, protected q_
procedure(sub_convert), pointer, public ffhd_to_primitive
logical, public, protected ffhd_hyperbolic_tc_sat
Whether saturation is considered for hyperbolic TC.
subroutine, public ffhd_get_temperature_from_te(w, x, ixil, ixol, res)
integer, public, protected tweight_
double precision, public, protected he_ion_fr2
Ratio of number He2+ / number He+ + He2+ He_ion_fr2 = He2+/(He2+ + He+)
logical, public, protected ffhd_trac
Whether TRAC method is used.
subroutine, public ffhd_to_conserved_origin(ixil, ixol, w, x)
logical, public, protected ffhd_thermal_conduction
Whether thermal conduction is used.
subroutine, public ffhd_ei_to_e(ixil, ixol, w, x)
logical, public, protected ffhd_gravity
Whether gravity is added.
subroutine, public rfactor_from_constant_ionization(w, x, ixil, ixol, rfactor)
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
double precision, public, protected ffhd_trac_mask
Height of the mask used in the TRAC method.
double precision, public, protected he_ion_fr
Ionization fraction of He He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
subroutine, public ffhd_get_temperature_from_eint(w, x, ixil, ixol, res)
integer, public, protected ffhd_trac_finegrid
Distance between two adjacent traced magnetic field lines (in finest cell size)
procedure(sub_small_values), pointer, public ffhd_handle_small_values
subroutine, public ffhd_e_to_ei(ixil, ixol, w, x)
Module for flux conservation near refinement boundaries.
Module with geometry-related routines (e.g., divergence, curl)
subroutine divvector(qvec, ixil, ixol, divq, nth_in)
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 small_pressure
double precision unit_time
Physical scaling factor for time.
double precision unit_density
Physical scaling factor for density.
integer, parameter unitpar
file handle for IO
double precision unit_mass
Physical scaling factor for mass.
integer, dimension(3, 3) kr
Kronecker delta tensor.
double precision phys_trac_mask
double precision unit_numberdensity
Physical scaling factor for number density.
character(len=std_len) convert_type
Which format to use when converting.
double precision unit_pressure
Physical scaling factor for pressure.
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision unit_length
Physical scaling factor for length.
double precision cmax_global
global fastest wave speed needed in fd scheme and glm method
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 dt
global time step
integer ndir
Number of spatial dimensions (components) for vector variables.
double precision courantpar
The Courant (CFL) number used for the simulation.
double precision, dimension(:), allocatable, parameter d
logical slab
Cartesian geometry or not.
integer nwauxio
Number of auxiliary variables that are only included in output.
double precision unit_velocity
Physical scaling factor for velocity.
logical b0field
split magnetic field as background B0 field
double precision unit_temperature
Physical scaling factor for temperature.
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 nghostcells
Number of ghost cells surrounding a grid.
logical phys_trac
Use TRAC for MHD or 1D HD.
logical need_global_cmax
need global maximal wave speed
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 slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
double precision small_density
integer boundspeed
bound (left/min and right.max) speed of Riemann fan
integer phys_trac_finegrid
integer, parameter unitconvert
integer number_equi_vars
number of equilibrium set variables, besides the mag field
Module for including gravity in (magneto)hydrodynamics simulations.
subroutine gravity_get_dt(wprim, ixil, ixol, dtnew, dxd, x)
subroutine gravity_init()
Initialize the module.
subroutine gravity_add_source(qdt, ixil, ixol, wct, wctprim, w, x, energy, qsourcesplit, active)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO
This module defines the procedures of a physics module. It contains function pointers for the various...
module radiative cooling – add optically thin radiative cooling
subroutine radiative_cooling_init_params(phys_gamma, he_abund)
Radiative cooling initialization.
subroutine radiative_cooling_init(fl, read_params)
subroutine radiative_cooling_add_source(qdt, ixil, ixol, wct, wctprim, w, x, qsourcesplit, active, fl)
Module for handling problematic values in simulations, such as negative pressures.
subroutine, public small_values_average(ixil, ixol, w, x, w_flag, windex)
logical, public trace_small_values
trace small values in the source file using traceback flag of compiler
subroutine, public small_values_error(wprim, x, ixil, ixol, w_flag, subname)
logical, dimension(:), allocatable, public small_values_fix_iw
Whether to apply small value fixes to certain variables.
character(len=20), public small_values_method
How to handle small values.
Generic supertimestepping method which can be used for multiple source terms in the governing equatio...
subroutine, public add_sts_method(sts_getdt, sts_set_sources, startvar, nflux, startwbc, nwbc, evolve_b)
subroutine which added programatically a term to be calculated using STS Params: sts_getdt function c...
subroutine, public set_conversion_methods_to_head(sts_before_first_cycle, sts_after_last_cycle)
Set the hooks called before the first cycle and after the last cycle in the STS update This method sh...
subroutine, public set_error_handling_to_head(sts_error_handling)
Set the hook of error handling in the STS update. This method is called before updating the BC....
subroutine, public sts_init()
Initialize sts module.
Thermal conduction for HD and MHD or RHD and RMHD or twofl (plasma-neutral) module Adaptation of mod_...
subroutine, public tc_get_hd_params(fl, read_hd_params)
Init TC coefficients: HD case.
double precision function, public get_tc_dt_mhd(w, ixil, ixol, dxd, x, fl)
Get the explicit timestep for the TC (mhd implementation) Note: for multi-D MHD (1D MHD will use HD f...
subroutine tc_init_params(phys_gamma)
subroutine, public sts_set_source_tc_mhd(ixil, ixol, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux, fl)
anisotropic thermal conduction with slope limited symmetric scheme Sharma 2007 Journal of Computation...
subroutine get_euv_image(qunit, fl)
subroutine get_sxr_image(qunit, fl)
subroutine get_euv_spectrum(qunit, fl)
subroutine get_whitelight_image(qunit, fl)
Module with all the methods that users can customize in AMRVAC.
procedure(rfactor), pointer usr_rfactor
procedure(set_equi_vars), pointer usr_set_equi_vars