49 call mpistop(
"FFHD: ffhd_energy=.false. requires eos_type='FI'")
54 if (
eos%eos_type ==
'FI' .or.
eos%eos_type ==
'PI')
then
57 else if (
eos%eos_type ==
'LTE')
then
58 eos%to_conserved => ffhd_to_conserved_lte
59 eos%to_primitive => ffhd_to_primitive_lte
61 call mpistop(
"Unknown FFHD EOS type: " // trim(
eos%eos_type))
71 eos%p_to_e => ffhd_p_to_e
77 if (
eos%eos_type ==
'LTE')
then
80 eos%get_thermal_pressure => ffhd_get_pthermal_lte
100 if (
eos%eos_type ==
'LTE' .and.
eos%ionE)
then
101 eos%get_csound2 => ffhd_get_csound2_lte
112 if (
eos%eos_type ==
'PI')
then
135 if (
eos%eos_type ==
'PI' .and.
eos%ionE)
then
137 call mpistop(
'FFHD PI energy EoS requires ffhd_energy=.true.')
138 eos%to_conserved => ffhd_to_conserved_pi
139 eos%to_primitive => ffhd_to_primitive_pi
144 eos%p_to_e => ffhd_p_to_e_pi
147 eos%get_thermal_pressure => ffhd_get_pthermal_pi
157 subroutine ffhd_bind_eos_to_source()
164 if (
allocated(
tc_fl))
then
165 tc_fl%get_temperature_from_conserved =>
eos%get_temperature_from_etot
166 if (
eos%eos_type ==
'LTE' .and.
eos%ionE)
then
169 tc_fl%get_temperature_from_eint =>
eos%get_temperature_from_eint
173 tc_fl%get_var_Rfactor =>
eos%get_Rfactor
174 tc_fl%inv_gamma_minus_1 =
eos%inv_gamma_minus_1
175 tc_fl%nH2rhoFactor =
eos%nH2rhoFactor
176 tc_fl%log_T_floor = eos_get_log_t_floor()
180 if (
allocated(
rc_fl))
then
182 rc_fl%get_pthermal =>
eos%get_thermal_pressure
183 rc_fl%get_var_Rfactor =>
eos%get_Rfactor
188 rc_fl%inv_gamma_minus_1 =
eos%inv_gamma_minus_1
189 rc_fl%nH2rhoFactor =
eos%nH2rhoFactor
195 if (
eos%ionE .and.
eos%eos_type ==
'LTE')
then
203 if (
eos%eos_type ==
'PI' .and.
eos%ionE)
then
205 if (
allocated(
rc_fl))
then
222 end subroutine ffhd_bind_eos_to_source
231 subroutine ffhd_to_conserved_lte(ixI^L, ixO^L, w, x)
233 integer,
intent(in) :: ixi^
l, ixo^
l
234 double precision,
intent(inout) :: w(ixi^s, nw)
235 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
237 call ffhd_p_to_e(ixi^
l, ixo^
l, w, x)
238 w(ixo^s,
mom(1)) = w(ixo^s,
rho_)*w(ixo^s,
mom(1))
239 end subroutine ffhd_to_conserved_lte
245 subroutine ffhd_p_to_e(ixI^L, ixO^L, w, x)
247 integer,
intent(in) :: ixi^
l, ixo^
l
248 double precision,
intent(inout) :: w(ixi^s, nw)
249 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
252 double precision :: p_to_eint, p_over_rho
253 double precision :: nh(ixi^s), nh_in(ixi^s), p_in(ixi^s)
254 double precision :: log_eint_mid, eint_total
255 double precision :: t_solve, y_solve, eint_nh_solve
260 call eos%get_nH(w, x, ixi^
l, ixo^
l, nh)
261 nh_in(ixo^s) = dlog10(nh(ixo^s))
262 if (
eos%p2eint_method /=
'bisect')
then
263 p_in(ixo^s) = dlog10(w(ixo^s,
p_)) - nh_in(ixo^s)
267 p_to_eint =
eos%inv_gamma_minus_1
268 {
do ix^db=ixomin^db,ixomax^db\}
270 p_over_rho = w(ix^
d,
p_) / w(ix^
d,
rho_)
271 if (p_over_rho >
eos%p_rho_FI_threshold)
then
272 p_to_eint =
eos%inv_gamma_minus_1 &
273 +
eos%eion_per_nH * nh(ix^
d) / w(ix^
d,
p_)
274 w(ix^
d,
e_) = w(ix^
d,
p_)*p_to_eint + &
276 else if (
eos%method ==
'analytic')
then
278 t_solve, y_solve, eint_nh_solve)
279 w(ix^
d,
e_) = eint_nh_solve * nh(ix^
d) + &
281 else if (
eos%p2eint_method ==
'bisect')
then
283 dlog10(w(ix^
d,
p_)), log_eint_mid)
284 eint_total = nh(ix^
d) * 10.0d0**log_eint_mid
285 eint_total = max(eint_total, &
286 nh(ix^
d) * 10.0d0**
eos%T%var2_min)
287 w(ix^
d,
e_) = eint_total + &
291 w(ix^
d,
e_) = w(ix^
d,
p_)*p_to_eint + &
295 w(ix^
d,
e_) = w(ix^
d,
p_)*p_to_eint + &
299 end subroutine ffhd_p_to_e
304 subroutine ffhd_to_primitive_lte(ixI^L, ixO^L, w, x)
306 integer,
intent(in) :: ixi^
l, ixo^
l
307 double precision,
intent(inout) :: w(ixi^s, nw)
308 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
310 double precision :: inv_rho
311 double precision :: nh(ixi^s), log_nh(ixi^s)
312 double precision :: eint_val, eint_in
316 call ffhd_handle_small_values(.false., w, x, ixi^
l, ixo^
l, &
317 'ffhd_to_primitive_LTE')
320 call eos%get_nH(w, x, ixi^
l, ixo^
l, nh)
321 if (eos%ionE) log_nh(ixo^s) = dlog10(nh(ixo^s))
323 {
do ix^db=ixomin^db,ixomax^db\}
324 inv_rho = 1.d0/w(ix^
d,rho_)
325 w(ix^
d,mom(1)) = w(ix^
d,mom(1))*inv_rho
326 if (ffhd_energy)
then
328 eint_val = w(ix^
d,e_) - half*w(ix^
d,rho_)*w(ix^
d,mom(1))**2
329 if (eos%method /=
'analytic')
then
330 eint_val = max(eint_val, nh(ix^
d)*10.0d0**eos%T%var2_min)
332 eint_val = max(eint_val, smalldouble)
333 if (eint_val * inv_rho > eos%eint_rho_FI_threshold)
then
334 w(ix^
d,p_) = eos%gamma_minus_1 &
335 * (eint_val - eos%eion_per_nH * nh(ix^
d))
337 eint_in = dlog10(eint_val) - log_nh(ix^
d)
338 w(ix^
d,p_) = nh(ix^
d) &
339 * p_nh_from_eint(log_nh(ix^
d), eint_in)
342 w(ix^
d,p_) = eos%gamma_minus_1 &
343 * (w(ix^
d,e_) - half*w(ix^
d,rho_)*w(ix^
d,mom(1))**2)
347 end subroutine ffhd_to_primitive_lte
352 subroutine ffhd_get_pthermal_lte(w, x, ixI^L, ixO^L, pth)
355 integer,
intent(in) :: ixi^
l, ixo^
l
356 double precision,
intent(in) :: w(ixi^s, 1:nw)
357 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
358 double precision,
intent(out):: pth(ixi^s)
360 double precision :: nh(ixi^s)
362 if (ffhd_energy)
then
363 call eos%get_nH(w, x, ixi^
l, ixo^
l, nh)
364 pth(ixo^s) = nh(ixo^s) * (1.0d0 + eos%He_abundance &
365 + (w(ixo^s,iw_ne) / nh(ixo^s))) * w(ixo^s,iw_te)
367 pth(ixo^s) = ffhd_adiab * w(ixo^s, rho_)**eos%gamma
371 {
do ix^db= ixo^lim^db\}
374 else if (check_small_values)
then
375 {
do ix^db= ixo^lim^db\}
376 if(pth(ix^d)<small_pressure)
then
377 write(*,*)
"Error: small value of gas pressure",pth(ix^d),&
378 " encountered when call ffhd_get_pthermal_LTE"
379 write(*,*)
"Iteration: ", it,
" Time: ", global_time
380 write(*,*)
"Location: ", x(ix^d,:)
381 write(*,*)
"Cell number: ", ix^d
383 write(*,*) trim(cons_wnames(iw)),
": ",w(ix^d,iw)
385 if(trace_small_values)
write(*,*) dsqrt(pth(ix^d)-bigdouble)
386 write(*,*)
"Saving status at the previous time step"
391 end subroutine ffhd_get_pthermal_lte
394 subroutine ffhd_get_csound2_lte(w, x, ixI^L, ixO^L, cs2)
396 integer,
intent(in) :: ixi^
l, ixo^
l
397 double precision,
intent(in) :: w(ixi^s, nw)
398 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
399 double precision,
intent(out) :: cs2(ixi^s)
402 call ffhd_get_gamma1_lte(w, x, ixi^
l, ixo^
l, cs2)
403 {
do ix^db=ixomin^db,ixomax^db\}
404 cs2(ix^
d) = cs2(ix^
d) * w(ix^
d, p_) / w(ix^
d, rho_)
406 end subroutine ffhd_get_csound2_lte
409 subroutine ffhd_get_gamma1_lte(w, x, ixI^L, ixO^L, gamma1)
411 integer,
intent(in) :: ixi^
l, ixo^
l
412 double precision,
intent(in) :: w(ixi^s, nw)
413 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
414 double precision,
intent(out) :: gamma1(ixi^s)
415 double precision :: nh_val, p_over_rho
418 if (eos%gamma1_method ==
'constant')
then
419 gamma1(ixo^s) = eos%gamma
423 {
do ix^db=ixomin^db,ixomax^db\}
424 p_over_rho = w(ix^
d, p_) / w(ix^
d, rho_)
425 if (p_over_rho > eos%p_rho_FI_threshold)
then
426 gamma1(ix^
d) = eos%gamma
428 nh_val = w(ix^
d, rho_) / eos%nH2rhoFactor
429 if (eos%method ==
'analytic')
then
430 if (iw_te > 0 .and. w(ix^
d,iw_te) > 0.0d0)
then
431 gamma1(ix^
d) = saha_gamma1_from_nh_t(nh_val, w(ix^
d,iw_te))
433 gamma1(ix^
d) = eos%gamma
436 gamma1(ix^
d) = gamma1_from_nh_p(dlog10(nh_val), &
437 dlog10(w(ix^
d, p_) / nh_val))
441 end subroutine ffhd_get_gamma1_lte
446 subroutine ffhd_to_prolong_lte(ixI^L, ixO^L, w, x)
447 integer,
intent(in) :: ixi^l, ixo^l
448 double precision,
intent(inout) :: w(ixi^s, nw)
449 double precision,
intent(in) :: x(ixi^s, 1:ndim)
451 double precision :: inv_rho, eint_val, nh_val, log_nh, t_loc, y_loc
454 {
do ix^db=ixomin^db,ixomax^db\}
455 inv_rho = 1.d0 / w(ix^d, rho_)
456 nh_val = w(ix^d, rho_) / eos%nH2rhoFactor
457 log_nh = dlog10(nh_val)
459 w(ix^d,mom(1)) = w(ix^d,mom(1))*inv_rho
461 eint_val = w(ix^d, e_) - half*w(ix^d, rho_)*w(ix^d,mom(1))**2
462 if (eos%method /=
'analytic')
then
463 eint_val = max(eint_val, nh_val * 10.0d0**eos%T%var2_min)
465 eint_val = max(eint_val, smalldouble)
467 if (eint_val * inv_rho > eos%eint_rho_FI_threshold)
then
468 w(ix^d, e_) = eos%gamma_minus_1 &
469 * (eint_val - eos%eion_per_nH * nh_val) &
470 / (nh_val * eos%n_per_nH_FI)
471 else if (eos%method ==
'analytic')
then
472 call saha_t_from_nh_eint(nh_val, eint_val / nh_val, t_loc, y_loc)
475 w(ix^d, e_) = t_from_nh_eint(log_nh, &
476 dlog10(eint_val) - log_nh)
479 end subroutine ffhd_to_prolong_lte
483 subroutine ffhd_from_prolong_lte(ixI^L, ixO^L, w, x)
484 integer,
intent(in) :: ixi^l, ixo^l
485 double precision,
intent(inout) :: w(ixi^s, nw)
486 double precision,
intent(in) :: x(ixi^s, 1:ndim)
488 double precision :: t_val, eint_val, t_fi, nh_val, log_nh, log_t_min
491 t_fi = (eos%eint_rho_FI_threshold &
492 * eos%nH2rhoFactor - eos%eion_per_nH) &
493 * eos%gamma_minus_1 / eos%n_per_nH_FI
495 if (eos%method ==
'entropy')
then
496 log_t_min = eos%eintT%var2_min
498 log_t_min = eos%eint_from_T%var2_min
501 {
do ix^db=ixomin^db,ixomax^db\}
503 nh_val = w(ix^d, rho_) / eos%nH2rhoFactor
504 log_nh = dlog10(nh_val)
506 if (t_val > t_fi)
then
508 * (eos%n_per_nH_FI * t_val * eos%inv_gamma_minus_1 &
510 else if (eos%method ==
'analytic')
then
511 eint_val = saha_eint_from_nh_t(nh_val, t_val) * nh_val
513 eint_val = eint_nh_from_t(log_nh, &
514 dlog10(max(t_val, 10.0d0**log_t_min))) * nh_val
517 w(ix^d, e_) = eint_val + half*w(ix^d, rho_)*w(ix^d,mom(1))**2
518 w(ix^d,mom(1)) = w(ix^d,rho_)*w(ix^d,mom(1))
520 end subroutine ffhd_from_prolong_lte
531 subroutine ffhd_p_to_e_pi(ixI^L, ixO^L, w, x)
533 integer,
intent(in) :: ixi^
l, ixo^
l
534 double precision,
intent(inout) :: w(ixi^s, nw)
535 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
536 double precision :: eint
539 {
do ix^db=ixomin^db,ixomax^db\}
540 if (ffhd_energy)
then
541 call eint_from_rho_p_pi(w(ix^
d,rho_), w(ix^
d,p_), eint)
542 w(ix^
d,e_) = eint + half*w(ix^
d,mom(1))**2*w(ix^
d,rho_)
545 end subroutine ffhd_p_to_e_pi
548 subroutine ffhd_to_conserved_pi(ixI^L, ixO^L, w, x)
550 integer,
intent(in) :: ixi^
l, ixo^
l
551 double precision,
intent(inout) :: w(ixi^s, nw)
552 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
554 call ffhd_p_to_e_pi(ixi^
l, ixo^
l, w, x)
555 w(ixo^s,mom(1)) = w(ixo^s,rho_)*w(ixo^s,mom(1))
556 end subroutine ffhd_to_conserved_pi
559 subroutine ffhd_to_primitive_pi(ixI^L, ixO^L, w, x)
561 integer,
intent(in) :: ixi^
l, ixo^
l
562 double precision,
intent(inout) :: w(ixi^s, nw)
563 double precision,
intent(in) :: x(ixi^s, 1:
ndim)
564 double precision :: inv_rho, eint_val, t, rfac
568 call ffhd_handle_small_values(.false., w, x, ixi^
l, ixo^
l, &
569 'ffhd_to_primitive_PI')
572 {
do ix^db=ixomin^db,ixomax^db\}
573 inv_rho = 1.d0/w(ix^
d,rho_)
574 w(ix^
d,mom(1)) = w(ix^
d,mom(1))*inv_rho
575 if (ffhd_energy)
then
576 eint_val = w(ix^
d,e_) - half*w(ix^
d,rho_)*w(ix^
d,mom(1))**2
577 eint_val = max(eint_val, smalldouble)
578 call state_from_eint_pi(w(ix^
d,rho_), eint_val, &
582 end subroutine ffhd_to_primitive_pi
585 subroutine ffhd_get_pthermal_pi(w, x, ixI^L, ixO^L, pth)
587 integer,
intent(in) :: ixi^
l, ixo^
l
588 double precision,
intent(in) :: w(ixi^s, 1:nw), x(ixi^s, 1:
ndim)
589 double precision,
intent(out):: pth(ixi^s)
590 double precision :: ei(ixi^s), tpi, rpi
593 ei(ixo^s) = ffhd_get_ei(w, ixi^
l, ixo^
l)
594 {
do ix^db=ixomin^db,ixomax^db\}
595 call state_from_eint_pi(w(ix^
d,rho_), ei(ix^
d), tpi, pth(ix^
d), rpi)
597 end subroutine ffhd_get_pthermal_pi
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
EoS state container – the single thermodynamic authority for AMRVAC.
type(eos_container), allocatable, public eos
The single EoS state object, allocated in eos_init and shared (read-mostly) across all EoS sub-module...
Analytic H-only Saha EoS (eos_method == 'analytic').
subroutine, public saha_state_from_nh_p(nh_code, p_code, t_out, y_out, eint_nh_out)
Given (nH, p) in CODE UNITS, find T and y by solving p = nH*(1+y(T))*T_code. Uses bisection on T....
LTE (Saha-table) EoS kernels and finalise for the eos% family.
double precision function, public p2eint_from_nh_p(nh, ponh)
Pressure-to-eint ratio from (log10 nH, log10 p/nH) in code units. Dispatches: analytic -> Saha solve ...
double precision function, public eint_nh_from_t(log_nh, log_t)
Internal energy per nH from (log10 nH, log10 T) in code units. Uses the bisection-built inverse table...
subroutine, public eint_from_p_bisect(log_nh_val, log_p_val, log_eint_nh_out)
Given log10(nH) and log10(p), find log10(eint/nH) by table-guessed bisection on the forward pressure ...
double precision function, public y_from_nh_eint(nh, eint_nh)
Ionization fraction from (log10 nH, log10 eint/nH) in code units. Dispatches: analytic -> Saha quadra...
subroutine, public get_temperature_from_eint_fast_lte(w, x, ixil, ixol, res)
subroutine, public eos_get_eintt_grid(n_nh, lg_nh_min, lg_nh_max)
log_nH grid metadata of the (log_nH, log_T) inverse table (eint from T), choosing the container by me...
double precision function, public t_from_nh_eint(nh, eint_nh)
Temperature from (log10 nH, log10 eint/nH) in code units. Dispatches: analytic -> Saha bisection/Newt...
PI (partial-ionisation, eos_type='PI') arm of the eos% family.
double precision function, dimension(log_nh, log_p_nh), public p2eint_pi(log_nh, log_p_nh)
eint/p factor from pressure per H: maps p -> eint = p * (this).
double precision function, dimension(log_nh, log_t), public eint_from_t_pi(log_nh, log_t)
Internal energy per H from temperature: eint/nH(T).
double precision function, dimension(log_nh, log_eint_nh), public y_from_eint_pi(log_nh, log_eint_nh)
Electron-to-hydrogen ratio ne/nH from internal energy per H. ne/nH = iz_H + A_He*iz_He*(1+iz_He) (mat...
subroutine, public get_gamma1_pi(w, x, ixil, ixol, gamma1)
Effective Gamma1 = cs2 * rho / p for the same primitive state.
double precision function, dimension(log_nh, log_eint_nh), public t_from_eint_pi(log_nh, log_eint_nh)
Temperature from internal energy per H.
Equation of state for AMRVAC, handled through a single eos_container object.
FFHD <-> EoS seam: binds the eos% authority into force-free hydrodynamics.
subroutine, public ffhd_link_eos()
Link the appropriate EoS conversion/closure routines per eos_type. Called from ffhd_activate after ff...
Frozen-field hydrodynamics module.
integer, public, protected e_
Index of the energy density (-1 if not present)
subroutine, public ffhd_to_primitive_origin(ixil, ixol, w, x)
procedure(sub_get_pthermal), pointer, public ffhd_get_rfactor
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.
procedure(sub_get_pthermal), pointer, public ffhd_get_pthermal
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)
subroutine, public ffhd_get_csound2(w, x, ixil, ixol, csound2)
logical, public, protected ffhd_energy
Whether an energy equation is used.
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
subroutine, public ffhd_get_pthermal_origin(w, x, ixil, ixol, pth)
procedure(sub_convert), pointer, public ffhd_to_primitive
subroutine, public ffhd_get_temperature_from_te(w, x, ixil, ixol, res)
subroutine, public ffhd_to_conserved_origin(ixil, ixol, w, x)
subroutine, public ffhd_ei_to_e(ixil, ixol, w, x)
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_.
subroutine, public ffhd_e_to_ei(ixil, ixol, w, x)
This module contains definitions of global parameters and variables and some generic functions/subrou...
double precision small_pressure
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision, dimension(:), allocatable, parameter d
logical fix_small_values
fix small values with average or replace methods
This module defines the procedures of a physics module. It contains function pointers for the various...
procedure(sub_check_params), pointer phys_bind_eos_to_source
procedure(sub_convert), pointer phys_to_primitive
procedure(sub_e_to_ei), pointer phys_e_to_ei
procedure(sub_e_to_ei), pointer phys_ei_to_e
procedure(sub_get_pthermal), pointer phys_get_gamma1
procedure(sub_get_pthermal), pointer phys_get_pthermal
procedure(sub_get_ei), pointer phys_get_ei
procedure(sub_convert), pointer phys_to_prolong
procedure(sub_convert), pointer phys_to_conserved
procedure(sub_convert), pointer phys_from_prolong
procedure(sub_get_rho), pointer phys_get_rho
module radiative cooling – add optically thin radiative cooling
subroutine build_y_mod_table(fl)
===================================================================
Module for handling problematic values in simulations, such as negative pressures.
logical, public trace_small_values
trace small values in the source file using traceback flag of compiler
Module with all the methods that users can customize in AMRVAC.
procedure(rfactor), pointer usr_rfactor