45 const double R = rfrac *
N;
46 std::vector<double> sdf((std::size_t)
N *
N *
N);
47 const double cs[2] = {0.25 *
N, 0.75 *
N};
48 for (
int z = 0; z <
N; ++z)
49 for (
int y = 0; y <
N; ++y)
50 for (
int x = 0; x <
N; ++x) {
54 for (
double sz : cs) {
55 auto wrap = [](
double d) {
return d -
N * std::round(d /
N); };
56 const double dx = wrap(x - sx), dy = wrap(y - sy), dz = wrap(z - sz);
57 best = std::min(best, std::sqrt(dx * dx + dy * dy + dz * dz) - R);
59 sdf[(std::size_t)x + (std::size_t)y *
N + (std::size_t)z *
N *
N] = best;
79static std::vector<double>
gatherGlobal(
const std::vector<double>& local,
int ox,
int oy,
int oz,
80 int lnx,
int lny,
int lnz,
int rank,
int size) {
81 std::vector<double> global;
83 global.assign((std::size_t)
N *
N *
N, 0.0);
84 for (
int r = 0; r < size; ++r) {
85 int meta[6] = {ox, oy, oz, lnx, lny, lnz};
88 for (
int z = 0; z < lnz; ++z)
89 for (
int y = 0; y < lny; ++y)
90 std::memcpy(&global[(std::size_t)ox + (std::size_t)(y + oy) *
N +
91 (std::size_t)(z + oz) *
N *
N],
92 &local[(std::size_t)y * lnx + (std::size_t)z * lnx * lny],
93 (std::size_t)lnx *
sizeof(
double));
97 MPI_Send(meta, 6, MPI_INT, 0, 100 + r, MPI_COMM_WORLD);
98 MPI_Send(local.data(), (
int)local.size(), MPI_DOUBLE, 0, 200 + r, MPI_COMM_WORLD);
99 }
else if (rank == 0) {
100 MPI_Recv(meta, 6, MPI_INT, r, 100 + r, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
101 std::vector<double> buf((std::size_t)meta[3] * meta[4] * meta[5]);
102 MPI_Recv(buf.data(), (
int)buf.size(), MPI_DOUBLE, r, 200 + r, MPI_COMM_WORLD,
104 for (
int z = 0; z < meta[5]; ++z)
105 for (
int y = 0; y < meta[4]; ++y)
106 std::memcpy(&global[(std::size_t)meta[0] + (std::size_t)(y + meta[1]) *
N +
107 (std::size_t)(z + meta[2]) *
N *
N],
108 &buf[(std::size_t)y * meta[3] + (std::size_t)z * meta[3] * meta[4]],
109 (std::size_t)meta[3] *
sizeof(
double));
115static double relErr(
const std::vector<double>& a,
const std::vector<double>& b) {
116 double md = 0, mb = 0;
118 for (std::size_t i = 0; i < b.size(); ++i) {
119 if (std::fabs(a[i] - b[i]) > md) {
120 md = std::fabs(a[i] - b[i]);
123 mb = std::max(mb, std::fabs(b[i]));
125 if (std::getenv(
"GP_MPI_DEBUG"))
126 std::printf(
" argmax |a-b| at (%d,%d,%d)\n", (
int)(am %
N), (
int)((am /
N) %
N),
127 (
int)(am / ((std::size_t)
N *
N)));
128 return md / (mb + 1e-300);
133static int runCase(
const char* name,
double rfrac,
int mo,
int ro,
int rank,
int size) {
134 const std::vector<double> gsdf =
packingSdf(rfrac);
135 peclet::core::decomp::BlockDecomposer<3> dec(
static_cast<std::size_t
>(size), IVec<3>{
N,
N,
N});
136 auto blk = dec.block(rank);
137 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
138 const int lnx = (int)blk.size[0], lny = (
int)blk.size[1], lnz = (int)blk.size[2];
139 std::vector<double> lsdf((std::size_t)lnx * lny * lnz);
140 for (
int z = 0; z < lnz; ++z)
141 for (
int y = 0; y < lny; ++y)
142 for (
int x = 0; x < lnx; ++x)
143 lsdf[(std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny] =
144 gsdf[(std::size_t)(x + ox) + (std::size_t)(y + oy) *
N + (std::size_t)(z + oz) *
N *
N];
147 sd.initMpi(
N,
N,
N, MPI_COMM_WORLD);
149 for (
int it = 0; it <
STEPS; ++it)
151 auto gu =
gatherGlobal(sd.getVelocity(0), ox, oy, oz, lnx, lny, lnz, rank, size);
152 const double resd = sd.maxOpenDivergence();
158 for (
int it = 0; it <
STEPS; ++it)
160 const double eu =
relErr(gu, ref.getVelocity(0));
165 const double tol = (size == 1) ? 0.0 : 1e-9;
166 const bool ok = eu <= tol;
167 std::printf(
" [%-12s np=%d] u rel=%.3e tol=%.0e div(d)=%.3e div(ref)=%.3e %s\n", name,
168 size, eu, tol, resd, ref.maxOpenDivergence(), ok ?
"OK" :
"FAIL");
172 MPI_Bcast(&fail, 1, MPI_INT, 0, MPI_COMM_WORLD);
176int main(
int argc,
char** argv) {
177 MPI_Init(&argc, &argv);
178 Kokkos::initialize(argc, argv);
181 int rank = 0, size = 1;
182 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
183 MPI_Comm_size(MPI_COMM_WORLD, &size);
184 fail |= runCase<Stag>(
"stag-gp22", 0.18, 2, 2, rank, size);
185 fail |= runCase<Stag>(
"stag-gp12-tch", 0.26, 1, 2, rank, size);
186 fail |= runCase<Colo>(
"colo-gp22", 0.18, 2, 2, rank, size);
188 std::printf(
"GHOST PROJECTION MPI (np=%d): %s\n", size, fail ?
"FAIL" :
"PASS");
static std::vector< double > gatherGlobal(const std::vector< double > &local, int ox, int oy, int oz, int lnx, int lny, int lnz, int rank, int size)