MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_hd_phys.t
Go to the documentation of this file.
1!> Hydrodynamics physics module
7 use mod_comm_lib, only: mpistop
8 implicit none
9 private
10
11 !> Whether an energy equation is used
12 logical, public, protected :: hd_energy = .true.
13
14 !> Whether thermal conduction is added
15 logical, public, protected :: hd_thermal_conduction = .false.
16 type(tc_fluid), allocatable, public :: tc_fl
17 type(te_fluid), allocatable, public :: te_fl_hd
18
19 !> Whether radiative cooling is added
20 logical, public, protected :: hd_radiative_cooling = .false.
21 type(rc_fluid), allocatable, public :: rc_fl
22
23 !> Whether dust is added
24 logical, public, protected :: hd_dust = .false.
25
26 !> Whether dust is added using and implicit update in IMEX
27 logical, public, protected :: hd_dust_implicit = .false.
28
29 !> Whether radiation-gas interaction is handled using flux limited diffusion
30 logical, public, protected :: hd_radiation_fld = .false.
31
32 !> Formalism to treat radiation: either fld or afld (anisotropic fld)
33 character(len=8), public :: hd_radiation_fld_formalism = 'fld'
34
35 !> Whether viscosity is added
36 logical, public, protected :: hd_viscosity = .false.
37
38 !> Whether gravity is added
39 logical, public, protected :: hd_gravity = .false.
40
41 !> Whether particles module is added
42 logical, public, protected :: hd_particles = .false.
43
44 !> Whether rotating frame is activated
45 logical, public, protected :: hd_rotating_frame = .false.
46
47 !> Whether CAK radiation line force is activated
48 logical, public, protected :: hd_cak_force = .false.
49
50 !> Number of tracer species
51 integer, public, protected :: hd_n_tracer = 0
52
53 !> Whether plasma is partially ionized
54 logical, public, protected :: hd_partial_ionization = .false.
55
56 !> Index of the density (in the w array)
57 integer, public, protected :: rho_
58
59 !> Indices of the momentum density
60 integer, allocatable, public, protected :: mom(:)
61
62 !> Indices of the momentum density for the form of better vectorization
63 integer, public, protected :: ^c&m^C_
64
65 !> Indices of the tracers
66 integer, allocatable, public, protected :: tracer(:)
67
68 !> Index of the energy density (-1 if not present)
69 integer, public, protected :: e_
70
71 !> Index of the gas pressure (-1 if not present) should equal e_
72 integer, public, protected :: p_
73
74 !> Index of the radiation energy (when fld active)
75 integer, public, protected :: r_e
76
77 !> Indices of temperature
78 integer, public, protected :: te_
79
80 !> Index of the cutoff temperature for the TRAC method
81 integer, public, protected :: tcoff_
82
83 !> The adiabatic index
84 double precision, public :: hd_gamma = 5.d0/3.0d0
85
86 !> gamma minus one and its inverse
87 double precision :: gamma_1, inv_gamma_1
88
89 !> The adiabatic constant
90 double precision, public :: hd_adiab = 1.0d0
91
92 !> The small_est allowed energy
93 double precision, protected :: small_e
94
95 !> The smallest allowed radiation energy (when fld active)
96 double precision, public, protected :: small_r_e
97
98 !> Whether TRAC method is used
99 logical, public, protected :: hd_trac = .false.
100 integer, public, protected :: hd_trac_type = 1
101
102 !> Helium abundance over Hydrogen
103 double precision, public, protected :: he_abundance=0.1d0
104 !> Ionization fraction of H
105 !> H_ion_fr = H+/(H+ + H)
106 double precision, public, protected :: h_ion_fr=1d0
107 !> Ionization fraction of He
108 !> He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
109 double precision, public, protected :: he_ion_fr=1d0
110 !> Ratio of number He2+ / number He+ + He2+
111 !> He_ion_fr2 = He2+/(He2+ + He+)
112 double precision, public, protected :: he_ion_fr2=1d0
113 ! used for eq of state when it is not defined by units,
114 ! the units do not contain terms related to ionization fraction
115 ! and it is p = RR * rho * T
116 double precision, public, protected :: rr=1d0
117 ! remove the below flag and assume default value = .false.
118 ! when eq state properly implemented everywhere
119 ! and not anymore through units
120 logical, public, protected :: eq_state_units = .true.
121
122 procedure(sub_get_pthermal), pointer :: hd_get_rfactor => null()
123 ! Public methods
124 public :: hd_phys_init
125 public :: hd_kin_en
126 public :: hd_get_pthermal
127 public :: hd_get_csound2
128 public :: hd_to_conserved
129 public :: hd_to_primitive
130 public :: hd_check_params
131 public :: hd_check_w
132 public :: hd_e_to_ei
133 public :: hd_ei_to_e
134 public :: hd_get_rfactor
135 ! Begin: following relevant for radiative hydro using FLD
136 ! first three are local and of interest for mod_usr applications
137 public :: hd_get_pradiation
138 public :: hd_get_ptot
139 public :: hd_get_trad
140 ! the following used in FLD modules
141 ! as pointer phys_get_tgas
143 ! as pointer phys_set_mg_bounds
144 public :: hd_set_mg_bounds
145 ! End: following relevant for radiative hydro using FLD
146
147contains
148
149 !> Read this module's parameters from a file
150 subroutine hd_read_params(files)
152 character(len=*), intent(in) :: files(:)
153 integer :: n
154
155 namelist /hd_list/ hd_energy, hd_n_tracer, hd_gamma, hd_adiab, &
161
162 do n = 1, size(files)
163 open(unitpar, file=trim(files(n)), status="old")
164 read(unitpar, hd_list, end=111)
165111 close(unitpar)
166 end do
167
168 end subroutine hd_read_params
169
170 !> Write this module's parameters to a snapsoht
171 subroutine hd_write_info(fh)
173 integer, intent(in) :: fh
174 integer, parameter :: n_par = 1
175 double precision :: values(n_par)
176 character(len=name_len) :: names(n_par)
177 integer, dimension(MPI_STATUS_SIZE) :: st
178 integer :: er
179
180 call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
181
182 names(1) = "gamma"
183 values(1) = hd_gamma
184 call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
185 call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
186 end subroutine hd_write_info
187
188 !> Initialize the module
189 subroutine hd_phys_init()
193 use mod_dust, only: dust_init
195 use mod_gravity, only: gravity_init
198 use mod_cak_force, only: cak_init
203 use mod_fld
204 use mod_afld
205
206 integer :: itr, idir
207
208 call hd_read_params(par_files)
209
210 physics_type = "hd"
211 phys_energy = hd_energy
212 phys_total_energy = hd_energy
213 phys_internal_e = .false.
214 phys_gamma = hd_gamma
215 phys_partial_ionization=hd_partial_ionization
216
218 if(phys_trac) then
219 if(ndim .eq. 1) then
220 if(hd_trac_type .gt. 2) then
222 if(mype==0) write(*,*) 'WARNING: set hd_trac_type=1'
223 end if
225 else
226 phys_trac=.false.
227 if(mype==0) write(*,*) 'WARNING: set hd_trac=F when ndim>=2'
228 end if
229 end if
230
231 ! set default gamma for polytropic/isothermal process
232 if(.not.hd_energy) then
233 if(hd_thermal_conduction) then
235 if(mype==0) write(*,*) 'WARNING: set hd_thermal_conduction=F when hd_energy=F'
236 end if
237 if(hd_radiative_cooling) then
239 if(mype==0) write(*,*) 'WARNING: set hd_radiative_cooling=F when hd_energy=F'
240 end if
241 end if
242 if(.not.eq_state_units) then
243 if(hd_partial_ionization) then
245 if(mype==0) write(*,*) 'WARNING: set hd_partial_ionization=F when eq_state_units=F'
246 end if
247 end if
249
250 allocate(start_indices(number_species),stop_indices(number_species))
251
252 ! set the index of the first flux variable for species 1
253 start_indices(1)=1
254 ! Determine flux variables
255 rho_ = var_set_rho()
256
257 allocate(mom(ndir))
258 mom(:) = var_set_momentum(ndir)
259 m^c_=mom(^c);
260
261 ! Set index of energy variable
262 if (hd_energy) then
263 e_ = var_set_energy()
264 p_ = e_
265 else
266 e_ = -1
267 p_ = -1
268 end if
269
270 if(hd_radiation_fld)then
271 if(hd_cak_force)then
272 if(mype==0) then
273 write(*,*)'Warning: CAK force addition together with FLD radiation'
274 endif
275 endif
277 if(mype==0) then
278 write(*,*)'Warning: Optically thin cooling together with FLD radiation'
279 endif
280 endif
281 if(hd_dust.and.hd_dust_implicit)then
282 call mpistop('implicit dust addition not compatible with FLD radiation')
283 endif
284 if(si_unit)then
285 call mpistop('using FLD implies the use of cgs units')
286 endif
287 if(.not.hd_energy)then
288 call mpistop('using FLD implies the use of an energy equation, set hd_energy=T')
289 else
290 !> set added variable and equation for radiation energy
291 r_e = var_set_radiation_energy()
292 phys_set_mg_bounds => hd_set_mg_bounds
293 phys_get_tgas => hd_get_temperature_from_etot
294 !> Initiate radiation-closure module
295 select case (hd_radiation_fld_formalism)
296 case('fld')
298 case('afld')
299 {^ifoned
300 call mpistop('using anisotropic FLD implies multidimensional setup')
301 }
303 case default
304 call mpistop('Radiation formalism unknown')
305 end select
306 endif
307 else
308 r_e=-1
309 endif
310
311 phys_get_dt => hd_get_dt
312 phys_get_cmax => hd_get_cmax
313 phys_get_tcutoff => hd_get_tcutoff
314 phys_get_cbounds => hd_get_cbounds
315 phys_get_flux => hd_get_flux
316 phys_add_source_geom => hd_add_source_geom
317 phys_add_source => hd_add_source
318 phys_to_conserved => hd_to_conserved
319 phys_to_primitive => hd_to_primitive
320 phys_check_params => hd_check_params
321 phys_check_w => hd_check_w
322 phys_get_pthermal => hd_get_pthermal
323 phys_get_v => hd_get_v
324 phys_get_rho => hd_get_rho
325 phys_write_info => hd_write_info
326 phys_handle_small_values => hd_handle_small_values
327
328 ! derive units from basic units
329 call hd_physical_units()
330
331 if (hd_dust) then
332 call dust_init(rho_, mom(:), e_)
333 endif
334
335 allocate(tracer(hd_n_tracer))
336
337 ! Set starting index of tracers
338 do itr = 1, hd_n_tracer
339 tracer(itr) = var_set_fluxvar("trc", "trp", itr, need_bc=.false.)
340 end do
341
342 ! set temperature as an auxiliary variable to get ionization degree
343 if(hd_partial_ionization) then
344 te_ = var_set_auxvar('Te','Te')
345 else
346 te_ = -1
347 end if
348
349 ! set number of variables which need update ghostcells
350 nwgc=nwflux+nwaux
351
352 ! set the index of the last flux variable for species 1
353 stop_indices(1)=nwflux
354
355 if(hd_trac) then
356 tcoff_ = var_set_wextra()
357 iw_tcoff=tcoff_
358 else
359 tcoff_ = -1
360 end if
361
362 ! choose Rfactor in ideal gas law
363 if(hd_partial_ionization) then
364 hd_get_rfactor=>rfactor_from_temperature_ionization
365 phys_update_temperature => hd_update_temperature
366 else if(associated(usr_rfactor)) then
368 else
369 hd_get_rfactor=>rfactor_from_constant_ionization
370 end if
371
372 ! initialize thermal conduction module
373 if (hd_thermal_conduction) then
374 if (.not. hd_energy) &
375 call mpistop("thermal conduction needs hd_energy=T")
376
377 call sts_init()
379
380 allocate(tc_fl)
381 call tc_get_hd_params(tc_fl,tc_params_read_hd)
382 call add_sts_method(hd_get_tc_dt_hd,hd_sts_set_source_tc_hd,e_,1,e_,1,.false.)
384 call set_error_handling_to_head(hd_tc_handle_small_e)
385 tc_fl%get_temperature_from_conserved => hd_get_temperature_from_etot
386 tc_fl%get_temperature_from_eint => hd_get_temperature_from_eint
387 tc_fl%get_rho => hd_get_rho
388 tc_fl%e_ = e_
389 end if
390
391 ! Initialize radiative cooling module
392 if (hd_radiative_cooling) then
393 if (.not. hd_energy) &
394 call mpistop("radiative cooling needs hd_energy=T")
396 allocate(rc_fl)
397 call radiative_cooling_init(rc_fl,rc_params_read)
398 rc_fl%get_rho => hd_get_rho
399 rc_fl%get_pthermal => hd_get_pthermal
400 rc_fl%get_var_Rfactor => hd_get_rfactor
401 rc_fl%e_ = e_
402 rc_fl%Tcoff_ = tcoff_
403 end if
404 allocate(te_fl_hd)
405 te_fl_hd%get_rho=> hd_get_rho
406 te_fl_hd%get_pthermal=> hd_get_pthermal
407 te_fl_hd%get_var_Rfactor => hd_get_rfactor
408{^ifthreed
409 phys_te_images => hd_te_images
410}
411 ! Initialize viscosity module
412 if (hd_viscosity) call viscosity_init(phys_wider_stencil)
413
414 ! Initialize gravity module
415 if (hd_gravity) call gravity_init()
416
417 ! Initialize rotating_frame module
419
420 ! Initialize CAK radiation force module
422
423 ! Initialize particles module
424 if (hd_particles) then
425 call particles_init()
426 end if
427
428 ! Check whether custom flux types have been defined
429 if (.not. allocated(flux_type)) then
430 allocate(flux_type(ndir, nw))
431 flux_type = flux_default
432 else if (any(shape(flux_type) /= [ndir, nw])) then
433 call mpistop("phys_check error: flux_type has wrong shape")
434 end if
435
436 nvector = 1 ! No. vector vars
437 allocate(iw_vector(nvector))
438 iw_vector(1) = mom(1) - 1
439 ! initialize ionization degree table
441
442 end subroutine hd_phys_init
443
444{^ifthreed
445 subroutine hd_te_images
448 select case(convert_type)
449 case('EIvtiCCmpi','EIvtuCCmpi')
451 case('ESvtiCCmpi','ESvtuCCmpi')
453 case('SIvtiCCmpi','SIvtuCCmpi')
455 case('WIvtiCCmpi','WIvtuCCmpi')
457 case default
458 call mpistop("Error in synthesize emission: Unknown convert_type")
459 end select
460 end subroutine hd_te_images
461}
462!!start th cond
463 ! wrappers for STS functions in thermal_conductivity module
464 ! which take as argument the tc_fluid (defined in the physics module)
465 subroutine hd_sts_set_source_tc_hd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
469 integer, intent(in) :: ixi^l, ixo^l, igrid, nflux
470 double precision, intent(in) :: x(ixi^s,1:ndim)
471 double precision, intent(inout) :: wres(ixi^s,1:nw), w(ixi^s,1:nw)
472 double precision, intent(in) :: my_dt
473 logical, intent(in) :: fix_conserve_at_step
474 call sts_set_source_tc_hd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl)
475 end subroutine hd_sts_set_source_tc_hd
476
477 function hd_get_tc_dt_hd(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
478 !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para/rho)
479 !and tc_k_para can depend on T=p/rho
482
483 integer, intent(in) :: ixi^l, ixo^l
484 double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
485 double precision, intent(in) :: w(ixi^s,1:nw)
486 double precision :: dtnew
487
488 dtnew=get_tc_dt_hd(w,ixi^l,ixo^l,dx^d,x,tc_fl)
489 end function hd_get_tc_dt_hd
490
491 subroutine hd_tc_handle_small_e(w, x, ixI^L, ixO^L, step)
492 ! move this in a different routine as in mhd if needed in more places
495
496 integer, intent(in) :: ixi^l,ixo^l
497 double precision, intent(inout) :: w(ixi^s,1:nw)
498 double precision, intent(in) :: x(ixi^s,1:ndim)
499 integer, intent(in) :: step
500
501 integer :: idir
502 logical :: flag(ixi^s,1:nw)
503 character(len=140) :: error_msg
504
505 flag=.false.
506 where(w(ixo^s,e_)<small_e) flag(ixo^s,e_)=.true.
507 if(any(flag(ixo^s,e_))) then
508 select case (small_values_method)
509 case ("replace")
510 where(flag(ixo^s,e_)) w(ixo^s,e_)=small_e
511 case ("average")
512 call small_values_average(ixi^l, ixo^l, w, x, flag, e_)
513 case default
514 ! small values error shows primitive variables
515 w(ixo^s,e_)=w(ixo^s,e_)*(hd_gamma - 1.0d0)
516 do idir = 1, ndir
517 w(ixo^s, iw_mom(idir)) = w(ixo^s, iw_mom(idir))/w(ixo^s,rho_)
518 end do
519 write(error_msg,"(a,i3)") "Thermal conduction step ", step
520 call small_values_error(w, x, ixi^l, ixo^l, flag, error_msg)
521 end select
522 end if
523 end subroutine hd_tc_handle_small_e
524
525 ! fill in tc_fluid fields from namelist
526 subroutine tc_params_read_hd(fl)
528 type(tc_fluid), intent(inout) :: fl
529 integer :: n
530 logical :: tc_saturate=.false.
531 double precision :: tc_k_para=0d0
532
533 namelist /tc_list/ tc_saturate, tc_k_para
534
535 do n = 1, size(par_files)
536 open(unitpar, file=trim(par_files(n)), status="old")
537 read(unitpar, tc_list, end=111)
538111 close(unitpar)
539 end do
540 fl%tc_saturate = tc_saturate
541 fl%tc_k_para = tc_k_para
542
543 end subroutine tc_params_read_hd
544
545 subroutine hd_get_rho(w,x,ixI^L,ixO^L,rho)
547 integer, intent(in) :: ixi^l, ixo^l
548 double precision, intent(in) :: w(ixi^s,1:nw),x(ixi^s,1:ndim)
549 double precision, intent(out) :: rho(ixi^s)
550
551 rho(ixo^s) = w(ixo^s,rho_)
552
553 end subroutine hd_get_rho
554
555!!end th cond
556!!rad cool
557 subroutine rc_params_read(fl)
559 use mod_constants, only: bigdouble
560 use mod_basic_types, only: std_len
561 type(rc_fluid), intent(inout) :: fl
562 integer :: n
563 ! list parameters
564 integer :: ncool = 4000
565
566 !> Name of cooling curve
567 character(len=std_len) :: coolcurve='JCcorona'
568
569 !> Fixed temperature not lower than tlow
570 logical :: tfix=.false.
571
572 !> Lower limit of temperature
573 double precision :: tlow=bigdouble
574
575 !> Add cooling source in a split way (.true.) or un-split way (.false.)
576 logical :: rc_split=.false.
577
578
579 namelist /rc_list/ coolcurve, ncool, tlow, tfix, rc_split
580
581 do n = 1, size(par_files)
582 open(unitpar, file=trim(par_files(n)), status="old")
583 read(unitpar, rc_list, end=111)
584111 close(unitpar)
585 end do
586
587 fl%ncool=ncool
588 fl%coolcurve=coolcurve
589 fl%tlow=tlow
590 fl%Tfix=tfix
591 fl%rc_split=rc_split
592 end subroutine rc_params_read
593!! end rad cool
594
598
599 if (.not. hd_energy) then
600 if (hd_gamma <= 0.0d0) call mpistop ("Error: hd_gamma <= 0")
601 if (hd_adiab < 0.0d0) call mpistop ("Error: hd_adiab < 0")
603 else
604 if (hd_gamma <= 0.0d0 .or. hd_gamma == 1.0d0) &
605 call mpistop ("Error: hd_gamma <= 0 or hd_gamma == 1.0")
606 small_e = small_pressure/(hd_gamma - 1.0d0)
607 inv_gamma_1=1.d0/(hd_gamma-1.d0)
609 end if
610
611 if (hd_dust) call dust_check_params()
612
613 if(hd_dust_implicit) then
614 if(.not.use_imex_scheme)then
615 call mpistop('select IMEX scheme for implicit dust update')
616 endif
617 ! implicit dust update
618 phys_implicit_update => dust_implicit_update
619 phys_evaluate_implicit => dust_evaluate_implicit
620 endif
621 if(hd_radiation_fld) then
622 if(.not.use_imex_scheme)then
623 call mpistop('select IMEX scheme for FLD radiation use')
624 endif
625 if(use_multigrid)then
626 call hd_set_mg_bounds()
627 else
628 call mpistop('multigrid must have BCs for IMEX and FLD radiation use')
629 endif
630 endif
631
632 end subroutine hd_check_params
633
634 !> Set the boundaries for the diffusion of E
639
640 integer :: ib
641
642 ! Set boundary conditions for the multigrid solver
643 do ib = 1, 2*ndim
644 select case (typeboundary(r_e, ib))
645 case (bc_symm)
646 ! d/dx u = 0
647 mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
648 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
649 case (bc_asymm)
650 ! u = 0
651 mg%bc(ib, mg_iphi)%bc_type = mg_bc_dirichlet
652 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
653 case (bc_cont)
654 ! d/dx u = 0
655 ! mg%bc(iB, mg_iphi)%bc_type = mg_bc_continuous
656 mg%bc(ib, mg_iphi)%bc_type = mg_bc_neumann
657 mg%bc(ib, mg_iphi)%bc_value = 0.0_dp
658 case (bc_periodic)
659 ! Nothing to do here
660 case (bc_noinflow)
661 call usr_special_mg_bc(ib)
662 case (bc_special)
663 call usr_special_mg_bc(ib)
664 case default
665 call mpistop("divE_multigrid warning: unknown b.c. ")
666 end select
667 end do
668 end subroutine hd_set_mg_bounds
669
670 subroutine hd_physical_units
672 double precision :: mp,kb
673 double precision :: a,b
674 ! Derive scaling units
675 if(si_unit) then
676 mp=mp_si
677 kb=kb_si
678 else
679 mp=mp_cgs
680 kb=kb_cgs
681 end if
682 if(eq_state_units) then
683 a=1d0+4d0*he_abundance
684 if(hd_partial_ionization) then
685 b=1d0+h_ion_fr+he_abundance*(he_ion_fr*(he_ion_fr2+1d0)+1d0)
686 else
687 b=2d0+3d0*he_abundance
688 end if
689 rr=1d0
690 else
691 a=1d0
692 b=1d0
693 rr=(1d0+h_ion_fr+he_abundance*(he_ion_fr*(he_ion_fr2+1d0)+1d0))/(1d0+4d0*he_abundance)
694 end if
695 if(unit_density/=1.d0 .or. unit_numberdensity/=1.d0) then
696 if(unit_density/=1.d0) then
698 else if(unit_numberdensity/=1.d0) then
700 end if
701 if(unit_temperature/=1.d0) then
704 if(unit_length/=1.d0) then
706 else if(unit_time/=1.d0) then
708 end if
709 else if(unit_pressure/=1.d0) then
712 if(unit_length/=1.d0) then
714 else if(unit_time/=1.d0) then
716 end if
717 else if(unit_velocity/=1.d0) then
720 if(unit_length/=1.d0) then
722 else if(unit_time/=1.d0) then
724 end if
725 else if(unit_time/=1.d0) then
729 end if
730 else if(unit_temperature/=1.d0) then
731 ! units of temperature and velocity are dependent
732 if(unit_pressure/=1.d0) then
736 if(unit_length/=1.d0) then
738 else if(unit_time/=1.d0) then
740 end if
741 end if
742 else if(unit_pressure/=1.d0) then
743 if(unit_velocity/=1.d0) then
747 if(unit_length/=1.d0) then
749 else if(unit_time/=1.d0) then
751 end if
752 else if(unit_time/=0.d0) then
757 end if
758 end if
760
761 !> Units for radiative flux and opacity, latter is used in FLD
764
765 end subroutine hd_physical_units
766
767 !> Returns logical argument flag where values are ok
768 subroutine hd_check_w(primitive, ixI^L, ixO^L, w, flag)
770 use mod_dust, only: dust_check_w
771
772 logical, intent(in) :: primitive
773 integer, intent(in) :: ixi^l, ixo^l
774 double precision, intent(in) :: w(ixi^s, nw)
775 logical, intent(inout) :: flag(ixi^s,1:nw)
776 double precision :: tmp(ixi^s)
777
778 flag=.false.
779
780 if (hd_energy) then
781 if (primitive) then
782 where(w(ixo^s, e_) < small_pressure) flag(ixo^s,e_) = .true.
783 else
784 tmp(ixo^s)=(hd_gamma-1.0d0)*(w(ixo^s,e_)-&
785 half*(^c&w(ixo^s,m^c_)**2+)/w(ixo^s,rho_))
786 where(tmp(ixo^s) < small_pressure) flag(ixo^s,e_) = .true.
787 endif
788 if(hd_radiation_fld)then
789 where(w(ixo^s, r_e) < small_r_e) flag(ixo^s,r_e) = .true.
790 endif
791 end if
792
793 where(w(ixo^s, rho_) < small_density) flag(ixo^s,rho_) = .true.
794
795 if(hd_dust) call dust_check_w(ixi^l,ixo^l,w,flag)
796
797 end subroutine hd_check_w
798
799 !> Transform primitive variables into conservative ones
800 subroutine hd_to_conserved(ixI^L, ixO^L, w, x)
802 use mod_dust, only: dust_to_conserved
803 integer, intent(in) :: ixi^l, ixo^l
804 double precision, intent(inout) :: w(ixi^s, nw)
805 double precision, intent(in) :: x(ixi^s, 1:ndim)
806
807 integer :: ix^d
808
809 {do ix^db=ixomin^db,ixomax^db\}
810 if (hd_energy) then
811 ! Calculate total energy from pressure and kinetic energy
812 w(ix^d,e_)=w(ix^d, e_)*inv_gamma_1+&
813 half*(^c&w(ix^d,m^c_)**2+)*w(ix^d,rho_)
814 end if
815 ! Convert velocity to momentum
816 ^c&w(ix^d,m^c_)=w(ix^d,rho_)*w(ix^d,m^c_)\
817 {end do\}
818
819 if (hd_dust) then
820 call dust_to_conserved(ixi^l, ixo^l, w, x)
821 end if
822
823 end subroutine hd_to_conserved
824
825 !> Transform conservative variables into primitive ones
826 subroutine hd_to_primitive(ixI^L, ixO^L, w, x)
828 use mod_dust, only: dust_to_primitive
829 integer, intent(in) :: ixi^l, ixo^l
830 double precision, intent(inout) :: w(ixi^s, nw)
831 double precision, intent(in) :: x(ixi^s, 1:ndim)
832
833 double precision :: inv_rho
834 integer :: ix^d
835
836 if (fix_small_values) then
837 call hd_handle_small_values(.false., w, x, ixi^l, ixo^l, 'hd_to_primitive')
838 end if
839
840 {do ix^db=ixomin^db,ixomax^db\}
841 inv_rho = 1.d0/w(ix^d,rho_)
842 ! Convert momentum to velocity
843 ^c&w(ix^d,m^c_)=w(ix^d,m^c_)*inv_rho\
844 ! Calculate pressure = (gamma-1) * (e-ek)
845 if(hd_energy) then
846 ! Compute pressure
847 w(ix^d,p_)=(hd_gamma-1.d0)*(w(ix^d,e_)&
848 -half*w(ix^d,rho_)*(^c&w(ix^d,m^c_)**2+))
849 end if
850 {end do\}
851
852 ! Convert dust momentum to dust velocity
853 if (hd_dust) then
854 call dust_to_primitive(ixi^l, ixo^l, w, x)
855 end if
856
857 end subroutine hd_to_primitive
858
859 !> Transform internal energy to total energy
860 subroutine hd_ei_to_e(ixI^L,ixO^L,w,x)
862 integer, intent(in) :: ixi^l, ixo^l
863 double precision, intent(inout) :: w(ixi^s, nw)
864 double precision, intent(in) :: x(ixi^s, 1:ndim)
865
866 ! Calculate total energy from internal and kinetic energy
867 w(ixo^s,e_)=w(ixo^s,e_)+half*(^c&w(ixo^s,m^c_)**2+)/w(ixo^s,rho_)
868
869 end subroutine hd_ei_to_e
870
871 !> Transform total energy to internal energy
872 subroutine hd_e_to_ei(ixI^L,ixO^L,w,x)
874 integer, intent(in) :: ixi^l, ixo^l
875 double precision, intent(inout) :: w(ixi^s, nw)
876 double precision, intent(in) :: x(ixi^s, 1:ndim)
877
878 ! Calculate ei = e - ek
879 w(ixo^s,e_)=w(ixo^s,e_)-half*(^c&w(ixo^s,m^c_)**2+)/w(ixo^s,rho_)
880
881 end subroutine hd_e_to_ei
882
883 !> Calculate v_i = m_i / rho within ixO^L
884 subroutine hd_get_v_idim(w, x, ixI^L, ixO^L, idim, v)
886 integer, intent(in) :: ixi^l, ixo^l, idim
887 double precision, intent(in) :: w(ixi^s, nw), x(ixi^s, 1:ndim)
888 double precision, intent(out) :: v(ixi^s)
889
890 v(ixo^s) = w(ixo^s, mom(idim)) / w(ixo^s, rho_)
891 end subroutine hd_get_v_idim
892
893 !> Calculate velocity vector v_i = m_i / rho within ixO^L
894 subroutine hd_get_v(w,x,ixI^L,ixO^L,v)
896
897 integer, intent(in) :: ixi^l, ixo^l
898 double precision, intent(in) :: w(ixi^s,nw), x(ixi^s,1:^nd)
899 double precision, intent(out) :: v(ixi^s,1:ndir)
900
901 integer :: idir
902
903 do idir=1,ndir
904 v(ixo^s,idir) = w(ixo^s, mom(idir)) / w(ixo^s, rho_)
905 end do
906
907 end subroutine hd_get_v
908
909 !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
910 subroutine hd_get_cmax(w, x, ixI^L, ixO^L, idim, cmax)
914
915 integer, intent(in) :: ixi^l, ixo^l, idim
916 ! w in primitive form
917 double precision, intent(in) :: w(ixi^s, nw), x(ixi^s, 1:ndim)
918 double precision, intent(inout) :: cmax(ixi^s)
919
920 if(hd_energy) then
921 cmax(ixo^s)=dabs(w(ixo^s,mom(idim)))+dsqrt(hd_gamma*w(ixo^s,p_)/w(ixo^s,rho_))
922 else
923 if (.not. associated(usr_set_pthermal)) then
924 cmax(ixo^s) = hd_adiab * w(ixo^s, rho_)**hd_gamma
925 else
926 call usr_set_pthermal(w,x,ixi^l,ixo^l,cmax)
927 end if
928 cmax(ixo^s)=dabs(w(ixo^s,mom(idim)))+dsqrt(hd_gamma*cmax(ixo^s)/w(ixo^s,rho_))
929 end if
930
931 if (hd_dust) then
932 call dust_get_cmax_prim(w, x, ixi^l, ixo^l, idim, cmax)
933 end if
934 end subroutine hd_get_cmax
935
936 !> get adaptive cutoff temperature for TRAC (Johnston 2019 ApJL, 873, L22)
937 subroutine hd_get_tcutoff(ixI^L,ixO^L,w,x,tco_local,Tmax_local)
939 integer, intent(in) :: ixi^l,ixo^l
940 double precision, intent(in) :: x(ixi^s,1:ndim)
941 ! in primitive form
942 double precision, intent(inout) :: w(ixi^s,1:nw)
943 double precision, intent(out) :: tco_local, tmax_local
944
945 double precision, parameter :: trac_delta=0.25d0
946 double precision :: tmp1(ixi^s),te(ixi^s),lts(ixi^s)
947 double precision :: ltr(ixi^s),ltrc,ltrp,tcoff(ixi^s)
948 integer :: jxo^l,hxo^l
949 integer :: jxp^l,hxp^l,ixp^l
950 logical :: lrlt(ixi^s)
951
952 {^ifoned
953 call hd_get_rfactor(w,x,ixi^l,ixi^l,te)
954 te(ixi^s)=w(ixi^s,p_)/(te(ixi^s)*w(ixi^s,rho_))
955
956 tco_local=zero
957 tmax_local=maxval(te(ixo^s))
958 select case(hd_trac_type)
959 case(0)
960 w(ixi^s,tcoff_)=3.d5/unit_temperature
961 case(1)
962 hxo^l=ixo^l-1;
963 jxo^l=ixo^l+1;
964 lts(ixo^s)=0.5d0*dabs(te(jxo^s)-te(hxo^s))/te(ixo^s)
965 lrlt=.false.
966 where(lts(ixo^s) > trac_delta)
967 lrlt(ixo^s)=.true.
968 end where
969 if(any(lrlt(ixo^s))) then
970 tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
971 end if
972 case(2)
973 !> iijima et al. 2021, LTRAC method
974 ltrc=1.5d0
975 ltrp=2.5d0
976 ixp^l=ixo^l^ladd1;
977 hxo^l=ixo^l-1;
978 jxo^l=ixo^l+1;
979 hxp^l=ixp^l-1;
980 jxp^l=ixp^l+1;
981 lts(ixp^s)=0.5d0*abs(te(jxp^s)-te(hxp^s))/te(ixp^s)
982 ltr(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
983 w(ixo^s,tcoff_)=te(ixo^s)*&
984 (0.25*(ltr(jxo^s)+two*ltr(ixo^s)+ltr(hxo^s)))**0.4d0
985 case default
986 call mpistop("hd_trac_type not allowed for 1D simulation")
987 end select
988 }
989 end subroutine hd_get_tcutoff
990
991 !> Calculate cmax_idim = csound + abs(v_idim) within ixO^L
992 subroutine hd_get_cbounds(wLC, wRC, wLp, wRp, x, ixI^L, ixO^L, idim,Hspeed,cmax, cmin)
994 use mod_dust, only: dust_get_cmax
995 use mod_variables
996
997 integer, intent(in) :: ixi^l, ixo^l, idim
998 ! conservative left and right status
999 double precision, intent(in) :: wlc(ixi^s, nw), wrc(ixi^s, nw)
1000 ! primitive left and right status
1001 double precision, intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
1002 double precision, intent(in) :: x(ixi^s, 1:ndim)
1003 double precision, intent(inout) :: cmax(ixi^s,1:number_species)
1004 double precision, intent(inout), optional :: cmin(ixi^s,1:number_species)
1005 double precision, intent(in) :: hspeed(ixi^s,1:number_species)
1006
1007 double precision :: wmean(ixi^s,nw)
1008 double precision, dimension(ixI^S) :: umean, dmean, csoundl, csoundr, tmp1,tmp2,tmp3
1009 integer :: ix^d
1010
1011 select case(boundspeed)
1012 case (1)
1013 ! This implements formula (10.52) from "Riemann Solvers and Numerical
1014 ! Methods for Fluid Dynamics" by Toro.
1015
1016 tmp1(ixo^s)=dsqrt(wlp(ixo^s,rho_))
1017 tmp2(ixo^s)=dsqrt(wrp(ixo^s,rho_))
1018 tmp3(ixo^s)=1.d0/(tmp1(ixo^s)+tmp2(ixo^s))
1019 umean(ixo^s)=(wlp(ixo^s,mom(idim))*tmp1(ixo^s)+wrp(ixo^s,mom(idim))*tmp2(ixo^s))*tmp3(ixo^s)
1020
1021 if(hd_energy) then
1022 csoundl(ixo^s)=hd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
1023 csoundr(ixo^s)=hd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
1024 else
1025 call hd_get_csound2(wlc,x,ixi^l,ixo^l,csoundl)
1026 call hd_get_csound2(wrc,x,ixi^l,ixo^l,csoundr)
1027 end if
1028
1029 dmean(ixo^s) = (tmp1(ixo^s)*csoundl(ixo^s)+tmp2(ixo^s)*csoundr(ixo^s)) * &
1030 tmp3(ixo^s) + 0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2 * &
1031 (wrp(ixo^s,mom(idim))-wlp(ixo^s,mom(idim)))**2
1032
1033 dmean(ixo^s)=dsqrt(dmean(ixo^s))
1034 if(present(cmin)) then
1035 cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
1036 cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
1037 if(h_correction) then
1038 {do ix^db=ixomin^db,ixomax^db\}
1039 cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1040 cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1041 {end do\}
1042 end if
1043 else
1044 cmax(ixo^s,1)=dabs(umean(ixo^s))+dmean(ixo^s)
1045 end if
1046
1047 if (hd_dust) then
1048 wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1049 call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1050 end if
1051
1052 case (2)
1053 wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1054 tmp1(ixo^s)=wmean(ixo^s,mom(idim))/wmean(ixo^s,rho_)
1055 call hd_get_csound2(wmean,x,ixi^l,ixo^l,csoundr)
1056 csoundr(ixo^s) = dsqrt(csoundr(ixo^s))
1057
1058 if(present(cmin)) then
1059 cmax(ixo^s,1)=max(tmp1(ixo^s)+csoundr(ixo^s),zero)
1060 cmin(ixo^s,1)=min(tmp1(ixo^s)-csoundr(ixo^s),zero)
1061 if(h_correction) then
1062 {do ix^db=ixomin^db,ixomax^db\}
1063 cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1064 cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1065 {end do\}
1066 end if
1067 else
1068 cmax(ixo^s,1)=dabs(tmp1(ixo^s))+csoundr(ixo^s)
1069 end if
1070
1071 if (hd_dust) then
1072 call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1073 end if
1074 case (3)
1075 ! Miyoshi 2005 JCP 208, 315 equation (67)
1076 if(hd_energy) then
1077 csoundl(ixo^s)=hd_gamma*wlp(ixo^s,p_)/wlp(ixo^s,rho_)
1078 csoundr(ixo^s)=hd_gamma*wrp(ixo^s,p_)/wrp(ixo^s,rho_)
1079 else
1080 call hd_get_csound2(wlc,x,ixi^l,ixo^l,csoundl)
1081 call hd_get_csound2(wrc,x,ixi^l,ixo^l,csoundr)
1082 end if
1083 csoundl(ixo^s)=max(dsqrt(csoundl(ixo^s)),dsqrt(csoundr(ixo^s)))
1084 if(present(cmin)) then
1085 cmin(ixo^s,1)=min(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))-csoundl(ixo^s)
1086 cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
1087 if(h_correction) then
1088 {do ix^db=ixomin^db,ixomax^db\}
1089 cmin(ix^d,1)=sign(one,cmin(ix^d,1))*max(abs(cmin(ix^d,1)),hspeed(ix^d,1))
1090 cmax(ix^d,1)=sign(one,cmax(ix^d,1))*max(abs(cmax(ix^d,1)),hspeed(ix^d,1))
1091 {end do\}
1092 end if
1093 else
1094 cmax(ixo^s,1)=max(wlp(ixo^s,mom(idim)),wrp(ixo^s,mom(idim)))+csoundl(ixo^s)
1095 end if
1096 if (hd_dust) then
1097 wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1098 call dust_get_cmax(wmean, x, ixi^l, ixo^l, idim, cmax, cmin)
1099 end if
1100 end select
1101
1102 end subroutine hd_get_cbounds
1103
1104 !> Calculate the square of the thermal sound speed csound2 within ixO^L.
1105 !> csound2=gamma*p/rho
1106 subroutine hd_get_csound2(w,x,ixI^L,ixO^L,csound2)
1108 integer, intent(in) :: ixi^l, ixo^l
1109 double precision, intent(in) :: w(ixi^s,nw)
1110 double precision, intent(in) :: x(ixi^s,1:ndim)
1111 double precision, intent(out) :: csound2(ixi^s)
1112
1113 call hd_get_pthermal(w,x,ixi^l,ixo^l,csound2)
1114 csound2(ixo^s)=hd_gamma*csound2(ixo^s)/w(ixo^s,rho_)
1115
1116 end subroutine hd_get_csound2
1117
1118 !> Calculate thermal pressure=(gamma-1)*(e-0.5*m**2/rho) within ixO^L
1119 subroutine hd_get_pthermal(w, x, ixI^L, ixO^L, pth)
1123
1124 integer, intent(in) :: ixi^l, ixo^l
1125 double precision, intent(in) :: w(ixi^s, 1:nw)
1126 double precision, intent(in) :: x(ixi^s, 1:ndim)
1127 double precision, intent(out):: pth(ixi^s)
1128 integer :: iw, ix^d
1129
1130 if (hd_energy) then
1131 pth(ixo^s) = (hd_gamma - 1.0d0) * (w(ixo^s, e_) - &
1132 hd_kin_en(w, ixi^l, ixo^l))
1133 else
1134 if (.not. associated(usr_set_pthermal)) then
1135 pth(ixo^s) = hd_adiab * w(ixo^s, rho_)**hd_gamma
1136 else
1137 call usr_set_pthermal(w,x,ixi^l,ixo^l,pth)
1138 end if
1139 end if
1140
1141 if (fix_small_values) then
1142 {do ix^db= ixo^lim^db\}
1143 if(pth(ix^d)<small_pressure) then
1144 pth(ix^d)=small_pressure
1145 endif
1146 {enddo^d&\}
1147 else 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 hd_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 end subroutine hd_get_pthermal
1167
1168 !> Calculate radiation pressure within ixO^L
1169 subroutine hd_get_pradiation(w, x, ixI^L, ixO^L, prad)
1171 use mod_fld
1172 use mod_afld
1173
1174 integer, intent(in) :: ixi^l, ixo^l
1175 double precision, intent(in) :: w(ixi^s, 1:nw)
1176 double precision, intent(in) :: x(ixi^s, 1:ndim)
1177 double precision, intent(out):: prad(ixo^s, 1:ndim, 1:ndim)
1178
1179 select case (hd_radiation_fld_formalism)
1180 case('fld')
1181 call fld_get_radpress(w, x, ixi^l, ixo^l, prad, nghostcells)
1182 case('afld')
1183 call afld_get_radpress(w, x, ixi^l, ixo^l, prad, nghostcells)
1184 case default
1185 call mpistop('Radiation formalism unknown')
1186 end select
1187 end subroutine hd_get_pradiation
1188
1189 !> calculates the sum of the gas pressure and max Prad tensor element
1190 subroutine hd_get_ptot(w, x, ixI^L, ixO^L, ptot)
1192
1193 integer, intent(in) :: ixi^l, ixo^l
1194 double precision, intent(in) :: w(ixi^s, 1:nw)
1195 double precision, intent(in) :: x(ixi^s, 1:ndim)
1196 double precision :: pth(ixi^s)
1197 double precision :: prad_tensor(ixo^s, 1:ndim, 1:ndim)
1198 double precision :: prad_max(ixo^s)
1199 double precision, intent(out):: ptot(ixi^s)
1200 integer :: ix^d
1201
1202 call hd_get_pthermal(w, x, ixi^l, ixo^l, pth)
1203 call hd_get_pradiation(w, x, ixi^l, ixo^l, prad_tensor)
1204
1205 {do ix^d = ixomin^d,ixomax^d\}
1206 prad_max(ix^d) = maxval(prad_tensor(ix^d,:,:))
1207 {enddo\}
1208
1209 ptot(ixo^s) = pth(ixo^s) + prad_max(ixo^s)
1210
1211 end subroutine hd_get_ptot
1212
1213 !> Calculates radiation temperature
1214 ! note: const_rad_a is assuming cgs units
1215 subroutine hd_get_trad(w, x, ixI^L, ixO^L, trad)
1217 use mod_constants
1218
1219 integer, intent(in) :: ixi^l, ixo^l
1220 double precision, intent(in) :: w(ixi^s, 1:nw)
1221 double precision, intent(in) :: x(ixi^s, 1:ndim)
1222 double precision, intent(out):: trad(ixi^s)
1223
1224 trad(ixi^s) = (w(ixi^s,r_e)*unit_pressure&
1225 /const_rad_a)**(1.d0/4.d0)/unit_temperature
1226
1227 end subroutine hd_get_trad
1228
1229 !> Calculate temperature=p/rho when in e_ the total energy is stored
1230 subroutine hd_get_temperature_from_etot(w, x, ixI^L, ixO^L, res)
1232 integer, intent(in) :: ixi^l, ixo^l
1233 double precision, intent(in) :: w(ixi^s, 1:nw)
1234 double precision, intent(in) :: x(ixi^s, 1:ndim)
1235 double precision, intent(out):: res(ixi^s)
1236
1237 double precision :: r(ixi^s)
1238
1239 call hd_get_rfactor(w,x,ixi^l,ixo^l,r)
1240 call hd_get_pthermal(w, x, ixi^l, ixo^l, res)
1241 res(ixo^s)=res(ixo^s)/(r(ixo^s)*w(ixo^s,rho_))
1242 end subroutine hd_get_temperature_from_etot
1243
1244 !> Calculate temperature=p/rho when in e_ the internal energy is stored
1245 subroutine hd_get_temperature_from_eint(w, x, ixI^L, ixO^L, res)
1247 integer, intent(in) :: ixi^l, ixo^l
1248 double precision, intent(in) :: w(ixi^s, 1:nw)
1249 double precision, intent(in) :: x(ixi^s, 1:ndim)
1250 double precision, intent(out):: res(ixi^s)
1251
1252 double precision :: r(ixi^s)
1253
1254 call hd_get_rfactor(w,x,ixi^l,ixo^l,r)
1255 res(ixo^s) = (hd_gamma - 1.0d0) * w(ixo^s, e_)/(w(ixo^s,rho_)*r(ixo^s))
1256 end subroutine hd_get_temperature_from_eint
1257
1258 ! Calculate flux f_idim[iw]
1259 subroutine hd_get_flux(wC, w, x, ixI^L, ixO^L, idim, f)
1261 use mod_dust, only: dust_get_flux_prim
1262
1263 integer, intent(in) :: ixi^l, ixo^l, idim
1264 ! conservative w
1265 double precision, intent(in) :: wc(ixi^s, 1:nw)
1266 ! primitive w
1267 double precision, intent(in) :: w(ixi^s, 1:nw)
1268 double precision, intent(in) :: x(ixi^s, 1:ndim)
1269 double precision, intent(out) :: f(ixi^s, nwflux)
1270
1271 double precision :: pth(ixi^s)
1272 integer :: ix^db
1273
1274 if (hd_energy) then
1275 {do ix^db=ixomin^db,ixomax^db\}
1276 f(ix^d,rho_)=w(ix^d,mom(idim))*w(ix^d,rho_)
1277 ! Momentum flux is v_i*m_i, +p in direction idim
1278 ^c&f(ix^d,m^c_)=w(ix^d,mom(idim))*wc(ix^d,m^c_)\
1279 f(ix^d,mom(idim))=f(ix^d,mom(idim))+w(ix^d,p_)
1280 ! Energy flux is v_i*(e + p)
1281 f(ix^d,e_)=w(ix^d,mom(idim))*(wc(ix^d,e_)+w(ix^d,p_))
1282 {end do\}
1283 else
1284 call hd_get_pthermal(wc, x, ixi^l, ixo^l, pth)
1285 {do ix^db=ixomin^db,ixomax^db\}
1286 f(ix^d,rho_)=w(ix^d,mom(idim))*w(ix^d,rho_)
1287 ! Momentum flux is v_i*m_i, +p in direction idim
1288 ^c&f(ix^d,m^c_)=w(ix^d,mom(idim))*wc(ix^d,m^c_)\
1289 f(ix^d,mom(idim))=f(ix^d,mom(idim))+pth(ix^d)
1290 {end do\}
1291 end if
1292
1293 if(hd_radiation_fld)then
1294 {do ix^db=ixomin^db,ixomax^db\}
1295 ! advection of radiation enery v_i*r_e
1296 f(ix^d,r_e)=w(ix^d,mom(idim))*wc(ix^d,r_e)
1297 {end do\}
1298 endif
1299
1300 do ix1 = 1, hd_n_tracer
1301 f(ixo^s, tracer(ix1)) = w(ixo^s,mom(idim)) * w(ixo^s, tracer(ix1))
1302 end do
1303
1304 ! Dust fluxes
1305 if (hd_dust) then
1306 call dust_get_flux_prim(w, x, ixi^l, ixo^l, idim, f)
1307 end if
1308
1309 end subroutine hd_get_flux
1310
1311 !> Add geometrical source terms to w
1312 !>
1313 !> Notice that the expressions of the geometrical terms depend only on ndir,
1314 !> not ndim. Eg, they are the same in 2.5D and in 3D, for any geometry.
1315 !>
1316 subroutine hd_add_source_geom(qdt, dtfactor, ixI^L, ixO^L, wCT, wprim, w, x)
1321 use mod_geometry
1322 integer, intent(in) :: ixi^l, ixo^l
1323 double precision, intent(in) :: qdt, dtfactor, x(ixi^s, 1:ndim)
1324 double precision, intent(inout) :: wct(ixi^s, 1:nw), wprim(ixi^s,1:nw),w(ixi^s, 1:nw)
1325 double precision :: pth(ixi^s), source(ixi^s), minrho
1326 integer :: iw,idir, h1x^l{^nooned, h2x^l}
1327 integer :: mr_,mphi_ ! Polar var. names
1328 integer :: irho, ifluid, n_fluids
1329 double precision :: exp_factor(ixi^s), del_exp_factor(ixi^s), exp_factor_primitive(ixi^s)
1330
1331 if (hd_dust) then
1332 n_fluids = 1 + dust_n_species
1333 else
1334 n_fluids = 1
1335 end if
1336
1337 select case (coordinate)
1338
1340 !the user provides the functions of exp_factor and del_exp_factor
1341 if(associated(usr_set_surface)) call usr_set_surface(ixi^l,x,block%dx,exp_factor,del_exp_factor,exp_factor_primitive)
1342 if(hd_energy) then
1343 source(ixo^s)=wprim(ixo^s, p_)
1344 else
1345 if(.not. associated(usr_set_pthermal)) then
1346 source(ixo^s)=hd_adiab * wprim(ixo^s, rho_)**hd_gamma
1347 else
1348 call usr_set_pthermal(wct,x,ixi^l,ixo^l,source)
1349 end if
1350 end if
1351 source(ixo^s) = source(ixo^s)*del_exp_factor(ixo^s)/exp_factor(ixo^s)
1352 w(ixo^s,mom(1)) = w(ixo^s,mom(1)) + qdt*source(ixo^s)
1353
1354 case (cylindrical)
1355 do ifluid = 0, n_fluids-1
1356 ! s[mr]=(pthermal+mphi**2/rho)/radius
1357 if (ifluid == 0) then
1358 ! gas
1359 irho = rho_
1360 mr_ = mom(r_)
1361 if(phi_>0) mphi_ = mom(phi_)
1362 if(hd_energy) then
1363 source(ixo^s)=wprim(ixo^s, p_)
1364 else
1365 if(.not. associated(usr_set_pthermal)) then
1366 source(ixo^s)=hd_adiab * wprim(ixo^s, rho_)**hd_gamma
1367 else
1368 call usr_set_pthermal(wct,x,ixi^l,ixo^l,source)
1369 end if
1370 end if
1371 minrho = 0.0d0
1372 else
1373 ! dust : no pressure
1374 irho = dust_rho(ifluid)
1375 mr_ = dust_mom(r_, ifluid)
1376 if(phi_>0) mphi_ = dust_mom(phi_, ifluid)
1377 source(ixi^s) = zero
1378 minrho = 0.0d0
1379 end if
1380 if(phi_ > 0) then
1381 where (wct(ixo^s, irho) > minrho)
1382 source(ixo^s) = source(ixo^s) + wct(ixo^s,mphi_)*wprim(ixo^s,mphi_)
1383 w(ixo^s, mr_) = w(ixo^s, mr_) + qdt*source(ixo^s)/x(ixo^s,r_)
1384 end where
1385 ! s[mphi]=(-mphi*vr)/radius
1386 where (wct(ixo^s, irho) > minrho)
1387 source(ixo^s) = -wct(ixo^s, mphi_) * wprim(ixo^s, mr_)
1388 w(ixo^s, mphi_) = w(ixo^s, mphi_) + qdt * source(ixo^s) / x(ixo^s, r_)
1389 end where
1390 else
1391 ! s[mr]=2pthermal/radius
1392 w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, r_)
1393 end if
1394 end do
1395 case (spherical)
1396 if (hd_dust) then
1397 call mpistop("Dust geom source terms not implemented yet with spherical geometries")
1398 end if
1399 mr_ = mom(r_)
1400 if(phi_>0) mphi_ = mom(phi_)
1401 h1x^l=ixo^l-kr(1,^d); {^nooned h2x^l=ixo^l-kr(2,^d);}
1402 if(hd_energy) then
1403 pth(ixo^s)=wprim(ixo^s, p_)
1404 else
1405 if(.not. associated(usr_set_pthermal)) then
1406 pth(ixo^s)=hd_adiab * wprim(ixo^s, rho_)**hd_gamma
1407 else
1408 call usr_set_pthermal(wct,x,ixi^l,ixo^l,pth)
1409 end if
1410 end if
1411 ! s[mr]=((vtheta**2+vphi**2)*rho+2*p)/r
1412 source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1413 *(block%surfaceC(ixo^s, 1) - block%surfaceC(h1x^s, 1)) &
1414 /block%dvolume(ixo^s)
1415 do idir = 2, ndir
1416 source(ixo^s) = source(ixo^s) + wprim(ixo^s, mom(idir))**2 * wprim(ixo^s, rho_)
1417 end do
1418 w(ixo^s, mr_) = w(ixo^s, mr_) + qdt * source(ixo^s) / x(ixo^s, 1)
1419
1420 {^nooned
1421 ! s[mtheta]=-(vr*vtheta*rho)/r+cot(theta)*(vphi**2*rho+p)/r
1422 source(ixo^s) = pth(ixo^s) * x(ixo^s, 1) &
1423 * (block%surfaceC(ixo^s, 2) - block%surfaceC(h2x^s, 2)) &
1424 / block%dvolume(ixo^s)
1425 if (ndir == 3) then
1426 source(ixo^s) = source(ixo^s) + (wprim(ixo^s, mom(3))**2 * wprim(ixo^s, rho_)) / tan(x(ixo^s, 2))
1427 end if
1428 source(ixo^s) = source(ixo^s) - (wprim(ixo^s, mom(2)) * wprim(ixo^s, mr_)) * wprim(ixo^s, rho_)
1429 w(ixo^s, mom(2)) = w(ixo^s, mom(2)) + qdt * source(ixo^s) / x(ixo^s, 1)
1430
1431 if (ndir == 3) then
1432 ! s[mphi]=-(vphi*vr/rho)/r-cot(theta)*(vtheta*vphi/rho)/r
1433 source(ixo^s) = -(wprim(ixo^s, mom(3)) * wprim(ixo^s, mr_)) * wprim(ixo^s, rho_)&
1434 - (wprim(ixo^s, mom(2)) * wprim(ixo^s, mom(3))) * wprim(ixo^s, rho_) / tan(x(ixo^s, 2))
1435 w(ixo^s, mom(3)) = w(ixo^s, mom(3)) + qdt * source(ixo^s) / x(ixo^s, 1)
1436 end if
1437 }
1438 end select
1439
1440 if (hd_rotating_frame) then
1441 if (hd_dust) then
1442 call mpistop("Rotating frame not implemented yet with dust")
1443 else
1444 call rotating_frame_add_source(qdt,dtfactor,ixi^l,ixo^l,wprim,w,x)
1445 end if
1446 end if
1447
1448 end subroutine hd_add_source_geom
1449
1450 ! w[iw]= w[iw]+qdt*S[wCT, qtC, x] where S is the source based on wCT within ixO
1451 subroutine hd_add_source(qdt,dtfactor, ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
1456 use mod_usr_methods, only: usr_gravity
1458 use mod_cak_force, only: cak_add_source
1459
1460 integer, intent(in) :: ixi^l, ixo^l
1461 double precision, intent(in) :: qdt, dtfactor
1462 double precision, intent(in) :: wct(ixi^s, 1:nw),wctprim(ixi^s,1:nw), x(ixi^s, 1:ndim)
1463 double precision, intent(inout) :: w(ixi^s, 1:nw)
1464 logical, intent(in) :: qsourcesplit
1465 logical, intent(inout) :: active
1466
1467 double precision :: gravity_field(ixi^s, 1:ndim)
1468 integer :: idust, idim
1469
1470 if(hd_dust .and. .not. hd_dust_implicit) then
1471 call dust_add_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1472 end if
1473
1474 if(hd_radiative_cooling) then
1475 call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1476 qsourcesplit,active, rc_fl)
1477 end if
1478
1479 if(hd_viscosity) then
1480 call viscosity_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1481 hd_energy,qsourcesplit,active)
1482 end if
1483
1484 if (hd_gravity) then
1485 call gravity_add_source(qdt,ixi^l,ixo^l,wct,wctprim,w,x,&
1486 hd_energy,qsourcesplit,active)
1487
1488 if (hd_dust .and. qsourcesplit .eqv. grav_split) then
1489 active = .true.
1490
1491 call usr_gravity(ixi^l, ixo^l, wct, x, gravity_field)
1492 do idust = 1, dust_n_species
1493 do idim = 1, ndim
1494 w(ixo^s, dust_mom(idim, idust)) = w(ixo^s, dust_mom(idim, idust)) &
1495 + qdt * gravity_field(ixo^s, idim) * wct(ixo^s, dust_rho(idust))
1496 end do
1497 end do
1498 end if
1499 end if
1500
1501 if (hd_cak_force) then
1502 call cak_add_source(qdt,ixi^l,ixo^l,wct,w,x,hd_energy,qsourcesplit,active)
1503 end if
1504
1505 ! This is where the radiation force and heating/cooling are added
1506 if (hd_radiation_fld) then
1507 call hd_add_radiation_source(qdt,ixi^l,ixo^l,wct,w,x,qsourcesplit,active)
1508 endif
1509
1510 if(hd_partial_ionization) then
1511 if(.not.qsourcesplit) then
1512 active = .true.
1513 call hd_update_temperature(ixi^l,ixo^l,wct,w,x)
1514 end if
1515 end if
1516
1517 end subroutine hd_add_source
1518
1519 subroutine hd_add_radiation_source(qdt,ixI^L,ixO^L,wCT,w,x,qsourcesplit,active)
1520 use mod_constants
1522 use mod_usr_methods
1523 use mod_fld
1524 use mod_afld
1525
1526 integer, intent(in) :: ixi^l, ixo^l
1527 double precision, intent(in) :: qdt, x(ixi^s,1:ndim)
1528 double precision, intent(in) :: wct(ixi^s,1:nw)
1529 double precision, intent(inout) :: w(ixi^s,1:nw)
1530 logical, intent(in) :: qsourcesplit
1531 logical, intent(inout) :: active
1532 double precision :: cmax(ixi^s)
1533
1534 select case(hd_radiation_fld_formalism)
1535 case('fld')
1536 call fld_get_diffcoef_central(w, wct, x, ixi^l, ixo^l)
1537 ! radiation force
1538 call get_fld_rad_force(qdt,ixi^l,ixo^l,wct,w,x,&
1539 hd_energy,qsourcesplit,active)
1540 call hd_handle_small_values(.true., w, x, ixi^l, ixo^l, 'fld_add_radiation')
1541 case('afld')
1542 call afld_get_diffcoef_central(w, wct, x, ixi^l, ixo^l)
1543 ! radiation force
1544 call get_afld_rad_force(qdt,ixi^l,ixo^l,wct,w,x,&
1545 hd_energy,qsourcesplit,active)
1546 call hd_handle_small_values(.true., w, x, ixi^l, ixo^l, 'afld_add_radiation')
1547 ! photon tiring, heating and cooling
1548 call get_afld_energy_interact(qdt,ixi^l,ixo^l,wct,w,x,&
1549 hd_energy,qsourcesplit,active)
1550 case default
1551 call mpistop('Radiation formalism unknown')
1552 end select
1553
1554 end subroutine hd_add_radiation_source
1555
1556 subroutine hd_get_dt(w, ixI^L, ixO^L, dtnew, dx^D, x)
1558 use mod_dust, only: dust_get_dt
1560 use mod_gravity, only: gravity_get_dt
1561 use mod_cak_force, only: cak_get_dt
1562 use mod_fld, only: fld_radforce_get_dt
1564
1565 integer, intent(in) :: ixi^l, ixo^l
1566 double precision, intent(in) :: dx^d, x(ixi^s, 1:^nd)
1567 double precision, intent(in) :: w(ixi^s, 1:nw)
1568 double precision, intent(inout) :: dtnew
1569
1570 dtnew = bigdouble
1571
1572 if(hd_dust) then
1573 call dust_get_dt(w, ixi^l, ixo^l, dtnew, dx^d, x)
1574 end if
1575
1576 if(hd_viscosity) then
1577 call viscosity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1578 end if
1579
1580 if(hd_gravity) then
1581 call gravity_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1582 end if
1583
1584 if (hd_cak_force) then
1585 call cak_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1586 end if
1587
1588 if(hd_radiation_fld) then
1589 select case(hd_radiation_fld_formalism)
1590 case('fld')
1591 call fld_radforce_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1592 case('afld')
1593 call afld_radforce_get_dt(w,ixi^l,ixo^l,dtnew,dx^d,x)
1594 case default
1595 call mpistop('Radiation formalism unknown')
1596 end select
1597 endif
1598
1599 end subroutine hd_get_dt
1600
1601 function hd_kin_en(w, ixI^L, ixO^L, inv_rho) result(ke)
1602 use mod_global_parameters, only: nw, ndim
1603 integer, intent(in) :: ixi^l, ixo^l
1604 double precision, intent(in) :: w(ixi^s, nw)
1605 double precision :: ke(ixo^s)
1606 double precision, intent(in), optional :: inv_rho(ixo^s)
1607
1608 if (present(inv_rho)) then
1609 ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) * inv_rho
1610 else
1611 ke = 0.5d0 * sum(w(ixo^s, mom(:))**2, dim=ndim+1) / w(ixo^s, rho_)
1612 end if
1613 end function hd_kin_en
1614
1615 function hd_inv_rho(w, ixI^L, ixO^L) result(inv_rho)
1616 use mod_global_parameters, only: nw, ndim
1617 integer, intent(in) :: ixi^l, ixo^l
1618 double precision, intent(in) :: w(ixi^s, nw)
1619 double precision :: inv_rho(ixo^s)
1620
1621 ! Can make this more robust
1622 inv_rho = 1.0d0 / w(ixo^s, rho_)
1623 end function hd_inv_rho
1624
1625 subroutine hd_handle_small_values(primitive, w, x, ixI^L, ixO^L, subname)
1626 ! handles hydro (density,pressure,velocity) bootstrapping
1627 ! any negative dust density is flagged as well (and throws an error)
1628 ! small_values_method=replace also for dust
1632 logical, intent(in) :: primitive
1633 integer, intent(in) :: ixi^l,ixo^l
1634 double precision, intent(inout) :: w(ixi^s,1:nw)
1635 double precision, intent(in) :: x(ixi^s,1:ndim)
1636 character(len=*), intent(in) :: subname
1637
1638 integer :: n,idir
1639 logical :: flag(ixi^s,1:nw)
1640
1641 call hd_check_w(primitive, ixi^l, ixo^l, w, flag)
1642
1643 if (any(flag)) then
1644 select case (small_values_method)
1645 case ("replace")
1646 where(flag(ixo^s,rho_)) w(ixo^s,rho_) = small_density
1647 do idir = 1, ndir
1648 if(small_values_fix_iw(mom(idir))) then
1649 where(flag(ixo^s,rho_)) w(ixo^s, mom(idir)) = 0.0d0
1650 end if
1651 end do
1652 if(hd_radiation_fld)then
1653 if (small_values_fix_iw(r_e)) then
1654 where(flag(ixo^s,r_e)) w(ixo^s,r_e) = small_r_e
1655 end if
1656 end if
1657 if(hd_energy)then
1658 if(small_values_fix_iw(e_)) then
1659 if(primitive) then
1660 where(flag(ixo^s,rho_)) w(ixo^s, p_) = small_pressure
1661 else
1662 where(flag(ixo^s,rho_)) w(ixo^s, e_) = small_e + hd_kin_en(w,ixi^l,ixo^l)
1663 endif
1664 end if
1665 endif
1666
1667 if(hd_energy) then
1668 if(primitive) then
1669 where(flag(ixo^s,e_)) w(ixo^s,p_) = small_pressure
1670 else
1671 where(flag(ixo^s,e_))
1672 ! Add kinetic energy
1673 w(ixo^s,e_) = small_e + hd_kin_en(w,ixi^l,ixo^l)
1674 end where
1675 end if
1676 end if
1677
1678 if(hd_dust)then
1679 do n=1,dust_n_species
1680 where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1681 do idir = 1, ndir
1682 where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1683 enddo
1684 enddo
1685 endif
1686 case ("average")
1687 if(primitive)then
1688 ! averaging for all primitive fields, including dust
1689 call small_values_average(ixi^l, ixo^l, w, x, flag)
1690 else
1691 ! do averaging of density
1692 call small_values_average(ixi^l, ixo^l, w, x, flag, rho_)
1693 if(hd_energy) then
1694 ! do averaging of pressure
1695 w(ixi^s,p_)=(hd_gamma-1.d0)*(w(ixi^s,e_) &
1696 -0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_))
1697 call small_values_average(ixi^l, ixo^l, w, x, flag, p_)
1698 w(ixi^s,e_)=w(ixi^s,p_)/(hd_gamma-1.d0) &
1699 +0.5d0*sum(w(ixi^s, mom(:))**2, dim=ndim+1)/w(ixi^s,rho_)
1700 end if
1701 if(hd_radiation_fld) then
1702 ! do averaging of radiative energy density
1703 call small_values_average(ixi^l, ixo^l, w, x, flag, r_e)
1704 endif
1705 if(hd_dust)then
1706 do n=1,dust_n_species
1707 where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_rho(n)) = 0.0d0
1708 do idir = 1, ndir
1709 where(flag(ixo^s,dust_rho(n))) w(ixo^s,dust_mom(idir,n)) = 0.0d0
1710 enddo
1711 enddo
1712 endif
1713 endif
1714 case default
1715 if(.not.primitive) then
1716 !convert w to primitive
1717 ! Calculate pressure = (gamma-1) * (e-ek)
1718 if(hd_energy) then
1719 w(ixo^s,p_)=(hd_gamma-1.d0)*(w(ixo^s,e_)-hd_kin_en(w,ixi^l,ixo^l))
1720 end if
1721 ! Convert gas momentum to velocity
1722 do idir = 1, ndir
1723 w(ixo^s, mom(idir)) = w(ixo^s, mom(idir))/w(ixo^s,rho_)
1724 end do
1725 end if
1726 ! NOTE: dust entries may still have conserved values here
1727 call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
1728 end select
1729 end if
1730 end subroutine hd_handle_small_values
1731
1732 subroutine rfactor_from_temperature_ionization(w,x,ixI^L,ixO^L,Rfactor)
1735 integer, intent(in) :: ixi^l, ixo^l
1736 double precision, intent(in) :: w(ixi^s,1:nw)
1737 double precision, intent(in) :: x(ixi^s,1:ndim)
1738 double precision, intent(out):: rfactor(ixi^s)
1739
1740 double precision :: iz_h(ixo^s),iz_he(ixo^s)
1741
1742 call ionization_degree_from_temperature(ixi^l,ixo^l,w(ixi^s,te_),iz_h,iz_he)
1743 ! assume the first and second ionization of Helium have the same degree
1744 rfactor(ixo^s)=(1.d0+iz_h(ixo^s)+0.1d0*(1.d0+iz_he(ixo^s)*(1.d0+iz_he(ixo^s))))/2.3d0
1745
1746 end subroutine rfactor_from_temperature_ionization
1747
1748 subroutine rfactor_from_constant_ionization(w,x,ixI^L,ixO^L,Rfactor)
1750 integer, intent(in) :: ixi^l, ixo^l
1751 double precision, intent(in) :: w(ixi^s,1:nw)
1752 double precision, intent(in) :: x(ixi^s,1:ndim)
1753 double precision, intent(out):: rfactor(ixi^s)
1754
1755 rfactor(ixo^s)=rr
1756
1757 end subroutine rfactor_from_constant_ionization
1758
1759 subroutine hd_update_temperature(ixI^L,ixO^L,wCT,w,x)
1762
1763 integer, intent(in) :: ixi^l, ixo^l
1764 double precision, intent(in) :: wct(ixi^s,1:nw), x(ixi^s,1:ndim)
1765 double precision, intent(inout) :: w(ixi^s,1:nw)
1766
1767 double precision :: iz_h(ixo^s),iz_he(ixo^s), pth(ixi^s)
1768
1769 call ionization_degree_from_temperature(ixi^l,ixo^l,wct(ixi^s,te_),iz_h,iz_he)
1770
1771 call hd_get_pthermal(w,x,ixi^l,ixo^l,pth)
1772
1773 w(ixo^s,te_)=(2.d0+3.d0*he_abundance)*pth(ixo^s)/(w(ixo^s,rho_)*(1.d0+iz_h(ixo^s)+&
1774 he_abundance*(iz_he(ixo^s)*(iz_he(ixo^s)+1.d0)+1.d0)))
1775
1776 end subroutine hd_update_temperature
1777
1778end module mod_hd_phys
Calculate w(iw)=w(iw)+qdt*SOURCE[wCT,qtC,x] within ixO for all indices iw=iwmin......
Module for including anisotropic flux limited diffusion (AFLD)-approximation in Radiation-hydrodynami...
Definition mod_afld.t:8
subroutine afld_get_diffcoef_central(w, wct, x, ixil, ixol)
Calculates cell-centered diffusion coefficient to be used in multigrid.
Definition mod_afld.t:674
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:130
subroutine, public afld_radforce_get_dt(w, ixil, ixol, dtnew, dxd, x)
Definition mod_afld.t:206
subroutine, public afld_get_radpress(w, x, ixil, ixol, rad_pressure, nth)
Calculate Radiation Pressure Returns Radiation Pressure as tensor.
Definition mod_afld.t:508
subroutine, public afld_init(he_abundance, afld_gamma)
Initialising FLD-module: Read opacities Initialise Multigrid adimensionalise kappa Add extra variable...
Definition mod_afld.t:91
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:233
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...
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.
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
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module for physical and numeric constants.
double precision, parameter bigdouble
A very large real number.
double precision, parameter const_rad_a
Module for including dust species, which interact with the gas through a drag force.
Definition mod_dust.t:3
subroutine, public dust_add_source(qdt, ixil, ixol, wct, w, x, qsourcesplit, active)
w[iw]= w[iw]+qdt*S[wCT, x] where S is the source based on wCT within ixO
Definition mod_dust.t:530
subroutine, public dust_evaluate_implicit(qtc, psa)
inplace update of psa==>F_im(psa)
Definition mod_dust.t:583
subroutine, public dust_to_primitive(ixil, ixol, w, x)
Definition mod_dust.t:228
subroutine, public dust_get_dt(w, ixil, ixol, dtnew, dxd, x)
Get dt related to dust and gas stopping time (Laibe 2011)
Definition mod_dust.t:898
integer, dimension(:, :), allocatable, public, protected dust_mom
Indices of the dust momentum densities.
Definition mod_dust.t:47
subroutine, public dust_to_conserved(ixil, ixol, w, x)
Definition mod_dust.t:208
integer, public, protected dust_n_species
The number of dust species.
Definition mod_dust.t:37
subroutine, public dust_get_flux_prim(w, x, ixil, ixol, idim, f)
Definition mod_dust.t:275
subroutine, public dust_check_w(ixil, ixol, w, flag)
Definition mod_dust.t:194
integer, dimension(:), allocatable, public, protected dust_rho
Indices of the dust densities.
Definition mod_dust.t:44
subroutine, public dust_get_cmax(w, x, ixil, ixol, idim, cmax, cmin)
Definition mod_dust.t:1011
subroutine, public dust_check_params()
Definition mod_dust.t:154
subroutine, public dust_get_cmax_prim(w, x, ixil, ixol, idim, cmax, cmin)
Definition mod_dust.t:1035
subroutine, public dust_init(g_rho, g_mom, g_energy)
Definition mod_dust.t:95
subroutine, public dust_implicit_update(dtfactor, qdt, qtc, psb, psa)
Implicit solve of psb=psa+dtfactor*dt*F_im(psb)
Definition mod_dust.t:652
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
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:138
subroutine, public fld_get_radpress(w, x, ixil, ixol, rad_pressure, nth)
Calculate Radiation Pressure Returns Radiation Pressure as tensor.
Definition mod_fld.t:449
subroutine fld_get_diffcoef_central(w, wct, x, ixil, ixol)
Calculates cell-centered diffusion coefficient to be used in multigrid.
Definition mod_fld.t:712
subroutine, public fld_init(he_abundance, r_gamma)
Initialising FLD-module: Read opacities Initialise Multigrid adimensionalise kappa Add extra variable...
Definition mod_fld.t:91
subroutine, public fld_radforce_get_dt(w, ixil, ixol, dtnew, dxd, x)
Definition mod_fld.t:173
Module with geometry-related routines (e.g., divergence, curl)
Definition mod_geometry.t:2
integer coordinate
Definition mod_geometry.t:7
integer, parameter spherical
integer, parameter cylindrical
integer, parameter cartesian_expansion
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 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
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.
integer, dimension(:, :), allocatable typeboundary
Array indicating the type of boundary condition per variable and per physical boundary.
double precision unit_numberdensity
Physical scaling factor for number density.
character(len=std_len) convert_type
Which format to use when converting.
double precision unit_pressure
Physical scaling factor for pressure.
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision unit_length
Physical scaling factor for length.
logical use_particles
Use particles module or not.
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
integer mype
The rank of the current MPI task.
double precision, dimension(:), allocatable, parameter d
integer ndir
Number of spatial dimensions (components) for vector variables.
integer, parameter bc_periodic
integer, parameter bc_special
boundary condition types
double precision unit_velocity
Physical scaling factor for velocity.
double precision unit_temperature
Physical scaling factor for temperature.
double precision unit_radflux
Physical scaling factor for radiation flux.
logical si_unit
Use SI units (.true.) or use cgs units (.false.)
double precision, dimension(:,:), allocatable dx
spatial steps for all dimensions at all levels
integer nghostcells
Number of ghost cells surrounding a grid.
logical phys_trac
Use TRAC for MHD or 1D HD.
logical fix_small_values
fix small values with average or replace methods
logical crash
Save a snapshot before crash a run met unphysical values.
logical use_multigrid
Use multigrid (only available in 2D and 3D)
integer r_
Indices for cylindrical coordinates FOR TESTS, negative value when not used:
integer boundspeed
bound (left/min and right.max) speed of Riemann fan
integer, parameter unitconvert
logical check_small_values
check and optionally fix unphysical small values (density, gas pressure)
Module for including gravity in (magneto)hydrodynamics simulations.
Definition mod_gravity.t:2
logical grav_split
source split or not
Definition mod_gravity.t:6
subroutine gravity_get_dt(w, ixil, ixol, dtnew, dxd, x)
Definition mod_gravity.t:81
subroutine gravity_init()
Initialize the module.
Definition mod_gravity.t:26
subroutine gravity_add_source(qdt, ixil, ixol, wct, wctprim, 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:43
Hydrodynamics physics module.
Definition mod_hd_phys.t:2
integer, public, protected m
Definition mod_hd_phys.t:63
subroutine, public hd_check_params
logical, public, protected hd_energy
Whether an energy equation is used.
Definition mod_hd_phys.t:12
logical, public, protected hd_dust
Whether dust is added.
Definition mod_hd_phys.t:24
subroutine, public hd_ei_to_e(ixil, ixol, w, x)
Transform internal energy to total energy.
integer, public, protected e_
Index of the energy density (-1 if not present)
Definition mod_hd_phys.t:69
logical, public, protected hd_radiative_cooling
Whether radiative cooling is added.
Definition mod_hd_phys.t:20
double precision, public, protected rr
double precision, public hd_gamma
The adiabatic index.
Definition mod_hd_phys.t:84
subroutine, public hd_get_temperature_from_etot(w, x, ixil, ixol, res)
Calculate temperature=p/rho when in e_ the total energy is stored.
integer, public, protected hd_trac_type
logical, public, protected hd_particles
Whether particles module is added.
Definition mod_hd_phys.t:42
logical, public, protected hd_radiation_fld
Whether radiation-gas interaction is handled using flux limited diffusion.
Definition mod_hd_phys.t:30
type(tc_fluid), allocatable, public tc_fl
Definition mod_hd_phys.t:16
subroutine, public hd_check_w(primitive, ixil, ixol, w, flag)
Returns logical argument flag where values are ok.
logical, public, protected hd_viscosity
Whether viscosity is added.
Definition mod_hd_phys.t:36
integer, public, protected r_e
Index of the radiation energy (when fld active)
Definition mod_hd_phys.t:75
procedure(sub_get_pthermal), pointer, public hd_get_rfactor
integer, public, protected c
Indices of the momentum density for the form of better vectorization.
Definition mod_hd_phys.t:63
subroutine, public hd_get_ptot(w, x, ixil, ixol, ptot)
calculates the sum of the gas pressure and max Prad tensor element
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.
integer, public, protected tcoff_
Index of the cutoff temperature for the TRAC method.
Definition mod_hd_phys.t:81
double precision, public, protected he_ion_fr2
Ratio of number He2+ / number He+ + He2+ He_ion_fr2 = He2+/(He2+ + He+)
integer, public, protected te_
Indices of temperature.
Definition mod_hd_phys.t:78
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
Definition mod_hd_phys.t:60
double precision, public, protected h_ion_fr
Ionization fraction of H H_ion_fr = H+/(H+ + H)
double precision function, dimension(ixo^s), public hd_kin_en(w, ixil, ixol, inv_rho)
subroutine, public hd_to_conserved(ixil, ixol, w, x)
Transform primitive variables into conservative ones.
logical, public, protected hd_cak_force
Whether CAK radiation line force is activated.
Definition mod_hd_phys.t:48
subroutine, public hd_phys_init()
Initialize the module.
integer, dimension(:), allocatable, public, protected tracer
Indices of the tracers.
Definition mod_hd_phys.t:66
logical, public, protected hd_thermal_conduction
Whether thermal conduction is added.
Definition mod_hd_phys.t:15
logical, public, protected eq_state_units
double precision, public hd_adiab
The adiabatic constant.
Definition mod_hd_phys.t:90
subroutine, public hd_get_trad(w, x, ixil, ixol, trad)
Calculates radiation temperature.
subroutine, public hd_to_primitive(ixil, ixol, w, x)
Transform conservative variables into primitive ones.
subroutine, public hd_set_mg_bounds
Set the boundaries for the diffusion of E.
integer, public, protected rho_
Index of the density (in the w array)
Definition mod_hd_phys.t:57
logical, public, protected hd_partial_ionization
Whether plasma is partially ionized.
Definition mod_hd_phys.t:54
double precision, public, protected small_r_e
The smallest allowed radiation energy (when fld active)
Definition mod_hd_phys.t:96
double precision, public, protected he_ion_fr
Ionization fraction of He He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
double precision, public, protected he_abundance
Helium abundance over Hydrogen.
logical, public, protected hd_gravity
Whether gravity is added.
Definition mod_hd_phys.t:39
integer, public, protected c_
Definition mod_hd_phys.t:63
type(rc_fluid), allocatable, public rc_fl
Definition mod_hd_phys.t:21
logical, public, protected hd_dust_implicit
Whether dust is added using and implicit update in IMEX.
Definition mod_hd_phys.t:27
subroutine, public hd_get_pradiation(w, x, ixil, ixol, prad)
Calculate radiation pressure within ixO^L.
logical, public, protected hd_trac
Whether TRAC method is used.
Definition mod_hd_phys.t:99
integer, public, protected hd_n_tracer
Number of tracer species.
Definition mod_hd_phys.t:51
type(te_fluid), allocatable, public te_fl_hd
Definition mod_hd_phys.t:17
logical, public, protected hd_rotating_frame
Whether rotating frame is activated.
Definition mod_hd_phys.t:45
subroutine, public hd_get_pthermal(w, x, ixil, ixol, pth)
Calculate thermal pressure=(gamma-1)*(e-0.5*m**2/rho) within ixO^L.
character(len=8), public hd_radiation_fld_formalism
Formalism to treat radiation: either fld or afld (anisotropic fld)
Definition mod_hd_phys.t:33
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
Definition mod_hd_phys.t:72
subroutine, public hd_e_to_ei(ixil, ixol, w, x)
Transform total energy to internal energy.
module ionization degree - get ionization degree for given temperature
subroutine ionization_degree_from_temperature(ixil, ixol, te, iz_h, iz_he)
Module to couple the octree-mg library to AMRVAC. This file uses the VACPP preprocessor,...
type(mg_t) mg
Data structure containing the multigrid tree.
Module containing all the particle routines.
subroutine particles_init()
Initialize particle data and parameters.
This module defines the procedures of a physics module. It contains function pointers for the various...
Definition mod_physics.t:4
module radiative cooling – add optically thin radiative cooling
subroutine radiative_cooling_init_params(phys_gamma, he_abund)
Radiative cooling initialization.
subroutine radiative_cooling_init(fl, read_params)
subroutine radiative_cooling_add_source(qdt, ixil, ixol, wct, wctprim, w, x, qsourcesplit, active, fl)
Module for including rotating frame in (magneto)hydrodynamics simulations The rotation vector is assu...
subroutine rotating_frame_add_source(qdt, dtfactor, ixil, ixol, wct, w, x)
w[iw]=w[iw]+qdt*S[wCT,qtC,x] where S is the source based on wCT within ixO
subroutine rotating_frame_init()
Initialize the module.
Module for handling problematic values in simulations, such as negative pressures.
subroutine, public small_values_average(ixil, ixol, w, x, w_flag, windex)
logical, public trace_small_values
trace small values in the source file using traceback flag of compiler
subroutine, public small_values_error(wprim, x, ixil, ixol, w_flag, subname)
logical, dimension(:), allocatable, public small_values_fix_iw
Whether to apply small value fixes to certain variables.
character(len=20), public small_values_method
How to handle small values.
Generic supertimestepping method which can be used for multiple source terms in the governing equatio...
subroutine, public add_sts_method(sts_getdt, sts_set_sources, startvar, nflux, startwbc, nwbc, evolve_b)
subroutine which added programatically a term to be calculated using STS Params: sts_getdt function c...
subroutine, public set_conversion_methods_to_head(sts_before_first_cycle, sts_after_last_cycle)
Set the hooks called before the first cycle and after the last cycle in the STS update This method sh...
subroutine, public set_error_handling_to_head(sts_error_handling)
Set the hook of error handling in the STS update. This method is called before updating the BC....
subroutine, public sts_init()
Initialize sts module.
Thermal conduction for HD and MHD or RHD and RMHD or twofl (plasma-neutral) module Adaptation of mod_...
subroutine, public tc_get_hd_params(fl, read_hd_params)
Init TC coefficients: HD case.
double precision function, public get_tc_dt_hd(w, ixil, ixol, dxd, x, fl)
Get the explicit timestep for the TC (hd implementation) Note: also used in 1D MHD (or for neutrals i...
subroutine tc_init_params(phys_gamma)
subroutine, public sts_set_source_tc_hd(ixil, ixol, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux, fl)
subroutine get_euv_image(qunit, fl)
subroutine get_sxr_image(qunit, fl)
subroutine get_euv_spectrum(qunit, fl)
subroutine get_whitelight_image(qunit, fl)
Module with all the methods that users can customize in AMRVAC.
procedure(rfactor), pointer usr_rfactor
procedure(set_surface), pointer usr_set_surface
procedure(phys_gravity), pointer usr_gravity
procedure(special_mg_bc), pointer usr_special_mg_bc
procedure(hd_pthermal), pointer usr_set_pthermal
integer nw
Total number of variables.
integer number_species
number of species: each species has different characterictic speeds and should be used accordingly in...
The module add viscous source terms and check time step.
subroutine viscosity_init(phys_wider_stencil)
Initialize the module.
subroutine viscosity_get_dt(w, ixil, ixol, dtnew, dxd, x)
procedure(sub_add_source), pointer, public viscosity_add_source