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