flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
verify_ibm_sandwich.py
Go to the documentation of this file.
1"""Verify the IBM on a sandwiched-channel (two-wall) configuration."""
2import numpy as np
3
4# Point-Value Polynomials (Reference)
5def poly_D_pt(xi): return xi * (1.0 + xi)
6def poly_Nc_pt(xi): return 2.0 * (xi**2 - 1.0)
7def poly_Nnb_pt(xi): return xi * (1.0 - xi)
8def poly_Nbc_pt(xi): return 2.0
9
10# Sandwich Point-Value Polynomials
11def poly_D_sw_pt(xm, xp): return xm * xp
12def poly_Nc_sw_pt(xm, xp): return (xm + 1.0) * (xp - 1.0)
13
14# Inhomogeneous Sandwich factors (from Table 2 derivation/paper)
15# u_ghost_+ approx w_nb u_nb + ...
16# Actually, for sandwich, we solve:
17# u_c = ...
18# D * u_c = ...
19# D * b_c - N_bc_pp * u_bc_p * a_gp ...
20# We need the N_bc terms.
21# Paper Table 2:
22# N_bc,+,+ : xi_- /(xi_-+xi_+) * (1 + xi_-)
23# N_bc,-,+ : xi_+ /(xi_-+xi_+) * (1 - xi_+)
24# Symmetry:
25# N_bc,-,- : xi_+ /(xi_-+xi_+) * (1 + xi_+) (Swap + and -)
26# N_bc,+,- : xi_- /(xi_-+xi_+) * (1 - xi_-)
27
28def poly_Nbc_pp_sw_pt(xm, xp): return xm / (xm + xp) * (1.0 + xm)
29def poly_Nbc_mp_sw_pt(xm, xp): return xp / (xm + xp) * (1.0 - xp)
30def poly_Nbc_mm_sw_pt(xm, xp): return xp / (xm + xp) * (1.0 + xp)
31def poly_Nbc_pm_sw_pt(xm, xp): return xm / (xm + xp) * (1.0 - xm)
32
34 print("Verifying Sandwich Inhomogeneous Terms...")
35
36 # 1D Diffusion: -u'' = f
37 # Discrete: (-u_E + 2u_C - u_W) / h^2 = f
38 # a_c = 2/h^2, a_nb = -1/h^2.
39 # Wait, my code uses: a_c = -2, a_nb = 1.
40 # L(u) = a_c u_c + a_nb u_nb.
41 # So L(u) ~ u'' ~ 2.
42
43 # Case: u(x) = (x - x_m)(x_p - x) + u_wall
44 # u(-xm) = u_wall
45 # u(xp) = u_wall
46 # u(0) = -xm*(-xp) + u_wall = xm*xp + u_wall
47 # u'' = -2.
48 # Standard stencil on u_c, u_E, u_W (if fluid) would give -2.
49
50 # Sandwich Operator:
51 # a'_c u_c = b'_c
52 # b'_c = D * b_c - Sum( N_bc * u_bc * a_ghost )
53 # b_c (standard) = L(u)_target = -2 (if u''=-2).
54 # a_ghost = 1 (standard neighbor coeff).
55
56 # So:
57 # a'_c u_c = D * (-2) - Sum(N_bc) * u_wall * 1.
58
59 # Let's verify if this holds for u_c = xm*xp + u_wall.
60
61 xis = [(0.5, 0.5), (0.2, 0.8), (0.1, 0.4)]
62 u_wall = 5.0
63
64 for xm, xp in xis:
65 D = poly_D_sw_pt(xm, xp)
66 Nc = poly_Nc_sw_pt(xm, xp)
67
68 Npp = poly_Nbc_pp_sw_pt(xm, xp)
69 Nmp = poly_Nbc_mp_sw_pt(xm, xp)
70 Nmm = poly_Nbc_mm_sw_pt(xm, xp)
71 Npm = poly_Nbc_pm_sw_pt(xm, xp)
72
73 # Standard coeffs
74 a_c = -2.0
75 a_g = 1.0 # a_E and a_W
76 b_c = 0.0 # Laplacian of u_wall + quadratic?
77 # u(x) = -x^2 + (xp-xm)x + xm*xp + u_wall
78 # u'' = -2.
79 # Discrete L(u) = -2 (Exact).
80 # So A*u = -2.
81 # b_c should be -2?
82 # The equation is A u = b.
83 # If we check consistency, we check if A' u_c = b'.
84 # Let's compute A' u_c.
85
86 # A'_c = D*a_c + Nc * a_g (Is Nc sum of Nc+ and Nc-?)
87 # Paper: A'_c = D*a_c + Nc,- * a_g- + Nc,+ * a_g+
88 # Here Nc in code seems to be single value?
89 # Table 2 lists "Nc+".
90 # By symmetry "Nc-" should be swapping xi.
91 # Actually code `compute_ibm_geometry_kernel` calculates:
92 # N_c_plus = poly_N_c_sandwich(xi_vals[km], xi_vals[kp]) -> (xm, xp)
93 # N_c_minus = poly_N_c_sandwich(xi_vals[kp], xi_vals[km]) -> (xp, xm)
94 # Note: In code km is Minus, kp is Plus.
95 # `poly_N_c_sandwich(xm, xp)` returns `(xm+1)(xp-1)`.
96 # Wait, `xp-1` term corresponds to the Plus boundary?
97 # Let's verify Table 2.
98 # Nc+ = (xm+1)(xp-1).
99 # Nc- = (xp+1)(xm-1) (Swap xm, xp).
100
101 Nc_p = poly_Nc_sw_pt(xm, xp)
102 Nc_m = poly_Nc_sw_pt(xp, xm)
103
104 A_prime_c = D * a_c + Nc_p * a_g + Nc_m * a_g
105
106 # b' = D * b_c - Sum terms.
107 # If u(x) satisfies the equation, b_c should be the forcing.
108 # u'' = -2.
109 # Solver: mu * lap(u) = f.
110 # Let mu=1. f = -2.
111 # b_c = f = -2.
112
113 # Terms:
114 # u_bc,- * a_g- * (Nmm + Npm) ?
115 # u_bc,+ * a_g+ * (Npp + Nmp) ?
116 # In our case u_bc,- = u_bc,+ = u_wall. a_g- = a_g+ = 1.
117 # SumN = Nmm + Npm + Npp + Nmp.
118
119 SumN = Nmm + Npm + Npp + Nmp
120
121 B_prime_c = D * (-2.0) - SumN * u_wall * 1.0
122
123 # Check: A'_c * u_c == B'_prime_c?
124 u_c_val = xm * xp + u_wall
125
126 lhs = A_prime_c * u_c_val
127 rhs = B_prime_c
128
129 diff = lhs - rhs
130 print(f"xi=({xm}, {xp}): LHS={lhs:.4f}, RHS={rhs:.4f}, Diff={diff:.4e}")
131
132 if abs(diff) > 1e-10:
133 print(" FAIL")
134 else:
135 print(" PASS")
136
137if __name__ == "__main__":