105static std::vector<double>
gatherGlobal(
const std::vector<double>& local,
int ox,
int oy,
int oz,
106 int lnx,
int lny,
int lnz,
int rank,
int size) {
107 std::vector<double> global;
109 global.assign(
GCELLS, 0.0);
110 for (
int r = 0; r < size; ++r) {
111 int meta[6] = {ox, oy, oz, lnx, lny, lnz};
114 for (
int z = 0; z < lnz; ++z)
115 for (
int y = 0; y < lny; ++y)
116 std::memcpy(&global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
117 (std::size_t)(z + oz) *
NX *
NY],
118 &local[(std::size_t)y * lnx + (std::size_t)z * lnx * lny],
119 (std::size_t)lnx *
sizeof(
double));
123 MPI_Send(meta, 6, MPI_INT, 0, 100 + r, MPI_COMM_WORLD);
124 MPI_Send(local.data(), (
int)local.size(), MPI_DOUBLE, 0, 200 + r, MPI_COMM_WORLD);
125 }
else if (rank == 0) {
126 MPI_Recv(meta, 6, MPI_INT, r, 100 + r, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
127 std::vector<double> buf((std::size_t)meta[3] * meta[4] * meta[5]);
128 MPI_Recv(buf.data(), (
int)buf.size(), MPI_DOUBLE, r, 200 + r, MPI_COMM_WORLD,
130 for (
int z = 0; z < meta[5]; ++z)
131 for (
int y = 0; y < meta[4]; ++y)
132 std::memcpy(&global[(std::size_t)meta[0] + (std::size_t)(y + meta[1]) *
NX +
133 (std::size_t)(z + meta[2]) *
NX *
NY],
134 &buf[(std::size_t)y * meta[3] + (std::size_t)z * meta[3] * meta[4]],
135 (std::size_t)meta[3] *
sizeof(
double));
159static int runCase(
const Config& c,
const peclet::core::decomp::BlockDecomposer<3>& dec,
int rank,
161 auto blk = dec.block(rank);
162 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
163 const int lnx = (int)blk.size[0], lny = (
int)blk.size[1], lnz = (int)blk.size[2];
165 sd.initMpi(dec, MPI_COMM_WORLD);
166 configure(sd, c, ox, oy, oz, lnx, lny, lnz);
167 std::vector<long> pd, bd;
169 for (
int it = 0; it < c.steps; ++it) {
171 pd.push_back(sd.lastPressureIterations());
172 bd.push_back(sd.lastBalancedForceIterations());
173 if (it == c.rebalance) {
174 std::vector<peclet::core::Real> w(
GCELLS, 1.0);
175 for (
int z = 0; z <
NZ / 2; ++z)
176 for (
int y = 0; y <
NY; ++y)
177 for (
int x = 0; x <
NX; ++x)
178 w[(std::size_t)x + (std::size_t)y *
NX + (std::size_t)z *
NX *
NY] = 4.0;
179 const auto o0 = sd.blockOrigin();
180 const long n0 = sd.nx() * sd.ny() * sd.nz();
181 sd.rebalanceByWeights(w);
182 const auto o1 = sd.blockOrigin();
183 int mv = (o0 != o1 || n0 != sd.nx() * sd.ny() * sd.nz()) ? 1 : 0, gmv = 0;
184 MPI_Allreduce(&mv, &gmv, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
188 const auto o = sd.blockOrigin();
189 const int px = o[0], py = o[1], pz = o[2];
190 const int qx = (int)sd.nx(), qy = (int)sd.ny(), qz = (int)sd.nz();
191 std::vector<double> gu[3];
192 for (
int comp = 0; comp < 3; ++comp)
193 gu[comp] =
gatherGlobal(sd.getVelocity(comp), px, py, pz, qx, qy, qz, rank, size);
194 const auto gp =
gatherGlobal(sd.getPressure(), px, py, pz, qx, qy, qz, rank, size);
195 const auto gb =
gatherGlobal(sd.getField(
"p_balanced"), px, py, pz, qx, qy, qz, rank, size);
196 const auto gc =
gatherGlobal(sd.getField(
"C"), px, py, pz, qx, qy, qz, rank, size);
201 std::vector<long> pr, br;
202 for (
int it = 0; it < c.steps; ++it) {
204 pr.push_back(ref.lastPressureIterations());
205 br.push_back(ref.lastBalancedForceIterations());
207 double du = 0, su = 0;
208 for (
int comp = 0; comp < 3; ++comp) {
209 du = std::fmax(du,
maxAbsDiff(gu[comp], ref.getVelocity(comp)));
210 su = std::fmax(su,
maxAbs(ref.getVelocity(comp)));
212 const double dp =
maxAbsDiff(gp, ref.getPressure()), sp =
maxAbs(ref.getPressure());
213 const double db =
maxAbsDiff(gb, ref.getField(
"p_balanced"));
214 const double dc =
maxAbsDiff(gc, ref.getField(
"C"));
215 long dbit = 0, bsum = 0, maxd = 0, maxr = 0, sumd = 0, sumr = 0;
216 for (std::size_t k = 0; k < pd.size(); ++k) {
217 dbit = std::max(dbit, std::labs(bd[k] - br[k]));
219 maxd = std::max(maxd, pd[k]);
220 maxr = std::max(maxr, pr[k]);
229 long bmaxd = 0, bmaxr = 0, bsumd = 0;
230 for (std::size_t k = 0; k < bd.size(); ++k) {
231 bmaxd = std::max(bmaxd, bd[k]);
232 bmaxr = std::max(bmaxr, br[k]);
235 const bool bfOk = (size == 1) ? (dbit == 0)
236 : (bmaxd <= bmaxr + 1 &&
237 std::labs(bsumd - bsum) <=
static_cast<long>(bd.size()));
238 const long dpit = std::labs(sumd - sumr);
240 (size == 1) ? (pd == pr) : (maxd <= maxr + 1 && dpit <= static_cast<long>(pd.size()));
241 const double uRef = std::fmax(su, c.walls ?
GRAV *
DT : 1e-3 *
DT);
242 const double tolU = (size == 1) ? 0.0 : 1e-11 * uRef;
243 const double tolP = (size == 1) ? 0.0 : 1e-9 * std::fmax(sp, 1e-12);
244 const double tolC = (size == 1) ? 0.0 : 1e-11;
245 const bool moveOk = c.rebalance < 0 || size == 1 || moved;
246 const bool ok = du <= tolU && dp <= tolP && db <= tolP && dc <= tolC && bfOk && pOk && moveOk;
248 " [%-18s np=%d] du %.3e (|u| %.3e) dP %.3e dP_b %.3e (|P| %.3e) dC %.3e "
249 "bf-iters sum %ld d/step %ld p-iters max %ld/%ld sum %ld/%ld%s %s\n",
250 c.name, size, du, su, dp, db, sp, dc, bsum, dbit, maxd, maxr, sumd, sumr,
251 c.rebalance >= 0 ? (moved ?
" (partition MOVED)" :
" (partition did NOT move)") :
"",
252 ok ?
"OK" :
"*** FAIL ***");
256 MPI_Bcast(&fail, 1, MPI_INT, 0, MPI_COMM_WORLD);