MPI-AMRVAC  3.1
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
mod_rhd_phys.t
Go to the documentation of this file.
1 !> Radiation-Hydrodynamics physics module
2 !> Module aims at solving the Hydrodynamic equations toghether with
3 !> the zeroth moment of the radiative transfer equation. A closure is
4 !> provided by the flux limited diffusion (FLD)-approximation in the mod_fld.t module. See
5 !> [1]Moens, N., Sundqvist, J. O., El Mellah, I., Poniatowski, L., Teunissen, J., and Keppens, R.,
6 !> “Radiation-hydrodynamics with MPI-AMRVAC . Flux-limited diffusion”,
7 !> <i>Astronomy and Astrophysics</i>, vol. 657, 2022. doi:10.1051/0004-6361/202141023.
8 !> For more information.
9 !> Another possible closure in the works is the anisotropic flux limited diffusion approximation (AFLD) described in mod_afld.t.
10 
15  use mod_physics
16  use mod_comm_lib, only: mpistop
17  implicit none
18  private
19 
20  !> Whether an energy equation is used
21  logical, public, protected :: rhd_energy = .true.
22 
23  !> Whether thermal conduction is added
24  logical, public, protected :: rhd_thermal_conduction = .false.
25  type(tc_fluid), allocatable, public :: tc_fl
26  type(te_fluid), allocatable, public :: te_fl_rhd
27 
28  !> Whether radiative cooling is added
29  logical, public, protected :: rhd_radiative_cooling = .false.
30  type(rc_fluid), allocatable, public :: rc_fl
31 
32  !> Whether dust is added
33  logical, public, protected :: rhd_dust = .false.
34 
35  !> Whether viscosity is added
36  logical, public, protected :: rhd_viscosity = .false.
37 
38  !> Whether gravity is added
39  logical, public, protected :: rhd_gravity = .false.
40 
41  !> Whether particles module is added
42  logical, public, protected :: rhd_particles = .false.
43 
44  !> Whether rotating frame is activated
45  logical, public, protected :: rhd_rotating_frame = .false.
46 
47  !> Number of tracer species
48  integer, public, protected :: rhd_n_tracer = 0
49 
50  !> Index of the density (in the w array)
51  integer, public, protected :: rho_
52 
53  !> Indices of the momentum density
54  integer, allocatable, public, protected :: mom(:)
55 
56  !> Indices of the tracers
57  integer, allocatable, public, protected :: tracer(:)
58 
59  !> Index of the energy density (-1 if not present)
60  integer, public, protected :: e_
61 
62  !> Index of the gas pressure (-1 if not present) should equal e_
63  integer, public, protected :: p_
64 
65  !> Index of the radiation energy
66  integer, public, protected :: r_e
67 
68  !> Indices of temperature
69  integer, public, protected :: te_
70 
71  !> Index of the cutoff temperature for the TRAC method
72  integer, public, protected :: tcoff_
73 
74  !> The adiabatic index
75  double precision, public :: rhd_gamma = 5.d0/3.0d0
76 
77  !> The adiabatic constant
78  double precision, public :: rhd_adiab = 1.0d0
79 
80  !> The small_est allowed energy
81  double precision, protected :: small_e
82 
83  !> The smallest allowed radiation energy
84  double precision, public, protected :: small_r_e = 0.d0
85 
86  !> Whether TRAC method is used
87  logical, public, protected :: rhd_trac = .false.
88  integer, public, protected :: rhd_trac_type = 1
89 
90  !> Allows overruling default corner filling (for debug mode, since otherwise corner primitives fail)
91  logical, public, protected :: rhd_force_diagonal = .false.
92 
93  !> Helium abundance over Hydrogen
94  double precision, public, protected :: he_abundance=0.1d0
95 
96  !> Formalism to treat radiation
97  character(len=8), public :: rhd_radiation_formalism = 'fld'
98 
99  !> In the case of no rhd_energy, how to compute pressure
100  character(len=8), public :: rhd_pressure = 'Trad'
101 
102  !> Treat radiation fld_Rad_force
103  logical, public, protected :: rhd_radiation_force = .true.
104 
105  !> Treat radiation-gas energy interaction
106  logical, public, protected :: rhd_energy_interact = .true.
107 
108  !> Treat radiation energy diffusion
109  logical, public, protected :: rhd_radiation_diffusion = .true.
110 
111  !> Treat radiation advection
112  logical, public, protected :: rhd_radiation_advection = .true.
113 
114  !> Whether plasma is partially ionized
115  logical, public, protected :: rhd_partial_ionization = .false.
116 
117  !> Do a running mean over the radiation pressure when determining dt
118  logical, protected :: radio_acoustic_filter = .false.
119  integer, protected :: size_ra_filter = 1
120 
121  !> kb/(m_p mu)* 1/a_rad**4,
122  double precision, public :: kbmpmua4
123 
124  !> Use the speed of light to calculate the timestep, usefull for debugging
125  logical :: dt_c = .false.
126 
127  !> Ionization fraction of H
128  !> H_ion_fr = H+/(H+ + H)
129  double precision, public, protected :: h_ion_fr=1d0
130  !> Ionization fraction of He
131  !> He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
132  double precision, public, protected :: he_ion_fr=1d0
133  !> Ratio of number He2+ / number He+ + He2+
134  !> He_ion_fr2 = He2+/(He2+ + He+)
135  double precision, public, protected :: he_ion_fr2=1d0
136  ! used for eq of state when it is not defined by units,
137  ! the units do not contain terms related to ionization fraction
138  ! and it is p = RR * rho * T
139  double precision, public, protected :: rr=1d0
140  ! remove the below flag and assume default value = .false.
141  ! when eq state properly implemented everywhere
142  ! and not anymore through units
143  logical, public, protected :: eq_state_units = .true.
144 
145  procedure(sub_get_pthermal), pointer :: rhd_get_rfactor => null()
146  ! Public methods
147  public :: rhd_phys_init
148  public :: rhd_kin_en
149  public :: rhd_get_pthermal
150  public :: rhd_get_pradiation
151  public :: rhd_get_ptot
152  public :: rhd_get_csound2
153  public :: rhd_to_conserved
154  public :: rhd_to_primitive
155  public :: rhd_check_params
156  public :: rhd_check_w
157  public :: rhd_get_tgas
158  public :: rhd_get_trad
159  public :: rhd_set_mg_bounds
160 
161 contains
162 
163  !> Read this module's parameters from a file
164  subroutine rhd_read_params(files)
166  character(len=*), intent(in) :: files(:)
167  integer :: n
168 
169  namelist /rhd_list/ rhd_energy, rhd_pressure, rhd_n_tracer, rhd_gamma, rhd_adiab, &
175  rhd_radiation_advection, radio_acoustic_filter, size_ra_filter, dt_c, rhd_partial_ionization
176 
177  do n = 1, size(files)
178  open(unitpar, file=trim(files(n)), status="old")
179  read(unitpar, rhd_list, end=111)
180 111 close(unitpar)
181  end do
182 
183  end subroutine rhd_read_params
184 
185  !> Write this module's parameters to a snapsoht
186  subroutine rhd_write_info(fh)
188  integer, intent(in) :: fh
189  integer, parameter :: n_par = 1
190  double precision :: values(n_par)
191  character(len=name_len) :: names(n_par)
192  integer, dimension(MPI_STATUS_SIZE) :: st
193  integer :: er
194 
195  call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
196 
197  names(1) = "gamma"
198  values(1) = rhd_gamma
199  call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
200  call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
201  end subroutine rhd_write_info
202 
203  !> Initialize the module
204  subroutine rhd_phys_init()
208  use mod_dust, only: dust_init
209  use mod_viscosity, only: viscosity_init
210  use mod_gravity, only: gravity_init
211  use mod_particles, only: particles_init
213  use mod_fld
214  use mod_afld
218  use mod_usr_methods, only: usr_rfactor
219 
220  integer :: itr, idir
221 
222  call rhd_read_params(par_files)
223 
224  physics_type = "rhd"
225  phys_energy = rhd_energy
226  phys_total_energy = rhd_energy
227  phys_gamma = rhd_gamma
228 
230  if(phys_trac) then
231  if(ndim .eq. 1) then
232  if(rhd_trac_type .gt. 2) then
233  rhd_trac_type=1
234  if(mype==0) write(*,*) 'WARNING: set rhd_trac_type=1'
235  end if
237  else
238  phys_trac=.false.
239  if(mype==0) write(*,*) 'WARNING: set rhd_trac=F when ndim>=2'
240  end if
241  end if
242 
243  ! set default gamma for polytropic/isothermal process
244  if(.not.rhd_energy) then
245  if(rhd_thermal_conduction) then
246  rhd_thermal_conduction=.false.
247  if(mype==0) write(*,*) 'WARNING: set rhd_thermal_conduction=F when rhd_energy=F'
248  end if
249  if(rhd_radiative_cooling) then
250  rhd_radiative_cooling=.false.
251  if(mype==0) write(*,*) 'WARNING: set rhd_radiative_cooling=F when rhd_energy=F'
252  end if
253  end if
254  if(.not.eq_state_units) then
255  if(rhd_partial_ionization) then
256  rhd_partial_ionization=.false.
257  if(mype==0) write(*,*) 'WARNING: set rhd_partial_ionization=F when eq_state_units=F'
258  end if
259  end if
261 
262  allocate(start_indices(number_species),stop_indices(number_species))
263 
264  ! set the index of the first flux variable for species 1
265  start_indices(1)=1
266  ! Determine flux variables
267  rho_ = var_set_rho()
268 
269  allocate(mom(ndir))
270  mom(:) = var_set_momentum(ndir)
271 
272  ! Set index of energy variable
273  if (rhd_energy) then
274  e_ = var_set_energy()
275  p_ = e_
276  else
277  e_ = -1
278  p_ = -1
279  end if
280 
281  !> set radiation energy
282  r_e = var_set_radiation_energy()
283 
284  ! set temperature as an auxiliary variable to get ionization degree
285  if(rhd_partial_ionization) then
286  te_ = var_set_auxvar('Te','Te')
287  else
288  te_ = -1
289  end if
290 
291  phys_get_dt => rhd_get_dt
292  phys_get_cmax => rhd_get_cmax
293  phys_get_a2max => rhd_get_a2max
294  phys_get_tcutoff => rhd_get_tcutoff
295  phys_get_cbounds => rhd_get_cbounds
296  phys_get_flux => rhd_get_flux
297  phys_add_source_geom => rhd_add_source_geom
298  phys_add_source => rhd_add_source
299  phys_to_conserved => rhd_to_conserved
300  phys_to_primitive => rhd_to_primitive
301  ! phys_ei_to_e => rhd_ei_to_e
302  ! phys_e_to_ei => rhd_e_to_ei
303  phys_check_params => rhd_check_params
304  phys_check_w => rhd_check_w
305  phys_get_pthermal => rhd_get_pthermal
306  phys_write_info => rhd_write_info
307  phys_handle_small_values => rhd_handle_small_values
308  phys_set_mg_bounds => rhd_set_mg_bounds
309  phys_get_trad => rhd_get_trad
310  phys_get_tgas => rhd_get_tgas
311 
312  ! Whether diagonal ghost cells are required for the physics
313  phys_req_diagonal = .false.
314 
315  ! derive units from basic units
316  call rhd_physical_units()
317 
318  if (rhd_dust) then
319  call dust_init(rho_, mom(:), e_)
320  endif
321 
322  !> Initiate radiation-closure module
323  select case (rhd_radiation_formalism)
324  case('fld')
325  call fld_init(he_abundance, rhd_radiation_diffusion, rhd_gamma)
326  case('afld')
327  call afld_init(he_abundance, rhd_radiation_diffusion, rhd_gamma)
328  case default
329  call mpistop('Radiation formalism unknown')
330  end select
331 
332  if (rhd_force_diagonal) then
333  ! ensure corners are filled, otherwise divide by zero when getting primitives
334  ! --> only for debug purposes
335  phys_req_diagonal = .true.
336  endif
337 
338  allocate(tracer(rhd_n_tracer))
339 
340  ! Set starting index of tracers
341  do itr = 1, rhd_n_tracer
342  tracer(itr) = var_set_fluxvar("trc", "trp", itr, need_bc=.false.)
343  end do
344 
345  ! set number of variables which need update ghostcells
346  nwgc=nwflux+nwaux
347 
348  ! set the index of the last flux variable for species 1
349  stop_indices(1)=nwflux
350 
351  if(rhd_trac) then
352  tcoff_ = var_set_wextra()
353  iw_tcoff=tcoff_
354  else
355  tcoff_ = -1
356  end if
357 
358  ! choose Rfactor in ideal gas law
359  if(rhd_partial_ionization) then
360  rhd_get_rfactor=>rfactor_from_temperature_ionization
361  phys_update_temperature => rhd_update_temperature
362  else if(associated(usr_rfactor)) then
363  rhd_get_rfactor=>usr_rfactor
364  else
365  rhd_get_rfactor=>rfactor_from_constant_ionization
366  end if
367 
368  ! initialize thermal conduction module
369  if (rhd_thermal_conduction) then
370  if (.not. rhd_energy) &
371  call mpistop("thermal conduction needs rhd_energy=T")
372  phys_req_diagonal = .true.
373 
374  call sts_init()
376 
377  allocate(tc_fl)
379  tc_fl%get_temperature_from_conserved => rhd_get_temperature_from_etot
383  tc_fl%get_temperature_from_eint => rhd_get_temperature_from_eint
384  tc_fl%get_rho => rhd_get_rho
385  tc_fl%e_ = e_
386  end if
387 
388  ! Initialize radiative cooling module
389  if (rhd_radiative_cooling) then
390  if (.not. rhd_energy) &
391  call mpistop("radiative cooling needs rhd_energy=T")
392  call radiative_cooling_init_params(rhd_gamma,he_abundance)
393  allocate(rc_fl)
395  rc_fl%get_rho => rhd_get_rho
396  rc_fl%get_pthermal => rhd_get_pthermal
397  rc_fl%get_var_Rfactor => rhd_get_rfactor
398  rc_fl%e_ = e_
399  rc_fl%Tcoff_ = tcoff_
400  end if
401  allocate(te_fl_rhd)
402  te_fl_rhd%get_rho=> rhd_get_rho
403  te_fl_rhd%get_pthermal=> rhd_get_pthermal
404  te_fl_rhd%get_var_Rfactor => rhd_get_rfactor
405 {^ifthreed
406  phys_te_images => rhd_te_images
407 }
408  ! Initialize viscosity module
409  if (rhd_viscosity) call viscosity_init(phys_wider_stencil,phys_req_diagonal)
410 
411  ! Initialize gravity module
412  if (rhd_gravity) call gravity_init()
413 
414  ! Initialize rotating_frame module
416 
417  ! Initialize particles module
418  if (rhd_particles) then
419  call particles_init()
420  phys_req_diagonal = .true.
421  end if
422 
423  ! Check whether custom flux types have been defined
424  if (.not. allocated(flux_type)) then
425  allocate(flux_type(ndir, nw))
426  flux_type = flux_default
427  else if (any(shape(flux_type) /= [ndir, nw])) then
428  call mpistop("phys_check error: flux_type has wrong shape")
429  end if
430 
431  nvector = 1 ! No. vector vars
432  allocate(iw_vector(nvector))
433  iw_vector(1) = mom(1) - 1
434 
435  !> Usefull constante
436  kbmpmua4 = unit_pressure**(-3.d0/4.d0)*unit_density*const_kb/(const_mp*fld_mu)*const_rad_a**(-1.d0/4.d0)
437  ! initialize ionization degree table
439 
440  end subroutine rhd_phys_init
441 
442 {^ifthreed
443  subroutine rhd_te_images()
446  select case(convert_type)
447  case('EIvtiCCmpi','EIvtuCCmpi')
449  case('ESvtiCCmpi','ESvtuCCmpi')
451  case('SIvtiCCmpi','SIvtuCCmpi')
453  case default
454  call mpistop("Error in synthesize emission: Unknown convert_type")
455  end select
456  end subroutine rhd_te_images
457 }
458 !!start th cond
459  ! wrappers for STS functions in thermal_conductivity module
460  ! which take as argument the tc_fluid (defined in the physics module)
461  subroutine rhd_sts_set_source_tc_rhd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
463  use mod_fix_conserve
465  integer, intent(in) :: ixI^L, ixO^L, igrid, nflux
466  double precision, intent(in) :: x(ixI^S,1:ndim)
467  double precision, intent(inout) :: wres(ixI^S,1:nw), w(ixI^S,1:nw)
468  double precision, intent(in) :: my_dt
469  logical, intent(in) :: fix_conserve_at_step
470  call sts_set_source_tc_hd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl)
471  end subroutine rhd_sts_set_source_tc_rhd
472 
473 
474  function rhd_get_tc_dt_rhd(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
475  !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para_i/rho)
476  !where tc_k_para_i=tc_k_para*B_i**2/B**2
477  !and T=p/rho
480 
481  integer, intent(in) :: ixi^l, ixo^l
482  double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
483  double precision, intent(in) :: w(ixi^s,1:nw)
484  double precision :: dtnew
485 
486  dtnew=get_tc_dt_hd(w,ixi^l,ixo^l,dx^d,x,tc_fl)
487  end function rhd_get_tc_dt_rhd
488 
489 
490  subroutine rhd_tc_handle_small_e(w, x, ixI^L, ixO^L, step)
491  ! move this in a different routine as in mhd if needed in more places
493  use mod_small_values
494 
495  integer, intent(in) :: ixI^L,ixO^L
496  double precision, intent(inout) :: w(ixI^S,1:nw)
497  double precision, intent(in) :: x(ixI^S,1:ndim)
498  integer, intent(in) :: step
499 
500  integer :: idir
501  logical :: flag(ixI^S,1:nw)
502  character(len=140) :: error_msg
503 
504  flag=.false.
505  where(w(ixo^s,e_)<small_e) flag(ixo^s,e_)=.true.
506  if(any(flag(ixo^s,e_))) then
507  select case (small_values_method)
508  case ("replace")
509  where(flag(ixo^s,e_)) w(ixo^s,e_)=small_e
510  case ("average")
511  call small_values_average(ixi^l, ixo^l, w, x, flag, e_)
512  case default
513  ! small values error shows primitive variables
514  w(ixo^s,e_)=w(ixo^s,e_)*(rhd_gamma - 1.0d0)
515  do idir = 1, ndir
516  w(ixo^s, iw_mom(idir)) = w(ixo^s, iw_mom(idir))/w(ixo^s,rho_)
517  end do
518  write(error_msg,"(a,i3)") "Thermal conduction step ", step
519  call small_values_error(w, x, ixi^l, ixo^l, flag, error_msg)
520  end select
521  end if
522  end subroutine rhd_tc_handle_small_e
523 
524  ! fill in tc_fluid fields from namelist
525  subroutine tc_params_read_rhd(fl)
527  use mod_global_parameters, only: unitpar
528  type(tc_fluid), intent(inout) :: fl
529  integer :: n
530  logical :: tc_saturate=.false.
531  double precision :: tc_k_para=0d0
532 
533  namelist /tc_list/ tc_saturate, tc_k_para
534 
535  do n = 1, size(par_files)
536  open(unitpar, file=trim(par_files(n)), status="old")
537  read(unitpar, tc_list, end=111)
538 111 close(unitpar)
539  end do
540  fl%tc_saturate = tc_saturate
541  fl%tc_k_para = tc_k_para
542 
543  end subroutine tc_params_read_rhd
544 
545  subroutine rhd_get_rho(w,x,ixI^L,ixO^L,rho)
547  integer, intent(in) :: ixI^L, ixO^L
548  double precision, intent(in) :: w(ixI^S,1:nw),x(ixI^S,1:ndim)
549  double precision, intent(out) :: rho(ixI^S)
550 
551  rho(ixo^s) = w(ixo^s,rho_)
552 
553  end subroutine rhd_get_rho
554 
555 !!end th cond
556 !!rad cool
557  subroutine rc_params_read(fl)
559  use mod_constants, only: bigdouble
560  use mod_basic_types, only: std_len
561  type(rc_fluid), intent(inout) :: fl
562  integer :: n
563  ! list parameters
564  integer :: ncool = 4000
565  double precision :: cfrac=0.1d0
566 
567  !> Name of cooling curve
568  character(len=std_len) :: coolcurve='JCcorona'
569 
570  !> Name of cooling method
571  character(len=std_len) :: coolmethod='exact'
572 
573  !> Fixed temperature not lower than tlow
574  logical :: Tfix=.false.
575 
576  !> Lower limit of temperature
577  double precision :: tlow=bigdouble
578 
579  !> Add cooling source in a split way (.true.) or un-split way (.false.)
580  logical :: rc_split=.false.
581 
582 
583  namelist /rc_list/ coolcurve, coolmethod, ncool, cfrac, tlow, tfix, rc_split
584 
585  do n = 1, size(par_files)
586  open(unitpar, file=trim(par_files(n)), status="old")
587  read(unitpar, rc_list, end=111)
588 111 close(unitpar)
589  end do
590 
591  fl%ncool=ncool
592  fl%coolcurve=coolcurve
593  fl%coolmethod=coolmethod
594  fl%tlow=tlow
595  fl%Tfix=tfix
596  fl%rc_split=rc_split
597  fl%cfrac=cfrac
598  end subroutine rc_params_read
599 !! end rad cool
600 
601  subroutine rhd_check_params
603  use mod_dust, only: dust_check_params
604 
605  if (.not. rhd_energy .and. rhd_pressure == 'adiabatic') then
606  if (rhd_gamma <= 0.0d0) call mpistop ("Error: rhd_gamma <= 0")
607  if (rhd_adiab < 0.0d0) call mpistop ("Error: rhd_adiab < 0")
609  elseif (rhd_pressure == 'Tcond') then
610  small_pressure = smalldouble
611  else
612  if (rhd_gamma <= 0.0d0 .or. rhd_gamma == 1.0d0) &
613  call mpistop ("Error: rhd_gamma <= 0 or rhd_gamma == 1.0")
614  small_e = small_pressure/(rhd_gamma - 1.0d0)
615  end if
616 
618 
619  if (rhd_dust) call dust_check_params()
620 
621  ! if (rhd_radiation_diffusion .and. (.not. use_imex_scheme) ) &
622  if (rhd_radiation_diffusion .and. (.not. use_imex_scheme) .and. ((rhd_radiation_formalism .eq. 'fld') .or. (rhd_radiation_formalism .eq. 'afld')) ) &
623  call mpistop("Use an IMEX scheme when doing FLD")
624 
625  if (use_multigrid) call rhd_set_mg_bounds()
626 
627  end subroutine rhd_check_params
628 
629  !> Set the boundaries for the diffusion of E
630  subroutine rhd_set_mg_bounds
633  use mod_usr_methods
634 
635  integer :: ib
636 
637  ! Set boundary conditions for the multigrid solver
638  do ib = 1, 2*ndim
639  select case (typeboundary(r_e, ib))
640  case (bc_symm)
641  ! d/dx u = 0
642  mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
643  mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
644  case (bc_asymm)
645  ! u = 0
646  mg%bc(ib, mg_iphi)%bc_type = mg_bc_dirichlet
647  mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
648  case (bc_cont)
649  ! d/dx u = 0
650  ! mg%bc(iB, mg_iphi)%bc_type = mg_bc_continuous
651  mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
652  mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
653  case (bc_periodic)
654  ! Nothing to do here
655  case (bc_noinflow)
656  call usr_special_mg_bc(ib)
657  case (bc_special)
658  call usr_special_mg_bc(ib)
659  case default
660  call mpistop("divE_multigrid warning: unknown b.c. ")
661  end select
662  end do
663  end subroutine rhd_set_mg_bounds
664 
667  double precision :: mp,kB
668  double precision :: a,b
669  ! Derive scaling units
670  if(si_unit) then
671  mp=mp_si
672  kb=kb_si
673  else
674  mp=mp_cgs
675  kb=kb_cgs
676  end if
677  if(eq_state_units) then
678  a = 1d0 + 4d0 * he_abundance
679  if(rhd_partial_ionization) then
680  b = 2.d0+3.d0*he_abundance
681  else
682  b = 1d0 + h_ion_fr + he_abundance*(he_ion_fr*(he_ion_fr2 + 1d0)+1d0)
683  end if
684  rr = 1d0
685  else
686  a = 1d0
687  b = 1d0
688  rr = (1d0 + h_ion_fr + he_abundance*(he_ion_fr*(he_ion_fr2 + 1d0)+1d0))/(1d0 + 4d0 * he_abundance)
689  end if
690  if(unit_density/=1.d0) then
692  else
693  ! unit of numberdensity is independent by default
695  end if
696  if(unit_velocity/=1.d0) then
699  else if(unit_pressure/=1.d0) then
702  else
703  ! unit of temperature is independent by default
706  end if
707  if(unit_time/=1.d0) then
709  else
710  ! unit of length is independent by default
712  end if
713 
714  !> Units for radiative flux and opacity
717 
718  end subroutine rhd_physical_units
719 
720  !> Returns logical argument flag where values are ok
721  subroutine rhd_check_w(primitive, ixI^L, ixO^L, w, flag)
723  use mod_dust, only: dust_check_w
724 
725  logical, intent(in) :: primitive
726  integer, intent(in) :: ixi^l, ixo^l
727  double precision, intent(in) :: w(ixi^s, nw)
728  logical, intent(inout) :: flag(ixi^s,1:nw)
729  double precision :: tmp(ixi^s)
730 
731  flag=.false.
732 
733  if (rhd_energy) then
734  if (primitive) then
735  where(w(ixo^s, e_) < small_pressure) flag(ixo^s,e_) = .true.
736  else
737  tmp(ixo^s) = (rhd_gamma - 1.0d0)*(w(ixo^s, e_) - &
738  rhd_kin_en(w, ixi^l, ixo^l))
739  where(tmp(ixo^s) < small_pressure) flag(ixo^s,e_) = .true.
740  endif
741  end if
742 
743  where(w(ixo^s, rho_) < small_density) flag(ixo^s,rho_) = .true.
744 
745  where(w(ixo^s, r_e) < small_r_e) flag(ixo^s,r_e) = .true.
746 
747  if(rhd_dust) call dust_check_w(ixi^l,ixo^l,w,flag)
748 
749  end subroutine rhd_check_w
750 
751  !> Transform primitive variables into conservative ones
752  subroutine rhd_to_conserved(ixI^L, ixO^L, w, x)
754  use mod_dust, only: dust_to_conserved
755  integer, intent(in) :: ixi^l, ixo^l
756  double precision, intent(inout) :: w(ixi^s, nw)
757  double precision, intent(in) :: x(ixi^s, 1:ndim)
758  double precision :: invgam
759  integer :: idir, itr
760 
761  !!if (fix_small_values) then
762  !! call rhd_handle_small_values(.true., w, x, ixI^L, ixO^L, 'rhd_to_conserved')
763  !!end if
764 
765  if (rhd_energy) then
766  invgam = 1.d0/(rhd_gamma - 1.0d0)
767  ! Calculate total energy from pressure and kinetic energy
768  w(ixo^s, e_) = w(ixo^s, e_) * invgam + &
769  0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) * w(ixo^s, rho_)
770  end if
771 
772  ! Convert velocity to momentum
773  do idir = 1, ndir
774  w(ixo^s, mom(idir)) = w(ixo^s, rho_) * w(ixo^s, mom(idir))
775  end do
776 
777  if (rhd_dust) then
778  call dust_to_conserved(ixi^l, ixo^l, w, x)
779  end if
780 
781  end subroutine rhd_to_conserved
782 
783  !> Transform conservative variables into primitive ones
784  subroutine rhd_to_primitive(ixI^L, ixO^L, w, x)
786  use mod_dust, only: dust_to_primitive
787  integer, intent(in) :: ixi^l, ixo^l
788  double precision, intent(inout) :: w(ixi^s, nw)
789  double precision, intent(in) :: x(ixi^s, 1:ndim)
790  integer :: itr, idir
791  double precision :: inv_rho(ixo^s)
792 
793  if (fix_small_values) then
794  call rhd_handle_small_values(.false., w, x, ixi^l, ixo^l, 'rhd_to_primitive')
795  end if
796 
797  inv_rho = 1.0d0 / w(ixo^s, rho_)
798 
799  if (rhd_energy) then
800  ! Compute pressure
801  w(ixo^s, e_) = (rhd_gamma - 1.0d0) * (w(ixo^s, e_) - &
802  rhd_kin_en(w, ixi^l, ixo^l, inv_rho))
803  end if
804 
805  ! Convert momentum to velocity
806  do idir = 1, ndir
807  w(ixo^s, mom(idir)) = w(ixo^s, mom(idir)) * inv_rho
808  end do
809 
810  ! Convert dust momentum to dust velocity
811  if (rhd_dust) then
812  call dust_to_primitive(ixi^l, ixo^l, w, x)
813  end if
814 
815  end subroutine rhd_to_primitive
816 
817  !> Transform internal energy to total energy
818  subroutine rhd_ei_to_e(ixI^L,ixO^L,w,x)
820  integer, intent(in) :: ixI^L, ixO^L
821  double precision, intent(inout) :: w(ixI^S, nw)
822  double precision, intent(in) :: x(ixI^S, 1:ndim)
823 
824  ! Calculate total energy from internal and kinetic energy
825  w(ixo^s,e_)=w(ixo^s,e_)&
826  +rhd_kin_en(w,ixi^l,ixo^l)
827 
828  end subroutine rhd_ei_to_e
829 
830  !> Transform total energy to internal energy
831  subroutine rhd_e_to_ei(ixI^L,ixO^L,w,x)
833  integer, intent(in) :: ixI^L, ixO^L
834  double precision, intent(inout) :: w(ixI^S, nw)
835  double precision, intent(in) :: x(ixI^S, 1:ndim)
836 
837  ! Calculate ei = e - ek
838  w(ixo^s,e_)=w(ixo^s,e_)&
839  -rhd_kin_en(w,ixi^l,ixo^l)
840 
841  end subroutine rhd_e_to_ei
842 
843  subroutine e_to_rhos(ixI^L, ixO^L, w, x)
845 
846  integer, intent(in) :: ixI^L, ixO^L
847  double precision :: w(ixI^S, nw)
848  double precision, intent(in) :: x(ixI^S, 1:ndim)
849 
850  if (rhd_energy) then
851  w(ixo^s, e_) = (rhd_gamma - 1.0d0) * w(ixo^s, rho_)**(1.0d0 - rhd_gamma) * &
852  (w(ixo^s, e_) - rhd_kin_en(w, ixi^l, ixo^l))
853  else
854  call mpistop("energy from entropy can not be used with -eos = iso !")
855  end if
856  end subroutine e_to_rhos
857 
858  subroutine rhos_to_e(ixI^L, ixO^L, w, x)
860 
861  integer, intent(in) :: ixI^L, ixO^L
862  double precision :: w(ixI^S, nw)
863  double precision, intent(in) :: x(ixI^S, 1:ndim)
864 
865  if (rhd_energy) then
866  w(ixo^s, e_) = w(ixo^s, rho_)**(rhd_gamma - 1.0d0) * w(ixo^s, e_) &
867  / (rhd_gamma - 1.0d0) + rhd_kin_en(w, ixi^l, ixo^l)
868  else
869  call mpistop("entropy from energy can not be used with -eos = iso !")
870  end if
871  end subroutine rhos_to_e
872 
873  !> Calculate v_i = m_i / rho within ixO^L
874  subroutine rhd_get_v(w, x, ixI^L, ixO^L, idim, v)
876  integer, intent(in) :: ixI^L, ixO^L, idim
877  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:ndim)
878  double precision, intent(out) :: v(ixI^S)
879 
880  v(ixo^s) = w(ixo^s, mom(idim)) / w(ixo^s, rho_)
881  end subroutine rhd_get_v
882 
883  !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
884  subroutine rhd_get_cmax(w, x, ixI^L, ixO^L, idim, cmax)
886  use mod_dust, only: dust_get_cmax
887 
888  integer, intent(in) :: ixI^L, ixO^L, idim
889  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:ndim)
890  double precision, intent(inout) :: cmax(ixI^S)
891  double precision :: csound(ixI^S)
892  double precision :: v(ixI^S)
893 
894  call rhd_get_v(w, x, ixi^l, ixo^l, idim, v)
895  call rhd_get_csound2(w,x,ixi^l,ixo^l,csound)
896  csound(ixo^s) = dsqrt(csound(ixo^s))
897 
898  cmax(ixo^s) = dabs(v(ixo^s))+csound(ixo^s)
899 
900  if (rhd_dust) then
901  call dust_get_cmax(w, x, ixi^l, ixo^l, idim, cmax)
902  end if
903  end subroutine rhd_get_cmax
904 
905  subroutine rhd_get_a2max(w,x,ixI^L,ixO^L,a2max)
907 
908  integer, intent(in) :: ixI^L, ixO^L
909  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
910  double precision, intent(inout) :: a2max(ndim)
911  double precision :: a2(ixI^S,ndim,nw)
912  integer :: gxO^L,hxO^L,jxO^L,kxO^L,i,j
913 
914  a2=zero
915  do i = 1,ndim
916  !> 4th order
917  hxo^l=ixo^l-kr(i,^d);
918  gxo^l=hxo^l-kr(i,^d);
919  jxo^l=ixo^l+kr(i,^d);
920  kxo^l=jxo^l+kr(i,^d);
921  a2(ixo^s,i,1:nw)=dabs(-w(kxo^s,1:nw)+16.d0*w(jxo^s,1:nw)&
922  -30.d0*w(ixo^s,1:nw)+16.d0*w(hxo^s,1:nw)-w(gxo^s,1:nw))
923  a2max(i)=maxval(a2(ixo^s,i,1:nw))/12.d0/dxlevel(i)**2
924  end do
925  end subroutine rhd_get_a2max
926 
927  !> get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
928  subroutine rhd_get_tcutoff(ixI^L,ixO^L,w,x,tco_local,Tmax_local)
930  integer, intent(in) :: ixI^L,ixO^L
931  double precision, intent(in) :: x(ixI^S,1:ndim)
932  double precision, intent(inout) :: w(ixI^S,1:nw)
933  double precision, intent(out) :: tco_local, Tmax_local
934 
935  double precision, parameter :: trac_delta=0.25d0
936  double precision :: tmp1(ixI^S),Te(ixI^S),lts(ixI^S)
937  double precision :: ltr(ixI^S),ltrc,ltrp,tcoff(ixI^S)
938  integer :: jxO^L,hxO^L
939  integer :: jxP^L,hxP^L,ixP^L
940  logical :: lrlt(ixI^S)
941 
942  {^ifoned
943  call rhd_get_temperature_from_etot(w,x,ixi^l,ixi^l,te)
944 
945  tco_local=zero
946  tmax_local=maxval(te(ixo^s))
947  select case(rhd_trac_type)
948  case(0)
949  w(ixi^s,tcoff_)=3.d5/unit_temperature
950  case(1)
951  hxo^l=ixo^l-1;
952  jxo^l=ixo^l+1;
953  lts(ixo^s)=0.5d0*dabs(te(jxo^s)-te(hxo^s))/te(ixo^s)
954  lrlt=.false.
955  where(lts(ixo^s) > trac_delta)
956  lrlt(ixo^s)=.true.
957  end where
958  if(any(lrlt(ixo^s))) then
959  tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
960  end if
961  case(2)
962  !> iijima et al. 2021, LTRAC method
963  ltrc=1.5d0
964  ltrp=2.5d0
965  ixp^l=ixo^l^ladd1;
966  hxo^l=ixo^l-1;
967  jxo^l=ixo^l+1;
968  hxp^l=ixp^l-1;
969  jxp^l=ixp^l+1;
970  lts(ixp^s)=0.5d0*abs(te(jxp^s)-te(hxp^s))/te(ixp^s)
971  ltr(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
972  w(ixo^s,tcoff_)=te(ixo^s)*&
973  (0.25*(ltr(jxo^s)+two*ltr(ixo^s)+ltr(hxo^s)))**0.4d0
974  case default
975  call mpistop("mrhd_trac_type not allowed for 1D simulation")
976  end select
977  }
978  end subroutine rhd_get_tcutoff
979 
980  !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
981  subroutine rhd_get_cbounds(wLC, wRC, wLp, wRp, x, ixI^L, ixO^L, idim,Hspeed,cmax, cmin)
983  use mod_dust, only: dust_get_cmax
984  use mod_variables
985 
986  integer, intent(in) :: ixI^L, ixO^L, idim
987  ! conservative left and right status
988  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S, nw)
989  ! primitive left and right status
990  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S, nw)
991  double precision, intent(in) :: x(ixI^S, 1:ndim)
992  double precision, intent(inout) :: cmax(ixI^S,1:number_species)
993  double precision, intent(inout), optional :: cmin(ixI^S,1:number_species)
994  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
995 
996  double precision :: wmean(ixI^S,nw)
997  double precision, dimension(ixI^S) :: umean, dmean, csoundL, csoundR, tmp1,tmp2,tmp3
998  integer :: ix^D
999 
1000  select case(boundspeed)
1001  case (1)
1002  ! This implements formula (10.52) from "Riemann Solvers and Numerical
1003  ! Methods for Fluid Dynamics" by Toro.
1004 
1005  tmp1(ixo^s)=dsqrt(wlp(ixo^s,rho_))
1006  tmp2(ixo^s)=dsqrt(wrp(ixo^s,rho_))
1007  tmp3(ixo^s)=1.d0/(dsqrt(wlp(ixo^s,rho_))+dsqrt(wrp(ixo^s,rho_)))
1008  umean(ixo^s)=(wlp(ixo^s,mom(idim))*tmp1(ixo^s)+wrp(ixo^s,mom(idim))*tmp2(ixo^s))*tmp3(ixo^s)
1009 
1010  if(rhd_energy) then
1011  csoundl(ixo^s)=rhd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
1012  csoundr(ixo^s)=rhd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
1013  else
1014  select case (rhd_pressure)
1015  case ('Trad')
1016  csoundl(ixo^s)=rhd_gamma*kbmpmua4*wlp(ixo^s,r_e)**(1.d0/4)
1017  csoundr(ixo^s)=rhd_gamma*kbmpmua4*wrp(ixo^s,r_e)**(1.d0/4)
1018  case ('adiabatic')
1019  csoundl(ixo^s)=rhd_gamma*rhd_adiab*wlp(ixo^s,rho_)**(rhd_gamma-one)
1020  csoundr(ixo^s)=rhd_gamma*rhd_adiab*wrp(ixo^s,rho_)**(rhd_gamma-one)
1021  end select
1022  end if
1023 
1024  dmean(ixo^s) = (tmp1(ixo^s)*csoundl(ixo^s)+tmp2(ixo^s)*csoundr(ixo^s)) * &
1025  tmp3(ixo^s) + 0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2 * &
1026  (wrp(ixo^s,mom(idim))-wlp(ixo^s,mom(idim)))**2
1027 
1028  dmean(ixo^s)=dsqrt(dmean(ixo^s))
1029  if(present(cmin)) then
1030  cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
1031  cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
1032  if(h_correction) then
1033  {do ix^db=ixomin^db,ixomax^db\}
1034  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1035  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1036  {end do\}
1037  end if
1038  else
1039  cmax(ixo^s,1)=dabs(umean(ixo^s))+dmean(ixo^s)
1040  end if
1041 
1042  if (rhd_dust) then
1043  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1044  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1045  end if
1046 
1047  case (2)
1048  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1049  tmp1(ixo^s)=wmean(ixo^s,mom(idim))/wmean(ixo^s,rho_)
1050  call rhd_get_csound2(wmean,x,ixi^l,ixo^l,csoundr)
1051  csoundr(ixo^s) = dsqrt(csoundr(ixo^s))
1052 
1053  if(present(cmin)) then
1054  cmax(ixo^s,1)=max(tmp1(ixo^s)+csoundr(ixo^s),zero)
1055  cmin(ixo^s,1)=min(tmp1(ixo^s)-csoundr(ixo^s),zero)
1056  if(h_correction) then
1057  {do ix^db=ixomin^db,ixomax^db\}
1058  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1059  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1060  {end do\}
1061  end if
1062  else
1063  cmax(ixo^s,1)=dabs(tmp1(ixo^s))+csoundr(ixo^s)
1064  end if
1065 
1066  if (rhd_dust) then
1067  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1068  end if
1069  case (3)
1070  ! Miyoshi 2005 JCP 208, 315 equation (67)
1071  if(rhd_energy) then
1072  csoundl(ixo^s)=rhd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
1073  csoundr(ixo^s)=rhd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
1074  else
1075  select case (rhd_pressure)
1076  case ('Trad')
1077  csoundl(ixo^s)=rhd_gamma*kbmpmua4*wlp(ixo^s,r_e)**(1.d0/4)
1078  csoundr(ixo^s)=rhd_gamma*kbmpmua4*wrp(ixo^s,r_e)**(1.d0/4)
1079  case ('adiabatic')
1080  csoundl(ixo^s)=rhd_gamma*rhd_adiab*wlp(ixo^s,rho_)**(rhd_gamma-one)
1081  csoundr(ixo^s)=rhd_gamma*rhd_adiab*wrp(ixo^s,rho_)**(rhd_gamma-one)
1082  end select
1083  end if
1084  csoundl(ixo^s)=max(dsqrt(csoundl(ixo^s)),dsqrt(csoundr(ixo^s)))
1085  if(present(cmin)) then
1086  cmin(ixo^s,1)=min(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))-csoundl(ixo^s)
1087  cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
1088  if(h_correction) then
1089  {do ix^db=ixomin^db,ixomax^db\}
1090  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1091  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1092  {end do\}
1093  end if
1094  else
1095  cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
1096  end if
1097  if (rhd_dust) then
1098  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1099  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1100  end if
1101  end select
1102 
1103  end subroutine rhd_get_cbounds
1104 
1105  !> Calculate the square of the thermal sound speed csound2 within ixO^L.
1106  !> csound2=gamma*p/rho
1107  subroutine rhd_get_csound2(w,x,ixI^L,ixO^L,csound2)
1109  integer, intent(in) :: ixi^l, ixo^l
1110  double precision, intent(in) :: w(ixi^s,nw)
1111  double precision, intent(in) :: x(ixi^s,1:ndim)
1112  double precision, intent(out) :: csound2(ixi^s)
1113 
1114  call rhd_get_ptot(w,x,ixi^l,ixo^l,csound2)
1115  csound2(ixo^s)=max(rhd_gamma,4.d0/3.d0)*csound2(ixo^s)/w(ixo^s,rho_)
1116  !> Turner & Stone 2001
1117 
1118  end subroutine rhd_get_csound2
1119 
1120  !> Calculate thermal pressure=(gamma-1)*(e-0.5*m**2/rho) within ixO^L
1121  subroutine rhd_get_pthermal(w, x, ixI^L, ixO^L, pth)
1125 
1126  integer, intent(in) :: ixi^l, ixo^l
1127  double precision, intent(in) :: w(ixi^s, 1:nw)
1128  double precision, intent(in) :: x(ixi^s, 1:ndim)
1129  double precision, intent(out):: pth(ixi^s)
1130  integer :: iw, ix^d
1131 
1132  if (rhd_energy) then
1133  pth(ixi^s) = (rhd_gamma - 1.d0) * (w(ixi^s, e_) - &
1134  0.5d0 * sum(w(ixi^s, mom(:))**2, dim=ndim+1) / w(ixi^s, rho_))
1135  else
1136  if (.not. associated(usr_set_pthermal)) then
1137  select case (rhd_pressure)
1138  case ('Trad')
1139  pth(ixi^s) = (w(ixi^s,r_e)*unit_pressure/const_rad_a)**0.25d0&
1140  /unit_temperature*w(ixi^s, rho_)
1141  case ('adiabatic')
1142  pth(ixi^s) = rhd_adiab * w(ixi^s, rho_)**rhd_gamma
1143  case ('Tcond') !> Thermal conduction?!
1144  pth(ixi^s) = (rhd_gamma-1.d0)*w(ixi^s,r_e)
1145  case default
1146  call mpistop('rhd_pressure unknown, use Trad or adiabatic')
1147  end select
1148  else
1149  call usr_set_pthermal(w,x,ixi^l,ixo^l,pth)
1150  end if
1151  end if
1152 
1153  if (fix_small_values) then
1154  {do ix^db= ixo^lim^db\}
1155  if(pth(ix^d)<small_pressure) then
1156  pth(ix^d)=small_pressure
1157  endif
1158  {enddo^d&\}
1159  else if (check_small_values) then
1160  {do ix^db= ixo^lim^db\}
1161  if(pth(ix^d)<small_pressure) then
1162  write(*,*) "Error: small value of gas pressure",pth(ix^d),&
1163  " encountered when call rhd_get_pthermal"
1164  write(*,*) "Iteration: ", it, " Time: ", global_time
1165  write(*,*) "Location: ", x(ix^d,:)
1166  write(*,*) "Cell number: ", ix^d
1167  do iw=1,nw
1168  write(*,*) trim(cons_wnames(iw)),": ",w(ix^d,iw)
1169  end do
1170  ! use erroneous arithmetic operation to crash the run
1171  if(trace_small_values) write(*,*) dsqrt(pth(ix^d)-bigdouble)
1172  write(*,*) "Saving status at the previous time step"
1173  crash=.true.
1174  end if
1175  {enddo^d&\}
1176  end if
1177 
1178  end subroutine rhd_get_pthermal
1179 
1180  !> Calculate radiation pressure within ixO^L
1181  subroutine rhd_get_pradiation(w, x, ixI^L, ixO^L, prad)
1183  use mod_fld
1184  use mod_afld
1185 
1186  integer, intent(in) :: ixi^l, ixo^l
1187  double precision, intent(in) :: w(ixi^s, 1:nw)
1188  double precision, intent(in) :: x(ixi^s, 1:ndim)
1189  double precision, intent(out):: prad(ixo^s, 1:ndim, 1:ndim)
1190 
1191  select case (rhd_radiation_formalism)
1192  case('fld')
1193  call fld_get_radpress(w, x, ixi^l, ixo^l, prad)
1194  case('afld')
1195  call afld_get_radpress(w, x, ixi^l, ixo^l, prad)
1196  case default
1197  call mpistop('Radiation formalism unknown')
1198  end select
1199  end subroutine rhd_get_pradiation
1200 
1201  !> calculates the sum of the gas pressure and max Prad tensor element
1202  subroutine rhd_get_ptot(w, x, ixI^L, ixO^L, ptot)
1204 
1205  integer, intent(in) :: ixi^l, ixo^l
1206  double precision, intent(in) :: w(ixi^s, 1:nw)
1207  double precision, intent(in) :: x(ixi^s, 1:ndim)
1208  double precision :: pth(ixi^s)
1209  double precision :: prad_tensor(ixo^s, 1:ndim, 1:ndim)
1210  double precision :: prad_max(ixo^s)
1211  double precision, intent(out):: ptot(ixi^s)
1212  integer :: ix^d
1213 
1214  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1215  call rhd_get_pradiation(w, x, ixi^l, ixo^l, prad_tensor)
1216 
1217  {do ix^d = ixomin^d,ixomax^d\}
1218  prad_max(ix^d) = maxval(prad_tensor(ix^d,:,:))
1219  {enddo\}
1220 
1221  !> filter cmax
1222  if (radio_acoustic_filter) then
1223  call rhd_radio_acoustic_filter(x, ixi^l, ixo^l, prad_max)
1224  endif
1225 
1226  ptot(ixo^s) = pth(ixo^s) + prad_max(ixo^s)
1227 
1228  end subroutine rhd_get_ptot
1229 
1230  !> Filter peaks in cmax due to radiation energy density, used for debugging
1231  subroutine rhd_radio_acoustic_filter(x, ixI^L, ixO^L, prad_max)
1233 
1234  integer, intent(in) :: ixI^L, ixO^L
1235  double precision, intent(in) :: x(ixI^S, 1:ndim)
1236  double precision, intent(inout) :: prad_max(ixO^S)
1237 
1238  double precision :: tmp_prad(ixI^S)
1239  integer :: ix^D, filter, idim
1240 
1241  if (size_ra_filter .lt. 1) call mpistop("ra filter of size < 1 makes no sense")
1242  if (size_ra_filter .gt. nghostcells) call mpistop("ra filter of size < nghostcells makes no sense")
1243 
1244  tmp_prad(ixi^s) = zero
1245  tmp_prad(ixo^s) = prad_max(ixo^s)
1246 
1247  do filter = 1,size_ra_filter
1248  do idim = 1,ndim
1249  ! {do ix^D = ixOmin^D+filter,ixOmax^D-filter\}
1250  {do ix^d = ixomin^d,ixomax^d\}
1251  prad_max(ix^d) = min(tmp_prad(ix^d),tmp_prad(ix^d+filter*kr(idim,^d)))
1252  prad_max(ix^d) = min(tmp_prad(ix^d),tmp_prad(ix^d-filter*kr(idim,^d)))
1253  {enddo\}
1254  enddo
1255  enddo
1256  end subroutine rhd_radio_acoustic_filter
1257 
1258  !> Calculate temperature=p/rho when in e_ the total energy is stored
1259  subroutine rhd_get_temperature_from_etot(w, x, ixI^L, ixO^L, res)
1261  integer, intent(in) :: ixI^L, ixO^L
1262  double precision, intent(in) :: w(ixI^S, 1:nw)
1263  double precision, intent(in) :: x(ixI^S, 1:ndim)
1264  double precision, intent(out):: res(ixI^S)
1265 
1266  double precision :: R(ixI^S)
1267 
1268  call rhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1269  call rhd_get_pthermal(w, x, ixi^l, ixo^l, res)
1270  res(ixo^s)=res(ixo^s)/(r(ixo^s)*w(ixo^s,rho_))
1271  end subroutine rhd_get_temperature_from_etot
1272 
1273 
1274  !> Calculate temperature=p/rho when in e_ the internal energy is stored
1275  subroutine rhd_get_temperature_from_eint(w, x, ixI^L, ixO^L, res)
1277  integer, intent(in) :: ixI^L, ixO^L
1278  double precision, intent(in) :: w(ixI^S, 1:nw)
1279  double precision, intent(in) :: x(ixI^S, 1:ndim)
1280  double precision, intent(out):: res(ixI^S)
1281  double precision :: R(ixI^S)
1282 
1283  call rhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1284  res(ixo^s) = (rhd_gamma - 1.0d0) * w(ixo^s, e_)/(w(ixo^s,rho_)*r(ixo^s))
1285  end subroutine rhd_get_temperature_from_eint
1286 
1287  !> Calculates gas temperature
1288  subroutine rhd_get_tgas(w, x, ixI^L, ixO^L, tgas)
1290 
1291  integer, intent(in) :: ixi^l, ixo^l
1292  double precision, intent(in) :: w(ixi^s, 1:nw)
1293  double precision, intent(in) :: x(ixi^s, 1:ndim)
1294  double precision :: pth(ixi^s)
1295  double precision, intent(out):: tgas(ixi^s)
1296 
1297  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1298  tgas(ixi^s) = pth(ixi^s)/w(ixi^s,rho_)
1299 
1300  end subroutine rhd_get_tgas
1301 
1302  !> Calculates radiation temperature
1303  subroutine rhd_get_trad(w, x, ixI^L, ixO^L, trad)
1305  use mod_constants
1306 
1307  integer, intent(in) :: ixi^l, ixo^l
1308  double precision, intent(in) :: w(ixi^s, 1:nw)
1309  double precision, intent(in) :: x(ixi^s, 1:ndim)
1310  double precision, intent(out):: trad(ixi^s)
1311 
1312  trad(ixi^s) = (w(ixi^s,r_e)*unit_pressure&
1313  /const_rad_a)**(1.d0/4.d0)/unit_temperature
1314 
1315  end subroutine rhd_get_trad
1316 
1317 
1318  !these are very similar to the subroutines without 1, used in mod_thermal_conductivity
1319  !but no check on whether energy variable is present
1320  subroutine rhd_ei_to_e1(ixI^L,ixO^L,w,x)
1322  integer, intent(in) :: ixI^L, ixO^L
1323  double precision, intent(inout) :: w(ixI^S, nw)
1324  double precision, intent(in) :: x(ixI^S, 1:ndim)
1325 
1326  ! Calculate total energy from internal and kinetic energy
1327  w(ixo^s,e_)=w(ixo^s,e_)&
1328  +rhd_kin_en(w,ixi^l,ixo^l)
1329 
1330  end subroutine rhd_ei_to_e1
1331 
1332  !> Transform total energy to internal energy
1333  !but no check on whether energy variable is present
1334  subroutine rhd_e_to_ei1(ixI^L,ixO^L,w,x)
1336  integer, intent(in) :: ixI^L, ixO^L
1337  double precision, intent(inout) :: w(ixI^S, nw)
1338  double precision, intent(in) :: x(ixI^S, 1:ndim)
1339 
1340  ! Calculate ei = e - ek
1341  w(ixo^s,e_)=w(ixo^s,e_)&
1342  -rhd_kin_en(w,ixi^l,ixo^l)
1343 
1344  end subroutine rhd_e_to_ei1
1345 
1346  ! Calculate flux f_idim[iw]
1347  subroutine rhd_get_flux_cons(w, x, ixI^L, ixO^L, idim, f)
1349  use mod_dust, only: dust_get_flux
1350 
1351  integer, intent(in) :: ixI^L, ixO^L, idim
1352  double precision, intent(in) :: w(ixI^S, 1:nw), x(ixI^S, 1:ndim)
1353  double precision, intent(out) :: f(ixI^S, nwflux)
1354  double precision :: pth(ixI^S), v(ixI^S),frame_vel(ixI^S)
1355  integer :: idir, itr
1356 
1357  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1358  call rhd_get_v(w, x, ixi^l, ixo^l, idim, v)
1359 
1360  f(ixo^s, rho_) = v(ixo^s) * w(ixo^s, rho_)
1361 
1362  ! Momentum flux is v_i*m_i, +p in direction idim
1363  do idir = 1, ndir
1364  f(ixo^s, mom(idir)) = v(ixo^s) * w(ixo^s, mom(idir))
1365  end do
1366 
1367  f(ixo^s, mom(idim)) = f(ixo^s, mom(idim)) + pth(ixo^s)
1368 
1369  if(rhd_energy) then
1370  ! Energy flux is v_i*(e + p)
1371  f(ixo^s, e_) = v(ixo^s) * (w(ixo^s, e_) + pth(ixo^s))
1372  end if
1373 
1374  if (rhd_radiation_advection) then
1375  f(ixo^s, r_e) = v(ixo^s) * w(ixo^s,r_e)
1376  else
1377  f(ixo^s, r_e) = zero
1378  endif
1379 
1380  do itr = 1, rhd_n_tracer
1381  f(ixo^s, tracer(itr)) = v(ixo^s) * w(ixo^s, tracer(itr))
1382  end do
1383 
1384  ! Dust fluxes
1385  if (rhd_dust) then
1386  call dust_get_flux(w, x, ixi^l, ixo^l, idim, f)
1387  end if
1388 
1389  end subroutine rhd_get_flux_cons
1390 
1391  ! Calculate flux f_idim[iw]
1392  subroutine rhd_get_flux(wC, w, x, ixI^L, ixO^L, idim, f)
1394  use mod_dust, only: dust_get_flux_prim
1395  use mod_viscosity, only: visc_get_flux_prim ! viscInDiv
1396 
1397  integer, intent(in) :: ixI^L, ixO^L, idim
1398  ! conservative w
1399  double precision, intent(in) :: wC(ixI^S, 1:nw)
1400  ! primitive w
1401  double precision, intent(in) :: w(ixI^S, 1:nw)
1402  double precision, intent(in) :: x(ixI^S, 1:ndim)
1403  double precision, intent(out) :: f(ixI^S, nwflux)
1404  double precision :: pth(ixI^S),frame_vel(ixI^S)
1405  integer :: idir, itr
1406 
1407  if (rhd_energy) then
1408  pth(ixo^s) = w(ixo^s,p_)
1409  else
1410  call rhd_get_pthermal(wc, x, ixi^l, ixo^l, pth)
1411  end if
1412 
1413  f(ixo^s, rho_) = w(ixo^s,mom(idim)) * w(ixo^s, rho_)
1414 
1415  ! Momentum flux is v_i*m_i, +p in direction idim
1416  do idir = 1, ndir
1417  f(ixo^s, mom(idir)) = w(ixo^s,mom(idim)) * wc(ixo^s, mom(idir))
1418  end do
1419 
1420  f(ixo^s, mom(idim)) = f(ixo^s, mom(idim)) + pth(ixo^s)
1421 
1422  if(rhd_energy) then
1423  ! Energy flux is v_i*(e + p)
1424  f(ixo^s, e_) = w(ixo^s,mom(idim)) * (wc(ixo^s, e_) + w(ixo^s,p_))
1425  end if
1426 
1427  if (rhd_radiation_advection) then
1428  f(ixo^s, r_e) = w(ixo^s,mom(idim)) * wc(ixo^s,r_e)
1429  else
1430  f(ixo^s, r_e) = zero
1431  endif
1432 
1433  do itr = 1, rhd_n_tracer
1434  f(ixo^s, tracer(itr)) = w(ixo^s,mom(idim)) * w(ixo^s, tracer(itr))
1435  end do
1436 
1437  ! Dust fluxes
1438  if (rhd_dust) then
1439  call dust_get_flux_prim(w, x, ixi^l, ixo^l, idim, f)
1440  end if
1441 
1442  ! Viscosity fluxes - viscInDiv
1443  if (rhd_viscosity) then
1444  call visc_get_flux_prim(w, x, ixi^l, ixo^l, idim, f, rhd_energy)
1445  endif
1446 
1447  end subroutine rhd_get_flux
1448 
1449  !> Add geometrical source terms to w
1450  !>
1451  !> Notice that the expressions of the geometrical terms depend only on ndir,
1452  !> not ndim. Eg, they are the same in 2.5D and in 3D, for any geometry.
1453  !>
1454  subroutine rhd_add_source_geom(qdt, dtfactor, ixI^L, ixO^L, wCT, w, x)
1456  use mod_usr_methods, only: usr_set_surface
1457  use mod_viscosity, only: visc_add_source_geom ! viscInDiv
1460  use mod_geometry
1461  integer, intent(in) :: ixI^L, ixO^L
1462  double precision, intent(in) :: qdt, dtfactor, x(ixI^S, 1:ndim)
1463  double precision, intent(inout) :: wCT(ixI^S, 1:nw), w(ixI^S, 1:nw)
1464  ! to change and to set as a parameter in the parfile once the possibility to
1465  ! solve the equations in an angular momentum conserving form has been
1466  ! implemented (change tvdlf.t eg)
1467  double precision :: pth(ixI^S), source(ixI^S), minrho
1468  integer :: iw,idir, h1x^L{^NOONED, h2x^L}
1469  integer :: mr_,mphi_ ! Polar var. names
1470  integer :: irho, ifluid, n_fluids
1471  double precision :: exp_factor(ixI^S), del_exp_factor(ixI^S), exp_factor_primitive(ixI^S)
1472 
1473  if (rhd_dust) then
1474  n_fluids = 1 + dust_n_species
1475  else
1476  n_fluids = 1
1477  end if
1478 
1479  select case (coordinate)
1480 
1481  case(cartesian_expansion)
1482  !the user provides the functions of exp_factor and del_exp_factor
1483  if(associated(usr_set_surface)) call usr_set_surface(ixi^l,x,block%dx,exp_factor,del_exp_factor,exp_factor_primitive)
1484  call rhd_get_pthermal(wct, x, ixi^l, ixo^l, source)
1485  source(ixo^s) = source(ixo^s)*del_exp_factor(ixo^s)/exp_factor(ixo^s)
1486  w(ixo^s,mom(1)) = w(ixo^s,mom(1)) + qdt*source(ixo^s)
1487 
1488  case (cylindrical)
1489  if ((rhd_radiation_formalism .eq. 'fld') .or. (rhd_radiation_formalism .eq. 'afld')) then
1490  call mpistop("Diffusion term not implemented yet with cylkindrical geometries")
1491  end if
1492 
1493  do ifluid = 0, n_fluids-1
1494  ! s[mr]=(pthermal+mphi**2/rho)/radius
1495  if (ifluid == 0) then
1496  ! gas
1497  irho = rho_
1498  mr_ = mom(r_)
1499  if(phi_>0) mphi_ = mom(phi_)
1500  call rhd_get_pthermal(wct, x, ixi^l, ixo^l, source)
1501  minrho = 0.0d0
1502  else
1503  ! dust : no pressure
1504  irho = dust_rho(ifluid)
1505  mr_ = dust_mom(r_, ifluid)
1506  if(phi_>0) mphi_ = dust_mom(phi_, ifluid)
1507  source(ixi^s) = zero
1508  minrho = 0.0d0
1509  end if
1510  if (phi_ > 0) then
1511  where (wct(ixo^s, irho) > minrho)
1512  source(ixo^s) = source(ixo^s) + wct(ixo^s, mphi_)**2 / wct(ixo^s, irho)
1513  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1514  end where
1515  ! s[mphi]=(-mphi*mr/rho)/radius
1516  where (wct(ixo^s, irho) > minrho)
1517  source(ixo^s) = -wct(ixo^s, mphi_) * wct(ixo^s, mr_) / wct(ixo^s, irho)
1518  w(ixo^s, mphi_) = w(ixo^s, mphi_) + qdt * source(ixo^s) / x(ixo^s, r_)
1519  end where
1520  else
1521  ! s[mr]=2pthermal/radius
1522  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1523  end if
1524  end do
1525  case (spherical)
1526 
1527  if ((rhd_radiation_formalism .eq. 'fld') .or. (rhd_radiation_formalism .eq. 'afld')) then
1528  call mpistop("Diffusion term not implemented yet with spherical geometries")
1529  end if
1530 
1531  if (rhd_dust) then
1532  call mpistop("Dust geom source terms not implemented yet with spherical geometries")
1533  end if
1534  mr_ = mom(r_)
1535  if(phi_>0) mphi_ = mom(phi_)
1536  h1x^l=ixo^l-kr(1,^d); {^nooned h2x^l=ixo^l-kr(2,^d);}
1537  ! s[mr]=((mtheta**2+mphi**2)/rho+2*p)/r
1538  call rhd_get_pthermal(wct, x, ixi^l, ixo^l, pth)
1539  source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1540  *(block%surfaceC(ixo^s, 1) - block%surfaceC(h1x^s, 1)) &
1541  /block%dvolume(ixo^s)
1542  if (ndir > 1) then
1543  do idir = 2, ndir
1544  source(ixo^s) = source(ixo^s) + wct(ixo^s, mom(idir))**2 / wct(ixo^s, rho_)
1545  end do
1546  end if
1547  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, 1)
1548 
1549  {^nooned
1550  ! s[mtheta]=-(mr*mtheta/rho)/r+cot(theta)*(mphi**2/rho+p)/r
1551  source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1552  * (block%surfaceC(ixo^s, 2) - block%surfaceC(h2x^s, 2)) &
1553  / block%dvolume(ixo^s)
1554  if (ndir == 3) then
1555  source(ixo^s) = source(ixo^s) + (wct(ixo^s, mom(3))**2 / wct(ixo^s, rho_)) / tan(x(ixo^s, 2))
1556  end if
1557  source(ixo^s) = source(ixo^s) - (wct(ixo^s, mom(2)) * wct(ixo^s, mr_)) / wct(ixo^s, rho_)
1558  w(ixo^s, mom(2)) = w(ixo^s, mom(2)) + qdt * source(ixo^s) / x(ixo^s, 1)
1559 
1560  if (ndir == 3) then
1561  ! s[mphi]=-(mphi*mr/rho)/r-cot(theta)*(mtheta*mphi/rho)/r
1562  source(ixo^s) = -(wct(ixo^s, mom(3)) * wct(ixo^s, mr_)) / wct(ixo^s, rho_)&
1563  - (wct(ixo^s, mom(2)) * wct(ixo^s, mom(3))) / wct(ixo^s, rho_) / tan(x(ixo^s, 2))
1564  w(ixo^s, mom(3)) = w(ixo^s, mom(3)) + qdt * source(ixo^s) / x(ixo^s, 1)
1565  end if
1566  }
1567  end select
1568 
1569  if (rhd_viscosity) call visc_add_source_geom(qdt,ixi^l,ixo^l,wct,w,x)
1570 
1571  if (rhd_rotating_frame) then
1572  if (rhd_dust) then
1573  call mpistop("Rotating frame not implemented yet with dust")
1574  else
1575  call rotating_frame_add_source(qdt,dtfactor,ixi^l,ixo^l,wct,w,x)
1576  end if
1577  end if
1578 
1579  end subroutine rhd_add_source_geom
1580 
1581  ! w[iw]= w[iw]+qdt*S[wCT, qtC, x] where S is the source based on wCT within ixO
1582  subroutine rhd_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
1587  use mod_usr_methods, only: usr_gravity
1589 
1590  integer, intent(in) :: ixI^L, ixO^L
1591  double precision, intent(in) :: qdt,dtfactor
1592  double precision, intent(in) :: wCT(ixI^S, 1:nw),wCTprim(ixI^S,1:nw),x(ixI^S, 1:ndim)
1593  double precision, intent(inout) :: w(ixI^S, 1:nw)
1594  logical, intent(in) :: qsourcesplit
1595  logical, intent(inout) :: active
1596 
1597  double precision :: gravity_field(ixI^S, 1:ndim)
1598  integer :: idust, idim
1599 
1600  if(rhd_dust) then
1601  call dust_add_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1602  end if
1603 
1604  if(rhd_radiative_cooling) then
1605  call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1606  qsourcesplit,active, rc_fl)
1607  end if
1608 
1609  if(rhd_viscosity) then
1610  call viscosity_add_source(qdt,ixi^l,ixo^l,wct,w,x,&
1611  rhd_energy,qsourcesplit,active)
1612  end if
1613 
1614  if (rhd_gravity) then
1615  call gravity_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1616  rhd_energy,.false.,qsourcesplit,active)
1617 
1618  if (rhd_dust .and. qsourcesplit .eqv. grav_split) then
1619  active = .true.
1620 
1621  call usr_gravity(ixi^l, ixo^l, wct, x, gravity_field)
1622  do idust = 1, dust_n_species
1623  do idim = 1, ndim
1624  w(ixo^s, dust_mom(idim, idust)) = w(ixo^s, dust_mom(idim, idust)) &
1625  + qdt * gravity_field(ixo^s, idim) * wct(ixo^s, dust_rho(idust))
1626  end do
1627  end do
1628  end if
1629  end if
1630 
1631  !> This is where the radiation force and heating/cooling are added/
1632  call rhd_add_radiation_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1633 
1634  if(rhd_partial_ionization) then
1635  if(.not.qsourcesplit) then
1636  active = .true.
1637  call rhd_update_temperature(ixi^l,ixo^l,wct,w,x)
1638  end if
1639  end if
1640 
1641  end subroutine rhd_add_source
1642 
1643  subroutine rhd_add_radiation_source(qdt,ixI^L,ixO^L,wCT,w,x,qsourcesplit,active)
1644  use mod_constants
1646  use mod_usr_methods
1647  use mod_fld!, only: fld_get_diffcoef_central, get_fld_rad_force, get_fld_energy_interact
1648  use mod_afld!, only: afld_get_diffcoef_central, get_afld_rad_force, get_afld_energy_interact
1649 
1650  integer, intent(in) :: ixI^L, ixO^L
1651  double precision, intent(in) :: qdt, x(ixI^S,1:ndim)
1652  double precision, intent(in) :: wCT(ixI^S,1:nw)
1653  double precision, intent(inout) :: w(ixI^S,1:nw)
1654  logical, intent(in) :: qsourcesplit
1655  logical, intent(inout) :: active
1656  double precision :: cmax(ixI^S)
1657 
1658 
1659  select case(rhd_radiation_formalism)
1660  case('fld')
1661 
1662  if (fld_diff_scheme .eq. 'mg') call fld_get_diffcoef_central(w, wct, x, ixi^l, ixo^l)
1663  ! if (fld_diff_scheme .eq. 'mg') call set_mg_bounds(wCT, x, ixI^L, ixO^L)
1664 
1665  !> radiation force
1666  if (rhd_radiation_force) call get_fld_rad_force(qdt,ixi^l,ixo^l,wct,w,x,&
1667  rhd_energy,qsourcesplit,active)
1668 
1669  call rhd_handle_small_values(.true., w, x, ixi^l, ixo^l, 'fld_e_interact')
1670 
1671  !> photon tiring, heating and cooling
1672  if (rhd_energy) then
1673  if (rhd_energy_interact) call get_fld_energy_interact(qdt,ixi^l,ixo^l,wct,w,x,&
1674  rhd_energy,qsourcesplit,active)
1675  endif
1676 
1677  case('afld')
1678 
1679  if (fld_diff_scheme .eq. 'mg') call afld_get_diffcoef_central(w, wct, x, ixi^l, ixo^l)
1680 
1681  !> radiation force
1682  if (rhd_radiation_force) call get_afld_rad_force(qdt,ixi^l,ixo^l,wct,w,x,&
1683  rhd_energy,qsourcesplit,active)
1684 
1685  call rhd_handle_small_values(.true., w, x, ixi^l, ixo^l, 'fld_e_interact')
1686 
1687  !> photon tiring, heating and cooling
1688  if (rhd_energy) then
1689  if (rhd_energy_interact) call get_afld_energy_interact(qdt,ixi^l,ixo^l,wct,w,x,&
1690  rhd_energy,qsourcesplit,active)
1691  endif
1692 
1693  case default
1694  call mpistop('Radiation formalism unknown')
1695  end select
1696 
1697  ! ! !> NOT necessary for calculation, just want to know the grid-dependent-timestep
1698  ! call rhd_get_cmax(w, x, ixI^L, ixO^L, 2, cmax)
1699  ! w(ixI^S,i_test) = cmax(ixI^S)
1700 
1701  end subroutine rhd_add_radiation_source
1702 
1703  subroutine rhd_get_dt(w, ixI^L, ixO^L, dtnew, dx^D, x)
1705  use mod_dust, only: dust_get_dt
1707  use mod_viscosity, only: viscosity_get_dt
1708  use mod_gravity, only: gravity_get_dt
1709  use mod_fld, only: fld_radforce_get_dt
1710  use mod_afld, only: afld_radforce_get_dt
1711 
1712  integer, intent(in) :: ixI^L, ixO^L
1713  double precision, intent(in) :: dx^D, x(ixI^S, 1:^ND)
1714  double precision, intent(in) :: w(ixI^S, 1:nw)
1715  double precision, intent(inout) :: dtnew
1716 
1717  dtnew = bigdouble
1718 
1719  if (.not. dt_c) then
1720 
1721  if(rhd_dust) then
1722  call dust_get_dt(w, ixi^l, ixo^l, dtnew, dx^d, x)
1723  end if
1724 
1725  if(rhd_radiation_force) then
1726  select case(rhd_radiation_formalism)
1727  case('fld')
1728  call fld_radforce_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1729  case('afld')
1730  call afld_radforce_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1731  case default
1732  call mpistop('Radiation formalism unknown')
1733  end select
1734  endif
1735 
1736  if(rhd_radiative_cooling) then
1737  call cooling_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x,rc_fl)
1738  end if
1739 
1740  if(rhd_viscosity) then
1741  call viscosity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1742  end if
1743 
1744  if(rhd_gravity) then
1745  call gravity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1746  end if
1747  else
1748  {^ifoned dtnew = dx1*unit_velocity/const_c}
1749  {^nooned dtnew = min(dx^d*unit_velocity/const_c)}
1750  endif
1751 
1752  end subroutine rhd_get_dt
1753 
1754  function rhd_kin_en(w, ixI^L, ixO^L, inv_rho) result(ke)
1755  use mod_global_parameters, only: nw, ndim
1756  integer, intent(in) :: ixi^l, ixo^l
1757  double precision, intent(in) :: w(ixi^s, nw)
1758  double precision :: ke(ixo^s)
1759  double precision, intent(in), optional :: inv_rho(ixo^s)
1760 
1761  if (present(inv_rho)) then
1762  ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) * inv_rho
1763  else
1764  ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) / w(ixo^s, rho_)
1765  end if
1766  end function rhd_kin_en
1767 
1768  function rhd_inv_rho(w, ixI^L, ixO^L) result(inv_rho)
1769  use mod_global_parameters, only: nw, ndim
1770  integer, intent(in) :: ixi^l, ixo^l
1771  double precision, intent(in) :: w(ixi^s, nw)
1772  double precision :: inv_rho(ixo^s)
1773 
1774  ! Can make this more robust
1775  inv_rho = 1.0d0 / w(ixo^s, rho_)
1776  end function rhd_inv_rho
1777 
1778  subroutine rhd_handle_small_values(primitive, w, x, ixI^L, ixO^L, subname)
1779  ! handles hydro (density,pressure,velocity) bootstrapping
1780  ! any negative dust density is flagged as well (and throws an error)
1781  ! small_values_method=replace also for dust
1783  use mod_small_values
1785  logical, intent(in) :: primitive
1786  integer, intent(in) :: ixI^L,ixO^L
1787  double precision, intent(inout) :: w(ixI^S,1:nw)
1788  double precision, intent(in) :: x(ixI^S,1:ndim)
1789  character(len=*), intent(in) :: subname
1790 
1791  integer :: n,idir
1792  logical :: flag(ixI^S,1:nw)
1793 
1794  call rhd_check_w(primitive, ixi^l, ixo^l, w, flag)
1795 
1796  if (any(flag)) then
1797  select case (small_values_method)
1798  case ("replace")
1799  where(flag(ixo^s,rho_)) w(ixo^s,rho_) = small_density
1800  do idir = 1, ndir
1801  if(small_values_fix_iw(mom(idir))) then
1802  where(flag(ixo^s,rho_)) w(ixo^s, mom(idir)) = 0.0d0
1803  end if
1804  end do
1805 
1806  if (small_values_fix_iw(r_e)) then
1807  where(flag(ixo^s,r_e)) w(ixo^s,r_e) = small_r_e
1808  end if
1809 
1810  if(rhd_energy)then
1811  if(small_values_fix_iw(e_)) then
1812  if(primitive) then
1813  where(flag(ixo^s,rho_)) w(ixo^s, p_) = small_pressure
1814  else
1815  where(flag(ixo^s,rho_)) w(ixo^s, e_) = small_e + rhd_kin_en(w,ixi^l,ixo^l)
1816  endif
1817  end if
1818  endif
1819 
1820  if(rhd_energy) then
1821  if(primitive) then
1822  where(flag(ixo^s,e_)) w(ixo^s,p_) = small_pressure
1823  else
1824  where(flag(ixo^s,e_))
1825  ! Add kinetic energy
1826  w(ixo^s,e_) = small_e + rhd_kin_en(w,ixi^l,ixo^l)
1827  end where
1828  end if
1829  end if
1830 
1831  if(rhd_dust)then
1832  do n=1,dust_n_species
1833  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1834  do idir = 1, ndir
1835  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1836  enddo
1837  enddo
1838  endif
1839  case ("average")
1840  if(primitive)then
1841  ! averaging for all primitive fields, including dust
1842  call small_values_average(ixi^l, ixo^l, w, x, flag)
1843  else
1844  ! do averaging of density
1845  call small_values_average(ixi^l, ixo^l, w, x, flag, rho_)
1846  if(rhd_energy) then
1847  ! do averaging of pressure
1848  w(ixi^s,p_)=(rhd_gamma-1.d0)*(w(ixi^s,e_) &
1849  -0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_))
1850  call small_values_average(ixi^l, ixo^l, w, x, flag, p_)
1851  w(ixi^s,e_)=w(ixi^s,p_)/(rhd_gamma-1.d0) &
1852  +0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_)
1853  end if
1854  ! do averaging of radiation energy
1855  call small_values_average(ixi^l, ixo^l, w, x, flag, r_e)
1856  if(rhd_dust)then
1857  do n=1,dust_n_species
1858  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1859  do idir = 1, ndir
1860  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1861  enddo
1862  enddo
1863  endif
1864  endif
1865  case default
1866  if(.not.primitive) then
1867  !convert w to primitive
1868  ! Calculate pressure = (gamma-1) * (e-ek)
1869  if(rhd_energy) then
1870  w(ixo^s,p_)=(rhd_gamma-1.d0)*(w(ixo^s,e_)-rhd_kin_en(w,ixi^l,ixo^l))
1871  end if
1872  ! Convert gas momentum to velocity
1873  do idir = 1, ndir
1874  w(ixo^s, mom(idir)) = w(ixo^s, mom(idir))/w(ixo^s,rho_)
1875  end do
1876  end if
1877  ! NOTE: dust entries may still have conserved values here
1878  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
1879  end select
1880  end if
1881  end subroutine rhd_handle_small_values
1882 
1883  subroutine rfactor_from_temperature_ionization(w,x,ixI^L,ixO^L,Rfactor)
1886  integer, intent(in) :: ixI^L, ixO^L
1887  double precision, intent(in) :: w(ixI^S,1:nw)
1888  double precision, intent(in) :: x(ixI^S,1:ndim)
1889  double precision, intent(out):: Rfactor(ixI^S)
1890 
1891  double precision :: iz_H(ixO^S),iz_He(ixO^S)
1892 
1893  call ionization_degree_from_temperature(ixi^l,ixo^l,w(ixi^s,te_),iz_h,iz_he)
1894  ! assume the first and second ionization of Helium have the same degree
1895  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
1896 
1898 
1899  subroutine rfactor_from_constant_ionization(w,x,ixI^L,ixO^L,Rfactor)
1901  integer, intent(in) :: ixI^L, ixO^L
1902  double precision, intent(in) :: w(ixI^S,1:nw)
1903  double precision, intent(in) :: x(ixI^S,1:ndim)
1904  double precision, intent(out):: Rfactor(ixI^S)
1905 
1906  rfactor(ixo^s)=rr
1907 
1908  end subroutine rfactor_from_constant_ionization
1909 
1910  subroutine rhd_update_temperature(ixI^L,ixO^L,wCT,w,x)
1913 
1914  integer, intent(in) :: ixI^L, ixO^L
1915  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
1916  double precision, intent(inout) :: w(ixI^S,1:nw)
1917 
1918  double precision :: iz_H(ixO^S),iz_He(ixO^S), pth(ixI^S)
1919 
1920  call ionization_degree_from_temperature(ixi^l,ixo^l,wct(ixi^s,te_),iz_h,iz_he)
1921 
1922  call rhd_get_pthermal(w,x,ixi^l,ixo^l,pth)
1923 
1924  w(ixo^s,te_)=(2.d0+3.d0*he_abundance)*pth(ixo^s)/(w(ixo^s,rho_)*(1.d0+iz_h(ixo^s)+&
1925  he_abundance*(iz_he(ixo^s)*(iz_he(ixo^s)+1.d0)+1.d0)))
1926 
1927  end subroutine rhd_update_temperature
1928 
1929 end module mod_rhd_phys
Calculate w(iw)=w(iw)+qdt*SOURCE[wCT,qtC,x] within ixO for all indices iw=iwmin......
Module for including anisotropic flux limited diffusion (AFLD)-approximation in Radiation-hydrodynami...
Definition: mod_afld.t:8
subroutine, public afld_radforce_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
Definition: mod_afld.t:316
subroutine, public get_afld_energy_interact(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 This subroutine handles th...
Definition: mod_afld.t:347
subroutine, public afld_init(He_abundance, rhd_radiation_diffusion, afld_gamma)
Initialising FLD-module: Read opacities Initialise Multigrid adimensionalise kappa Add extra variable...
Definition: mod_afld.t:126
subroutine afld_get_diffcoef_central(w, wCT, x, ixIL, ixOL)
Calculates cell-centered diffusion coefficient to be used in multigrid.
Definition: mod_afld.t:1263
subroutine, public get_afld_rad_force(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 This subroutine handles th...
Definition: mod_afld.t:208
subroutine, public afld_get_radpress(w, x, ixIL, ixOL, rad_pressure)
Calculate Radiation Pressure Returns Radiation Pressure as tensor.
Definition: mod_afld.t:716
Module with basic data types used in amrvac.
integer, parameter std_len
Default length for strings.
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
double precision, parameter const_rad_a
Definition: mod_constants.t:61
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_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_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.
Nicolas Moens Module for including flux limited diffusion (FLD)-approximation in Radiation-hydrodynam...
Definition: mod_fld.t:9
double precision, public fld_mu
mean particle mass
Definition: mod_fld.t:23
subroutine, public fld_radforce_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
Definition: mod_fld.t:291
character(len=8) fld_diff_scheme
Which method to solve diffusion part.
Definition: mod_fld.t:46
subroutine, public get_fld_rad_force(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 This subroutine handles th...
Definition: mod_fld.t:183
subroutine, public fld_get_radpress(w, x, ixIL, ixOL, rad_pressure)
Calculate Radiation Pressure Returns Radiation Pressure as tensor.
Definition: mod_fld.t:699
subroutine, public fld_init(He_abundance, rhd_radiation_diffusion, rhd_gamma)
Initialising FLD-module: Read opacities Initialise Multigrid adimensionalise kappa Add extra variable...
Definition: mod_fld.t:120
subroutine, public get_fld_energy_interact(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 This subroutine handles th...
Definition: mod_fld.t:322
subroutine fld_get_diffcoef_central(w, wCT, x, ixIL, ixOL)
Calculates cell-centered diffusion coefficient to be used in multigrid.
Definition: mod_fld.t:1023
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.
integer, parameter bc_noinflow
double precision small_pressure
double precision unit_time
Physical scaling factor for time.
double precision unit_density
Physical scaling factor for density.
double precision unit_opacity
Physical scaling factor for Opacity.
integer, parameter unitpar
file handle for IO
integer, parameter bc_asymm
double precision global_time
The global simulation time.
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.
integer, dimension(:, :), allocatable typeboundary
Array indicating the type of boundary condition per variable and per physical boundary.
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.
integer, parameter bc_periodic
integer, parameter bc_special
boundary condition types
double precision unit_velocity
Physical scaling factor for velocity.
double precision unit_temperature
Physical scaling factor for temperature.
double precision unit_radflux
Physical scaling factor for radiation flux.
integer, parameter bc_cont
logical si_unit
Use SI units (.true.) or use cgs units (.false.)
double precision, dimension(:,:), allocatable dx
integer nghostcells
Number of ghost cells surrounding a grid.
integer, parameter bc_symm
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.
logical use_multigrid
Use multigrid (only available in 2D and 3D)
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
module ionization degree - get ionization degree for given temperature
subroutine ionization_degree_from_temperature(ixIL, ixOL, Te, iz_H, iz_He)
Module to couple the octree-mg library to AMRVAC. This file uses the VACPP preprocessor,...
type(mg_t) mg
Data structure containing the multigrid tree.
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)
Radiation-Hydrodynamics physics module Module aims at solving the Hydrodynamic equations toghether wi...
Definition: mod_rhd_phys.t:11
subroutine rhd_add_source_geom(qdt, dtfactor, ixIL, ixOL, wCT, w, x)
Add geometrical source terms to w.
logical, public, protected rhd_radiative_cooling
Whether radiative cooling is added.
Definition: mod_rhd_phys.t:29
integer, public, protected rhd_n_tracer
Number of tracer species.
Definition: mod_rhd_phys.t:48
subroutine, public rhd_to_primitive(ixIL, ixOL, w, x)
Transform conservative variables into primitive ones.
Definition: mod_rhd_phys.t:785
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
Definition: mod_rhd_phys.t:63
type(tc_fluid), allocatable, public tc_fl
Definition: mod_rhd_phys.t:25
subroutine rhd_ei_to_e(ixIL, ixOL, w, x)
Transform internal energy to total energy.
Definition: mod_rhd_phys.t:819
logical, public, protected rhd_dust
Whether dust is added.
Definition: mod_rhd_phys.t:33
integer, public, protected rhd_trac_type
Definition: mod_rhd_phys.t:88
integer, public, protected te_
Indices of temperature.
Definition: mod_rhd_phys.t:69
subroutine rhd_ei_to_e1(ixIL, ixOL, w, x)
logical, public, protected rhd_rotating_frame
Whether rotating frame is activated.
Definition: mod_rhd_phys.t:45
double precision function, dimension(ixo^s), public rhd_kin_en(w, ixIL, ixOL, inv_rho)
subroutine rhd_get_dt(w, ixIL, ixOL, dtnew, dxD, x)
subroutine, public rhd_get_pradiation(w, x, ixIL, ixOL, prad)
Calculate radiation pressure within ixO^L.
subroutine, public rhd_to_conserved(ixIL, ixOL, w, x)
Transform primitive variables into conservative ones.
Definition: mod_rhd_phys.t:753
logical, public, protected rhd_viscosity
Whether viscosity is added.
Definition: mod_rhd_phys.t:36
double precision, public kbmpmua4
kb/(m_p mu)* 1/a_rad**4,
Definition: mod_rhd_phys.t:122
subroutine rhd_get_temperature_from_eint(w, x, ixIL, ixOL, res)
Calculate temperature=p/rho when in e_ the internal energy is stored.
subroutine, public rhd_get_tgas(w, x, ixIL, ixOL, tgas)
Calculates gas temperature.
subroutine, public rhd_check_params
Definition: mod_rhd_phys.t:602
subroutine rfactor_from_temperature_ionization(w, x, ixIL, ixOL, Rfactor)
subroutine rhd_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_rhd_phys.t:982
logical, public, protected rhd_trac
Whether TRAC method is used.
Definition: mod_rhd_phys.t:87
subroutine, public rhd_phys_init()
Initialize the module.
Definition: mod_rhd_phys.t:205
character(len=8), public rhd_radiation_formalism
Formalism to treat radiation.
Definition: mod_rhd_phys.t:97
integer, public, protected rho_
Index of the density (in the w array)
Definition: mod_rhd_phys.t:51
integer, public, protected r_e
Index of the radiation energy.
Definition: mod_rhd_phys.t:66
logical, public, protected rhd_radiation_diffusion
Treat radiation energy diffusion.
Definition: mod_rhd_phys.t:109
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
Definition: mod_rhd_phys.t:54
character(len=8), public rhd_pressure
In the case of no rhd_energy, how to compute pressure.
Definition: mod_rhd_phys.t:100
subroutine rhd_add_source(qdt, dtfactor, ixIL, ixOL, wCT, wCTprim, w, x, qsourcesplit, active)
subroutine rhd_e_to_ei(ixIL, ixOL, w, x)
Transform total energy to internal energy.
Definition: mod_rhd_phys.t:832
subroutine rhd_add_radiation_source(qdt, ixIL, ixOL, wCT, w, x, qsourcesplit, active)
subroutine, public rhd_get_trad(w, x, ixIL, ixOL, trad)
Calculates radiation temperature.
subroutine rhd_get_tcutoff(ixIL, ixOL, w, x, tco_local, Tmax_local)
get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
Definition: mod_rhd_phys.t:929
subroutine rhd_write_info(fh)
Write this module's parameters to a snapsoht.
Definition: mod_rhd_phys.t:187
subroutine rfactor_from_constant_ionization(w, x, ixIL, ixOL, Rfactor)
logical, public, protected rhd_partial_ionization
Whether plasma is partially ionized.
Definition: mod_rhd_phys.t:115
subroutine rhos_to_e(ixIL, ixOL, w, x)
Definition: mod_rhd_phys.t:859
logical, public, protected rhd_force_diagonal
Allows overruling default corner filling (for debug mode, since otherwise corner primitives fail)
Definition: mod_rhd_phys.t:91
subroutine, public rhd_get_csound2(w, x, ixIL, ixOL, csound2)
Calculate the square of the thermal sound speed csound2 within ixO^L. csound2=gamma*p/rho.
logical, public, protected rhd_radiation_force
Treat radiation fld_Rad_force.
Definition: mod_rhd_phys.t:103
logical, public, protected rhd_energy
Whether an energy equation is used.
Definition: mod_rhd_phys.t:21
subroutine, public rhd_get_ptot(w, x, ixIL, ixOL, ptot)
calculates the sum of the gas pressure and max Prad tensor element
double precision, public rhd_adiab
The adiabatic constant.
Definition: mod_rhd_phys.t:78
subroutine rhd_e_to_ei1(ixIL, ixOL, w, x)
Transform total energy to internal energy.
double precision, public, protected small_r_e
The smallest allowed radiation energy.
Definition: mod_rhd_phys.t:84
subroutine tc_params_read_rhd(fl)
Definition: mod_rhd_phys.t:526
subroutine rhd_get_rho(w, x, ixIL, ixOL, rho)
Definition: mod_rhd_phys.t:546
subroutine rhd_tc_handle_small_e(w, x, ixIL, ixOL, step)
Definition: mod_rhd_phys.t:491
double precision, public, protected h_ion_fr
Ionization fraction of H H_ion_fr = H+/(H+ + H)
Definition: mod_rhd_phys.t:129
subroutine rhd_handle_small_values(primitive, w, x, ixIL, ixOL, subname)
subroutine rhd_get_v(w, x, ixIL, ixOL, idim, v)
Calculate v_i = m_i / rho within ixO^L.
Definition: mod_rhd_phys.t:875
double precision function rhd_get_tc_dt_rhd(w, ixIL, ixOL, dxD, x)
Definition: mod_rhd_phys.t:475
subroutine rhd_get_temperature_from_etot(w, x, ixIL, ixOL, res)
Calculate temperature=p/rho when in e_ the total energy is stored.
subroutine rhd_get_flux(wC, w, x, ixIL, ixOL, idim, f)
integer, dimension(:), allocatable, public, protected tracer
Indices of the tracers.
Definition: mod_rhd_phys.t:57
subroutine rhd_get_cmax(w, x, ixIL, ixOL, idim, cmax)
Calculate cmax_idim = csound + abs(v_idim) within ixO^L.
Definition: mod_rhd_phys.t:885
subroutine rhd_update_temperature(ixIL, ixOL, wCT, w, x)
integer, public, protected e_
Index of the energy density (-1 if not present)
Definition: mod_rhd_phys.t:60
subroutine rhd_radio_acoustic_filter(x, ixIL, ixOL, prad_max)
Filter peaks in cmax due to radiation energy density, used for debugging.
double precision, public, protected he_abundance
Helium abundance over Hydrogen.
Definition: mod_rhd_phys.t:94
subroutine, public rhd_set_mg_bounds
Set the boundaries for the diffusion of E.
Definition: mod_rhd_phys.t:631
subroutine e_to_rhos(ixIL, ixOL, w, x)
Definition: mod_rhd_phys.t:844
double precision, public, protected he_ion_fr2
Ratio of number He2+ / number He+ + He2+ He_ion_fr2 = He2+/(He2+ + He+)
Definition: mod_rhd_phys.t:135
logical, public, protected rhd_thermal_conduction
Whether thermal conduction is added.
Definition: mod_rhd_phys.t:24
subroutine rhd_physical_units
Definition: mod_rhd_phys.t:666
double precision, public, protected rr
Definition: mod_rhd_phys.t:139
subroutine, public rhd_get_pthermal(w, x, ixIL, ixOL, pth)
Calculate thermal pressure=(gamma-1)*(e-0.5*m**2/rho) within ixO^L.
subroutine rhd_sts_set_source_tc_rhd(ixIL, ixOL, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux)
Definition: mod_rhd_phys.t:462
double precision function, dimension(ixo^s) rhd_inv_rho(w, ixIL, ixOL)
logical, public, protected rhd_radiation_advection
Treat radiation advection.
Definition: mod_rhd_phys.t:112
logical, public, protected rhd_particles
Whether particles module is added.
Definition: mod_rhd_phys.t:42
subroutine rhd_get_a2max(w, x, ixIL, ixOL, a2max)
Definition: mod_rhd_phys.t:906
double precision, public, protected he_ion_fr
Ionization fraction of He He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
Definition: mod_rhd_phys.t:132
subroutine rc_params_read(fl)
Definition: mod_rhd_phys.t:558
type(te_fluid), allocatable, public te_fl_rhd
Definition: mod_rhd_phys.t:26
logical, public, protected rhd_energy_interact
Treat radiation-gas energy interaction.
Definition: mod_rhd_phys.t:106
logical, public, protected eq_state_units
Definition: mod_rhd_phys.t:143
type(rc_fluid), allocatable, public rc_fl
Definition: mod_rhd_phys.t:30
logical, public, protected rhd_gravity
Whether gravity is added.
Definition: mod_rhd_phys.t:39
subroutine rhd_get_flux_cons(w, x, ixIL, ixOL, idim, f)
integer, public, protected tcoff_
Index of the cutoff temperature for the TRAC method.
Definition: mod_rhd_phys.t:72
subroutine, public rhd_check_w(primitive, ixIL, ixOL, w, flag)
Returns logical argument flag where values are ok.
Definition: mod_rhd_phys.t:722
subroutine rhd_te_images()
Definition: mod_rhd_phys.t:444
double precision, public rhd_gamma
The adiabatic index.
Definition: mod_rhd_phys.t:75
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)
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(special_mg_bc), pointer usr_special_mg_bc
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)