MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_ffhd_phys.t
Go to the documentation of this file.
1!> Frozen-field hydrodynamics module
3
4#include "amrvac.h"
5
6 use mod_global_parameters, only: std_len, const_c
10 use mod_physics
11 use mod_eos
12 use mod_comm_lib, only: mpistop
13
14 implicit none
15 private
16
17 !> Whether an energy equation is used
18 logical, public, protected :: ffhd_energy = .true.
19
20 !> Whether thermal conduction is used
21 logical, public, protected :: ffhd_thermal_conduction = .false.
22 !> Whether hyperbolic type thermal conduction is used
23 logical, public, protected :: ffhd_hyperbolic_tc = .false.
24 !> Whether saturation is considered for hyperbolic TC
25 logical, public, protected :: ffhd_hyperbolic_tc_sat = .false.
26 !> Whether the perpendicular hyperbolic-TC channel is enabled
27 logical, public, protected :: ffhd_hyperbolic_tc_use_perp = .false.
28 !> type of fluid for thermal conduction
29 type(tc_fluid), public, allocatable :: tc_fl
30 !> type of fluid for thermal emission synthesis
31 type(te_fluid), public, allocatable :: te_fl_ffhd
32
33 !> Whether radiative cooling is added
34 logical, public, protected :: ffhd_radiative_cooling = .false.
35 !> type of fluid for radiative cooling
36 type(rc_fluid), public, allocatable :: rc_fl
37
38 !> Whether gravity is added
39 logical, public, protected :: ffhd_gravity = .false.
40
41 !> Whether TRAC method is used
42 logical, public, protected :: ffhd_trac = .false.
43
44 !> Which TRAC method is used
45 integer, public, protected :: ffhd_trac_type=1
46
47 !> Height of the mask used in the TRAC method
48 double precision, public, protected :: ffhd_trac_mask = 0.d0
49
50 !> Distance between two adjacent traced magnetic field lines (in finest cell size)
51 integer, public, protected :: ffhd_trac_finegrid=4
52
53 !> Whether plasma is partially ionized
54
55 !> Index of the density (in the w array)
56 integer, public, protected :: rho_
57
58 !> Indices of the momentum density
59 integer, allocatable, public, protected :: mom(:)
60
61 !> Index of the energy density (-1 if not present)
62 integer, public, protected :: e_
63
64 !> Index of the gas pressure (-1 if not present) should equal e_
65 integer, public, protected :: p_
66
67 !> Indices of temperature and electron number density (LTE stored aux state)
68 integer, public, protected :: te_
69 integer, public, protected :: ne_
70
71 !> Index of the cutoff temperature for the TRAC method
72 integer, public, protected :: tcoff_
73 integer, public, protected :: tweight_
74 integer, public, protected :: q_
75
76 !> The adiabatic index (now owned by eos%; use eos%gamma)
77
78 !> The adiabatic constant
79 double precision, public :: ffhd_adiab = 1.0d0
80
81 !> The thermal conductivity kappa in hyperbolic thermal conduction
82 double precision, public :: hyperbolic_tc_kappa
83
84 !> Helium abundance over Hydrogen (now owned by eos%; use eos%He_abundance)
85 !> Ionization fraction of H
86 !> H_ion_fr = H+/(H+ + H)
87 double precision, public, protected :: h_ion_fr=1d0
88 !> Ionization fraction of He
89 !> He_ion_fr = (He2+ + He+)/(He2+ + He+ + He)
90 double precision, public, protected :: he_ion_fr=1d0
91 !> Ratio of number He2+ / number He+ + He2+
92 !> He_ion_fr2 = He2+/(He2+ + He+)
93 double precision, public, protected :: he_ion_fr2=1d0
94 ! used for eq of state when it is not defined by units,
95 ! the units do not contain terms related to ionization fraction
96 ! and it is p = RR * rho * T
97 double precision, public, protected :: rr=1d0
98 ! remove the below flag and assume default value = .false.
99
100
101 !define the function interface for the kinetic energy
102 abstract interface
103
104 function fun_kin_en(w, ixI^L, ixO^L, inv_rho) result(ke)
105 use mod_global_parameters, only: nw, ndim,block
106 integer, intent(in) :: ixi^l, ixo^l
107 double precision, intent(in) :: w(ixi^s, nw)
108 double precision :: ke(ixo^s)
109 double precision, intent(in), optional :: inv_rho(ixo^s)
110 end function fun_kin_en
111
112 end interface
113
114 procedure(sub_convert), pointer :: ffhd_to_primitive => null()
115 procedure(sub_convert), pointer :: ffhd_to_conserved => null()
116 procedure(sub_small_values), pointer, public :: ffhd_handle_small_values => null()
117 procedure(sub_get_pthermal), pointer :: ffhd_get_pthermal => null()
118 procedure(sub_get_pthermal), pointer :: ffhd_get_rfactor => null()
119 procedure(sub_get_pthermal), pointer :: ffhd_get_temperature => null()
120 procedure(sub_get_v), pointer :: ffhd_get_v => null()
121 procedure(fun_kin_en), pointer :: ffhd_kin_en => null()
122 ! Public methods
123 public :: ffhd_phys_init
124 public :: ffhd_kin_en
125 public :: ffhd_get_ei
126 public :: ffhd_get_pthermal
127 public :: ffhd_get_rfactor
128 public :: ffhd_get_temperature
129 public :: ffhd_get_v
130 public :: ffhd_get_rho
131 public :: ffhd_get_v_idim
132 public :: ffhd_to_conserved
133 public :: ffhd_to_primitive
134 public :: ffhd_get_csound2
135 public :: ffhd_e_to_ei
136 public :: ffhd_ei_to_e
137 ! concrete routines referenced by the mod_ffhd_eos seam
145
146contains
147
148 subroutine ffhd_read_params(files)
150 character(len=*), intent(in) :: files(:)
151 integer :: n
152
153 ! gamma and eos%He_abundance migrated to &eos_list (eos%gamma / eos%He_abundance)
154 namelist /ffhd_list/ ffhd_energy, ffhd_adiab, &
158
159 do n = 1, size(files)
160 open(unitpar, file=trim(files(n)), status="old")
161 read(unitpar, ffhd_list, end=111)
162111 close(unitpar)
163 end do
164 end subroutine ffhd_read_params
165
166 !> Write this module's parameters to a snapsoht
167 subroutine ffhd_write_info(fh)
169 integer, intent(in) :: fh
170 integer, parameter :: n_par = 1
171 double precision :: values(n_par)
172 character(len=name_len) :: names(n_par)
173 integer, dimension(MPI_STATUS_SIZE) :: st
174 integer :: er
175
176 call mpi_file_write(fh, n_par, 1, mpi_integer, st, er)
177
178 names(1) = "gamma"
179 values(1) = eos%gamma
180 call mpi_file_write(fh, values, n_par, mpi_double_precision, st, er)
181 call mpi_file_write(fh, names, n_par * name_len, mpi_character, st, er)
182 end subroutine ffhd_write_info
183
184 subroutine ffhd_phys_init()
188 use mod_gravity, only: gravity_init
193 integer :: itr, idir
194
195 call ffhd_read_params(par_files)
196
197 if(.not. ffhd_energy) then
200 if(mype==0) write(*,*) 'WARNING: set ffhd_thermal_conduction=F when ffhd_energy=F'
201 end if
202 if(ffhd_hyperbolic_tc) then
203 ffhd_hyperbolic_tc=.false.
204 if(mype==0) write(*,*) 'WARNING: set ffhd_hyperbolic_tc=F when ffhd_energy=F'
205 end if
208 if(mype==0) write(*,*) 'WARNING: set ffhd_radiative_cooling=F when ffhd_energy=F'
209 end if
210 if(ffhd_trac) then
211 ffhd_trac=.false.
212 if(mype==0) write(*,*) 'WARNING: set ffhd_trac=F when ffhd_energy=F'
213 end if
214 ! PI/LTE carry a thermodynamic state and so need the energy equation; only
215 ! FI is meaningful without it (also guarded in ffhd_link_eos).
216 if (eos%eos_type /= 'FI') &
217 call mpistop("eos_type "//trim(eos%eos_type)//" requires ffhd_energy=T")
218 end if
219
220 if(ffhd_hyperbolic_tc) then
222 if(mype==0) write(*,*) 'WARNING: turn off parabolic TC when using hyperbolic TC'
223 end if
224
225 physics_type = "ffhd"
226 phys_energy=ffhd_energy
227 phys_internal_e=.false.
230 ! eos_type='PI' is the single partial-ionisation selector (no legacy flag).
231
232 phys_gamma = eos%gamma
233 phys_total_energy=ffhd_energy
235
236 {^ifoned
237 if(ffhd_trac .and. ffhd_trac_type .gt. 2) then
239 if(mype==0) write(*,*) 'WARNING: reset ffhd_trac_type=1 for 1D simulation'
240 end if
241 }
242 if(ffhd_trac .and. ffhd_trac_type .le. 4) then
243 ffhd_trac_mask=bigdouble
244 if(mype==0) write(*,*) 'WARNING: set ffhd_trac_mask==bigdouble for global TRAC method'
245 end if
247
248 allocate(start_indices(number_species),stop_indices(number_species))
249 start_indices(1)=1
250 ! Determine flux variables
251 rho_ = var_set_rho()
252
253 allocate(mom(1))
254 mom(:) = var_set_momentum(1)
255
256 ! Set index of energy variable
257 if(ffhd_energy) then
258 e_ = var_set_energy() ! energy density
259 p_ = e_ ! gas pressure
260 else
261 e_ = -1
262 p_ = -1
263 end if
264
265 if(ffhd_hyperbolic_tc) then
266 q_ = var_set_fluxvar('q', 'q', need_bc=.false.)
267 need_global_cmax=.true.
268 else
269 q_=-1
270 end if
271
272 !> LTE stores Ne_/Te_ as advection-free extra vars (repopulated each step by
273 !> eos%update_eos); PI keeps Te_ as an auxiliary var for the ionisation
274 !> degree. Mirrors mhd: register here (before stop_indices) so FI leaves
275 !> nwaux=0 and the var layout byte-identical.
276 if (eos%eos_type == 'LTE') then
277 ne_ = var_set_ne()
278 te_ = var_set_te()
279 else if (eos%eos_type == 'PI') then ! PI stores Te via var_set_te (sets iw_te) so the generic mod_eos_pi getters address it like LTE
280 ne_ = -1
281 te_ = var_set_te()
282 else
283 ne_ = -1
284 te_ = -1
285 end if
286
287 ! set number of variables which need update ghostcells
288 ! set number of variables which need update ghostcells.
289 ! The EoS-derived slots Ne/Te are derived state that must stay consistent with (rho,e)
290 ! wherever the conserved state is valid, so they have to travel with it. var_set_ne /
291 ! var_set_te bump nw but neither nwflux nor nwaux, so the historic nwflux+nwaux silently
292 ! excluded them: they were never communicated, only derived, and every ghost cell held
293 ! zero until something derived it. Extend the window to whichever of them exist (they are
294 ! registered contiguously just above); FI leaves both at -1 and the window is unchanged.
295 ! bc_phys is unaffected -- it iterates nwflux+nwaux independently.
296 nwgc=nwflux+nwaux
297 if (iw_ne > 0) nwgc = max(nwgc, iw_ne)
298 if (iw_te > 0) nwgc = max(nwgc, iw_te)
299
300 ! set the index of the last flux variable for species 1
301 stop_indices(1)=nwflux
302
303 ! set cutoff temperature when using the TRAC method, as well as an auxiliary weight
304 tweight_ = -1
305 if(ffhd_trac) then
306 tcoff_ = var_set_wextra()
307 iw_tcoff=tcoff_
308 if(ffhd_trac_type .ge. 3) then
309 tweight_ = var_set_wextra()
310 iw_tweight=tweight_
311 end if
312 else
313 tcoff_ = -1
314 end if
315
316 nvector = 0 ! No. vector vars
317
318 ! Check whether custom flux types have been defined
319 if(.not. allocated(flux_type)) then
320 allocate(flux_type(ndir, nwflux))
321 flux_type = flux_default
322 else if(any(shape(flux_type) /= [ndir, nwflux])) then
323 call mpistop("phys_check error: flux_type has wrong shape")
324 end if
325
326 phys_get_dt => ffhd_get_dt
327 phys_get_cmax => ffhd_get_cmax_origin
328 phys_get_tcutoff => ffhd_get_tcutoff
329 phys_get_cbounds => ffhd_get_cbounds
330 phys_to_primitive => ffhd_to_primitive_origin
332 phys_to_conserved => ffhd_to_conserved_origin
334 phys_get_flux => ffhd_get_flux
335 phys_get_v => ffhd_get_v_origin
336 ffhd_get_v => ffhd_get_v_origin
337 phys_get_rho => ffhd_get_rho
338 ffhd_kin_en => ffhd_kin_en_origin
339 phys_add_source_geom => ffhd_add_source_geom
340 phys_add_source => ffhd_add_source
341 phys_check_params => ffhd_check_params
342 phys_write_info => ffhd_write_info
343 phys_handle_small_values => ffhd_handle_small_values_origin
344 ffhd_handle_small_values => ffhd_handle_small_values_origin
345 phys_check_w => ffhd_check_w_origin
346
347 if(.not.ffhd_energy) then
348 phys_get_pthermal => ffhd_get_pthermal_iso
349 ffhd_get_pthermal => ffhd_get_pthermal_iso
350 else
351 phys_get_pthermal => ffhd_get_pthermal_origin
353 end if
354
355 ! Rfactor / temperature getter dispatch now lives in ffhd_link_eos (per eos_type)
356
357 ! derive units from basic units
358 call ffhd_physical_units()
359
360 if(ffhd_hyperbolic_tc) then
361 if(si_unit)then
362 ! parallel conduction Spitzer
364 else
365 ! in cgs
367 endif
368 end if
369 if(.not. ffhd_energy .and. ffhd_thermal_conduction) then
370 call mpistop("thermal conduction needs ffhd_energy=T")
371 end if
372 if(.not. ffhd_energy .and. ffhd_hyperbolic_tc) then
373 call mpistop("hyperbolic thermal conduction needs ffhd_energy=T")
374 end if
375 if(.not. ffhd_energy .and. ffhd_radiative_cooling) then
376 call mpistop("radiative cooling needs ffhd_energy=T")
377 end if
378
379 ! initialize thermal conduction module
381 call sts_init()
382 call tc_init_params(eos%gamma)
383
384 allocate(tc_fl)
385 call tc_get_hd_params(tc_fl,tc_params_read_ffhd)
386 call add_sts_method(ffhd_get_tc_dt_ffhd,ffhd_sts_set_source_tc_ffhd,e_,1,e_,1,.false.)
388 call set_error_handling_to_head(ffhd_tc_handle_small_e)
389 tc_fl%e_ = e_
390 tc_fl%Tcoff_ = tcoff_
391 ! get_temperature_*/get_rho/get_ne_nH/get_var_Rfactor/scalars wired in ffhd_bind_eos_to_source
392 end if
393
394 ! Initialize radiative cooling module
396 call radiative_cooling_init_params(eos%gamma,eos%He_abundance)
397 allocate(rc_fl)
398 call radiative_cooling_init(rc_fl,rc_params_read)
399 rc_fl%e_ = e_
400 rc_fl%Tcoff_ = tcoff_
401 rc_fl%subtract_equi = .false.
402 ! get_rho/get_pthermal/get_var_Rfactor/get_Te/get_ne_nH + EoS scalars/kernels
403 ! wired in ffhd_bind_eos_to_source
404 end if
405
406{^ifthreed
407 allocate(te_fl_ffhd)
408 phys_te_images => ffhd_te_images
409 ! te_fl_ffhd%get_rho/get_pthermal/get_var_Rfactor/get_ne_nH wired in ffhd_bind_eos_to_source
410}
411
412 ! Initialize gravity module
413 if(ffhd_gravity) then
414 call gravity_init()
415 end if
416
417 ! The PI ionisation backend (both ionE modes) is initialised centrally in
418 ! eos_finalise_PI (mod_eos_pi) -- mirrors hd/mhd, which no longer call
419 ! ionization_degree_init from the phys module (one source of truth; calling
420 ! it here too triggers "ionization_degree_init called more than once").
421 end subroutine ffhd_phys_init
422
423{^ifthreed
424 subroutine ffhd_te_images
427
428 select case(convert_type)
429 case('EIvtiCCmpi','EIvtuCCmpi')
431 case('ESvtiCCmpi','ESvtuCCmpi')
433 case('SIvtiCCmpi','SIvtuCCmpi')
435 case('WIvtiCCmpi','WIvtuCCmpi')
437 case default
438 call mpistop("Error in synthesize emission: Unknown convert_type")
439 end select
440 end subroutine ffhd_te_images
441}
442
443 subroutine ffhd_sts_set_source_tc_ffhd(ixI^L,ixO^L,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux)
447 integer, intent(in) :: ixi^l, ixo^l, igrid, nflux
448 double precision, intent(in) :: x(ixi^s,1:ndim)
449 double precision, intent(inout) :: wres(ixi^s,1:nw), w(ixi^s,1:nw)
450 double precision, intent(in) :: my_dt
451 logical, intent(in) :: fix_conserve_at_step
452 call sts_set_source_tc_mhd(ixi^l,ixo^l,w,x,wres,fix_conserve_at_step,my_dt,igrid,nflux,tc_fl)
453 end subroutine ffhd_sts_set_source_tc_ffhd
454
455 function ffhd_get_tc_dt_ffhd(w,ixI^L,ixO^L,dx^D,x) result(dtnew)
456 !Check diffusion time limit dt < dx_i**2/((gamma-1)*tc_k_para_i/rho)
457 !where tc_k_para_i=tc_k_para*B_i**2/B**2
458 !and T=p/rho
461
462 integer, intent(in) :: ixi^l, ixo^l
463 double precision, intent(in) :: dx^d, x(ixi^s,1:ndim)
464 double precision, intent(in) :: w(ixi^s,1:nw)
465 double precision :: dtnew
466
467 dtnew=get_tc_dt_mhd(w,ixi^l,ixo^l,dx^d,x,tc_fl)
468 end function ffhd_get_tc_dt_ffhd
469
470 subroutine ffhd_tc_handle_small_e(w, x, ixI^L, ixO^L, step)
472
473 integer, intent(in) :: ixi^l,ixo^l
474 double precision, intent(inout) :: w(ixi^s,1:nw)
475 double precision, intent(in) :: x(ixi^s,1:ndim)
476 integer, intent(in) :: step
477 character(len=140) :: error_msg
478
479 write(error_msg,"(a,i3)") "Thermal conduction step ", step
480 call ffhd_handle_small_ei(w,x,ixi^l,ixo^l,e_,error_msg)
481 end subroutine ffhd_tc_handle_small_e
482
483 subroutine tc_params_read_ffhd(fl)
485 type(tc_fluid), intent(inout) :: fl
486 integer :: n
487 ! list parameters
488 logical :: tc_saturate=.false., tc_frozen_ion=.true.
489 double precision :: tc_k_para=0d0
490 character(len=std_len) :: tc_slope_limiter="MC"
491
492 namelist /tc_list/ tc_saturate, tc_slope_limiter, tc_k_para, tc_frozen_ion
493
494 do n = 1, size(par_files)
495 open(unitpar, file=trim(par_files(n)), status="old")
496 read(unitpar, tc_list, end=111)
497111 close(unitpar)
498 end do
499
500 fl%tc_saturate = tc_saturate
501 fl%frozen_ion = tc_frozen_ion
502 fl%tc_k_para = tc_k_para
503 select case(tc_slope_limiter)
504 case ('no','none')
505 fl%tc_slope_limiter = 0
506 case ('MC')
507 ! montonized central limiter Woodward and Collela limiter (eq.3.51h), a factor of 2 is pulled out
508 fl%tc_slope_limiter = 1
509 case('minmod')
510 ! minmod limiter
511 fl%tc_slope_limiter = 2
512 case ('superbee')
513 ! Roes superbee limiter (eq.3.51i)
514 fl%tc_slope_limiter = 3
515 case ('koren')
516 ! Barry Koren Right variant
517 fl%tc_slope_limiter = 4
518 case default
519 call mpistop("Unknown tc_slope_limiter, choose MC, minmod")
520 end select
521 end subroutine tc_params_read_ffhd
522
523 subroutine rc_params_read(fl)
525 use mod_constants, only: bigdouble
526 type(rc_fluid), intent(inout) :: fl
527 integer :: n
528 integer :: ncool = 4000
529
530 !> Name of cooling curve
531 character(len=std_len) :: coolcurve='JCcorona'
532
533 !> Fixed temperature not lower than tlow
534 logical :: tfix=.false.
535
536 !> Lower limit of temperature
537 double precision :: tlow=bigdouble
538
539 !> Add cooling source in a split way (.true.) or un-split way (.false.)
540 logical :: rc_split=.false.
541 logical :: rad_damp=.false.
542 double precision :: rad_damp_height=0.5d0
543 double precision :: rad_damp_scale=0.15d0
544
545 namelist /rc_list/ coolcurve, ncool, tlow, tfix, rc_split, rad_damp, rad_damp_height, rad_damp_scale
546
547 do n = 1, size(par_files)
548 open(unitpar, file=trim(par_files(n)), status="old")
549 read(unitpar, rc_list, end=111)
550111 close(unitpar)
551 end do
552
553 fl%ncool=ncool
554 fl%coolcurve=coolcurve
555 fl%tlow=tlow
556 fl%Tfix=tfix
557 fl%rc_split=rc_split
558 fl%rad_damp=rad_damp
559 fl%rad_damp_height=rad_damp_height
560 fl%rad_damp_scale=rad_damp_scale
561 end subroutine rc_params_read
562
563 subroutine ffhd_check_params
567 use mod_geometry, only: coordinate
568
569
570 if (.not. ffhd_energy) then
571 if (eos%gamma <= 0.0d0) call mpistop ("Error: eos%gamma <= 0")
572 if (ffhd_adiab < 0.0d0) call mpistop ("Error: ffhd_adiab < 0")
574 else
575 if (eos%gamma <= 0.0d0 .or. eos%gamma == 1.0d0) &
576 call mpistop ("Error: eos%gamma <= 0 or eos%gamma == 1")
577 small_e = small_pressure * eos%inv_gamma_minus_1
578 end if
579
580 if (number_equi_vars > 0 .and. .not. associated(usr_set_equi_vars)) then
581 call mpistop("usr_set_equi_vars has to be implemented in the user file")
582 end if
583
584
585 if(mype==0)then
586 write(*,*)'====FFHD run with settings===================='
587 write(*,*)'Using mod_ffhd_phys with settings:'
588 write(*,*)'SI_unit=',si_unit
589 write(*,*)'Dimensionality :',ndim
590 write(*,*)'vector components:',ndir
591 write(*,*)'coordinate set to type,slab:',coordinate,slab
592 write(*,*)'number of variables nw=',nw
593 write(*,*)' start index iwstart=',iwstart
594 write(*,*)'number of vector variables=',nvector
595 write(*,*)'number of stagger variables nws=',nws
596 write(*,*)'number of variables with BCs=',nwgc
597 write(*,*)'number of vars with fluxes=',nwflux
598 write(*,*)'number of vars with flux + BC=',nwfluxbc
599 write(*,*)'number of auxiliary variables=',nwaux
600 write(*,*)'number of extra vars without flux=',nwextra
601 write(*,*)'number of extra vars for wextra=',nw_extra
602 write(*,*)'number of auxiliary I/O variables=',nwauxio
603 write(*,*)' ffhd_energy=',ffhd_energy
604 write(*,*)' ffhd_gravity=',ffhd_gravity
605 write(*,*)' ffhd_radiative_cooling=',ffhd_radiative_cooling
606 write(*,*)' ffhd_hyperbolic_tc=',ffhd_hyperbolic_tc
607 write(*,*)' ffhd_trac=',ffhd_trac
608 write(*,*)'number of ghostcells=',nghostcells
609 write(*,*)'number due to phys_wider_stencil=',phys_wider_stencil
610 write(*,*)'==========================================='
611 endif
612 end subroutine ffhd_check_params
613
614 subroutine ffhd_physical_units()
616 double precision :: mp,kb
617 double precision :: a,b
618
619 if(si_unit) then
620 mp=mp_si
621 kb=kb_si
622 else
623 mp=mp_cgs
624 kb=kb_cgs
625 end if
626
627 ! Normalisation dispatch keyed solely on eos%eos_type (FI is the default, so
628 ! legacy parfiles that set neither eos_type nor any flag land in the FI/PI
629 ! absorbed-(a,b), RR=1 branch -- the historical eq_state_units=.true. result).
630 if (eos%eos_type == 'LTE') then
631 !> Remove the assumed FI normalisation from the units; handle in EoS.
632 a=1d0
633 b=1d0
634 eos%nH2rhoFactor = 1d0+4d0*eos%He_abundance
635 rr=(2d0+3d0*eos%He_abundance)/(1d0+4d0*eos%He_abundance)
636 else
637 !> FI / PI: absorbed-(a,b), RR=1. The (1+4He) factor is absorbed into
638 !> unit_density, so nH2rhoFactor stays at the eos_init default of 1 (else
639 !> get_ne_nH would double-divide rho and under-cool by (1+4He)^2).
640 a=1d0+4d0*eos%He_abundance
641 if(eos%eos_type=='PI') then
642 b=1d0+h_ion_fr+eos%He_abundance*(he_ion_fr*(he_ion_fr2+1d0)+1d0)
643 else
644 b=2d0+3d0*eos%He_abundance
645 end if
646 rr=1d0
647 end if
648 if(unit_density/=1.d0 .or. unit_numberdensity/=1.d0) then
649 if(unit_density/=1.d0) then
651 else if(unit_numberdensity/=1.d0) then
653 end if
654 if(unit_temperature/=1.d0) then
657 if(unit_length/=1.d0) then
659 else if(unit_time/=1.d0) then
661 end if
662 else if(unit_pressure/=1.d0) then
665 if(unit_length/=1.d0) then
667 else if(unit_time/=1.d0) then
669 end if
670 else if(unit_velocity/=1.d0) then
673 if(unit_length/=1.d0) then
675 else if(unit_time/=1.d0) then
677 end if
678 else if(unit_time/=1.d0) then
682 end if
683 else if(unit_temperature/=1.d0) then
684 ! units of temperature and velocity are dependent
685 if(unit_pressure/=1.d0) then
689 if(unit_length/=1.d0) then
691 else if(unit_time/=1.d0) then
693 end if
694 end if
695 else if(unit_pressure/=1.d0) then
696 if(unit_velocity/=1.d0) then
700 if(unit_length/=1.d0) then
702 else if(unit_time/=1.d0) then
704 end if
705 else if(unit_time/=0.d0) then
710 end if
711 end if
713 end subroutine ffhd_physical_units
714
715 subroutine ffhd_check_w_origin(primitive,ixI^L,ixO^L,w,flag)
717 logical, intent(in) :: primitive
718 integer, intent(in) :: ixi^l, ixo^l
719 double precision, intent(in) :: w(ixi^s,nw)
720 double precision :: tmp(ixi^s)
721 logical, intent(inout) :: flag(ixi^s,1:nw)
722
723 flag=.false.
724 where(w(ixo^s,rho_) < small_density) flag(ixo^s,rho_) = .true.
725
726 if(ffhd_energy) then
727 if(primitive) then
728 where(w(ixo^s,e_) < small_pressure) flag(ixo^s,e_) = .true.
729 else
730 tmp(ixo^s)=w(ixo^s,e_)-ffhd_kin_en(w,ixi^l,ixo^l)
731 where(tmp(ixo^s) < small_e) flag(ixo^s,e_) = .true.
732 end if
733 end if
734 end subroutine ffhd_check_w_origin
735
736 subroutine ffhd_to_conserved_origin(ixI^L,ixO^L,w,x)
738 integer, intent(in) :: ixi^l, ixo^l
739 double precision, intent(inout) :: w(ixi^s, nw)
740 double precision, intent(in) :: x(ixi^s, 1:ndim)
741
742 if(ffhd_energy) then
743 w(ixo^s,e_)=w(ixo^s,p_)*eos%inv_gamma_minus_1+half*w(ixo^s,mom(1))**2*w(ixo^s,rho_)
744 end if
745 w(ixo^s,mom(1))=w(ixo^s,rho_)*w(ixo^s,mom(1))
746 end subroutine ffhd_to_conserved_origin
747
748 subroutine ffhd_to_primitive_origin(ixI^L,ixO^L,w,x)
750 integer, intent(in) :: ixi^l, ixo^l
751 double precision, intent(inout) :: w(ixi^s, nw)
752 double precision, intent(in) :: x(ixi^s, 1:ndim)
753
754 if(fix_small_values) then
755 call ffhd_handle_small_values(.false., w, x, ixi^l, ixo^l, 'ffhd_to_primitive_origin')
756 end if
757
758 w(ixo^s,mom(1)) = w(ixo^s,mom(1))/w(ixo^s,rho_)
759 if(ffhd_energy) then
760 w(ixo^s,p_)=eos%gamma_minus_1*(w(ixo^s,e_)-half*w(ixo^s,rho_)*w(ixo^s,mom(1))**2)
761 end if
762 end subroutine ffhd_to_primitive_origin
763
764 subroutine ffhd_ei_to_e(ixI^L,ixO^L,w,x)
766 integer, intent(in) :: ixi^l, ixo^l
767 double precision, intent(inout) :: w(ixi^s, nw)
768 double precision, intent(in) :: x(ixi^s, 1:ndim)
769
770 w(ixo^s,e_)=w(ixo^s,e_)+ffhd_kin_en(w,ixi^l,ixo^l)
771 end subroutine ffhd_ei_to_e
772
773 subroutine ffhd_e_to_ei(ixI^L,ixO^L,w,x)
775 integer, intent(in) :: ixi^l, ixo^l
776 double precision, intent(inout) :: w(ixi^s, nw)
777 double precision, intent(in) :: x(ixi^s, 1:ndim)
778
779 ! Restrict to ixO^L (mirrors hd/mhd): update_eos_LTE calls phys_e_to_ei
780 ! over the mesh interior while ixI^S still spans unfilled corner ghosts
781 ! (rho=0 -> SIGFPE in ffhd_kin_en). FI is unaffected (update_eos_FI no-op;
782 ! the TC STS heads pass the range they need).
783 w(ixo^s,e_)=w(ixo^s,e_)-ffhd_kin_en(w,ixi^l,ixo^l)
784 if(fix_small_values) then
785 call ffhd_handle_small_ei(w,x,ixi^l,ixo^l,e_,'ffhd_e_to_ei')
786 end if
787 end subroutine ffhd_e_to_ei
788
789 !> Internal energy eint = E_total - E_kinetic (single field-aligned momentum).
790 !> Wired to phys_get_ei; the LTE+ionE radiative cooling uses it to recover the
791 !> gas internal energy from the conserved state.
792 function ffhd_get_ei(w, ixI^L, ixO^L) result(ei)
794 integer, intent(in) :: ixi^l, ixo^l
795 double precision, intent(in) :: w(ixi^s, nw)
796 double precision :: ei(ixo^s)
797
798 ei(ixo^s) = w(ixo^s,e_) - ffhd_kin_en(w,ixi^l,ixo^l)
799 end function ffhd_get_ei
800
801 subroutine ffhd_handle_small_values_origin(primitive, w, x, ixI^L, ixO^L, subname)
804 logical, intent(in) :: primitive
805 integer, intent(in) :: ixi^l,ixo^l
806 double precision, intent(inout) :: w(ixi^s,1:nw)
807 double precision, intent(in) :: x(ixi^s,1:ndim)
808 character(len=*), intent(in) :: subname
809
810 logical :: flag(ixi^s,1:nw)
811 double precision :: tmp2(ixi^s)
812
813 call phys_check_w(primitive, ixi^l, ixi^l, w, flag)
814
815 if(any(flag)) then
816 select case (small_values_method)
817 case ("replace")
818 where(flag(ixo^s,rho_)) w(ixo^s,rho_) = small_density
819 if(small_values_fix_iw(mom(1))) then
820 where(flag(ixo^s,rho_)) w(ixo^s, mom(1)) = 0.0d0
821 end if
822 if(ffhd_energy) then
823 if(primitive) then
824 where(flag(ixo^s,e_)) w(ixo^s,p_) = small_pressure
825 else
826 where(flag(ixo^s,e_))
827 w(ixo^s,e_) = small_e+ffhd_kin_en(w,ixi^l,ixo^l)
828 end where
829 end if
830 end if
831 case ("average")
832 call small_values_average(ixi^l, ixo^l, w, x, flag, rho_)
833 if(ffhd_energy) then
834 if(primitive) then
835 call small_values_average(ixi^l, ixo^l, w, x, flag, p_)
836 else
837 w(ixi^s,e_)=w(ixi^s,e_)-ffhd_kin_en(w,ixi^l,ixi^l)
838 call small_values_average(ixi^l, ixo^l, w, x, flag, e_)
839 w(ixi^s,e_)=w(ixi^s,e_)+ffhd_kin_en(w,ixi^l,ixi^l)
840 end if
841 end if
842 case default
843 if(.not.primitive) then
844 if(ffhd_energy) then
845 w(ixo^s,p_)=eos%gamma_minus_1*(w(ixo^s,e_)-ffhd_kin_en(w,ixi^l,ixo^l))
846 end if
847 w(ixo^s,mom(1))=w(ixo^s,mom(1))/w(ixo^s,rho_)
848 end if
849 call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
850 end select
851 end if
852 end subroutine ffhd_handle_small_values_origin
853
854 subroutine ffhd_get_v_origin(w,x,ixI^L,ixO^L,v)
856 integer, intent(in) :: ixi^l, ixo^l
857 double precision, intent(in) :: w(ixi^s,nw), x(ixi^s,1:ndim)
858 double precision, intent(out) :: v(ixi^s,ndir)
859 double precision :: rho(ixi^s)
860 integer :: idir
861
862 call ffhd_get_rho(w,x,ixi^l,ixo^l,rho)
863 rho(ixo^s)=1.d0/rho(ixo^s)
864 do idir=1,ndir
865 v(ixo^s,ndir) = w(ixo^s,mom(1))*block%B0(ixo^s,idir,0)*rho(ixo^s)
866 end do
867 end subroutine ffhd_get_v_origin
868
869 subroutine ffhd_get_v_idim(w,x,ixI^L,ixO^L,idim,v)
871 integer, intent(in) :: ixi^l, ixo^l, idim
872 double precision, intent(in) :: w(ixi^s,nw), x(ixi^s,1:ndim)
873 double precision, intent(out) :: v(ixi^s)
874 double precision :: rho(ixi^s)
875
876 call ffhd_get_rho(w,x,ixi^l,ixo^l,rho)
877 v(ixo^s) = (w(ixo^s, mom(1))*block%B0(ixo^s,idim,0)) / rho(ixo^s)
878 end subroutine ffhd_get_v_idim
879
880 subroutine ffhd_get_cmax_origin(wprim,x,ixI^L,ixO^L,idim,cmax)
882 integer, intent(in) :: ixi^l, ixo^l, idim
883 ! w in primitive form
884 double precision, intent(in) :: wprim(ixi^s, nw), x(ixi^s,1:ndim)
885 double precision, intent(inout) :: cmax(ixi^s)
886
887 if(ffhd_energy) then
888 if (eos%ionE) then
889 ! LTE/PI energy: Gamma_1(p,rho)*p/rho from the EoS (wprim is primitive)
890 call eos%get_csound2(wprim,x,ixi^l,ixo^l,cmax)
891 cmax(ixo^s)=dsqrt(cmax(ixo^s))
892 else
893 cmax(ixo^s)=dsqrt(eos%gamma*wprim(ixo^s,p_)/wprim(ixo^s,rho_))
894 end if
895 else
896 cmax(ixo^s)=dsqrt(eos%gamma*ffhd_adiab*wprim(ixo^s,rho_)**eos%gamma_minus_1)
897 end if
898 cmax(ixo^s)=dabs(wprim(ixo^s,mom(1))*block%B0(ixo^s,idim,0))+cmax(ixo^s)
899
900 end subroutine ffhd_get_cmax_origin
901
902 subroutine ffhd_get_tcutoff(ixI^L,ixO^L,w,x,Tco_local,Tmax_local)
904 use mod_geometry
905 integer, intent(in) :: ixi^l,ixo^l
906 double precision, intent(in) :: x(ixi^s,1:ndim)
907 double precision, intent(inout) :: w(ixi^s,1:nw)
908 double precision, intent(out) :: tco_local,tmax_local
909 double precision, parameter :: trac_delta=0.25d0
910 double precision :: te(ixi^s),lts(ixi^s)
911 double precision, dimension(ixI^S,1:ndim) :: gradt
912 double precision :: bdir(ndim)
913 double precision :: ltrc,ltrp,altr
914 integer :: idims,ix^d,jxo^l,hxo^l,ixa^d,ixb^d
915 integer :: jxp^l,hxp^l,ixp^l,ixq^l
916 logical :: lrlt(ixi^s)
917
918 call ffhd_get_temperature(w,x,ixi^l,ixi^l,te)
919 tco_local=zero
920 tmax_local=maxval(te(ixo^s))
921
922 {^ifoned
923 select case(ffhd_trac_type)
924 case(0)
925 !> test case, fixed cutoff temperature
926 block%wextra(ixi^s,tcoff_)=2.5d5/unit_temperature
927 case(1)
928 hxo^l=ixo^l-1;
929 jxo^l=ixo^l+1;
930 lts(ixo^s)=0.5d0*dabs(te(jxo^s)-te(hxo^s))/te(ixo^s)
931 lrlt=.false.
932 where(lts(ixo^s) > trac_delta)
933 lrlt(ixo^s)=.true.
934 end where
935 if(any(lrlt(ixo^s))) then
936 tco_local=maxval(te(ixo^s), mask=lrlt(ixo^s))
937 end if
938 case(2)
939 !> iijima et al. 2021, LTRAC method
940 ltrc=1.5d0
941 ltrp=4.d0
942 ixp^l=ixo^l^ladd1;
943 hxo^l=ixo^l-1;
944 jxo^l=ixo^l+1;
945 hxp^l=ixp^l-1;
946 jxp^l=ixp^l+1;
947 lts(ixp^s)=0.5d0*dabs(te(jxp^s)-te(hxp^s))/te(ixp^s)
948 lts(ixp^s)=max(one, (exp(lts(ixp^s))/ltrc)**ltrp)
949 lts(ixo^s)=0.25d0*(lts(jxo^s)+two*lts(ixo^s)+lts(hxo^s))
950 block%wextra(ixo^s,tcoff_)=te(ixo^s)*lts(ixo^s)**0.4d0
951 case default
952 call mpistop("ffhd_trac_type not allowed for 1D simulation")
953 end select
954 }
955 {^nooned
956 select case(ffhd_trac_type)
957 case(0)
958 !> test case, fixed cutoff temperature
959 if(slab_uniform) then
960 !> assume cgs units
961 block%wextra(ixi^s,tcoff_)=max(min(3.d5/unit_temperature,6.d5/unit_temperature-3.d-4/unit_temperature*unit_length*x(ixi^s,ndim)),zero)
962 else
963 block%wextra(ixi^s,tcoff_)=2.5d5/unit_temperature
964 end if
965 case(1,4,6)
966 do idims=1,ndim
967 call gradient(te,ixi^l,ixo^l,idims,gradt(ixi^s,idims))
968 end do
969 if(ffhd_trac_type .gt. 1) then
970 ! B direction at cell center
971 bdir=zero
972 {do ixa^d=0,1\}
973 ixb^d=(ixomin^d+ixomax^d-1)/2+ixa^d;
974 bdir(1:ndim)=bdir(1:ndim)+block%B0(ixb^d,1:ndim,0)
975 {end do\}
976 if(sum(bdir(:)**2) .gt. zero) then
977 bdir(1:ndim)=bdir(1:ndim)/dsqrt(sum(bdir(:)**2))
978 end if
979 block%special_values(3:ndim+2)=bdir(1:ndim)
980 end if
981 {do ix^db=ixomin^db,ixomax^db\}
982 {^iftwod
983 ! temperature length scale inversed
984 lts(ix^d)=min(block%ds(ix^d,1),block%ds(ix^d,2))*&
985 abs(^d&gradt({ix^d},^d)*block%B0({ix^d},^d,0)+)/te(ix^d)
986 }
987 {^ifthreed
988 ! temperature length scale inversed
989 lts(ix^d)=min(block%ds(ix^d,1),block%ds(ix^d,2),block%ds(ix^d,3))*&
990 abs(^d&gradt({ix^d},^d)*block%B0({ix^d},^d,0)+)/te(ix^d)
991 }
992 if(lts(ix^d)>trac_delta) then
993 block%special_values(1)=max(block%special_values(1),te(ix^d))
994 end if
995 {end do\}
996 block%special_values(2)=tmax_local
997 case(2)
998 !> iijima et al. 2021, LTRAC method
999 ltrc=1.5d0
1000 ltrp=4.d0
1001 ixp^l=ixo^l^ladd2;
1002 do idims=1,ndim
1003 ixq^l=ixp^l;
1004 hxp^l=ixp^l;
1005 jxp^l=ixp^l;
1006 select case(idims)
1007 {case(^d)
1008 ixqmin^d=ixqmin^d+1
1009 ixqmax^d=ixqmax^d-1
1010 hxpmax^d=ixpmin^d
1011 jxpmin^d=ixpmax^d
1012 \}
1013 end select
1014 call gradient(te,ixi^l,ixq^l,idims,gradt(ixi^s,idims))
1015 call gradientf(te,x,ixi^l,hxp^l,idims,gradt(ixi^s,idims),nghostcells,.true.)
1016 call gradientf(te,x,ixi^l,jxp^l,idims,gradt(ixi^s,idims),nghostcells,.false.)
1017 end do
1018 {do ix^db=ixpmin^db,ixpmax^db\}
1019 ! temperature length scale inversed
1020 lts(ix^d)=abs(^d&gradt({ix^d},^d)*block%B0({ix^d},^d,0)+)/te(ix^d)
1021 ! fraction of cells size to temperature length scale
1022 lts(ix^d)=min(^d&block%ds({ix^d},^d))*lts(ix^d)
1023 lts(ix^d)=max(one,(exp(lts(ix^d))/ltrc)**ltrp)
1024 {end do\}
1025
1026 ! need one ghost layer for thermal conductivity
1027 ixp^l=ixo^l^ladd1;
1028 {do ix^db=ixpmin^db,ixpmax^db\}
1029 {^iftwod
1030 altr=0.25d0*((lts(ix1-1,ix2)+two*lts(ix^d)+lts(ix1+1,ix2))*block%B0(ix^d,1,0)**2+&
1031 (lts(ix1,ix2-1)+two*lts(ix^d)+lts(ix1,ix2+1))*block%B0(ix^d,2,0)**2)
1032 block%wextra(ix^d,tcoff_)=te(ix^d)*altr**0.4d0
1033 }
1034 {^ifthreed
1035 altr=0.25d0*((lts(ix1-1,ix2,ix3)+two*lts(ix^d)+lts(ix1+1,ix2,ix3))*block%B0(ix^d,1,0)**2+&
1036 (lts(ix1,ix2-1,ix3)+two*lts(ix^d)+lts(ix1,ix2+1,ix3))*block%B0(ix^d,2,0)**2+&
1037 (lts(ix1,ix2,ix3-1)+two*lts(ix^d)+lts(ix1,ix2,ix3+1))*block%B0(ix^d,3,0)**2)
1038 block%wextra(ix^d,tcoff_)=te(ix^d)*altr**0.4d0
1039 }
1040 {end do\}
1041 case(3,5)
1042 !> do nothing here
1043 case default
1044 call mpistop("unknown ffhd_trac_type")
1045 end select
1046 }
1047 end subroutine ffhd_get_tcutoff
1048
1049 subroutine ffhd_get_cbounds(wLC,wRC,wLp,wRp,x,ixI^L,ixO^L,idim,Hspeed,cmax,cmin)
1051 integer, intent(in) :: ixi^l, ixo^l, idim
1052 double precision, intent(in) :: wlc(ixi^s, nw), wrc(ixi^s, nw)
1053 double precision, intent(in) :: wlp(ixi^s, nw), wrp(ixi^s, nw)
1054 double precision, intent(in) :: x(ixi^s,1:ndim)
1055 double precision, intent(inout) :: cmax(ixi^s,1:number_species)
1056 double precision, intent(inout), optional :: cmin(ixi^s,1:number_species)
1057 double precision, intent(in) :: hspeed(ixi^s,1:number_species)
1058 double precision :: wmean(ixi^s,nw), wmeanp(ixi^s,nw)
1059 double precision, dimension(ixI^S) :: umean, dmean, csoundl, csoundr, tmp1,tmp2,tmp3
1060
1061 select case (boundspeed)
1062 case (1)
1063 ! This implements formula (10.52) from "Riemann Solvers and Numerical
1064 ! Methods for Fluid Dynamics" by Toro.
1065 tmp1(ixo^s)=dsqrt(wlp(ixo^s,rho_))
1066 tmp2(ixo^s)=dsqrt(wrp(ixo^s,rho_))
1067 tmp3(ixo^s)=1.d0/(tmp1(ixo^s)+tmp2(ixo^s))
1068 umean(ixo^s)=(wlp(ixo^s,mom(1))*tmp1(ixo^s)&
1069 +wrp(ixo^s,mom(1))*tmp2(ixo^s))*tmp3(ixo^s)
1070 umean(ixo^s)=umean(ixo^s)*block%B0(ixo^s,idim,idim)
1071 call ffhd_csound2_cbounds(wlc,wlp,x,ixi^l,ixo^l,csoundl)
1072 call ffhd_csound2_cbounds(wrc,wrp,x,ixi^l,ixo^l,csoundr)
1073 dmean(ixo^s)=(tmp1(ixo^s)*csoundl(ixo^s)+tmp2(ixo^s)*csoundr(ixo^s)) * &
1074 tmp3(ixo^s) + 0.5d0*tmp1(ixo^s)*tmp2(ixo^s)*tmp3(ixo^s)**2 * &
1075 ((wrp(ixo^s,mom(1))-wlp(ixo^s,mom(1)))*block%B0(ixo^s,idim,idim))**2
1076 dmean(ixo^s)=dsqrt(dmean(ixo^s))
1077 if(present(cmin)) then
1078 cmin(ixo^s,1)=umean(ixo^s)-dmean(ixo^s)
1079 cmax(ixo^s,1)=umean(ixo^s)+dmean(ixo^s)
1080 else
1081 cmax(ixo^s,1)=dabs(umean(ixo^s))+dmean(ixo^s)
1082 end if
1083 case (2)
1084 wmean(ixo^s,1:nwflux)=0.5d0*(wlc(ixo^s,1:nwflux)+wrc(ixo^s,1:nwflux))
1085 tmp1(ixo^s)=wmean(ixo^s,mom(1))*block%B0(ixo^s,idim,idim)/wmean(ixo^s,rho_)
1086 if (eos%ionE) then
1087 wmeanp(ixo^s,1:nwflux)=0.5d0*(wlp(ixo^s,1:nwflux)+wrp(ixo^s,1:nwflux))
1088 call eos%get_csound2(wmeanp,x,ixi^l,ixo^l,csoundr)
1089 else
1090 call ffhd_get_csound2(wmean,x,ixi^l,ixo^l,csoundr)
1091 end if
1092 csoundr(ixo^s) = dsqrt(csoundr(ixo^s))
1093 if(present(cmin)) then
1094 cmax(ixo^s,1)=max(tmp1(ixo^s)+csoundr(ixo^s),zero)
1095 cmin(ixo^s,1)=min(tmp1(ixo^s)-csoundr(ixo^s),zero)
1096 else
1097 cmax(ixo^s,1)=dabs(tmp1(ixo^s))+csoundr(ixo^s)
1098 end if
1099 case (3)
1100 ! Miyoshi 2005 JCP 208, 315 equation (67)
1101 call ffhd_csound2_cbounds(wlc,wlp,x,ixi^l,ixo^l,csoundl)
1102 call ffhd_csound2_cbounds(wrc,wrp,x,ixi^l,ixo^l,csoundr)
1103 csoundl(ixo^s)=max(dsqrt(csoundl(ixo^s)),dsqrt(csoundr(ixo^s)))
1104 if(present(cmin)) then
1105 cmin(ixo^s,1)=min(wlp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim),&
1106 wrp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim))-csoundl(ixo^s)
1107 cmax(ixo^s,1)=max(wlp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim),&
1108 wrp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim))+csoundl(ixo^s)
1109 else
1110 cmax(ixo^s,1)=max(wlp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim),&
1111 wrp(ixo^s,mom(1))*block%B0(ixo^s,idim,idim))+csoundl(ixo^s)
1112 end if
1113 end select
1114 end subroutine ffhd_get_cbounds
1115
1116 !> Sound speed^2 at a Riemann interface. FI uses the conserved-state pthermal
1117 !> path (bit-identical to the legacy ffhd_get_csound2(wC) call); LTE uses the
1118 !> primitive Gamma_1*p/rho via eos% because the stored Te_/Ne_ are NOT
1119 !> reconstructed onto interface states (they are advection-free extra vars).
1120 subroutine ffhd_csound2_cbounds(wC,wp,x,ixI^L,ixO^L,cs2)
1122 integer, intent(in) :: ixi^l, ixo^l
1123 double precision, intent(in) :: wc(ixi^s,nw), wp(ixi^s,nw), x(ixi^s,1:ndim)
1124 double precision, intent(out):: cs2(ixi^s)
1125
1126 if (eos%ionE) then
1127 call eos%get_csound2(wp,x,ixi^l,ixo^l,cs2)
1128 else
1129 call ffhd_get_csound2(wc,x,ixi^l,ixo^l,cs2)
1130 end if
1131 end subroutine ffhd_csound2_cbounds
1132
1133 subroutine ffhd_get_pthermal_iso(w,x,ixI^L,ixO^L,pth)
1135
1136 integer, intent(in) :: ixi^l, ixo^l
1137 double precision, intent(in) :: w(ixi^s,nw)
1138 double precision, intent(in) :: x(ixi^s,1:ndim)
1139 double precision, intent(out):: pth(ixi^s)
1140
1141 call ffhd_get_rho(w,x,ixi^l,ixo^l,pth)
1142 pth(ixo^s)=ffhd_adiab*pth(ixo^s)**eos%gamma
1143 end subroutine ffhd_get_pthermal_iso
1144
1145 subroutine ffhd_get_pthermal_origin(w,x,ixI^L,ixO^L,pth)
1148 integer, intent(in) :: ixi^l, ixo^l
1149 double precision, intent(in) :: w(ixi^s,nw)
1150 double precision, intent(in) :: x(ixi^s,1:ndim)
1151 double precision, intent(out):: pth(ixi^s)
1152 integer :: iw, ix^d
1153
1154 pth(ixo^s)=eos%gamma_minus_1*(w(ixo^s,e_)-ffhd_kin_en(w,ixi^l,ixo^l))
1155 if (fix_small_values) then
1156 {do ix^db= ixo^lim^db\}
1157 if(pth(ix^d)<small_pressure) then
1158 pth(ix^d)=small_pressure
1159 end if
1160 {end do^D&\}
1161 elseif(check_small_values) then
1162 {do ix^db= ixo^lim^db\}
1163 if(pth(ix^d)<small_pressure) then
1164 write(*,*) "Error: small value of gas pressure",pth(ix^d),&
1165 " encountered when call ffhd_get_pthermal"
1166 write(*,*) "Iteration: ", it, " Time: ", global_time
1167 write(*,*) "Location: ", x(ix^d,:)
1168 write(*,*) "Cell number: ", ix^d
1169 do iw=1,nw
1170 write(*,*) trim(cons_wnames(iw)),": ",w(ix^d,iw)
1171 end do
1172 ! use erroneous arithmetic operation to crash the run
1173 if(trace_small_values) write(*,*) dsqrt(pth(ix^d)-bigdouble)
1174 write(*,*) "Saving status at the previous time step"
1175 crash=.true.
1176 end if
1177 {end do^D&\}
1178 end if
1179 end subroutine ffhd_get_pthermal_origin
1180
1181 subroutine ffhd_get_temperature_from_te(w, x, ixI^L, ixO^L, res)
1183 integer, intent(in) :: ixi^l, ixo^l
1184 double precision, intent(in) :: w(ixi^s, 1:nw)
1185 double precision, intent(in) :: x(ixi^s, 1:ndim)
1186 double precision, intent(out):: res(ixi^s)
1187
1188 res(ixo^s) = w(ixo^s, te_)
1189 end subroutine ffhd_get_temperature_from_te
1190
1191 subroutine ffhd_get_temperature_from_eint(w, x, ixI^L, ixO^L, res)
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, intent(out):: res(ixi^s)
1197 double precision :: r(ixi^s)
1198
1199 call ffhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1200 res(ixo^s) = eos%gamma_minus_1 * w(ixo^s, e_)/(w(ixo^s,rho_)*r(ixo^s))
1201 end subroutine ffhd_get_temperature_from_eint
1202
1203 subroutine ffhd_get_temperature_from_etot(w, x, ixI^L, ixO^L, res)
1205 integer, intent(in) :: ixi^l, ixo^l
1206 double precision, intent(in) :: w(ixi^s, 1:nw)
1207 double precision, intent(in) :: x(ixi^s, 1:ndim)
1208 double precision, intent(out):: res(ixi^s)
1209
1210 double precision :: r(ixi^s)
1211
1212 call ffhd_get_rfactor(w,x,ixi^l,ixo^l,r)
1213 call ffhd_get_pthermal(w,x,ixi^l,ixo^l,res)
1214 res(ixo^s)=res(ixo^s)/(r(ixo^s)*w(ixo^s,rho_))
1215 end subroutine ffhd_get_temperature_from_etot
1216
1217 subroutine ffhd_get_csound2(w,x,ixI^L,ixO^L,csound2)
1219 integer, intent(in) :: ixi^l, ixo^l
1220 double precision, intent(in) :: w(ixi^s,nw)
1221 double precision, intent(in) :: x(ixi^s,1:ndim)
1222 double precision, intent(out) :: csound2(ixi^s)
1223 double precision :: rho(ixi^s)
1224
1225 call ffhd_get_rho(w,x,ixi^l,ixo^l,rho)
1226 if(ffhd_energy) then
1227 call ffhd_get_pthermal(w,x,ixi^l,ixo^l,csound2)
1228 csound2(ixo^s)=eos%gamma*csound2(ixo^s)/rho(ixo^s)
1229 else
1230 csound2(ixo^s)=eos%gamma*ffhd_adiab*rho(ixo^s)**eos%gamma_minus_1
1231 end if
1232 end subroutine ffhd_get_csound2
1233
1234 subroutine ffhd_get_flux(wC,w,x,ixI^L,ixO^L,idim,f)
1236 use mod_geometry
1237 integer, intent(in) :: ixi^l, ixo^l, idim
1238 ! conservative w
1239 double precision, intent(in) :: wc(ixi^s,nw)
1240 ! primitive w
1241 double precision, intent(in) :: w(ixi^s,nw)
1242 double precision, intent(in) :: x(ixi^s,1:ndim)
1243 double precision,intent(out) :: f(ixi^s,nwflux)
1244 double precision :: ptotal(ixo^s)
1245
1246 f(ixo^s,rho_)=w(ixo^s,mom(1))*w(ixo^s,rho_)*block%B0(ixo^s,idim,idim)
1247
1248 if(ffhd_energy) then
1249 ptotal(ixo^s)=w(ixo^s,p_)
1250 else
1251 ptotal(ixo^s)=ffhd_adiab*w(ixo^s,rho_)**eos%gamma
1252 end if
1253
1254 ! Get flux of momentum
1255 f(ixo^s,mom(1))=(wc(ixo^s,mom(1))*w(ixo^s,mom(1))+ptotal(ixo^s))*block%B0(ixo^s,idim,idim)
1256
1257 ! Get flux of energy
1258 if(ffhd_energy) then
1259 f(ixo^s,e_)=w(ixo^s,mom(1))*(wc(ixo^s,e_)+ptotal(ixo^s))*block%B0(ixo^s,idim,idim)
1260 if(ffhd_hyperbolic_tc) then
1261 f(ixo^s,e_)=f(ixo^s,e_)+w(ixo^s,q_)*block%B0(ixo^s,idim,idim)
1262 f(ixo^s,q_)=zero
1263 end if
1264 end if
1265 end subroutine ffhd_get_flux
1266
1267 subroutine ffhd_add_source(qdt,dtfactor,ixI^L,ixO^L,wCT,wCTprim,w,x,qsourcesplit,active)
1271 integer, intent(in) :: ixi^l, ixo^l
1272 double precision, intent(in) :: qdt,dtfactor
1273 double precision, intent(in) :: wct(ixi^s,1:nw),wctprim(ixi^s,1:nw), x(ixi^s,1:ndim)
1274 double precision, intent(inout) :: w(ixi^s,1:nw)
1275 logical, intent(in) :: qsourcesplit
1276 logical, intent(inout) :: active
1277
1278 if (.not. qsourcesplit) then
1279 active = .true.
1280 call add_punitb(qdt,ixi^l,ixo^l,wct,w,x,wctprim)
1281 if(ffhd_hyperbolic_tc) then
1282 call add_hyperbolic_tc_source(qdt,ixi^l,ixo^l,wct,w,x,wctprim)
1283 end if
1284 end if
1285
1286 if(ffhd_radiative_cooling) then
1287 call radiative_cooling_add_source(qdt,ixi^l,ixo^l,wct,wctprim,&
1288 w,x,qsourcesplit,active, rc_fl)
1289 end if
1290
1291 if(ffhd_gravity) then
1292 call gravity_add_source(qdt,ixi^l,ixo^l,wct,wctprim,&
1293 w,x,ffhd_energy,qsourcesplit,active)
1294 end if
1295
1296 ! update temperature from new pressure, density, and old ionization degree
1297 if(eos%eos_type == 'PI') then
1298 if(.not.qsourcesplit) then
1299 active = .true.
1300 call eos%update_eos(ixi^l,ixo^l,w,x)
1301 end if
1302 end if
1303 end subroutine ffhd_add_source
1304
1305 subroutine add_punitb(qdt,ixI^L,ixO^L,wCT,w,x,wCTprim)
1307 use mod_geometry
1308 integer, intent(in) :: ixi^l,ixo^l
1309 double precision, intent(in) :: qdt
1310 double precision, intent(in) :: wct(ixi^s,1:nw),x(ixi^s,1:ndim)
1311 double precision, intent(in) :: wctprim(ixi^s,1:nw)
1312 double precision, intent(inout) :: w(ixi^s,1:nw)
1313
1314 integer :: idims,hxo^l
1315 double precision :: divb(ixi^s)
1316 double precision :: rhovpar(ixi^s),gradrhov(ixi^s)
1317
1318 divb=zero
1319 if(slab_uniform) then
1320 do idims=1,ndim
1321 hxo^l=ixo^l-kr(idims,^d);
1322 divb(ixo^s)=divb(ixo^s)+(block%B0(ixo^s,idims,idims)-block%B0(hxo^s,idims,idims))/dxlevel(idims)
1323 end do
1324 else
1325 call divvector(block%B0(ixi^s,1:ndir,0),ixi^l,ixo^l,divb)
1326 end if
1327 w(ixo^s,mom(1))=w(ixo^s,mom(1))+qdt*wctprim(ixo^s,p_)*divb(ixo^s)
1328 end subroutine add_punitb
1329
1330 subroutine ffhd_get_rho(w,x,ixI^L,ixO^L,rho)
1332 integer, intent(in) :: ixi^l, ixo^l
1333 double precision, intent(in) :: w(ixi^s,1:nw),x(ixi^s,1:ndim)
1334 double precision, intent(out) :: rho(ixi^s)
1335
1336 rho(ixo^s) = w(ixo^s,rho_)
1337 end subroutine ffhd_get_rho
1338
1339 subroutine ffhd_handle_small_ei(w, x, ixI^L, ixO^L, ie, subname)
1342 integer, intent(in) :: ixi^l,ixo^l, ie
1343 double precision, intent(inout) :: w(ixi^s,1:nw)
1344 double precision, intent(in) :: x(ixi^s,1:ndim)
1345 character(len=*), intent(in) :: subname
1346 integer :: idir
1347 logical :: flag(ixi^s,1:nw)
1348 double precision :: rho(ixi^s)
1349
1350 flag=.false.
1351 where(w(ixo^s,ie)<small_e) flag(ixo^s,ie)=.true.
1352 if(any(flag(ixo^s,ie))) then
1353 select case (small_values_method)
1354 case ("replace")
1355 where(flag(ixo^s,ie)) w(ixo^s,ie)=small_e
1356 case ("average")
1357 call small_values_average(ixi^l, ixo^l, w, x, flag, ie)
1358 case default
1359 w(ixo^s,e_)=w(ixo^s,e_)*eos%gamma_minus_1
1360 call ffhd_get_rho(w,x,ixi^l,ixo^l,rho)
1361 w(ixo^s,mom(1)) = w(ixo^s,mom(1))/rho(ixo^s)
1362 call small_values_error(w, x, ixi^l, ixo^l, flag, subname)
1363 end select
1364 end if
1365 end subroutine ffhd_handle_small_ei
1366
1367
1368 subroutine ffhd_get_dt(wprim,ixI^L,ixO^L,dtnew,dx^D,x)
1370 use mod_usr_methods
1371 use mod_gravity, only: gravity_get_dt
1372 integer, intent(in) :: ixi^l, ixo^l
1373 double precision, intent(inout) :: dtnew
1374 double precision, intent(in) :: dx^d
1375 double precision, intent(in) :: wprim(ixi^s,1:nw)
1376 double precision, intent(in) :: x(ixi^s,1:ndim)
1377
1378 dtnew = bigdouble
1379
1380 if(ffhd_gravity) then
1381 call gravity_get_dt(wprim,ixi^l,ixo^l,dtnew,dx^d,x)
1382 end if
1383 end subroutine ffhd_get_dt
1384
1385 subroutine ffhd_add_source_geom(qdt,dtfactor,ixI^L,ixO^L,wCT,wprim,w,x)
1387 integer, intent(in) :: ixi^l, ixo^l
1388 double precision, intent(in) :: qdt, dtfactor,x(ixi^s,1:ndim)
1389 double precision, intent(inout) :: wct(ixi^s,1:nw), wprim(ixi^s,1:nw),w(ixi^s,1:nw)
1390
1391 ! no geometric source terms needed for ffhd, no divergences of tensors
1392 end subroutine ffhd_add_source_geom
1393
1394 function ffhd_kin_en_origin(w, ixI^L, ixO^L, inv_rho) result(ke)
1395 use mod_global_parameters, only: nw, ndim,block
1396 integer, intent(in) :: ixi^l, ixo^l
1397 double precision, intent(in) :: w(ixi^s, nw)
1398 double precision :: ke(ixo^s)
1399 double precision, intent(in), optional :: inv_rho(ixo^s)
1400
1401 if(present(inv_rho)) then
1402 ke(ixo^s)=0.5d0*w(ixo^s,mom(1))**2*inv_rho(ixo^s)
1403 else
1404 ke(ixo^s)=0.5d0*w(ixo^s,mom(1))**2/w(ixo^s,rho_)
1405 end if
1406 end function ffhd_kin_en_origin
1407
1408
1409 subroutine rfactor_from_constant_ionization(w,x,ixI^L,ixO^L,Rfactor)
1411 integer, intent(in) :: ixi^l, ixo^l
1412 double precision, intent(in) :: w(ixi^s,1:nw)
1413 double precision, intent(in) :: x(ixi^s,1:ndim)
1414 double precision, intent(out):: rfactor(ixi^s)
1415
1416 rfactor(ixo^s)=rr
1418
1419 subroutine add_hyperbolic_tc_source(qdt,ixI^L,ixO^L,wCT,w,x,wCTprim)
1421
1422 integer, intent(in) :: ixi^l,ixo^l
1423 double precision, intent(in) :: qdt
1424 double precision, dimension(ixI^S,1:ndim), intent(in) :: x
1425 double precision, dimension(ixI^S,1:nw), intent(in) :: wct,wctprim
1426 double precision, dimension(ixI^S,1:nw), intent(inout) :: w
1427
1428 double precision, dimension(ixI^S) :: te, r
1429 double precision :: sigma_t5,sigma_t7,sigmat5_bgradt,f_sat,tau
1430 integer :: ix^d
1431
1432 ! EoS-aware temperature: T = p/(R*rho). For FI R=RR (=1 under eq_state_units)
1433 ! recovers p/rho; for LTE R=Rfactor_from_LTE varies, so LTE+HTC is physically
1434 ! consistent. Computed over ixI^L (the +-2 stencil reaches ghost layers;
1435 ! their R uses the update_eos_4_bc-refreshed aux state, as in mhd).
1436 call ffhd_get_rfactor(wct,x,ixi^l,ixi^l,r)
1437 te(ixi^s)=wctprim(ixi^s,p_)/(r(ixi^s)*wct(ixi^s,rho_))
1438 ! temperature on face T_(i+1/2)=(7(T_i+T_(i+1))-(T_(i-1)+T_(i+2)))/12
1439 ! T_(i+1/2)-T_(i-1/2)=(8(T_(i+1)-T_(i-1))-T_(i+2)+T_(i-2))/12
1440 {^iftwod
1441 do ix2=ixomin2,ixomax2
1442 do ix1=ixomin1,ixomax1
1443 if(ffhd_trac) then
1444 if(te(ix^d)<block%wextra(ix^d,tcoff_)) then
1445 sigma_t5=hyperbolic_tc_kappa*sqrt(block%wextra(ix^d,tcoff_)**5)
1446 sigma_t7=sigma_t5*block%wextra(ix^d,tcoff_)
1447 else
1448 sigma_t5=hyperbolic_tc_kappa*sqrt(te(ix^d)**5)
1449 sigma_t7=sigma_t5*te(ix^d)
1450 end if
1451 else
1452 sigma_t5=hyperbolic_tc_kappa*sqrt(te(ix^d)**5)
1453 sigma_t7=sigma_t5*te(ix^d)
1454 end if
1455 sigmat5_bgradt=sigma_t5*(&
1456 block%B0(ix^d,1,0)*((8.d0*(te(ix1+1,ix2)-te(ix1-1,ix2))-te(ix1+2,ix2)+te(ix1-2,ix2))/12.d0)/block%ds(ix^d,1)&
1457 +block%B0(ix^d,2,0)*((8.d0*(te(ix1,ix2+1)-te(ix1,ix2-1))-te(ix1,ix2+2)+te(ix1,ix2-2))/12.d0)/block%ds(ix^d,2))
1458 if(ffhd_hyperbolic_tc_sat) then
1459 ! 5 phi rho c^3, phi=0.3, c=sqrt(p/rho) isothermal sound speed
1460 f_sat=one/(one+dabs(sigmat5_bgradt)/(1.5d0*wct(ix^d,rho_)*(wctprim(ix^d,p_)/wct(ix^d,rho_))**1.5d0))
1461 tau=max(4.d0*dt, f_sat*sigma_t7*courantpar**2/(wctprim(ix^d,p_)*eos%inv_gamma_minus_1*cmax_global**2))
1462 w(ix^d,q_)=w(ix^d,q_)-qdt*(f_sat*sigmat5_bgradt+wct(ix^d,q_))/tau
1463 else
1464 w(ix^d,q_)=w(ix^d,q_)-qdt*(sigmat5_bgradt+wct(ix^d,q_))/&
1465 max(4.d0*dt, sigma_t7*courantpar**2/(wctprim(ix^d,p_)*eos%inv_gamma_minus_1*cmax_global**2))
1466 end if
1467 end do
1468 end do
1469 }
1470 {^ifthreed
1471 do ix3=ixomin3,ixomax3
1472 do ix2=ixomin2,ixomax2
1473 do ix1=ixomin1,ixomax1
1474 if(ffhd_trac) then
1475 if(te(ix^d)<block%wextra(ix^d,tcoff_)) then
1476 sigma_t5=hyperbolic_tc_kappa*sqrt(block%wextra(ix^d,tcoff_)**5)
1477 sigma_t7=sigma_t5*block%wextra(ix^d,tcoff_)
1478 else
1479 sigma_t5=hyperbolic_tc_kappa*sqrt(te(ix^d)**5)
1480 sigma_t7=sigma_t5*te(ix^d)
1481 end if
1482 else
1483 sigma_t5=hyperbolic_tc_kappa*sqrt(te(ix^d)**5)
1484 sigma_t7=sigma_t5*te(ix^d)
1485 end if
1486 sigmat5_bgradt=sigma_t5*(&
1487 block%B0(ix^d,1,0)*((8.d0*(te(ix1+1,ix2,ix3)-te(ix1-1,ix2,ix3))-te(ix1+2,ix2,ix3)+te(ix1-2,ix2,ix3))/12.d0)/block%ds(ix^d,1)&
1488 +block%B0(ix^d,2,0)*((8.d0*(te(ix1,ix2+1,ix3)-te(ix1,ix2-1,ix3))-te(ix1,ix2+2,ix3)+te(ix1,ix2-2,ix3))/12.d0)/block%ds(ix^d,2)&
1489 +block%B0(ix^d,3,0)*((8.d0*(te(ix1,ix2,ix3+1)-te(ix1,ix2,ix3-1))-te(ix1,ix2,ix3+2)+te(ix1,ix2,ix3-2))/12.d0)/block%ds(ix^d,3))
1490 if(ffhd_hyperbolic_tc_sat) then
1491 ! 5 phi rho c^3, phi=0.3, c=sqrt(p/rho) isothermal sound speed
1492 f_sat=one/(one+dabs(sigmat5_bgradt)/(1.5d0*wct(ix^d,rho_)*(wctprim(ix^d,p_)/wct(ix^d,rho_))**1.5d0))
1493 tau=max(4.d0*dt, f_sat*sigma_t7*courantpar**2/(wctprim(ix^d,p_)*eos%inv_gamma_minus_1*cmax_global**2))
1494 w(ix^d,q_)=w(ix^d,q_)-qdt*(f_sat*sigmat5_bgradt+wct(ix^d,q_))/tau
1495 else
1496 w(ix^d,q_)=w(ix^d,q_)-qdt*(sigmat5_bgradt+wct(ix^d,q_))/&
1497 max(4.d0*dt, sigma_t7*courantpar**2/(wctprim(ix^d,p_)*eos%inv_gamma_minus_1*cmax_global**2))
1498 end if
1499 end do
1500 end do
1501 end do
1502 }
1503 end subroutine add_hyperbolic_tc_source
1504
1505end module mod_ffhd_phys
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.
subroutine add_convert_method(phys_convert_vars, nwc, dataset_names, file_suffix)
Definition mod_convert.t:59
PI (partial-ionisation) ionisation-degree backend for the eos% family.
Equation of state for AMRVAC, handled through a single eos_container object.
Definition mod_eos.t:30
Frozen-field hydrodynamics module.
integer, public, protected te_
Indices of temperature and electron number density (LTE stored aux state).
integer, public, protected ffhd_trac_type
Which TRAC method is used.
integer, public, protected e_
Index of the energy density (-1 if not present).
subroutine, public ffhd_to_primitive_origin(ixil, ixol, w, x)
double precision, public hyperbolic_tc_kappa
The thermal conductivity kappa in hyperbolic thermal conduction.
procedure(sub_get_pthermal), pointer, public ffhd_get_rfactor
double precision, public ffhd_adiab
The adiabatic index (now owned by eos%; use eosgamma).
procedure(sub_get_pthermal), pointer, public ffhd_get_temperature
type(rc_fluid), allocatable, public rc_fl
type of fluid for radiative cooling
integer, public, protected rho_
Whether plasma is partially ionized.
integer, public, protected tcoff_
Index of the cutoff temperature for the TRAC method.
procedure(sub_get_pthermal), pointer, public ffhd_get_pthermal
subroutine, public ffhd_get_rho(w, x, ixil, ixol, rho)
integer, public, protected ne_
procedure(sub_convert), pointer, public ffhd_to_conserved
integer, dimension(:), allocatable, public, protected mom
Indices of the momentum density.
subroutine, public ffhd_get_temperature_from_etot(w, x, ixil, ixol, res)
logical, public, protected ffhd_hyperbolic_tc_use_perp
Whether the perpendicular hyperbolic-TC channel is enabled.
double precision, public, protected h_ion_fr
Helium abundance over Hydrogen (now owned by eos%; use eosHe_abundance) Ionization fraction of H H_io...
procedure(fun_kin_en), pointer, public ffhd_kin_en
subroutine, public ffhd_phys_init()
procedure(sub_get_v), pointer, public ffhd_get_v
subroutine, public ffhd_get_csound2(w, x, ixil, ixol, csound2)
logical, public, protected ffhd_energy
Whether an energy equation is used.
double precision, public, protected rr
type(tc_fluid), allocatable, public tc_fl
type of fluid for thermal conduction
double precision function, dimension(ixo^s), public ffhd_get_ei(w, ixil, ixol)
Internal energy eint = E_total - E_kinetic (single field-aligned momentum). Wired to phys_get_ei; the...
type(te_fluid), allocatable, public te_fl_ffhd
type of fluid for thermal emission synthesis
logical, public, protected ffhd_hyperbolic_tc
Whether hyperbolic type thermal conduction is used.
logical, public, protected ffhd_radiative_cooling
Whether radiative cooling is added.
subroutine, public ffhd_get_v_idim(w, x, ixil, ixol, idim, v)
subroutine, public ffhd_get_pthermal_origin(w, x, ixil, ixol, pth)
integer, public, protected q_
procedure(sub_convert), pointer, public ffhd_to_primitive
logical, public, protected ffhd_hyperbolic_tc_sat
Whether saturation is considered for hyperbolic TC.
subroutine, public ffhd_get_temperature_from_te(w, x, ixil, ixol, res)
integer, public, protected tweight_
double precision, public, protected he_ion_fr2
Ratio of number He2+ / number He+ + He2+ He_ion_fr2 = He2+/(He2+ + He+).
logical, public, protected ffhd_trac
Whether TRAC method is used.
subroutine, public ffhd_to_conserved_origin(ixil, ixol, w, x)
logical, public, protected ffhd_thermal_conduction
Whether thermal conduction is used.
subroutine, public ffhd_ei_to_e(ixil, ixol, w, x)
logical, public, protected ffhd_gravity
Whether gravity is added.
subroutine, public rfactor_from_constant_ionization(w, x, ixil, ixol, rfactor)
integer, public, protected p_
Index of the gas pressure (-1 if not present) should equal e_.
double precision, public, protected ffhd_trac_mask
Height of the mask used in the TRAC method.
double precision, public, protected he_ion_fr
Ionization fraction of He He_ion_fr = (He2+ + He+)/(He2+ + He+ + He).
subroutine, public ffhd_get_temperature_from_eint(w, x, ixil, ixol, res)
integer, public, protected ffhd_trac_finegrid
Distance between two adjacent traced magnetic field lines (in finest cell size).
procedure(sub_small_values), pointer, public ffhd_handle_small_values
subroutine, public ffhd_e_to_ei(ixil, ixol, w, x)
Module for flux conservation near refinement boundaries.
Module with geometry-related routines (e.g., divergence, curl).
Definition mod_geometry.t:2
subroutine divvector(qvec, ixil, ixol, divq, nth_in)
integer coordinate
Definition mod_geometry.t:7
subroutine gradient(q, ixil, ixol, idir, gradq, nth_in)
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.
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 unit_mass
Physical scaling factor for mass.
integer, dimension(3, 3) kr
Kronecker delta tensor.
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.
double precision cmax_global
global fastest wave speed needed in fd scheme and glm method
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 dt
global time step
integer ndir
Number of spatial dimensions (components) for vector variables.
double precision courantpar
The Courant (CFL) number used for the simulation.
double precision, dimension(:), allocatable, parameter d
logical slab
Cartesian geometry or not.
integer nwauxio
Number of auxiliary variables that are only included in output.
double precision unit_velocity
Physical scaling factor for velocity.
logical b0field
split magnetic field as background B0 field
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
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 need_global_cmax
need global maximal wave speed
logical fix_small_values
fix small values with average or replace methods
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
integer boundspeed
bound (left/min and right.max) speed of Riemann fan
integer, parameter unitconvert
integer number_equi_vars
number of equilibrium set variables, besides the mag field
Module for including gravity in (magneto)hydrodynamics simulations.
Definition mod_gravity.t:2
subroutine gravity_get_dt(wprim, 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
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 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_mhd(w, ixil, ixol, dxd, x, fl)
Get the explicit timestep for the TC (mhd implementation) Note: for multi-D MHD (1D MHD will use HD f...
subroutine tc_init_params(phys_gamma)
subroutine, public sts_set_source_tc_mhd(ixil, ixol, w, x, wres, fix_conserve_at_step, my_dt, igrid, nflux, fl)
anisotropic thermal conduction with slope limited symmetric scheme Sharma 2007 Journal of Computation...
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_equi_vars), pointer usr_set_equi_vars