72int main(
int argc,
char** argv) {
73 MPI_Init(&argc, &argv);
74 Kokkos::initialize(argc, argv);
75 int fail = 0, size = 1, rank = 0;
76 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
77 MPI_Comm_size(MPI_COMM_WORLD, &size);
79 const double centres[4] = {0.5 *
N,
N - 0.5, -0.5, 0.5 *
N};
80 const int cutWallY[4] = {0, 0, 0, 1};
81 const char* label[4] = {
"clear of the open faces",
"cutting the OUTFLOW face",
82 "cutting the INFLOW face",
"cutting the -y WALL"};
83 peclet::core::decomp::BlockDecomposer<3> dec =
84 peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
N,
N,
N);
85 auto blk = dec.block(rank);
86 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
87 const int lnx = (int)blk.size[0], lny = (
int)blk.size[1], lnz = (int)blk.size[2];
88 for (
int cs = 0; cs < 4; ++cs) {
89 const std::vector<double> gsdf =
91 std::vector<double> lsdf((std::size_t)lnx * lny * lnz);
92 for (
int z = 0; z < lnz; ++z)
93 for (
int y = 0; y < lny; ++y)
94 for (
int x = 0; x < lnx; ++x)
95 lsdf[(std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny] =
96 gsdf[(std::size_t)(x + ox) + (std::size_t)(y + oy) *
N +
97 (std::size_t)(z + oz) *
N *
N];
100 sd.initMpi(
N,
N,
N, MPI_COMM_WORLD);
104 for (
int it = 0; it <
STEPS; ++it) {
112 std::vector<double> ur((std::size_t)
N *
N *
N);
113 std::vector<double> orr[3] = {std::vector<double>((std::size_t)
N *
N *
N),
114 std::vector<double>((std::size_t)
N *
N *
N),
115 std::vector<double>((std::size_t)
N *
N *
N)};
122 for (
int it = 0; it <
STEPS; ++it) {
132 MPI_Bcast(ur.data(), (
int)ur.size(), MPI_DOUBLE, 0, MPI_COMM_WORLD);
133 MPI_Bcast(&itersR, 1, MPI_LONG, 0, MPI_COMM_WORLD);
134 MPI_Bcast(&divR, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
135 for (
int q = 0; q < 3; ++q)
136 MPI_Bcast(orr[q].data(), (
int)orr[q].size(), MPI_DOUBLE, 0, MPI_COMM_WORLD);
139 for (
int z = 0; z < lnz; ++z)
140 for (
int y = 0; y < lny; ++y)
141 for (
int x = 0; x < lnx; ++x)
142 for (
int q = 0; q < 3; ++q) {
143 const std::size_t li =
144 (std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny;
145 const std::size_t gi = (std::size_t)(x + ox) + (std::size_t)(y + oy) *
N +
146 (std::size_t)(z + oz) *
N *
N;
147 dop = std::max(dop, std::fabs(od[q][li] - orr[q][gi]));
150 MPI_Allreduce(&dop, &gdop, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
153 std::printf(
" openness dist-vs-single max diff %.3e (must be 0)\n", gdop);
158 double d = 0, umax = 0;
159 for (
int z = 0; z < lnz; ++z)
160 for (
int y = 0; y < lny; ++y)
161 for (
int x = 0; x < lnx; ++x) {
162 const std::size_t li =
163 (std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny;
164 const std::size_t gi =
165 (std::size_t)(x + ox) + (std::size_t)(y + oy) *
N + (std::size_t)(z + oz) *
N *
N;
166 d = std::max(d, std::fabs(ud[li] - ur[gi]));
167 umax = std::max(umax, std::fabs(ur[gi]));
169 double g[2] = {d, umax}, gg[2];
170 MPI_Allreduce(g, gg, 2, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
171 const double rel = gg[0] / gg[1];
172 const double tol = (size == 1) ? 1e-13 : 1e-7;
175 "[openbc-solid-mpi] np=%d sphere %-24s dist-vs-single rel %.2e (tol %.0e) "
176 "iters %ld/%ld proj max|div| %.2e/%.2e\n",
177 size, label[cs], rel, tol, itersD, itersR, divD, divR);
182 if (!(divD < 1e-6) || !(divR < 1e-6))
187 MPI_Allreduce(&fail, &gfail, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
189 std::printf(
"[openbc-solid-mpi] %s\n", gfail ?
"FAILED" :
"OK");