flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_reductions.cpp
Go to the documentation of this file.
1// Correctness of the Kokkos MAC reductions (peclet::flow::localSumMax / localDot / subtractAll)
2// over the inner cells of an extended (inner+ghost) block, vs a host reference. Validates the
3// parallel_reduce indexing (x-fastest, +ghost) and the mean-subtraction. Runs on whatever backend
4// Kokkos was built for (CUDA locally; OpenMP for CI). The MPI_Allreduce wrapper is host MPI and
5// unchanged.
6#include <cmath>
7#include <cstdio>
8#include <Kokkos_Core.hpp>
9#include <random>
10#include <vector>
11
12#include "mac_reductions.hpp"
13
14using namespace peclet::flow;
15
16int main(int argc, char** argv) {
17 Kokkos::initialize(argc, argv);
18 int status = 0;
19 {
20 const int ghost = 2;
21 Ext3 inner{20, 16, 12};
22 Ext3 ext{inner.x + 2 * ghost, inner.y + 2 * ghost, inner.z + 2 * ghost};
23 const std::size_t n = static_cast<std::size_t>(ext.x) * ext.y * ext.z;
24
25 std::mt19937 rng(13);
26 std::uniform_real_distribution<float> uf(-1.f, 1.f);
27 std::vector<double> ha(n), hb(n);
28 for (std::size_t i = 0; i < n; ++i) {
29 ha[i] = uf(rng);
30 hb[i] = uf(rng);
31 }
32
33 DField a("a", n), b("b", n);
34 {
35 auto h = Kokkos::create_mirror_view(a);
36 for (std::size_t i = 0; i < n; ++i)
37 h(i) = ha[i];
38 Kokkos::deep_copy(a, h);
39 }
40 {
41 auto h = Kokkos::create_mirror_view(b);
42 for (std::size_t i = 0; i < n; ++i)
43 h(i) = hb[i];
44 Kokkos::deep_copy(b, h);
45 }
46
47 // device
48 SumMax sm = localSumMax(a, ext, ghost, inner);
49 double dot = localDot(a, b, ext, ghost, inner);
50
51 // host reference (same inner-cell traversal)
52 double rsum = 0.0, rmax = 0.0, rdot = 0.0;
53 long count = 0;
54 for (int iz = 0; iz < inner.z; ++iz)
55 for (int iy = 0; iy < inner.y; ++iy)
56 for (int ix = 0; ix < inner.x; ++ix) {
57 std::size_t idx = (std::size_t)(ix + ghost) + (std::size_t)(iy + ghost) * ext.x +
58 (std::size_t)(iz + ghost) * (std::size_t)ext.x * ext.y;
59 rsum += ha[idx];
60 rmax = std::fmax(rmax, std::fabs(ha[idx]));
61 rdot += ha[idx] * hb[idx];
62 ++count;
63 }
64
65 auto close = [](double x, double y) { return std::fabs(x - y) <= 1e-9 * (1.0 + std::fabs(y)); };
66 if (!close(sm.sum, rsum) || !close(sm.maxabs, rmax) || !close(dot, rdot)) {
67 std::fprintf(stderr, "FAIL: sum %.10g/%.10g max %.10g/%.10g dot %.10g/%.10g\n", sm.sum,
68 rsum, sm.maxabs, rmax, dot, rdot);
69 status = 1;
70 }
71
72 // mean-subtraction over the WHOLE extended block, then re-sum inner cells.
73 const double mean = rsum / static_cast<double>(count);
74 subtractAll(a, mean);
75 SumMax sm2 = localSumMax(a, ext, ghost, inner);
76 const double expect2 = rsum - mean * static_cast<double>(count);
77 if (!close(sm2.sum, expect2)) {
78 std::fprintf(stderr, "FAIL: post-subtract inner sum %.10g != %.10g\n", sm2.sum, expect2);
79 status = 1;
80 }
81
82 if (!status)
83 std::printf(
84 "[mac_reductions] PASS: sum/max/dot + mean-subtract match host (%ld inner cells, exec: "
85 "%s)\n",
86 count, Exec::name());
87 }
88 Kokkos::finalize();
89 return status;
90}
flow — portable (Kokkos) global reductions over a MAC grid's inner (owned) cells.
double localDot(DConst a, DConst b, Ext3 ext, int ghost, Ext3 inner)
Local inner product <a,b> over the inner cells.
Kokkos::View< double *, Mem > DField
SumMax localSumMax(DConst f, Ext3 ext, int ghost, Ext3 inner)
Local sum and max|.| over the inner cells.
void subtractAll(DField f, double m)
Subtract a constant from EVERY cell of the extended block (the mean-removal scatter).
{sum, max|.|} reduction value.
int main(int argc, char **argv)