33 pure double precision function pchip_interval(p0, p1, p2, p3, t)
result(v)
34 double precision,
intent(in) :: p0, p1, p2, p3, t
35 double precision :: d0, d1, d2, m1, m2
36 double precision :: tt, ttt, h00, h10, h01, h11
37 double precision :: s, a1, a2, lim
47 if (d0*d1 <= 0.0d0)
then
50 m1 = 2.0d0*d0*d1 / (d0 + d1)
52 if (d1*d2 <= 0.0d0)
then
55 m2 = 2.0d0*d1*d2 / (d1 + d2)
60 if (a1 < 0.0d0) a1 = 0.0d0
61 if (a2 < 0.0d0) a2 = 0.0d0
63 if (a1 > lim) a1 = lim
64 if (a2 > lim) a2 = lim
71 h00 = 2.0d0*ttt - 3.0d0*tt + 1.0d0
72 h10 = ttt - 2.0d0*tt + t
73 h01 = -2.0d0*ttt + 3.0d0*tt
76 v = h00*p1 + h10*m1 + h01*p2 + h11*m2
77 end function pchip_interval
85 double precision,
intent(in) :: nodes(n), val, scale_m
86 integer,
intent(in) :: n, m
87 integer,
intent(in) :: guard(m)
90 k = 1 + min(m-1, max(0, int(floor((val - nodes(1)) * scale_m))))
92 do while (ix < n .and. nodes(ix) < val)
101 double precision,
intent(in) :: vary, varx
102 integer,
intent(in) :: nx, ny
103 double precision,
intent(in) :: table(ny, nx)
104 double precision,
intent(in) :: vmin_y, vmax_y, vmin_x, vmax_x
106 double precision :: fx, fy, tx, ty, rx, ry, xstep_inv, ystep_inv
107 integer :: ix, iy, ix1, iy1
109 xstep_inv = dble(nx-1) / (vmax_x - vmin_x)
110 ystep_inv = dble(ny-1) / (vmax_y - vmin_y)
113 fx = (varx - vmin_x) * xstep_inv
114 fy = (vary - vmin_y) * ystep_inv
117 rx = max(0.0d0, min(fx, dble(nx-1)))
118 ry = max(0.0d0, min(fy, dble(ny-1)))
123 ix1 = min(ix+1, nx-1)
124 iy1 = min(iy+1, ny-1)
129 z = (1.0d0-ty) * ((1.0d0-tx)*table(iy+1, ix+1) + tx*table(iy+1, ix1+1)) &
130 + ty * ((1.0d0-tx)*table(iy1+1,ix+1) + tx*table(iy1+1,ix1+1))
133 pure double precision function interp_clamped_monotone_bicubic_table( &
134 vary, varx, table, nx, ny, vmin_y, vmax_y, vmin_x, vmax_x)
result(z)
145 double precision,
intent(in) :: vary, varx
146 integer,
intent(in) :: nx, ny
147 double precision,
intent(in) :: table(ny, nx)
148 double precision,
intent(in) :: vmin_y, vmax_y, vmin_x, vmax_x
150 double precision :: fx, fy, rx, ry, tx, ty, xstep_inv, ystep_inv
153 double precision :: g0, g1, g2, g3
155 xstep_inv = dble(nx-1) / (vmax_x - vmin_x)
156 ystep_inv = dble(ny-1) / (vmax_y - vmin_y)
158 fx = (varx - vmin_x) * xstep_inv
159 fy = (vary - vmin_y) * ystep_inv
161 rx = max(0.0d0, min(fx, dble(nx-1)))
162 ry = max(0.0d0, min(fy, dble(ny-1)))
171 g0 = x_interp_row(iy-1, ix, tx)
172 g1 = x_interp_row(iy , ix, tx)
173 g2 = x_interp_row(iy+1, ix, tx)
174 g3 = x_interp_row(iy+2, ix, tx)
177 z = y_interp_from4(g0, g1, g2, g3, ty)
181 pure integer function clampi(i, lo, hi)
result(o)
182 integer,
intent(in) :: i, lo, hi
183 o = max(lo, min(hi, i))
186 pure double precision function x_interp_row(j, i, t)
result(v)
189 integer,
intent(in) :: j, i
190 double precision,
intent(in) :: t
191 integer :: i0, i1, i2, i3, jj
192 double precision :: p0, p1, p2, p3
194 jj = clampi(j, 0, ny-1)
195 i0 = clampi(i-1, 0, nx-1)
196 i1 = clampi(i , 0, nx-1)
197 i2 = clampi(i+1, 0, nx-1)
198 i3 = clampi(i+2, 0, nx-1)
200 p0 = table(jj+1, i0+1)
201 p1 = table(jj+1, i1+1)
202 p2 = table(jj+1, i2+1)
203 p3 = table(jj+1, i3+1)
205 v = pchip_interval(p0, p1, p2, p3, t)
206 end function x_interp_row
208 pure double precision function y_interp_from4(v0, v1, v2, v3, t)
result(v)
210 double precision,
intent(in) :: v0, v1, v2, v3, t
211 v = pchip_interval(v0, v1, v2, v3, t)
212 end function y_interp_from4
214 end function interp_clamped_monotone_bicubic_table
221 double precision,
intent(in) :: var1, var2
223 if (tc%is_uniform)
then
230 z = interp_clamped_monotone_bicubic_table(var1, var2, tc%table, &
232 tc%var1_min, tc%var1_max, tc%var2_min, tc%var2_max)
234 z = interp_clamped_monotone_bicubic_table_nu(var1, var2, tc%table, &
235 tc%dim1, tc%dim2, tc%var1_nodes, tc%var2_nodes, &
236 tc%guard_1, tc%guard_M_1, tc%guard_scale_1, &
237 tc%guard_2, tc%guard_M_2, tc%guard_scale_2)
243 double precision,
intent(in) :: var1, var2
245 if (tc%is_uniform)
then
248 tc%var1_min, tc%var1_max, tc%var2_min, tc%var2_max)
250 z = interp_clamped_bilinear_table_nu(var1, var2, tc%table, &
251 tc%dim1, tc%dim2, tc%var1_nodes, tc%var2_nodes, &
252 tc%guard_1, tc%guard_M_1, tc%guard_scale_1, &
253 tc%guard_2, tc%guard_M_2, tc%guard_scale_2)
269 pure double precision function interp_clamped_bilinear_table_nu( &
270 var1, var2, table, dim1, dim2, var1_nodes, var2_nodes, &
271 guard_1, M_1, scale_1, guard_2, M_2, scale_2)
result(z)
272 double precision,
intent(in) :: var1, var2
273 integer,
intent(in) :: dim1, dim2
274 double precision,
intent(in) :: table(dim1, dim2)
275 double precision,
intent(in) :: var1_nodes(dim1), var2_nodes(dim2)
276 integer,
intent(in) :: m_1, m_2
277 double precision,
intent(in) :: scale_1, scale_2
278 integer,
intent(in) :: guard_1(m_1), guard_2(m_2)
280 integer :: i1, i2, i1p, i2p, ii
281 double precision :: t1, t2
284 if (var1 <= var1_nodes(1))
then
286 else if (var1 >= var1_nodes(dim1))
then
287 i1 = dim1 - 2; t1 = 1.0d0
290 i1 = max(0, min(ii - 2, dim1 - 2))
291 t1 = (var1 - var1_nodes(i1+1)) / (var1_nodes(i1+2) - var1_nodes(i1+1))
292 t1 = max(0.0d0, min(t1, 1.0d0))
296 if (var2 <= var2_nodes(1))
then
298 else if (var2 >= var2_nodes(dim2))
then
299 i2 = dim2 - 2; t2 = 1.0d0
302 i2 = max(0, min(ii - 2, dim2 - 2))
303 t2 = (var2 - var2_nodes(i2+1)) / (var2_nodes(i2+2) - var2_nodes(i2+1))
304 t2 = max(0.0d0, min(t2, 1.0d0))
307 i1p = min(i1+1, dim1-1)
308 i2p = min(i2+1, dim2-1)
310 z = (1.0d0-t2) * ((1.0d0-t1)*table(i1+1, i2+1) + t1*table(i1p+1, i2+1)) &
311 + t2 * ((1.0d0-t1)*table(i1+1, i2p+1) + t1*table(i1p+1, i2p+1))
312 end function interp_clamped_bilinear_table_nu
322 pure double precision function interp_clamped_monotone_bicubic_table_nu( &
323 var1, var2, table, dim1, dim2, var1_nodes, var2_nodes, &
324 guard_1, M_1, scale_1, guard_2, M_2, scale_2)
result(z)
325 double precision,
intent(in) :: var1, var2
326 integer,
intent(in) :: dim1, dim2
327 double precision,
intent(in) :: table(dim1, dim2)
328 double precision,
intent(in) :: var1_nodes(dim1), var2_nodes(dim2)
329 integer,
intent(in) :: m_1, m_2
330 double precision,
intent(in) :: scale_1, scale_2
331 integer,
intent(in) :: guard_1(m_1), guard_2(m_2)
333 integer :: i1, i2, ii
334 double precision :: t1, t2
335 double precision :: g0, g1, g2, g3
338 if (var1 <= var1_nodes(1))
then
340 else if (var1 >= var1_nodes(dim1))
then
341 i1 = dim1 - 2; t1 = 1.0d0
344 i1 = max(0, min(ii - 2, dim1 - 2))
345 t1 = (var1 - var1_nodes(i1+1)) / (var1_nodes(i1+2) - var1_nodes(i1+1))
346 t1 = max(0.0d0, min(t1, 1.0d0))
350 if (var2 <= var2_nodes(1))
then
352 else if (var2 >= var2_nodes(dim2))
then
353 i2 = dim2 - 2; t2 = 1.0d0
356 i2 = max(0, min(ii - 2, dim2 - 2))
357 t2 = (var2 - var2_nodes(i2+1)) / (var2_nodes(i2+2) - var2_nodes(i2+1))
358 t2 = max(0.0d0, min(t2, 1.0d0))
363 g0 = ax1_interp_col_nu(i2-1, i1, t1)
364 g1 = ax1_interp_col_nu(i2 , i1, t1)
365 g2 = ax1_interp_col_nu(i2+1, i1, t1)
366 g3 = ax1_interp_col_nu(i2+2, i1, t1)
368 z = pchip_interval(g0, g1, g2, g3, t2)
372 pure integer function clampi_nu(i, lo, hi)
result(o)
373 integer,
intent(in) :: i, lo, hi
374 o = max(lo, min(hi, i))
375 end function clampi_nu
377 pure double precision function ax1_interp_col_nu(j2, i1_cell, t)
result(v)
381 integer,
intent(in) :: j2, i1_cell
382 double precision,
intent(in) :: t
383 integer :: a0, a1, a2, a3, b
384 double precision :: p0, p1, p2, p3
386 b = clampi_nu(j2, 0, dim2-1)
387 a0 = clampi_nu(i1_cell-1, 0, dim1-1)
388 a1 = clampi_nu(i1_cell , 0, dim1-1)
389 a2 = clampi_nu(i1_cell+1, 0, dim1-1)
390 a3 = clampi_nu(i1_cell+2, 0, dim1-1)
392 p0 = table(a0+1, b+1)
393 p1 = table(a1+1, b+1)
394 p2 = table(a2+1, b+1)
395 p3 = table(a3+1, b+1)
397 v = pchip_interval(p0, p1, p2, p3, t)
398 end function ax1_interp_col_nu
400 end function interp_clamped_monotone_bicubic_table_nu
406 vmin_y, vmax_y, vmin_x, vmax_x, results)
407 double precision,
intent(in) :: vary, varx
408 integer,
intent(in) :: nq, nx, ny
409 double precision,
intent(in) :: table_il(nq, ny, nx)
410 double precision,
intent(in) :: vmin_y, vmax_y, vmin_x, vmax_x
411 double precision,
intent(out) :: results(nq)
413 double precision :: fx, fy, rx, ry, tx, ty, xstep_inv, ystep_inv
415 integer :: i0, i1, i2, i3, j0, j1, j2, j3
416 double precision :: g0(nq), g1(nq), g2(nq), g3(nq)
417 double precision :: p0, p1, p2, p3
419 xstep_inv = dble(nx-1) / (vmax_x - vmin_x)
420 ystep_inv = dble(ny-1) / (vmax_y - vmin_y)
422 fx = (varx - vmin_x) * xstep_inv
423 fy = (vary - vmin_y) * ystep_inv
425 rx = max(0.0d0, min(fx, dble(nx-1)))
426 ry = max(0.0d0, min(fy, dble(ny-1)))
428 ix = int(rx); iy = int(ry)
429 tx = rx - dble(ix); ty = ry - dble(iy)
432 i0 = max(0, min(nx-1, ix-1))
433 i1 = max(0, min(nx-1, ix))
434 i2 = max(0, min(nx-1, ix+1))
435 i3 = max(0, min(nx-1, ix+2))
439 j1 = max(0, min(ny-1, iy - 1 + j0))
441 p0 = table_il(q, j1+1, i0+1)
442 p1 = table_il(q, j1+1, i1+1)
443 p2 = table_il(q, j1+1, i2+1)
444 p3 = table_il(q, j1+1, i3+1)
446 case(0); g0(q) = pchip_interval(p0, p1, p2, p3, tx)
447 case(1); g1(q) = pchip_interval(p0, p1, p2, p3, tx)
448 case(2); g2(q) = pchip_interval(p0, p1, p2, p3, tx)
449 case(3); g3(q) = pchip_interval(p0, p1, p2, p3, tx)
456 results(q) = pchip_interval(g0(q), g1(q), g2(q), g3(q), ty)
470 var1_nodes, var2_nodes, &
471 guard_1, M_1, scale_1, guard_2, M_2, scale_2, results)
472 double precision,
intent(in) :: vary, varx
473 integer,
intent(in) :: nq, nx, ny
474 double precision,
intent(in) :: table_il(nq, ny, nx)
475 double precision,
intent(in) :: var1_nodes(ny), var2_nodes(nx)
476 integer,
intent(in) :: m_1, m_2
477 double precision,
intent(in) :: scale_1, scale_2
478 integer,
intent(in) :: guard_1(m_1), guard_2(m_2)
479 double precision,
intent(out) :: results(nq)
481 double precision :: tx, ty
482 integer :: ix, iy, q, ii
483 integer :: i0, i1, i2, i3, j0, j1, j2, j3
484 double precision :: g0(nq), g1(nq), g2(nq), g3(nq)
485 double precision :: p0, p1, p2, p3
488 if (vary <= var1_nodes(1))
then
490 else if (vary >= var1_nodes(ny))
then
491 iy = ny - 2; ty = 1.0d0
494 iy = max(0, min(ii - 2, ny - 2))
495 ty = (vary - var1_nodes(iy+1)) &
496 / (var1_nodes(iy+2) - var1_nodes(iy+1))
497 ty = max(0.0d0, min(ty, 1.0d0))
501 if (varx <= var2_nodes(1))
then
503 else if (varx >= var2_nodes(nx))
then
504 ix = nx - 2; tx = 1.0d0
507 ix = max(0, min(ii - 2, nx - 2))
508 tx = (varx - var2_nodes(ix+1)) &
509 / (var2_nodes(ix+2) - var2_nodes(ix+1))
510 tx = max(0.0d0, min(tx, 1.0d0))
513 i0 = max(0, min(nx-1, ix-1))
514 i1 = max(0, min(nx-1, ix))
515 i2 = max(0, min(nx-1, ix+1))
516 i3 = max(0, min(nx-1, ix+2))
520 j1 = max(0, min(ny-1, iy - 1 + j0))
522 p0 = table_il(q, j1+1, i0+1)
523 p1 = table_il(q, j1+1, i1+1)
524 p2 = table_il(q, j1+1, i2+1)
525 p3 = table_il(q, j1+1, i3+1)
527 case(0); g0(q) = pchip_interval(p0, p1, p2, p3, tx)
528 case(1); g1(q) = pchip_interval(p0, p1, p2, p3, tx)
529 case(2); g2(q) = pchip_interval(p0, p1, p2, p3, tx)
530 case(3); g3(q) = pchip_interval(p0, p1, p2, p3, tx)
536 results(q) = pchip_interval(g0(q), g1(q), g2(q), g3(q), ty)
543 if (
allocated(tc%table))
then
544 tc%step_inv_1 = dble(tc%dim1-1) / (tc%var1_max - tc%var1_min)
545 tc%step_inv_2 = dble(tc%dim2-1) / (tc%var2_max - tc%var2_min)
EoS state container – the single thermodynamic authority for AMRVAC.
Interpolation kernels for the EoS tables (pure math; no EoS state).
pure double precision function, public interp_clamped_bilinear_table(vary, varx, table, nx, ny, vmin_y, vmax_y, vmin_x, vmax_x)
subroutine, public interp_pchip_interleaved_nu(vary, varx, table_il, nq, nx, ny, var1_nodes, var2_nodes, guard_1, m_1, scale_1, guard_2, m_2, scale_2, results)
Adaptive-grid sibling of interp_pchip_interleaved. Replaces the affine index calculation (x - x_min) ...
pure double precision function, public bilinear_lookup(var1, var2, tc)
Dispatch wrapper: bilinear lookup that branches on is_uniform.
subroutine, public interp_pchip_interleaved(vary, varx, table_il, nq, nx, ny, vmin_y, vmax_y, vmin_x, vmax_x, results)
Interleaved PCHIP: evaluate N quantities at the same (vary, varx) point. Table layout: table_il(nq,...
pure integer function, public find_index_guard(nodes, n, val, guard, m, scale_m)
Fast adaptive index lookup. Returns the smallest 1-based ii such that nodes(ii) >= val....
pure double precision function, public bicubic_lookup(var1, var2, tc)
Dispatch wrapper: bicubic lookup that branches on the table's is_uniform flag. Hides the uniform-vs-a...
subroutine, public precompute_step_inv(tc)
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,...