48 select case (
eos%method_id)
60 eos%update_eos => update_eos_lte
62 eos%get_temperature_from_eint => get_temperature_from_eint_lte
63 eos%get_Te => get_te_lte
66 eos%get_Rfactor => rfactor_from_lte
67 select case (
eos%method_id)
75 subroutine update_eos_lte(ixI^L, ixO^L, w, x)
78 integer,
intent(in) :: ixi^
l,ixo^
l
79 double precision,
intent(in) :: x(ixi^s,1:
ndim)
80 double precision,
intent(inout) :: w(ixi^s,1:nw)
82 double precision :: wlocal(ixi^s,1:nw)
83 double precision :: deltaefactor(ixi^s)
84 double precision :: prev_y(ixi^s), new_y(ixi^s)
85 double precision :: pth(ixi^s)
86 double precision :: nh_in(ixi^s), nh(ixi^s), eint_in(ixi^s)
87 double precision :: rfactor_fi
88 double precision :: yy, eint_nh_floor
89 double precision :: time0
94 wlocal(ixi^s,1:nw)=w(ixi^s,1:nw)
97 pth(ixo^s) =
eos%gamma_minus_1 * wlocal(ixo^s,iw_e)
99 call eos%get_nH(w, x, ixi^
l, ixo^
l, nh)
108 {
do ix^db=ixomin^db,ixomax^db\}
110 wlocal(ix^
d,iw_e) = max(wlocal(ix^
d,iw_e), eint_nh_floor)
113 nh_in(ixo^s) = dlog10(nh(ixo^s))
114 {
do ix^db=ixomin^db,ixomax^db\}
117 eint_nh_floor = nh(ix^
d) * 10.0d0**
eos%T%var2_min
118 if (wlocal(ix^
d,iw_e) < eint_nh_floor)
then
119 wlocal(ix^
d,iw_e) = eint_nh_floor
122 eint_in(ixo^s) = dlog10(wlocal(ixo^s,iw_e)) - nh_in(ixo^s)
127 rfactor_fi = eos%n_per_nH_FI / eos%nH2rhoFactor
129 {
do ix^db=ixomin^db,ixomax^db\}
130 if (wlocal(ix^d,iw_e) / w(ix^d,iw_rho) > eos%eint_rho_FI_threshold)
then
132 new_y(ix^d) = eos%neOnH_FI
135 w(ix^d,iw_te) = eos%gamma_minus_1 &
136 * (wlocal(ix^d,iw_e) - eos%eion_per_nH * nh(ix^d)) &
137 / (rfactor_fi * w(ix^d,iw_rho))
139 w(ix^d,iw_te) = pth(ix^d) / (nh(ix^d) * (1.0d0 + eos%He_abundance + new_y(ix^d)))
143 if (eos%method_id == eos_analytic)
then
145 call saha_t_from_nh_eint(nh(ix^d), &
146 wlocal(ix^d,iw_e) / nh(ix^d), &
151 if (.not. eos%ionE)
then
153 w(ix^d,iw_te) = pth(ix^d) / (nh(ix^d) * (1.0d0 + eos%He_abundance + new_y(ix^d)))
154 else if (eos%method_id == eos_entropy)
then
158 call t_and_y_from_nh_eint(nh_in(ix^d), eint_in(ix^d), &
162 if (eint_in(ix^d) < eos%T%var2_max)
then
163 call t_and_y_from_nh_eint(nh_in(ix^d), eint_in(ix^d), &
168 new_y(ix^d) = eos%neOnH_FI
169 w(ix^d,iw_te) = eos%gamma_minus_1 &
170 * (wlocal(ix^d,iw_e) - eos%eion_per_nH * nh(ix^d)) &
171 / (rfactor_fi * w(ix^d,iw_rho))
178 w(ixo^s,iw_ne) = new_y(ixo^s) * nh(ixo^s)
180 timeeos_update=timeeos_update+(mpi_wtime()-timeeos0)
182 end subroutine update_eos_lte
191 subroutine rfactor_from_lte(w,x,ixI^L,ixO^L,Rfactor)
193 integer,
intent(in) :: ixi^
l, ixo^
l
194 double precision,
intent(in) :: w(ixi^s,1:nw)
195 double precision,
intent(in) :: x(ixi^s,1:
ndim)
196 double precision,
intent(out):: rfactor(ixi^s)
198 double precision :: y_nh
201 {
do ix^db=ixomin^db,ixomax^db\}
202 y_nh = w(ix^
d, iw_ne) * eos%nH2rhoFactor / w(ix^
d, iw_rho)
203 rfactor(ix^
d) = (1.0d0 + eos%He_abundance + y_nh) / eos%nH2rhoFactor
206 end subroutine rfactor_from_lte
215 subroutine get_te_lte(w,x,ixI^L,ixO^L,T)
217 integer,
intent(in) :: ixi^
l, ixo^
l
218 double precision,
intent(in) :: w(ixi^s,1:nw)
219 double precision,
intent(in) :: x(ixi^s,1:
ndim)
220 double precision,
intent(out) :: t(ixi^s)
222 t(ixo^s) = w(ixo^s,iw_te)
224 end subroutine get_te_lte
226 subroutine get_temperature_from_eint_lte(w, x, ixI^L, ixO^L, res)
230 integer,
intent(in) :: ixi^l,ixo^l
231 double precision,
intent(in) :: x(ixi^s,1:ndim)
232 double precision,
intent(in) :: w(ixi^s,1:nw)
233 double precision,
intent(out) :: res(ixi^s)
235 double precision :: nh(ixi^s),nh_in(ixi^s), eint_in(ixi^s)
236 double precision :: rfactor(ixi^s), rfactor_fi, t_loc, y_loc
239 timeeos0 = mpi_wtime()
241 rfactor_fi = eos%n_per_nH_FI / (1.0d0 + 4.0d0*eos%He_abundance)
243 call eos%get_nH(w, x, ixi^l, ixo^l, nh)
244 nh_in(ixo^s) = dlog10(nh(ixo^s))
245 eint_in(ixo^s) = dlog10(w(ixo^s,iw_e)) - nh_in(ixo^s)
247 {
do ix^db=ixomin^db,ixomax^db\}
248 if (w(ix^d,iw_e) / w(ix^d,iw_rho) > eos%eint_rho_FI_threshold)
then
250 res(ix^d) = eos%gamma_minus_1 &
251 * (w(ix^d,iw_e) - eos%eion_per_nH * nh(ix^d)) &
252 / (rfactor_fi * w(ix^d,iw_rho))
253 else if (eos%method_id == eos_analytic)
then
254 call saha_t_from_nh_eint(nh(ix^d), &
255 w(ix^d,iw_e) / nh(ix^d), t_loc, y_loc)
262 timeeos_tfromei=timeeos_tfromei+(mpi_wtime()-timeeos0)
263 end subroutine get_temperature_from_eint_lte
276 integer,
intent(in) :: ixi^l,ixo^l
277 double precision,
intent(in) :: x(ixi^s,1:ndim)
278 double precision,
intent(in) :: w(ixi^s,1:nw)
279 double precision,
intent(out) :: res(ixi^s)
281 double precision :: inv_rfactor_fi, eion_rho_inv
282 double precision :: log_nh_val, log_eint_nh_val
283 double precision :: fx, fy, rx, ry, nh_loc, t_loc, y_loc
284 integer :: jx, jy, jx1, jy1, ix^d
285 double precision,
parameter :: ln10 = 2.302585092994046d0
287 if (eos%type_id /= eos_type_lte)
call mpistop(
"get_temperature_from_eint_fast_LTE called outside its eos_type (LTE)")
288 timeeos0 = mpi_wtime()
291 inv_rfactor_fi = (1.0d0 + 4.0d0*eos%He_abundance) / eos%n_per_nH_FI
292 eion_rho_inv = eos%eion_per_nH / eos%nH2rhoFactor
296 res(ixo^s) = eos%gamma_minus_1 * inv_rfactor_fi &
297 * (w(ixo^s,iw_e) - eion_rho_inv * w(ixo^s,iw_rho)) &
301 {
do ix^db=ixomin^db,ixomax^db\}
302 if (w(ix^d,iw_e) <= eos%eint_rho_FI_threshold * w(ix^d,iw_rho))
then
303 if (eos%method_id == eos_analytic)
then
304 nh_loc = w(ix^d, iw_rho) / eos%nH2rhoFactor
305 call saha_t_from_nh_eint(nh_loc, &
306 w(ix^d,iw_e) / nh_loc, t_loc, y_loc)
308 else if (eos%method_id == eos_entropy)
then
309 if (iw_log_nh > 0)
then
310 log_nh_val = block%wextra(ix^d, iw_log_nh)
312 log_nh_val = dlog10(w(ix^d, iw_rho) / eos%nH2rhoFactor)
314 log_eint_nh_val = dlog10(w(ix^d, iw_e)) - log_nh_val
316 eos%Tfwd_y, eos%Tfwd_xy, log_nh_val, log_eint_nh_val)
318 if (iw_log_nh > 0)
then
319 log_nh_val = block%wextra(ix^d, iw_log_nh)
321 log_nh_val = dlog10(w(ix^d, iw_rho) / eos%nH2rhoFactor)
323 log_eint_nh_val = dlog10(w(ix^d, iw_e)) - log_nh_val
325 if (eos%T%is_uniform)
then
327 ry = max(0.0d0, min((log_nh_val - eos%T%var1_min) * eos%T%step_inv_1, &
329 rx = max(0.0d0, min((log_eint_nh_val - eos%T%var2_min) * eos%T%step_inv_2, &
331 jy = int(ry); jx = int(rx)
332 jy1 = min(jy+1, eos%T%dim1-1)
333 jx1 = min(jx+1, eos%T%dim2-1)
334 fy = ry - dble(jy); fx = rx - dble(jx)
335 res(ix^d) = dexp(ln10 * ( &
336 (1.0d0-fy)*((1.0d0-fx)*eos%T%table(jy+1,jx+1) &
337 + fx *eos%T%table(jy+1,jx1+1)) &
338 + fy *((1.0d0-fx)*eos%T%table(jy1+1,jx+1) &
339 + fx *eos%T%table(jy1+1,jx1+1))))
344 res(ix^d) = dexp(ln10 * bilinear_lookup( &
345 log_nh_val, log_eint_nh_val, eos%T))
351 timeeos_tfromei = timeeos_tfromei + (mpi_wtime()-timeeos0)
365 double precision,
intent(in) :: nh, eint_nh
366 double precision,
parameter :: ln10 = 2.302585092994046d0
367 double precision :: t_loc, y_loc, eint_rho
369 if (eos%type_id /= eos_type_lte)
call mpistop(
"y_from_nH_eint called outside its eos_type (LTE)")
370 if (eos%method_id == eos_analytic)
then
372 eint_rho = 10.0d0**eint_nh / eos%nH2rhoFactor
373 if (eint_rho > eos%eint_rho_FI_threshold)
then
374 result_val = eos%neOnH_FI
377 call saha_t_from_nh_eint(10.0d0**nh, 10.0d0**eint_nh, t_loc, y_loc)
379 else if (eos%method_id == eos_entropy)
then
382 eos%neOnH_y, eos%neOnH_xy, nh, eint_nh)
384 result_val = dexp(ln10 * bicubic_lookup(nh, eint_nh, eos%neOnH))
392 double precision,
intent(in) :: nh, eint_nh
393 double precision,
parameter :: ln10 = 2.302585092994046d0
394 double precision :: t_loc, y_loc, eint_rho, rfactor_fi
396 if (eos%type_id /= eos_type_lte)
call mpistop(
"T_from_nH_eint called outside its eos_type (LTE)")
397 if (eos%method_id == eos_analytic)
then
399 eint_rho = 10.0d0**eint_nh / eos%nH2rhoFactor
400 if (eint_rho > eos%eint_rho_FI_threshold)
then
401 rfactor_fi = eos%n_per_nH_FI / (1.0d0 + 4.0d0*eos%He_abundance)
402 result_val = eos%gamma_minus_1 &
403 * (10.0d0**eint_nh - eos%eion_per_nH) / rfactor_fi
406 call saha_t_from_nh_eint(10.0d0**nh, 10.0d0**eint_nh, t_loc, y_loc)
408 else if (eos%method_id == eos_entropy)
then
410 eos%Tfwd_y, eos%Tfwd_xy, nh, eint_nh)
412 result_val = dexp(ln10 * bicubic_lookup(nh, eint_nh, eos%T))
419 subroutine t_and_y_from_nh_eint(log_nH, log_eint_nH, T_out, y_out)
421 double precision,
intent(in) :: log_nh, log_eint_nh
422 double precision,
intent(out) :: t_out, y_out
423 double precision,
parameter :: ln10 = 2.302585092994046d0
424 double precision :: results(3)
426 if (eos%method_id == eos_analytic)
then
427 call saha_t_from_nh_eint(10.0d0**log_nh, 10.0d0**log_eint_nh, t_out, y_out)
428 else if (eos%method_id == eos_entropy)
then
430 eos%Tfwd_y, eos%Tfwd_xy, &
431 eos%neOnH, eos%neOnH_x, eos%neOnH_y, eos%neOnH_xy, &
432 log_nh, log_eint_nh, t_out, y_out)
433 else if (
allocated(eos%table_eint_il))
then
436 if (eos%T%is_uniform)
then
437 call interp_pchip_interleaved(log_nh, log_eint_nh, &
438 eos%table_eint_il, 3, eos%T%dim2, eos%T%dim1, &
439 eos%T%var1_min, eos%T%var1_max, &
440 eos%T%var2_min, eos%T%var2_max, results)
442 call interp_pchip_interleaved_nu(log_nh, log_eint_nh, &
443 eos%table_eint_il, 3, eos%T%dim2, eos%T%dim1, &
444 eos%T%var1_nodes, eos%T%var2_nodes, &
445 eos%T%guard_1, eos%T%guard_M_1, eos%T%guard_scale_1, &
446 eos%T%guard_2, eos%T%guard_M_2, eos%T%guard_scale_2, &
449 t_out = dexp(ln10 * results(1))
450 y_out = dexp(ln10 * results(2))
453 t_out = dexp(ln10 * bicubic_lookup(log_nh, log_eint_nh, eos%T))
454 y_out = dexp(ln10 * bicubic_lookup(log_nh, log_eint_nh, eos%neOnH))
456 end subroutine t_and_y_from_nh_eint
462 double precision,
intent(in) :: nh, ponh
463 double precision :: nh_code, p_code, t_loc, y_loc, eint_nh_loc, p_rho
465 if (eos%type_id /= eos_type_lte)
call mpistop(
"p2eint_from_nH_p called outside its eos_type (LTE)")
466 if (eos%method_id == eos_analytic)
then
468 p_code = nh_code * 10.0d0**ponh
470 p_rho = p_code / (nh_code * eos%nH2rhoFactor)
471 if (p_rho > eos%p_rho_FI_threshold)
then
472 result_val = eos%inv_gamma_minus_1 &
473 + eos%eion_per_nH * nh_code / p_code
476 call saha_state_from_nh_p(nh_code, p_code, t_loc, y_loc, eint_nh_loc)
477 result_val = eint_nh_loc * nh_code / p_code
478 else if (eos%method_id == eos_entropy)
then
481 eos%eintP_y, eos%eintP_xy, nh, ponh)
483 result_val = bicubic_lookup(nh, ponh, eos%p2eint)
494 double precision,
intent(in) :: log_nh, log_p_nh
495 if (eos%type_id /= eos_type_lte)
call mpistop(
"gamma1_from_nH_p called outside its eos_type (LTE)")
496 if (eos%method_id == eos_entropy)
then
500 eos%g1p_xy, log_nh, log_p_nh)
502 g1 = bicubic_lookup(log_nh, log_p_nh, eos%gamma1_p)
508 double precision function log_p_from_nh_eint(log_nH, log_eint_nH)
result(lp)
509 double precision,
intent(in) :: log_nh, log_eint_nh
510 lp = bicubic_lookup(log_nh, log_eint_nh, eos%log_p)
511 end function log_p_from_nh_eint
517 double precision,
intent(in) :: log_nh, log_eint_nh
518 double precision,
parameter :: ln10 = 2.302585092994046d0
519 double precision :: t_loc, y_loc
521 if (eos%type_id /= eos_type_lte)
call mpistop(
"p_nH_from_eint called outside its eos_type (LTE)")
522 if (eos%method_id == eos_analytic)
then
523 call saha_t_from_nh_eint(10.0d0**log_nh, 10.0d0**log_eint_nh, t_loc, y_loc)
524 p_nh = (1.0d0 + eos%He_abundance + y_loc) * t_loc
525 else if (eos%method_id == eos_entropy)
then
527 eos%pfwd_xy, log_nh, log_eint_nh)
529 p_nh = dexp(ln10 * bicubic_lookup(log_nh, log_eint_nh, eos%p_over_nH))
538 double precision,
intent(in) :: log_nh, log_t
539 double precision,
parameter :: ln10 = 2.302585092994046d0
540 double precision :: log_e_nh
542 if (eos%type_id /= eos_type_lte)
call mpistop(
"eint_nH_from_T called outside its eos_type (LTE)")
543 if (eos%method_id == eos_entropy)
then
547 eos%eintT_y, eos%eintT_xy, log_nh, log_t)
548 eint_nh = 10.0d0**log_e_nh
549 else if (
allocated(eos%eint_from_T%table))
then
550 eint_nh = dexp(ln10 * bicubic_lookup(log_nh, log_t, eos%eint_from_T))
552 eint_nh = saha_eint_from_nh_t(10.0d0**log_nh, 10.0d0**log_t)
570 subroutine log_p_bisect_cached(log_nH, log_p_target, &
571 log_eint_lo, log_eint_hi, max_iter, log_eint_result)
573 double precision,
intent(in) :: log_nh, log_p_target
574 double precision,
intent(inout) :: log_eint_lo, log_eint_hi
575 integer,
intent(in) :: max_iter
576 double precision,
intent(out) :: log_eint_result
578 integer :: nx, ny, ix, iy, iter, ii
579 integer :: i0, i1, i2, i3, j0, j1, j2, j3
580 double precision :: tx, ty, rx, ry
581 double precision :: xstep_inv, ystep_inv
582 double precision :: vmin_x, vmax_x, vmin_y, vmax_y
583 double precision :: log_eint_mid, log_p_eval
587 double precision :: tv(4,4)
593 is_unif = eos%log_p%is_uniform
596 vmin_x = eos%log_p%var2_min
597 vmax_x = eos%log_p%var2_max
598 vmin_y = eos%log_p%var1_min
599 vmax_y = eos%log_p%var1_max
600 xstep_inv = dble(nx-1) / (vmax_x - vmin_x)
601 ystep_inv = dble(ny-1) / (vmax_y - vmin_y)
606 ry = (log_nh - vmin_y) * ystep_inv
607 ry = max(0.0d0, min(ry, dble(ny-1)))
612 if (log_nh <= eos%log_p%var1_nodes(1))
then
614 else if (log_nh >= eos%log_p%var1_nodes(ny))
then
615 iy = ny - 2; ty = 1.0d0
617 ii = find_index_guard(eos%log_p%var1_nodes, ny, log_nh, &
618 eos%log_p%guard_1, eos%log_p%guard_M_1, eos%log_p%guard_scale_1)
619 iy = max(0, min(ii - 2, ny - 2))
620 ty = (log_nh - eos%log_p%var1_nodes(iy+1)) &
621 / (eos%log_p%var1_nodes(iy+2) - eos%log_p%var1_nodes(iy+1))
622 ty = max(0.0d0, min(ty, 1.0d0))
627 j0 = max(0, min(ny-1, iy-1))
628 j1 = max(0, min(ny-1, iy ))
629 j2 = max(0, min(ny-1, iy+1))
630 j3 = max(0, min(ny-1, iy+2))
634 do iter = 1, max_iter
635 log_eint_mid = 0.5d0 * (log_eint_lo + log_eint_hi)
639 rx = (log_eint_mid - vmin_x) * xstep_inv
640 rx = max(0.0d0, min(rx, dble(nx-1)))
645 if (log_eint_mid <= eos%log_p%var2_nodes(1))
then
647 else if (log_eint_mid >= eos%log_p%var2_nodes(nx))
then
648 ix = nx - 2; tx = 1.0d0
650 ii = find_index_guard(eos%log_p%var2_nodes, nx, log_eint_mid, &
651 eos%log_p%guard_2, eos%log_p%guard_M_2, eos%log_p%guard_scale_2)
652 ix = max(0, min(ii - 2, nx - 2))
653 tx = (log_eint_mid - eos%log_p%var2_nodes(ix+1)) &
654 / (eos%log_p%var2_nodes(ix+2) - eos%log_p%var2_nodes(ix+1))
655 tx = max(0.0d0, min(tx, 1.0d0))
660 if (ix /= ix_cached)
then
661 i0 = max(0, min(nx-1, ix-1))
662 i1 = max(0, min(nx-1, ix ))
663 i2 = max(0, min(nx-1, ix+1))
664 i3 = max(0, min(nx-1, ix+2))
666 tv(1,1) = eos%log_p%table(j0+1, i0+1)
667 tv(1,2) = eos%log_p%table(j0+1, i1+1)
668 tv(1,3) = eos%log_p%table(j0+1, i2+1)
669 tv(1,4) = eos%log_p%table(j0+1, i3+1)
670 tv(2,1) = eos%log_p%table(j1+1, i0+1)
671 tv(2,2) = eos%log_p%table(j1+1, i1+1)
672 tv(2,3) = eos%log_p%table(j1+1, i2+1)
673 tv(2,4) = eos%log_p%table(j1+1, i3+1)
674 tv(3,1) = eos%log_p%table(j2+1, i0+1)
675 tv(3,2) = eos%log_p%table(j2+1, i1+1)
676 tv(3,3) = eos%log_p%table(j2+1, i2+1)
677 tv(3,4) = eos%log_p%table(j2+1, i3+1)
678 tv(4,1) = eos%log_p%table(j3+1, i0+1)
679 tv(4,2) = eos%log_p%table(j3+1, i1+1)
680 tv(4,3) = eos%log_p%table(j3+1, i2+1)
681 tv(4,4) = eos%log_p%table(j3+1, i3+1)
687 log_p_eval = pchip_2d_from_cache(tv, tx, ty)
689 if (log_p_eval < log_p_target)
then
690 log_eint_lo = log_eint_mid
692 log_eint_hi = log_eint_mid
695 if (dabs(log_eint_hi - log_eint_lo) < 1.0d-14)
exit
698 log_eint_result = 0.5d0 * (log_eint_lo + log_eint_hi)
702 pure double precision function pchip_1d(p0, p1, p2, p3, t)
result(v)
703 double precision,
intent(in) :: p0, p1, p2, p3, t
704 double precision :: d0, d1, d2, m1, m2, s, a1, a2, lim
705 double precision :: tt, ttt, h00, h10, h01, h11
707 d0 = p1 - p0; d1 = p2 - p1; d2 = p3 - p2
709 if (d1 == 0.0d0)
then
710 m1 = 0.0d0; m2 = 0.0d0
712 if (d0*d1 <= 0.0d0)
then
715 m1 = 2.0d0*d0*d1 / (d0 + d1)
717 if (d1*d2 <= 0.0d0)
then
720 m2 = 2.0d0*d1*d2 / (d1 + d2)
724 if (a1 < 0.0d0) a1 = 0.0d0
725 if (a2 < 0.0d0) a2 = 0.0d0
727 if (a1 > lim) a1 = lim
728 if (a2 > lim) a2 = lim
733 h00 = 2.0d0*ttt - 3.0d0*tt + 1.0d0
734 h10 = ttt - 2.0d0*tt + t
735 h01 = -2.0d0*ttt + 3.0d0*tt
737 v = h00*p1 + h10*m1 + h01*p2 + h11*m2
740 pure double precision function pchip_2d_from_cache(c, tx, ty)
result(z)
741 double precision,
intent(in) :: c(4,4), tx, ty
742 double precision :: g0, g1, g2, g3
744 g0 =
pchip_1d(c(1,1), c(1,2), c(1,3), c(1,4), tx)
745 g1 =
pchip_1d(c(2,1), c(2,2), c(2,3), c(2,4), tx)
746 g2 =
pchip_1d(c(3,1), c(3,2), c(3,3), c(3,4), tx)
747 g3 =
pchip_1d(c(4,1), c(4,2), c(4,3), c(4,4), tx)
750 end function pchip_2d_from_cache
752 end subroutine log_p_bisect_cached
759 double precision,
intent(in) :: log_nh_val, log_p_val
760 double precision,
intent(out) :: log_eint_nh_out
762 double precision :: log_p_target, p2eint_ratio, log_eint_guess
763 double precision :: log_p_at_guess, log_eint_lo, log_eint_hi
764 double precision :: f_bracket, margin
767 if (eos%type_id /= eos_type_lte)
call mpistop(
"eint_from_p_bisect called outside its eos_type (LTE)")
768 log_p_target = log_p_val - log_nh_val
772 log_eint_guess = dlog10(p2eint_ratio) + log_p_target
774 log_eint_guess = max(log_eint_guess, eos%log_p%var2_min)
775 log_eint_guess = min(log_eint_guess, eos%log_p%var2_max)
777 log_p_at_guess = log_p_from_nh_eint(log_nh_val, log_eint_guess)
781 if (log_p_at_guess < log_p_target)
then
782 log_eint_lo = log_eint_guess
783 log_eint_hi = min(log_eint_guess + margin, eos%log_p%var2_max)
784 f_bracket = log_p_from_nh_eint(log_nh_val, log_eint_hi) - log_p_target
786 log_eint_lo = max(log_eint_guess - margin, eos%log_p%var2_min)
787 log_eint_hi = log_eint_guess
788 f_bracket = -(log_p_from_nh_eint(log_nh_val, log_eint_lo) - log_p_target)
791 if (f_bracket >= 0.0d0)
then
794 log_eint_lo = eos%log_p%var2_min
795 log_eint_hi = eos%log_p%var2_max
799 call log_p_bisect_cached(log_nh_val, log_p_target, &
800 log_eint_lo, log_eint_hi, max_iter, log_eint_nh_out)
814 integer,
intent(out) :: n_nh
815 double precision,
intent(out) :: lg_nh_min, lg_nh_max
817 if (eos%type_id /= eos_type_lte)
call mpistop(
"eos_get_eintT_grid called outside its eos_type (LTE)")
818 if (
allocated(eos%eint_from_T%table))
then
819 n_nh = eos%eint_from_T%dim1
820 lg_nh_min = eos%eint_from_T%var1_min
821 lg_nh_max = eos%eint_from_T%var1_max
822 else if (
allocated(eos%eintT%table))
then
823 n_nh = eos%eintT%dim1
824 lg_nh_min = eos%eintT%var1_min
825 lg_nh_max = eos%eintT%var1_max
pure double precision function pchip_1d(p0, p1, p2, p3, t)
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
EoS state container – the single thermodynamic authority for AMRVAC.
integer, parameter, public eos_analytic
integer, parameter, public eos_entropy
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).
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.
Analytic H-only Saha EoS (eos_method == 'analytic').
subroutine, public finalise_analytic_lte()
Analytic-method finalise (H-only Saha): no table unit conversion needed; build the Gamma1 table only ...
subroutine, public load_analytic_lte()
Analytic-method load: no binary tables (on-the-fly Saha solve); just announce the method.
'state' method (eos_method='state', legacy 'tables') of the LTE EoS family.
subroutine, public finalise_state_lte()
Table-based method finalise: shift the loaded T/neOnH (and ionE-derived) tables to code units,...
subroutine, public load_state_lte()
state arms of the eos_init / eos_finalise dispatchers (mod_eos_LTE)
Shared LTE lookup-table infrastructure (build/IO; not on the hot path).
LTE (Saha-table) EoS kernels and finalise for the eos% family.
double precision function, public p_nh_from_eint(log_nh, log_eint_nh)
p/nH from (log10 nH, log10 eint/nH) in code units. Returns (1+He+y)*T directly – single lookup replac...
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 ...
subroutine, public eos_finalise_lte()
LTE arm of eos_finalise: wire the LTE runtime pointer targets, then dispatch on eos_method to the per...
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 gamma1_from_nh_p(log_nh, log_p_nh)
Gamma_1 from pressure-indexed table: (log10 nH, log10 p/nH) -> Gamma_1. For 'entropy' the conversion ...
subroutine, public eos_init_lte()
update_eos_LTE, get_Te_LTE, get_temperature_from_eint_LTE and Rfactor_from_LTE are PRIVATE: all bound...
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...
Shared EoS accessors (EoS-type-agnostic) for the eos% family.
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer, parameter ndim
Number of spatial dimensions for grid variables.
double precision, dimension(:), allocatable, parameter d
double precision unit_temperature
Physical scaling factor for temperature.
A Fortran 90 module for creating 1D and 2D lookup tables. These tables can be used to efficiently int...
pure integer function, public find_index_bsearch(list, val)
Binary search of sorted list for the smallest ix such that list(ix) >= val. On failure,...
This module defines the procedures of a physics module. It contains function pointers for the various...
procedure(sub_e_to_ei), pointer phys_e_to_ei
double precision timeeos0