50int main(
int argc,
char** argv) {
51 MPI_Init(&argc, &argv);
52 int rank = 0, size = 1;
53 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
54 MPI_Comm_size(MPI_COMM_WORLD, &size);
57 const double dmin[3] = {0.0, 0.0, 0.0};
58 const double dsize[3] = {10.0, 8.0, 6.0};
59 IVec<3> gsize{40, 32, 24};
60 BlockDecomposer<3> dec(
static_cast<std::size_t
>(size), gsize);
63 for (
int i = 0; i < 3; ++i) {
64 map.origin[i] =
dmin[i];
65 map.cellSize[i] = dsize[i] /
static_cast<double>(gsize[i]);
66 map.periodic[i] =
true;
68 ParticleMigrator<3> mig;
69 mig.init(dec, rank, map, MPI_COMM_WORLD);
72 const std::int64_t N = 5000;
74 std::vector<Vec<3>> pos;
75 std::vector<char> payload;
76 for (std::int64_t
id = rank;
id < N;
id += size) {
77 Vec<3> x{
dmin[0] +
frac((std::uint64_t)
id * 3 + 0) * dsize[0],
78 dmin[1] +
frac((std::uint64_t)
id * 3 + 1) * dsize[1],
79 dmin[2] +
frac((std::uint64_t)
id * 3 + 2) * dsize[2]};
82 p.
pos[0] = (float)x[0];
83 p.pos[1] = (float)x[1];
84 p.pos[2] = (float)x[2];
88 p.shape_id = (int)(
id % 4);
90 std::size_t off = payload.size();
91 payload.resize(off + stride);
92 std::memcpy(&payload[off], &p, stride);
95 std::int64_t expectSum = N * (N - 1) / 2, expectXor = 0;
96 for (std::int64_t i = 0; i < N; ++i)
100 for (
int step = 0; step < 6; ++step) {
101 mig.migrate(pos, payload, stride);
103 std::int64_t lcount = (std::int64_t)pos.size(), lsum = 0, lxor = 0;
104 for (std::size_t k = 0; k < pos.size(); ++k) {
105 if (mig.ownerOf(pos[k]) != rank)
108 std::memcpy(&p, &payload[k * stride], stride);
112 std::int64_t gcount = 0, gsum = 0, gxor = 0;
113 MPI_Allreduce(&lcount, &gcount, 1, MPI_INT64_T, MPI_SUM, MPI_COMM_WORLD);
114 MPI_Allreduce(&lsum, &gsum, 1, MPI_INT64_T, MPI_SUM, MPI_COMM_WORLD);
115 MPI_Allreduce(&lxor, &gxor, 1, MPI_INT64_T, MPI_BXOR, MPI_COMM_WORLD);
116 if (gcount != N || gsum != expectSum || gxor != expectXor) {
118 std::fprintf(stderr,
" step %d FAILED: count=%lld sum=%lld xor=%lld\n", step,
119 (
long long)gcount, (
long long)gsum, (
long long)gxor);
124 for (std::size_t k = 0; k < pos.size(); ++k) {
126 std::memcpy(&p, &payload[k * stride], stride);
127 for (
int i = 0; i < 3; ++i)
128 pos[k][i] += (
frac((std::uint64_t)p.
id * 7 + i + step * 131) - 0.5) * 0.25 * dsize[i];
134 const double rcut = 0.5;
135 std::vector<Vec<3>> gpos;
136 std::vector<char> gpay;
137 std::size_t nghost = mig.gatherGhosts(pos, payload, stride, rcut, gpos, gpay);
140 for (std::size_t k = 0; k < gpos.size(); ++k)
141 if (!mig.withinRcutOfBlock(gpos[k], rank, rcut, img))
143 long long lg = (
long long)nghost, gghost = 0;
144 MPI_Reduce(&lg, &gghost, 1, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD);
147 MPI_Allreduce(&fail, &total, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
149 std::printf(
"# %lld ghost particles gathered (rcut=%.2f)\n", gghost, rcut);
151 std::printf(
"OK (np=%d): %lld packing particles migrate+ghost correctly over 6 steps\n", size,
154 std::fprintf(stderr,
"FAILED (np=%d): %d\n", size, total);
157 return total == 0 ? 0 : 1;
static double frac(std::uint64_t x)
int main(int argc, char **argv)