flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_ibm_polynomials.py
Go to the documentation of this file.
1
import
numpy
as
np
2
3
def
poly_D
(xi):
4
return
xi * (1.0 + xi)
5
6
def
poly_N_c
(xi):
7
return
2.0 * (xi**2 - 1.0)
8
9
def
poly_N_nb
(xi):
10
return
xi * (1.0 - xi)
11
12
def
poly_N_bc
(xi):
13
return
2.0
14
15
def
verify_1d_operator
():
16
"""
17
Verify 1D IBM Operator consistency with second derivative.
18
19
Setup:
20
- Domain: x in [0, 1]
21
- Grid: N cells, dx = 1/N
22
- Boundary: Located at x_b = (i_ghost + xi) * dx
23
- Function: u(x) = (x - x_b)^2
24
u(x_b) = 0
25
u'(x) = 2(x - x_b)
26
u''(x) = 2
27
28
Discrete Operator L(u) should equal d^2u/dx^2 = 2.
29
L(u)_c = (A_c * u_c + A_nb * u_nb + B_rhs) / D_scale
30
31
Wait, in our code:
32
A_c_mod = D*A_c + K*A_g
33
A_nb_mod = D*A_nb + M*A_g
34
B_mod = D*B + B_fac
35
36
Standard Stencil (Diffusion):
37
A_c = -2/dx^2, A_nb = 1/dx^2, A_g = 1/dx^2
38
B = 0
39
40
Modified Stencil:
41
A_c' = D*(-2) + N_c*(1)
42
A_nb' = D*(1) + N_nb*(1) <- (Here neighbor is fluid, ghost is on other side)
43
So if ghost is West:
44
A_E' = D*(1) + N_E*(1) = D + 0 (since N_E applies to ghost dir)
45
Wait, N_nb in code applies to the FLUID neighbor in the interpolation stencil?
46
Table 1 says "N_{nb,d} applies to the fluid neighbor used in interpolation".
47
Interpolation uses: Ghost(at -1), Center(0), Neighbor(1).
48
So N_nb applies to Neighbor at +1.
49
50
So:
51
A_E' = D * A_E + N_nb * A_W (Cross term? No.)
52
Let's look at code:
53
modify_stencil_ibm_kernel:
54
A_c += A_nb * K (A_nb is the coeff OF the ghost direction in standard stencil)
55
56
Example: Ghost is West (index 1 in loop).
57
orig_AW is the coefficient for u_W in standard stencil.
58
K = N_c * R (R=1 for 1D)
59
M = 0
60
X = N_nb * R
61
62
Update:
63
A_C += orig_AW * K = -2*D + 1*N_c
64
65
Neighbor updates:
66
mod_AW += orig_AW * (D*M - 1) = 1 * (0 - 1) = -1.
67
So A_W becomes 1 + (-1) = 0. Correct.
68
69
mod_AE += orig_AE * X = 1 * N_nb = N_nb.
70
So A_E becomes D*1 + N_nb.
71
72
So Discrete Eq:
73
(A_C' * u_C + A_E' * u_E) * (1/dx^2) / D_scale
74
= [ (-2D + N_c)*u_C + (D + N_nb)*u_E ] / D
75
76
RHS correction:
77
B_val for West ghost:
78
Code says B = 0 if is_ghost is true?
79
Wait, in `compute_ibm_geometry_kernel`:
80
if (is_ghost[kp]) {
81
K = N_c * R
82
X = N_nb * R
83
B = 0
84
}
85
Where is u_bc handled?
86
Ah, `compute_ibm_geometry_kernel` assumes B_val is 0 in the code shown in `src/cfd_solver_ibm.cu`?
87
Let's check lines 220-230.
88
89
Line 226: ibm_data.B_val[...] = 0.0f;
90
91
This looks suspicious! The text says N_bc * u_bc.
92
The code seems to set B_val = 0.
93
94
Let's verify if u_bc is handled elsewhere or if this is the Bug.
95
If u_bc = 0 (Homogeneous Dirichlet), then B=0 is correct.
96
Our verification case uses u=0 at boundary, so B=0 is fine for now.
97
98
Test for u_bc = 0.
99
"""
100
101
print(
"Testing 1D Operator Consistency (u_bc = 0)..."
)
102
103
# Arbitrary theta (0 < theta <= 1)
104
# distance = theta * dx
105
thetas = [0.1, 0.3, 0.5, 0.8, 0.99]
106
107
for
theta
in
thetas:
108
# Polynomials
109
D =
poly_D
(theta)
110
Nc =
poly_N_c
(theta)
111
Nnb =
poly_N_nb
(theta)
112
113
# Standard Stencil Coeffs (scaled by dx^2)
114
# u'' = (u_E - 2u_C + u_W) / dx^2
115
a_W = 1.0
116
a_C = -2.0
117
a_E = 1.0
118
119
# Modified Stencil (Ghost is West)
120
# a_C' = D*a_C + Nc*a_W = -2D + Nc
121
# a_W' = 0
122
# a_E' = D*a_E + Nnb*a_W = D + Nnb
123
124
# Note: In code `mod_AE += orig_AE * (descale * M - 1.0f)`?
125
# No, for East (k=0), M=1, X=0 (if fluid).
126
# Wait, if West is ghost, East is fluid.
127
# For East direction (k=0): is_ghost=False -> K=0, M=1, X=0.
128
# mod_AE += orig_AE * (D*1 - 1) -> A_E becomes D*A_E.
129
#
130
# For West direction (k=1): is_ghost=True -> K=Nc, M=0, X=Nnb.
131
# A_C += orig_AW * Nc
132
# mod_AW += orig_AW * (D*0 - 1) = -orig_AW -> A_W = 0.
133
# mod_AE += orig_AW * X = 1 * Nnb.
134
#
135
# Total A_E = D*A_E + Nnb*A_W = D + Nnb.
136
# Total A_C = D*A_C + Nc*A_W = -2D + Nc.
137
138
a_C_mod = -2.0 * D + Nc
139
a_E_mod = D + Nnb
140
141
# Test Field: u(x) = x^2 (Parabola with vertex at 0)
142
# Shift so boundary is at x = -theta.
143
# Center at x=0. East at x=1. West at x=-1.
144
# Boundary at x_b = -theta.
145
# u(x) = (x - x_b)^2 = (x + theta)^2
146
# u_C = (0 + theta)^2 = theta^2
147
# u_E = (1 + theta)^2 = 1 + 2theta + theta^2
148
# u_bc = 0
149
150
u_C = theta**2
151
u_E = (1.0 + theta)**2
152
153
# Apply Operator
154
# L(u) = (a_C' * u_C + a_E' * u_E) / D
155
156
val = (a_C_mod * u_C + a_E_mod * u_E) / D
157
158
# Expected Second Derivative: d2/dx2 (x+theta)^2 = 2
159
expected = 2.0
160
161
print(f
"Theta={theta:.2f}: L(u)={val:.6f}, Expected={expected:.6f}, Diff={val-expected:.6e}"
)
162
163
if
abs(val - expected) > 1e-5:
164
print(
" FAIL: Operator inconsistent"
)
165
return
False
166
167
print(
"PASS: 1D Operator Consistent for Quadratic Profile"
)
168
return
True
169
170
if
__name__ ==
"__main__"
:
171
verify_1d_operator
()
test_ibm_polynomials.verify_1d_operator
verify_1d_operator()
Definition
test_ibm_polynomials.py:15
test_ibm_polynomials.poly_N_c
poly_N_c(xi)
Definition
test_ibm_polynomials.py:6
test_ibm_polynomials.poly_N_bc
poly_N_bc(xi)
Definition
test_ibm_polynomials.py:12
test_ibm_polynomials.poly_N_nb
poly_N_nb(xi)
Definition
test_ibm_polynomials.py:9
test_ibm_polynomials.poly_D
poly_D(xi)
Definition
test_ibm_polynomials.py:3
scripts
test_ibm_polynomials.py
Generated by
1.9.8