MPI-AMRVAC  3.1
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
mod_hd_phys.t
Go to the documentation of this file.
1 !> Hydrodynamics physics module
2 module mod_hd_phys
6  use mod_physics
7  use mod_comm_lib, only: mpistop
8  implicit none
9  private
10 
11  !> Whether an energy equation is used
12  logical, public, protected :: hd_energy = .true.
13 
14  !> Whether thermal conduction is added
15  logical, public, protected :: hd_thermal_conduction = .false.
16  type(tc_fluid), allocatable, public :: tc_fl
17  type(te_fluid), allocatable, public :: te_fl_hd
18 
19  !> Whether radiative cooling is added
20  logical, public, protected :: hd_radiative_cooling = .false.
21  type(rc_fluid), allocatable, public :: rc_fl
22 
23  !> Whether dust is added
24  logical, public, protected :: hd_dust = .false.
25 
26  !> Whether viscosity is added
27  logical, public, protected :: hd_viscosity = .false.
28 
29  !> Whether gravity is added
30  logical, public, protected :: hd_gravity = .false.
31 
32  !> Whether particles module is added
33  logical, public, protected :: hd_particles = .false.
34 
35  !> Whether rotating frame is activated
36  logical, public, protected :: hd_rotating_frame = .false.
37 
38  !> Whether CAK radiation line force is activated
39  logical, public, protected :: hd_cak_force = .false.
40 
41  !> Number of tracer species
42  integer, public, protected :: hd_n_tracer = 0
43 
44  !> Whether plasma is partially ionized
45  logical, public, protected :: hd_partial_ionization = .false.
46 
47  !> Index of the density (in the w array)
48  integer, public, protected :: rho_
49 
50  !> Indices of the momentum density
51  integer, allocatable, public, protected :: mom(:)
52 
53  !> Indices of the tracers
54  integer, allocatable, public, protected :: tracer(:)
55 
56  !> Index of the energy density (-1 if not present)
57  integer, public, protected :: e_
58 
59  !> Index of the gas pressure (-1 if not present) should equal e_
60  integer, public, protected :: p_
61 
62  !> Indices of temperature
63  integer, public, protected :: te_
64 
65  !> Index of the cutoff temperature for the TRAC method
66  integer, public, protected :: tcoff_
67 
68  !> The adiabatic index
69  double precision, public :: hd_gamma = 5.d0/3.0d0
70 
71  !> The adiabatic constant
72  double precision, public :: hd_adiab = 1.0d0
73 
74  !> The small_est allowed energy
75  double precision, protected :: small_e
76 
77  !> Whether TRAC method is used
78  logical, public, protected :: hd_trac = .false.
79  integer, public, protected :: hd_trac_type = 1
80 
81  !> Allows overruling default corner filling (for debug mode, since otherwise corner primitives fail)
82  logical, public, protected :: hd_force_diagonal = .false.
83 
84  !> Helium abundance over Hydrogen
85  double precision, public, protected :: he_abundance=0.1d0
86  !> Ionization fraction of H
87  !> H_ion_fr = H+/(H+ + H)
88  double precision, public, protected :: h_ion_fr=1d0
89  !> Ionization fraction of He
90  !> He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
91  double precision, public, protected :: he_ion_fr=1d0
92  !> Ratio of number He2+ / number He+ + He2+
93  !> He_ion_fr2 = He2+/(He2+ + He+)
94  double precision, public, protected :: he_ion_fr2=1d0
95  ! used for eq of state when it is not defined by units,
96  ! the units do not contain terms related to ionization fraction
97  ! and it is p = RR * rho * T
98  double precision, public, protected :: rr=1d0
99  ! remove the below flag and assume default value = .false.
100  ! when eq state properly implemented everywhere
101  ! and not anymore through units
102  logical, public, protected :: eq_state_units = .true.
103 
104  procedure(sub_get_pthermal), pointer :: hd_get_rfactor => null()
105  ! Public methods
106  public :: hd_phys_init
107  public :: hd_kin_en
108  public :: hd_get_pthermal
109  public :: hd_get_csound2
110  public :: hd_to_conserved
111  public :: hd_to_primitive
112  public :: hd_check_params
113  public :: hd_check_w
114 
115 contains
116 
117  !> Read this module's parameters from a file
118  subroutine hd_read_params(files)
120  character(len=*), intent(in) :: files(:)
121  integer :: n
122 
123  namelist /hd_list/ hd_energy, hd_n_tracer, hd_gamma, hd_adiab, &
128 
129  do n = 1, size(files)
130  open(unitpar, file=trim(files(n)), status="old")
131  read(unitpar, hd_list, end=111)
132 111 close(unitpar)
133  end do
134 
135  end subroutine hd_read_params
136 
137  !> Write this module's parameters to a snapsoht
138  subroutine hd_write_info(fh)
140  integer, intent(in) :: fh
141  integer, parameter :: n_par = 1
142  double precision :: values(n_par)
143  character(len=name_len) :: names(n_par)
144  integer, dimension(MPI_STATUS_SIZE) :: st
145  integer :: er
146 
147  call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
148 
149  names(1) = "gamma"
150  values(1) = hd_gamma
151  call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
152  call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
153  end subroutine hd_write_info
154 
155  !> Initialize the module
156  subroutine hd_phys_init()
160  use mod_dust, only: dust_init
161  use mod_viscosity, only: viscosity_init
162  use mod_gravity, only: gravity_init
163  use mod_particles, only: particles_init
165  use mod_cak_force, only: cak_init
169  use mod_usr_methods, only: usr_rfactor
170 
171  integer :: itr, idir
172 
173  call hd_read_params(par_files)
174 
175  physics_type = "hd"
176  phys_energy = hd_energy
177  phys_total_energy = hd_energy
178  phys_internal_e = .false.
179  phys_gamma = hd_gamma
180  phys_partial_ionization=hd_partial_ionization
181 
183  if(phys_trac) then
184  if(ndim .eq. 1) then
185  if(hd_trac_type .gt. 2) then
186  hd_trac_type=1
187  if(mype==0) write(*,*) 'WARNING: set hd_trac_type=1'
188  end if
190  else
191  phys_trac=.false.
192  if(mype==0) write(*,*) 'WARNING: set hd_trac=F when ndim>=2'
193  end if
194  end if
195 
196  ! set default gamma for polytropic/isothermal process
197  if(.not.hd_energy) then
198  if(hd_thermal_conduction) then
199  hd_thermal_conduction=.false.
200  if(mype==0) write(*,*) 'WARNING: set hd_thermal_conduction=F when hd_energy=F'
201  end if
202  if(hd_radiative_cooling) then
203  hd_radiative_cooling=.false.
204  if(mype==0) write(*,*) 'WARNING: set hd_radiative_cooling=F when hd_energy=F'
205  end if
206  end if
207  if(.not.eq_state_units) then
208  if(hd_partial_ionization) then
209  hd_partial_ionization=.false.
210  if(mype==0) write(*,*) 'WARNING: set hd_partial_ionization=F when eq_state_units=F'
211  end if
212  end if
214 
215  allocate(start_indices(number_species),stop_indices(number_species))
216 
217  ! set the index of the first flux variable for species 1
218  start_indices(1)=1
219  ! Determine flux variables
220  rho_ = var_set_rho()
221 
222  allocate(mom(ndir))
223  mom(:) = var_set_momentum(ndir)
224 
225  ! Set index of energy variable
226  if (hd_energy) then
227  e_ = var_set_energy()
228  p_ = e_
229  else
230  e_ = -1
231  p_ = -1
232  end if
233 
234  phys_get_dt => hd_get_dt
235  phys_get_cmax => hd_get_cmax
236  phys_get_a2max => hd_get_a2max
237  phys_get_tcutoff => hd_get_tcutoff
238  phys_get_cbounds => hd_get_cbounds
239  phys_get_flux => hd_get_flux
240  phys_add_source_geom => hd_add_source_geom
241  phys_add_source => hd_add_source
242  phys_to_conserved => hd_to_conserved
243  phys_to_primitive => hd_to_primitive
244  phys_check_params => hd_check_params
245  phys_check_w => hd_check_w
246  phys_get_pthermal => hd_get_pthermal
247  phys_get_v => hd_get_v
248  phys_get_rho => hd_get_rho
249  phys_write_info => hd_write_info
250  phys_handle_small_values => hd_handle_small_values
251 
252  ! Whether diagonal ghost cells are required for the physics
253  phys_req_diagonal = .false.
254 
255  ! derive units from basic units
256  call hd_physical_units()
257 
258  if (hd_dust) then
259  call dust_init(rho_, mom(:), e_)
260  endif
261 
262  if (hd_force_diagonal) then
263  ! ensure corners are filled, otherwise divide by zero when getting primitives
264  ! --> only for debug purposes
265  phys_req_diagonal = .true.
266  endif
267 
268  allocate(tracer(hd_n_tracer))
269 
270  ! Set starting index of tracers
271  do itr = 1, hd_n_tracer
272  tracer(itr) = var_set_fluxvar("trc", "trp", itr, need_bc=.false.)
273  end do
274 
275  ! set number of variables which need update ghostcells
276  nwgc=nwflux+nwaux
277 
278  ! set the index of the last flux variable for species 1
279  stop_indices(1)=nwflux
280 
281  ! set temperature as an auxiliary variable to get ionization degree
282  if(hd_partial_ionization) then
283  te_ = var_set_auxvar('Te','Te')
284  else
285  te_ = -1
286  end if
287 
288  if(hd_trac) then
289  tcoff_ = var_set_wextra()
290  iw_tcoff=tcoff_
291  else
292  tcoff_ = -1
293  end if
294 
295  ! choose Rfactor in ideal gas law
296  if(hd_partial_ionization) then
298  phys_update_temperature => hd_update_temperature
299  else if(associated(usr_rfactor)) then
300  hd_get_rfactor=>usr_rfactor
301  else
302  hd_get_rfactor=>rfactor_from_constant_ionization
303  end if
304 
305  ! initialize thermal conduction module
306  if (hd_thermal_conduction) then
307  if (.not. hd_energy) &
308  call mpistop("thermal conduction needs hd_energy=T")
309  phys_req_diagonal = .true.
310 
311  call sts_init()
313 
314  allocate(tc_fl)
319  tc_fl%get_temperature_from_conserved => hd_get_temperature_from_etot
320  tc_fl%get_temperature_from_eint => hd_get_temperature_from_eint
321  tc_fl%get_rho => hd_get_rho
322  tc_fl%e_ = e_
323  end if
324 
325  ! Initialize radiative cooling module
326  if (hd_radiative_cooling) then
327  if (.not. hd_energy) &
328  call mpistop("radiative cooling needs hd_energy=T")
330  allocate(rc_fl)
332  rc_fl%get_rho => hd_get_rho
333  rc_fl%get_pthermal => hd_get_pthermal
334  rc_fl%get_var_Rfactor => hd_get_rfactor
335  rc_fl%e_ = e_
336  rc_fl%Tcoff_ = tcoff_
337  end if
338  allocate(te_fl_hd)
339  te_fl_hd%get_rho=> hd_get_rho
340  te_fl_hd%get_pthermal=> hd_get_pthermal
341  te_fl_hd%get_var_Rfactor => hd_get_rfactor
342 {^ifthreed
343  phys_te_images => hd_te_images
344 }
345  ! Initialize viscosity module
346  if (hd_viscosity) call viscosity_init(phys_wider_stencil,phys_req_diagonal)
347 
348  ! Initialize gravity module
349  if (hd_gravity) call gravity_init()
350 
351  ! Initialize rotating_frame module
353 
354  ! Initialize CAK radiation force module
355  if (hd_cak_force) call cak_init(hd_gamma)
356 
357  ! Initialize particles module
358  if (hd_particles) then
359  call particles_init()
360  phys_req_diagonal = .true.
361  end if
362 
363  ! Check whether custom flux types have been defined
364  if (.not. allocated(flux_type)) then
365  allocate(flux_type(ndir, nw))
366  flux_type = flux_default
367  else if (any(shape(flux_type) /= [ndir, nw])) then
368  call mpistop("phys_check error: flux_type has wrong shape")
369  end if
370 
371  nvector = 1 ! No. vector vars
372  allocate(iw_vector(nvector))
373  iw_vector(1) = mom(1) - 1
374  ! initialize ionization degree table
376 
377  end subroutine hd_phys_init
378 
379 {^ifthreed
380  subroutine hd_te_images
383  select case(convert_type)
384  case('EIvtiCCmpi','EIvtuCCmpi')
386  case('ESvtiCCmpi','ESvtuCCmpi')
388  case('SIvtiCCmpi','SIvtuCCmpi')
390  case('WIvtiCCmpi','WIvtuCCmpi')
392  case default
393  call mpistop("Error in synthesize emission: Unknown convert_type")
394  end select
395  end subroutine hd_te_images
396 }
397 !!start th cond
398  ! wrappers for STS functions in thermal_conductivity module
399  ! which take as argument the tc_fluid (defined in the physics module)
400  subroutine hd_sts_set_source_tc_hd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
402  use mod_fix_conserve
404  integer, intent(in) :: ixI^L, ixO^L, igrid, nflux
405  double precision, intent(in) :: x(ixI^S,1:ndim)
406  double precision, intent(inout) :: wres(ixI^S,1:nw), w(ixI^S,1:nw)
407  double precision, intent(in) :: my_dt
408  logical, intent(in) :: fix_conserve_at_step
409  call sts_set_source_tc_hd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl)
410  end subroutine hd_sts_set_source_tc_hd
411 
412  function hd_get_tc_dt_hd(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
413  !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para_i/rho)
414  !where tc_k_para_i=tc_k_para*B_i**2/B**2
415  !and T=p/rho
418 
419  integer, intent(in) :: ixi^l, ixo^l
420  double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
421  double precision, intent(in) :: w(ixi^s,1:nw)
422  double precision :: dtnew
423 
424  dtnew=get_tc_dt_hd(w,ixi^l,ixo^l,dx^d,x,tc_fl)
425  end function hd_get_tc_dt_hd
426 
427  subroutine hd_tc_handle_small_e(w, x, ixI^L, ixO^L, step)
428  ! move this in a different routine as in mhd if needed in more places
430  use mod_small_values
431 
432  integer, intent(in) :: ixI^L,ixO^L
433  double precision, intent(inout) :: w(ixI^S,1:nw)
434  double precision, intent(in) :: x(ixI^S,1:ndim)
435  integer, intent(in) :: step
436 
437  integer :: idir
438  logical :: flag(ixI^S,1:nw)
439  character(len=140) :: error_msg
440 
441  flag=.false.
442  where(w(ixo^s,e_)<small_e) flag(ixo^s,e_)=.true.
443  if(any(flag(ixo^s,e_))) then
444  select case (small_values_method)
445  case ("replace")
446  where(flag(ixo^s,e_)) w(ixo^s,e_)=small_e
447  case ("average")
448  call small_values_average(ixi^l, ixo^l, w, x, flag, e_)
449  case default
450  ! small values error shows primitive variables
451  w(ixo^s,e_)=w(ixo^s,e_)*(hd_gamma - 1.0d0)
452  do idir = 1, ndir
453  w(ixo^s, iw_mom(idir)) = w(ixo^s, iw_mom(idir))/w(ixo^s,rho_)
454  end do
455  write(error_msg,"(a,i3)") "Thermal conduction step ", step
456  call small_values_error(w, x, ixi^l, ixo^l, flag, error_msg)
457  end select
458  end if
459  end subroutine hd_tc_handle_small_e
460 
461  ! fill in tc_fluid fields from namelist
462  subroutine tc_params_read_hd(fl)
464  type(tc_fluid), intent(inout) :: fl
465  integer :: n
466  logical :: tc_saturate=.false.
467  double precision :: tc_k_para=0d0
468 
469  namelist /tc_list/ tc_saturate, tc_k_para
470 
471  do n = 1, size(par_files)
472  open(unitpar, file=trim(par_files(n)), status="old")
473  read(unitpar, tc_list, end=111)
474 111 close(unitpar)
475  end do
476  fl%tc_saturate = tc_saturate
477  fl%tc_k_para = tc_k_para
478 
479  end subroutine tc_params_read_hd
480 
481  subroutine hd_get_rho(w,x,ixI^L,ixO^L,rho)
483  integer, intent(in) :: ixI^L, ixO^L
484  double precision, intent(in) :: w(ixI^S,1:nw),x(ixI^S,1:ndim)
485  double precision, intent(out) :: rho(ixI^S)
486 
487  rho(ixo^s) = w(ixo^s,rho_)
488 
489  end subroutine hd_get_rho
490 
491 !!end th cond
492 !!rad cool
493  subroutine rc_params_read(fl)
495  use mod_constants, only: bigdouble
496  use mod_basic_types, only: std_len
497  type(rc_fluid), intent(inout) :: fl
498  integer :: n
499  ! list parameters
500  integer :: ncool = 4000
501  double precision :: cfrac=0.1d0
502 
503  !> Name of cooling curve
504  character(len=std_len) :: coolcurve='JCcorona'
505 
506  !> Name of cooling method
507  character(len=std_len) :: coolmethod='exact'
508 
509  !> Fixed temperature not lower than tlow
510  logical :: Tfix=.false.
511 
512  !> Lower limit of temperature
513  double precision :: tlow=bigdouble
514 
515  !> Add cooling source in a split way (.true.) or un-split way (.false.)
516  logical :: rc_split=.false.
517 
518 
519  namelist /rc_list/ coolcurve, coolmethod, ncool, cfrac, tlow, tfix, rc_split
520 
521  do n = 1, size(par_files)
522  open(unitpar, file=trim(par_files(n)), status="old")
523  read(unitpar, rc_list, end=111)
524 111 close(unitpar)
525  end do
526 
527  fl%ncool=ncool
528  fl%coolcurve=coolcurve
529  fl%coolmethod=coolmethod
530  fl%tlow=tlow
531  fl%Tfix=tfix
532  fl%rc_split=rc_split
533  fl%cfrac=cfrac
534  end subroutine rc_params_read
535 !! end rad cool
536 
537  subroutine hd_check_params
540 
541  if (.not. hd_energy) then
542  if (hd_gamma <= 0.0d0) call mpistop ("Error: hd_gamma <= 0")
543  if (hd_adiab < 0.0d0) call mpistop ("Error: hd_adiab < 0")
545  else
546  if (hd_gamma <= 0.0d0 .or. hd_gamma == 1.0d0) &
547  call mpistop ("Error: hd_gamma <= 0 or hd_gamma == 1.0")
548  small_e = small_pressure/(hd_gamma - 1.0d0)
549  end if
550 
551  if (hd_dust) call dust_check_params()
552  if(use_imex_scheme) then
553  ! implicit dust update
554  phys_implicit_update => dust_implicit_update
555  phys_evaluate_implicit => dust_evaluate_implicit
556  endif
557 
558  end subroutine hd_check_params
559 
560  subroutine hd_physical_units
562  double precision :: mp,kB
563  double precision :: a,b
564  ! Derive scaling units
565  if(si_unit) then
566  mp=mp_si
567  kb=kb_si
568  else
569  mp=mp_cgs
570  kb=kb_cgs
571  end if
572  if(eq_state_units) then
573  a = 1d0 + 4d0 * he_abundance
574  if(hd_partial_ionization) then
575  b = 2.d0+3.d0*he_abundance
576  else
577  b = 1d0 + h_ion_fr + he_abundance*(he_ion_fr*(he_ion_fr2 + 1d0)+1d0)
578  end if
579  rr = 1d0
580  else
581  a = 1d0
582  b = 1d0
583  rr = (1d0 + h_ion_fr + he_abundance*(he_ion_fr*(he_ion_fr2 + 1d0)+1d0))/(1d0 + 4d0 * he_abundance)
584  end if
585  if(unit_density/=1.d0) then
587  else
588  ! unit of numberdensity is independent by default
590  end if
591  if(unit_velocity/=1.d0) then
594  else if(unit_pressure/=1.d0) then
597  else
598  ! unit of temperature is independent by default
601  end if
602  if(unit_time/=1.d0) then
604  else
605  ! unit of length is independent by default
607  end if
609 
610  end subroutine hd_physical_units
611 
612  !> Returns logical argument flag where values are ok
613  subroutine hd_check_w(primitive, ixI^L, ixO^L, w, flag)
615  use mod_dust, only: dust_check_w
616 
617  logical, intent(in) :: primitive
618  integer, intent(in) :: ixi^l, ixo^l
619  double precision, intent(in) :: w(ixi^s, nw)
620  logical, intent(inout) :: flag(ixi^s,1:nw)
621  double precision :: tmp(ixi^s)
622 
623  flag=.false.
624 
625  if (hd_energy) then
626  if (primitive) then
627  where(w(ixo^s, e_) < small_pressure) flag(ixo^s,e_) = .true.
628  else
629  tmp(ixo^s) = (hd_gamma - 1.0d0)*(w(ixo^s, e_) - &
630  hd_kin_en(w, ixi^l, ixo^l))
631  where(tmp(ixo^s) < small_pressure) flag(ixo^s,e_) = .true.
632  endif
633  end if
634 
635  where(w(ixo^s, rho_) < small_density) flag(ixo^s,rho_) = .true.
636 
637  if(hd_dust) call dust_check_w(ixi^l,ixo^l,w,flag)
638 
639  end subroutine hd_check_w
640 
641  !> Transform primitive variables into conservative ones
642  subroutine hd_to_conserved(ixI^L, ixO^L, w, x)
644  use mod_dust, only: dust_to_conserved
645  integer, intent(in) :: ixi^l, ixo^l
646  double precision, intent(inout) :: w(ixi^s, nw)
647  double precision, intent(in) :: x(ixi^s, 1:ndim)
648  double precision :: invgam
649  integer :: idir, itr
650 
651  !!if (fix_small_values) then
652  !! call hd_handle_small_values(.true., w, x, ixI^L, ixO^L, 'hd_to_conserved')
653  !!end if
654 
655  if (hd_energy) then
656  invgam = 1.d0/(hd_gamma - 1.0d0)
657  ! Calculate total energy from pressure and kinetic energy
658  w(ixo^s, e_) = w(ixo^s, e_) * invgam + &
659  0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) * w(ixo^s, rho_)
660  end if
661 
662  ! Convert velocity to momentum
663  do idir = 1, ndir
664  w(ixo^s, mom(idir)) = w(ixo^s, rho_) * w(ixo^s, mom(idir))
665  end do
666 
667  if (hd_dust) then
668  call dust_to_conserved(ixi^l, ixo^l, w, x)
669  end if
670 
671  end subroutine hd_to_conserved
672 
673  !> Transform conservative variables into primitive ones
674  subroutine hd_to_primitive(ixI^L, ixO^L, w, x)
676  use mod_dust, only: dust_to_primitive
677  integer, intent(in) :: ixi^l, ixo^l
678  double precision, intent(inout) :: w(ixi^s, nw)
679  double precision, intent(in) :: x(ixi^s, 1:ndim)
680  integer :: itr, idir
681  double precision :: inv_rho(ixo^s)
682 
683  if (fix_small_values) then
684  call hd_handle_small_values(.false., w, x, ixi^l, ixo^l, 'hd_to_primitive')
685  end if
686 
687  inv_rho = 1.0d0 / w(ixo^s, rho_)
688 
689  if (hd_energy) then
690  ! Compute pressure
691  w(ixo^s, e_) = (hd_gamma - 1.0d0) * (w(ixo^s, e_) - &
692  hd_kin_en(w, ixi^l, ixo^l, inv_rho))
693  end if
694 
695  ! Convert momentum to velocity
696  do idir = 1, ndir
697  w(ixo^s, mom(idir)) = w(ixo^s, mom(idir)) * inv_rho
698  end do
699 
700  ! Convert dust momentum to dust velocity
701  if (hd_dust) then
702  call dust_to_primitive(ixi^l, ixo^l, w, x)
703  end if
704 
705  end subroutine hd_to_primitive
706 
707  !> Transform internal energy to total energy
708  subroutine hd_ei_to_e(ixI^L,ixO^L,w,x)
710  integer, intent(in) :: ixI^L, ixO^L
711  double precision, intent(inout) :: w(ixI^S, nw)
712  double precision, intent(in) :: x(ixI^S, 1:ndim)
713 
714  ! Calculate total energy from internal and kinetic energy
715  w(ixo^s,e_)=w(ixo^s,e_)&
716  +hd_kin_en(w,ixi^l,ixo^l)
717 
718  end subroutine hd_ei_to_e
719 
720  !> Transform total energy to internal energy
721  subroutine hd_e_to_ei(ixI^L,ixO^L,w,x)
723  integer, intent(in) :: ixI^L, ixO^L
724  double precision, intent(inout) :: w(ixI^S, nw)
725  double precision, intent(in) :: x(ixI^S, 1:ndim)
726 
727  ! Calculate ei = e - ek
728  w(ixo^s,e_)=w(ixo^s,e_)&
729  -hd_kin_en(w,ixi^l,ixo^l)
730 
731  end subroutine hd_e_to_ei
732 
733  subroutine e_to_rhos(ixI^L, ixO^L, w, x)
735 
736  integer, intent(in) :: ixI^L, ixO^L
737  double precision :: w(ixI^S, nw)
738  double precision, intent(in) :: x(ixI^S, 1:ndim)
739 
740  if (hd_energy) then
741  w(ixo^s, e_) = (hd_gamma - 1.0d0) * w(ixo^s, rho_)**(1.0d0 - hd_gamma) * &
742  (w(ixo^s, e_) - hd_kin_en(w, ixi^l, ixo^l))
743  else
744  call mpistop("energy from entropy can not be used with -eos = iso !")
745  end if
746  end subroutine e_to_rhos
747 
748  subroutine rhos_to_e(ixI^L, ixO^L, w, x)
750 
751  integer, intent(in) :: ixI^L, ixO^L
752  double precision :: w(ixI^S, nw)
753  double precision, intent(in) :: x(ixI^S, 1:ndim)
754 
755  if (hd_energy) then
756  w(ixo^s, e_) = w(ixo^s, rho_)**(hd_gamma - 1.0d0) * w(ixo^s, e_) &
757  / (hd_gamma - 1.0d0) + hd_kin_en(w, ixi^l, ixo^l)
758  else
759  call mpistop("entropy from energy can not be used with -eos = iso !")
760  end if
761  end subroutine rhos_to_e
762 
763  !> Calculate v_i = m_i / rho within ixO^L
764  subroutine hd_get_v_idim(w, x, ixI^L, ixO^L, idim, v)
766  integer, intent(in) :: ixI^L, ixO^L, idim
767  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:ndim)
768  double precision, intent(out) :: v(ixI^S)
769 
770  v(ixo^s) = w(ixo^s, mom(idim)) / w(ixo^s, rho_)
771  end subroutine hd_get_v_idim
772 
773  !> Calculate velocity vector v_i = m_i / rho within ixO^L
774  subroutine hd_get_v(w,x,ixI^L,ixO^L,v)
776 
777  integer, intent(in) :: ixI^L, ixO^L
778  double precision, intent(in) :: w(ixI^S,nw), x(ixI^S,1:^ND)
779  double precision, intent(out) :: v(ixI^S,1:ndir)
780 
781  integer :: idir
782 
783  do idir=1,ndir
784  v(ixo^s,idir) = w(ixo^s, mom(idir)) / w(ixo^s, rho_)
785  end do
786 
787  end subroutine hd_get_v
788 
789  !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
790  subroutine hd_get_cmax(w, x, ixI^L, ixO^L, idim, cmax)
792  use mod_dust, only: dust_get_cmax
793 
794  integer, intent(in) :: ixI^L, ixO^L, idim
795  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:ndim)
796  double precision, intent(inout) :: cmax(ixI^S)
797  double precision :: csound(ixI^S)
798  double precision :: v(ixI^S)
799 
800  call hd_get_v_idim(w, x, ixi^l, ixo^l, idim, v)
801  call hd_get_csound2(w,x,ixi^l,ixo^l,csound)
802  csound(ixo^s) = dsqrt(csound(ixo^s))
803 
804  cmax(ixo^s) = dabs(v(ixo^s))+csound(ixo^s)
805 
806  if (hd_dust) then
807  call dust_get_cmax(w, x, ixi^l, ixo^l, idim, cmax)
808  end if
809  end subroutine hd_get_cmax
810 
811  subroutine hd_get_a2max(w,x,ixI^L,ixO^L,a2max)
813 
814  integer, intent(in) :: ixI^L, ixO^L
815  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
816  double precision, intent(inout) :: a2max(ndim)
817  double precision :: a2(ixI^S,ndim,nw)
818  integer :: gxO^L,hxO^L,jxO^L,kxO^L,i,j
819 
820  a2=zero
821  do i = 1,ndim
822  !> 4th order
823  hxo^l=ixo^l-kr(i,^d);
824  gxo^l=hxo^l-kr(i,^d);
825  jxo^l=ixo^l+kr(i,^d);
826  kxo^l=jxo^l+kr(i,^d);
827  a2(ixo^s,i,1:nw)=dabs(-w(kxo^s,1:nw)+16.d0*w(jxo^s,1:nw)&
828  -30.d0*w(ixo^s,1:nw)+16.d0*w(hxo^s,1:nw)-w(gxo^s,1:nw))
829  a2max(i)=maxval(a2(ixo^s,i,1:nw))/12.d0/dxlevel(i)**2
830  end do
831  end subroutine hd_get_a2max
832 
833  !> get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
834  subroutine hd_get_tcutoff(ixI^L,ixO^L,w,x,tco_local,Tmax_local)
836  integer, intent(in) :: ixI^L,ixO^L
837  double precision, intent(in) :: x(ixI^S,1:ndim)
838  double precision, intent(inout) :: w(ixI^S,1:nw)
839  double precision, intent(out) :: tco_local, Tmax_local
840 
841  double precision, parameter :: trac_delta=0.25d0
842  double precision :: tmp1(ixI^S),Te(ixI^S),lts(ixI^S)
843  double precision :: ltr(ixI^S),ltrc,ltrp,tcoff(ixI^S)
844  integer :: jxO^L,hxO^L
845  integer :: jxP^L,hxP^L,ixP^L
846  logical :: lrlt(ixI^S)
847 
848  {^ifoned
849  call hd_get_temperature_from_etot(w,x,ixi^l,ixi^l,te)
850 
851  tco_local=zero
852  tmax_local=maxval(te(ixo^s))
853  select case(hd_trac_type)
854  case(0)
855  w(ixi^s,tcoff_)=3.d5/unit_temperature
856  case(1)
857  hxo^l=ixo^l-1;
858  jxo^l=ixo^l+1;
859  lts(ixo^s)=0.5d0*dabs(te(jxo^s)-te(hxo^s))/te(ixo^s)
860  lrlt=.false.
861  where(lts(ixo^s) > trac_delta)
862  lrlt(ixo^s)=.true.
863  end where
864  if(any(lrlt(ixo^s))) then
865  tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
866  end if
867  case(2)
868  !> iijima et al. 2021, LTRAC method
869  ltrc=1.5d0
870  ltrp=2.5d0
871  ixp^l=ixo^l^ladd1;
872  hxo^l=ixo^l-1;
873  jxo^l=ixo^l+1;
874  hxp^l=ixp^l-1;
875  jxp^l=ixp^l+1;
876  lts(ixp^s)=0.5d0*abs(te(jxp^s)-te(hxp^s))/te(ixp^s)
877  ltr(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
878  w(ixo^s,tcoff_)=te(ixo^s)*&
879  (0.25*(ltr(jxo^s)+two*ltr(ixo^s)+ltr(hxo^s)))**0.4d0
880  case default
881  call mpistop("mhd_trac_type not allowed for 1D simulation")
882  end select
883  }
884  end subroutine hd_get_tcutoff
885 
886  !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
887  subroutine hd_get_cbounds(wLC, wRC, wLp, wRp, x, ixI^L, ixO^L, idim,Hspeed,cmax, cmin)
889  use mod_dust, only: dust_get_cmax
890  use mod_variables
891 
892  integer, intent(in) :: ixI^L, ixO^L, idim
893  ! conservative left and right status
894  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S, nw)
895  ! primitive left and right status
896  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S, nw)
897  double precision, intent(in) :: x(ixI^S, 1:ndim)
898  double precision, intent(inout) :: cmax(ixI^S,1:number_species)
899  double precision, intent(inout), optional :: cmin(ixI^S,1:number_species)
900  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
901 
902  double precision :: wmean(ixI^S,nw)
903  double precision, dimension(ixI^S) :: umean, dmean, csoundL, csoundR, tmp1,tmp2,tmp3
904  integer :: ix^D
905 
906  select case(boundspeed)
907  case (1)
908  ! This implements formula (10.52) from "Riemann Solvers and Numerical
909  ! Methods for Fluid Dynamics" by Toro.
910 
911  tmp1(ixo^s)=dsqrt(wlp(ixo^s,rho_))
912  tmp2(ixo^s)=dsqrt(wrp(ixo^s,rho_))
913  tmp3(ixo^s)=1.d0/(dsqrt(wlp(ixo^s,rho_))+dsqrt(wrp(ixo^s,rho_)))
914  umean(ixo^s)=(wlp(ixo^s,mom(idim))*tmp1(ixo^s)+wrp(ixo^s,mom(idim))*tmp2(ixo^s))*tmp3(ixo^s)
915 
916  if(hd_energy) then
917  csoundl(ixo^s)=hd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
918  csoundr(ixo^s)=hd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
919  else
920  call hd_get_csound2(wlc,x,ixi^l,ixo^l,csoundl)
921  call hd_get_csound2(wrc,x,ixi^l,ixo^l,csoundr)
922  end if
923 
924  dmean(ixo^s) = (tmp1(ixo^s)*csoundl(ixo^s)+tmp2(ixo^s)*csoundr(ixo^s)) * &
925  tmp3(ixo^s) + 0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2 * &
926  (wrp(ixo^s,mom(idim))-wlp(ixo^s,mom(idim)))**2
927 
928  dmean(ixo^s)=dsqrt(dmean(ixo^s))
929  if(present(cmin)) then
930  cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
931  cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
932  if(h_correction) then
933  {do ix^db=ixomin^db,ixomax^db\}
934  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
935  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
936  {end do\}
937  end if
938  else
939  cmax(ixo^s,1)=dabs(umean(ixo^s))+dmean(ixo^s)
940  end if
941 
942  if (hd_dust) then
943  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
944  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
945  end if
946 
947  case (2)
948  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
949  tmp1(ixo^s)=wmean(ixo^s,mom(idim))/wmean(ixo^s,rho_)
950  call hd_get_csound2(wmean,x,ixi^l,ixo^l,csoundr)
951  csoundr(ixo^s) = dsqrt(csoundr(ixo^s))
952 
953  if(present(cmin)) then
954  cmax(ixo^s,1)=max(tmp1(ixo^s)+csoundr(ixo^s),zero)
955  cmin(ixo^s,1)=min(tmp1(ixo^s)-csoundr(ixo^s),zero)
956  if(h_correction) then
957  {do ix^db=ixomin^db,ixomax^db\}
958  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
959  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
960  {end do\}
961  end if
962  else
963  cmax(ixo^s,1)=dabs(tmp1(ixo^s))+csoundr(ixo^s)
964  end if
965 
966  if (hd_dust) then
967  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
968  end if
969  case (3)
970  ! Miyoshi 2005 JCP 208, 315 equation (67)
971  if(hd_energy) then
972  csoundl(ixo^s)=hd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
973  csoundr(ixo^s)=hd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
974  else
975  call hd_get_csound2(wlc,x,ixi^l,ixo^l,csoundl)
976  call hd_get_csound2(wrc,x,ixi^l,ixo^l,csoundr)
977  end if
978  csoundl(ixo^s)=max(dsqrt(csoundl(ixo^s)),dsqrt(csoundr(ixo^s)))
979  if(present(cmin)) then
980  cmin(ixo^s,1)=min(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))-csoundl(ixo^s)
981  cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
982  if(h_correction) then
983  {do ix^db=ixomin^db,ixomax^db\}
984  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
985  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
986  {end do\}
987  end if
988  else
989  cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
990  end if
991  if (hd_dust) then
992  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
993  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
994  end if
995  end select
996 
997  end subroutine hd_get_cbounds
998 
999  !> Calculate the square of the thermal sound speed csound2 within ixO^L.
1000  !> csound2=gamma*p/rho
1001  subroutine hd_get_csound2(w,x,ixI^L,ixO^L,csound2)
1003  integer, intent(in) :: ixi^l, ixo^l
1004  double precision, intent(in) :: w(ixi^s,nw)
1005  double precision, intent(in) :: x(ixi^s,1:ndim)
1006  double precision, intent(out) :: csound2(ixi^s)
1007 
1008  call hd_get_pthermal(w,x,ixi^l,ixo^l,csound2)
1009  csound2(ixo^s)=hd_gamma*csound2(ixo^s)/w(ixo^s,rho_)
1010 
1011  end subroutine hd_get_csound2
1012 
1013  !> Calculate thermal pressure=(gamma-1)*(e-0.5*m**2/rho) within ixO^L
1014  subroutine hd_get_pthermal(w, x, ixI^L, ixO^L, pth)
1018 
1019  integer, intent(in) :: ixi^l, ixo^l
1020  double precision, intent(in) :: w(ixi^s, 1:nw)
1021  double precision, intent(in) :: x(ixi^s, 1:ndim)
1022  double precision, intent(out):: pth(ixi^s)
1023  integer :: iw, ix^d
1024 
1025  if (hd_energy) then
1026  pth(ixo^s) = (hd_gamma - 1.0d0) * (w(ixo^s, e_) - &
1027  hd_kin_en(w, ixi^l, ixo^l))
1028  else
1029  if (.not. associated(usr_set_pthermal)) then
1030  pth(ixo^s) = hd_adiab * w(ixo^s, rho_)**hd_gamma
1031  else
1032  call usr_set_pthermal(w,x,ixi^l,ixo^l,pth)
1033  end if
1034  end if
1035 
1036  if (fix_small_values) then
1037  {do ix^db= ixo^lim^db\}
1038  if(pth(ix^d)<small_pressure) then
1039  pth(ix^d)=small_pressure
1040  endif
1041  {enddo^d&\}
1042  else if (check_small_values) then
1043  {do ix^db= ixo^lim^db\}
1044  if(pth(ix^d)<small_pressure) then
1045  write(*,*) "Error: small value of gas pressure",pth(ix^d),&
1046  " encountered when call hd_get_pthermal"
1047  write(*,*) "Iteration: ", it, " Time: ", global_time
1048  write(*,*) "Location: ", x(ix^d,:)
1049  write(*,*) "Cell number: ", ix^d
1050  do iw=1,nw
1051  write(*,*) trim(cons_wnames(iw)),": ",w(ix^d,iw)
1052  end do
1053  ! use erroneous arithmetic operation to crash the run
1054  if(trace_small_values) write(*,*) dsqrt(pth(ix^d)-bigdouble)
1055  write(*,*) "Saving status at the previous time step"
1056  crash=.true.
1057  end if
1058  {enddo^d&\}
1059  end if
1060 
1061  end subroutine hd_get_pthermal
1062 
1063  !> Calculate temperature=p/rho when in e_ the total energy is stored
1064  subroutine hd_get_temperature_from_etot(w, x, ixI^L, ixO^L, res)
1066  integer, intent(in) :: ixI^L, ixO^L
1067  double precision, intent(in) :: w(ixI^S, 1:nw)
1068  double precision, intent(in) :: x(ixI^S, 1:ndim)
1069  double precision, intent(out):: res(ixI^S)
1070 
1071  double precision :: R(ixI^S)
1072 
1073  call hd_get_rfactor(w,x,ixi^l,ixo^l,r)
1074  call hd_get_pthermal(w, x, ixi^l, ixo^l, res)
1075  res(ixo^s)=res(ixo^s)/(r(ixo^s)*w(ixo^s,rho_))
1076  end subroutine hd_get_temperature_from_etot
1077 
1078  !> Calculate temperature=p/rho when in e_ the internal energy is stored
1079  subroutine hd_get_temperature_from_eint(w, x, ixI^L, ixO^L, res)
1081  integer, intent(in) :: ixI^L, ixO^L
1082  double precision, intent(in) :: w(ixI^S, 1:nw)
1083  double precision, intent(in) :: x(ixI^S, 1:ndim)
1084  double precision, intent(out):: res(ixI^S)
1085 
1086  double precision :: R(ixI^S)
1087 
1088  call hd_get_rfactor(w,x,ixi^l,ixo^l,r)
1089  res(ixo^s) = (hd_gamma - 1.0d0) * w(ixo^s, e_)/(w(ixo^s,rho_)*r(ixo^s))
1090  end subroutine hd_get_temperature_from_eint
1091 
1092  ! Calculate flux f_idim[iw]
1093  subroutine hd_get_flux_cons(w, x, ixI^L, ixO^L, idim, f)
1095  use mod_dust, only: dust_get_flux
1096 
1097  integer, intent(in) :: ixI^L, ixO^L, idim
1098  double precision, intent(in) :: w(ixI^S, 1:nw), x(ixI^S, 1:ndim)
1099  double precision, intent(out) :: f(ixI^S, nwflux)
1100  double precision :: pth(ixI^S), v(ixI^S),frame_vel(ixI^S)
1101  integer :: idir, itr
1102 
1103  call hd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1104  call hd_get_v_idim(w, x, ixi^l, ixo^l, idim, v)
1105 
1106  f(ixo^s, rho_) = v(ixo^s) * w(ixo^s, rho_)
1107 
1108  ! Momentum flux is v_i*m_i, +p in direction idim
1109  do idir = 1, ndir
1110  f(ixo^s, mom(idir)) = v(ixo^s) * w(ixo^s, mom(idir))
1111  end do
1112 
1113  f(ixo^s, mom(idim)) = f(ixo^s, mom(idim)) + pth(ixo^s)
1114 
1115  if(hd_energy) then
1116  ! Energy flux is v_i*(e + p)
1117  f(ixo^s, e_) = v(ixo^s) * (w(ixo^s, e_) + pth(ixo^s))
1118  end if
1119 
1120  do itr = 1, hd_n_tracer
1121  f(ixo^s, tracer(itr)) = v(ixo^s) * w(ixo^s, tracer(itr))
1122  end do
1123 
1124  ! Dust fluxes
1125  if (hd_dust) then
1126  call dust_get_flux(w, x, ixi^l, ixo^l, idim, f)
1127  end if
1128 
1129  end subroutine hd_get_flux_cons
1130 
1131  ! Calculate flux f_idim[iw]
1132  subroutine hd_get_flux(wC, w, x, ixI^L, ixO^L, idim, f)
1134  use mod_dust, only: dust_get_flux_prim
1135  use mod_viscosity, only: visc_get_flux_prim ! viscInDiv
1136 
1137  integer, intent(in) :: ixI^L, ixO^L, idim
1138  ! conservative w
1139  double precision, intent(in) :: wC(ixI^S, 1:nw)
1140  ! primitive w
1141  double precision, intent(in) :: w(ixI^S, 1:nw)
1142  double precision, intent(in) :: x(ixI^S, 1:ndim)
1143  double precision, intent(out) :: f(ixI^S, nwflux)
1144  double precision :: pth(ixI^S),frame_vel(ixI^S)
1145  integer :: idir, itr
1146 
1147  if (hd_energy) then
1148  pth(ixo^s) = w(ixo^s,p_)
1149  else
1150  call hd_get_pthermal(wc, x, ixi^l, ixo^l, pth)
1151  end if
1152 
1153  f(ixo^s, rho_) = w(ixo^s,mom(idim)) * w(ixo^s, rho_)
1154 
1155  ! Momentum flux is v_i*m_i, +p in direction idim
1156  do idir = 1, ndir
1157  f(ixo^s, mom(idir)) = w(ixo^s,mom(idim)) * wc(ixo^s, mom(idir))
1158  end do
1159 
1160  f(ixo^s, mom(idim)) = f(ixo^s, mom(idim)) + pth(ixo^s)
1161 
1162  if(hd_energy) then
1163  ! Energy flux is v_i*(e + p)
1164  f(ixo^s, e_) = w(ixo^s,mom(idim)) * (wc(ixo^s, e_) + w(ixo^s,p_))
1165  end if
1166 
1167  do itr = 1, hd_n_tracer
1168  f(ixo^s, tracer(itr)) = w(ixo^s,mom(idim)) * w(ixo^s, tracer(itr))
1169  end do
1170 
1171  ! Dust fluxes
1172  if (hd_dust) then
1173  call dust_get_flux_prim(w, x, ixi^l, ixo^l, idim, f)
1174  end if
1175 
1176  ! Viscosity fluxes - viscInDiv
1177  if (hd_viscosity) then
1178  call visc_get_flux_prim(w, x, ixi^l, ixo^l, idim, f, hd_energy)
1179  endif
1180 
1181  end subroutine hd_get_flux
1182 
1183  !> Add geometrical source terms to w
1184  !>
1185  !> Notice that the expressions of the geometrical terms depend only on ndir,
1186  !> not ndim. Eg, they are the same in 2.5D and in 3D, for any geometry.
1187  !>
1188  !> Ileyk : to do :
1189  !> - address the source term for the dust in case (coordinate == spherical)
1190  subroutine hd_add_source_geom(qdt, dtfactor, ixI^L, ixO^L, wCT, w, x)
1192  use mod_usr_methods, only: usr_set_surface
1193  use mod_viscosity, only: visc_add_source_geom ! viscInDiv
1196  use mod_geometry
1197  integer, intent(in) :: ixI^L, ixO^L
1198  double precision, intent(in) :: qdt, dtfactor, x(ixI^S, 1:ndim)
1199  double precision, intent(inout) :: wCT(ixI^S, 1:nw), w(ixI^S, 1:nw)
1200  ! to change and to set as a parameter in the parfile once the possibility to
1201  ! solve the equations in an angular momentum conserving form has been
1202  ! implemented (change tvdlf.t eg)
1203  double precision :: pth(ixI^S), source(ixI^S), minrho
1204  integer :: iw,idir, h1x^L{^NOONED, h2x^L}
1205  integer :: mr_,mphi_ ! Polar var. names
1206  integer :: irho, ifluid, n_fluids
1207  double precision :: exp_factor(ixI^S), del_exp_factor(ixI^S), exp_factor_primitive(ixI^S)
1208 
1209  if (hd_dust) then
1210  n_fluids = 1 + dust_n_species
1211  else
1212  n_fluids = 1
1213  end if
1214 
1215  select case (coordinate)
1216 
1217  case(cartesian_expansion)
1218  !the user provides the functions of exp_factor and del_exp_factor
1219  if(associated(usr_set_surface)) call usr_set_surface(ixi^l,x,block%dx,exp_factor,del_exp_factor,exp_factor_primitive)
1220  call hd_get_pthermal(wct, x, ixi^l, ixo^l, source)
1221  source(ixo^s) = source(ixo^s)*del_exp_factor(ixo^s)/exp_factor(ixo^s)
1222  w(ixo^s,mom(1)) = w(ixo^s,mom(1)) + qdt*source(ixo^s)
1223 
1224  case (cylindrical)
1225  do ifluid = 0, n_fluids-1
1226  ! s[mr]=(pthermal+mphi**2/rho)/radius
1227  if (ifluid == 0) then
1228  ! gas
1229  irho = rho_
1230  mr_ = mom(r_)
1231  if(phi_>0) mphi_ = mom(phi_)
1232  call hd_get_pthermal(wct, x, ixi^l, ixo^l, source)
1233  minrho = 0.0d0
1234  else
1235  ! dust : no pressure
1236  irho = dust_rho(ifluid)
1237  mr_ = dust_mom(r_, ifluid)
1238  if(phi_>0) mphi_ = dust_mom(phi_, ifluid)
1239  source(ixi^s) = zero
1240  minrho = 0.0d0
1241  end if
1242  if (phi_ > 0) then
1243  where (wct(ixo^s, irho) > minrho)
1244  source(ixo^s) = source(ixo^s) + wct(ixo^s, mphi_)**2 / wct(ixo^s, irho)
1245  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1246  end where
1247  ! s[mphi]=(-mphi*mr/rho)/radius
1248  where (wct(ixo^s, irho) > minrho)
1249  source(ixo^s) = -wct(ixo^s, mphi_) * wct(ixo^s, mr_) / wct(ixo^s, irho)
1250  w(ixo^s, mphi_) = w(ixo^s, mphi_) + qdt * source(ixo^s) / x(ixo^s, r_)
1251  end where
1252  else
1253  ! s[mr]=2pthermal/radius
1254  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1255  end if
1256  end do
1257  case (spherical)
1258  if (hd_dust) then
1259  call mpistop("Dust geom source terms not implemented yet with spherical geometries")
1260  end if
1261  mr_ = mom(r_)
1262  if(phi_>0) mphi_ = mom(phi_)
1263  h1x^l=ixo^l-kr(1,^d); {^nooned h2x^l=ixo^l-kr(2,^d);}
1264  ! s[mr]=((mtheta**2+mphi**2)/rho+2*p)/r
1265  call hd_get_pthermal(wct, x, ixi^l, ixo^l, pth)
1266  source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1267  *(block%surfaceC(ixo^s, 1) - block%surfaceC(h1x^s, 1)) &
1268  /block%dvolume(ixo^s)
1269  if (ndir > 1) then
1270  do idir = 2, ndir
1271  source(ixo^s) = source(ixo^s) + wct(ixo^s, mom(idir))**2 / wct(ixo^s, rho_)
1272  end do
1273  end if
1274  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, 1)
1275 
1276  {^nooned
1277  ! s[mtheta]=-(mr*mtheta/rho)/r+cot(theta)*(mphi**2/rho+p)/r
1278  source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1279  * (block%surfaceC(ixo^s, 2) - block%surfaceC(h2x^s, 2)) &
1280  / block%dvolume(ixo^s)
1281  if (ndir == 3) then
1282  source(ixo^s) = source(ixo^s) + (wct(ixo^s, mom(3))**2 / wct(ixo^s, rho_)) / tan(x(ixo^s, 2))
1283  end if
1284  source(ixo^s) = source(ixo^s) - (wct(ixo^s, mom(2)) * wct(ixo^s, mr_)) / wct(ixo^s, rho_)
1285  w(ixo^s, mom(2)) = w(ixo^s, mom(2)) + qdt * source(ixo^s) / x(ixo^s, 1)
1286 
1287  if (ndir == 3) then
1288  ! s[mphi]=-(mphi*mr/rho)/r-cot(theta)*(mtheta*mphi/rho)/r
1289  source(ixo^s) = -(wct(ixo^s, mom(3)) * wct(ixo^s, mr_)) / wct(ixo^s, rho_)&
1290  - (wct(ixo^s, mom(2)) * wct(ixo^s, mom(3))) / wct(ixo^s, rho_) / tan(x(ixo^s, 2))
1291  w(ixo^s, mom(3)) = w(ixo^s, mom(3)) + qdt * source(ixo^s) / x(ixo^s, 1)
1292  end if
1293  }
1294  end select
1295 
1296  if (hd_viscosity) call visc_add_source_geom(qdt,ixi^l,ixo^l,wct,w,x)
1297 
1298  if (hd_rotating_frame) then
1299  if (hd_dust) then
1300  call mpistop("Rotating frame not implemented yet with dust")
1301  else
1302  call rotating_frame_add_source(qdt,dtfactor,ixi^l,ixo^l,wct,w,x)
1303  end if
1304  end if
1305 
1306  end subroutine hd_add_source_geom
1307 
1308  ! w[iw]= w[iw]+qdt*S[wCT, qtC, x] where S is the source based on wCT within ixO
1309  subroutine hd_add_source(qdt,dtfactor, ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
1314  use mod_usr_methods, only: usr_gravity
1316  use mod_cak_force, only: cak_add_source
1317 
1318  integer, intent(in) :: ixI^L, ixO^L
1319  double precision, intent(in) :: qdt, dtfactor
1320  double precision, intent(in) :: wCT(ixI^S, 1:nw),wCTprim(ixI^S,1:nw), x(ixI^S, 1:ndim)
1321  double precision, intent(inout) :: w(ixI^S, 1:nw)
1322  logical, intent(in) :: qsourcesplit
1323  logical, intent(inout) :: active
1324 
1325  double precision :: gravity_field(ixI^S, 1:ndim)
1326  integer :: idust, idim
1327 
1328  if(hd_dust .and. .not. use_imex_scheme) then
1329  call dust_add_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1330  end if
1331 
1332  if(hd_radiative_cooling) then
1333  call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1334  qsourcesplit,active, rc_fl)
1335  end if
1336 
1337  if(hd_viscosity) then
1338  call viscosity_add_source(qdt,ixi^l,ixo^l,wct,w,x,&
1339  hd_energy,qsourcesplit,active)
1340  end if
1341 
1342  if (hd_gravity) then
1343  call gravity_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1344  hd_energy,.false.,qsourcesplit,active)
1345 
1346  if (hd_dust .and. qsourcesplit .eqv. grav_split) then
1347  active = .true.
1348 
1349  call usr_gravity(ixi^l, ixo^l, wct, x, gravity_field)
1350  do idust = 1, dust_n_species
1351  do idim = 1, ndim
1352  w(ixo^s, dust_mom(idim, idust)) = w(ixo^s, dust_mom(idim, idust)) &
1353  + qdt * gravity_field(ixo^s, idim) * wct(ixo^s, dust_rho(idust))
1354  end do
1355  end do
1356  end if
1357  end if
1358 
1359  if (hd_cak_force) then
1360  call cak_add_source(qdt,ixi^l,ixo^l,wct,w,x,hd_energy,qsourcesplit,active)
1361  end if
1362 
1363  if(hd_partial_ionization) then
1364  if(.not.qsourcesplit) then
1365  active = .true.
1366  call hd_update_temperature(ixi^l,ixo^l,wct,w,x)
1367  end if
1368  end if
1369 
1370  end subroutine hd_add_source
1371 
1372  subroutine hd_get_dt(w, ixI^L, ixO^L, dtnew, dx^D, x)
1374  use mod_dust, only: dust_get_dt
1376  use mod_viscosity, only: viscosity_get_dt
1377  use mod_gravity, only: gravity_get_dt
1378  use mod_cak_force, only: cak_get_dt
1379 
1380  integer, intent(in) :: ixI^L, ixO^L
1381  double precision, intent(in) :: dx^D, x(ixI^S, 1:^ND)
1382  double precision, intent(in) :: w(ixI^S, 1:nw)
1383  double precision, intent(inout) :: dtnew
1384 
1385  dtnew = bigdouble
1386 
1387  if(hd_dust) then
1388  call dust_get_dt(w, ixi^l, ixo^l, dtnew, dx^d, x)
1389  end if
1390 
1391  if(hd_radiative_cooling) then
1392  call cooling_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x,rc_fl)
1393  end if
1394 
1395  if(hd_viscosity) then
1396  call viscosity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1397  end if
1398 
1399  if(hd_gravity) then
1400  call gravity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1401  end if
1402 
1403  if (hd_cak_force) then
1404  call cak_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1405  end if
1406 
1407  end subroutine hd_get_dt
1408 
1409  function hd_kin_en(w, ixI^L, ixO^L, inv_rho) result(ke)
1410  use mod_global_parameters, only: nw, ndim
1411  integer, intent(in) :: ixi^l, ixo^l
1412  double precision, intent(in) :: w(ixi^s, nw)
1413  double precision :: ke(ixo^s)
1414  double precision, intent(in), optional :: inv_rho(ixo^s)
1415 
1416  if (present(inv_rho)) then
1417  ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) * inv_rho
1418  else
1419  ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) / w(ixo^s, rho_)
1420  end if
1421  end function hd_kin_en
1422 
1423  function hd_inv_rho(w, ixI^L, ixO^L) result(inv_rho)
1424  use mod_global_parameters, only: nw, ndim
1425  integer, intent(in) :: ixi^l, ixo^l
1426  double precision, intent(in) :: w(ixi^s, nw)
1427  double precision :: inv_rho(ixo^s)
1428 
1429  ! Can make this more robust
1430  inv_rho = 1.0d0 / w(ixo^s, rho_)
1431  end function hd_inv_rho
1432 
1433  subroutine hd_handle_small_values(primitive, w, x, ixI^L, ixO^L, subname)
1434  ! handles hydro (density,pressure,velocity) bootstrapping
1435  ! any negative dust density is flagged as well (and throws an error)
1436  ! small_values_method=replace also for dust
1438  use mod_small_values
1440  logical, intent(in) :: primitive
1441  integer, intent(in) :: ixI^L,ixO^L
1442  double precision, intent(inout) :: w(ixI^S,1:nw)
1443  double precision, intent(in) :: x(ixI^S,1:ndim)
1444  character(len=*), intent(in) :: subname
1445 
1446  integer :: n,idir
1447  logical :: flag(ixI^S,1:nw)
1448 
1449  call hd_check_w(primitive, ixi^l, ixo^l, w, flag)
1450 
1451  if (any(flag)) then
1452  select case (small_values_method)
1453  case ("replace")
1454  where(flag(ixo^s,rho_)) w(ixo^s,rho_) = small_density
1455  do idir = 1, ndir
1456  if(small_values_fix_iw(mom(idir))) then
1457  where(flag(ixo^s,rho_)) w(ixo^s, mom(idir)) = 0.0d0
1458  end if
1459  end do
1460  if(hd_energy)then
1461  if(small_values_fix_iw(e_)) then
1462  if(primitive) then
1463  where(flag(ixo^s,rho_)) w(ixo^s, p_) = small_pressure
1464  else
1465  where(flag(ixo^s,rho_)) w(ixo^s, e_) = small_e + hd_kin_en(w,ixi^l,ixo^l)
1466  endif
1467  end if
1468  endif
1469 
1470  if(hd_energy) then
1471  if(primitive) then
1472  where(flag(ixo^s,e_)) w(ixo^s,p_) = small_pressure
1473  else
1474  where(flag(ixo^s,e_))
1475  ! Add kinetic energy
1476  w(ixo^s,e_) = small_e + hd_kin_en(w,ixi^l,ixo^l)
1477  end where
1478  end if
1479  end if
1480 
1481  if(hd_dust)then
1482  do n=1,dust_n_species
1483  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1484  do idir = 1, ndir
1485  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1486  enddo
1487  enddo
1488  endif
1489  case ("average")
1490  if(primitive)then
1491  ! averaging for all primitive fields, including dust
1492  call small_values_average(ixi^l, ixo^l, w, x, flag)
1493  else
1494  ! do averaging of density
1495  call small_values_average(ixi^l, ixo^l, w, x, flag, rho_)
1496  if(hd_energy) then
1497  ! do averaging of pressure
1498  w(ixi^s,p_)=(hd_gamma-1.d0)*(w(ixi^s,e_) &
1499  -0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_))
1500  call small_values_average(ixi^l, ixo^l, w, x, flag, p_)
1501  w(ixi^s,e_)=w(ixi^s,p_)/(hd_gamma-1.d0) &
1502  +0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_)
1503  end if
1504  if(hd_dust)then
1505  do n=1,dust_n_species
1506  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1507  do idir = 1, ndir
1508  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1509  enddo
1510  enddo
1511  endif
1512  endif
1513  case default
1514  if(.not.primitive) then
1515  !convert w to primitive
1516  ! Calculate pressure = (gamma-1) * (e-ek)
1517  if(hd_energy) then
1518  w(ixo^s,p_)=(hd_gamma-1.d0)*(w(ixo^s,e_)-hd_kin_en(w,ixi^l,ixo^l))
1519  end if
1520  ! Convert gas momentum to velocity
1521  do idir = 1, ndir
1522  w(ixo^s, mom(idir)) = w(ixo^s, mom(idir))/w(ixo^s,rho_)
1523  end do
1524  end if
1525  ! NOTE: dust entries may still have conserved values here
1526  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
1527  end select
1528  end if
1529  end subroutine hd_handle_small_values
1530 
1531  subroutine rfactor_from_temperature_ionization(w,x,ixI^L,ixO^L,Rfactor)
1534  integer, intent(in) :: ixI^L, ixO^L
1535  double precision, intent(in) :: w(ixI^S,1:nw)
1536  double precision, intent(in) :: x(ixI^S,1:ndim)
1537  double precision, intent(out):: Rfactor(ixI^S)
1538 
1539  double precision :: iz_H(ixO^S),iz_He(ixO^S)
1540 
1541  call ionization_degree_from_temperature(ixi^l,ixo^l,w(ixi^s,te_),iz_h,iz_he)
1542  ! assume the first and second ionization of Helium have the same degree
1543  rfactor(ixo^s)=(1.d0+iz_h(ixo^s)+0.1d0*(1.d0+iz_he(ixo^s)*(1.d0+iz_he(ixo^s))))/2.3d0
1544 
1546 
1547  subroutine rfactor_from_constant_ionization(w,x,ixI^L,ixO^L,Rfactor)
1549  integer, intent(in) :: ixI^L, ixO^L
1550  double precision, intent(in) :: w(ixI^S,1:nw)
1551  double precision, intent(in) :: x(ixI^S,1:ndim)
1552  double precision, intent(out):: Rfactor(ixI^S)
1553 
1554  rfactor(ixo^s)=rr
1555 
1556  end subroutine rfactor_from_constant_ionization
1557 
1558  subroutine hd_update_temperature(ixI^L,ixO^L,wCT,w,x)
1561 
1562  integer, intent(in) :: ixI^L, ixO^L
1563  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
1564  double precision, intent(inout) :: w(ixI^S,1:nw)
1565 
1566  double precision :: iz_H(ixO^S),iz_He(ixO^S), pth(ixI^S)
1567 
1568  call ionization_degree_from_temperature(ixi^l,ixo^l,wct(ixi^s,te_),iz_h,iz_he)
1569 
1570  call hd_get_pthermal(w,x,ixi^l,ixo^l,pth)
1571 
1572  w(ixo^s,te_)=(2.d0+3.d0*he_abundance)*pth(ixo^s)/(w(ixo^s,rho_)*(1.d0+iz_h(ixo^s)+&
1573  he_abundance*(iz_he(ixo^s)*(iz_he(ixo^s)+1.d0)+1.d0)))
1574 
1575  end subroutine hd_update_temperature
1576 
1577 end module mod_hd_phys
Calculate w(iw)=w(iw)+qdt*SOURCE[wCT,qtC,x] within ixO for all indices iw=iwmin......
Module with basic data types used in amrvac.
integer, parameter std_len
Default length for strings.
Module to include CAK radiation line force in (magneto)hydrodynamic models Computes both the force fr...
Definition: mod_cak_force.t:27
subroutine cak_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
Check time step for total radiation contribution.
subroutine cak_init(phys_gamma)
Initialize the module.
Definition: mod_cak_force.t:98
subroutine cak_add_source(qdt, ixIL, ixOL, wCT, w, x, energy, qsourcesplit, active)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO
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
Module for including dust species, which interact with the gas through a drag force.
Definition: mod_dust.t:3
subroutine, public dust_check_w(ixIL, ixOL, w, flag)
Definition: mod_dust.t:194
subroutine, public dust_get_flux(w, x, ixIL, ixOL, idim, f)
Definition: mod_dust.t:252
subroutine, public dust_implicit_update(dtfactor, qdt, qtC, psb, psa)
Implicit solve of psb=psa+dtfactor*dt*F_im(psb)
Definition: mod_dust.t:651
subroutine, public dust_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
Get dt related to dust and gas stopping time (Laibe 2011)
Definition: mod_dust.t:897
subroutine, public dust_add_source(qdt, ixIL, ixOL, wCT, w, x, qsourcesplit, active)
w[iw]= w[iw]+qdt*S[wCT, x] where S is the source based on wCT within ixO
Definition: mod_dust.t:529
subroutine, public dust_to_primitive(ixIL, ixOL, w, x)
Definition: mod_dust.t:228
integer, dimension(:, :), allocatable, public, protected dust_mom
Indices of the dust momentum densities.
Definition: mod_dust.t:22
subroutine, public dust_get_cmax(w, x, ixIL, ixOL, idim, cmax, cmin)
Definition: mod_dust.t:1010
integer, public, protected dust_n_species
The number of dust species.
Definition: mod_dust.t:12
integer, dimension(:), allocatable, public, protected dust_rho
Indices of the dust densities.
Definition: mod_dust.t:19
subroutine, public dust_get_flux_prim(w, x, ixIL, ixOL, idim, f)
Definition: mod_dust.t:275
subroutine, public dust_check_params()
Definition: mod_dust.t:154
subroutine, public dust_evaluate_implicit(qtC, psa)
inplace update of psa==>F_im(psa)
Definition: mod_dust.t:582
subroutine, public dust_init(g_rho, g_mom, g_energy)
Definition: mod_dust.t:95
subroutine, public dust_to_conserved(ixIL, ixOL, w, x)
Definition: mod_dust.t:208
Module for flux conservation near refinement boundaries.
Module with geometry-related routines (e.g., divergence, curl)
Definition: mod_geometry.t:2
integer coordinate
Definition: mod_geometry.t:7
integer, parameter spherical
Definition: mod_geometry.t:11
integer, parameter cylindrical
Definition: mod_geometry.t:10
integer, parameter cartesian_expansion
Definition: mod_geometry.t:12
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.
logical h_correction
If true, do H-correction to fix the carbuncle problem at grid-aligned shocks.
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 global_time
The global simulation time.
double precision unit_mass
Physical scaling factor for mass.
logical use_imex_scheme
whether IMEX in use or not
integer, dimension(3, 3) kr
Kronecker delta tensor.
integer it
Number of time steps taken.
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.
logical use_particles
Use particles module or not.
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.
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.
logical crash
Save a snapshot before crash a run met unphysical values.
double precision small_density
integer r_
Indices for cylindrical coordinates FOR TESTS, negative value when not used:
integer boundspeed
bound (left/min and right.max) speed of Riemann fan
integer, parameter unitconvert
double precision, dimension(ndim) dxlevel
logical check_small_values
check and optionally fix unphysical small values (density, gas pressure)
Module for including gravity in (magneto)hydrodynamics simulations.
Definition: mod_gravity.t:2
logical grav_split
source split or not
Definition: mod_gravity.t:6
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
Hydrodynamics physics module.
Definition: mod_hd_phys.t:2
subroutine, public hd_check_params
Definition: mod_hd_phys.t:538
logical, public, protected hd_energy
Whether an energy equation is used.
Definition: mod_hd_phys.t:12
logical, public, protected hd_dust
Whether dust is added.
Definition: mod_hd_phys.t:24
subroutine rfactor_from_temperature_ionization(w, x, ixIL, ixOL, Rfactor)
Definition: mod_hd_phys.t:1532
integer, public, protected e_
Index of the energy density (-1 if not present)
Definition: mod_hd_phys.t:57
logical, public, protected hd_radiative_cooling
Whether radiative cooling is added.
Definition: mod_hd_phys.t:20
double precision, public, protected rr
Definition: mod_hd_phys.t:98
subroutine hd_get_flux(wC, w, x, ixIL, ixOL, idim, f)
Definition: mod_hd_phys.t:1133
double precision, public hd_gamma
The adiabatic index.
Definition: mod_hd_phys.t:69
subroutine rhos_to_e(ixIL, ixOL, w, x)
Definition: mod_hd_phys.t:749
subroutine hd_get_a2max(w, x, ixIL, ixOL, a2max)
Definition: mod_hd_phys.t:812
subroutine hd_add_source_geom(qdt, dtfactor, ixIL, ixOL, wCT, w, x)
Add geometrical source terms to w.
Definition: mod_hd_phys.t:1191
integer, public, protected hd_trac_type
Definition: mod_hd_phys.t:79
subroutine hd_get_flux_cons(w, x, ixIL, ixOL, idim, f)
Definition: mod_hd_phys.t:1094
logical, public, protected hd_particles
Whether particles module is added.
Definition: mod_hd_phys.t:33
subroutine hd_te_images
Definition: mod_hd_phys.t:381
type(tc_fluid), allocatable, public tc_fl
Definition: mod_hd_phys.t:16
logical, public, protected hd_viscosity
Whether viscosity is added.
Definition: mod_hd_phys.t:27
subroutine rc_params_read(fl)
Definition: mod_hd_phys.t:494
subroutine hd_get_rho(w, x, ixIL, ixOL, rho)
Definition: mod_hd_phys.t:482
subroutine, public hd_check_w(primitive, ixIL, ixOL, w, flag)
Returns logical argument flag where values are ok.
Definition: mod_hd_phys.t:614
integer, public, protected tcoff_
Index of the cutoff temperature for the TRAC method.
Definition: mod_hd_phys.t:66
subroutine hd_e_to_ei(ixIL, ixOL, w, x)
Transform total energy to internal energy.
Definition: mod_hd_phys.t:722
double precision, public, protected he_ion_fr2
Ratio of number He2+ / number He+ + He2+ He_ion_fr2 = He2+/(He2+ + He+)
Definition: mod_hd_phys.t:94
subroutine hd_sts_set_source_tc_hd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux)
Definition: mod_hd_phys.t:401
subroutine hd_ei_to_e(ixIL, ixOL, w, x)
Transform internal energy to total energy.
Definition: mod_hd_phys.t:709
subroutine hd_add_source(qdt, dtfactor, ixIL, ixOL, wCT, wCTprim, w, x, qsourcesplit, active)
Definition: mod_hd_phys.t:1310
subroutine hd_write_info(fh)
Write this module's parameters to a snapsoht.
Definition: mod_hd_phys.t:139
integer, public, protected te_
Indices of temperature.
Definition: mod_hd_phys.t:63
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
Definition: mod_hd_phys.t:51
subroutine hd_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
Definition: mod_hd_phys.t:1373
double precision function hd_get_tc_dt_hd(w, ixIL, ixOL, dxD, x)
Definition: mod_hd_phys.t:413
double precision, public, protected h_ion_fr
Ionization fraction of H H_ion_fr = H+/(H+ + H)
Definition: mod_hd_phys.t:88
logical, public, protected hd_cak_force
Whether CAK radiation line force is activated.
Definition: mod_hd_phys.t:39
subroutine hd_get_cbounds(wLC, wRC, wLp, wRp, x, ixIL, ixOL, idim, Hspeed, cmax, cmin)
Calculate cmax_idim = csound + abs(v_idim) within ixO^L.
Definition: mod_hd_phys.t:888
subroutine, public hd_phys_init()
Initialize the module.
Definition: mod_hd_phys.t:157
subroutine hd_get_temperature_from_eint(w, x, ixIL, ixOL, res)
Calculate temperature=p/rho when in e_ the internal energy is stored.
Definition: mod_hd_phys.t:1080
integer, dimension(:), allocatable, public, protected tracer
Indices of the tracers.
Definition: mod_hd_phys.t:54
logical, public, protected hd_thermal_conduction
Whether thermal conduction is added.
Definition: mod_hd_phys.t:15
logical, public, protected eq_state_units
Definition: mod_hd_phys.t:102
logical, public, protected hd_force_diagonal
Allows overruling default corner filling (for debug mode, since otherwise corner primitives fail)
Definition: mod_hd_phys.t:82
subroutine, public hd_get_pthermal(w, x, ixIL, ixOL, pth)
Calculate thermal pressure=(gamma-1)*(e-0.5*m**2/rho) within ixO^L.
Definition: mod_hd_phys.t:1015
double precision, public hd_adiab
The adiabatic constant.
Definition: mod_hd_phys.t:72
subroutine hd_get_tcutoff(ixIL, ixOL, w, x, tco_local, Tmax_local)
get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
Definition: mod_hd_phys.t:835
integer, public, protected rho_
Index of the density (in the w array)
Definition: mod_hd_phys.t:48
subroutine tc_params_read_hd(fl)
Definition: mod_hd_phys.t:463
subroutine hd_get_v_idim(w, x, ixIL, ixOL, idim, v)
Calculate v_i = m_i / rho within ixO^L.
Definition: mod_hd_phys.t:765
logical, public, protected hd_partial_ionization
Whether plasma is partially ionized.
Definition: mod_hd_phys.t:45
double precision, public, protected he_ion_fr
Ionization fraction of He He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
Definition: mod_hd_phys.t:91
double precision, public, protected he_abundance
Helium abundance over Hydrogen.
Definition: mod_hd_phys.t:85
logical, public, protected hd_gravity
Whether gravity is added.
Definition: mod_hd_phys.t:30
subroutine hd_physical_units
Definition: mod_hd_phys.t:561
subroutine rfactor_from_constant_ionization(w, x, ixIL, ixOL, Rfactor)
Definition: mod_hd_phys.t:1548
subroutine, public hd_to_conserved(ixIL, ixOL, w, x)
Transform primitive variables into conservative ones.
Definition: mod_hd_phys.t:643
type(rc_fluid), allocatable, public rc_fl
Definition: mod_hd_phys.t:21
subroutine, public hd_to_primitive(ixIL, ixOL, w, x)
Transform conservative variables into primitive ones.
Definition: mod_hd_phys.t:675
logical, public, protected hd_trac
Whether TRAC method is used.
Definition: mod_hd_phys.t:78
integer, public, protected hd_n_tracer
Number of tracer species.
Definition: mod_hd_phys.t:42
type(te_fluid), allocatable, public te_fl_hd
Definition: mod_hd_phys.t:17
subroutine e_to_rhos(ixIL, ixOL, w, x)
Definition: mod_hd_phys.t:734
subroutine hd_get_cmax(w, x, ixIL, ixOL, idim, cmax)
Calculate cmax_idim = csound + abs(v_idim) within ixO^L.
Definition: mod_hd_phys.t:791
logical, public, protected hd_rotating_frame
Whether rotating frame is activated.
Definition: mod_hd_phys.t:36
subroutine hd_get_v(w, x, ixIL, ixOL, v)
Calculate velocity vector v_i = m_i / rho within ixO^L.
Definition: mod_hd_phys.t:775
double precision function, dimension(ixo^s), public hd_kin_en(w, ixIL, ixOL, inv_rho)
Definition: mod_hd_phys.t:1410
subroutine hd_update_temperature(ixIL, ixOL, wCT, w, x)
Definition: mod_hd_phys.t:1559
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
Definition: mod_hd_phys.t:60
subroutine hd_tc_handle_small_e(w, x, ixIL, ixOL, step)
Definition: mod_hd_phys.t:428
subroutine hd_get_temperature_from_etot(w, x, ixIL, ixOL, res)
Calculate temperature=p/rho when in e_ the total energy is stored.
Definition: mod_hd_phys.t:1065
subroutine hd_handle_small_values(primitive, w, x, ixIL, ixOL, subname)
Definition: mod_hd_phys.t:1434
subroutine, public hd_get_csound2(w, x, ixIL, ixOL, csound2)
Calculate the square of the thermal sound speed csound2 within ixO^L. csound2=gamma*p/rho.
Definition: mod_hd_phys.t:1002
double precision function, dimension(ixo^s) hd_inv_rho(w, ixIL, ixOL)
Definition: mod_hd_phys.t:1424
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
subroutine particles_init()
Initialize particle data and parameters.
Definition: mod_particles.t:15
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 including rotating frame in (magneto)hydrodynamics simulations The rotation vector is assu...
subroutine rotating_frame_add_source(qdt, dtfactor, ixIL, ixOL, wCT, w, x)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO
subroutine rotating_frame_init()
Initialize the module.
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_hd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux, fl)
subroutine, public tc_get_hd_params(fl, read_hd_params)
Init TC coefficients: HD case.
subroutine tc_init_params(phys_gamma)
double precision function, public get_tc_dt_hd(w, ixIL, ixOL, dxD, x, fl)
Get the explicit timestep for the TC (hd implementation)
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_surface), pointer usr_set_surface
procedure(phys_gravity), pointer usr_gravity
procedure(hd_pthermal), pointer usr_set_pthermal
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
subroutine visc_add_source_geom(qdt, ixIL, ixOL, wCT, w, x)
subroutine, public visc_get_flux_prim(w, x, ixIL, ixOL, idim, f, energy)