52 long st[3] = {1, e.x, (long)e.x * e.y};
53 int dims[3] = {e.x, e.y, e.z};
54 int N3[3] = {e.x - 2 *
G, e.y - 2 *
G, e.z - 2 *
G};
55 for (
int a = 0; a < 3; ++a) {
56 const int b = (a + 1) % 3, c = (a + 2) % 3;
57 const long sa = st[a], sb = st[b], sc = st[c];
61 Kokkos::MDRangePolicy<
peclet::flow::SExec, Kokkos::Rank<2>>(sp, {0, 0}, {dims[b], dims[c]}),
62 KOKKOS_LAMBDA(
int p0,
int p1) {
63 const long base = (long)p0 * sb + (
long)p1 * sc;
64 for (
int gl = 0; gl <
G; ++gl) {
65 f(base + (
long)gl * sa) = f(base + (
long)(gl +
N) * sa);
66 f(base + (
long)(
G +
N + gl) * sa) = f(base + (
long)(
G + gl) * sa);
73int main(
int argc,
char** argv) {
74 MPI_Init(&argc, &argv);
75 Kokkos::initialize(argc, argv);
76 int fail = 0, size = 1, rank = 0;
78 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
79 MPI_Comm_size(MPI_COMM_WORLD, &size);
80 IVec<kDim> gs{24, 20, 16};
81 std::array<bool, kDim> periodic{
true,
true,
true};
84 BlockDecomposer<kDim> dec(
static_cast<std::size_t
>(size), gs);
85 GridHaloTopology<kDim> halo;
86 halo.buildTopology(dec, rank,
G, periodic, MPI_COMM_WORLD);
87 const auto& idx = halo.indexer();
88 const Index n = idx.numCellsInclGhost();
89 const auto eg = idx.sizeInclGhost(), og = idx.originInclGhost();
90 const I3 e{(int)eg[0], (
int)eg[1], (int)eg[2]}, ogv{(int)og[0], (
int)og[1], (int)og[2]};
92 SField u(
"u", n), b(
"b", n);
93 auto hb = Kokkos::create_mirror_view(b);
94 auto hu = Kokkos::create_mirror_view(u);
95 for (Index c = 0; c < n; ++c) {
99 idx.forEachInner([&](
const IVec<kDim>& l) {
100 hb(idx.localMdToLocal(l)) =
source(l[0] + og[0], l[1] + og[1], l[2] + og[2], gs);
102 Kokkos::deep_copy(b, hb);
103 Kokkos::deep_copy(u, hu);
105 GridHalo<double> dev;
108 for (
int k = 0; k <
SWEEPS; ++k)
109 for (
int color = 0; color < 2; ++color) {
112 diffSmoothColor(u, b, e, ogv,
G,
BETA,
AC, color, empty);
114 Kokkos::deep_copy(hu, u);
118 const I3 ge{(int)gs[0] + 2 *
G, (
int)gs[1] + 2 *
G, (int)gs[2] + 2 *
G}, geo{-
G, -
G, -
G};
119 const Index gn = (Index)ge.
x * ge.y * ge.z;
120 SField ur(
"ur", gn), br(
"br", gn);
121 auto hbr = Kokkos::create_mirror_view(br);
122 for (Index c = 0; c < gn; ++c)
124 for (
int z = 0; z < gs[2]; ++z)
125 for (
int y = 0; y < gs[1]; ++y)
126 for (
int x = 0; x < gs[0]; ++x)
127 hbr((
long)(x +
G) + (
long)(y +
G) * ge.x + (
long)(z +
G) * (
long)ge.x * ge.y) =
129 Kokkos::deep_copy(br, hbr);
130 Kokkos::deep_copy(ur, 0.0);
131 for (
int k = 0; k <
SWEEPS; ++k)
132 for (
int color = 0; color < 2; ++color) {
134 diffSmoothColor(ur, br, ge, geo,
G,
BETA,
AC, color, empty);
136 auto hur = Kokkos::create_mirror_view(ur);
137 Kokkos::deep_copy(hur, ur);
140 double maxdiff = 0.0;
141 idx.forEachInner([&](
const IVec<kDim>& l) {
142 const int gx = l[0] + og[0], gy = l[1] + og[1], gz = l[2] + og[2];
143 const double a = hu(idx.localMdToLocal(l));
145 hur((
long)(gx +
G) + (
long)(gy +
G) * ge.x + (
long)(gz +
G) * (
long)ge.x * ge.y);
146 const double d = std::fabs(a - r);
150 if (maxdiff > 1e-12) {
152 std::fprintf(stderr,
"[rank %d] max|distributed - serial| = %.3e\n", rank, maxdiff);
157 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
160 std::printf(
"OK (np=%d): distributed RB-GS diffusion == serial reference\n", size);
162 std::fprintf(stderr,
"FAILED (np=%d): %d ranks differ\n", size, totalFail);
166 return totalFail == 0 ? 0 : 1;