flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_ibm_apply.cpp
Go to the documentation of this file.
1// Correctness of the Kokkos IBM operator assembly: build the base backward-Euler diffusion stencil
2// (ibmBuildDiffusion), build the Robust-Scaled overlay (ibmFillEntry), then apply it
3// (ibmModifyStencil), and compare the modified stencil + inhomogeneous term + row scaling to a host
4// replication. 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 "cut_cell_ibm.hpp"
12
13using namespace peclet::flow;
14using DSpace = Kokkos::DefaultExecutionSpace;
15using FV = Kokkos::View<float*, IMem>;
16using DV = Kokkos::View<double*, IMem>;
17
18int main(int argc, char** argv) {
19 Kokkos::initialize(argc, argv);
20 int status = 0;
21 {
22 const int ex = 12, ey = 12, ez = 12;
23 const std::size_t n = (std::size_t)ex * ey * ez;
24 const double beta = 0.7, idiag = 3.0;
25 const float u_bc = 0.25f;
26 const int M = 64; // cut cells
27
28 // distinct interior grid indices + random cut-cell SDF configs
29 std::mt19937 rng(7);
30 std::uniform_int_distribution<int> ic(2, 9);
31 std::uniform_real_distribution<float> uc(0.05f, 0.95f), us(-0.95f, -0.05f), uf(0.05f, 0.95f),
32 u01(0, 1);
33 std::vector<int> cidx;
34 std::vector<float> sc(M);
35 std::vector<float> sn((std::size_t)M * 6);
36 std::vector<char> used(n, 0);
37 for (int i = 0; i < M;) {
38 int x = ic(rng), y = ic(rng), z = ic(rng);
39 std::size_t c = (std::size_t)x + (std::size_t)y * ex + (std::size_t)z * ex * ey;
40 if (used[c])
41 continue;
42 used[c] = 1;
43 cidx.push_back((int)c);
44 sc[i] = uc(rng);
45 bool sw = u01(rng) < 0.3f;
46 for (int k = 0; k < 6; ++k) {
47 bool solid = (sw && k < 2) || (u01(rng) < 0.5f);
48 sn[(std::size_t)i * 6 + k] = solid ? us(rng) : uf(rng);
49 }
50 ++i;
51 }
52
53 auto mkF = [&](const char* nm) {
54 FV v(nm, n);
55 return v;
56 };
57 FV AC = mkF("AC"), AW = mkF("AW"), AE = mkF("AE"), AS = mkF("AS"), AN = mkF("AN"),
58 AB = mkF("AB"), AT = mkF("AT");
59 DV inhom("inhom", n), rscale("rscale", n); // zero-init
60 ibmBuildDiffusion(AC, AW, AE, AS, AN, AB, AT, ex, ey, ez, beta, idiag);
61
62 // build overlay on device
64 Kokkos::View<int*, IMem>("ci", M), Kokkos::View<int*, IMem>("nb", M),
65 Kokkos::View<float*, IMem>("dr", M), Kokkos::View<int*, IMem>("dc", (std::size_t)M * 6),
66 FV("K", (std::size_t)M * 6), FV("Mv", (std::size_t)M * 6),
67 FV("X", (std::size_t)M * 6), FV("Nbc", (std::size_t)M * 6),
68 FV("R", (std::size_t)M * 6)};
69 Kokkos::View<int*, IMem> dci("dci", M);
70 {
71 auto m = Kokkos::create_mirror_view(dci);
72 for (int i = 0; i < M; ++i)
73 m(i) = cidx[i];
74 Kokkos::deep_copy(dci, m);
75 }
76 FV dsc("dsc", M);
77 {
78 auto m = Kokkos::create_mirror_view(dsc);
79 for (int i = 0; i < M; ++i)
80 m(i) = sc[i];
81 Kokkos::deep_copy(dsc, m);
82 }
83 FV dsn("dsn", (std::size_t)M * 6);
84 {
85 auto m = Kokkos::create_mirror_view(dsn);
86 for (std::size_t i = 0; i < (std::size_t)M * 6; ++i)
87 m(i) = sn[i];
88 Kokkos::deep_copy(dsn, m);
89 }
90 Kokkos::parallel_for(
91 "bo", Kokkos::RangePolicy<DSpace>(0, M), KOKKOS_LAMBDA(int i) {
92 float s6[6];
93 for (int k = 0; k < 6; ++k)
94 s6[k] = dsn((std::size_t)i * 6 + k);
95 ibmFillEntry<0>(ov, i, dci(i), dsc(i), s6, 0);
96 });
97 Kokkos::fence();
98 ibmModifyStencil(AC, AW, AE, AS, AN, AB, AT, inhom, rscale, ov, M, u_bc);
99
100 auto gf = [&](FV v) {
101 std::vector<float> o(n);
102 auto m = Kokkos::create_mirror_view(v);
103 Kokkos::deep_copy(m, v);
104 for (std::size_t i = 0; i < n; ++i)
105 o[i] = m(i);
106 return o;
107 };
108 auto gd = [&](DV v) {
109 std::vector<double> o(n);
110 auto m = Kokkos::create_mirror_view(v);
111 Kokkos::deep_copy(m, v);
112 for (std::size_t i = 0; i < n; ++i)
113 o[i] = m(i);
114 return o;
115 };
116 auto GAC = gf(AC), GAW = gf(AW), GAE = gf(AE), GAS = gf(AS), GAN = gf(AN), GAB = gf(AB),
117 GAT = gf(AT);
118 auto GIN = gd(inhom), GRS = gd(rscale);
119
120 // --- host replication ---
121 std::vector<float> hAC(n), hAW(n), hAE(n), hAS(n), hAN(n), hAB(n), hAT(n);
122 std::vector<double> hin(n, 0), hrs(n, 0);
123 float nb = (float)(-beta), cc = (float)(idiag + 6.0 * beta);
124 for (std::size_t i = 0; i < n; ++i) {
125 hAC[i] = cc;
126 hAW[i] = nb;
127 hAE[i] = nb;
128 hAS[i] = nb;
129 hAN[i] = nb;
130 hAB[i] = nb;
131 hAT[i] = nb;
132 }
134 HOV h{Kokkos::View<int*, Kokkos::HostSpace>("hci", M),
135 Kokkos::View<int*, Kokkos::HostSpace>("hnb", M),
136 Kokkos::View<float*, Kokkos::HostSpace>("hdr", M),
137 Kokkos::View<int*, Kokkos::HostSpace>("hdc", (std::size_t)M * 6),
138 Kokkos::View<float*, Kokkos::HostSpace>("hK", (std::size_t)M * 6),
139 Kokkos::View<float*, Kokkos::HostSpace>("hM", (std::size_t)M * 6),
140 Kokkos::View<float*, Kokkos::HostSpace>("hX", (std::size_t)M * 6),
141 Kokkos::View<float*, Kokkos::HostSpace>("hNbc", (std::size_t)M * 6),
142 Kokkos::View<float*, Kokkos::HostSpace>("hR", (std::size_t)M * 6)};
143 for (int i = 0; i < M; ++i) {
144 float s6[6];
145 for (int k = 0; k < 6; ++k)
146 s6[k] = sn[(std::size_t)i * 6 + k];
147 ibmFillEntry<0>(h, i, cidx[i], sc[i], s6, 0);
148 }
149 const int OPP[6] = {1, 0, 3, 2, 5, 4};
150 for (int li = 0; li < M; ++li) {
151 int c = h.cell_index(li);
152 float descale = h.D_rescale(li);
153 hrs[c] = descale;
154 double orig[6] = {hAE[c], hAW[c], hAN[c], hAS[c], hAT[c], hAB[c]};
155 double aC = (double)hAC[c] * (double)descale;
156 double mod[6] = {0, 0, 0, 0, 0, 0};
157 double inh = 0;
158 for (int k = 0; k < 6; ++k) {
159 float K = h.K_val(li * 6 + k), Mv = h.M_val(li * 6 + k), X = h.X_val(li * 6 + k),
160 Nbc = h.Nbc_val(li * 6 + k);
161 double vnb = orig[k];
162 aC += vnb * K;
163 inh += (double)Nbc * u_bc * vnb;
164 mod[k] += vnb * ((double)descale * Mv - 1.0);
165 mod[OPP[k]] += vnb * X;
166 }
167 hAC[c] = (float)aC;
168 hAE[c] = (float)(orig[0] + mod[0]);
169 hAW[c] = (float)(orig[1] + mod[1]);
170 hAN[c] = (float)(orig[2] + mod[2]);
171 hAS[c] = (float)(orig[3] + mod[3]);
172 hAT[c] = (float)(orig[4] + mod[4]);
173 hAB[c] = (float)(orig[5] + mod[5]);
174 hin[c] += inh;
175 }
176
177 // Modified coefficients involve descale*M-1 cancellation + cross-terms; fma contraction differs
178 // between nvcc and gcc, so use a relative tolerance appropriate to that (dist/inhom tracked
179 // separately).
180 auto cf = [&](float a, float b) {
181 return std::fabs((double)a - (double)b) <= 2e-3 * (1.0 + std::fabs((double)b));
182 };
183 auto cd = [&](double a, double b) { return std::fabs(a - b) <= 2e-3 * (1.0 + std::fabs(b)); };
184 int bad = 0;
185 double maxrel = 0;
186 auto rel = [&](double a, double b) {
187 double r = std::fabs(a - b) / (1.0 + std::fabs(b));
188 if (r > maxrel)
189 maxrel = r;
190 };
191 for (std::size_t i = 0; i < n; ++i) {
192 rel(GAC[i], hAC[i]);
193 rel(GAW[i], hAW[i]);
194 rel(GAE[i], hAE[i]);
195 rel(GIN[i], hin[i]);
196 if (!cf(GAC[i], hAC[i]) || !cf(GAW[i], hAW[i]) || !cf(GAE[i], hAE[i]) ||
197 !cf(GAS[i], hAS[i]) || !cf(GAN[i], hAN[i]) || !cf(GAB[i], hAB[i]) || !cf(GAT[i], hAT[i]))
198 ++bad;
199 if (!cd(GIN[i], hin[i]) || !cd(GRS[i], hrs[i]))
200 ++bad;
201 }
202 if (bad) {
203 std::fprintf(stderr, "FAIL: %d modified-stencil cells differ (max rel diff %.3e)\n", bad,
204 maxrel);
205 status = 1;
206 } else
207 std::printf(
208 "[ibm_apply] PASS: build+overlay+modify stencil (%d cut cells) matches host (exec: %s)\n",
209 M, DSpace::name());
210 }
211 Kokkos::finalize();
212 return status;
213}
flow — portable (Kokkos) Robust-Scaled cut-cell IBM primitives + per-cut-cell overlay build.
int main()
Definition dbg_scene.cpp:13
void ibmModifyStencil(MV AC, MV AW, MV AE, MV AS, MV AN, MV AB, MV AT, Kokkos::View< double *, IMem > a_inhom, Kokkos::View< double *, IMem > rhs_scale, const OV &ibm, int numActive, typename OV::value_type u_bc_val, Kokkos::View< const double *, IMem > u_bc=Kokkos::View< const double *, IMem >())
void ibmBuildDiffusion(MV AC, MV AW, MV AE, MV AS, MV AN, MV AB, MV AT, int ex, int ey, int ez, double bx, double by, double bz, double idiag)
static constexpr double AC
Kokkos::DefaultExecutionSpace DSpace
Kokkos::View< double *, IMem > DV
Kokkos::View< float *, IMem > FV