33 double precision,
parameter :: LN10 = 2.302585092994046d0
56 character(len=8),
parameter :: quantity(6) = &
57 [character(8)::
'neOnH',
'Tfwd',
'pfwd',
'eintP',
'g1p',
'eintT']
58 character(len=3),
parameter :: deriv(4) = &
59 [character(3)::
'',
'_x',
'_y',
'_xy']
61 if (
mype == 0)
write(*,*) &
62 'EoS method: entropy (bicubic Hermite, 4-derivative corners, no closure)'
63 do iq = 1,
size(quantity)
64 do id = 1,
size(deriv)
76 call entropy_shift_prepare(
eos%neOnH, .false.)
77 call entropy_shift_prepare(
eos%neOnH_x, .false.)
78 call entropy_shift_prepare(
eos%neOnH_y, .false.)
79 call entropy_shift_prepare(
eos%neOnH_xy, .false.)
80 call entropy_shift_prepare(
eos%Tfwd, .false.)
81 call entropy_shift_prepare(
eos%Tfwd_x, .false.)
82 call entropy_shift_prepare(
eos%Tfwd_y, .false.)
83 call entropy_shift_prepare(
eos%Tfwd_xy, .false.)
84 call entropy_shift_prepare(
eos%pfwd, .false.)
85 call entropy_shift_prepare(
eos%pfwd_x, .false.)
86 call entropy_shift_prepare(
eos%pfwd_y, .false.)
87 call entropy_shift_prepare(
eos%pfwd_xy, .false.)
88 call entropy_shift_prepare(
eos%eintP, .false.)
89 call entropy_shift_prepare(
eos%eintP_x, .false.)
90 call entropy_shift_prepare(
eos%eintP_y, .false.)
91 call entropy_shift_prepare(
eos%eintP_xy, .false.)
92 call entropy_shift_prepare(
eos%g1p, .false.)
93 call entropy_shift_prepare(
eos%g1p_x, .false.)
94 call entropy_shift_prepare(
eos%g1p_y, .false.)
95 call entropy_shift_prepare(
eos%g1p_xy, .false.)
96 call entropy_shift_prepare(
eos%eintT, .true.)
97 call entropy_shift_prepare(
eos%eintT_x, .true.)
98 call entropy_shift_prepare(
eos%eintT_y, .true.)
99 call entropy_shift_prepare(
eos%eintT_xy, .true.)
104 eos%T%var2_min =
eos%Tfwd%var2_min
105 eos%T%var2_max =
eos%Tfwd%var2_max
106 eos%T%var1_min =
eos%Tfwd%var1_min
107 eos%T%var1_max =
eos%Tfwd%var1_max
108 if (
mype == 0)
write(*,
'(A)') &
109 ' EoS entropy: forward + inverse tables loaded; no aux builds.'
113 pure subroutine locate_idx_uniform(n, vmin, vmax, val, ix, t, h)
114 integer,
intent(in) :: n
115 double precision,
intent(in) :: vmin, vmax, val
116 integer,
intent(out) :: ix
117 double precision,
intent(out) :: t, h
118 h = (vmax - vmin) / dble(n - 1)
119 if (val <= vmin)
then
120 ix = 1; t = 0.0d0;
return
122 if (val >= vmax)
then
123 ix = n - 1; t = 1.0d0;
return
125 ix = 1 + int((val - vmin) / h)
127 if (ix > n - 1) ix = n - 1
128 t = (val - (vmin + (ix - 1) * h)) / h
129 if (t < 0.0d0) t = 0.0d0
130 if (t > 1.0d0) t = 1.0d0
131 end subroutine locate_idx_uniform
133 pure subroutine locate_idx_nodes(n, nodes, val, ix, t, h)
134 integer,
intent(in) :: n
135 double precision,
intent(in) :: nodes(n), val
136 integer,
intent(out) :: ix
137 double precision,
intent(out) :: t, h
138 integer :: lo, mid, hi
139 if (val <= nodes(1))
then
140 ix = 1; t = 0.0d0; h = nodes(2) - nodes(1);
return
142 if (val >= nodes(n))
then
143 ix = n - 1; t = 1.0d0; h = nodes(n) - nodes(n - 1);
return
148 if (hi - lo <= 1)
exit
150 if (nodes(mid) <= val)
then
157 h = nodes(ix + 1) - nodes(ix)
158 t = (val - nodes(ix)) / h
159 if (t < 0.0d0) t = 0.0d0
160 if (t > 1.0d0) t = 1.0d0
161 end subroutine locate_idx_nodes
163 pure subroutine locate_idx_axis1(tab, val, ix, t, h)
165 double precision,
intent(in) :: val
166 integer,
intent(out) :: ix
167 double precision,
intent(out) :: t, h
168 if (tab%is_uniform)
then
169 call locate_idx_uniform(tab%dim1, tab%var1_min, tab%var1_max, val, ix, t, h)
171 call locate_idx_nodes(tab%dim1, tab%var1_nodes, val, ix, t, h)
173 end subroutine locate_idx_axis1
175 pure subroutine locate_idx_axis2(tab, val, ix, t, h)
177 double precision,
intent(in) :: val
178 integer,
intent(out) :: ix
179 double precision,
intent(out) :: t, h
180 if (tab%is_uniform)
then
181 call locate_idx_uniform(tab%dim2, tab%var2_min, tab%var2_max, val, ix, t, h)
183 call locate_idx_nodes(tab%dim2, tab%var2_nodes, val, ix, t, h)
185 end subroutine locate_idx_axis2
190 pure subroutine cubic_basis(t, H0, H1, H2, H3)
191 double precision,
intent(in) :: t
192 double precision,
intent(out) :: h0, h1, h2, h3
193 double precision :: t2, t3
196 h0 = 2.0d0*t3 - 3.0d0*t2 + 1.0d0
197 h1 = t3 - 2.0d0*t2 + t
198 h2 = -2.0d0*t3 + 3.0d0*t2
200 end subroutine cubic_basis
209 pure subroutine bicubic_hermite_eval(f_t, fx_t, fy_t, fxy_t, x, y, val)
211 double precision,
intent(in) :: x, y
212 double precision,
intent(out) :: val
214 double precision :: tx, ty,
dx, dy
215 double precision :: h0x, h1x, h2x, h3x
216 double precision :: h0y, h1y, h2y, h3y
217 double precision :: f00, f10, f01, f11
218 double precision :: fx00, fx10, fx01, fx11
219 double precision :: fy00, fy10, fy01, fy11
220 double precision :: fxy00, fxy10, fxy01, fxy11
222 call locate_idx_axis1(f_t, x, ix, tx,
dx)
223 call locate_idx_axis2(f_t, y, iy, ty, dy)
225 call cubic_basis(tx, h0x, h1x, h2x, h3x)
226 call cubic_basis(ty, h0y, h1y, h2y, h3y)
228 f00 = f_t%table(ix, iy ); f10 = f_t%table(ix+1, iy )
229 f01 = f_t%table(ix, iy+1); f11 = f_t%table(ix+1, iy+1)
230 fx00 = fx_t%table(ix, iy ) *
dx
231 fx10 = fx_t%table(ix+1, iy ) *
dx
232 fx01 = fx_t%table(ix, iy+1) *
dx
233 fx11 = fx_t%table(ix+1, iy+1) *
dx
234 fy00 = fy_t%table(ix, iy ) * dy
235 fy10 = fy_t%table(ix+1, iy ) * dy
236 fy01 = fy_t%table(ix, iy+1) * dy
237 fy11 = fy_t%table(ix+1, iy+1) * dy
238 fxy00 = fxy_t%table(ix, iy ) *
dx * dy
239 fxy10 = fxy_t%table(ix+1, iy ) *
dx * dy
240 fxy01 = fxy_t%table(ix, iy+1) *
dx * dy
241 fxy11 = fxy_t%table(ix+1, iy+1) *
dx * dy
243 val = h0x*h0y*f00 + h2x*h0y*f10 + h0x*h2y*f01 + h2x*h2y*f11 &
244 + h1x*h0y*fx00 + h3x*h0y*fx10 + h1x*h2y*fx01 + h3x*h2y*fx11 &
245 + h0x*h1y*fy00 + h2x*h1y*fy10 + h0x*h3y*fy01 + h2x*h3y*fy11 &
246 + h1x*h1y*fxy00 + h3x*h1y*fxy10 + h1x*h3y*fxy01 + h3x*h3y*fxy11
247 end subroutine bicubic_hermite_eval
251 log_nH_code, log_e_nh_code) &
254 double precision,
intent(in) :: log_nh_code, log_e_nh_code
255 double precision :: t_cgs
256 call bicubic_hermite_eval(tfwd, tfwd_x, tfwd_y, tfwd_xy, &
257 log_nh_code, log_e_nh_code, t_cgs)
262 log_nH_code, log_e_nh_code) &
265 double precision,
intent(in) :: log_nh_code, log_e_nh_code
266 double precision :: p_cgs, nh_cgs
267 call bicubic_hermite_eval(pfwd, pfwd_x, pfwd_y, pfwd_xy, &
268 log_nh_code, log_e_nh_code, p_cgs)
276 neOnH_xy, log_nH_code, &
277 log_e_nh_code)
result(y)
279 double precision,
intent(in) :: log_nh_code, log_e_nh_code
280 call bicubic_hermite_eval(neonh, neonh_x, neonh_y, neonh_xy, &
281 log_nh_code, log_e_nh_code, y)
287 neOnH, neOnH_x, neOnH_y, neOnH_xy, &
288 log_nH_code, log_e_nh_code, &
298 double precision,
intent(in) :: log_nh_code, log_e_nh_code
299 double precision,
intent(out) :: t_code, y_out
300 double precision :: t_cgs
302 double precision :: tx, ty,
dx, dy
303 double precision :: h0x, h1x, h2x, h3x
304 double precision :: h0y, h1y, h2y, h3y
306 call locate_idx_axis1(tfwd, log_nh_code, ix, tx,
dx)
307 call locate_idx_axis2(tfwd, log_e_nh_code, iy, ty, dy)
308 call cubic_basis(tx, h0x, h1x, h2x, h3x)
309 call cubic_basis(ty, h0y, h1y, h2y, h3y)
311 t_cgs = contract_value(tfwd, tfwd_x, tfwd_y, tfwd_xy, ix, iy, &
312 dx, dy, h0x, h1x, h2x, h3x, h0y, h1y, h2y, h3y)
313 y_out = contract_value(neonh, neonh_x, neonh_y, neonh_xy, ix, iy, &
314 dx, dy, h0x, h1x, h2x, h3x, h0y, h1y, h2y, h3y)
321 pure double precision function contract_value(f_t, fx_t, fy_t, fxy_t, &
323 H0x, H1x, H2x, H3x, &
324 H0y, H1y, H2y, H3y)
result(val)
328 integer,
intent(in) :: ix, iy
329 double precision,
intent(in) ::
dx, dy
330 double precision,
intent(in) :: h0x, h1x, h2x, h3x
331 double precision,
intent(in) :: h0y, h1y, h2y, h3y
332 double precision :: f00, f10, f01, f11
333 double precision :: fx00, fx10, fx01, fx11
334 double precision :: fy00, fy10, fy01, fy11
335 double precision :: fxy00, fxy10, fxy01, fxy11
336 f00 = f_t%table(ix, iy ); f10 = f_t%table(ix+1, iy )
337 f01 = f_t%table(ix, iy+1); f11 = f_t%table(ix+1, iy+1)
338 fx00 = fx_t%table(ix, iy ) *
dx
339 fx10 = fx_t%table(ix+1, iy ) *
dx
340 fx01 = fx_t%table(ix, iy+1) *
dx
341 fx11 = fx_t%table(ix+1, iy+1) *
dx
342 fy00 = fy_t%table(ix, iy ) * dy
343 fy10 = fy_t%table(ix+1, iy ) * dy
344 fy01 = fy_t%table(ix, iy+1) * dy
345 fy11 = fy_t%table(ix+1, iy+1) * dy
346 fxy00 = fxy_t%table(ix, iy ) *
dx * dy
347 fxy10 = fxy_t%table(ix+1, iy ) *
dx * dy
348 fxy01 = fxy_t%table(ix, iy+1) *
dx * dy
349 fxy11 = fxy_t%table(ix+1, iy+1) *
dx * dy
350 val = h0x*h0y*f00 + h2x*h0y*f10 + h0x*h2y*f01 + h2x*h2y*f11 &
351 + h1x*h0y*fx00 + h3x*h0y*fx10 + h1x*h2y*fx01 + h3x*h2y*fx11 &
352 + h0x*h1y*fy00 + h2x*h1y*fy10 + h0x*h3y*fy01 + h2x*h3y*fy11 &
353 + h1x*h1y*fxy00 + h3x*h1y*fxy10 + h1x*h3y*fxy01 + h3x*h3y*fxy11
354 end function contract_value
363 log_nH_code, log_p_nH_code)
result(ratio)
369 double precision,
intent(in) :: log_nh_code, log_p_nh_code
370 double precision :: log_e_nh_cgs, log_e_nh_code
371 call bicubic_hermite_eval(eintp, eintp_x, eintp_y, eintp_xy, &
372 log_nh_code, log_p_nh_code, log_e_nh_cgs)
374 ratio = 10.0d0**(log_e_nh_code - log_p_nh_code)
379 log_nH_code, log_p_nH_code) &
382 double precision,
intent(in) :: log_nh_code, log_p_nh_code
383 call bicubic_hermite_eval(g1p, g1p_x, g1p_y, g1p_xy, &
384 log_nh_code, log_p_nh_code, g1)
390 log_nH_code, log_T_code) &
391 result(log_e_nh_code)
395 double precision,
intent(in) :: log_nh_code, log_t_code
396 double precision :: log_e_nh_cgs
397 call bicubic_hermite_eval(eintt, eintt_x, eintt_y, eintt_xy, &
398 log_nh_code, log_t_code, log_e_nh_cgs)
405 subroutine entropy_table_prepare(tc)
413 end subroutine entropy_table_prepare
416 subroutine entropy_shift_prepare(tc, axis2_is_T)
418 logical,
intent(in) :: axis2_is_t
424 call entropy_table_prepare(tc)
425 end subroutine entropy_shift_prepare
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...
Interpolation kernels for the EoS tables (pure math; no EoS state).
subroutine, public precompute_step_inv(tc)
Entropy-method LTE EoS: every query is ONE bicubic Hermite evaluation.
double precision function, public entropy_eint_from_nh_t(eintt, eintt_x, eintt_y, eintt_xy, log_nh_code, log_t_code)
Inverse: log10(eint/nH) from (log nH, log T). Single bicubic Hermite eval of the eintT table.
pure double precision function, public entropy_p_nh_from_eint(pfwd, pfwd_x, pfwd_y, pfwd_xy, log_nh_code, log_e_nh_code)
double precision function, public entropy_t_from_nh_eint(tfwd, tfwd_x, tfwd_y, tfwd_xy, log_nh_code, log_e_nh_code)
Public wrappers – code-unit out.
subroutine, public finalise_entropy_lte()
Entropy-method finalise: shift each loaded table's axes from CGS to code units and run the standard p...
double precision function, public entropy_gamma1_from_nh_p(g1p, g1p_x, g1p_y, g1p_xy, log_nh_code, log_p_nh_code)
Inverse: Gamma_1 from (log nH, log p/nH). Bicubic Hermite of g1p.
subroutine, public entropy_t_and_y_from_nh_eint(tfwd, tfwd_x, tfwd_y, tfwd_xy, neonh, neonh_x, neonh_y, neonh_xy, log_nh_code, log_e_nh_code, t_code, y_out)
Forward: T and y from (log nH, log eint/nH) – combined for the update_eos_LTE hot path that needs bot...
double precision function, public entropy_y_from_nh_eint(neonh, neonh_x, neonh_y, neonh_xy, log_nh_code, log_e_nh_code)
Forward: ne/nH from (log nH, log eint/nH). Single bicubic Hermite eval of the neOnH table.
double precision function, public entropy_eint_from_nh_p(eintp, eintp_x, eintp_y, eintp_xy, log_nh_code, log_p_nh_code)
Inverse: log10(eint/nH) from (log nH, log p/nH). Single bicubic Hermite eval of the eintP table....
subroutine, public load_entropy_lte()
Forward (log nH, log eint/nH) -> thermodynamic state.
Shared LTE lookup-table infrastructure (build/IO; not on the hot path).
subroutine, public eos_validate_table(tc, name)
Defensive consistency check for one table after init. Aborts with a diagnostic message if any silent-...
subroutine, public load_tables_lte(fieldname)
Read one named table file into its eos% container. The filename encodes the composition (H or HHe) an...
subroutine, public shift_axis_to_code(tc)
Shift a table's (log_nH, log_eint/nH) axes – and adaptive node arrays if present – from CGS storage t...
subroutine, public shift_axis_to_code_t(tc)
subroutine, public ensure_axis_nodes(tc)
Ensure tcvar1_nodes / tcvar2_nodes are allocated and populated so that build_*_table routines and oth...
subroutine, public eos_build_guards(tc)
Build guard (bucket) arrays so that adaptive index lookup is O(1). No-op for uniform tables....
subroutine, public precompute_fi_bypass_constants()
This module contains definitions of global parameters and variables and some generic functions/subrou...
double precision unit_numberdensity
Physical scaling factor for number density.
double precision unit_pressure
Physical scaling factor for pressure.
integer mype
The rank of the current MPI task.
double precision unit_temperature
Physical scaling factor for temperature.
double precision, dimension(:,:), allocatable dx
spatial steps for all dimensions at all levels