flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
test_sdflow_colocated_mpi.cpp
Go to the documentation of this file.
1// cfd-gpu — the assembled multi-rank COLLOCATED solver step (collocated plan phase 5c).
2//
3// The collocated counterpart of test_sdflow_mpi: solves creeping (Stokes) flow through a periodic
4// 2x2x2 sphere packing with Solver<Colocated>, two ways -- single-rank on the full grid, and
5// distributed (each rank constructs the solver with its ORB block dims, calls initMpi, setSolid
6// with its LOCAL SDF block). The collocated approximate (MAC) projection runs multi-rank on exactly
7// the same transport-core halo machinery as the staggered solver: the cell-velocity halo feeds
8// centerToFace, the projected face field is halo-exchanged, the cut-cell pressure MG is MPI-folded.
9// The superficial velocity <u> (hence the permeability k = mu*<u>/F) is reduced over ranks and must
10// equal single-rank: np=1 bit-exact, np>1 to the MG-PCG reduction-order floor (the inner-product
11// Allreduce reorders the Krylov path). Build with -DCFD_MPI.
12#include <mpi.h>
13
14#include <cmath>
15#include <cstdio>
16#include <Kokkos_Core.hpp>
17#include <vector>
18
19#include "flow_ibm.hpp"
20#include "peclet/core/common/types.hpp"
21#include "peclet/core/decomp/block_decomposer.hpp"
22
23using peclet::core::IVec;
25
26static constexpr int N = 32, STEPS = 120;
27static constexpr double RHO = 1.0, MU = 0.1, F = 1e-3, DT = 60.0;
28
29// global sphere-packing SDF (flat x-fastest, negative inside), 2x2x2 spheres, periodic
30// min-distance.
31static std::vector<double> packingSdf(double rfrac = 0.18) {
32 const double R = rfrac * N;
33 std::vector<double> sdf((std::size_t)N * N * N);
34 const double cs[2] = {0.25 * N, 0.75 * N};
35 for (int z = 0; z < N; ++z)
36 for (int y = 0; y < N; ++y)
37 for (int x = 0; x < N; ++x) {
38 double best = 1e30;
39 for (double sx : cs)
40 for (double sy : cs)
41 for (double sz : cs) {
42 auto wrap = [](double d) { return d - N * std::round(d / N); };
43 const double dx = wrap(x - sx), dy = wrap(y - sy), dz = wrap(z - sz);
44 best = std::min(best, std::sqrt(dx * dx + dy * dy + dz * dz) - R);
45 }
46 sdf[(std::size_t)x + (std::size_t)y * N + (std::size_t)z * N * N] = best;
47 }
48 return sdf;
49}
50
51static void configure(Colo& s) {
52 s.setRho(RHO);
53 s.setMu(MU);
54 s.setDt(DT);
55 s.setBodyForce(F, 0, 0);
56 s.setAdvection(false);
59 s.setPressurePcg(true, 200, 1e-9);
60}
61
62static double localUSum(Colo& s) {
63 auto u = s.getVelocity(0);
64 double sum = 0;
65 for (double v : u)
66 sum += v;
67 return sum;
68}
69
70int main(int argc, char** argv) {
71 MPI_Init(&argc, &argv);
72 Kokkos::initialize(argc, argv);
73 int fail = 0, size = 1, rank = 0;
74 {
75 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
76 MPI_Comm_size(MPI_COMM_WORLD, &size);
77 const std::vector<double> gsdf = packingSdf();
78 const double gcells = (double)N * N * N;
79
80 // --- distributed solve ---
81 peclet::core::decomp::BlockDecomposer<3> dec(static_cast<std::size_t>(size), IVec<3>{N, N, N});
82 auto blk = dec.block(rank);
83 const int ox = (int)blk.origin[0], oy = (int)blk.origin[1], oz = (int)blk.origin[2];
84 const int lnx = (int)blk.size[0], lny = (int)blk.size[1], lnz = (int)blk.size[2];
85 std::vector<double> lsdf((std::size_t)lnx * lny * lnz);
86 for (int z = 0; z < lnz; ++z)
87 for (int y = 0; y < lny; ++y)
88 for (int x = 0; x < lnx; ++x)
89 lsdf[(std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny] =
90 gsdf[(std::size_t)(x + ox) + (std::size_t)(y + oy) * N +
91 (std::size_t)(z + oz) * N * N];
92
93 Colo sd(lnx, lny, lnz);
94 sd.initMpi(N, N, N, MPI_COMM_WORLD);
95 configure(sd);
96 sd.setSolid(lsdf, /*cutcell_pressure=*/true);
97 for (int it = 0; it < STEPS; ++it)
98 sd.step();
99 double lsum = localUSum(sd), gsum = 0;
100 MPI_Allreduce(&lsum, &gsum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
101 const double k_dist = MU * (gsum / gcells) / F;
102 const double div_dist = sd.maxOpenDivergence();
103
104 // --- single-rank reference (full grid) on rank 0 ---
105 double k_ref = 0.0;
106 if (rank == 0) {
107 Colo ref(N, N, N);
108 configure(ref);
109 ref.setSolid(gsdf, true);
110 for (int it = 0; it < STEPS; ++it)
111 ref.step();
112 double rsum = 0;
113 {
114 auto u = ref.getVelocity(0);
115 for (double v : u)
116 rsum += v;
117 }
118 k_ref = MU * (rsum / gcells) / F;
119 }
120 MPI_Bcast(&k_ref, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
121
122 const double reld = std::fabs(k_dist - k_ref) / (std::fabs(k_ref) + 1e-30);
123 const double tol =
124 (size == 1) ? 1e-12 : 2e-5; // np=1 bit-exact; np>1 the MG-PCG reduction-order floor
125 if (rank == 0)
126 std::printf(" k_dist=%.8e k_ref=%.8e rel=%.2e div=%.2e (np=%d, tol %.0e)\n", k_dist,
127 k_ref, reld, div_dist, size, tol);
128 if (reld > tol || !(div_dist < 1e-5))
129 fail = 1;
130 }
131 int totalFail = 0;
132 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
133 if (rank == 0) {
134 if (totalFail == 0)
135 std::printf("OK (np=%d): distributed collocated Stokes permeability == single-rank\n", size);
136 else
137 std::fprintf(stderr, "FAILED (np=%d)\n", size);
138 }
139 Kokkos::finalize();
140 MPI_Finalize();
141 return totalFail == 0 ? 0 : 1;
142}
void setSolid(const std::vector< double > &sdfInner, bool cutcellPressure)
Definition flow_ibm.hpp:435
void setPressurePcg(bool, int maxit, double rtol)
Definition flow_ibm.hpp:204
double maxOpenDivergence()
Definition flow_ibm.hpp:685
void setAdvection(bool on)
Definition flow_ibm.hpp:142
void setVelocityIterations(int it)
Definition flow_ibm.hpp:140
void setPressureLevels(int levels)
Definition flow_ibm.hpp:179
void setDt(double d)
Definition flow_ibm.hpp:138
void setBodyForce(double fx, double fy, double fz)
Definition flow_ibm.hpp:139
std::vector< double > getVelocity(int c)
Definition flow_ibm.hpp:652
void setMu(double m)
Definition flow_ibm.hpp:137
void setRho(double r)
Definition flow_ibm.hpp:136
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
int main(int argc, char **argv)
static constexpr double RHO
static constexpr double MU
static constexpr int STEPS
static constexpr int N
static void configure(Colo &s)
static constexpr double DT
static constexpr double F
static double localUSum(Colo &s)
static std::vector< double > packingSdf(double rfrac=0.18)