75 const std::size_t n = (std::size_t)ext.
x * ext.
y * ext.
z;
76 CCField ox(
"ox", n), oy(
"oy", n), oz(
"oz", n);
77 Kokkos::deep_copy(ox, 1.0);
78 Kokkos::deep_copy(oy, 1.0);
79 Kokkos::deep_copy(oz, 1.0);
80 mg.
setOpenness(CCConst(ox), CCConst(oy), CCConst(oz), 1.0, 1.0, 1.0);
81 CCField b(
"b", n), x(
"x", n), r(
"r", n), p(
"p", n), z(
"z", n), Ap(
"Ap", n);
84 res.iters = mg.
solvePCG(b, x, r, p, z, Ap, 300, 1e-10, 2, 2, 8);
85 res.x = Kokkos::create_mirror_view(x);
86 Kokkos::deep_copy(res.x, x);
105int main(
int argc,
char** argv) {
106 MPI_Init(&argc, &argv);
107 Kokkos::initialize(argc, argv);
108 int rank = 0, size = 1;
109 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
110 MPI_Comm_size(MPI_COMM_WORLD, &size);
126 const Case cases[] = {
127 {
"A control 32^3 in-place", {32, 32, 32}, 4, -1,
false, -1},
128 {
"B forced telescope@1 32^3", {32, 32, 32}, 4, 1,
true, -1},
129 {
"C0 starved 24^3, no telescope", {24, 24, 24}, 6, -1,
false, 0},
130 {
"C1 starved 24^3, telescope", {24, 24, 24}, 6, -1,
true, 0},
132 int itersC0 = -1, itersC1 = -1, itersRef = -1, teleC1 = 0;
133 C3 cgC0{}, cgC1{}, cgRef{};
134 for (
const Case& c : cases) {
135 if (size == 1 && c.tele)
141 peclet::core::decomp::BlockDecomposer<3> plain((std::size_t)size, c.gs);
142 mg.initMpi(c.gs[0], c.gs[1], c.gs[2], c.nlev, MPI_COMM_WORLD,
143 c.name[0] ==
'C' ? &plain :
nullptr);
144 CutcellMG::Level& l0 = mg.
level(0);
148 ref.setAgglomerationMode(c.bottom);
149 ref.init(c.gs[0], c.gs[1], c.gs[2], c.nlev);
150 const C3 re{c.gs[0] + 2 *
G, c.gs[1] + 2 *
G, c.gs[2] + 2 *
G}, ro{0, 0, 0};
153 double maxdiff =
compareBlock(d, l0, r, re), gmax = 0.0;
154 MPI_Allreduce(&maxdiff, &gmax, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
157 const double tol = (size == 1) ? 1e-13 : 1e-7;
158 const bool ok = gmax <= tol;
162 std::printf(
" %-42s np=%d levels(rank0)=%d iters=%3d max|dist-ref|=%.3e %s\n", c.name,
163 size, mg.
localLevels(), d.iters, gmax, ok ?
"ok" :
"FAIL");
164 if (c.name[0] ==
'C' && c.name[1] ==
'0') {
168 if (c.name[0] ==
'C' && c.name[1] ==
'1') {
173 cgRef = ref.coarsestGlobal();
176 if (size > 1 && itersC1 >= 0) {
180 MPI_Bcast(&tele0, 1, MPI_INT, 0, MPI_COMM_WORLD);
181 int cg[3] = {cgC1.x, cgC1.y, cgC1.z};
182 MPI_Bcast(
cg, 3, MPI_INT, 0, MPI_COMM_WORLD);
183 const bool sameBottom = (
cg[0] == cgRef.x &&
cg[1] == cgRef.y &&
cg[2] == cgRef.z);
184 const bool ok = (tele0 >= 1) && sameBottom && (std::abs(itersC1 - itersRef) <= 1);
189 " starved 24^3: coarsest global no-telescope %dx%dx%d, telescope %dx%dx%d "
190 "(%d telescope%s), single-rank %dx%dx%d; iterations %d / %d / %d %s\n",
191 cgC0.x, cgC0.y, cgC0.z,
cg[0],
cg[1],
cg[2], tele0, tele0 == 1 ?
"" :
"s", cgRef.x,
192 cgRef.y, cgRef.z, itersC0, itersC1, itersRef,
193 ok ?
"ok" :
"FAIL (telescoped hierarchy != single-rank)");
200 const IVec<3> gs{48, 32, 32};
201 std::vector<double> w((std::size_t)gs[0] * gs[1] * gs[2]);
202 for (Index z = 0; z < gs[2]; ++z)
203 for (Index y = 0; y < gs[1]; ++y)
204 for (Index x = 0; x < gs[0]; ++x)
205 w[(std::size_t)(x + y * gs[0] + z * gs[0] * gs[1])] = x < 3 ? 20.0 : 1.0;
206 peclet::core::decomp::BlockDecomposer<3> weighted((std::size_t)size, gs, w);
207 const bool oddRoot = (weighted.block(0).size[0] % 2) != 0;
210 int teleN[2] = {0, 0}, repN[2] = {0, 0};
212 for (
int k = 0; k < 2; ++k) {
216 mg.initMpi(gs[0], gs[1], gs[2], nlev, MPI_COMM_WORLD, &weighted);
217 CutcellMG::Level& l0 = mg.
level(0);
224 ref.setAgglomerationMode(-1);
225 ref.init(gs[0], gs[1], gs[2], nlev);
226 const C3 re{gs[0] + 2 *
G, gs[1] + 2 *
G, gs[2] + 2 *
G}, ro{0, 0, 0};
229 for (std::size_t i = 0; i < d[1].x.extent(0); ++i)
230 dc = std::max(dc, std::fabs(d[1].x(i) - d[0].x(i)));
231 double g[2] = {dr, dc}, gmax[2] = {0.0, 0.0};
232 MPI_Allreduce(g, gmax, 2, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
233 int rep0 = repN[1], tele0 = teleN[0];
234 int cgr[3] = {
cg[1].x,
cg[1].y,
cg[1].z};
235 MPI_Bcast(&rep0, 1, MPI_INT, 0, MPI_COMM_WORLD);
236 MPI_Bcast(&tele0, 1, MPI_INT, 0, MPI_COMM_WORLD);
237 MPI_Bcast(cgr, 3, MPI_INT, 0, MPI_COMM_WORLD);
238 const C3 cgRef = ref.coarsestGlobal();
239 const bool ok = oddRoot && rep0 >= 1 && gmax[0] <= 1e-7 && gmax[1] <= 1e-7 &&
240 cgr[0] == cgRef.
x && cgr[1] == cgRef.
y && cgr[2] == cgRef.
z &&
241 std::abs(d[1].iters - r.iters) <= 1;
246 " %-42s np=%d root split x=%ld (%s) collapse: %d telescope(s), %d iters; "
247 "repartition: %d repartition stage(s), %d iters, coarsest %dx%dx%d; single-rank "
248 "%d iters, coarsest %dx%dx%d max|rep-ref|=%.3e max|rep-collapse|=%.3e %s\n",
249 "D weighted dec0 48x32x32, repartition", size, (
long)weighted.block(0).size[0],
250 oddRoot ?
"odd" :
"EVEN - precondition broken", tele0, d[0].iters, rep0, d[1].iters,
251 cgr[0], cgr[1], cgr[2], r.iters, cgRef.
x, cgRef.
y, cgRef.
z, gmax[0], gmax[1],
257 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
260 std::printf(
"OK (np=%d): telescoped CutcellMG == single-rank reference\n", size);
262 std::fprintf(stderr,
"FAILED (np=%d)\n", size);
266 return totalFail == 0 ? 0 : 1;