flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_advection.cpp
Go to the documentation of this file.
1// Correctness of the Kokkos staggered advection operator (sadv::advect / advect_fou) vs a host
2// replication using the same templated functions. Random U,V,W,PHI on an extended (inner+ghost=2)
3// block; apply the conservative Koren-TVD (and FOU) advection per inner cell on the device and on
4// the host, require a match (per-cell deterministic double math). Runs on whatever backend Kokkos
5// has.
6#include <cmath>
7#include <cstdio>
8#include <Kokkos_Core.hpp>
9#include <random>
10#include <vector>
11
13
14using namespace sadv;
15using Mem = Kokkos::DefaultExecutionSpace::memory_space;
16using DView = Kokkos::View<double*, Mem>;
17using CView = Kokkos::View<const double*, Mem>;
18
19// Host accessor mirroring ViewAcc (same indexing) for the reference.
20struct HostAcc {
21 const double* d;
22 int ex, ey;
23 double operator()(int x, int y, int z) const {
24 return d[(long)x + (long)y * ex + (long)z * (long)ex * ey];
25 }
26};
27
28int main(int argc, char** argv) {
29 Kokkos::initialize(argc, argv);
30 int status = 0;
31 {
32 const int ghost = 2;
33 const int ix0 = ghost, iy0 = ghost, iz0 = ghost;
34 const int inx = 16, iny = 12, inz = 10;
35 const int ex = inx + 2 * ghost, ey = iny + 2 * ghost, ez = inz + 2 * ghost;
36 const std::size_t n = (std::size_t)ex * ey * ez;
37
38 std::mt19937 rng(5);
39 std::uniform_real_distribution<double> uf(-1.0, 1.0);
40 std::vector<double> hU(n), hV(n), hW(n), hP(n);
41 for (std::size_t i = 0; i < n; ++i) {
42 hU[i] = uf(rng);
43 hV[i] = uf(rng);
44 hW[i] = uf(rng);
45 hP[i] = uf(rng);
46 }
47
48 auto up = [&](const char* nm, std::vector<double>& h) {
49 DView v(nm, n);
50 auto m = Kokkos::create_mirror_view(v);
51 for (std::size_t i = 0; i < n; ++i)
52 m(i) = h[i];
53 Kokkos::deep_copy(v, m);
54 return v;
55 };
56 DView U = up("U", hU), V = up("V", hV), W = up("W", hW), P = up("P", hP);
57
58 const long ninner = (long)inx * iny * inz;
59 DView outTVD("outTVD", ninner), outFOU("outFOU", ninner);
60 const int comp = 0;
61 Kokkos::parallel_for(
62 "advect", Kokkos::RangePolicy<Kokkos::DefaultExecutionSpace>(0, ninner),
63 KOKKOS_LAMBDA(long c) {
64 const int lx = (int)(c % inx), ly = (int)((c / inx) % iny),
65 lz = (int)(c / ((long)inx * iny));
66 const int x = lx + ix0, y = ly + iy0, z = lz + iz0;
67 ViewAcc Ua{CView(U), ex, ey}, Va{CView(V), ex, ey}, Wa{CView(W), ex, ey},
68 Pa{CView(P), ex, ey};
69 outTVD(c) = advect(comp, x, y, z, Ua, Va, Wa, Pa);
70 outFOU(c) = advect_fou(comp, x, y, z, Ua, Va, Wa, Pa);
71 });
72
73 auto hT = Kokkos::create_mirror_view(outTVD);
74 Kokkos::deep_copy(hT, outTVD);
75 auto hF = Kokkos::create_mirror_view(outFOU);
76 Kokkos::deep_copy(hF, outFOU);
77
78 // host reference
79 int bad = 0;
80 HostAcc Uh{hU.data(), ex, ey}, Vh{hV.data(), ex, ey}, Wh{hW.data(), ex, ey},
81 Ph{hP.data(), ex, ey};
82 auto close = [](double a, double b) { return std::fabs(a - b) <= 1e-9 * (1.0 + std::fabs(b)); };
83 for (long c = 0; c < ninner; ++c) {
84 const int lx = (int)(c % inx), ly = (int)((c / inx) % iny), lz = (int)(c / ((long)inx * iny));
85 const int x = lx + ix0, y = ly + iy0, z = lz + iz0;
86 const double rT = advect(comp, x, y, z, Uh, Vh, Wh, Ph);
87 const double rF = advect_fou(comp, x, y, z, Uh, Vh, Wh, Ph);
88 if (!close(hT(c), rT) || !close(hF(c), rF))
89 ++bad;
90 }
91 if (bad) {
92 std::fprintf(stderr, "FAIL: %d/%ld advection cells differ\n", bad, ninner);
93 status = 1;
94 } else
95 std::printf("[advection] PASS: %ld cells, Koren-TVD + FOU match host (exec: %s)\n", ninner,
96 Kokkos::DefaultExecutionSpace::name());
97 }
98 Kokkos::finalize();
99 return status;
100}
double advect(int comp, int x, int y, int z, A U, A V, A W, A PHI)
double advect_fou(int comp, int x, int y, int z, A U, A V, A W, A PHI)
flow — portable (Kokkos) staggered MAC momentum advection (Koren TVD + FOU).
double operator()(int x, int y, int z) const
const double * d
Kokkos::DefaultExecutionSpace::memory_space Mem
int main(int argc, char **argv)
Kokkos::View< const double *, Mem > CView
Kokkos::View< double *, Mem > DView