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  ! Number of variables need reconstruction in w
352  nw_recon=nwflux
353 
354  if(rhd_trac) then
355  tcoff_ = var_set_wextra()
356  iw_tcoff=tcoff_
357  else
358  tcoff_ = -1
359  end if
360 
361  ! choose Rfactor in ideal gas law
362  if(rhd_partial_ionization) then
363  rhd_get_rfactor=>rfactor_from_temperature_ionization
364  phys_update_temperature => rhd_update_temperature
365  else if(associated(usr_rfactor)) then
366  rhd_get_rfactor=>usr_rfactor
367  else
368  rhd_get_rfactor=>rfactor_from_constant_ionization
369  end if
370 
371  ! initialize thermal conduction module
372  if (rhd_thermal_conduction) then
373  if (.not. rhd_energy) &
374  call mpistop("thermal conduction needs rhd_energy=T")
375  phys_req_diagonal = .true.
376 
377  call sts_init()
379 
380  allocate(tc_fl)
382  tc_fl%get_temperature_from_conserved => rhd_get_temperature_from_etot
386  tc_fl%get_temperature_from_eint => rhd_get_temperature_from_eint
387  tc_fl%get_rho => rhd_get_rho
388  tc_fl%e_ = e_
389  end if
390 
391  ! Initialize radiative cooling module
392  if (rhd_radiative_cooling) then
393  if (.not. rhd_energy) &
394  call mpistop("radiative cooling needs rhd_energy=T")
395  call radiative_cooling_init_params(rhd_gamma,he_abundance)
396  allocate(rc_fl)
398  rc_fl%get_rho => rhd_get_rho
399  rc_fl%get_pthermal => rhd_get_pthermal
400  rc_fl%get_var_Rfactor => rhd_get_rfactor
401  rc_fl%e_ = e_
402  rc_fl%Tcoff_ = tcoff_
403  end if
404  allocate(te_fl_rhd)
405  te_fl_rhd%get_rho=> rhd_get_rho
406  te_fl_rhd%get_pthermal=> rhd_get_pthermal
407  te_fl_rhd%get_var_Rfactor => rhd_get_rfactor
408 {^ifthreed
409  phys_te_images => rhd_te_images
410 }
411  ! Initialize viscosity module
412  if (rhd_viscosity) call viscosity_init(phys_wider_stencil,phys_req_diagonal)
413 
414  ! Initialize gravity module
415  if (rhd_gravity) call gravity_init()
416 
417  ! Initialize rotating_frame module
419 
420  ! Initialize particles module
421  if (rhd_particles) then
422  call particles_init()
423  phys_req_diagonal = .true.
424  end if
425 
426  ! Check whether custom flux types have been defined
427  if (.not. allocated(flux_type)) then
428  allocate(flux_type(ndir, nw))
429  flux_type = flux_default
430  else if (any(shape(flux_type) /= [ndir, nw])) then
431  call mpistop("phys_check error: flux_type has wrong shape")
432  end if
433 
434  nvector = 1 ! No. vector vars
435  allocate(iw_vector(nvector))
436  iw_vector(1) = mom(1) - 1
437 
438  !> Usefull constante
439  kbmpmua4 = unit_pressure**(-3.d0/4.d0)*unit_density*const_kb/(const_mp*fld_mu)*const_rad_a**(-1.d0/4.d0)
440  ! initialize ionization degree table
442 
443  end subroutine rhd_phys_init
444 
445 {^ifthreed
446  subroutine rhd_te_images()
449  select case(convert_type)
450  case('EIvtiCCmpi','EIvtuCCmpi')
452  case('ESvtiCCmpi','ESvtuCCmpi')
454  case('SIvtiCCmpi','SIvtuCCmpi')
456  case default
457  call mpistop("Error in synthesize emission: Unknown convert_type")
458  end select
459  end subroutine rhd_te_images
460 }
461 !!start th cond
462  ! wrappers for STS functions in thermal_conductivity module
463  ! which take as argument the tc_fluid (defined in the physics module)
464  subroutine rhd_sts_set_source_tc_rhd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
466  use mod_fix_conserve
468  integer, intent(in) :: ixI^L, ixO^L, igrid, nflux
469  double precision, intent(in) :: x(ixI^S,1:ndim)
470  double precision, intent(inout) :: wres(ixI^S,1:nw), w(ixI^S,1:nw)
471  double precision, intent(in) :: my_dt
472  logical, intent(in) :: fix_conserve_at_step
473  call sts_set_source_tc_hd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl)
474  end subroutine rhd_sts_set_source_tc_rhd
475 
476 
477  function rhd_get_tc_dt_rhd(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
478  !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para_i/rho)
479  !where tc_k_para_i=tc_k_para*B_i**2/B**2
480  !and T=p/rho
483 
484  integer, intent(in) :: ixi^l, ixo^l
485  double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
486  double precision, intent(in) :: w(ixi^s,1:nw)
487  double precision :: dtnew
488 
489  dtnew=get_tc_dt_hd(w,ixi^l,ixo^l,dx^d,x,tc_fl)
490  end function rhd_get_tc_dt_rhd
491 
492 
493  subroutine rhd_tc_handle_small_e(w, x, ixI^L, ixO^L, step)
494  ! move this in a different routine as in mhd if needed in more places
496  use mod_small_values
497 
498  integer, intent(in) :: ixI^L,ixO^L
499  double precision, intent(inout) :: w(ixI^S,1:nw)
500  double precision, intent(in) :: x(ixI^S,1:ndim)
501  integer, intent(in) :: step
502 
503  integer :: idir
504  logical :: flag(ixI^S,1:nw)
505  character(len=140) :: error_msg
506 
507  flag=.false.
508  where(w(ixo^s,e_)<small_e) flag(ixo^s,e_)=.true.
509  if(any(flag(ixo^s,e_))) then
510  select case (small_values_method)
511  case ("replace")
512  where(flag(ixo^s,e_)) w(ixo^s,e_)=small_e
513  case ("average")
514  call small_values_average(ixi^l, ixo^l, w, x, flag, e_)
515  case default
516  ! small values error shows primitive variables
517  w(ixo^s,e_)=w(ixo^s,e_)*(rhd_gamma - 1.0d0)
518  do idir = 1, ndir
519  w(ixo^s, iw_mom(idir)) = w(ixo^s, iw_mom(idir))/w(ixo^s,rho_)
520  end do
521  write(error_msg,"(a,i3)") "Thermal conduction step ", step
522  call small_values_error(w, x, ixi^l, ixo^l, flag, error_msg)
523  end select
524  end if
525  end subroutine rhd_tc_handle_small_e
526 
527  ! fill in tc_fluid fields from namelist
528  subroutine tc_params_read_rhd(fl)
530  use mod_global_parameters, only: unitpar
531  type(tc_fluid), intent(inout) :: fl
532  integer :: n
533  logical :: tc_saturate=.false.
534  double precision :: tc_k_para=0d0
535 
536  namelist /tc_list/ tc_saturate, tc_k_para
537 
538  do n = 1, size(par_files)
539  open(unitpar, file=trim(par_files(n)), status="old")
540  read(unitpar, tc_list, end=111)
541 111 close(unitpar)
542  end do
543  fl%tc_saturate = tc_saturate
544  fl%tc_k_para = tc_k_para
545 
546  end subroutine tc_params_read_rhd
547 
548  subroutine rhd_get_rho(w,x,ixI^L,ixO^L,rho)
550  integer, intent(in) :: ixI^L, ixO^L
551  double precision, intent(in) :: w(ixI^S,1:nw),x(ixI^S,1:ndim)
552  double precision, intent(out) :: rho(ixI^S)
553 
554  rho(ixo^s) = w(ixo^s,rho_)
555 
556  end subroutine rhd_get_rho
557 
558 !!end th cond
559 !!rad cool
560  subroutine rc_params_read(fl)
562  use mod_constants, only: bigdouble
563  use mod_basic_types, only: std_len
564  type(rc_fluid), intent(inout) :: fl
565  integer :: n
566  ! list parameters
567  integer :: ncool = 4000
568  double precision :: cfrac=0.1d0
569 
570  !> Name of cooling curve
571  character(len=std_len) :: coolcurve='JCcorona'
572 
573  !> Name of cooling method
574  character(len=std_len) :: coolmethod='exact'
575 
576  !> Fixed temperature not lower than tlow
577  logical :: Tfix=.false.
578 
579  !> Lower limit of temperature
580  double precision :: tlow=bigdouble
581 
582  !> Add cooling source in a split way (.true.) or un-split way (.false.)
583  logical :: rc_split=.false.
584 
585 
586  namelist /rc_list/ coolcurve, coolmethod, ncool, cfrac, tlow, tfix, rc_split
587 
588  do n = 1, size(par_files)
589  open(unitpar, file=trim(par_files(n)), status="old")
590  read(unitpar, rc_list, end=111)
591 111 close(unitpar)
592  end do
593 
594  fl%ncool=ncool
595  fl%coolcurve=coolcurve
596  fl%coolmethod=coolmethod
597  fl%tlow=tlow
598  fl%Tfix=tfix
599  fl%rc_split=rc_split
600  fl%cfrac=cfrac
601  end subroutine rc_params_read
602 !! end rad cool
603 
604  subroutine rhd_check_params
606  use mod_dust, only: dust_check_params
607 
608  if (.not. rhd_energy .and. rhd_pressure == 'adiabatic') then
609  if (rhd_gamma <= 0.0d0) call mpistop ("Error: rhd_gamma <= 0")
610  if (rhd_adiab < 0.0d0) call mpistop ("Error: rhd_adiab < 0")
612  elseif (rhd_pressure == 'Tcond') then
613  small_pressure = smalldouble
614  else
615  if (rhd_gamma <= 0.0d0 .or. rhd_gamma == 1.0d0) &
616  call mpistop ("Error: rhd_gamma <= 0 or rhd_gamma == 1.0")
617  small_e = small_pressure/(rhd_gamma - 1.0d0)
618  end if
619 
621 
622  if (rhd_dust) call dust_check_params()
623 
624  ! if (rhd_radiation_diffusion .and. (.not. use_imex_scheme) ) &
625  if (rhd_radiation_diffusion .and. (.not. use_imex_scheme) .and. ((rhd_radiation_formalism .eq. 'fld') .or. (rhd_radiation_formalism .eq. 'afld')) ) &
626  call mpistop("Use an IMEX scheme when doing FLD")
627 
628  if (use_multigrid) call rhd_set_mg_bounds()
629 
630  end subroutine rhd_check_params
631 
632  !> Set the boundaries for the diffusion of E
633  subroutine rhd_set_mg_bounds
636  use mod_usr_methods
637 
638  integer :: ib
639 
640  ! Set boundary conditions for the multigrid solver
641  do ib = 1, 2*ndim
642  select case (typeboundary(r_e, ib))
643  case (bc_symm)
644  ! d/dx u = 0
645  mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
646  mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
647  case (bc_asymm)
648  ! u = 0
649  mg%bc(ib, mg_iphi)%bc_type = mg_bc_dirichlet
650  mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
651  case (bc_cont)
652  ! d/dx u = 0
653  ! mg%bc(iB, mg_iphi)%bc_type = mg_bc_continuous
654  mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
655  mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
656  case (bc_periodic)
657  ! Nothing to do here
658  case (bc_noinflow)
659  call usr_special_mg_bc(ib)
660  case (bc_special)
661  call usr_special_mg_bc(ib)
662  case default
663  call mpistop("divE_multigrid warning: unknown b.c. ")
664  end select
665  end do
666  end subroutine rhd_set_mg_bounds
667 
670  double precision :: mp,kB
671  double precision :: a,b
672  ! Derive scaling units
673  if(si_unit) then
674  mp=mp_si
675  kb=kb_si
676  else
677  mp=mp_cgs
678  kb=kb_cgs
679  end if
680  if(eq_state_units) then
681  a = 1d0 + 4d0 * he_abundance
682  if(rhd_partial_ionization) then
683  b = 2.d0+3.d0*he_abundance
684  else
685  b = 1d0 + h_ion_fr + he_abundance*(he_ion_fr*(he_ion_fr2 + 1d0)+1d0)
686  end if
687  rr = 1d0
688  else
689  a = 1d0
690  b = 1d0
691  rr = (1d0 + h_ion_fr + he_abundance*(he_ion_fr*(he_ion_fr2 + 1d0)+1d0))/(1d0 + 4d0 * he_abundance)
692  end if
693  if(unit_density/=1.d0) then
695  else
696  ! unit of numberdensity is independent by default
698  end if
699  if(unit_velocity/=1.d0) then
702  else if(unit_pressure/=1.d0) then
705  else
706  ! unit of temperature is independent by default
709  end if
710  if(unit_time/=1.d0) then
712  else
713  ! unit of length is independent by default
715  end if
716 
717  !> Units for radiative flux and opacity
720 
721  end subroutine rhd_physical_units
722 
723  !> Returns logical argument flag where values are ok
724  subroutine rhd_check_w(primitive, ixI^L, ixO^L, w, flag)
726  use mod_dust, only: dust_check_w
727 
728  logical, intent(in) :: primitive
729  integer, intent(in) :: ixi^l, ixo^l
730  double precision, intent(in) :: w(ixi^s, nw)
731  logical, intent(inout) :: flag(ixi^s,1:nw)
732  double precision :: tmp(ixi^s)
733 
734  flag=.false.
735 
736  if (rhd_energy) then
737  if (primitive) then
738  where(w(ixo^s, e_) < small_pressure) flag(ixo^s,e_) = .true.
739  else
740  tmp(ixo^s) = (rhd_gamma - 1.0d0)*(w(ixo^s, e_) - &
741  rhd_kin_en(w, ixi^l, ixo^l))
742  where(tmp(ixo^s) < small_pressure) flag(ixo^s,e_) = .true.
743  endif
744  end if
745 
746  where(w(ixo^s, rho_) < small_density) flag(ixo^s,rho_) = .true.
747 
748  where(w(ixo^s, r_e) < small_r_e) flag(ixo^s,r_e) = .true.
749 
750  if(rhd_dust) call dust_check_w(ixi^l,ixo^l,w,flag)
751 
752  end subroutine rhd_check_w
753 
754  !> Transform primitive variables into conservative ones
755  subroutine rhd_to_conserved(ixI^L, ixO^L, w, x)
757  use mod_dust, only: dust_to_conserved
758  integer, intent(in) :: ixi^l, ixo^l
759  double precision, intent(inout) :: w(ixi^s, nw)
760  double precision, intent(in) :: x(ixi^s, 1:ndim)
761  double precision :: invgam
762  integer :: idir, itr
763 
764  !!if (fix_small_values) then
765  !! call rhd_handle_small_values(.true., w, x, ixI^L, ixO^L, 'rhd_to_conserved')
766  !!end if
767 
768  if (rhd_energy) then
769  invgam = 1.d0/(rhd_gamma - 1.0d0)
770  ! Calculate total energy from pressure and kinetic energy
771  w(ixo^s, e_) = w(ixo^s, e_) * invgam + &
772  0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) * w(ixo^s, rho_)
773  end if
774 
775  ! Convert velocity to momentum
776  do idir = 1, ndir
777  w(ixo^s, mom(idir)) = w(ixo^s, rho_) * w(ixo^s, mom(idir))
778  end do
779 
780  if (rhd_dust) then
781  call dust_to_conserved(ixi^l, ixo^l, w, x)
782  end if
783 
784  end subroutine rhd_to_conserved
785 
786  !> Transform conservative variables into primitive ones
787  subroutine rhd_to_primitive(ixI^L, ixO^L, w, x)
789  use mod_dust, only: dust_to_primitive
790  integer, intent(in) :: ixi^l, ixo^l
791  double precision, intent(inout) :: w(ixi^s, nw)
792  double precision, intent(in) :: x(ixi^s, 1:ndim)
793  integer :: itr, idir
794  double precision :: inv_rho(ixo^s)
795 
796  if (fix_small_values) then
797  call rhd_handle_small_values(.false., w, x, ixi^l, ixo^l, 'rhd_to_primitive')
798  end if
799 
800  inv_rho = 1.0d0 / w(ixo^s, rho_)
801 
802  if (rhd_energy) then
803  ! Compute pressure
804  w(ixo^s, e_) = (rhd_gamma - 1.0d0) * (w(ixo^s, e_) - &
805  rhd_kin_en(w, ixi^l, ixo^l, inv_rho))
806  end if
807 
808  ! Convert momentum to velocity
809  do idir = 1, ndir
810  w(ixo^s, mom(idir)) = w(ixo^s, mom(idir)) * inv_rho
811  end do
812 
813  ! Convert dust momentum to dust velocity
814  if (rhd_dust) then
815  call dust_to_primitive(ixi^l, ixo^l, w, x)
816  end if
817 
818  end subroutine rhd_to_primitive
819 
820  !> Transform internal energy to total energy
821  subroutine rhd_ei_to_e(ixI^L,ixO^L,w,x)
823  integer, intent(in) :: ixI^L, ixO^L
824  double precision, intent(inout) :: w(ixI^S, nw)
825  double precision, intent(in) :: x(ixI^S, 1:ndim)
826 
827  ! Calculate total energy from internal and kinetic energy
828  w(ixo^s,e_)=w(ixo^s,e_)&
829  +rhd_kin_en(w,ixi^l,ixo^l)
830 
831  end subroutine rhd_ei_to_e
832 
833  !> Transform total energy to internal energy
834  subroutine rhd_e_to_ei(ixI^L,ixO^L,w,x)
836  integer, intent(in) :: ixI^L, ixO^L
837  double precision, intent(inout) :: w(ixI^S, nw)
838  double precision, intent(in) :: x(ixI^S, 1:ndim)
839 
840  ! Calculate ei = e - ek
841  w(ixo^s,e_)=w(ixo^s,e_)&
842  -rhd_kin_en(w,ixi^l,ixo^l)
843 
844  end subroutine rhd_e_to_ei
845 
846  subroutine e_to_rhos(ixI^L, ixO^L, w, x)
848 
849  integer, intent(in) :: ixI^L, ixO^L
850  double precision :: w(ixI^S, nw)
851  double precision, intent(in) :: x(ixI^S, 1:ndim)
852 
853  if (rhd_energy) then
854  w(ixo^s, e_) = (rhd_gamma - 1.0d0) * w(ixo^s, rho_)**(1.0d0 - rhd_gamma) * &
855  (w(ixo^s, e_) - rhd_kin_en(w, ixi^l, ixo^l))
856  else
857  call mpistop("energy from entropy can not be used with -eos = iso !")
858  end if
859  end subroutine e_to_rhos
860 
861  subroutine rhos_to_e(ixI^L, ixO^L, w, x)
863 
864  integer, intent(in) :: ixI^L, ixO^L
865  double precision :: w(ixI^S, nw)
866  double precision, intent(in) :: x(ixI^S, 1:ndim)
867 
868  if (rhd_energy) then
869  w(ixo^s, e_) = w(ixo^s, rho_)**(rhd_gamma - 1.0d0) * w(ixo^s, e_) &
870  / (rhd_gamma - 1.0d0) + rhd_kin_en(w, ixi^l, ixo^l)
871  else
872  call mpistop("entropy from energy can not be used with -eos = iso !")
873  end if
874  end subroutine rhos_to_e
875 
876  !> Calculate v_i = m_i / rho within ixO^L
877  subroutine rhd_get_v(w, x, ixI^L, ixO^L, idim, v)
879  integer, intent(in) :: ixI^L, ixO^L, idim
880  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:ndim)
881  double precision, intent(out) :: v(ixI^S)
882 
883  v(ixo^s) = w(ixo^s, mom(idim)) / w(ixo^s, rho_)
884  end subroutine rhd_get_v
885 
886  !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
887  subroutine rhd_get_cmax(w, x, ixI^L, ixO^L, idim, cmax)
890  use mod_dust, only: dust_get_cmax_prim
891 
892  integer, intent(in) :: ixI^L, ixO^L, idim
893  ! w in primitive form
894  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S, 1:ndim)
895  double precision, intent(inout) :: cmax(ixI^S)
896 
897  if(rhd_energy) then
898  cmax(ixo^s)=dabs(w(ixo^s,mom(idim)))+dsqrt(rhd_gamma*w(ixo^s,p_)/w(ixo^s,rho_))
899  else
900  if (.not. associated(usr_set_pthermal)) then
901  select case (rhd_pressure)
902  case ('Trad')
903  cmax(ixo^s) = (w(ixo^s,r_e)*unit_pressure/const_rad_a)**0.25d0&
904  /unit_temperature*w(ixo^s, rho_)
905  case ('adiabatic')
906  cmax(ixo^s) = rhd_adiab * w(ixo^s, rho_)**rhd_gamma
907  case ('Tcond') !> Thermal conduction?!
908  cmax(ixo^s) = (rhd_gamma-1.d0)*w(ixo^s,r_e)
909  case default
910  call mpistop('rhd_pressure unknown, use Trad or adiabatic')
911  end select
912  else
913  call usr_set_pthermal(w,x,ixi^l,ixo^l,cmax)
914  end if
915  cmax(ixo^s)=dabs(w(ixo^s,mom(idim)))+dsqrt(rhd_gamma*cmax(ixo^s)/w(ixo^s,rho_))
916  end if
917 
918  if (rhd_dust) then
919  call dust_get_cmax_prim(w, x, ixi^l, ixo^l, idim, cmax)
920  end if
921  end subroutine rhd_get_cmax
922 
923  subroutine rhd_get_a2max(w,x,ixI^L,ixO^L,a2max)
925 
926  integer, intent(in) :: ixI^L, ixO^L
927  double precision, intent(in) :: w(ixI^S, nw), x(ixI^S,1:ndim)
928  double precision, intent(inout) :: a2max(ndim)
929  double precision :: a2(ixI^S,ndim,nw)
930  integer :: gxO^L,hxO^L,jxO^L,kxO^L,i,j
931 
932  a2=zero
933  do i = 1,ndim
934  !> 4th order
935  hxo^l=ixo^l-kr(i,^d);
936  gxo^l=hxo^l-kr(i,^d);
937  jxo^l=ixo^l+kr(i,^d);
938  kxo^l=jxo^l+kr(i,^d);
939  a2(ixo^s,i,1:nw)=dabs(-w(kxo^s,1:nw)+16.d0*w(jxo^s,1:nw)&
940  -30.d0*w(ixo^s,1:nw)+16.d0*w(hxo^s,1:nw)-w(gxo^s,1:nw))
941  a2max(i)=maxval(a2(ixo^s,i,1:nw))/12.d0/dxlevel(i)**2
942  end do
943  end subroutine rhd_get_a2max
944 
945  !> get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
946  subroutine rhd_get_tcutoff(ixI^L,ixO^L,w,x,tco_local,Tmax_local)
948  integer, intent(in) :: ixI^L,ixO^L
949  double precision, intent(in) :: x(ixI^S,1:ndim)
950  double precision, intent(inout) :: w(ixI^S,1:nw)
951  double precision, intent(out) :: tco_local, Tmax_local
952 
953  double precision, parameter :: trac_delta=0.25d0
954  double precision :: tmp1(ixI^S),Te(ixI^S),lts(ixI^S)
955  double precision :: ltr(ixI^S),ltrc,ltrp,tcoff(ixI^S)
956  integer :: jxO^L,hxO^L
957  integer :: jxP^L,hxP^L,ixP^L
958  logical :: lrlt(ixI^S)
959 
960  {^ifoned
961  call rhd_get_temperature_from_etot(w,x,ixi^l,ixi^l,te)
962 
963  tco_local=zero
964  tmax_local=maxval(te(ixo^s))
965  select case(rhd_trac_type)
966  case(0)
967  w(ixi^s,tcoff_)=3.d5/unit_temperature
968  case(1)
969  hxo^l=ixo^l-1;
970  jxo^l=ixo^l+1;
971  lts(ixo^s)=0.5d0*dabs(te(jxo^s)-te(hxo^s))/te(ixo^s)
972  lrlt=.false.
973  where(lts(ixo^s) > trac_delta)
974  lrlt(ixo^s)=.true.
975  end where
976  if(any(lrlt(ixo^s))) then
977  tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
978  end if
979  case(2)
980  !> iijima et al. 2021, LTRAC method
981  ltrc=1.5d0
982  ltrp=2.5d0
983  ixp^l=ixo^l^ladd1;
984  hxo^l=ixo^l-1;
985  jxo^l=ixo^l+1;
986  hxp^l=ixp^l-1;
987  jxp^l=ixp^l+1;
988  lts(ixp^s)=0.5d0*abs(te(jxp^s)-te(hxp^s))/te(ixp^s)
989  ltr(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
990  w(ixo^s,tcoff_)=te(ixo^s)*&
991  (0.25*(ltr(jxo^s)+two*ltr(ixo^s)+ltr(hxo^s)))**0.4d0
992  case default
993  call mpistop("mrhd_trac_type not allowed for 1D simulation")
994  end select
995  }
996  end subroutine rhd_get_tcutoff
997 
998  !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
999  subroutine rhd_get_cbounds(wLC, wRC, wLp, wRp, x, ixI^L, ixO^L, idim,Hspeed,cmax, cmin)
1001  use mod_dust, only: dust_get_cmax
1002  use mod_variables
1003 
1004  integer, intent(in) :: ixI^L, ixO^L, idim
1005  ! conservative left and right status
1006  double precision, intent(in) :: wLC(ixI^S, nw), wRC(ixI^S, nw)
1007  ! primitive left and right status
1008  double precision, intent(in) :: wLp(ixI^S, nw), wRp(ixI^S, nw)
1009  double precision, intent(in) :: x(ixI^S, 1:ndim)
1010  double precision, intent(inout) :: cmax(ixI^S,1:number_species)
1011  double precision, intent(inout), optional :: cmin(ixI^S,1:number_species)
1012  double precision, intent(in) :: Hspeed(ixI^S,1:number_species)
1013 
1014  double precision :: wmean(ixI^S,nw)
1015  double precision, dimension(ixI^S) :: umean, dmean, csoundL, csoundR, tmp1,tmp2,tmp3
1016  integer :: ix^D
1017 
1018  select case(boundspeed)
1019  case (1)
1020  ! This implements formula (10.52) from "Riemann Solvers and Numerical
1021  ! Methods for Fluid Dynamics" by Toro.
1022 
1023  tmp1(ixo^s)=dsqrt(wlp(ixo^s,rho_))
1024  tmp2(ixo^s)=dsqrt(wrp(ixo^s,rho_))
1025  tmp3(ixo^s)=1.d0/(dsqrt(wlp(ixo^s,rho_))+dsqrt(wrp(ixo^s,rho_)))
1026  umean(ixo^s)=(wlp(ixo^s,mom(idim))*tmp1(ixo^s)+wrp(ixo^s,mom(idim))*tmp2(ixo^s))*tmp3(ixo^s)
1027 
1028  if(rhd_energy) then
1029  csoundl(ixo^s)=rhd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
1030  csoundr(ixo^s)=rhd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
1031  else
1032  select case (rhd_pressure)
1033  case ('Trad')
1034  csoundl(ixo^s)=rhd_gamma*kbmpmua4*wlp(ixo^s,r_e)**(1.d0/4)
1035  csoundr(ixo^s)=rhd_gamma*kbmpmua4*wrp(ixo^s,r_e)**(1.d0/4)
1036  case ('adiabatic')
1037  csoundl(ixo^s)=rhd_gamma*rhd_adiab*wlp(ixo^s,rho_)**(rhd_gamma-one)
1038  csoundr(ixo^s)=rhd_gamma*rhd_adiab*wrp(ixo^s,rho_)**(rhd_gamma-one)
1039  end select
1040  end if
1041 
1042  dmean(ixo^s) = (tmp1(ixo^s)*csoundl(ixo^s)+tmp2(ixo^s)*csoundr(ixo^s)) * &
1043  tmp3(ixo^s) + 0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2 * &
1044  (wrp(ixo^s,mom(idim))-wlp(ixo^s,mom(idim)))**2
1045 
1046  dmean(ixo^s)=dsqrt(dmean(ixo^s))
1047  if(present(cmin)) then
1048  cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
1049  cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
1050  if(h_correction) then
1051  {do ix^db=ixomin^db,ixomax^db\}
1052  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1053  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1054  {end do\}
1055  end if
1056  else
1057  cmax(ixo^s,1)=dabs(umean(ixo^s))+dmean(ixo^s)
1058  end if
1059 
1060  if (rhd_dust) then
1061  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1062  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1063  end if
1064 
1065  case (2)
1066  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1067  tmp1(ixo^s)=wmean(ixo^s,mom(idim))/wmean(ixo^s,rho_)
1068  call rhd_get_csound2(wmean,x,ixi^l,ixo^l,csoundr)
1069  csoundr(ixo^s) = dsqrt(csoundr(ixo^s))
1070 
1071  if(present(cmin)) then
1072  cmax(ixo^s,1)=max(tmp1(ixo^s)+csoundr(ixo^s),zero)
1073  cmin(ixo^s,1)=min(tmp1(ixo^s)-csoundr(ixo^s),zero)
1074  if(h_correction) then
1075  {do ix^db=ixomin^db,ixomax^db\}
1076  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1077  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1078  {end do\}
1079  end if
1080  else
1081  cmax(ixo^s,1)=dabs(tmp1(ixo^s))+csoundr(ixo^s)
1082  end if
1083 
1084  if (rhd_dust) then
1085  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1086  end if
1087  case (3)
1088  ! Miyoshi 2005 JCP 208, 315 equation (67)
1089  if(rhd_energy) then
1090  csoundl(ixo^s)=rhd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
1091  csoundr(ixo^s)=rhd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
1092  else
1093  select case (rhd_pressure)
1094  case ('Trad')
1095  csoundl(ixo^s)=rhd_gamma*kbmpmua4*wlp(ixo^s,r_e)**(1.d0/4)
1096  csoundr(ixo^s)=rhd_gamma*kbmpmua4*wrp(ixo^s,r_e)**(1.d0/4)
1097  case ('adiabatic')
1098  csoundl(ixo^s)=rhd_gamma*rhd_adiab*wlp(ixo^s,rho_)**(rhd_gamma-one)
1099  csoundr(ixo^s)=rhd_gamma*rhd_adiab*wrp(ixo^s,rho_)**(rhd_gamma-one)
1100  end select
1101  end if
1102  csoundl(ixo^s)=max(dsqrt(csoundl(ixo^s)),dsqrt(csoundr(ixo^s)))
1103  if(present(cmin)) then
1104  cmin(ixo^s,1)=min(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))-csoundl(ixo^s)
1105  cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
1106  if(h_correction) then
1107  {do ix^db=ixomin^db,ixomax^db\}
1108  cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1109  cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1110  {end do\}
1111  end if
1112  else
1113  cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
1114  end if
1115  if (rhd_dust) then
1116  wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1117  call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1118  end if
1119  end select
1120 
1121  end subroutine rhd_get_cbounds
1122 
1123  !> Calculate the square of the thermal sound speed csound2 within ixO^L.
1124  !> csound2=gamma*p/rho
1125  subroutine rhd_get_csound2(w,x,ixI^L,ixO^L,csound2)
1127  integer, intent(in) :: ixi^l, ixo^l
1128  double precision, intent(in) :: w(ixi^s,nw)
1129  double precision, intent(in) :: x(ixi^s,1:ndim)
1130  double precision, intent(out) :: csound2(ixi^s)
1131 
1132  call rhd_get_ptot(w,x,ixi^l,ixo^l,csound2)
1133  csound2(ixo^s)=max(rhd_gamma,4.d0/3.d0)*csound2(ixo^s)/w(ixo^s,rho_)
1134  !> Turner & Stone 2001
1135 
1136  end subroutine rhd_get_csound2
1137 
1138  !> Calculate thermal pressure=(gamma-1)*(e-0.5*m**2/rho) within ixO^L
1139  subroutine rhd_get_pthermal(w, x, ixI^L, ixO^L, pth)
1143 
1144  integer, intent(in) :: ixi^l, ixo^l
1145  double precision, intent(in) :: w(ixi^s, 1:nw)
1146  double precision, intent(in) :: x(ixi^s, 1:ndim)
1147  double precision, intent(out):: pth(ixi^s)
1148  integer :: iw, ix^d
1149 
1150  if (rhd_energy) then
1151  pth(ixi^s) = (rhd_gamma - 1.d0) * (w(ixi^s, e_) - &
1152  0.5d0 * sum(w(ixi^s, mom(:))**2, dim=ndim+1) / w(ixi^s, rho_))
1153  else
1154  if (.not. associated(usr_set_pthermal)) then
1155  select case (rhd_pressure)
1156  case ('Trad')
1157  pth(ixi^s) = (w(ixi^s,r_e)*unit_pressure/const_rad_a)**0.25d0&
1158  /unit_temperature*w(ixi^s, rho_)
1159  case ('adiabatic')
1160  pth(ixi^s) = rhd_adiab * w(ixi^s, rho_)**rhd_gamma
1161  case ('Tcond') !> Thermal conduction?!
1162  pth(ixi^s) = (rhd_gamma-1.d0)*w(ixi^s,r_e)
1163  case default
1164  call mpistop('rhd_pressure unknown, use Trad or adiabatic')
1165  end select
1166  else
1167  call usr_set_pthermal(w,x,ixi^l,ixo^l,pth)
1168  end if
1169  end if
1170 
1171  if (fix_small_values) then
1172  {do ix^db= ixo^lim^db\}
1173  if(pth(ix^d)<small_pressure) then
1174  pth(ix^d)=small_pressure
1175  endif
1176  {enddo^d&\}
1177  else if (check_small_values) then
1178  {do ix^db= ixo^lim^db\}
1179  if(pth(ix^d)<small_pressure) then
1180  write(*,*) "Error: small value of gas pressure",pth(ix^d),&
1181  " encountered when call rhd_get_pthermal"
1182  write(*,*) "Iteration: ", it, " Time: ", global_time
1183  write(*,*) "Location: ", x(ix^d,:)
1184  write(*,*) "Cell number: ", ix^d
1185  do iw=1,nw
1186  write(*,*) trim(cons_wnames(iw)),": ",w(ix^d,iw)
1187  end do
1188  ! use erroneous arithmetic operation to crash the run
1189  if(trace_small_values) write(*,*) dsqrt(pth(ix^d)-bigdouble)
1190  write(*,*) "Saving status at the previous time step"
1191  crash=.true.
1192  end if
1193  {enddo^d&\}
1194  end if
1195 
1196  end subroutine rhd_get_pthermal
1197 
1198  !> Calculate radiation pressure within ixO^L
1199  subroutine rhd_get_pradiation(w, x, ixI^L, ixO^L, prad)
1201  use mod_fld
1202  use mod_afld
1203 
1204  integer, intent(in) :: ixi^l, ixo^l
1205  double precision, intent(in) :: w(ixi^s, 1:nw)
1206  double precision, intent(in) :: x(ixi^s, 1:ndim)
1207  double precision, intent(out):: prad(ixo^s, 1:ndim, 1:ndim)
1208 
1209  select case (rhd_radiation_formalism)
1210  case('fld')
1211  call fld_get_radpress(w, x, ixi^l, ixo^l, prad)
1212  case('afld')
1213  call afld_get_radpress(w, x, ixi^l, ixo^l, prad)
1214  case default
1215  call mpistop('Radiation formalism unknown')
1216  end select
1217  end subroutine rhd_get_pradiation
1218 
1219  !> calculates the sum of the gas pressure and max Prad tensor element
1220  subroutine rhd_get_ptot(w, x, ixI^L, ixO^L, ptot)
1222 
1223  integer, intent(in) :: ixi^l, ixo^l
1224  double precision, intent(in) :: w(ixi^s, 1:nw)
1225  double precision, intent(in) :: x(ixi^s, 1:ndim)
1226  double precision :: pth(ixi^s)
1227  double precision :: prad_tensor(ixo^s, 1:ndim, 1:ndim)
1228  double precision :: prad_max(ixo^s)
1229  double precision, intent(out):: ptot(ixi^s)
1230  integer :: ix^d
1231 
1232  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1233  call rhd_get_pradiation(w, x, ixi^l, ixo^l, prad_tensor)
1234 
1235  {do ix^d = ixomin^d,ixomax^d\}
1236  prad_max(ix^d) = maxval(prad_tensor(ix^d,:,:))
1237  {enddo\}
1238 
1239  !> filter cmax
1240  if (radio_acoustic_filter) then
1241  call rhd_radio_acoustic_filter(x, ixi^l, ixo^l, prad_max)
1242  endif
1243 
1244  ptot(ixo^s) = pth(ixo^s) + prad_max(ixo^s)
1245 
1246  end subroutine rhd_get_ptot
1247 
1248  !> Filter peaks in cmax due to radiation energy density, used for debugging
1249  subroutine rhd_radio_acoustic_filter(x, ixI^L, ixO^L, prad_max)
1251 
1252  integer, intent(in) :: ixI^L, ixO^L
1253  double precision, intent(in) :: x(ixI^S, 1:ndim)
1254  double precision, intent(inout) :: prad_max(ixO^S)
1255 
1256  double precision :: tmp_prad(ixI^S)
1257  integer :: ix^D, filter, idim
1258 
1259  if (size_ra_filter .lt. 1) call mpistop("ra filter of size < 1 makes no sense")
1260  if (size_ra_filter .gt. nghostcells) call mpistop("ra filter of size < nghostcells makes no sense")
1261 
1262  tmp_prad(ixi^s) = zero
1263  tmp_prad(ixo^s) = prad_max(ixo^s)
1264 
1265  do filter = 1,size_ra_filter
1266  do idim = 1,ndim
1267  ! {do ix^D = ixOmin^D+filter,ixOmax^D-filter\}
1268  {do ix^d = ixomin^d,ixomax^d\}
1269  prad_max(ix^d) = min(tmp_prad(ix^d),tmp_prad(ix^d+filter*kr(idim,^d)))
1270  prad_max(ix^d) = min(tmp_prad(ix^d),tmp_prad(ix^d-filter*kr(idim,^d)))
1271  {enddo\}
1272  enddo
1273  enddo
1274  end subroutine rhd_radio_acoustic_filter
1275 
1276  !> Calculate temperature=p/rho when in e_ the total energy is stored
1277  subroutine rhd_get_temperature_from_etot(w, x, ixI^L, ixO^L, res)
1279  integer, intent(in) :: ixI^L, ixO^L
1280  double precision, intent(in) :: w(ixI^S, 1:nw)
1281  double precision, intent(in) :: x(ixI^S, 1:ndim)
1282  double precision, intent(out):: res(ixI^S)
1283 
1284  double precision :: R(ixI^S)
1285 
1286  call rhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1287  call rhd_get_pthermal(w, x, ixi^l, ixo^l, res)
1288  res(ixo^s)=res(ixo^s)/(r(ixo^s)*w(ixo^s,rho_))
1289  end subroutine rhd_get_temperature_from_etot
1290 
1291 
1292  !> Calculate temperature=p/rho when in e_ the internal energy is stored
1293  subroutine rhd_get_temperature_from_eint(w, x, ixI^L, ixO^L, res)
1295  integer, intent(in) :: ixI^L, ixO^L
1296  double precision, intent(in) :: w(ixI^S, 1:nw)
1297  double precision, intent(in) :: x(ixI^S, 1:ndim)
1298  double precision, intent(out):: res(ixI^S)
1299  double precision :: R(ixI^S)
1300 
1301  call rhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1302  res(ixo^s) = (rhd_gamma - 1.0d0) * w(ixo^s, e_)/(w(ixo^s,rho_)*r(ixo^s))
1303  end subroutine rhd_get_temperature_from_eint
1304 
1305  !> Calculates gas temperature
1306  subroutine rhd_get_tgas(w, x, ixI^L, ixO^L, tgas)
1308 
1309  integer, intent(in) :: ixi^l, ixo^l
1310  double precision, intent(in) :: w(ixi^s, 1:nw)
1311  double precision, intent(in) :: x(ixi^s, 1:ndim)
1312  double precision :: pth(ixi^s)
1313  double precision, intent(out):: tgas(ixi^s)
1314 
1315  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1316  tgas(ixi^s) = pth(ixi^s)/w(ixi^s,rho_)
1317 
1318  end subroutine rhd_get_tgas
1319 
1320  !> Calculates radiation temperature
1321  subroutine rhd_get_trad(w, x, ixI^L, ixO^L, trad)
1323  use mod_constants
1324 
1325  integer, intent(in) :: ixi^l, ixo^l
1326  double precision, intent(in) :: w(ixi^s, 1:nw)
1327  double precision, intent(in) :: x(ixi^s, 1:ndim)
1328  double precision, intent(out):: trad(ixi^s)
1329 
1330  trad(ixi^s) = (w(ixi^s,r_e)*unit_pressure&
1331  /const_rad_a)**(1.d0/4.d0)/unit_temperature
1332 
1333  end subroutine rhd_get_trad
1334 
1335 
1336  !these are very similar to the subroutines without 1, used in mod_thermal_conductivity
1337  !but no check on whether energy variable is present
1338  subroutine rhd_ei_to_e1(ixI^L,ixO^L,w,x)
1340  integer, intent(in) :: ixI^L, ixO^L
1341  double precision, intent(inout) :: w(ixI^S, nw)
1342  double precision, intent(in) :: x(ixI^S, 1:ndim)
1343 
1344  ! Calculate total energy from internal and kinetic energy
1345  w(ixo^s,e_)=w(ixo^s,e_)&
1346  +rhd_kin_en(w,ixi^l,ixo^l)
1347 
1348  end subroutine rhd_ei_to_e1
1349 
1350  !> Transform total energy to internal energy
1351  !but no check on whether energy variable is present
1352  subroutine rhd_e_to_ei1(ixI^L,ixO^L,w,x)
1354  integer, intent(in) :: ixI^L, ixO^L
1355  double precision, intent(inout) :: w(ixI^S, nw)
1356  double precision, intent(in) :: x(ixI^S, 1:ndim)
1357 
1358  ! Calculate ei = e - ek
1359  w(ixo^s,e_)=w(ixo^s,e_)&
1360  -rhd_kin_en(w,ixi^l,ixo^l)
1361 
1362  end subroutine rhd_e_to_ei1
1363 
1364  ! Calculate flux f_idim[iw]
1365  subroutine rhd_get_flux_cons(w, x, ixI^L, ixO^L, idim, f)
1367  use mod_dust, only: dust_get_flux
1368 
1369  integer, intent(in) :: ixI^L, ixO^L, idim
1370  double precision, intent(in) :: w(ixI^S, 1:nw), x(ixI^S, 1:ndim)
1371  double precision, intent(out) :: f(ixI^S, nwflux)
1372  double precision :: pth(ixI^S), v(ixI^S),frame_vel(ixI^S)
1373  integer :: idir, itr
1374 
1375  call rhd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1376  call rhd_get_v(w, x, ixi^l, ixo^l, idim, v)
1377 
1378  f(ixo^s, rho_) = v(ixo^s) * w(ixo^s, rho_)
1379 
1380  ! Momentum flux is v_i*m_i, +p in direction idim
1381  do idir = 1, ndir
1382  f(ixo^s, mom(idir)) = v(ixo^s) * w(ixo^s, mom(idir))
1383  end do
1384 
1385  f(ixo^s, mom(idim)) = f(ixo^s, mom(idim)) + pth(ixo^s)
1386 
1387  if(rhd_energy) then
1388  ! Energy flux is v_i*(e + p)
1389  f(ixo^s, e_) = v(ixo^s) * (w(ixo^s, e_) + pth(ixo^s))
1390  end if
1391 
1392  if (rhd_radiation_advection) then
1393  f(ixo^s, r_e) = v(ixo^s) * w(ixo^s,r_e)
1394  else
1395  f(ixo^s, r_e) = zero
1396  endif
1397 
1398  do itr = 1, rhd_n_tracer
1399  f(ixo^s, tracer(itr)) = v(ixo^s) * w(ixo^s, tracer(itr))
1400  end do
1401 
1402  ! Dust fluxes
1403  if (rhd_dust) then
1404  call dust_get_flux(w, x, ixi^l, ixo^l, idim, f)
1405  end if
1406 
1407  end subroutine rhd_get_flux_cons
1408 
1409  ! Calculate flux f_idim[iw]
1410  subroutine rhd_get_flux(wC, w, x, ixI^L, ixO^L, idim, f)
1412  use mod_dust, only: dust_get_flux_prim
1413  use mod_viscosity, only: visc_get_flux_prim ! viscInDiv
1414 
1415  integer, intent(in) :: ixI^L, ixO^L, idim
1416  ! conservative w
1417  double precision, intent(in) :: wC(ixI^S, 1:nw)
1418  ! primitive w
1419  double precision, intent(in) :: w(ixI^S, 1:nw)
1420  double precision, intent(in) :: x(ixI^S, 1:ndim)
1421  double precision, intent(out) :: f(ixI^S, nwflux)
1422  double precision :: pth(ixI^S),frame_vel(ixI^S)
1423  integer :: idir, itr
1424 
1425  if (rhd_energy) then
1426  pth(ixo^s) = w(ixo^s,p_)
1427  else
1428  call rhd_get_pthermal(wc, x, ixi^l, ixo^l, pth)
1429  end if
1430 
1431  f(ixo^s, rho_) = w(ixo^s,mom(idim)) * w(ixo^s, rho_)
1432 
1433  ! Momentum flux is v_i*m_i, +p in direction idim
1434  do idir = 1, ndir
1435  f(ixo^s, mom(idir)) = w(ixo^s,mom(idim)) * wc(ixo^s, mom(idir))
1436  end do
1437 
1438  f(ixo^s, mom(idim)) = f(ixo^s, mom(idim)) + pth(ixo^s)
1439 
1440  if(rhd_energy) then
1441  ! Energy flux is v_i*(e + p)
1442  f(ixo^s, e_) = w(ixo^s,mom(idim)) * (wc(ixo^s, e_) + w(ixo^s,p_))
1443  end if
1444 
1445  if (rhd_radiation_advection) then
1446  f(ixo^s, r_e) = w(ixo^s,mom(idim)) * wc(ixo^s,r_e)
1447  else
1448  f(ixo^s, r_e) = zero
1449  endif
1450 
1451  do itr = 1, rhd_n_tracer
1452  f(ixo^s, tracer(itr)) = w(ixo^s,mom(idim)) * w(ixo^s, tracer(itr))
1453  end do
1454 
1455  ! Dust fluxes
1456  if (rhd_dust) then
1457  call dust_get_flux_prim(w, x, ixi^l, ixo^l, idim, f)
1458  end if
1459 
1460  ! Viscosity fluxes - viscInDiv
1461  if (rhd_viscosity) then
1462  call visc_get_flux_prim(w, x, ixi^l, ixo^l, idim, f, rhd_energy)
1463  endif
1464 
1465  end subroutine rhd_get_flux
1466 
1467  !> Add geometrical source terms to w
1468  !>
1469  !> Notice that the expressions of the geometrical terms depend only on ndir,
1470  !> not ndim. Eg, they are the same in 2.5D and in 3D, for any geometry.
1471  !>
1472  subroutine rhd_add_source_geom(qdt, dtfactor, ixI^L, ixO^L, wCT, wprim, w, x)
1475  use mod_viscosity, only: visc_add_source_geom ! viscInDiv
1478  use mod_geometry
1479  integer, intent(in) :: ixI^L, ixO^L
1480  double precision, intent(in) :: qdt, dtfactor, x(ixI^S, 1:ndim)
1481  double precision, intent(inout) :: wCT(ixI^S, 1:nw), wprim(ixI^S,1:nw), w(ixI^S, 1:nw)
1482  ! to change and to set as a parameter in the parfile once the possibility to
1483  ! solve the equations in an angular momentum conserving form has been
1484  ! implemented (change tvdlf.t eg)
1485  double precision :: pth(ixI^S), source(ixI^S), minrho
1486  integer :: iw,idir, h1x^L{^NOONED, h2x^L}
1487  integer :: mr_,mphi_ ! Polar var. names
1488  integer :: irho, ifluid, n_fluids
1489  double precision :: exp_factor(ixI^S), del_exp_factor(ixI^S), exp_factor_primitive(ixI^S)
1490 
1491  if (rhd_dust) then
1492  n_fluids = 1 + dust_n_species
1493  else
1494  n_fluids = 1
1495  end if
1496 
1497  select case (coordinate)
1498 
1499  case(cartesian_expansion)
1500  !the user provides the functions of exp_factor and del_exp_factor
1501  if(associated(usr_set_surface)) call usr_set_surface(ixi^l,x,block%dx,exp_factor,del_exp_factor,exp_factor_primitive)
1502  if(rhd_energy) then
1503  source(ixo^s) =wprim(ixo^s, p_)
1504  else
1505  if(.not. associated(usr_set_pthermal)) then
1506  source(ixo^s)=rhd_adiab * wprim(ixo^s, rho_)**rhd_gamma
1507  else
1508  call usr_set_pthermal(wct,x,ixi^l,ixo^l,source)
1509  end if
1510  end if
1511  source(ixo^s) = source(ixo^s)*del_exp_factor(ixo^s)/exp_factor(ixo^s)
1512  w(ixo^s,mom(1)) = w(ixo^s,mom(1)) + qdt*source(ixo^s)
1513 
1514  case (cylindrical)
1515  if ((rhd_radiation_formalism .eq. 'fld') .or. (rhd_radiation_formalism .eq. 'afld')) then
1516  call mpistop("Diffusion term not implemented yet with cylkindrical geometries")
1517  end if
1518 
1519  do ifluid = 0, n_fluids-1
1520  ! s[mr]=(pthermal+mphi**2/rho)/radius
1521  if (ifluid == 0) then
1522  ! gas
1523  irho = rho_
1524  mr_ = mom(r_)
1525  if(phi_>0) mphi_ = mom(phi_)
1526  if(rhd_energy) then
1527  source(ixo^s) =wprim(ixo^s, p_)
1528  else
1529  if(.not. associated(usr_set_pthermal)) then
1530  source(ixo^s)=rhd_adiab * wprim(ixo^s, rho_)**rhd_gamma
1531  else
1532  call usr_set_pthermal(wct,x,ixi^l,ixo^l,source)
1533  end if
1534  end if
1535  minrho = 0.0d0
1536  else
1537  ! dust : no pressure
1538  irho = dust_rho(ifluid)
1539  mr_ = dust_mom(r_, ifluid)
1540  if(phi_>0) mphi_ = dust_mom(phi_, ifluid)
1541  source(ixi^s) = zero
1542  minrho = 0.0d0
1543  end if
1544  if (phi_ > 0) then
1545  source(ixo^s) = source(ixo^s) + wprim(ixo^s, mphi_)**2 * wprim(ixo^s, irho)
1546  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1547  ! s[mphi]=(-vphi*vr*rho)/radius
1548  source(ixo^s) = -wprim(ixo^s, mphi_) * wprim(ixo^s, mr_) * wprim(ixo^s, irho)
1549  w(ixo^s, mphi_) = w(ixo^s, mphi_) + qdt * source(ixo^s) / x(ixo^s, r_)
1550  else
1551  ! s[mr]=2pthermal/radius
1552  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1553  end if
1554  end do
1555  case (spherical)
1556 
1557  if ((rhd_radiation_formalism .eq. 'fld') .or. (rhd_radiation_formalism .eq. 'afld')) then
1558  call mpistop("Diffusion term not implemented yet with spherical geometries")
1559  end if
1560 
1561  if (rhd_dust) then
1562  call mpistop("Dust geom source terms not implemented yet with spherical geometries")
1563  end if
1564  mr_ = mom(r_)
1565  if(phi_>0) mphi_ = mom(phi_)
1566  h1x^l=ixo^l-kr(1,^d); {^nooned h2x^l=ixo^l-kr(2,^d);}
1567  ! s[mr]=((vtheta**2+vphi**2)*rho+2*p)/r
1568  if(rhd_energy) then
1569  pth(ixo^s) =wprim(ixo^s, p_)
1570  else
1571  if(.not. associated(usr_set_pthermal)) then
1572  pth(ixo^s)=rhd_adiab * wprim(ixo^s, rho_)**rhd_gamma
1573  else
1574  call usr_set_pthermal(wct,x,ixi^l,ixo^l,pth)
1575  end if
1576  end if
1577  source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1578  *(block%surfaceC(ixo^s, 1) - block%surfaceC(h1x^s, 1)) &
1579  /block%dvolume(ixo^s)
1580  do idir = 2, ndir
1581  source(ixo^s) = source(ixo^s) + wprim(ixo^s, mom(idir))**2 * wprim(ixo^s, rho_)
1582  end do
1583  w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, 1)
1584 
1585  {^nooned
1586  ! s[mtheta]=-(vr*vtheta*rho)/r+cot(theta)*(vphi**2*rho+p)/r
1587  source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1588  * (block%surfaceC(ixo^s, 2) - block%surfaceC(h2x^s, 2)) &
1589  / block%dvolume(ixo^s)
1590  if (ndir == 3) then
1591  source(ixo^s) = source(ixo^s) + (wprim(ixo^s, mom(3))**2 * wprim(ixo^s, rho_)) / tan(x(ixo^s, 2))
1592  end if
1593  source(ixo^s) = source(ixo^s) - (wprim(ixo^s, mom(2)) * wprim(ixo^s, mr_)) * wprim(ixo^s, rho_)
1594  w(ixo^s, mom(2)) = w(ixo^s, mom(2)) + qdt * source(ixo^s) / x(ixo^s, 1)
1595 
1596  if (ndir == 3) then
1597  ! s[mphi]=-(vphi*vr/rho)/r-cot(theta)*(vtheta*vphi/rho)/r
1598  source(ixo^s) = -(wprim(ixo^s, mom(3)) * wprim(ixo^s, mr_)) * wprim(ixo^s, rho_)&
1599  - (wprim(ixo^s, mom(2)) * wprim(ixo^s, mom(3))) * wprim(ixo^s, rho_) / tan(x(ixo^s, 2))
1600  w(ixo^s, mom(3)) = w(ixo^s, mom(3)) + qdt * source(ixo^s) / x(ixo^s, 1)
1601  end if
1602  }
1603  end select
1604 
1605  if (rhd_viscosity) call visc_add_source_geom(qdt,ixi^l,ixo^l,wprim,w,x)
1606 
1607  if (rhd_rotating_frame) then
1608  if (rhd_dust) then
1609  call mpistop("Rotating frame not implemented yet with dust")
1610  else
1611  call rotating_frame_add_source(qdt,dtfactor,ixi^l,ixo^l,wprim,w,x)
1612  end if
1613  end if
1614 
1615  end subroutine rhd_add_source_geom
1616 
1617  ! w[iw]= w[iw]+qdt*S[wCT, qtC, x] where S is the source based on wCT within ixO
1618  subroutine rhd_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
1623  use mod_usr_methods, only: usr_gravity
1625 
1626  integer, intent(in) :: ixI^L, ixO^L
1627  double precision, intent(in) :: qdt,dtfactor
1628  double precision, intent(in) :: wCT(ixI^S, 1:nw),wCTprim(ixI^S,1:nw),x(ixI^S, 1:ndim)
1629  double precision, intent(inout) :: w(ixI^S, 1:nw)
1630  logical, intent(in) :: qsourcesplit
1631  logical, intent(inout) :: active
1632 
1633  double precision :: gravity_field(ixI^S, 1:ndim)
1634  integer :: idust, idim
1635 
1636  if(rhd_dust) then
1637  call dust_add_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1638  end if
1639 
1640  if(rhd_radiative_cooling) then
1641  call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1642  qsourcesplit,active, rc_fl)
1643  end if
1644 
1645  if(rhd_viscosity) then
1646  call viscosity_add_source(qdt,ixi^l,ixo^l,wct,w,x,&
1647  rhd_energy,qsourcesplit,active)
1648  end if
1649 
1650  if (rhd_gravity) then
1651  call gravity_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1652  rhd_energy,.false.,qsourcesplit,active)
1653 
1654  if (rhd_dust .and. qsourcesplit .eqv. grav_split) then
1655  active = .true.
1656 
1657  call usr_gravity(ixi^l, ixo^l, wct, x, gravity_field)
1658  do idust = 1, dust_n_species
1659  do idim = 1, ndim
1660  w(ixo^s, dust_mom(idim, idust)) = w(ixo^s, dust_mom(idim, idust)) &
1661  + qdt * gravity_field(ixo^s, idim) * wct(ixo^s, dust_rho(idust))
1662  end do
1663  end do
1664  end if
1665  end if
1666 
1667  !> This is where the radiation force and heating/cooling are added/
1668  call rhd_add_radiation_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1669 
1670  if(rhd_partial_ionization) then
1671  if(.not.qsourcesplit) then
1672  active = .true.
1673  call rhd_update_temperature(ixi^l,ixo^l,wct,w,x)
1674  end if
1675  end if
1676 
1677  end subroutine rhd_add_source
1678 
1679  subroutine rhd_add_radiation_source(qdt,ixI^L,ixO^L,wCT,w,x,qsourcesplit,active)
1680  use mod_constants
1682  use mod_usr_methods
1683  use mod_fld!, only: fld_get_diffcoef_central, get_fld_rad_force, get_fld_energy_interact
1684  use mod_afld!, only: afld_get_diffcoef_central, get_afld_rad_force, get_afld_energy_interact
1685 
1686  integer, intent(in) :: ixI^L, ixO^L
1687  double precision, intent(in) :: qdt, x(ixI^S,1:ndim)
1688  double precision, intent(in) :: wCT(ixI^S,1:nw)
1689  double precision, intent(inout) :: w(ixI^S,1:nw)
1690  logical, intent(in) :: qsourcesplit
1691  logical, intent(inout) :: active
1692  double precision :: cmax(ixI^S)
1693 
1694 
1695  select case(rhd_radiation_formalism)
1696  case('fld')
1697 
1698  if (fld_diff_scheme .eq. 'mg') call fld_get_diffcoef_central(w, wct, x, ixi^l, ixo^l)
1699  ! if (fld_diff_scheme .eq. 'mg') call set_mg_bounds(wCT, x, ixI^L, ixO^L)
1700 
1701  !> radiation force
1702  if (rhd_radiation_force) call get_fld_rad_force(qdt,ixi^l,ixo^l,wct,w,x,&
1703  rhd_energy,qsourcesplit,active)
1704 
1705  call rhd_handle_small_values(.true., w, x, ixi^l, ixo^l, 'fld_e_interact')
1706 
1707  !> photon tiring, heating and cooling
1708  if (rhd_energy) then
1709  if (rhd_energy_interact) call get_fld_energy_interact(qdt,ixi^l,ixo^l,wct,w,x,&
1710  rhd_energy,qsourcesplit,active)
1711  endif
1712 
1713  case('afld')
1714 
1715  if (fld_diff_scheme .eq. 'mg') call afld_get_diffcoef_central(w, wct, x, ixi^l, ixo^l)
1716 
1717  !> radiation force
1718  if (rhd_radiation_force) call get_afld_rad_force(qdt,ixi^l,ixo^l,wct,w,x,&
1719  rhd_energy,qsourcesplit,active)
1720 
1721  call rhd_handle_small_values(.true., w, x, ixi^l, ixo^l, 'fld_e_interact')
1722 
1723  !> photon tiring, heating and cooling
1724  if (rhd_energy) then
1725  if (rhd_energy_interact) call get_afld_energy_interact(qdt,ixi^l,ixo^l,wct,w,x,&
1726  rhd_energy,qsourcesplit,active)
1727  endif
1728 
1729  case default
1730  call mpistop('Radiation formalism unknown')
1731  end select
1732 
1733  ! ! !> NOT necessary for calculation, just want to know the grid-dependent-timestep
1734  ! call rhd_get_cmax(w, x, ixI^L, ixO^L, 2, cmax)
1735  ! w(ixI^S,i_test) = cmax(ixI^S)
1736 
1737  end subroutine rhd_add_radiation_source
1738 
1739  subroutine rhd_get_dt(w, ixI^L, ixO^L, dtnew, dx^D, x)
1741  use mod_dust, only: dust_get_dt
1743  use mod_viscosity, only: viscosity_get_dt
1744  use mod_gravity, only: gravity_get_dt
1745  use mod_fld, only: fld_radforce_get_dt
1746  use mod_afld, only: afld_radforce_get_dt
1747 
1748  integer, intent(in) :: ixI^L, ixO^L
1749  double precision, intent(in) :: dx^D, x(ixI^S, 1:^ND)
1750  double precision, intent(in) :: w(ixI^S, 1:nw)
1751  double precision, intent(inout) :: dtnew
1752 
1753  dtnew = bigdouble
1754 
1755  if (.not. dt_c) then
1756 
1757  if(rhd_dust) then
1758  call dust_get_dt(w, ixi^l, ixo^l, dtnew, dx^d, x)
1759  end if
1760 
1761  if(rhd_radiation_force) then
1762  select case(rhd_radiation_formalism)
1763  case('fld')
1764  call fld_radforce_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1765  case('afld')
1766  call afld_radforce_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1767  case default
1768  call mpistop('Radiation formalism unknown')
1769  end select
1770  endif
1771 
1772  if(rhd_radiative_cooling) then
1773  call cooling_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x,rc_fl)
1774  end if
1775 
1776  if(rhd_viscosity) then
1777  call viscosity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1778  end if
1779 
1780  if(rhd_gravity) then
1781  call gravity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1782  end if
1783  else
1784  {^ifoned dtnew = dx1*unit_velocity/const_c}
1785  {^nooned dtnew = min(dx^d*unit_velocity/const_c)}
1786  endif
1787 
1788  end subroutine rhd_get_dt
1789 
1790  function rhd_kin_en(w, ixI^L, ixO^L, inv_rho) result(ke)
1791  use mod_global_parameters, only: nw, ndim
1792  integer, intent(in) :: ixi^l, ixo^l
1793  double precision, intent(in) :: w(ixi^s, nw)
1794  double precision :: ke(ixo^s)
1795  double precision, intent(in), optional :: inv_rho(ixo^s)
1796 
1797  if (present(inv_rho)) then
1798  ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) * inv_rho
1799  else
1800  ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) / w(ixo^s, rho_)
1801  end if
1802  end function rhd_kin_en
1803 
1804  function rhd_inv_rho(w, ixI^L, ixO^L) result(inv_rho)
1805  use mod_global_parameters, only: nw, ndim
1806  integer, intent(in) :: ixi^l, ixo^l
1807  double precision, intent(in) :: w(ixi^s, nw)
1808  double precision :: inv_rho(ixo^s)
1809 
1810  ! Can make this more robust
1811  inv_rho = 1.0d0 / w(ixo^s, rho_)
1812  end function rhd_inv_rho
1813 
1814  subroutine rhd_handle_small_values(primitive, w, x, ixI^L, ixO^L, subname)
1815  ! handles hydro (density,pressure,velocity) bootstrapping
1816  ! any negative dust density is flagged as well (and throws an error)
1817  ! small_values_method=replace also for dust
1819  use mod_small_values
1821  logical, intent(in) :: primitive
1822  integer, intent(in) :: ixI^L,ixO^L
1823  double precision, intent(inout) :: w(ixI^S,1:nw)
1824  double precision, intent(in) :: x(ixI^S,1:ndim)
1825  character(len=*), intent(in) :: subname
1826 
1827  integer :: n,idir
1828  logical :: flag(ixI^S,1:nw)
1829 
1830  call rhd_check_w(primitive, ixi^l, ixo^l, w, flag)
1831 
1832  if (any(flag)) then
1833  select case (small_values_method)
1834  case ("replace")
1835  where(flag(ixo^s,rho_)) w(ixo^s,rho_) = small_density
1836  do idir = 1, ndir
1837  if(small_values_fix_iw(mom(idir))) then
1838  where(flag(ixo^s,rho_)) w(ixo^s, mom(idir)) = 0.0d0
1839  end if
1840  end do
1841 
1842  if (small_values_fix_iw(r_e)) then
1843  where(flag(ixo^s,r_e)) w(ixo^s,r_e) = small_r_e
1844  end if
1845 
1846  if(rhd_energy)then
1847  if(small_values_fix_iw(e_)) then
1848  if(primitive) then
1849  where(flag(ixo^s,rho_)) w(ixo^s, p_) = small_pressure
1850  else
1851  where(flag(ixo^s,rho_)) w(ixo^s, e_) = small_e + rhd_kin_en(w,ixi^l,ixo^l)
1852  endif
1853  end if
1854  endif
1855 
1856  if(rhd_energy) then
1857  if(primitive) then
1858  where(flag(ixo^s,e_)) w(ixo^s,p_) = small_pressure
1859  else
1860  where(flag(ixo^s,e_))
1861  ! Add kinetic energy
1862  w(ixo^s,e_) = small_e + rhd_kin_en(w,ixi^l,ixo^l)
1863  end where
1864  end if
1865  end if
1866 
1867  if(rhd_dust)then
1868  do n=1,dust_n_species
1869  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1870  do idir = 1, ndir
1871  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1872  enddo
1873  enddo
1874  endif
1875  case ("average")
1876  if(primitive)then
1877  ! averaging for all primitive fields, including dust
1878  call small_values_average(ixi^l, ixo^l, w, x, flag)
1879  else
1880  ! do averaging of density
1881  call small_values_average(ixi^l, ixo^l, w, x, flag, rho_)
1882  if(rhd_energy) then
1883  ! do averaging of pressure
1884  w(ixi^s,p_)=(rhd_gamma-1.d0)*(w(ixi^s,e_) &
1885  -0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_))
1886  call small_values_average(ixi^l, ixo^l, w, x, flag, p_)
1887  w(ixi^s,e_)=w(ixi^s,p_)/(rhd_gamma-1.d0) &
1888  +0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_)
1889  end if
1890  ! do averaging of radiation energy
1891  call small_values_average(ixi^l, ixo^l, w, x, flag, r_e)
1892  if(rhd_dust)then
1893  do n=1,dust_n_species
1894  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1895  do idir = 1, ndir
1896  where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1897  enddo
1898  enddo
1899  endif
1900  endif
1901  case default
1902  if(.not.primitive) then
1903  !convert w to primitive
1904  ! Calculate pressure = (gamma-1) * (e-ek)
1905  if(rhd_energy) then
1906  w(ixo^s,p_)=(rhd_gamma-1.d0)*(w(ixo^s,e_)-rhd_kin_en(w,ixi^l,ixo^l))
1907  end if
1908  ! Convert gas momentum to velocity
1909  do idir = 1, ndir
1910  w(ixo^s, mom(idir)) = w(ixo^s, mom(idir))/w(ixo^s,rho_)
1911  end do
1912  end if
1913  ! NOTE: dust entries may still have conserved values here
1914  call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
1915  end select
1916  end if
1917  end subroutine rhd_handle_small_values
1918 
1919  subroutine rfactor_from_temperature_ionization(w,x,ixI^L,ixO^L,Rfactor)
1922  integer, intent(in) :: ixI^L, ixO^L
1923  double precision, intent(in) :: w(ixI^S,1:nw)
1924  double precision, intent(in) :: x(ixI^S,1:ndim)
1925  double precision, intent(out):: Rfactor(ixI^S)
1926 
1927  double precision :: iz_H(ixO^S),iz_He(ixO^S)
1928 
1929  call ionization_degree_from_temperature(ixi^l,ixo^l,w(ixi^s,te_),iz_h,iz_he)
1930  ! assume the first and second ionization of Helium have the same degree
1931  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
1932 
1934 
1935  subroutine rfactor_from_constant_ionization(w,x,ixI^L,ixO^L,Rfactor)
1937  integer, intent(in) :: ixI^L, ixO^L
1938  double precision, intent(in) :: w(ixI^S,1:nw)
1939  double precision, intent(in) :: x(ixI^S,1:ndim)
1940  double precision, intent(out):: Rfactor(ixI^S)
1941 
1942  rfactor(ixo^s)=rr
1943 
1944  end subroutine rfactor_from_constant_ionization
1945 
1946  subroutine rhd_update_temperature(ixI^L,ixO^L,wCT,w,x)
1949 
1950  integer, intent(in) :: ixI^L, ixO^L
1951  double precision, intent(in) :: wCT(ixI^S,1:nw), x(ixI^S,1:ndim)
1952  double precision, intent(inout) :: w(ixI^S,1:nw)
1953 
1954  double precision :: iz_H(ixO^S),iz_He(ixO^S), pth(ixI^S)
1955 
1956  call ionization_degree_from_temperature(ixi^l,ixo^l,wct(ixi^s,te_),iz_h,iz_he)
1957 
1958  call rhd_get_pthermal(w,x,ixi^l,ixo^l,pth)
1959 
1960  w(ixo^s,te_)=(2.d0+3.d0*he_abundance)*pth(ixo^s)/(w(ixo^s,rho_)*(1.d0+iz_h(ixo^s)+&
1961  he_abundance*(iz_he(ixo^s)*(iz_he(ixo^s)+1.d0)+1.d0)))
1962 
1963  end subroutine rhd_update_temperature
1964 
1965 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:788
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:822
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:756
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:605
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.
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:835
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:947
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:862
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:529
subroutine rhd_get_rho(w, x, ixIL, ixOL, rho)
Definition: mod_rhd_phys.t:549
subroutine rhd_tc_handle_small_e(w, x, ixIL, ixOL, step)
Definition: mod_rhd_phys.t:494
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:878
double precision function rhd_get_tc_dt_rhd(w, ixIL, ixOL, dxD, x)
Definition: mod_rhd_phys.t:478
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:888
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:634
subroutine e_to_rhos(ixIL, ixOL, w, x)
Definition: mod_rhd_phys.t:847
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:669
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:465
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:924
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:561
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:725
subroutine rhd_te_images()
Definition: mod_rhd_phys.t:447
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)