38#include <Kokkos_Core.hpp>
49 std::fprintf(stderr, "CHECK failed: %s\n at %s:%d\n", #cond, __FILE__, __LINE__); \
54constexpr int NX = 24,
NY = 24,
NZ = 16;
56constexpr int MAXIT = 200;
57constexpr double RTOL = 1e-8;
58constexpr int STEPS = 8;
59constexpr double MU = 0.01,
DT = 1.0,
ULID = 1.0,
GRAV = 0.1;
62constexpr double DIV_TOL = 1e-8;
64enum Driver { kPcg = 0, kFcg = 1, kCheb = 2 };
65const char* driverName(Driver d) {
66 return d == kPcg ?
"MG-PCG" : (
d == kFcg ?
"FCG " :
"Cheb ");
69double maxAbs(
const std::vector<double>& v) {
72 m = std::fmax(
m, std::fabs(
x));
82 s.setPressurePcg(
true, MAXIT, RTOL);
84 s.setPressureFcg(
true, MAXIT, RTOL);
86 s.setPressureChebyshev(
true, MAXIT, RTOL);
114void run(
const Case& cs, Driver d) {
116 s.setPressureCoarseGhost(!gAblate);
120 s.setAdvection(
false);
121 s.setDomainBc(4, 1, 0, 0, 0);
123 s.setDomainBc(5, 2,
ULID, 0.0, 0.0);
125 s.setDomainBc(5, 1, 0, 0, 0);
127 s.setDomainBc(0, 1, 0, 0, 0);
128 s.setDomainBc(1, 1, 0, 0, 0);
131 s.setPressureGeometry(std::vector<double>((std::size_t)
NX *
NY *
NZ, 10.0));
133 if (
cs.ratio > 0.0) {
134 std::vector<double>
rho((std::size_t)
NX *
NY *
NZ);
135 for (
int z = 0;
z <
NZ; ++
z) {
136 const bool heavy =
cs.heavyAbove ? (
z >=
NZ / 2) : (
z <
NZ / 2);
137 for (
int y = 0;
y <
NY; ++
y)
138 for (
int x = 0;
x <
NX; ++
x)
139 rho[(std::size_t)
x + (std::size_t)y *
NX + (std::size_t)
z *
NX *
NY] =
140 heavy ?
cs.ratio : 1.0;
143 s.setField(
"rho", rho);
144 s.setDensityMode(
true);
147 }
else if (
cs.gravity) {
148 s.setBodyForce(0.0, 0.0, -
GRAV);
152 long itMax = 0, itMed = 0;
153 std::vector<long>
its;
155 for (
int k = 0;
k <
STEPS; ++
k) {
157 its.push_back(
s.lastPressureIterations());
158 div =
s.maxOpenDivergence();
160 const double umax = std::fmax(
maxAbs(
s.getVelocity(0)),
165 itMax = std::max(itMax,
v);
167 std::vector<long> sorted =
its;
168 std::sort(sorted.begin(), sorted.end());
169 itMed = sorted[sorted.size() / 2];
171 const bool gated = (
cs.gate >> (
int)d) & 1;
172 std::printf(
" %-22s %s its median %3ld max %3ld div/u %.2e max|u| %.3e%s\n",
cs.name,
173 driverName(d), itMed, itMax, divRel, umax,
174 gated ?
"" :
" [open: S3 coefficient coarsening, not gated]");
178 CHECK(std::isfinite(umax));
179 CHECK(itMax < MAXIT);
180 CHECK(divRel < DIV_TOL);
184int main(
int argc,
char** argv) {
185 for (
int i = 1; i < argc; ++i)
186 if (std::strcmp(argv[i],
"--no-coarse-ghost") == 0)
188 Kokkos::initialize(argc, argv);
190 std::printf(
"3-D wall-bounded pressure convergence: %dx%dx%d, %d levels, %d steps, cap %d%s\n",
192 gAblate ?
" [--no-coarse-ghost — pre-WO-H ablation, EXPECTED TO FAIL]" :
"");
193 const int ALL = (1 << kPcg) | (1 << kFcg) | (1 << kCheb);
194 const int FCG_CHEB = (1 << kFcg) | (1 << kCheb);
195 const int CHEB_ONLY = (1 << kCheb);
196 const Case cases[] = {
198 {
"A lid box const-rho",
true,
false, 0.0,
false, ALL},
199 {
"B hydrostatic const",
false,
true, 0.0,
false, ALL},
200 {
"C hydro strat 1e2",
false,
true, 1e2,
false, FCG_CHEB},
201 {
"C hydro strat 1e3",
false,
true, 1e3,
false, CHEB_ONLY},
202 {
"D inflow small-c 1e2",
true,
false, 1e2,
true, FCG_CHEB},
203 {
"D inflow small-c 1e3",
true,
false, 1e3,
true, FCG_CHEB},
205 for (
const Case& c : cases)
206 for (Driver d : {kPcg, kFcg, kCheb})
209 std::printf(
"PASS: %zu wall-bounded configurations x 3 drivers (14 gated) on nz = %d\n",
210 sizeof(cases) /
sizeof(cases[0]),
NZ);
212 std::fprintf(stderr,
"FAIL: %d check(s)\n",
failures);
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
static constexpr int STEPS
static double maxAbs(const std::vector< double > &a)
static constexpr double GRAV
static constexpr double DT
static constexpr double MU
static constexpr int LEVELS
static constexpr double ULID