flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_ibm.cpp
Go to the documentation of this file.
1// Correctness of the Kokkos IBM pieces (sdflow): the variable-coefficient RB-GS smoother
2// (ibmRbgsSweep) vs host replication + a Laplacian convergence sanity, and the geometric fields
3// (ibmVolfrac / ibmSolidMask) property checks (all-fluid -> theta 1 / mask 0, all-solid -> 0 / 1).
4// Runs on whatever backend Kokkos was built for.
5#include <cmath>
6#include <cstdio>
7#include <Kokkos_Core.hpp>
8#include <random>
9#include <vector>
10
11#include "mac_ibm.hpp"
12
13using namespace peclet::flow;
14
15static long l3(int x, int y, int z, C3 e) {
16 return (long)x + (long)y * e.x + (long)z * (long)e.x * e.y;
17}
18
19int main(int argc, char** argv) {
20 Kokkos::initialize(argc, argv);
21 int status = 0;
22 {
23 const int g = 1;
24 C3 inner{18, 14, 10}, e{inner.x + 2 * g, inner.y + 2 * g, inner.z + 2 * g}, og{0, 0, 0};
25 const std::size_t n = (std::size_t)e.x * e.y * e.z;
26
27 std::mt19937 rng(91);
28 std::uniform_real_distribution<double> uf(-1.0, 1.0);
29 std::uniform_real_distribution<float> uac(3.0f, 7.0f), uoff(-1.0f, 1.0f), u01(0.0f, 1.0f);
30 std::vector<double> hx(n), hb(n), hmask(n);
31 std::vector<float> hAC(n), hAW(n), hAE(n), hAS(n), hAN(n), hAB(n), hAT(n);
32 for (std::size_t i = 0; i < n; ++i) {
33 hx[i] = uf(rng);
34 hb[i] = uf(rng);
35 hmask[i] = (u01(rng) < 0.2f) ? 1.0 : 0.0;
36 hAC[i] = uac(rng);
37 hAW[i] = uoff(rng);
38 hAE[i] = uoff(rng);
39 hAS[i] = uoff(rng);
40 hAN[i] = uoff(rng);
41 hAB[i] = uoff(rng);
42 hAT[i] = uoff(rng);
43 }
44 auto upd = [&](const char* nm, std::vector<double>& h) {
45 CCField v(nm, n);
46 auto m = Kokkos::create_mirror_view(v);
47 for (std::size_t i = 0; i < n; ++i)
48 m(i) = h[i];
49 Kokkos::deep_copy(v, m);
50 return v;
51 };
52 auto upf = [&](const char* nm, std::vector<float>& h) {
53 Kokkos::View<float*, CCMem> v(nm, n);
54 auto m = Kokkos::create_mirror_view(v);
55 for (std::size_t i = 0; i < n; ++i)
56 m(i) = h[i];
57 Kokkos::deep_copy(v, m);
58 return v;
59 };
60 auto getd = [&](CCField v) {
61 std::vector<double> o(n);
62 auto m = Kokkos::create_mirror_view(v);
63 Kokkos::deep_copy(m, v);
64 for (std::size_t i = 0; i < n; ++i)
65 o[i] = m(i);
66 return o;
67 };
68
69 CCField x = upd("x", hx), b = upd("b", hb), mask = upd("mask", hmask);
70 auto AC = upf("AC", hAC), AW = upf("AW", hAW), AE = upf("AE", hAE), AS = upf("AS", hAS),
71 AN = upf("AN", hAN), AB = upf("AB", hAB), AT = upf("AT", hAT);
72
73 ibmRbgsSweep(x, b, AC, AW, AE, AS, AN, AB, AT, mask, e, og, g);
74 auto gx = getd(x);
75
76 // host RB-GS (same float->double promotion, colour 0 then 1)
77 std::vector<double> rx = hx;
78 for (int color = 0; color < 2; ++color)
79 for (int z = g; z < e.z - g; ++z)
80 for (int y = g; y < e.y - g; ++y)
81 for (int xx = g; xx < e.x - g; ++xx) {
82 if (((og.x + xx + og.y + y + og.z + z) & 1) != color)
83 continue;
84 long i = l3(xx, y, z, e), sx = 1, sy = e.x, sz = (long)e.x * e.y;
85 if (hmask[i] > 0.5) {
86 rx[i] = 0.0;
87 continue;
88 }
89 double ac = hAC[i];
90 if (std::fabs(ac) < 1e-30)
91 continue;
92 double s = (double)hAE[i] * rx[i + sx] + (double)hAW[i] * rx[i - sx] +
93 (double)hAN[i] * rx[i + sy] + (double)hAS[i] * rx[i - sy] +
94 (double)hAT[i] * rx[i + sz] + (double)hAB[i] * rx[i - sz];
95 rx[i] = (hb[i] - s) / ac;
96 }
97 auto close = [](double a, double b2) {
98 return std::fabs(a - b2) <= 1e-9 * (1.0 + std::fabs(b2));
99 };
100 int bad = 0;
101 for (std::size_t i = 0; i < n; ++i)
102 if (!close(gx[i], rx[i]))
103 ++bad;
104 if (bad) {
105 std::fprintf(stderr, "FAIL: %d RB-GS cells differ\n", bad);
106 status = 1;
107 }
108
109 // Laplacian convergence: AC=6, A_off=-1, no mask -> 6x - sum_nbr = b ; residual drops.
110 std::vector<float> lc(n, 6.f), lo(n, -1.f);
111 auto LC = upf("LC", lc), LW = upf("LW", lo), LE = upf("LE", lo), LS = upf("LS", lo),
112 LN = upf("LN", lo), LB = upf("LB", lo), LT = upf("LT", lo);
113 CCField px = upd("px", hx);
114 CCConst noMask; // empty mask
115 auto resid = [&]() {
116 auto m = getd(px);
117 double r = 0;
118 for (int z = g; z < e.z - g; ++z)
119 for (int y = g; y < e.y - g; ++y)
120 for (int xx = g; xx < e.x - g; ++xx) {
121 long i = l3(xx, y, z, e), sx = 1, sy = e.x, sz = (long)e.x * e.y;
122 double s = m[i + sx] + m[i - sx] + m[i + sy] + m[i - sy] + m[i + sz] + m[i - sz];
123 double res = (6.0 * m[i] - s) - hb[i];
124 r += res * res;
125 }
126 return std::sqrt(r);
127 };
128 double r0 = resid();
129 for (int it = 0; it < 100; ++it)
130 ibmRbgsSweep(px, b, LC, LW, LE, LS, LN, LB, LT, noMask, e, og, g);
131 double r1 = resid();
132 if (!(r1 < 0.2 * r0)) {
133 std::fprintf(stderr, "FAIL: IBM smoother residual %.3e -> %.3e\n", r0, r1);
134 status = 1;
135 }
136
137 // volfrac / solid-mask properties
138 std::vector<double> allf(n, 10.0), alls(n, -10.0);
139 CCField sf = upd("sf", allf), so = upd("so", alls), th("th", n), mk("mk", n);
140 Off3 off{0, 0, 0};
141 ibmVolfrac(th, sf, e, off);
142 auto gth = getd(th);
143 for (std::size_t i = 0; i < n; ++i)
144 if (!close(gth[i], 1.0))
145 ++bad;
146 ibmVolfrac(th, so, e, off);
147 auto gth2 = getd(th);
148 for (std::size_t i = 0; i < n; ++i)
149 if (!close(gth2[i], 0.0))
150 ++bad;
151 ibmSolidMask(mk, sf, e, off);
152 auto gmk = getd(mk);
153 for (std::size_t i = 0; i < n; ++i)
154 if (!close(gmk[i], 0.0))
155 ++bad;
156 ibmSolidMask(mk, so, e, off);
157 auto gmk2 = getd(mk);
158 for (std::size_t i = 0; i < n; ++i)
159 if (!close(gmk2[i], 1.0))
160 ++bad;
161 if (bad && !status) {
162 std::fprintf(stderr, "FAIL: volfrac/mask property\n");
163 status = 1;
164 }
165
166 if (!status)
167 std::printf(
168 "[mac_ibm] PASS: variable-coeff RB-GS matches host; Laplacian resid %.2e -> %.2e; "
169 "volfrac/mask ok (exec: %s)\n",
170 r0, r1, CCExec::name());
171 }
172 Kokkos::finalize();
173 return status;
174}
flow — portable (Kokkos) IBM geometric fields + variable-coefficient RB-GS smoother.
void ibmSolidMask(CCField mask, CCConst sdf, C3 ext, Off3 off)
Definition mac_ibm.hpp:87
void ibmRbgsSweep(CCField x, CCConst b, MConst AC, MConst AW, MConst AE, MConst AS, MConst AN, MConst AB, MConst AT, CCConst solidmask, C3 ext, C3 og, int g)
Definition mac_ibm.hpp:147
Kokkos::View< double *, CCMem > CCField
Kokkos::View< const double *, CCMem > CCConst
void ibmVolfrac(CCField theta, CCConst sdf, C3 ext, Off3 off)
Definition mac_ibm.hpp:73
static constexpr double AC
int main(int argc, char **argv)
Definition test_ibm.cpp:19
static long l3(int x, int y, int z, C3 e)
Definition test_ibm.cpp:15