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_LAMBDA(
int p0,
int p1) {
62 const long base = (long)p0 * sb + (
long)p1 * sc;
63 for (
int gl = 0; gl <
G; ++gl) {
64 f(base + (
long)gl * sa) = f(base + (
long)(gl +
N) * sa);
65 f(base + (
long)(
G +
N + gl) * sa) = f(base + (
long)(
G + gl) * sa);
72int main(
int argc,
char** argv) {
73 MPI_Init(&argc, &argv);
74 Kokkos::initialize(argc, argv);
75 int fail = 0, size = 1, rank = 0;
77 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
78 MPI_Comm_size(MPI_COMM_WORLD, &size);
79 IVec<kDim> gs{24, 20, 16};
80 std::array<bool, kDim> periodic{
true,
true,
true};
83 BlockDecomposer<kDim> dec(
static_cast<std::size_t
>(size), gs);
84 GridHaloTopology<kDim> halo;
85 halo.buildTopology(dec, rank,
G, periodic, MPI_COMM_WORLD);
86 const auto& idx = halo.indexer();
87 const Index n = idx.numCellsInclGhost();
88 const auto eg = idx.sizeInclGhost(), og = idx.originInclGhost();
89 const I3 e{(int)eg[0], (
int)eg[1], (int)eg[2]}, ogv{(int)og[0], (
int)og[1], (int)og[2]};
91 SField u(
"u", n), b(
"b", n);
92 auto hb = Kokkos::create_mirror_view(b);
93 auto hu = Kokkos::create_mirror_view(u);
94 for (Index c = 0; c < n; ++c) {
98 idx.forEachInner([&](
const IVec<kDim>& l) {
99 hb(idx.localMdToLocal(l)) =
source(l[0] + og[0], l[1] + og[1], l[2] + og[2], gs);
101 Kokkos::deep_copy(b, hb);
102 Kokkos::deep_copy(u, hu);
104 GridHalo<double> dev;
107 for (
int k = 0; k <
SWEEPS; ++k)
108 for (
int color = 0; color < 2; ++color) {
111 diffSmoothColor(u, b, e, ogv,
G,
BETA,
AC, color, empty);
113 Kokkos::deep_copy(hu, u);
117 const I3 ge{(int)gs[0] + 2 *
G, (
int)gs[1] + 2 *
G, (int)gs[2] + 2 *
G}, geo{-
G, -
G, -
G};
118 const Index gn = (Index)ge.x * ge.y * ge.z;
119 SField ur(
"ur", gn), br(
"br", gn);
120 auto hbr = Kokkos::create_mirror_view(br);
121 for (Index c = 0; c < gn; ++c)
123 for (
int z = 0; z < gs[2]; ++z)
124 for (
int y = 0; y < gs[1]; ++y)
125 for (
int x = 0; x < gs[0]; ++x)
126 hbr((
long)(x +
G) + (
long)(y +
G) * ge.x + (
long)(z +
G) * (
long)ge.x * ge.y) =
128 Kokkos::deep_copy(br, hbr);
129 Kokkos::deep_copy(ur, 0.0);
130 for (
int k = 0; k <
SWEEPS; ++k)
131 for (
int color = 0; color < 2; ++color) {
133 diffSmoothColor(ur, br, ge, geo,
G,
BETA,
AC, color, empty);
135 auto hur = Kokkos::create_mirror_view(ur);
136 Kokkos::deep_copy(hur, ur);
139 double maxdiff = 0.0;
140 idx.forEachInner([&](
const IVec<kDim>& l) {
141 const int gx = l[0] + og[0], gy = l[1] + og[1], gz = l[2] + og[2];
142 const double a = hu(idx.localMdToLocal(l));
144 hur((
long)(gx +
G) + (
long)(gy +
G) * ge.x + (
long)(gz +
G) * (
long)ge.x * ge.y);
145 const double d = std::fabs(a - r);
149 if (maxdiff > 1e-12) {
151 std::fprintf(stderr,
"[rank %d] max|distributed - serial| = %.3e\n", rank, maxdiff);
156 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
159 std::printf(
"OK (np=%d): distributed RB-GS diffusion == serial reference\n", size);
161 std::fprintf(stderr,
"FAILED (np=%d): %d ranks differ\n", size, totalFail);
165 return totalFail == 0 ? 0 : 1;
void diffSmoothColor(SField c, SConst b, I3 e, I3 og, int g, double bx, double by, double bz, double Ac, int color, SConst dcorr, bool aniso)