flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
verify_ibm_math.py
Go to the documentation of this file.
1"""Unit-verify the cut-cell IBM stencil mathematics."""
2import numpy as np
3
4def poly_D_pt(xi): return xi * (1.0 + xi)
5def poly_Nnb_pt(xi): return xi * (1.0 - xi)
6def poly_Nc_pt(xi): return 2.0 * (xi**2 - 1.0)
7def poly_Nbc_pt(xi): return 2.0
8
9def poly_D_avg(xi): return xi * (1.0 + xi) - 1.0/12.0
10def poly_Nnb_avg(xi): return xi * (1.0 - xi) + 1.0/12.0
11def poly_Nc_avg(xi): return 2.0 * (xi**2 - 1.0) - 1.0/6.0
12def poly_Nbc_avg(xi): return 2.0
13
15 print("Testing Point-Value IBM Polynomials for Quadratic Exactness...")
16 thetas = [0.1, 0.3, 0.5, 0.8]
17 for xi in thetas:
18 D = poly_D_pt(xi)
19 Nc = poly_Nc_pt(xi)
20 Nnb = poly_Nnb_pt(xi)
21 Nbc = poly_Nbc_pt(xi)
22
23 # Test 1: Constant field u=1
24 # u_ghost = (Nnb*1 + Nc*1 + Nbc*1) / D
25 u_ghost = (Nnb + Nc + Nbc) / D
26 if abs(u_ghost - 1.0) > 1e-12:
27 print(f" FAIL Constant (xi={xi}): u_ghost={u_ghost}")
28
29 # Test 2: Quadratic u = (x + xi)^2
30 # Boundary at -xi where u=0.
31 # u_c (x=0) = xi^2
32 # u_nb (x=1) = (1+xi)^2
33 # u_ghost (x=-1) = (-1+xi)^2
34 u_c = xi**2
35 u_nb = (1.0 + xi)**2
36 u_ghost_target = (-1.0 + xi)**2
37
38 u_ghost_calc = (Nnb * u_nb + Nc * u_c + Nbc * 0.0) / D
39 if abs(u_ghost_calc - u_ghost_target) > 1e-12:
40 print(f" FAIL Quadratic (xi={xi}): calc={u_ghost_calc}, target={u_ghost_target}")
41 else:
42 print(f" PASS xi={xi}")
43
45 print("\nTesting Cell-Average IBM Polynomials for Quadratic Exactness...")
46 # u_avg = integral_{-0.5}^{0.5} (Ax^2 + Bx + C) dx = A/12 + C
47 # u_point(x) = Ax^2 + Bx + C
48 thetas = [0.1, 0.3, 0.5, 0.8]
49 for xi in thetas:
50 D = poly_D_avg(xi)
51 Nc = poly_Nc_avg(xi)
52 Nnb = poly_Nnb_avg(xi)
53 Nbc = poly_Nbc_avg(xi)
54
55 # Boundary at -xi where u_point(-xi) = 0.
56 # Let u_point(x) = (x + xi)^2 = x^2 + 2*xi*x + xi^2
57 # u_c = integral_{-0.5}^{0.5} (x + xi)^2 dx = 1/12 + xi^2
58 # u_nb = integral_{0.5}^{1.5} (x + xi)^2 dx = integral_{-0.5}^{0.5} (x + 1 + xi)^2 dx = 1/12 + (1+xi)^2
59 # u_ghost_target = integral_{-1.5}^{-0.5} (x + xi)^2 dx = integral_{-0.5}^{0.5} (x - 1 + xi)^2 dx = 1/12 + (-1+xi)^2
60
61 u_c = 1.0/12.0 + xi**2
62 u_nb = 1.0/12.0 + (1.0 + xi)**2
63 u_ghost_target = 1.0/12.0 + (xi - 1.0)**2
64
65 u_ghost_calc = (Nnb * u_nb + Nc * u_c + Nbc * 0.0) / D
66 if abs(u_ghost_calc - u_ghost_target) > 1e-12:
67 print(f" FAIL Quadratic (xi={xi}): calc={u_ghost_calc}, target={u_ghost_target}")
68 else:
69 print(f" PASS xi={xi}")
70
71def poly_D_sw_pt(xm, xp): return xm * xp
72def poly_Nc_sw_pt(xm, xp): return (xm + 1.0) * (xp - 1.0)
73def poly_Nbc_pp_sw_pt(xm, xp): return xm / (xm + xp) * (1.0 + xm)
74def poly_Nbc_mp_sw_pt(xm, xp): return xp / (xm + xp) * (1.0 - xp)
75
76def poly_D_sw_avg(xm, xp): return xm * xp - 1.0/12.0
77def poly_Nc_sw_avg(xm, xp): return (xm + 1.0) * (xp - 1.0) - 1.0/12.0
78def poly_Nbc_pp_sw_avg(xm, xp): return xm / (xm + xp) * (1.0 + xm) - 1.0/12.0
79def poly_Nbc_mp_sw_avg(xm, xp): return xp / (xm + xp) * (1.0 - xp) + 1.0/12.0
80
82 print("\nTesting Sandwiched Point-Value Polynomials...")
83 xis = [(0.5, 0.5), (0.2, 0.8), (0.1, 0.4)]
84 for xm, xp in xis:
85 D = poly_D_sw_pt(xm, xp)
86 Nc = poly_Nc_sw_pt(xm, xp)
87 Nbc_pp = poly_Nbc_pp_sw_pt(xm, xp)
88 Nbc_mp = poly_Nbc_mp_sw_pt(xm, xp)
89
90 # Test: Quadratic u(x) = (x + xm)(xp - x)
91 # u(-xm) = 0. u(xp) = 0.
92 # u(0) = xm * xp
93 # u(1) = (1 + xm)(xp - 1)
94 u_c = xm * xp
95 u_ghost_target = (1.0 + xm) * (xp - 1.0)
96
97 # u_ghost = (Nc * u_c + ...) / D
98 u_ghost_calc = (Nc * u_c) / D
99 if abs(u_ghost_calc - u_ghost_target) > 1e-12:
100 print(f" FAIL (xm={xm}, xp={xp}): calc={u_ghost_calc}, target={u_ghost_target}")
101 else:
102 print(f" PASS xm={xm}, xp={xp}")
103
105 print("\nTesting Sandwiched Cell-Average Polynomials...")
106 xis = [(0.5, 0.5), (0.2, 0.8), (0.1, 0.4)]
107 for xm, xp in xis:
108 D = poly_D_sw_avg(xm, xp)
109 Nc = poly_Nc_sw_avg(xm, xp)
110
111 # Quadratic with zero wall values at x=-xm and x=xp:
112 # u(x) = (x + xm)(xp - x) = -x^2 + (xp-xm)x + xm*xp
113 # Cell average over a unit cell centered at x0 is u(x0) - 1/12.
114 u_c = xm * xp - 1.0/12.0
115 u_ghost_target = (1.0 + xm) * (xp - 1.0) - 1.0/12.0
116
117 u_ghost_calc = (Nc * u_c) / D
118 if abs(u_ghost_calc - u_ghost_target) > 1e-12:
119 print(f" FAIL (xm={xm}, xp={xp}): calc={u_ghost_calc}, target={u_ghost_target}")
120 else:
121 print(f" PASS xm={xm}, xp={xp}")
122
123if __name__ == "__main__":
poly_Nbc_pp_sw_avg(xm, xp)
poly_Nbc_pp_sw_pt(xm, xp)
poly_Nbc_mp_sw_avg(xm, xp)
poly_Nbc_mp_sw_pt(xm, xp)