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