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)
887  use mod_dust, only: dust_get_cmax_prim
888 
889  integer, intent(in) :: ixI^L, ixO^L, idim
890  ! w in primitive form
891  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:ndim)
892  double precision, intent(inout) :: cmax(ixI^S)
893 
894  if(rhd_energy) then
895  cmax(ixo^s)=dabs(w(ixo^s,mom(idim)))+dsqrt(rhd_gamma*w(ixo^s,p_)/w(ixo^s,rho_))
896  else
897  if (.not. associated(usr_set_pthermal)) then
898  select case (rhd_pressure)
899  case ('Trad')
900  cmax(ixo^s) = (w(ixo^s,r_e)*unit_pressure/const_rad_a)**0.25d0&
901  /unit_temperature*w(ixo^s, rho_)
902  case ('adiabatic')
903  cmax(ixo^s) = rhd_adiab * w(ixo^s, rho_)**rhd_gamma
904  case ('Tcond') !> Thermal conduction?!
905  cmax(ixo^s) = (rhd_gamma-1.d0)*w(ixo^s,r_e)
906  case default
907  call mpistop('rhd_pressure unknown, use Trad or adiabatic')
908  end select
909  else
910  call usr_set_pthermal(w,x,ixi^l,ixo^l,cmax)
911  end if
912  cmax(ixo^s)=dabs(w(ixo^s,mom(idim)))+dsqrt(rhd_gamma*cmax(ixo^s)/w(ixo^s,rho_))
913  end if
914 
915  if (rhd_dust) then
916  call dust_get_cmax_prim(w, x, ixi^l, ixo^l, idim, cmax)
917  end if
918  end subroutine rhd_get_cmax
919 
920  subroutine rhd_get_a2max(w,x,ixI^L,ixO^L,a2max)
922 
923  integer, intent(in) :: ixI^L, ixO^L
924  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
925  double precision, intent(inout) :: a2max(ndim)
926  double precision :: a2(ixI^S,ndim,nw)
927  integer :: gxO^L,hxO^L,jxO^L,kxO^L,i,j
928 
929  a2=zero
930  do i = 1,ndim
931  !> 4th order
932  hxo^l=ixo^l-kr(i,^d);
933  gxo^l=hxo^l-kr(i,^d);
934  jxo^l=ixo^l+kr(i,^d);
935  kxo^l=jxo^l+kr(i,^d);
936  a2(ixo^s,i,1:nw)=dabs(-w(kxo^s,1:nw)+16.d0*w(jxo^s,1:nw)&
937  -30.d0*w(ixo^s,1:nw)+16.d0*w(hxo^s,1:nw)-w(gxo^s,1:nw))
938  a2max(i)=maxval(a2(ixo^s,i,1:nw))/12.d0/dxlevel(i)**2
939  end do
940  end subroutine rhd_get_a2max
941 
942  !> get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
943  subroutine rhd_get_tcutoff(ixI^L,ixO^L,w,x,tco_local,Tmax_local)
945  integer, intent(in) :: ixI^L,ixO^L
946  double precision, intent(in) :: x(ixI^S,1:ndim)
947  double precision, intent(inout) :: w(ixI^S,1:nw)
948  double precision, intent(out) :: tco_local, Tmax_local
949 
950  double precision, parameter :: trac_delta=0.25d0
951  double precision :: tmp1(ixI^S),Te(ixI^S),lts(ixI^S)
952  double precision :: ltr(ixI^S),ltrc,ltrp,tcoff(ixI^S)
953  integer :: jxO^L,hxO^L
954  integer :: jxP^L,hxP^L,ixP^L
955  logical :: lrlt(ixI^S)
956 
957  {^ifoned
958  call rhd_get_temperature_from_etot(w,x,ixi^l,ixi^l,te)
959 
960  tco_local=zero
961  tmax_local=maxval(te(ixo^s))
962  select case(rhd_trac_type)
963  case(0)
964  w(ixi^s,tcoff_)=3.d5/unit_temperature
965  case(1)
966  hxo^l=ixo^l-1;
967  jxo^l=ixo^l+1;
968  lts(ixo^s)=0.5d0*dabs(te(jxo^s)-te(hxo^s))/te(ixo^s)
969  lrlt=.false.
970  where(lts(ixo^s) > trac_delta)
971  lrlt(ixo^s)=.true.
972  end where
973  if(any(lrlt(ixo^s))) then
974  tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
975  end if
976  case(2)
977  !> iijima et al. 2021, LTRAC method
978  ltrc=1.5d0
979  ltrp=2.5d0
980  ixp^l=ixo^l^ladd1;
981  hxo^l=ixo^l-1;
982  jxo^l=ixo^l+1;
983  hxp^l=ixp^l-1;
984  jxp^l=ixp^l+1;
985  lts(ixp^s)=0.5d0*abs(te(jxp^s)-te(hxp^s))/te(ixp^s)
986  ltr(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
987  w(ixo^s,tcoff_)=te(ixo^s)*&
988  (0.25*(ltr(jxo^s)+two*ltr(ixo^s)+ltr(hxo^s)))**0.4d0
989  case default
990  call mpistop("mrhd_trac_type not allowed for 1D simulation")
991  end select
992  }
993  end subroutine rhd_get_tcutoff
994 
995  !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
996  subroutine rhd_get_cbounds(wLC, wRC, wLp, wRp, x, ixI^L, ixO^L, idim,Hspeed,cmax, cmin)
998  use mod_dust, only: dust_get_cmax
999  use mod_variables
1000 
1001  integer, intent(in) :: ixI^L, ixO^L, idim
1002  ! conservative left and right status
1003  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S, nw)
1004  ! primitive left and right status
1005  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S, nw)
1006  double precision, intent(in) :: x(ixI^S, 1:ndim)
1007  double precision, intent(inout) :: cmax(ixI^S,1:number_species)
1008  double precision, intent(inout), optional :: cmin(ixI^S,1:number_species)
1009  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
1010 
1011  double precision :: wmean(ixI^S,nw)
1012  double precision, dimension(ixI^S) :: umean, dmean, csoundL, csoundR, tmp1,tmp2,tmp3
1013  integer :: ix^D
1014 
1015  select case(boundspeed)
1016  case (1)
1017  ! This implements formula (10.52) from "Riemann Solvers and Numerical
1018  ! Methods for Fluid Dynamics" by Toro.
1019 
1020  tmp1(ixo^s)=dsqrt(wlp(ixo^s,rho_))
1021  tmp2(ixo^s)=dsqrt(wrp(ixo^s,rho_))
1022  tmp3(ixo^s)=1.d0/(dsqrt(wlp(ixo^s,rho_))+dsqrt(wrp(ixo^s,rho_)))
1023  umean(ixo^s)=(wlp(ixo^s,mom(idim))*tmp1(ixo^s)+wrp(ixo^s,mom(idim))*tmp2(ixo^s))*tmp3(ixo^s)
1024 
1025  if(rhd_energy) then
1026  csoundl(ixo^s)=rhd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
1027  csoundr(ixo^s)=rhd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
1028  else
1029  select case (rhd_pressure)
1030  case ('Trad')
1031  csoundl(ixo^s)=rhd_gamma*kbmpmua4*wlp(ixo^s,r_e)**(1.d0/4)
1032  csoundr(ixo^s)=rhd_gamma*kbmpmua4*wrp(ixo^s,r_e)**(1.d0/4)
1033  case ('adiabatic')
1034  csoundl(ixo^s)=rhd_gamma*rhd_adiab*wlp(ixo^s,rho_)**(rhd_gamma-one)
1035  csoundr(ixo^s)=rhd_gamma*rhd_adiab*wrp(ixo^s,rho_)**(rhd_gamma-one)
1036  end select
1037  end if
1038 
1039  dmean(ixo^s) = (tmp1(ixo^s)*csoundl(ixo^s)+tmp2(ixo^s)*csoundr(ixo^s)) * &
1040  tmp3(ixo^s) + 0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2 * &
1041  (wrp(ixo^s,mom(idim))-wlp(ixo^s,mom(idim)))**2
1042 
1043  dmean(ixo^s)=dsqrt(dmean(ixo^s))
1044  if(present(cmin)) then
1045  cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
1046  cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
1047  if(h_correction) then
1048  {do ix^db=ixomin^db,ixomax^db\}
1049  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1050  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1051  {end do\}
1052  end if
1053  else
1054  cmax(ixo^s,1)=dabs(umean(ixo^s))+dmean(ixo^s)
1055  end if
1056 
1057  if (rhd_dust) then
1058  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1059  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1060  end if
1061 
1062  case (2)
1063  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1064  tmp1(ixo^s)=wmean(ixo^s,mom(idim))/wmean(ixo^s,rho_)
1065  call rhd_get_csound2(wmean,x,ixi^l,ixo^l,csoundr)
1066  csoundr(ixo^s) = dsqrt(csoundr(ixo^s))
1067 
1068  if(present(cmin)) then
1069  cmax(ixo^s,1)=max(tmp1(ixo^s)+csoundr(ixo^s),zero)
1070  cmin(ixo^s,1)=min(tmp1(ixo^s)-csoundr(ixo^s),zero)
1071  if(h_correction) then
1072  {do ix^db=ixomin^db,ixomax^db\}
1073  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1074  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1075  {end do\}
1076  end if
1077  else
1078  cmax(ixo^s,1)=dabs(tmp1(ixo^s))+csoundr(ixo^s)
1079  end if
1080 
1081  if (rhd_dust) then
1082  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1083  end if
1084  case (3)
1085  ! Miyoshi 2005 JCP 208, 315 equation (67)
1086  if(rhd_energy) then
1087  csoundl(ixo^s)=rhd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
1088  csoundr(ixo^s)=rhd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
1089  else
1090  select case (rhd_pressure)
1091  case ('Trad')
1092  csoundl(ixo^s)=rhd_gamma*kbmpmua4*wlp(ixo^s,r_e)**(1.d0/4)
1093  csoundr(ixo^s)=rhd_gamma*kbmpmua4*wrp(ixo^s,r_e)**(1.d0/4)
1094  case ('adiabatic')
1095  csoundl(ixo^s)=rhd_gamma*rhd_adiab*wlp(ixo^s,rho_)**(rhd_gamma-one)
1096  csoundr(ixo^s)=rhd_gamma*rhd_adiab*wrp(ixo^s,rho_)**(rhd_gamma-one)
1097  end select
1098  end if
1099  csoundl(ixo^s)=max(dsqrt(csoundl(ixo^s)),dsqrt(csoundr(ixo^s)))
1100  if(present(cmin)) then
1101  cmin(ixo^s,1)=min(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))-csoundl(ixo^s)
1102  cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
1103  if(h_correction) then
1104  {do ix^db=ixomin^db,ixomax^db\}
1105  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1106  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1107  {end do\}
1108  end if
1109  else
1110  cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
1111  end if
1112  if (rhd_dust) then
1113  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1114  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1115  end if
1116  end select
1117 
1118  end subroutine rhd_get_cbounds
1119 
1120  !> Calculate the square of the thermal sound speed csound2 within ixO^L.
1121  !> csound2=gamma*p/rho
1122  subroutine rhd_get_csound2(w,x,ixI^L,ixO^L,csound2)
1124  integer, intent(in) :: ixi^l, ixo^l
1125  double precision, intent(in) :: w(ixi^s,nw)
1126  double precision, intent(in) :: x(ixi^s,1:ndim)
1127  double precision, intent(out) :: csound2(ixi^s)
1128 
1129  call rhd_get_ptot(w,x,ixi^l,ixo^l,csound2)
1130  csound2(ixo^s)=max(rhd_gamma,4.d0/3.d0)*csound2(ixo^s)/w(ixo^s,rho_)
1131  !> Turner & Stone 2001
1132 
1133  end subroutine rhd_get_csound2
1134 
1135  !> Calculate thermal pressure=(gamma-1)*(e-0.5*m**2/rho) within ixO^L
1136  subroutine rhd_get_pthermal(w, x, ixI^L, ixO^L, pth)
1140 
1141  integer, intent(in) :: ixi^l, ixo^l
1142  double precision, intent(in) :: w(ixi^s, 1:nw)
1143  double precision, intent(in) :: x(ixi^s, 1:ndim)
1144  double precision, intent(out):: pth(ixi^s)
1145  integer :: iw, ix^d
1146 
1147  if (rhd_energy) then
1148  pth(ixi^s) = (rhd_gamma - 1.d0) * (w(ixi^s, e_) - &
1149  0.5d0 * sum(w(ixi^s, mom(:))**2, dim=ndim+1) / w(ixi^s, rho_))
1150  else
1151  if (.not. associated(usr_set_pthermal)) then
1152  select case (rhd_pressure)
1153  case ('Trad')
1154  pth(ixi^s) = (w(ixi^s,r_e)*unit_pressure/const_rad_a)**0.25d0&
1155  /unit_temperature*w(ixi^s, rho_)
1156  case ('adiabatic')
1157  pth(ixi^s) = rhd_adiab * w(ixi^s, rho_)**rhd_gamma
1158  case ('Tcond') !> Thermal conduction?!
1159  pth(ixi^s) = (rhd_gamma-1.d0)*w(ixi^s,r_e)
1160  case default
1161  call mpistop('rhd_pressure unknown, use Trad or adiabatic')
1162  end select
1163  else
1164  call usr_set_pthermal(w,x,ixi^l,ixo^l,pth)
1165  end if
1166  end if
1167 
1168  if (fix_small_values) then
1169  {do ix^db= ixo^lim^db\}
1170  if(pth(ix^d)<small_pressure) then
1171  pth(ix^d)=small_pressure
1172  endif
1173  {enddo^d&\}
1174  else if (check_small_values) then
1175  {do ix^db= ixo^lim^db\}
1176  if(pth(ix^d)<small_pressure) then
1177  write(*,*) "Error: small value of gas pressure",pth(ix^d),&
1178  " encountered when call rhd_get_pthermal"
1179  write(*,*) "Iteration: ", it, " Time: ", global_time
1180  write(*,*) "Location: ", x(ix^d,:)
1181  write(*,*) "Cell number: ", ix^d
1182  do iw=1,nw
1183  write(*,*) trim(cons_wnames(iw)),": ",w(ix^d,iw)
1184  end do
1185  ! use erroneous arithmetic operation to crash the run
1186  if(trace_small_values) write(*,*) dsqrt(pth(ix^d)-bigdouble)
1187  write(*,*) "Saving status at the previous time step"
1188  crash=.true.
1189  end if
1190  {enddo^d&\}
1191  end if
1192 
1193  end subroutine rhd_get_pthermal
1194 
1195  !> Calculate radiation pressure within ixO^L
1196  subroutine rhd_get_pradiation(w, x, ixI^L, ixO^L, prad)
1198  use mod_fld
1199  use mod_afld
1200 
1201  integer, intent(in) :: ixi^l, ixo^l
1202  double precision, intent(in) :: w(ixi^s, 1:nw)
1203  double precision, intent(in) :: x(ixi^s, 1:ndim)
1204  double precision, intent(out):: prad(ixo^s, 1:ndim, 1:ndim)
1205 
1206  select case (rhd_radiation_formalism)
1207  case('fld')
1208  call fld_get_radpress(w, x, ixi^l, ixo^l, prad)
1209  case('afld')
1210  call afld_get_radpress(w, x, ixi^l, ixo^l, prad)
1211  case default
1212  call mpistop('Radiation formalism unknown')
1213  end select
1214  end subroutine rhd_get_pradiation
1215 
1216  !> calculates the sum of the gas pressure and max Prad tensor element
1217  subroutine rhd_get_ptot(w, x, ixI^L, ixO^L, ptot)
1219 
1220  integer, intent(in) :: ixi^l, ixo^l
1221  double precision, intent(in) :: w(ixi^s, 1:nw)
1222  double precision, intent(in) :: x(ixi^s, 1:ndim)
1223  double precision :: pth(ixi^s)
1224  double precision :: prad_tensor(ixo^s, 1:ndim, 1:ndim)
1225  double precision :: prad_max(ixo^s)
1226  double precision, intent(out):: ptot(ixi^s)
1227  integer :: ix^d
1228 
1229  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1230  call rhd_get_pradiation(w, x, ixi^l, ixo^l, prad_tensor)
1231 
1232  {do ix^d = ixomin^d,ixomax^d\}
1233  prad_max(ix^d) = maxval(prad_tensor(ix^d,:,:))
1234  {enddo\}
1235 
1236  !> filter cmax
1237  if (radio_acoustic_filter) then
1238  call rhd_radio_acoustic_filter(x, ixi^l, ixo^l, prad_max)
1239  endif
1240 
1241  ptot(ixo^s) = pth(ixo^s) + prad_max(ixo^s)
1242 
1243  end subroutine rhd_get_ptot
1244 
1245  !> Filter peaks in cmax due to radiation energy density, used for debugging
1246  subroutine rhd_radio_acoustic_filter(x, ixI^L, ixO^L, prad_max)
1248 
1249  integer, intent(in) :: ixI^L, ixO^L
1250  double precision, intent(in) :: x(ixI^S, 1:ndim)
1251  double precision, intent(inout) :: prad_max(ixO^S)
1252 
1253  double precision :: tmp_prad(ixI^S)
1254  integer :: ix^D, filter, idim
1255 
1256  if (size_ra_filter .lt. 1) call mpistop("ra filter of size < 1 makes no sense")
1257  if (size_ra_filter .gt. nghostcells) call mpistop("ra filter of size < nghostcells makes no sense")
1258 
1259  tmp_prad(ixi^s) = zero
1260  tmp_prad(ixo^s) = prad_max(ixo^s)
1261 
1262  do filter = 1,size_ra_filter
1263  do idim = 1,ndim
1264  ! {do ix^D = ixOmin^D+filter,ixOmax^D-filter\}
1265  {do ix^d = ixomin^d,ixomax^d\}
1266  prad_max(ix^d) = min(tmp_prad(ix^d),tmp_prad(ix^d+filter*kr(idim,^d)))
1267  prad_max(ix^d) = min(tmp_prad(ix^d),tmp_prad(ix^d-filter*kr(idim,^d)))
1268  {enddo\}
1269  enddo
1270  enddo
1271  end subroutine rhd_radio_acoustic_filter
1272 
1273  !> Calculate temperature=p/rho when in e_ the total energy is stored
1274  subroutine rhd_get_temperature_from_etot(w, x, ixI^L, ixO^L, res)
1276  integer, intent(in) :: ixI^L, ixO^L
1277  double precision, intent(in) :: w(ixI^S, 1:nw)
1278  double precision, intent(in) :: x(ixI^S, 1:ndim)
1279  double precision, intent(out):: res(ixI^S)
1280 
1281  double precision :: R(ixI^S)
1282 
1283  call rhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1284  call rhd_get_pthermal(w, x, ixi^l, ixo^l, res)
1285  res(ixo^s)=res(ixo^s)/(r(ixo^s)*w(ixo^s,rho_))
1286  end subroutine rhd_get_temperature_from_etot
1287 
1288 
1289  !> Calculate temperature=p/rho when in e_ the internal energy is stored
1290  subroutine rhd_get_temperature_from_eint(w, x, ixI^L, ixO^L, res)
1292  integer, intent(in) :: ixI^L, ixO^L
1293  double precision, intent(in) :: w(ixI^S, 1:nw)
1294  double precision, intent(in) :: x(ixI^S, 1:ndim)
1295  double precision, intent(out):: res(ixI^S)
1296  double precision :: R(ixI^S)
1297 
1298  call rhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1299  res(ixo^s) = (rhd_gamma - 1.0d0) * w(ixo^s, e_)/(w(ixo^s,rho_)*r(ixo^s))
1300  end subroutine rhd_get_temperature_from_eint
1301 
1302  !> Calculates gas temperature
1303  subroutine rhd_get_tgas(w, x, ixI^L, ixO^L, tgas)
1305 
1306  integer, intent(in) :: ixi^l, ixo^l
1307  double precision, intent(in) :: w(ixi^s, 1:nw)
1308  double precision, intent(in) :: x(ixi^s, 1:ndim)
1309  double precision :: pth(ixi^s)
1310  double precision, intent(out):: tgas(ixi^s)
1311 
1312  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1313  tgas(ixi^s) = pth(ixi^s)/w(ixi^s,rho_)
1314 
1315  end subroutine rhd_get_tgas
1316 
1317  !> Calculates radiation temperature
1318  subroutine rhd_get_trad(w, x, ixI^L, ixO^L, trad)
1320  use mod_constants
1321 
1322  integer, intent(in) :: ixi^l, ixo^l
1323  double precision, intent(in) :: w(ixi^s, 1:nw)
1324  double precision, intent(in) :: x(ixi^s, 1:ndim)
1325  double precision, intent(out):: trad(ixi^s)
1326 
1327  trad(ixi^s) = (w(ixi^s,r_e)*unit_pressure&
1328  /const_rad_a)**(1.d0/4.d0)/unit_temperature
1329 
1330  end subroutine rhd_get_trad
1331 
1332 
1333  !these are very similar to the subroutines without 1, used in mod_thermal_conductivity
1334  !but no check on whether energy variable is present
1335  subroutine rhd_ei_to_e1(ixI^L,ixO^L,w,x)
1337  integer, intent(in) :: ixI^L, ixO^L
1338  double precision, intent(inout) :: w(ixI^S, nw)
1339  double precision, intent(in) :: x(ixI^S, 1:ndim)
1340 
1341  ! Calculate total energy from internal and kinetic energy
1342  w(ixo^s,e_)=w(ixo^s,e_)&
1343  +rhd_kin_en(w,ixi^l,ixo^l)
1344 
1345  end subroutine rhd_ei_to_e1
1346 
1347  !> Transform total energy to internal energy
1348  !but no check on whether energy variable is present
1349  subroutine rhd_e_to_ei1(ixI^L,ixO^L,w,x)
1351  integer, intent(in) :: ixI^L, ixO^L
1352  double precision, intent(inout) :: w(ixI^S, nw)
1353  double precision, intent(in) :: x(ixI^S, 1:ndim)
1354 
1355  ! Calculate ei = e - ek
1356  w(ixo^s,e_)=w(ixo^s,e_)&
1357  -rhd_kin_en(w,ixi^l,ixo^l)
1358 
1359  end subroutine rhd_e_to_ei1
1360 
1361  ! Calculate flux f_idim[iw]
1362  subroutine rhd_get_flux_cons(w, x, ixI^L, ixO^L, idim, f)
1364  use mod_dust, only: dust_get_flux
1365 
1366  integer, intent(in) :: ixI^L, ixO^L, idim
1367  double precision, intent(in) :: w(ixI^S, 1:nw), x(ixI^S, 1:ndim)
1368  double precision, intent(out) :: f(ixI^S, nwflux)
1369  double precision :: pth(ixI^S), v(ixI^S),frame_vel(ixI^S)
1370  integer :: idir, itr
1371 
1372  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1373  call rhd_get_v(w, x, ixi^l, ixo^l, idim, v)
1374 
1375  f(ixo^s, rho_) = v(ixo^s) * w(ixo^s, rho_)
1376 
1377  ! Momentum flux is v_i*m_i, +p in direction idim
1378  do idir = 1, ndir
1379  f(ixo^s, mom(idir)) = v(ixo^s) * w(ixo^s, mom(idir))
1380  end do
1381 
1382  f(ixo^s, mom(idim)) = f(ixo^s, mom(idim)) + pth(ixo^s)
1383 
1384  if(rhd_energy) then
1385  ! Energy flux is v_i*(e + p)
1386  f(ixo^s, e_) = v(ixo^s) * (w(ixo^s, e_) + pth(ixo^s))
1387  end if
1388 
1389  if (rhd_radiation_advection) then
1390  f(ixo^s, r_e) = v(ixo^s) * w(ixo^s,r_e)
1391  else
1392  f(ixo^s, r_e) = zero
1393  endif
1394 
1395  do itr = 1, rhd_n_tracer
1396  f(ixo^s, tracer(itr)) = v(ixo^s) * w(ixo^s, tracer(itr))
1397  end do
1398 
1399  ! Dust fluxes
1400  if (rhd_dust) then
1401  call dust_get_flux(w, x, ixi^l, ixo^l, idim, f)
1402  end if
1403 
1404  end subroutine rhd_get_flux_cons
1405 
1406  ! Calculate flux f_idim[iw]
1407  subroutine rhd_get_flux(wC, w, x, ixI^L, ixO^L, idim, f)
1409  use mod_dust, only: dust_get_flux_prim
1410  use mod_viscosity, only: visc_get_flux_prim ! viscInDiv
1411 
1412  integer, intent(in) :: ixI^L, ixO^L, idim
1413  ! conservative w
1414  double precision, intent(in) :: wC(ixI^S, 1:nw)
1415  ! primitive w
1416  double precision, intent(in) :: w(ixI^S, 1:nw)
1417  double precision, intent(in) :: x(ixI^S, 1:ndim)
1418  double precision, intent(out) :: f(ixI^S, nwflux)
1419  double precision :: pth(ixI^S),frame_vel(ixI^S)
1420  integer :: idir, itr
1421 
1422  if (rhd_energy) then
1423  pth(ixo^s) = w(ixo^s,p_)
1424  else
1425  call rhd_get_pthermal(wc, x, ixi^l, ixo^l, pth)
1426  end if
1427 
1428  f(ixo^s, rho_) = w(ixo^s,mom(idim)) * w(ixo^s, rho_)
1429 
1430  ! Momentum flux is v_i*m_i, +p in direction idim
1431  do idir = 1, ndir
1432  f(ixo^s, mom(idir)) = w(ixo^s,mom(idim)) * wc(ixo^s, mom(idir))
1433  end do
1434 
1435  f(ixo^s, mom(idim)) = f(ixo^s, mom(idim)) + pth(ixo^s)
1436 
1437  if(rhd_energy) then
1438  ! Energy flux is v_i*(e + p)
1439  f(ixo^s, e_) = w(ixo^s,mom(idim)) * (wc(ixo^s, e_) + w(ixo^s,p_))
1440  end if
1441 
1442  if (rhd_radiation_advection) then
1443  f(ixo^s, r_e) = w(ixo^s,mom(idim)) * wc(ixo^s,r_e)
1444  else
1445  f(ixo^s, r_e) = zero
1446  endif
1447 
1448  do itr = 1, rhd_n_tracer
1449  f(ixo^s, tracer(itr)) = w(ixo^s,mom(idim)) * w(ixo^s, tracer(itr))
1450  end do
1451 
1452  ! Dust fluxes
1453  if (rhd_dust) then
1454  call dust_get_flux_prim(w, x, ixi^l, ixo^l, idim, f)
1455  end if
1456 
1457  ! Viscosity fluxes - viscInDiv
1458  if (rhd_viscosity) then
1459  call visc_get_flux_prim(w, x, ixi^l, ixo^l, idim, f, rhd_energy)
1460  endif
1461 
1462  end subroutine rhd_get_flux
1463 
1464  !> Add geometrical source terms to w
1465  !>
1466  !> Notice that the expressions of the geometrical terms depend only on ndir,
1467  !> not ndim. Eg, they are the same in 2.5D and in 3D, for any geometry.
1468  !>
1469  subroutine rhd_add_source_geom(qdt, dtfactor, ixI^L, ixO^L, wCT, wprim, w, x)
1472  use mod_viscosity, only: visc_add_source_geom ! viscInDiv
1475  use mod_geometry
1476  integer, intent(in) :: ixI^L, ixO^L
1477  double precision, intent(in) :: qdt, dtfactor, x(ixI^S, 1:ndim)
1478  double precision, intent(inout) :: wCT(ixI^S, 1:nw), wprim(ixI^S,1:nw), w(ixI^S, 1:nw)
1479  ! to change and to set as a parameter in the parfile once the possibility to
1480  ! solve the equations in an angular momentum conserving form has been
1481  ! implemented (change tvdlf.t eg)
1482  double precision :: pth(ixI^S), source(ixI^S), minrho
1483  integer :: iw,idir, h1x^L{^NOONED, h2x^L}
1484  integer :: mr_,mphi_ ! Polar var. names
1485  integer :: irho, ifluid, n_fluids
1486  double precision :: exp_factor(ixI^S), del_exp_factor(ixI^S), exp_factor_primitive(ixI^S)
1487 
1488  if (rhd_dust) then
1489  n_fluids = 1 + dust_n_species
1490  else
1491  n_fluids = 1
1492  end if
1493 
1494  select case (coordinate)
1495 
1496  case(cartesian_expansion)
1497  !the user provides the functions of exp_factor and del_exp_factor
1498  if(associated(usr_set_surface)) call usr_set_surface(ixi^l,x,block%dx,exp_factor,del_exp_factor,exp_factor_primitive)
1499  if(rhd_energy) then
1500  source(ixo^s) =wprim(ixo^s, p_)
1501  else
1502  if(.not. associated(usr_set_pthermal)) then
1503  source(ixo^s)=rhd_adiab * wprim(ixo^s, rho_)**rhd_gamma
1504  else
1505  call usr_set_pthermal(wct,x,ixi^l,ixo^l,source)
1506  end if
1507  end if
1508  source(ixo^s) = source(ixo^s)*del_exp_factor(ixo^s)/exp_factor(ixo^s)
1509  w(ixo^s,mom(1)) = w(ixo^s,mom(1)) + qdt*source(ixo^s)
1510 
1511  case (cylindrical)
1512  if ((rhd_radiation_formalism .eq. 'fld') .or. (rhd_radiation_formalism .eq. 'afld')) then
1513  call mpistop("Diffusion term not implemented yet with cylkindrical geometries")
1514  end if
1515 
1516  do ifluid = 0, n_fluids-1
1517  ! s[mr]=(pthermal+mphi**2/rho)/radius
1518  if (ifluid == 0) then
1519  ! gas
1520  irho = rho_
1521  mr_ = mom(r_)
1522  if(phi_>0) mphi_ = mom(phi_)
1523  if(rhd_energy) then
1524  source(ixo^s) =wprim(ixo^s, p_)
1525  else
1526  if(.not. associated(usr_set_pthermal)) then
1527  source(ixo^s)=rhd_adiab * wprim(ixo^s, rho_)**rhd_gamma
1528  else
1529  call usr_set_pthermal(wct,x,ixi^l,ixo^l,source)
1530  end if
1531  end if
1532  minrho = 0.0d0
1533  else
1534  ! dust : no pressure
1535  irho = dust_rho(ifluid)
1536  mr_ = dust_mom(r_, ifluid)
1537  if(phi_>0) mphi_ = dust_mom(phi_, ifluid)
1538  source(ixi^s) = zero
1539  minrho = 0.0d0
1540  end if
1541  if (phi_ > 0) then
1542  source(ixo^s) = source(ixo^s) + wprim(ixo^s, mphi_)**2 * wprim(ixo^s, irho)
1543  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1544  ! s[mphi]=(-vphi*vr*rho)/radius
1545  source(ixo^s) = -wprim(ixo^s, mphi_) * wprim(ixo^s, mr_) * wprim(ixo^s, irho)
1546  w(ixo^s, mphi_) = w(ixo^s, mphi_) + qdt * source(ixo^s) / x(ixo^s, r_)
1547  else
1548  ! s[mr]=2pthermal/radius
1549  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1550  end if
1551  end do
1552  case (spherical)
1553 
1554  if ((rhd_radiation_formalism .eq. 'fld') .or. (rhd_radiation_formalism .eq. 'afld')) then
1555  call mpistop("Diffusion term not implemented yet with spherical geometries")
1556  end if
1557 
1558  if (rhd_dust) then
1559  call mpistop("Dust geom source terms not implemented yet with spherical geometries")
1560  end if
1561  mr_ = mom(r_)
1562  if(phi_>0) mphi_ = mom(phi_)
1563  h1x^l=ixo^l-kr(1,^d); {^nooned h2x^l=ixo^l-kr(2,^d);}
1564  ! s[mr]=((vtheta**2+vphi**2)*rho+2*p)/r
1565  if(rhd_energy) then
1566  pth(ixo^s) =wprim(ixo^s, p_)
1567  else
1568  if(.not. associated(usr_set_pthermal)) then
1569  pth(ixo^s)=rhd_adiab * wprim(ixo^s, rho_)**rhd_gamma
1570  else
1571  call usr_set_pthermal(wct,x,ixi^l,ixo^l,pth)
1572  end if
1573  end if
1574  source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1575  *(block%surfaceC(ixo^s, 1) - block%surfaceC(h1x^s, 1)) &
1576  /block%dvolume(ixo^s)
1577  do idir = 2, ndir
1578  source(ixo^s) = source(ixo^s) + wprim(ixo^s, mom(idir))**2 * wprim(ixo^s, rho_)
1579  end do
1580  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, 1)
1581 
1582  {^nooned
1583  ! s[mtheta]=-(vr*vtheta*rho)/r+cot(theta)*(vphi**2*rho+p)/r
1584  source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1585  * (block%surfaceC(ixo^s, 2) - block%surfaceC(h2x^s, 2)) &
1586  / block%dvolume(ixo^s)
1587  if (ndir == 3) then
1588  source(ixo^s) = source(ixo^s) + (wprim(ixo^s, mom(3))**2 * wprim(ixo^s, rho_)) / tan(x(ixo^s, 2))
1589  end if
1590  source(ixo^s) = source(ixo^s) - (wprim(ixo^s, mom(2)) * wprim(ixo^s, mr_)) * wprim(ixo^s, rho_)
1591  w(ixo^s, mom(2)) = w(ixo^s, mom(2)) + qdt * source(ixo^s) / x(ixo^s, 1)
1592 
1593  if (ndir == 3) then
1594  ! s[mphi]=-(vphi*vr/rho)/r-cot(theta)*(vtheta*vphi/rho)/r
1595  source(ixo^s) = -(wprim(ixo^s, mom(3)) * wprim(ixo^s, mr_)) * wprim(ixo^s, rho_)&
1596  - (wprim(ixo^s, mom(2)) * wprim(ixo^s, mom(3))) * wprim(ixo^s, rho_) / tan(x(ixo^s, 2))
1597  w(ixo^s, mom(3)) = w(ixo^s, mom(3)) + qdt * source(ixo^s) / x(ixo^s, 1)
1598  end if
1599  }
1600  end select
1601 
1602  if (rhd_viscosity) call visc_add_source_geom(qdt,ixi^l,ixo^l,wprim,w,x)
1603 
1604  if (rhd_rotating_frame) then
1605  if (rhd_dust) then
1606  call mpistop("Rotating frame not implemented yet with dust")
1607  else
1608  call rotating_frame_add_source(qdt,dtfactor,ixi^l,ixo^l,wprim,w,x)
1609  end if
1610  end if
1611 
1612  end subroutine rhd_add_source_geom
1613 
1614  ! w[iw]= w[iw]+qdt*S[wCT, qtC, x] where S is the source based on wCT within ixO
1615  subroutine rhd_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
1620  use mod_usr_methods, only: usr_gravity
1622 
1623  integer, intent(in) :: ixI^L, ixO^L
1624  double precision, intent(in) :: qdt,dtfactor
1625  double precision, intent(in) :: wCT(ixI^S, 1:nw),wCTprim(ixI^S,1:nw),x(ixI^S, 1:ndim)
1626  double precision, intent(inout) :: w(ixI^S, 1:nw)
1627  logical, intent(in) :: qsourcesplit
1628  logical, intent(inout) :: active
1629 
1630  double precision :: gravity_field(ixI^S, 1:ndim)
1631  integer :: idust, idim
1632 
1633  if(rhd_dust) then
1634  call dust_add_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1635  end if
1636 
1637  if(rhd_radiative_cooling) then
1638  call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1639  qsourcesplit,active, rc_fl)
1640  end if
1641 
1642  if(rhd_viscosity) then
1643  call viscosity_add_source(qdt,ixi^l,ixo^l,wct,w,x,&
1644  rhd_energy,qsourcesplit,active)
1645  end if
1646 
1647  if (rhd_gravity) then
1648  call gravity_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1649  rhd_energy,.false.,qsourcesplit,active)
1650 
1651  if (rhd_dust .and. qsourcesplit .eqv. grav_split) then
1652  active = .true.
1653 
1654  call usr_gravity(ixi^l, ixo^l, wct, x, gravity_field)
1655  do idust = 1, dust_n_species
1656  do idim = 1, ndim
1657  w(ixo^s, dust_mom(idim, idust)) = w(ixo^s, dust_mom(idim, idust)) &
1658  + qdt * gravity_field(ixo^s, idim) * wct(ixo^s, dust_rho(idust))
1659  end do
1660  end do
1661  end if
1662  end if
1663 
1664  !> This is where the radiation force and heating/cooling are added/
1665  call rhd_add_radiation_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1666 
1667  if(rhd_partial_ionization) then
1668  if(.not.qsourcesplit) then
1669  active = .true.
1670  call rhd_update_temperature(ixi^l,ixo^l,wct,w,x)
1671  end if
1672  end if
1673 
1674  end subroutine rhd_add_source
1675 
1676  subroutine rhd_add_radiation_source(qdt,ixI^L,ixO^L,wCT,w,x,qsourcesplit,active)
1677  use mod_constants
1679  use mod_usr_methods
1680  use mod_fld!, only: fld_get_diffcoef_central, get_fld_rad_force, get_fld_energy_interact
1681  use mod_afld!, only: afld_get_diffcoef_central, get_afld_rad_force, get_afld_energy_interact
1682 
1683  integer, intent(in) :: ixI^L, ixO^L
1684  double precision, intent(in) :: qdt, x(ixI^S,1:ndim)
1685  double precision, intent(in) :: wCT(ixI^S,1:nw)
1686  double precision, intent(inout) :: w(ixI^S,1:nw)
1687  logical, intent(in) :: qsourcesplit
1688  logical, intent(inout) :: active
1689  double precision :: cmax(ixI^S)
1690 
1691 
1692  select case(rhd_radiation_formalism)
1693  case('fld')
1694 
1695  if (fld_diff_scheme .eq. 'mg') call fld_get_diffcoef_central(w, wct, x, ixi^l, ixo^l)
1696  ! if (fld_diff_scheme .eq. 'mg') call set_mg_bounds(wCT, x, ixI^L, ixO^L)
1697 
1698  !> radiation force
1699  if (rhd_radiation_force) call get_fld_rad_force(qdt,ixi^l,ixo^l,wct,w,x,&
1700  rhd_energy,qsourcesplit,active)
1701 
1702  call rhd_handle_small_values(.true., w, x, ixi^l, ixo^l, 'fld_e_interact')
1703 
1704  !> photon tiring, heating and cooling
1705  if (rhd_energy) then
1706  if (rhd_energy_interact) call get_fld_energy_interact(qdt,ixi^l,ixo^l,wct,w,x,&
1707  rhd_energy,qsourcesplit,active)
1708  endif
1709 
1710  case('afld')
1711 
1712  if (fld_diff_scheme .eq. 'mg') call afld_get_diffcoef_central(w, wct, x, ixi^l, ixo^l)
1713 
1714  !> radiation force
1715  if (rhd_radiation_force) call get_afld_rad_force(qdt,ixi^l,ixo^l,wct,w,x,&
1716  rhd_energy,qsourcesplit,active)
1717 
1718  call rhd_handle_small_values(.true., w, x, ixi^l, ixo^l, 'fld_e_interact')
1719 
1720  !> photon tiring, heating and cooling
1721  if (rhd_energy) then
1722  if (rhd_energy_interact) call get_afld_energy_interact(qdt,ixi^l,ixo^l,wct,w,x,&
1723  rhd_energy,qsourcesplit,active)
1724  endif
1725 
1726  case default
1727  call mpistop('Radiation formalism unknown')
1728  end select
1729 
1730  ! ! !> NOT necessary for calculation, just want to know the grid-dependent-timestep
1731  ! call rhd_get_cmax(w, x, ixI^L, ixO^L, 2, cmax)
1732  ! w(ixI^S,i_test) = cmax(ixI^S)
1733 
1734  end subroutine rhd_add_radiation_source
1735 
1736  subroutine rhd_get_dt(w, ixI^L, ixO^L, dtnew, dx^D, x)
1738  use mod_dust, only: dust_get_dt
1740  use mod_viscosity, only: viscosity_get_dt
1741  use mod_gravity, only: gravity_get_dt
1742  use mod_fld, only: fld_radforce_get_dt
1743  use mod_afld, only: afld_radforce_get_dt
1744 
1745  integer, intent(in) :: ixI^L, ixO^L
1746  double precision, intent(in) :: dx^D, x(ixI^S, 1:^ND)
1747  double precision, intent(in) :: w(ixI^S, 1:nw)
1748  double precision, intent(inout) :: dtnew
1749 
1750  dtnew = bigdouble
1751 
1752  if (.not. dt_c) then
1753 
1754  if(rhd_dust) then
1755  call dust_get_dt(w, ixi^l, ixo^l, dtnew, dx^d, x)
1756  end if
1757 
1758  if(rhd_radiation_force) then
1759  select case(rhd_radiation_formalism)
1760  case('fld')
1761  call fld_radforce_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1762  case('afld')
1763  call afld_radforce_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1764  case default
1765  call mpistop('Radiation formalism unknown')
1766  end select
1767  endif
1768 
1769  if(rhd_radiative_cooling) then
1770  call cooling_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x,rc_fl)
1771  end if
1772 
1773  if(rhd_viscosity) then
1774  call viscosity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1775  end if
1776 
1777  if(rhd_gravity) then
1778  call gravity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1779  end if
1780  else
1781  {^ifoned dtnew = dx1*unit_velocity/const_c}
1782  {^nooned dtnew = min(dx^d*unit_velocity/const_c)}
1783  endif
1784 
1785  end subroutine rhd_get_dt
1786 
1787  function rhd_kin_en(w, ixI^L, ixO^L, inv_rho) result(ke)
1788  use mod_global_parameters, only: nw, ndim
1789  integer, intent(in) :: ixi^l, ixo^l
1790  double precision, intent(in) :: w(ixi^s, nw)
1791  double precision :: ke(ixo^s)
1792  double precision, intent(in), optional :: inv_rho(ixo^s)
1793 
1794  if (present(inv_rho)) then
1795  ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) * inv_rho
1796  else
1797  ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) / w(ixo^s, rho_)
1798  end if
1799  end function rhd_kin_en
1800 
1801  function rhd_inv_rho(w, ixI^L, ixO^L) result(inv_rho)
1802  use mod_global_parameters, only: nw, ndim
1803  integer, intent(in) :: ixi^l, ixo^l
1804  double precision, intent(in) :: w(ixi^s, nw)
1805  double precision :: inv_rho(ixo^s)
1806 
1807  ! Can make this more robust
1808  inv_rho = 1.0d0 / w(ixo^s, rho_)
1809  end function rhd_inv_rho
1810 
1811  subroutine rhd_handle_small_values(primitive, w, x, ixI^L, ixO^L, subname)
1812  ! handles hydro (density,pressure,velocity) bootstrapping
1813  ! any negative dust density is flagged as well (and throws an error)
1814  ! small_values_method=replace also for dust
1816  use mod_small_values
1818  logical, intent(in) :: primitive
1819  integer, intent(in) :: ixI^L,ixO^L
1820  double precision, intent(inout) :: w(ixI^S,1:nw)
1821  double precision, intent(in) :: x(ixI^S,1:ndim)
1822  character(len=*), intent(in) :: subname
1823 
1824  integer :: n,idir
1825  logical :: flag(ixI^S,1:nw)
1826 
1827  call rhd_check_w(primitive, ixi^l, ixo^l, w, flag)
1828 
1829  if (any(flag)) then
1830  select case (small_values_method)
1831  case ("replace")
1832  where(flag(ixo^s,rho_)) w(ixo^s,rho_) = small_density
1833  do idir = 1, ndir
1834  if(small_values_fix_iw(mom(idir))) then
1835  where(flag(ixo^s,rho_)) w(ixo^s, mom(idir)) = 0.0d0
1836  end if
1837  end do
1838 
1839  if (small_values_fix_iw(r_e)) then
1840  where(flag(ixo^s,r_e)) w(ixo^s,r_e) = small_r_e
1841  end if
1842 
1843  if(rhd_energy)then
1844  if(small_values_fix_iw(e_)) then
1845  if(primitive) then
1846  where(flag(ixo^s,rho_)) w(ixo^s, p_) = small_pressure
1847  else
1848  where(flag(ixo^s,rho_)) w(ixo^s, e_) = small_e + rhd_kin_en(w,ixi^l,ixo^l)
1849  endif
1850  end if
1851  endif
1852 
1853  if(rhd_energy) then
1854  if(primitive) then
1855  where(flag(ixo^s,e_)) w(ixo^s,p_) = small_pressure
1856  else
1857  where(flag(ixo^s,e_))
1858  ! Add kinetic energy
1859  w(ixo^s,e_) = small_e + rhd_kin_en(w,ixi^l,ixo^l)
1860  end where
1861  end if
1862  end if
1863 
1864  if(rhd_dust)then
1865  do n=1,dust_n_species
1866  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1867  do idir = 1, ndir
1868  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1869  enddo
1870  enddo
1871  endif
1872  case ("average")
1873  if(primitive)then
1874  ! averaging for all primitive fields, including dust
1875  call small_values_average(ixi^l, ixo^l, w, x, flag)
1876  else
1877  ! do averaging of density
1878  call small_values_average(ixi^l, ixo^l, w, x, flag, rho_)
1879  if(rhd_energy) then
1880  ! do averaging of pressure
1881  w(ixi^s,p_)=(rhd_gamma-1.d0)*(w(ixi^s,e_) &
1882  -0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_))
1883  call small_values_average(ixi^l, ixo^l, w, x, flag, p_)
1884  w(ixi^s,e_)=w(ixi^s,p_)/(rhd_gamma-1.d0) &
1885  +0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_)
1886  end if
1887  ! do averaging of radiation energy
1888  call small_values_average(ixi^l, ixo^l, w, x, flag, r_e)
1889  if(rhd_dust)then
1890  do n=1,dust_n_species
1891  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1892  do idir = 1, ndir
1893  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1894  enddo
1895  enddo
1896  endif
1897  endif
1898  case default
1899  if(.not.primitive) then
1900  !convert w to primitive
1901  ! Calculate pressure = (gamma-1) * (e-ek)
1902  if(rhd_energy) then
1903  w(ixo^s,p_)=(rhd_gamma-1.d0)*(w(ixo^s,e_)-rhd_kin_en(w,ixi^l,ixo^l))
1904  end if
1905  ! Convert gas momentum to velocity
1906  do idir = 1, ndir
1907  w(ixo^s, mom(idir)) = w(ixo^s, mom(idir))/w(ixo^s,rho_)
1908  end do
1909  end if
1910  ! NOTE: dust entries may still have conserved values here
1911  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
1912  end select
1913  end if
1914  end subroutine rhd_handle_small_values
1915 
1916  subroutine rfactor_from_temperature_ionization(w,x,ixI^L,ixO^L,Rfactor)
1919  integer, intent(in) :: ixI^L, ixO^L
1920  double precision, intent(in) :: w(ixI^S,1:nw)
1921  double precision, intent(in) :: x(ixI^S,1:ndim)
1922  double precision, intent(out):: Rfactor(ixI^S)
1923 
1924  double precision :: iz_H(ixO^S),iz_He(ixO^S)
1925 
1926  call ionization_degree_from_temperature(ixi^l,ixo^l,w(ixi^s,te_),iz_h,iz_he)
1927  ! assume the first and second ionization of Helium have the same degree
1928  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
1929 
1931 
1932  subroutine rfactor_from_constant_ionization(w,x,ixI^L,ixO^L,Rfactor)
1934  integer, intent(in) :: ixI^L, ixO^L
1935  double precision, intent(in) :: w(ixI^S,1:nw)
1936  double precision, intent(in) :: x(ixI^S,1:ndim)
1937  double precision, intent(out):: Rfactor(ixI^S)
1938 
1939  rfactor(ixo^s)=rr
1940 
1941  end subroutine rfactor_from_constant_ionization
1942 
1943  subroutine rhd_update_temperature(ixI^L,ixO^L,wCT,w,x)
1946 
1947  integer, intent(in) :: ixI^L, ixO^L
1948  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
1949  double precision, intent(inout) :: w(ixI^S,1:nw)
1950 
1951  double precision :: iz_H(ixO^S),iz_He(ixO^S), pth(ixI^S)
1952 
1953  call ionization_degree_from_temperature(ixi^l,ixo^l,wct(ixi^s,te_),iz_h,iz_he)
1954 
1955  call rhd_get_pthermal(w,x,ixi^l,ixo^l,pth)
1956 
1957  w(ixo^s,te_)=(2.d0+3.d0*he_abundance)*pth(ixo^s)/(w(ixo^s,rho_)*(1.d0+iz_h(ixo^s)+&
1958  he_abundance*(iz_he(ixo^s)*(iz_he(ixo^s)+1.d0)+1.d0)))
1959 
1960  end subroutine rhd_update_temperature
1961 
1962 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:58
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:898
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:530
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:47
subroutine, public dust_get_cmax(w, x, ixIL, ixOL, idim, cmax, cmin)
Definition: mod_dust.t:1011
integer, public, protected dust_n_species
The number of dust species.
Definition: mod_dust.t:37
integer, dimension(:), allocatable, public, protected dust_rho
Indices of the dust densities.
Definition: mod_dust.t:44
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_get_cmax_prim(w, x, ixIL, ixOL, idim, cmax, cmin)
Definition: mod_dust.t:1035
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.
double precision, 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 for MHD or 1D HD.
logical fix_small_values
fix small values with average or replace methods
logical crash
Save a snapshot before crash a run met unphysical values.
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
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
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:87
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
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:997
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:944
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
subroutine rhd_add_source_geom(qdt, dtfactor, ixIL, ixOL, wCT, wprim, w, x)
Add geometrical source terms to w.
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:921
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:90
subroutine viscosity_init(phys_wider_stencil, phys_req_diagonal)
Initialize the module.
Definition: mod_viscosity.t:59
subroutine visc_add_source_geom(qdt, ixIL, ixOL, wCT, w, x)
subroutine, public visc_get_flux_prim(w, x, ixIL, ixOL, idim, f, energy)