68int main(
int argc,
char** argv) {
69 MPI_Init(&argc, &argv);
70 Kokkos::initialize(argc, argv);
71 int fail = 0, size = 1, rank = 0;
72 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
73 MPI_Comm_size(MPI_COMM_WORLD, &size);
74 for (
int pass = 0; pass < 2; ++pass) {
75 const bool slipZ = (pass == 1);
77 std::printf(
"[velocitymg_bc] pass %d: +-z %s\n", pass,
78 slipZ ?
"FREE-SLIP (type 4)" :
"no-slip walls");
79 const std::vector<double> gsdf =
sphereSdf();
82 peclet::core::decomp::BlockDecomposer<3> dec =
83 peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
N,
N,
N);
84 auto blk = dec.block(rank);
85 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
86 const int lnx = (int)blk.size[0], lny = (
int)blk.size[1], lnz = (int)blk.size[2];
87 std::vector<double> lsdf((std::size_t)lnx * lny * lnz);
88 for (
int z = 0; z < lnz; ++z)
89 for (
int y = 0; y < lny; ++y)
90 for (
int x = 0; x < lnx; ++x)
91 lsdf[(std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny] =
92 gsdf[(std::size_t)(x + ox) + (std::size_t)(y + oy) *
N +
93 (std::size_t)(z + oz) *
N *
N];
95 sd.initMpi(
N,
N,
N, MPI_COMM_WORLD);
99 for (
int it = 0; it <
STEPS; ++it) {
107 std::vector<double> ub((std::size_t)
N *
N *
N), uc((std::size_t)
N *
N *
N);
108 long cyclesRef = 0, sweepsRef = 0;
112 rb.setSolid(gsdf,
true);
113 for (
int it = 0; it <
STEPS; ++it) {
115 cyclesRef += rb.lastMomentumSweeps();
117 ub = rb.getVelocity(0);
121 for (
int it = 0; it <
STEPS; ++it) {
127 MPI_Bcast(ub.data(), (
int)ub.size(), MPI_DOUBLE, 0, MPI_COMM_WORLD);
128 MPI_Bcast(uc.data(), (
int)uc.size(), MPI_DOUBLE, 0, MPI_COMM_WORLD);
129 MPI_Bcast(&cyclesRef, 1, MPI_LONG, 0, MPI_COMM_WORLD);
130 MPI_Bcast(&sweepsRef, 1, MPI_LONG, 0, MPI_COMM_WORLD);
132 double dab = 0, dbc = 0, umax = 0;
133 for (
int z = 0; z < lnz; ++z)
134 for (
int y = 0; y < lny; ++y)
135 for (
int x = 0; x < lnx; ++x) {
136 const std::size_t li = (std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny;
137 const std::size_t gi =
138 (std::size_t)(x + ox) + (std::size_t)(y + oy) *
N + (std::size_t)(z + oz) *
N *
N;
139 dab = std::max(dab, std::fabs(ud[li] - ub[gi]));
140 dbc = std::max(dbc, std::fabs(ub[gi] - uc[gi]));
141 umax = std::max(umax, std::fabs(uc[gi]));
143 double g[3] = {dab, dbc, umax}, gg[3];
144 MPI_Allreduce(g, gg, 3, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
145 const double relAB = gg[0] / gg[2], relBC = gg[1] / gg[2];
146 const double tolAB = (size == 1) ? 1e-12 : 1e-7;
147 const double tolBC = 1e-5;
150 " dist-vs-single (vmg) rel %.2e (tol %.0e) vmg-vs-RBGS rel %.2e (tol %.0e) "
151 "div %.2e cycles/step %.1f (single %.1f) vs RB-GS sweeps/step %.1f (np=%d)\n",
152 relAB, tolAB, relBC, tolBC, divd, cycles / (
double)
STEPS, cyclesRef / (
double)
STEPS,
153 sweepsRef / (
double)
STEPS, size);
154 if (!(relAB <= tolAB) || !(relBC <= tolBC) ||
164 for (
int y = 0; y < lny; ++y)
165 for (
int x = 0; x < lnx; ++x)
166 wmax = std::max(wmax, std::fabs(wd[(std::size_t)x + (std::size_t)y * lnx]));
168 MPI_Allreduce(&wmax, &wg, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
170 std::printf(
" slip face -z: max|w| on the boundary plane %.2e (impermeable)\n", wg);
176 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
180 "OK (np=%d): mixed (solid + domain-BC) velocity MG distributed == single-rank == RB-GS "
181 "(walls, and +-z free-slip)\n",
184 std::fprintf(stderr,
"FAILED (np=%d)\n", size);
188 return totalFail == 0 ? 0 : 1;