26static std::vector<double>
packingSdf(
double rfrac = 0.18) {
27 const double R = rfrac *
N;
28 std::vector<double> sdf((std::size_t)
N *
N *
N);
29 const double cs[2] = {0.25 *
N, 0.75 *
N};
30 for (
int z = 0; z <
N; ++z)
31 for (
int y = 0; y <
N; ++y)
32 for (
int x = 0; x <
N; ++x) {
36 for (
double sz : cs) {
37 auto wrap = [](
double d) {
return d -
N * std::round(d /
N); };
38 const double dx = wrap(x - sx), dy = wrap(y - sy), dz = wrap(z - sz);
39 best = std::min(best, std::sqrt(dx * dx + dy * dy + dz * dz) - R);
41 sdf[(std::size_t)x + (std::size_t)y *
N + (std::size_t)z *
N *
N] = best;
61static std::vector<double>
localSdf(
const std::vector<double>& gsdf,
const BlockDecomposer<3>& dec,
63 auto b = dec.block(rank);
64 const int ox = (int)b.origin[0], oy = (
int)b.origin[1], oz = (int)b.origin[2];
65 const int lnx = (int)b.size[0], lny = (
int)b.size[1], lnz = (int)b.size[2];
66 std::vector<double> l((std::size_t)lnx * lny * lnz);
67 for (
int z = 0; z < lnz; ++z)
68 for (
int y = 0; y < lny; ++y)
69 for (
int x = 0; x < lnx; ++x)
70 l[(std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny] =
71 gsdf[(std::size_t)(x + ox) + (std::size_t)(y + oy) *
N + (std::size_t)(z + oz) *
N *
N];
83int main(
int argc,
char** argv) {
84 MPI_Init(&argc, &argv);
85 Kokkos::initialize(argc, argv);
86 int fail = 0, size = 1, rank = 0;
88 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
89 MPI_Comm_size(MPI_COMM_WORLD, &size);
91 const double gcells = (double)
N *
N *
N;
94 BlockDecomposer<3> D1((std::size_t)size, IVec<3>{
N,
N,
N});
95 std::vector<peclet::core::Real> w((std::size_t)
N *
N *
N, 1.0);
96 for (
int z = 0; z <
N; ++z)
97 for (
int y = 0; y <
N; ++y)
98 for (
int x = 0; x <
N; ++x)
100 w[(std::size_t)x + (std::size_t)y *
N + (std::size_t)z *
N *
N] = 6.0;
101 BlockDecomposer<3> D2((std::size_t)size, IVec<3>{
N,
N,
N}, w);
104 auto b1 = D1.block(rank);
105 IbmSolver sd((
int)b1.size[0], (
int)b1.size[1], (
int)b1.size[2]);
106 sd.initMpi(D1, MPI_COMM_WORLD);
108 sd.setSolid(
localSdf(gsdf, D1, rank),
true);
109 for (
int it = 0; it <
STEPS / 2; ++it)
111 double uPre = 0, uPost = 0;
114 MPI_Allreduce(&l, &uPre, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
119 MPI_Allreduce(&l, &uPost, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
122 std::printf(
" global-u sum pre=%.12e post=%.12e |d|=%.2e (redistribute data movement)\n",
123 uPre, uPost, std::fabs(uPre - uPost));
127 MPI_Allreduce(&lsum, &gsum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
128 const double k_dist =
MU * (gsum / gcells) /
F;
129 const double div_dist = sd.maxOpenDivergence();
134 IbmSolver ref(
N,
N,
N);
136 ref.setSolid(gsdf,
true);
137 for (
int it = 0; it <
STEPS; ++it)
140 for (
double v : ref.getVelocity(0))
142 k_ref =
MU * (rsum / gcells) /
F;
144 MPI_Bcast(&k_ref, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
146 const double reld = std::fabs(k_dist - k_ref) / (std::fabs(k_ref) + 1e-30);
147 const double tol = (size == 1) ? 1e-12 : 2e-5;
150 " k_dist=%.8e k_ref=%.8e rel=%.2e div=%.2e (np=%d, tol %.0e, redistributed)\n",
151 k_dist, k_ref, reld, div_dist, size, tol);
152 if (reld > tol || !(div_dist < 1e-5))
156 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
158 std::printf(totalFail == 0 ?
"OK (np=%d): mid-run redistribute preserves the solution\n"
159 :
"FAILED (np=%d)\n",
163 return totalFail == 0 ? 0 : 1;