MPI-AMRVAC  3.1
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
mod_ffhd_phys.t
Go to the documentation of this file.
1 !> Frozen-field hydrodynamics module
3 
4 #include "amrvac.h"
5 
6  use mod_global_parameters, only: std_len, const_c
10  use mod_physics
11  use mod_comm_lib, only: mpistop
12 
13  implicit none
14  private
15 
16  !> Whether an energy equation is used
17  logical, public, protected :: ffhd_energy = .true.
18 
19  !> Whether thermal conduction is used
20  logical, public, protected :: ffhd_thermal_conduction = .false.
21  !> Whether hyperbolic type thermal conduction is used
22  logical, public, protected :: ffhd_hyperbolic_thermal_conduction = .false.
23  !> type of fluid for thermal conduction
24  type(tc_fluid), public, allocatable :: tc_fl
25  !> type of fluid for thermal emission synthesis
26  type(te_fluid), public, allocatable :: te_fl_ffhd
27 
28  !> Whether radiative cooling is added
29  logical, public, protected :: ffhd_radiative_cooling = .false.
30  !> type of fluid for radiative cooling
31  type(rc_fluid), public, allocatable :: rc_fl
32 
33  !> Whether viscosity is added
34  logical, public, protected :: ffhd_viscosity = .false.
35 
36  !> Whether gravity is added
37  logical, public, protected :: ffhd_gravity = .false.
38 
39  !> Whether TRAC method is used
40  logical, public, protected :: ffhd_trac = .false.
41 
42  !> Which TRAC method is used
43  integer, public, protected :: ffhd_trac_type=1
44 
45  !> Height of the mask used in the TRAC method
46  double precision, public, protected :: ffhd_trac_mask = 0.d0
47 
48  !> Distance between two adjacent traced magnetic field lines (in finest cell size)
49  integer, public, protected :: ffhd_trac_finegrid=4
50 
51  !> Whether plasma is partially ionized
52  logical, public, protected :: ffhd_partial_ionization = .false.
53 
54  !> Index of the density (in the w array)
55  integer, public, protected :: rho_
56 
57  !> Indices of the momentum density
58  integer, allocatable, public, protected :: mom(:)
59 
60  !> Index of the energy density (-1 if not present)
61  integer, public, protected :: e_
62 
63  !> Index of the gas pressure (-1 if not present) should equal e_
64  integer, public, protected :: p_
65 
66  !> Indices of temperature
67  integer, public, protected :: te_
68 
69  !> Index of the cutoff temperature for the TRAC method
70  integer, public, protected :: tcoff_
71  integer, public, protected :: tweight_
72  integer, public, protected :: q_
73 
74  !> The adiabatic index
75  double precision, public :: ffhd_gamma = 5.d0/3.0d0
76 
77  !> The adiabatic constant
78  double precision, public :: ffhd_adiab = 1.0d0
79 
80  !> The small_est allowed energy
81  double precision, protected :: small_e
82 
83  !> The thermal conductivity kappa in hyperbolic thermal conduction
84  double precision, public :: hypertc_kappa
85 
86  !> Helium abundance over Hydrogen
87  double precision, public, protected :: he_abundance=0.1d0
88  !> Ionization fraction of H
89  !> H_ion_fr = H+/(H+ + H)
90  double precision, public, protected :: h_ion_fr=1d0
91  !> Ionization fraction of He
92  !> He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
93  double precision, public, protected :: he_ion_fr=1d0
94  !> Ratio of number He2+ / number He+ + He2+
95  !> He_ion_fr2 = He2+/(He2+ + He+)
96  double precision, public, protected :: he_ion_fr2=1d0
97  ! used for eq of state when it is not defined by units,
98  ! the units do not contain terms related to ionization fraction
99  ! and it is p = RR * rho * T
100  double precision, public, protected :: rr=1d0
101  ! remove the below flag and assume default value = .false.
102  ! when eq state properly implemented everywhere
103  ! and not anymore through units
104  logical, public, protected :: eq_state_units = .true.
105 
106  !> gamma minus one and its inverse
107  double precision :: gamma_1, inv_gamma_1
108 
109  !define the subroutine interface for the ambipolar mask
110  abstract interface
111 
112  function fun_kin_en(w, ixI^L, ixO^L, inv_rho) result(ke)
113  use mod_global_parameters, only: nw, ndim,block
114  integer, intent(in) :: ixi^l, ixo^l
115  double precision, intent(in) :: w(ixi^s, nw)
116  double precision :: ke(ixo^s)
117  double precision, intent(in), optional :: inv_rho(ixo^s)
118  end function fun_kin_en
119 
120  end interface
121 
122  procedure(sub_convert), pointer :: ffhd_to_primitive => null()
123  procedure(sub_convert), pointer :: ffhd_to_conserved => null()
124  procedure(sub_small_values), pointer :: ffhd_handle_small_values => null()
125  procedure(sub_get_pthermal), pointer :: ffhd_get_pthermal => null()
126  procedure(sub_get_pthermal), pointer :: ffhd_get_rfactor => null()
127  procedure(sub_get_pthermal), pointer :: ffhd_get_temperature => null()
128  procedure(sub_get_v), pointer :: ffhd_get_v => null()
129  procedure(fun_kin_en), pointer :: ffhd_kin_en => null()
130  ! Public methods
131  public :: ffhd_phys_init
132  public :: ffhd_kin_en
133  public :: ffhd_get_pthermal
134  public :: ffhd_get_temperature
135  public :: ffhd_get_v
136  public :: ffhd_get_rho
137  public :: ffhd_get_v_idim
138  public :: ffhd_to_conserved
139  public :: ffhd_to_primitive
140  public :: ffhd_get_csound2
141  public :: ffhd_e_to_ei
142  public :: ffhd_ei_to_e
143 
144 contains
145 
146  subroutine ffhd_read_params(files)
148  use mod_particles, only: particles_eta, particles_etah
149  character(len=*), intent(in) :: files(:)
150  integer :: n
151 
152  namelist /ffhd_list/ ffhd_energy, ffhd_gamma, ffhd_adiab,&
156 
157  do n = 1, size(files)
158  open(unitpar, file=trim(files(n)), status="old")
159  read(unitpar, ffhd_list, end=111)
160 111 close(unitpar)
161  end do
162  end subroutine ffhd_read_params
163 
164  !> Write this module's parameters to a snapsoht
165  subroutine ffhd_write_info(fh)
167  integer, intent(in) :: fh
168  integer, parameter :: n_par = 1
169  double precision :: values(n_par)
170  character(len=name_len) :: names(n_par)
171  integer, dimension(MPI_STATUS_SIZE) :: st
172  integer :: er
173 
174  call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
175 
176  names(1) = "gamma"
177  values(1) = ffhd_gamma
178  call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
179  call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
180  end subroutine ffhd_write_info
181 
182  subroutine ffhd_phys_init()
186  use mod_viscosity, only: viscosity_init
187  use mod_gravity, only: gravity_init
191  use mod_usr_methods, only: usr_rfactor
192  integer :: itr, idir
193 
194  call ffhd_read_params(par_files)
195 
196  if(.not. ffhd_energy) then
197  if(ffhd_thermal_conduction) then
199  if(mype==0) write(*,*) 'WARNING: set ffhd_thermal_conduction=F when ffhd_energy=F'
200  end if
201  if(ffhd_thermal_conduction) then
203  if(mype==0) write(*,*) 'WARNING: set ffhd_hyperbolic_thermal_conduction=F when ffhd_energy=F'
204  end if
205  if(ffhd_radiative_cooling) then
206  ffhd_radiative_cooling=.false.
207  if(mype==0) write(*,*) 'WARNING: set ffhd_radiative_cooling=F when ffhd_energy=F'
208  end if
209  if(ffhd_trac) then
210  ffhd_trac=.false.
211  if(mype==0) write(*,*) 'WARNING: set ffhd_trac=F when ffhd_energy=F'
212  end if
213  if(ffhd_partial_ionization) then
215  if(mype==0) write(*,*) 'WARNING: set ffhd_partial_ionization=F when ffhd_energy=F'
216  end if
217  end if
218  if(.not.eq_state_units) then
219  if(ffhd_partial_ionization) then
221  if(mype==0) write(*,*) 'WARNING: set ffhd_partial_ionization=F when eq_state_units=F'
222  end if
223  end if
224 
227  if(mype==0) write(*,*) 'WARNING: turn off parabolic TC when using hyperbolic TC'
228  end if
229 
230  physics_type = "ffhd"
231  phys_energy=ffhd_energy
232  phys_internal_e=.false.
235  phys_partial_ionization=ffhd_partial_ionization
236 
237  phys_gamma = ffhd_gamma
238  phys_total_energy=ffhd_energy
240 
241  {^ifoned
242  if(ffhd_trac .and. ffhd_trac_type .gt. 2) then
244  if(mype==0) write(*,*) 'WARNING: reset ffhd_trac_type=1 for 1D simulation'
245  end if
246  }
247  if(ffhd_trac .and. ffhd_trac_type .le. 4) then
248  ffhd_trac_mask=bigdouble
249  if(mype==0) write(*,*) 'WARNING: set ffhd_trac_mask==bigdouble for global TRAC method'
250  end if
252 
253  allocate(start_indices(number_species),stop_indices(number_species))
254  ! set the index of the first flux variable for species 1
255  start_indices(1)=1
256  ! Determine flux variables
257  rho_ = var_set_rho()
258 
259  allocate(mom(1))
260  mom(:) = var_set_momentum(1)
261 
262  ! Set index of energy variable
263  if(ffhd_energy) then
264  e_ = var_set_energy() ! energy density
265  p_ = e_ ! gas pressure
266  else
267  e_ = -1
268  p_ = -1
269  end if
270 
272  q_ = var_set_q()
273  need_global_cs2max=.true.
274  else
275  q_=-1
276  end if
277 
278  ! set number of variables which need update ghostcells
279  nwgc=nwflux
280 
281  ! set the index of the last flux variable for species 1
282  stop_indices(1)=nwflux
283 
284  ! set temperature as an auxiliary variable to get ionization degree
285  if(ffhd_partial_ionization) then
286  te_ = var_set_auxvar('Te','Te')
287  else
288  te_ = -1
289  end if
290 
291  ! set cutoff temperature when using the TRAC method, as well as an auxiliary weight
292  tweight_ = -1
293  if(ffhd_trac) then
294  tcoff_ = var_set_wextra()
295  iw_tcoff=tcoff_
296  if(ffhd_trac_type .ge. 3) then
297  tweight_ = var_set_wextra()
298  iw_tweight=tweight_
299  end if
300  else
301  tcoff_ = -1
302  end if
303 
304  nvector = 0 ! No. vector vars
305 
306  ! Check whether custom flux types have been defined
307  if(.not. allocated(flux_type)) then
308  allocate(flux_type(ndir, nwflux))
309  flux_type = flux_default
310  else if(any(shape(flux_type) /= [ndir, nwflux])) then
311  call mpistop("phys_check error: flux_type has wrong shape")
312  end if
313 
314  phys_get_dt => ffhd_get_dt
315  phys_get_cmax => ffhd_get_cmax_origin
316  phys_get_a2max => ffhd_get_a2max
317  phys_get_cs2max => ffhd_get_cs2max
318  phys_get_tcutoff => ffhd_get_tcutoff
319  phys_get_cbounds => ffhd_get_cbounds
320  phys_to_primitive => ffhd_to_primitive_origin
322  phys_to_conserved => ffhd_to_conserved_origin
324  phys_get_flux => ffhd_get_flux
325  phys_get_v => ffhd_get_v_origin
327  phys_get_rho => ffhd_get_rho
329  !> need to check source geom here
330  !phys_add_source_geom => ffhd_add_source_geom
331  phys_add_source => ffhd_add_source
332  phys_check_params => ffhd_check_params
333  phys_write_info => ffhd_write_info
334  phys_handle_small_values => ffhd_handle_small_values_origin
335  ffhd_handle_small_values => ffhd_handle_small_values_origin
336  phys_check_w => ffhd_check_w_origin
337 
338  if(.not.ffhd_energy) then
339  phys_get_pthermal => ffhd_get_pthermal_iso
341  else
342  phys_get_pthermal => ffhd_get_pthermal_origin
344  end if
345 
346  ! choose Rfactor in ideal gas law
347  if(ffhd_partial_ionization) then
348  ffhd_get_rfactor=>rfactor_from_temperature_ionization
349  phys_update_temperature => ffhd_update_temperature
350  else if(associated(usr_rfactor)) then
351  ffhd_get_rfactor=>usr_rfactor
352  else
353  ffhd_get_rfactor=>rfactor_from_constant_ionization
354  end if
355 
356  if(ffhd_partial_ionization) then
358  else
360  end if
361 
362  ! derive units from basic units
363  call ffhd_physical_units()
364 
367  end if
368  if(.not. ffhd_energy .and. ffhd_thermal_conduction) then
369  call mpistop("thermal conduction needs ffhd_energy=T")
370  end if
372  call mpistop("hyperbolic thermal conduction needs ffhd_energy=T")
373  end if
374  if(.not. ffhd_energy .and. ffhd_radiative_cooling) then
375  call mpistop("radiative cooling needs ffhd_energy=T")
376  end if
377 
378  ! initialize thermal conduction module
379  if(ffhd_thermal_conduction) then
380  phys_req_diagonal = .true.
381 
382  call sts_init()
384 
385  allocate(tc_fl)
388  tc_fl%get_temperature_from_conserved => ffhd_get_temperature_from_etot
389  tc_fl%get_temperature_from_eint => ffhd_get_temperature_from_eint
392  tc_fl%get_rho => ffhd_get_rho
393  tc_fl%e_ = e_
394  tc_fl%Tcoff_ = tcoff_
395  end if
396 
397  ! Initialize radiative cooling module
398  if(ffhd_radiative_cooling) then
400  allocate(rc_fl)
402  rc_fl%get_rho => ffhd_get_rho
403  rc_fl%get_pthermal => ffhd_get_pthermal
404  rc_fl%get_var_Rfactor => ffhd_get_rfactor
405  rc_fl%e_ = e_
406  rc_fl%Tcoff_ = tcoff_
407  rc_fl%has_equi = .false.
408  end if
409  allocate(te_fl_ffhd)
410  te_fl_ffhd%get_rho=> ffhd_get_rho
411  te_fl_ffhd%get_pthermal=> ffhd_get_pthermal
412  te_fl_ffhd%get_var_Rfactor => ffhd_get_rfactor
413 {^ifthreed
414  phys_te_images => ffhd_te_images
415 }
416  ! Initialize viscosity module
417  if(ffhd_viscosity) call viscosity_init(phys_wider_stencil,phys_req_diagonal)
418 
419  ! Initialize gravity module
420  if(ffhd_gravity) then
421  call gravity_init()
422  end if
423 
424  ! initialize ionization degree table
426  end subroutine ffhd_phys_init
427 
428 {^ifthreed
429  subroutine ffhd_te_images
432 
433  select case(convert_type)
434  case('EIvtiCCmpi','EIvtuCCmpi')
436  case('ESvtiCCmpi','ESvtuCCmpi')
438  case('SIvtiCCmpi','SIvtuCCmpi')
440  case('WIvtiCCmpi','WIvtuCCmpi')
442  case default
443  call mpistop("Error in synthesize emission: Unknown convert_type")
444  end select
445  end subroutine ffhd_te_images
446 }
447 
448  subroutine ffhd_sts_set_source_tc_ffhd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
450  use mod_fix_conserve
452  integer, intent(in) :: ixI^L, ixO^L, igrid, nflux
453  double precision, intent(in) :: x(ixI^S,1:ndim)
454  double precision, intent(inout) :: wres(ixI^S,1:nw), w(ixI^S,1:nw)
455  double precision, intent(in) :: my_dt
456  logical, intent(in) :: fix_conserve_at_step
457  call sts_set_source_tc_ffhd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl)
458  end subroutine ffhd_sts_set_source_tc_ffhd
459 
460  function ffhd_get_tc_dt_ffhd(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
461  !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para_i/rho)
462  !where tc_k_para_i=tc_k_para*B_i**2/B**2
463  !and T=p/rho
466 
467  integer, intent(in) :: ixi^l, ixo^l
468  double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
469  double precision, intent(in) :: w(ixi^s,1:nw)
470  double precision :: dtnew
471 
472  dtnew=get_tc_dt_ffhd(w,ixi^l,ixo^l,dx^d,x,tc_fl)
473  end function ffhd_get_tc_dt_ffhd
474 
475  subroutine ffhd_tc_handle_small_e(w, x, ixI^L, ixO^L, step)
477 
478  integer, intent(in) :: ixI^L,ixO^L
479  double precision, intent(inout) :: w(ixI^S,1:nw)
480  double precision, intent(in) :: x(ixI^S,1:ndim)
481  integer, intent(in) :: step
482  character(len=140) :: error_msg
483 
484  write(error_msg,"(a,i3)") "Thermal conduction step ", step
485  call ffhd_handle_small_ei(w,x,ixi^l,ixo^l,e_,error_msg)
486  end subroutine ffhd_tc_handle_small_e
487 
488  subroutine tc_params_read_ffhd(fl)
490  type(tc_fluid), intent(inout) :: fl
491  integer :: n
492  ! list parameters
493  logical :: tc_saturate=.false.
494  double precision :: tc_k_para=0d0
495  character(len=std_len) :: tc_slope_limiter="MC"
496 
497  namelist /tc_list/ tc_saturate, tc_slope_limiter, tc_k_para
498 
499  do n = 1, size(par_files)
500  open(unitpar, file=trim(par_files(n)), status="old")
501  read(unitpar, tc_list, end=111)
502 111 close(unitpar)
503  end do
504 
505  fl%tc_saturate = tc_saturate
506  fl%tc_k_para = tc_k_para
507  select case(tc_slope_limiter)
508  case ('no','none')
509  fl%tc_slope_limiter = 0
510  case ('MC')
511  ! montonized central limiter Woodward and Collela limiter (eq.3.51h), a factor of 2 is pulled out
512  fl%tc_slope_limiter = 1
513  case('minmod')
514  ! minmod limiter
515  fl%tc_slope_limiter = 2
516  case ('superbee')
517  ! Roes superbee limiter (eq.3.51i)
518  fl%tc_slope_limiter = 3
519  case ('koren')
520  ! Barry Koren Right variant
521  fl%tc_slope_limiter = 4
522  case default
523  call mpistop("Unknown tc_slope_limiter, choose MC, minmod")
524  end select
525  end subroutine tc_params_read_ffhd
526 
527  subroutine rc_params_read(fl)
529  use mod_constants, only: bigdouble
530  type(rc_fluid), intent(inout) :: fl
531  integer :: n
532  integer :: ncool = 4000
533  double precision :: cfrac=0.1d0
534 
535  !> Name of cooling curve
536  character(len=std_len) :: coolcurve='JCcorona'
537 
538  !> Name of cooling method
539  character(len=std_len) :: coolmethod='exact'
540 
541  !> Fixed temperature not lower than tlow
542  logical :: Tfix=.false.
543 
544  !> Lower limit of temperature
545  double precision :: tlow=bigdouble
546 
547  !> Add cooling source in a split way (.true.) or un-split way (.false.)
548  logical :: rc_split=.false.
549  logical :: rad_cut=.false.
550  double precision :: rad_cut_hgt=0.5d0
551  double precision :: rad_cut_dey=0.15d0
552 
553  namelist /rc_list/ coolcurve, coolmethod, ncool, cfrac, tlow, tfix, rc_split, rad_cut, rad_cut_hgt, rad_cut_dey
554 
555  do n = 1, size(par_files)
556  open(unitpar, file=trim(par_files(n)), status="old")
557  read(unitpar, rc_list, end=111)
558 111 close(unitpar)
559  end do
560 
561  fl%ncool=ncool
562  fl%coolcurve=coolcurve
563  fl%coolmethod=coolmethod
564  fl%tlow=tlow
565  fl%Tfix=tfix
566  fl%rc_split=rc_split
567  fl%cfrac=cfrac
568  fl%rad_cut=rad_cut
569  fl%rad_cut_hgt=rad_cut_hgt
570  fl%rad_cut_dey=rad_cut_dey
571  end subroutine rc_params_read
572 
573  subroutine ffhd_check_params
575  use mod_usr_methods
577 
578  gamma_1=ffhd_gamma-1.d0
579  if (.not. ffhd_energy) then
580  if (ffhd_gamma <= 0.0d0) call mpistop ("Error: ffhd_gamma <= 0")
581  if (ffhd_adiab < 0.0d0) call mpistop ("Error: ffhd_adiab < 0")
583  else
584  if (ffhd_gamma <= 0.0d0 .or. ffhd_gamma == 1.0d0) &
585  call mpistop ("Error: ffhd_gamma <= 0 or ffhd_gamma == 1")
586  inv_gamma_1=1.d0/gamma_1
587  small_e = small_pressure * inv_gamma_1
588  end if
589 
590  if (number_equi_vars > 0 .and. .not. associated(usr_set_equi_vars)) then
591  call mpistop("usr_set_equi_vars has to be implemented in the user file")
592  end if
593  end subroutine ffhd_check_params
594 
595  subroutine ffhd_physical_units()
597  double precision :: mp,kB
598  double precision :: a,b
599 
600  if(si_unit) then
601  mp=mp_si
602  kb=kb_si
603  else
604  mp=mp_cgs
605  kb=kb_cgs
606  end if
607  if(eq_state_units) then
608  a = 1d0 + 4d0 * he_abundance
609  if(ffhd_partial_ionization) then
610  b = 2+.3d0
611  else
612  b = 1d0 + h_ion_fr + he_abundance*(he_ion_fr*(he_ion_fr2 + 1d0)+1d0)
613  end if
614  rr = 1d0
615  else
616  a = 1d0
617  b = 1d0
618  rr = (1d0 + h_ion_fr + he_abundance*(he_ion_fr*(he_ion_fr2 + 1d0)+1d0))/(1d0 + 4d0 * he_abundance)
619  end if
620  if(unit_density/=1.d0) then
622  else
624  end if
625  if(unit_velocity/=1.d0) then
628  else if(unit_pressure/=1.d0) then
631  else
634  end if
635  if(unit_time/=1.d0) then
637  else
639  end if
641  end subroutine ffhd_physical_units
642 
643  subroutine ffhd_check_w_origin(primitive,ixI^L,ixO^L,w,flag)
645  logical, intent(in) :: primitive
646  integer, intent(in) :: ixI^L, ixO^L
647  double precision, intent(in) :: w(ixI^S,nw)
648  double precision :: tmp(ixI^S)
649  logical, intent(inout) :: flag(ixI^S,1:nw)
650 
651  flag=.false.
652  where(w(ixo^s,rho_) < small_density) flag(ixo^s,rho_) = .true.
653 
654  if(ffhd_energy) then
655  if(primitive) then
656  where(w(ixo^s,e_) < small_pressure) flag(ixo^s,e_) = .true.
657  else
658  tmp(ixo^s)=w(ixo^s,e_)-ffhd_kin_en(w,ixi^l,ixo^l)
659  where(tmp(ixo^s) < small_e) flag(ixo^s,e_) = .true.
660  end if
661  end if
662  end subroutine ffhd_check_w_origin
663 
664  subroutine ffhd_to_conserved_origin(ixI^L,ixO^L,w,x)
666  integer, intent(in) :: ixI^L, ixO^L
667  double precision, intent(inout) :: w(ixI^S, nw)
668  double precision, intent(in) :: x(ixI^S, 1:ndim)
669  double precision :: inv_gamma2(ixO^S)
670  integer :: idir
671 
672  if(ffhd_energy) then
673  w(ixo^s,e_)=w(ixo^s,p_)*inv_gamma_1+half*w(ixo^s,mom(1))**2*w(ixo^s,rho_)
674  end if
675  w(ixo^s,mom(1))=w(ixo^s,rho_)*w(ixo^s,mom(1))
676  end subroutine ffhd_to_conserved_origin
677 
678  subroutine ffhd_to_primitive_origin(ixI^L,ixO^L,w,x)
680  integer, intent(in) :: ixI^L, ixO^L
681  double precision, intent(inout) :: w(ixI^S, nw)
682  double precision, intent(in) :: x(ixI^S, 1:ndim)
683  double precision :: inv_rho(ixO^S), gamma2(ixO^S)
684 
685  if(fix_small_values) then
686  !> fix small values preventing NaN numbers in the following converting
687  call ffhd_handle_small_values(.false., w, x, ixi^l, ixo^l, 'ffhd_to_primitive_origin')
688  end if
689 
690  w(ixo^s,mom(1)) = w(ixo^s,mom(1))/w(ixo^s,rho_)
691  if(ffhd_energy) then
692  w(ixo^s,p_)=gamma_1*(w(ixo^s,e_)-half*w(ixo^s,rho_)*w(ixo^s,mom(1))**2)
693  end if
694  end subroutine ffhd_to_primitive_origin
695 
696  subroutine ffhd_ei_to_e(ixI^L,ixO^L,w,x)
698  integer, intent(in) :: ixi^l, ixo^l
699  double precision, intent(inout) :: w(ixi^s, nw)
700  double precision, intent(in) :: x(ixi^s, 1:ndim)
701 
702  w(ixi^s,e_)=w(ixi^s,e_)+ffhd_kin_en(w,ixi^l,ixi^l)
703  end subroutine ffhd_ei_to_e
704 
705  subroutine ffhd_e_to_ei(ixI^L,ixO^L,w,x)
707  integer, intent(in) :: ixi^l, ixo^l
708  double precision, intent(inout) :: w(ixi^s, nw)
709  double precision, intent(in) :: x(ixi^s, 1:ndim)
710 
711  w(ixi^s,e_)=w(ixi^s,e_)-ffhd_kin_en(w,ixi^l,ixi^l)
712  if(fix_small_values) then
713  call ffhd_handle_small_ei(w,x,ixi^l,ixi^l,e_,'ffhd_e_to_ei')
714  end if
715  end subroutine ffhd_e_to_ei
716 
717  subroutine ffhd_handle_small_values_origin(primitive, w, x, ixI^L, ixO^L, subname)
719  use mod_small_values
720  logical, intent(in) :: primitive
721  integer, intent(in) :: ixI^L,ixO^L
722  double precision, intent(inout) :: w(ixI^S,1:nw)
723  double precision, intent(in) :: x(ixI^S,1:ndim)
724  character(len=*), intent(in) :: subname
725 
726  logical :: flag(ixI^S,1:nw)
727  double precision :: tmp2(ixI^S)
728 
729  call phys_check_w(primitive, ixi^l, ixi^l, w, flag)
730 
731  if(any(flag)) then
732  select case (small_values_method)
733  case ("replace")
734  where(flag(ixo^s,rho_)) w(ixo^s,rho_) = small_density
735  if(small_values_fix_iw(mom(1))) then
736  where(flag(ixo^s,rho_)) w(ixo^s, mom(1)) = 0.0d0
737  end if
738  if(ffhd_energy) then
739  if(primitive) then
740  where(flag(ixo^s,e_)) w(ixo^s,p_) = small_pressure
741  else
742  where(flag(ixo^s,e_))
743  w(ixo^s,e_) = small_e+ffhd_kin_en(w,ixi^l,ixo^l)
744  end where
745  end if
746  end if
747  case ("average")
748  call small_values_average(ixi^l, ixo^l, w, x, flag, rho_)
749  if(ffhd_energy) then
750  if(primitive) then
751  call small_values_average(ixi^l, ixo^l, w, x, flag, p_)
752  else
753  w(ixi^s,e_)=w(ixi^s,e_)-ffhd_kin_en(w,ixi^l,ixi^l)
754  call small_values_average(ixi^l, ixo^l, w, x, flag, e_)
755  w(ixi^s,e_)=w(ixi^s,e_)+ffhd_kin_en(w,ixi^l,ixi^l)
756  end if
757  end if
758  case default
759  if(.not.primitive) then
760  if(ffhd_energy) then
761  w(ixo^s,p_)=gamma_1*(w(ixo^s,e_)-ffhd_kin_en(w,ixi^l,ixo^l))
762  end if
763  w(ixo^s,mom(1))=w(ixo^s,mom(1))/w(ixo^s,rho_)
764  end if
765  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
766  end select
767  end if
768  end subroutine ffhd_handle_small_values_origin
769 
770  subroutine ffhd_get_v_origin(w,x,ixI^L,ixO^L,v)
772  integer, intent(in) :: ixI^L, ixO^L
773  double precision, intent(in) :: w(ixI^S,nw), x(ixI^S,1:ndim)
774  double precision, intent(out) :: v(ixI^S,ndir)
775  double precision :: rho(ixI^S)
776  integer :: idir
777 
778  call ffhd_get_rho(w,x,ixi^l,ixo^l,rho)
779  rho(ixo^s)=1.d0/rho(ixo^s)
780  do idir=1,ndir
781  v(ixo^s,ndir) = w(ixo^s,mom(1))*block%B0(ixo^s,idir,0)*rho(ixo^s)
782  end do
783  end subroutine ffhd_get_v_origin
784 
785  subroutine ffhd_get_v_idim(w,x,ixI^L,ixO^L,idim,v)
787  integer, intent(in) :: ixi^l, ixo^l, idim
788  double precision, intent(in) :: w(ixi^s,nw), x(ixi^s,1:ndim)
789  double precision, intent(out) :: v(ixi^s)
790  double precision :: rho(ixi^s)
791 
792  call ffhd_get_rho(w,x,ixi^l,ixo^l,rho)
793  v(ixo^s) = (w(ixo^s, mom(1))*block%B0(ixo^s,idim,0)) / rho(ixo^s)
794  end subroutine ffhd_get_v_idim
795 
796  subroutine ffhd_get_cmax_origin(w,x,ixI^L,ixO^L,idim,cmax)
798  integer, intent(in) :: ixI^L, ixO^L, idim
799  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
800  double precision, intent(inout) :: cmax(ixI^S)
801  double precision :: vel(ixI^S)
802 
803  call ffhd_get_csound(w,x,ixi^l,ixo^l,idim,cmax)
804  call ffhd_get_v_idim(w,x,ixi^l,ixo^l,idim,vel)
805 
806  cmax(ixo^s)=abs(vel(ixo^s))+cmax(ixo^s)
807  end subroutine ffhd_get_cmax_origin
808 
809  subroutine ffhd_get_cs2max(w,x,ixI^L,ixO^L,cs2max)
811  integer, intent(in) :: ixI^L, ixO^L
812  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
813  double precision, intent(inout) :: cs2max
814  double precision :: cs2(ixI^S)
815 
816  call ffhd_get_csound2(w,x,ixi^l,ixo^l,cs2)
817  cs2max=maxval(cs2(ixo^s))
818  end subroutine ffhd_get_cs2max
819 
820  subroutine ffhd_get_a2max(w,x,ixI^L,ixO^L,a2max)
822  integer, intent(in) :: ixI^L, ixO^L
823  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
824  double precision, intent(inout) :: a2max(ndim)
825  double precision :: a2(ixI^S,ndim,nw)
826  integer :: gxO^L,hxO^L,jxO^L,kxO^L,i,j
827 
828  a2=zero
829  do i = 1,ndim
830  !> 4th order
831  hxo^l=ixo^l-kr(i,^d);
832  gxo^l=hxo^l-kr(i,^d);
833  jxo^l=ixo^l+kr(i,^d);
834  kxo^l=jxo^l+kr(i,^d);
835  a2(ixo^s,i,1:nw)=abs(-w(kxo^s,1:nw)+16.d0*w(jxo^s,1:nw)&
836  -30.d0*w(ixo^s,1:nw)+16.d0*w(hxo^s,1:nw)-w(gxo^s,1:nw))
837  a2max(i)=maxval(a2(ixo^s,i,1:nw))/12.d0/dxlevel(i)**2
838  end do
839  end subroutine ffhd_get_a2max
840 
841  subroutine ffhd_get_tcutoff(ixI^L,ixO^L,w,x,Tco_local,Tmax_local)
843  use mod_geometry
844  integer, intent(in) :: ixI^L,ixO^L
845  double precision, intent(in) :: x(ixI^S,1:ndim)
846  double precision, intent(inout) :: w(ixI^S,1:nw)
847  double precision, intent(out) :: Tco_local,Tmax_local
848  double precision, parameter :: trac_delta=0.25d0
849  double precision :: tmp1(ixI^S),Te(ixI^S),lts(ixI^S)
850  double precision, dimension(ixI^S,1:ndir) :: bunitvec
851  double precision, dimension(ixI^S,1:ndim) :: gradT
852  double precision :: Bdir(ndim)
853  double precision :: ltrc,ltrp,altr(ixI^S)
854  integer :: idims,jxO^L,hxO^L,ixA^D,ixB^D
855  integer :: jxP^L,hxP^L,ixP^L,ixQ^L
856  logical :: lrlt(ixI^S)
857 
858  call ffhd_get_temperature(w,x,ixi^l,ixi^l,te)
859  tco_local=zero
860  tmax_local=maxval(te(ixo^s))
861 
862  {^ifoned
863  select case(ffhd_trac_type)
864  case(0)
865  !> test case, fixed cutoff temperature
866  block%wextra(ixi^s,tcoff_)=2.5d5/unit_temperature
867  case(1)
868  hxo^l=ixo^l-1;
869  jxo^l=ixo^l+1;
870  lts(ixo^s)=0.5d0*abs(te(jxo^s)-te(hxo^s))/te(ixo^s)
871  lrlt=.false.
872  where(lts(ixo^s) > trac_delta)
873  lrlt(ixo^s)=.true.
874  end where
875  if(any(lrlt(ixo^s))) then
876  tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
877  end if
878  case(2)
879  !> iijima et al. 2021, LTRAC method
880  ltrc=1.5d0
881  ltrp=4.d0
882  ixp^l=ixo^l^ladd1;
883  hxo^l=ixo^l-1;
884  jxo^l=ixo^l+1;
885  hxp^l=ixp^l-1;
886  jxp^l=ixp^l+1;
887  lts(ixp^s)=0.5d0*abs(te(jxp^s)-te(hxp^s))/te(ixp^s)
888  lts(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
889  lts(ixo^s)=0.25d0*(lts(jxo^s)+two*lts(ixo^s)+lts(hxo^s))
890  block%wextra(ixo^s,tcoff_)=te(ixo^s)*lts(ixo^s)**0.4d0
891  case default
892  call mpistop("ffhd_trac_type not allowed for 1D simulation")
893  end select
894  }
895  {^nooned
896  select case(ffhd_trac_type)
897  case(0)
898  !> test case, fixed cutoff temperature
899  if(slab_uniform) then
900  !> assume cgs units
901  block%wextra(ixi^s,tcoff_)=max(min(3.d5/unit_temperature,6.d5/unit_temperature-3.d-4/unit_temperature*unit_length*x(ixi^s,ndim)),zero)
902  else
903  block%wextra(ixi^s,tcoff_)=2.5d5/unit_temperature
904  end if
905  case(1,4,6)
906  do idims=1,ndim
907  call gradient(te,ixi^l,ixo^l,idims,tmp1)
908  gradt(ixo^s,idims)=tmp1(ixo^s)
909  end do
910  bunitvec(ixo^s,:)=block%B0(ixo^s,:,0)
911  if(ffhd_trac_type .gt. 1) then
912  ! B direction at cell center
913  bdir=zero
914  {do ixa^d=0,1\}
915  ixb^d=(ixomin^d+ixomax^d-1)/2+ixa^d;
916  bdir(1:ndim)=bdir(1:ndim)+bunitvec(ixb^d,1:ndim)
917  {end do\}
918  if(sum(bdir(:)**2) .gt. zero) then
919  bdir(1:ndim)=bdir(1:ndim)/dsqrt(sum(bdir(:)**2))
920  end if
921  block%special_values(3:ndim+2)=bdir(1:ndim)
922  end if
923  tmp1(ixo^s)=dsqrt(sum(bunitvec(ixo^s,:)**2,dim=ndim+1))
924  where(tmp1(ixo^s)/=0.d0)
925  tmp1(ixo^s)=1.d0/tmp1(ixo^s)
926  else where
927  tmp1(ixo^s)=bigdouble
928  end where
929  ! b unit vector: magnetic field direction vector
930  do idims=1,ndim
931  bunitvec(ixo^s,idims)=bunitvec(ixo^s,idims)*tmp1(ixo^s)
932  end do
933  ! temperature length scale inversed
934  lts(ixo^s)=abs(sum(gradt(ixo^s,1:ndim)*bunitvec(ixo^s,1:ndim),dim=ndim+1))/te(ixo^s)
935  ! fraction of cells size to temperature length scale
936  if(slab_uniform) then
937  lts(ixo^s)=minval(dxlevel)*lts(ixo^s)
938  else
939  lts(ixo^s)=minval(block%ds(ixo^s,:),dim=ndim+1)*lts(ixo^s)
940  end if
941  lrlt=.false.
942  where(lts(ixo^s) > trac_delta)
943  lrlt(ixo^s)=.true.
944  end where
945  if(any(lrlt(ixo^s))) then
946  block%special_values(1)=maxval(te(ixo^s), mask=lrlt(ixo^s))
947  else
948  block%special_values(1)=zero
949  end if
950  block%special_values(2)=tmax_local
951  case(2)
952  !> iijima et al. 2021, LTRAC method
953  ltrc=1.5d0
954  ltrp=4.d0
955  ixp^l=ixo^l^ladd2;
956  do idims=1,ndim
957  ixq^l=ixp^l;
958  hxp^l=ixp^l;
959  jxp^l=ixp^l;
960  select case(idims)
961  {case(^d)
962  ixqmin^d=ixqmin^d+1
963  ixqmax^d=ixqmax^d-1
964  hxpmax^d=ixpmin^d
965  jxpmin^d=ixpmax^d
966  \}
967  end select
968  call gradient(te,ixi^l,ixq^l,idims,gradt(ixi^s,idims))
969  call gradientx(te,x,ixi^l,hxp^l,idims,gradt(ixi^s,idims),.false.)
970  call gradientq(te,x,ixi^l,jxp^l,idims,gradt(ixi^s,idims))
971  end do
972  bunitvec(ixp^s,:)=block%B0(ixp^s,:,0)
973  lts(ixp^s)=abs(sum(gradt(ixp^s,1:ndim)*bunitvec(ixp^s,1:ndim),dim=ndim+1))/te(ixp^s)
974  if(slab_uniform) then
975  lts(ixp^s)=minval(dxlevel)*lts(ixp^s)
976  else
977  lts(ixp^s)=minval(block%ds(ixp^s,:),dim=ndim+1)*lts(ixp^s)
978  end if
979  lts(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
980 
981  altr=zero
982  ixp^l=ixo^l^ladd1;
983  do idims=1,ndim
984  hxo^l=ixp^l-kr(idims,^d);
985  jxo^l=ixp^l+kr(idims,^d);
986  altr(ixp^s)=altr(ixp^s)+0.25d0*(lts(hxo^s)+two*lts(ixp^s)+lts(jxo^s))*bunitvec(ixp^s,idims)**2
987  end do
988  block%wextra(ixp^s,tcoff_)=te(ixp^s)*altr(ixp^s)**0.4d0
989  case(3,5)
990  !> do nothing here
991  case default
992  call mpistop("unknown ffhd_trac_type")
993  end select
994  }
995  end subroutine ffhd_get_tcutoff
996 
997  subroutine ffhd_get_cbounds(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
999  integer, intent(in) :: ixI^L, ixO^L, idim
1000  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S, nw)
1001  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S, nw)
1002  double precision, intent(in) :: x(ixI^S,1:ndim)
1003  double precision, intent(inout) :: cmax(ixI^S,1:number_species)
1004  double precision, intent(inout), optional :: cmin(ixI^S,1:number_species)
1005  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
1006  double precision :: wmean(ixI^S,nw)
1007  double precision, dimension(ixI^S) :: umean, dmean, csoundL, csoundR, tmp1,tmp2,tmp3
1008  integer :: ix^D
1009 
1010  select case (boundspeed)
1011  case (1)
1012  ! This implements formula (10.52) from "Riemann Solvers and Numerical
1013  ! Methods for Fluid Dynamics" by Toro.
1014  tmp1(ixo^s)=sqrt(wlp(ixo^s,rho_))
1015  tmp2(ixo^s)=sqrt(wrp(ixo^s,rho_))
1016  tmp3(ixo^s)=1.d0/(tmp1(ixo^s)+tmp2(ixo^s))
1017  umean(ixo^s)=(wlp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim)*tmp1(ixo^s)&
1018  +wrp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim)*tmp2(ixo^s))*tmp3(ixo^s)
1019  call ffhd_get_csound_prim(wlp,x,ixi^l,ixo^l,idim,csoundl)
1020  call ffhd_get_csound_prim(wrp,x,ixi^l,ixo^l,idim,csoundr)
1021  dmean(ixo^s)=(tmp1(ixo^s)*csoundl(ixo^s)+tmp2(ixo^s)*csoundr(ixo^s)) * &
1022  tmp3(ixo^s) + 0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2 * &
1023  (wrp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim)-wlp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim))**2
1024  dmean(ixo^s)=dsqrt(dmean(ixo^s))
1025  if(present(cmin)) then
1026  cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
1027  cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
1028  else
1029  cmax(ixo^s,1)=abs(umean(ixo^s))+dmean(ixo^s)
1030  end if
1031  case (2)
1032  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1033  tmp1(ixo^s)=wmean(ixo^s,mom(1))*block%B0(ixo^s,idim,idim)/wmean(ixo^s,rho_)
1034  call ffhd_get_csound(wmean,x,ixi^l,ixo^l,idim,csoundr)
1035  if(present(cmin)) then
1036  cmax(ixo^s,1)=max(tmp1(ixo^s)+csoundr(ixo^s),zero)
1037  cmin(ixo^s,1)=min(tmp1(ixo^s)-csoundr(ixo^s),zero)
1038  else
1039  cmax(ixo^s,1)=abs(tmp1(ixo^s))+csoundr(ixo^s)
1040  end if
1041  case (3)
1042  ! Miyoshi 2005 JCP 208, 315 equation (67)
1043  call ffhd_get_csound_prim(wlp,x,ixi^l,ixo^l,idim,csoundl)
1044  call ffhd_get_csound_prim(wrp,x,ixi^l,ixo^l,idim,csoundr)
1045  csoundl(ixo^s)=max(csoundl(ixo^s),csoundr(ixo^s))
1046  if(present(cmin)) then
1047  cmin(ixo^s,1)=min(wlp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim),&
1048  wrp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim))-csoundl(ixo^s)
1049  cmax(ixo^s,1)=max(wlp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim),&
1050  wrp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim))+csoundl(ixo^s)
1051  else
1052  cmax(ixo^s,1)=max(wlp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim),&
1053  wrp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim))+csoundl(ixo^s)
1054  end if
1055  end select
1056  end subroutine ffhd_get_cbounds
1057 
1058  subroutine ffhd_get_csound(w,x,ixI^L,ixO^L,idim,csound)
1060  integer, intent(in) :: ixI^L, ixO^L, idim
1061  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
1062  double precision, intent(out):: csound(ixI^S)
1063 
1064  call ffhd_get_csound2(w,x,ixi^l,ixo^l,csound)
1065  csound(ixo^s) = dsqrt(csound(ixo^s))*abs(block%B0(ixo^s,idim,idim))
1066  end subroutine ffhd_get_csound
1067 
1068  !> Calculate fast magnetosonic wave speed
1069  subroutine ffhd_get_csound_prim(w,x,ixI^L,ixO^L,idim,csound)
1071 
1072  integer, intent(in) :: ixI^L, ixO^L, idim
1073  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
1074  double precision, intent(out):: csound(ixI^S)
1075 
1076  if(ffhd_energy) then
1077  csound(ixo^s)=ffhd_gamma*w(ixo^s,e_)/w(ixo^s,rho_)
1078  else
1079  csound(ixo^s)=ffhd_gamma*ffhd_adiab*w(ixo^s,rho_)**gamma_1
1080  end if
1081  csound(ixo^s) = dsqrt(csound(ixo^s))
1082  end subroutine ffhd_get_csound_prim
1083 
1084  subroutine ffhd_get_pthermal_iso(w,x,ixI^L,ixO^L,pth)
1086 
1087  integer, intent(in) :: ixI^L, ixO^L
1088  double precision, intent(in) :: w(ixI^S,nw)
1089  double precision, intent(in) :: x(ixI^S,1:ndim)
1090  double precision, intent(out):: pth(ixI^S)
1091 
1092  call ffhd_get_rho(w,x,ixi^l,ixo^l,pth)
1093  pth(ixo^s)=ffhd_adiab*pth(ixo^s)**ffhd_gamma
1094  end subroutine ffhd_get_pthermal_iso
1095 
1096  subroutine ffhd_get_pthermal_origin(w,x,ixI^L,ixO^L,pth)
1099  integer, intent(in) :: ixI^L, ixO^L
1100  double precision, intent(in) :: w(ixI^S,nw)
1101  double precision, intent(in) :: x(ixI^S,1:ndim)
1102  double precision, intent(out):: pth(ixI^S)
1103  integer :: iw, ix^D
1104 
1105  pth(ixo^s)=gamma_1*(w(ixo^s,e_)-ffhd_kin_en(w,ixi^l,ixo^l))
1106  if (fix_small_values) then
1107  {do ix^db= ixo^lim^db\}
1108  if(pth(ix^d)<small_pressure) then
1109  pth(ix^d)=small_pressure
1110  end if
1111  {end do^D&\}
1112  elseif(check_small_values) then
1113  {do ix^db= ixo^lim^db\}
1114  if(pth(ix^d)<small_pressure) then
1115  write(*,*) "Error: small value of gas pressure",pth(ix^d),&
1116  " encountered when call ffhd_get_pthermal"
1117  write(*,*) "Iteration: ", it, " Time: ", global_time
1118  write(*,*) "Location: ", x(ix^d,:)
1119  write(*,*) "Cell number: ", ix^d
1120  do iw=1,nw
1121  write(*,*) trim(cons_wnames(iw)),": ",w(ix^d,iw)
1122  end do
1123  ! use erroneous arithmetic operation to crash the run
1124  if(trace_small_values) write(*,*) sqrt(pth(ix^d)-bigdouble)
1125  write(*,*) "Saving status at the previous time step"
1126  crash=.true.
1127  end if
1128  {end do^D&\}
1129  end if
1130  end subroutine ffhd_get_pthermal_origin
1131 
1132  subroutine ffhd_get_temperature_from_te(w, x, ixI^L, ixO^L, res)
1134  integer, intent(in) :: ixI^L, ixO^L
1135  double precision, intent(in) :: w(ixI^S, 1:nw)
1136  double precision, intent(in) :: x(ixI^S, 1:ndim)
1137  double precision, intent(out):: res(ixI^S)
1138 
1139  res(ixo^s) = w(ixo^s, te_)
1140  end subroutine ffhd_get_temperature_from_te
1141 
1142  subroutine ffhd_get_temperature_from_eint(w, x, ixI^L, ixO^L, res)
1144  integer, intent(in) :: ixI^L, ixO^L
1145  double precision, intent(in) :: w(ixI^S, 1:nw)
1146  double precision, intent(in) :: x(ixI^S, 1:ndim)
1147  double precision, intent(out):: res(ixI^S)
1148  double precision :: R(ixI^S)
1149 
1150  call ffhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1151  res(ixo^s) = gamma_1 * w(ixo^s, e_)/(w(ixo^s,rho_)*r(ixo^s))
1152  end subroutine ffhd_get_temperature_from_eint
1153 
1154  subroutine ffhd_get_temperature_from_etot(w, x, ixI^L, ixO^L, res)
1156  integer, intent(in) :: ixI^L, ixO^L
1157  double precision, intent(in) :: w(ixI^S, 1:nw)
1158  double precision, intent(in) :: x(ixI^S, 1:ndim)
1159  double precision, intent(out):: res(ixI^S)
1160 
1161  double precision :: R(ixI^S)
1162 
1163  call ffhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1164  call ffhd_get_pthermal(w,x,ixi^l,ixo^l,res)
1165  res(ixo^s)=res(ixo^s)/(r(ixo^s)*w(ixo^s,rho_))
1166  end subroutine ffhd_get_temperature_from_etot
1167 
1168  subroutine ffhd_get_csound2(w,x,ixI^L,ixO^L,csound2)
1170  integer, intent(in) :: ixi^l, ixo^l
1171  double precision, intent(in) :: w(ixi^s,nw)
1172  double precision, intent(in) :: x(ixi^s,1:ndim)
1173  double precision, intent(out) :: csound2(ixi^s)
1174  double precision :: rho(ixi^s)
1175 
1176  call ffhd_get_rho(w,x,ixi^l,ixo^l,rho)
1177  if(ffhd_energy) then
1178  call ffhd_get_pthermal(w,x,ixi^l,ixo^l,csound2)
1179  csound2(ixo^s)=ffhd_gamma*csound2(ixo^s)/rho(ixo^s)
1180  else
1181  csound2(ixo^s)=ffhd_gamma*ffhd_adiab*rho(ixo^s)**gamma_1
1182  end if
1183  end subroutine ffhd_get_csound2
1184 
1185  subroutine ffhd_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
1187  use mod_geometry
1188  integer, intent(in) :: ixI^L, ixO^L, idim
1189  ! conservative w
1190  double precision, intent(in) :: wC(ixI^S,nw)
1191  ! primitive w
1192  double precision, intent(in) :: w(ixI^S,nw)
1193  double precision, intent(in) :: x(ixI^S,1:ndim)
1194  double precision,intent(out) :: f(ixI^S,nwflux)
1195  double precision :: ptotal(ixO^S)
1196  double precision :: tmp(ixI^S)
1197  integer :: idirmin, iw, idir, jdir, kdir
1198  double precision, dimension(ixI^S) :: Te,tau,sigT
1199 
1200  f(ixo^s,rho_)=w(ixo^s,mom(1))*w(ixo^s,rho_)*block%B0(ixo^s,idim,idim)
1201 
1202  if(ffhd_energy) then
1203  ptotal(ixo^s)=w(ixo^s,p_)
1204  else
1205  ptotal(ixo^s)=ffhd_adiab*w(ixo^s,rho_)**ffhd_gamma
1206  end if
1207 
1208  ! Get flux of momentum
1209  f(ixo^s,mom(1))=(wc(ixo^s,mom(1))*w(ixo^s,mom(1))+ptotal(ixo^s))*block%B0(ixo^s,idim,idim)
1210 
1211  ! Get flux of energy
1212  if(ffhd_energy) then
1213  f(ixo^s,e_)=w(ixo^s,mom(1))*(wc(ixo^s,e_)+ptotal(ixo^s))*block%B0(ixo^s,idim,idim)
1215  f(ixo^s,e_)=f(ixo^s,e_)+w(ixo^s,q_)*block%B0(ixo^s,idim,idim)
1216  f(ixo^s,q_)=zero
1217  end if
1218  end if
1219  end subroutine ffhd_get_flux
1220 
1221  subroutine ffhd_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
1225  use mod_gravity, only: gravity_add_source
1226  integer, intent(in) :: ixI^L, ixO^L
1227  double precision, intent(in) :: qdt,dtfactor
1228  double precision, intent(in) :: wCT(ixI^S,1:nw),wCTprim(ixI^S,1:nw), x(ixI^S,1:ndim)
1229  double precision, intent(inout) :: w(ixI^S,1:nw)
1230  logical, intent(in) :: qsourcesplit
1231  logical, intent(inout) :: active
1232 
1233  if (.not. qsourcesplit) then
1234  active = .true.
1235  call add_punitb(qdt,ixi^l,ixo^l,wct,w,x,wctprim)
1237  call add_hypertc_source(qdt,ixi^l,ixo^l,wct,w,x,wctprim)
1238  end if
1239  end if
1240 
1241  if(ffhd_radiative_cooling) then
1242  call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,wctprim,&
1243  w,x,qsourcesplit,active, rc_fl)
1244  end if
1245 
1246  if(ffhd_viscosity) then
1247  call viscosity_add_source(qdt,ixi^l,ixo^l,wct,&
1248  w,x,ffhd_energy,qsourcesplit,active)
1249  end if
1250 
1251  if(ffhd_gravity) then
1252  call gravity_add_source(qdt,ixi^l,ixo^l,wct,wctprim,&
1253  w,x,ffhd_energy,.false.,qsourcesplit,active)
1254  end if
1255 
1256  ! update temperature from new pressure, density, and old ionization degree
1257  if(ffhd_partial_ionization) then
1258  if(.not.qsourcesplit) then
1259  active = .true.
1260  call ffhd_update_temperature(ixi^l,ixo^l,wct,w,x)
1261  end if
1262  end if
1263  end subroutine ffhd_add_source
1264 
1265  subroutine add_punitb(qdt,ixI^L,ixO^L,wCT,w,x,wCTprim)
1267  use mod_geometry
1268  integer, intent(in) :: ixI^L,ixO^L
1269  double precision, intent(in) :: qdt
1270  double precision, intent(in) :: wCT(ixI^S,1:nw),x(ixI^S,1:ndim)
1271  double precision, intent(in) :: wCTprim(ixI^S,1:nw)
1272  double precision, intent(inout) :: w(ixI^S,1:nw)
1273 
1274  integer :: idims,hxO^L
1275  double precision :: divb(ixI^S)
1276 
1277  divb=zero
1278  if(slab_uniform) then
1279  do idims=1,ndim
1280  hxo^l=ixo^l-kr(idims,^d);
1281  divb(ixo^s)=divb(ixo^s)+(block%B0(ixo^s,idims,idims)-block%B0(hxo^s,idims,idims))/dxlevel(idims)
1282  end do
1283  else
1284  call divvector(block%B0(ixi^s,1:ndir,0),ixi^l,ixo^l,divb)
1285  end if
1286  w(ixo^s,mom(1))=w(ixo^s,mom(1))+qdt*wctprim(ixo^s,p_)*divb(ixo^s)
1287  end subroutine add_punitb
1288 
1289  subroutine ffhd_get_rho(w,x,ixI^L,ixO^L,rho)
1291  integer, intent(in) :: ixi^l, ixo^l
1292  double precision, intent(in) :: w(ixi^s,1:nw),x(ixi^s,1:ndim)
1293  double precision, intent(out) :: rho(ixi^s)
1294 
1295  rho(ixo^s) = w(ixo^s,rho_)
1296  end subroutine ffhd_get_rho
1297 
1298  subroutine ffhd_handle_small_ei(w, x, ixI^L, ixO^L, ie, subname)
1300  use mod_small_values
1301  integer, intent(in) :: ixI^L,ixO^L, ie
1302  double precision, intent(inout) :: w(ixI^S,1:nw)
1303  double precision, intent(in) :: x(ixI^S,1:ndim)
1304  character(len=*), intent(in) :: subname
1305  integer :: idir
1306  logical :: flag(ixI^S,1:nw)
1307  double precision :: rho(ixI^S)
1308 
1309  flag=.false.
1310  where(w(ixo^s,ie)<small_e) flag(ixo^s,ie)=.true.
1311  if(any(flag(ixo^s,ie))) then
1312  select case (small_values_method)
1313  case ("replace")
1314  where(flag(ixo^s,ie)) w(ixo^s,ie)=small_e
1315  case ("average")
1316  call small_values_average(ixi^l, ixo^l, w, x, flag, ie)
1317  case default
1318  w(ixo^s,e_)=w(ixo^s,e_)*gamma_1
1319  call ffhd_get_rho(w,x,ixi^l,ixo^l,rho)
1320  w(ixo^s,mom(1)) = w(ixo^s,mom(1))/rho(ixo^s)
1321  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
1322  end select
1323  end if
1324  end subroutine ffhd_handle_small_ei
1325 
1326  subroutine ffhd_update_temperature(ixI^L,ixO^L,wCT,w,x)
1329  integer, intent(in) :: ixI^L, ixO^L
1330  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
1331  double precision, intent(inout) :: w(ixI^S,1:nw)
1332  double precision :: iz_H(ixO^S),iz_He(ixO^S), pth(ixI^S)
1333 
1334  call ionization_degree_from_temperature(ixi^l,ixo^l,wct(ixi^s,te_),iz_h,iz_he)
1335  call ffhd_get_pthermal(w,x,ixi^l,ixo^l,pth)
1336  w(ixo^s,te_)=(2.d0+3.d0*he_abundance)*pth(ixo^s)/(w(ixo^s,rho_)*(1.d0+iz_h(ixo^s)+&
1337  he_abundance*(iz_he(ixo^s)*(iz_he(ixo^s)+1.d0)+1.d0)))
1338  end subroutine ffhd_update_temperature
1339 
1340  subroutine ffhd_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
1342  use mod_usr_methods
1344  use mod_viscosity, only: viscosity_get_dt
1345  use mod_gravity, only: gravity_get_dt
1346  integer, intent(in) :: ixI^L, ixO^L
1347  double precision, intent(inout) :: dtnew
1348  double precision, intent(in) :: dx^D
1349  double precision, intent(in) :: w(ixI^S,1:nw)
1350  double precision, intent(in) :: x(ixI^S,1:ndim)
1351  integer :: idirmin,idim
1352  double precision :: dxarr(ndim)
1353  double precision :: current(ixI^S,7-2*ndir:3),eta(ixI^S)
1354 
1355  dtnew = bigdouble
1356 
1357  if(ffhd_radiative_cooling) then
1358  call cooling_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x,rc_fl)
1359  end if
1360 
1361  if(ffhd_viscosity) then
1362  call viscosity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1363  end if
1364 
1365  if(ffhd_gravity) then
1366  call gravity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1367  end if
1368  end subroutine ffhd_get_dt
1369 
1370 ! subroutine ffhd_add_source_geom(qdt,dtfactor,ixI^L,ixO^L,wCT,w,x)
1371 ! use mod_global_parameters
1372 ! use mod_geometry
1373 !
1374 ! integer, intent(in) :: ixI^L, ixO^L
1375 ! double precision, intent(in) :: qdt, dtfactor,x(ixI^S,1:ndim)
1376 ! double precision, intent(inout) :: wCT(ixI^S,1:nw), w(ixI^S,1:nw)
1377 !
1378 ! integer :: iw,idir, h1x^L{^NOONED, h2x^L}
1379 ! double precision :: tmp(ixI^S),tmp1(ixI^S),tmp2(ixI^S),invrho(ixO^S),invr(ixO^S)
1380 !
1381 ! integer :: mr_,mphi_ ! Polar var. names
1382 ! integer :: br_,bphi_
1383 !
1384 ! mr_=mom(1); mphi_=mom(1)-1+phi_ ! Polar var. names
1385 ! br_=mag(1); bphi_=mag(1)-1+phi_
1386 !
1387 ! ! 1/rho
1388 ! invrho(ixO^S)=1.d0/wCT(ixO^S,rho_)
1389 ! ! include dt in invr, invr is always used with qdt
1390 ! if(local_timestep) then
1391 ! invr(ixO^S) = block%dt(ixO^S) * dtfactor/x(ixO^S,1)
1392 ! else
1393 ! invr(ixO^S) = qdt/x(ixO^S,1)
1394 ! end if
1395 !
1396 !
1397 ! select case (coordinate)
1398 ! case (cylindrical)
1399 ! call ffhd_get_p_total(wCT,x,ixI^L,ixO^L,tmp)
1400 ! if(phi_>0) then
1401 ! w(ixO^S,mr_)=w(ixO^S,mr_)+invr(ixO^S)*(tmp(ixO^S)-&
1402 ! wCT(ixO^S,bphi_)**2+wCT(ixO^S,mphi_)**2*invrho(ixO^S))
1403 ! w(ixO^S,mphi_)=w(ixO^S,mphi_)+invr(ixO^S)*(&
1404 ! -wCT(ixO^S,mphi_)*wCT(ixO^S,mr_)*invrho(ixO^S) &
1405 ! +wCT(ixO^S,bphi_)*wCT(ixO^S,br_))
1406 ! if(.not.stagger_grid) then
1407 ! w(ixO^S,bphi_)=w(ixO^S,bphi_)+invr(ixO^S)*&
1408 ! (wCT(ixO^S,bphi_)*wCT(ixO^S,mr_) &
1409 ! -wCT(ixO^S,br_)*wCT(ixO^S,mphi_)) &
1410 ! *invrho(ixO^S)
1411 ! end if
1412 ! else
1413 ! w(ixO^S,mr_)=w(ixO^S,mr_)+invr(ixO^S)*tmp(ixO^S)
1414 ! end if
1415 ! if(ffhd_glm) w(ixO^S,br_)=w(ixO^S,br_)+wCT(ixO^S,psi_)*invr(ixO^S)
1416 ! case (spherical)
1417 ! h1x^L=ixO^L-kr(1,^D); {^NOONED h2x^L=ixO^L-kr(2,^D);}
1418 ! call ffhd_get_p_total(wCT,x,ixI^L,ixO^L,tmp1)
1419 ! ! m1
1420 ! tmp(ixO^S)=tmp1(ixO^S)*x(ixO^S,1) &
1421 ! *(block%surfaceC(ixO^S,1)-block%surfaceC(h1x^S,1))/block%dvolume(ixO^S)
1422 ! do idir=2,ndir
1423 ! tmp(ixO^S)=tmp(ixO^S)+wCT(ixO^S,mom(idir))**2*invrho(ixO^S)-wCT(ixO^S,mag(idir))**2
1424 ! end do
1425 ! w(ixO^S,mom(1))=w(ixO^S,mom(1))+tmp(ixO^S)*invr(ixO^S)
1426 ! ! b1
1427 ! if(ffhd_glm) then
1428 ! w(ixO^S,mag(1))=w(ixO^S,mag(1))+invr(ixO^S)*2.0d0*wCT(ixO^S,psi_)
1429 ! end if
1430 !
1431 ! {^NOONED
1432 ! ! m2
1433 ! ! This will make hydrostatic p=const an exact solution
1434 ! if(local_timestep) then
1435 ! tmp(ixO^S) = block%dt(ixO^S) * tmp1(ixO^S)
1436 ! else
1437 ! tmp(ixO^S) = qdt * tmp1(ixO^S)
1438 ! end if
1439 ! w(ixO^S,mom(2))=w(ixO^S,mom(2))+tmp(ixO^S) &
1440 ! *(block%surfaceC(ixO^S,2)-block%surfaceC(h2x^S,2)) &
1441 ! /block%dvolume(ixO^S)
1442 ! tmp(ixO^S)=-(wCT(ixO^S,mom(1))*wCT(ixO^S,mom(2))*invrho(ixO^S) &
1443 ! -wCT(ixO^S,mag(1))*wCT(ixO^S,mag(2)))
1444 ! if(ndir==3) then
1445 ! tmp(ixO^S)=tmp(ixO^S)+(wCT(ixO^S,mom(3))**2*invrho(ixO^S) &
1446 ! -wCT(ixO^S,mag(3))**2)*dcos(x(ixO^S,2))/dsin(x(ixO^S,2))
1447 ! end if
1448 ! w(ixO^S,mom(2))=w(ixO^S,mom(2))+tmp(ixO^S)*invr(ixO^S)
1449 ! ! b2
1450 ! if(.not.stagger_grid) then
1451 ! tmp(ixO^S)=(wCT(ixO^S,mom(1))*wCT(ixO^S,mag(2)) &
1452 ! -wCT(ixO^S,mom(2))*wCT(ixO^S,mag(1)))*invrho(ixO^S)
1453 ! if(ffhd_glm) then
1454 ! tmp(ixO^S)=tmp(ixO^S) &
1455 ! + dcos(x(ixO^S,2))/dsin(x(ixO^S,2))*wCT(ixO^S,psi_)
1456 ! end if
1457 ! w(ixO^S,mag(2))=w(ixO^S,mag(2))+tmp(ixO^S)*invr(ixO^S)
1458 ! end if
1459 ! }
1460 !
1461 ! if(ndir==3) then
1462 ! ! m3
1463 ! tmp(ixO^S)=-(wCT(ixO^S,mom(3))*wCT(ixO^S,mom(1))*invrho(ixO^S) &
1464 ! -wCT(ixO^S,mag(3))*wCT(ixO^S,mag(1))) {^NOONED &
1465 ! -(wCT(ixO^S,mom(2))*wCT(ixO^S,mom(3))*invrho(ixO^S) &
1466 ! -wCT(ixO^S,mag(2))*wCT(ixO^S,mag(3))) &
1467 ! *dcos(x(ixO^S,2))/dsin(x(ixO^S,2)) }
1468 ! w(ixO^S,mom(3))=w(ixO^S,mom(3))+tmp(ixO^S)*invr(ixO^S)
1469 ! ! b3
1470 ! if(.not.stagger_grid) then
1471 ! tmp(ixO^S)=(wCT(ixO^S,mom(1))*wCT(ixO^S,mag(3)) &
1472 ! -wCT(ixO^S,mom(3))*wCT(ixO^S,mag(1)))*invrho(ixO^S) {^NOONED &
1473 ! -(wCT(ixO^S,mom(3))*wCT(ixO^S,mag(2)) &
1474 ! -wCT(ixO^S,mom(2))*wCT(ixO^S,mag(3)))*dcos(x(ixO^S,2)) &
1475 ! /(wCT(ixO^S,rho_)*dsin(x(ixO^S,2))) }
1476 ! w(ixO^S,mag(3))=w(ixO^S,mag(3))+tmp(ixO^S)*invr(ixO^S)
1477 ! end if
1478 ! end if
1479 ! end select
1480 ! end subroutine ffhd_add_source_geom
1481 
1482  function ffhd_kin_en_origin(w, ixI^L, ixO^L, inv_rho) result(ke)
1483  use mod_global_parameters, only: nw, ndim,block
1484  integer, intent(in) :: ixi^l, ixo^l
1485  double precision, intent(in) :: w(ixi^s, nw)
1486  double precision :: ke(ixo^s)
1487  double precision, intent(in), optional :: inv_rho(ixo^s)
1488 
1489  if(present(inv_rho)) then
1490  ke(ixo^s)=0.5d0*w(ixo^s,mom(1))**2*inv_rho(ixo^s)
1491  else
1492  ke(ixo^s)=0.5d0*w(ixo^s,mom(1))**2/w(ixo^s,rho_)
1493  end if
1494  end function ffhd_kin_en_origin
1495 
1496  subroutine rfactor_from_temperature_ionization(w,x,ixI^L,ixO^L,Rfactor)
1499  integer, intent(in) :: ixI^L, ixO^L
1500  double precision, intent(in) :: w(ixI^S,1:nw)
1501  double precision, intent(in) :: x(ixI^S,1:ndim)
1502  double precision, intent(out):: Rfactor(ixI^S)
1503  double precision :: iz_H(ixO^S),iz_He(ixO^S)
1504 
1505  call ionization_degree_from_temperature(ixi^l,ixo^l,w(ixi^s,te_),iz_h,iz_he)
1506  rfactor(ixo^s)=(1.d0+iz_h(ixo^s)+0.1d0*(1.d0+iz_he(ixo^s)*(1.d0+iz_he(ixo^s))))/(2.d0+3.d0*he_abundance)
1508 
1509  subroutine rfactor_from_constant_ionization(w,x,ixI^L,ixO^L,Rfactor)
1511  integer, intent(in) :: ixI^L, ixO^L
1512  double precision, intent(in) :: w(ixI^S,1:nw)
1513  double precision, intent(in) :: x(ixI^S,1:ndim)
1514  double precision, intent(out):: Rfactor(ixI^S)
1515 
1516  rfactor(ixo^s)=rr
1517  end subroutine rfactor_from_constant_ionization
1518 
1519  subroutine get_tau(ixI^L,ixO^L,w,Te,tau,sigT5)
1521  integer, intent(in) :: ixI^L, ixO^L
1522  double precision, dimension(ixI^S,1:nw), intent(in) :: w
1523  double precision, dimension(ixI^S), intent(in) :: Te
1524  double precision, dimension(ixI^S), intent(out) :: tau,sigT5
1525  integer :: ix^D
1526  double precision :: dxmin,taumin
1527  double precision, dimension(ixI^S) :: sigT7,eint
1528 
1529  taumin=4.d0
1530  !> w supposed to be wCTprim here
1531  if(ffhd_trac) then
1532  where(te(ixo^s) .lt. block%wextra(ixo^s,tcoff_))
1533  sigt5(ixo^s)=hypertc_kappa*sqrt(block%wextra(ixo^s,tcoff_)**5)
1534  sigt7(ixo^s)=sigt5(ixo^s)*block%wextra(ixo^s,tcoff_)
1535  else where
1536  sigt5(ixo^s)=hypertc_kappa*sqrt(te(ixo^s)**5)
1537  sigt7(ixo^s)=sigt5(ixo^s)*te(ixo^s)
1538  end where
1539  else
1540  sigt5(ixo^s)=hypertc_kappa*sqrt(te(ixo^s)**5)
1541  sigt7(ixo^s)=sigt5(ixo^s)*te(ixo^s)
1542  end if
1543  eint(ixo^s)=w(ixo^s,p_)/(ffhd_gamma-one)
1544  tau(ixo^s)=max(taumin*dt,sigt7(ixo^s)/eint(ixo^s)/cs2max_global)
1545  end subroutine get_tau
1546 
1547  subroutine add_hypertc_source(qdt,ixI^L,ixO^L,wCT,w,x,wCTprim)
1549  integer, intent(in) :: ixI^L,ixO^L
1550  double precision, intent(in) :: qdt
1551  double precision, dimension(ixI^S,1:ndim), intent(in) :: x
1552  double precision, dimension(ixI^S,1:nw), intent(in) :: wCT,wCTprim
1553  double precision, dimension(ixI^S,1:nw), intent(inout) :: w
1554  integer :: idims
1555  integer :: hxC^L,hxO^L,ixC^L,jxC^L,jxO^L,kxC^L
1556  double precision :: invdx
1557  double precision, dimension(ixI^S) :: Te,tau,sigT,htc_qsrc,Tface
1558  double precision, dimension(ixI^S) :: htc_esrc
1559 
1560  te(ixi^s)=wctprim(ixi^s,p_)/wct(ixi^s,rho_)
1561  call get_tau(ixi^l,ixo^l,wctprim,te,tau,sigt)
1562  htc_qsrc=zero
1563  do idims=1,ndim
1564  invdx=1.d0/dxlevel(idims)
1565  ixc^l=ixo^l;
1566  ixcmin^d=ixomin^d-kr(idims,^d);ixcmax^d=ixomax^d;
1567  jxc^l=ixc^l+kr(idims,^d);
1568  kxc^l=jxc^l+kr(idims,^d);
1569  hxc^l=ixc^l-kr(idims,^d);
1570  hxo^l=ixo^l-kr(idims,^d);
1571  tface(ixc^s)=(7.d0*(te(ixc^s)+te(jxc^s))-(te(hxc^s)+te(kxc^s)))/12.d0
1572  htc_qsrc(ixo^s)=htc_qsrc(ixo^s)+sigt(ixo^s)*block%B0(ixo^s,idims,0)*(tface(ixo^s)-tface(hxo^s))*invdx
1573  end do
1574  htc_qsrc(ixo^s)=(htc_qsrc(ixo^s)+wct(ixo^s,q_))/tau(ixo^s)
1575  w(ixo^s,q_)=w(ixo^s,q_)-qdt*htc_qsrc(ixo^s)
1576  end subroutine add_hypertc_source
1577 end module mod_ffhd_phys
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: mod_comm_lib.t:208
Module for physical and numeric constants.
Definition: mod_constants.t:2
double precision, parameter bigdouble
A very large real number.
Definition: mod_constants.t:11
subroutine add_convert_method(phys_convert_vars, nwc, dataset_names, file_suffix)
Definition: mod_convert.t:64
Frozen-field hydrodynamics module.
Definition: mod_ffhd_phys.t:2
integer, public, protected te_
Indices of temperature.
Definition: mod_ffhd_phys.t:67
integer, public, protected ffhd_trac_type
Which TRAC method is used.
Definition: mod_ffhd_phys.t:43
subroutine ffhd_get_cs2max(w, x, ixIL, ixOL, cs2max)
double precision, public hypertc_kappa
The thermal conductivity kappa in hyperbolic thermal conduction.
Definition: mod_ffhd_phys.t:84
integer, public, protected e_
Index of the energy density (-1 if not present)
Definition: mod_ffhd_phys.t:61
subroutine ffhd_handle_small_values_origin(primitive, w, x, ixIL, ixOL, subname)
double precision, public ffhd_gamma
The adiabatic index.
Definition: mod_ffhd_phys.t:75
double precision function ffhd_get_tc_dt_ffhd(w, ixIL, ixOL, dxD, x)
logical, public, protected eq_state_units
subroutine ffhd_update_temperature(ixIL, ixOL, wCT, w, x)
subroutine ffhd_get_temperature_from_eint(w, x, ixIL, ixOL, res)
subroutine ffhd_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
double precision, public ffhd_adiab
The adiabatic constant.
Definition: mod_ffhd_phys.t:78
procedure(sub_get_pthermal), pointer, public ffhd_get_temperature
subroutine ffhd_get_temperature_from_etot(w, x, ixIL, ixOL, res)
subroutine rfactor_from_constant_ionization(w, x, ixIL, ixOL, Rfactor)
logical, public, protected ffhd_hyperbolic_thermal_conduction
Whether hyperbolic type thermal conduction is used.
Definition: mod_ffhd_phys.t:22
subroutine, public ffhd_get_v_idim(w, x, ixIL, ixOL, idim, v)
type(rc_fluid), allocatable, public rc_fl
type of fluid for radiative cooling
Definition: mod_ffhd_phys.t:31
subroutine ffhd_get_tcutoff(ixIL, ixOL, w, x, Tco_local, Tmax_local)
subroutine tc_params_read_ffhd(fl)
integer, public, protected rho_
Index of the density (in the w array)
Definition: mod_ffhd_phys.t:55
integer, public, protected tcoff_
Index of the cutoff temperature for the TRAC method.
Definition: mod_ffhd_phys.t:70
procedure(sub_get_pthermal), pointer, public ffhd_get_pthermal
subroutine ffhd_check_params
logical, public, protected ffhd_partial_ionization
Whether plasma is partially ionized.
Definition: mod_ffhd_phys.t:52
procedure(sub_convert), pointer, public ffhd_to_conserved
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
Definition: mod_ffhd_phys.t:58
subroutine ffhd_te_images
subroutine ffhd_to_conserved_origin(ixIL, ixOL, w, x)
double precision, public, protected h_ion_fr
Ionization fraction of H H_ion_fr = H+/(H+ + H)
Definition: mod_ffhd_phys.t:90
procedure(fun_kin_en), pointer, public ffhd_kin_en
subroutine, public ffhd_phys_init()
subroutine ffhd_add_source(qdt, dtfactor, ixIL, ixOL, wCT, wCTprim, w, x, qsourcesplit, active)
procedure(sub_get_v), pointer, public ffhd_get_v
subroutine ffhd_get_a2max(w, x, ixIL, ixOL, a2max)
subroutine ffhd_write_info(fh)
Write this module's parameters to a snapsoht.
subroutine ffhd_to_primitive_origin(ixIL, ixOL, w, x)
subroutine ffhd_get_cbounds(wLC, wRC, wLp, wRp, x, ixIL, ixOL, idim, Hspeed, cmax, cmin)
logical, public, protected ffhd_energy
Whether an energy equation is used.
Definition: mod_ffhd_phys.t:17
double precision, public, protected rr
type(tc_fluid), allocatable, public tc_fl
type of fluid for thermal conduction
Definition: mod_ffhd_phys.t:24
subroutine ffhd_get_flux(wC, w, x, ixIL, ixOL, idim, f)
subroutine ffhd_physical_units()
subroutine, public ffhd_e_to_ei(ixIL, ixOL, w, x)
subroutine add_punitb(qdt, ixIL, ixOL, wCT, w, x, wCTprim)
subroutine ffhd_get_csound(w, x, ixIL, ixOL, idim, csound)
subroutine rfactor_from_temperature_ionization(w, x, ixIL, ixOL, Rfactor)
type(te_fluid), allocatable, public te_fl_ffhd
type of fluid for thermal emission synthesis
Definition: mod_ffhd_phys.t:26
double precision, public, protected he_abundance
Helium abundance over Hydrogen.
Definition: mod_ffhd_phys.t:87
subroutine ffhd_get_v_origin(w, x, ixIL, ixOL, v)
logical, public, protected ffhd_viscosity
Whether viscosity is added.
Definition: mod_ffhd_phys.t:34
logical, public, protected ffhd_radiative_cooling
Whether radiative cooling is added.
Definition: mod_ffhd_phys.t:29
subroutine ffhd_get_temperature_from_te(w, x, ixIL, ixOL, res)
subroutine rc_params_read(fl)
subroutine ffhd_handle_small_ei(w, x, ixIL, ixOL, ie, subname)
integer, public, protected q_
Definition: mod_ffhd_phys.t:72
procedure(sub_convert), pointer, public ffhd_to_primitive
integer, public, protected tweight_
Definition: mod_ffhd_phys.t:71
subroutine ffhd_get_cmax_origin(w, x, ixIL, ixOL, idim, cmax)
double precision, public, protected he_ion_fr2
Ratio of number He2+ / number He+ + He2+ He_ion_fr2 = He2+/(He2+ + He+)
Definition: mod_ffhd_phys.t:96
logical, public, protected ffhd_trac
Whether TRAC method is used.
Definition: mod_ffhd_phys.t:40
subroutine get_tau(ixIL, ixOL, w, Te, tau, sigT5)
subroutine ffhd_check_w_origin(primitive, ixIL, ixOL, w, flag)
subroutine ffhd_get_pthermal_origin(w, x, ixIL, ixOL, pth)
subroutine, public ffhd_ei_to_e(ixIL, ixOL, w, x)
subroutine ffhd_tc_handle_small_e(w, x, ixIL, ixOL, step)
logical, public, protected ffhd_thermal_conduction
Whether thermal conduction is used.
Definition: mod_ffhd_phys.t:20
logical, public, protected ffhd_gravity
Whether gravity is added.
Definition: mod_ffhd_phys.t:37
subroutine add_hypertc_source(qdt, ixIL, ixOL, wCT, w, x, wCTprim)
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
Definition: mod_ffhd_phys.t:64
subroutine ffhd_get_pthermal_iso(w, x, ixIL, ixOL, pth)
subroutine ffhd_get_csound_prim(w, x, ixIL, ixOL, idim, csound)
Calculate fast magnetosonic wave speed.
double precision function, dimension(ixo^s) ffhd_kin_en_origin(w, ixIL, ixOL, inv_rho)
double precision, public, protected ffhd_trac_mask
Height of the mask used in the TRAC method.
Definition: mod_ffhd_phys.t:46
double precision, public, protected he_ion_fr
Ionization fraction of He He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
Definition: mod_ffhd_phys.t:93
subroutine, public ffhd_get_csound2(w, x, ixIL, ixOL, csound2)
subroutine, public ffhd_get_rho(w, x, ixIL, ixOL, rho)
integer, public, protected ffhd_trac_finegrid
Distance between two adjacent traced magnetic field lines (in finest cell size)
Definition: mod_ffhd_phys.t:49
subroutine ffhd_sts_set_source_tc_ffhd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux)
Module for flux conservation near refinement boundaries.
Module with geometry-related routines (e.g., divergence, curl)
Definition: mod_geometry.t:2
subroutine gradient(q, ixIL, ixOL, idir, gradq)
Calculate gradient of a scalar q within ixL in direction idir.
Definition: mod_geometry.t:321
subroutine divvector(qvec, ixIL, ixOL, divq, fourthorder, sixthorder)
Calculate divergence of a vector qvec within ixL.
Definition: mod_geometry.t:516
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.
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
integer mype
The rank of the current MPI task.
integer, dimension(:), allocatable, parameter d
integer ndir
Number of spatial dimensions (components) for vector variables.
double precision unit_velocity
Physical scaling factor for velocity.
logical b0field
split magnetic field as background B0 field
logical need_global_cs2max
global value for csound speed
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
logical phys_trac
Use TRAC (Johnston 2019 ApJL, 873, L22) for MHD or 1D HD.
double precision cs2max_global
global largest cs2 for hyperbolic thermal conduction
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, parameter unitconvert
double precision, dimension(ndim) dxlevel
Module for including gravity in (magneto)hydrodynamics simulations.
Definition: mod_gravity.t:2
subroutine gravity_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
Definition: mod_gravity.t:86
subroutine gravity_add_source(qdt, ixIL, ixOL, wCT, wCTprim, w, x, energy, rhov, qsourcesplit, active)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO
Definition: mod_gravity.t:43
subroutine gravity_init()
Initialize the module.
Definition: mod_gravity.t:26
module ionization degree - get ionization degree for given temperature
subroutine ionization_degree_from_temperature(ixIL, ixOL, Te, iz_H, iz_He)
Module containing all the particle routines.
Definition: mod_particles.t:2
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition: mod_physics.t:4
module radiative cooling – add optically thin radiative cooling for HD and MHD
subroutine radiative_cooling_init(fl, read_params)
subroutine cooling_get_dt(w, ixIL, ixOL, dtnew, dxD, x, fl)
subroutine radiative_cooling_init_params(phys_gamma, He_abund)
Radiative cooling initialization.
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.
logical, public trace_small_values
trace small values in the source file using traceback flag of compiler
subroutine, public small_values_average(ixIL, ixOL, w, x, w_flag, windex)
logical, dimension(:), allocatable, public small_values_fix_iw
Whether to apply small value fixes to certain variables.
subroutine, public small_values_error(wprim, x, ixIL, ixOL, w_flag, subname)
character(len=20), public small_values_method
How to handle small values.
Generic supertimestepping method 1) in amrvac.par in sts_list set the following parameters which have...
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 sts_set_source_tc_ffhd(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 tc_init_params(phys_gamma)
double precision function, public get_tc_dt_ffhd(w, ixIL, ixOL, dxD, x, fl)
Get the explicut timestep for the TC (ffhd implementation)
subroutine, public tc_get_ffhd_params(fl, read_ffhd_params)
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
The module add viscous source terms and check time step.
Definition: mod_viscosity.t:10
subroutine viscosity_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
subroutine viscosity_add_source(qdt, ixIL, ixOL, wCT, w, x, energy, qsourcesplit, active)
Definition: mod_viscosity.t:89
subroutine viscosity_init(phys_wider_stencil, phys_req_diagonal)
Initialize the module.
Definition: mod_viscosity.t:58