49#include <Kokkos_Core.hpp>
54#include "peclet/core/common/types.hpp"
55#include "peclet/core/decomp/block_decomposer.hpp"
57using peclet::core::IVec;
71 const int q[3] = {x, y, z}, n[3] = {
NX,
NY,
NZ};
72 return (q[c.axis] < n[c.axis] / 2) ?
RATIO : 1.0;
77 std::vector<double> v((std::size_t)
lnx *
lny *
lnz);
78 for (
int z = 0; z <
lnz; ++z)
79 for (
int y = 0; y <
lny; ++y)
80 for (
int x = 0; x <
lnx; ++x)
81 v[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] =
82 f(x + ox, y + oy, z + oz);
89 s.
setMu(c.walls ? 0.0 : 0.1);
100 s.
setField(
"rho",
blockOf([&](
int x,
int y,
int z) {
return rhoAt(c, x, y, z); }, ox, oy, oz,
lnx,
121static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
122 int lnx,
int lny,
int lnz,
int rank,
int size) {
123 std::vector<double>
global;
126 for (
int r = 0; r < size; ++r) {
130 for (
int z = 0; z <
lnz; ++z)
131 for (
int y = 0; y <
lny; ++y)
132 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
133 (std::size_t)(z + oz) *
NX *
NY],
135 (std::size_t)
lnx *
sizeof(
double));
141 }
else if (rank == 0) {
146 for (
int z = 0; z <
meta[5]; ++z)
147 for (
int y = 0; y <
meta[4]; ++y)
148 std::memcpy(&
global[(std::size_t)
meta[0] + (std::size_t)(y +
meta[1]) *
NX +
149 (std::size_t)(z +
meta[2]) *
NX *
NY],
151 (std::size_t)
meta[3] *
sizeof(
double));
157static double maxAbsDiff(
const std::vector<double>& a,
const std::vector<double>& b) {
162 for (std::size_t i = 0; i < b.size(); ++i) {
163 const double d = std::fabs(a[i] - b[i]);
170static double maxAbs(
const std::vector<double>& a) {
173 m = std::fmax(m, std::fabs(v));
180 for (
int z = 1; z <
NZ; ++z) {
181 const std::size_t i0 =
182 (std::size_t)(
NX / 2) + (std::size_t)(
NY / 2) *
NX + (std::size_t)(z - 1) *
NX *
NY;
183 const std::size_t i1 = i0 + (std::size_t)
NX *
NY;
184 const double rf = 0.5 * (((z <
NZ / 2) ?
RATIO : 1.0) + ((z - 1 <
NZ / 2) ?
RATIO : 1.0));
185 perr = std::fmax(perr, std::fabs((p[i1] - p[i0]) +
GRAV * rf) / (
GRAV *
RATIO));
192 Kokkos::initialize(
argc, argv);
195 int rank = 0, size = 1;
199 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
200 auto blk =
dec.block(rank);
201 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
202 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
203 const int gn[3] = {
NX,
NY,
NZ};
204 bool cut[3] = {
false,
false,
false};
205 for (
const auto& sz :
dec.sizes())
206 for (
int a = 0; a < 3; ++a)
207 if ((
int)sz[a] != gn[a])
210 std::printf(
"VARDENSITY MPI np=%d grid %dx%dx%d block %dx%dx%d cut axes: %s%s%s\n", size,
214 const Config configs[] = {{
"walls-z", 2,
true}, {
"jump-z", 2,
false}};
220 if (size > 1 && !cut[c.axis]) {
223 " [%-7s np=%d] FAIL — the decomposition does NOT cut axis %d; this test "
224 "exists to gate the domain-BC / property-ghost rank ownership on a CUT "
225 "walled axis (WO-F)\n",
226 c.name, size, c.axis);
234 std::vector<long>
itd;
235 for (
int it = 0; it <
STEPS; ++it) {
240 std::vector<double>
gu[3];
241 for (
int comp = 0; comp < 3; ++comp)
243 const std::vector<double>
gp =
250 std::vector<long>
itr;
252 for (
int it = 0; it <
STEPS; ++it) {
254 itr.push_back(ref.lastPressureIterations());
256 std::fmax(
maxAbs(ref.getVelocity(0)),
257 std::fmax(
maxAbs(ref.getVelocity(1)),
maxAbs(ref.getVelocity(2)))));
259 double du = 0,
umag = 0;
260 for (
int comp = 0; comp < 3; ++comp) {
261 du = std::fmax(du,
maxAbsDiff(
gu[comp], ref.getVelocity(comp)));
265 const double pmag =
maxAbs(ref.getPressure());
267 const double utol = (size == 1) ? 0.0 : std::fmax(1e-15, 1e-11 *
umag);
268 const double ptol = (size == 1) ? 0.0 : std::fmax(1e-12, 1e-11 *
pmag);
278 for (std::size_t k = 0; k <
itr.size(); ++k) {
279 if (k > 0 &&
refUmax[k - 1] <= 1e-12)
299 const long itTol = (size == 1) ? 0 : 1;
301 double umax = -1, perr = -1;
305 ok = ok && umax < 1e-14 && perr < 1e-11;
309 std::snprintf(
extra,
sizeof(
extra),
" | max|u|=%.2e dP/dz err=%.2e", umax, perr);
311 " [%-7s np=%d] du=%.3e dp=%.3e (tol %.1e/%.1e) | cheb its %ld..%ld "
312 "max-delta=%ld over %d/%d non-degenerate steps%s %s\n",
313 c.name, size, du, dp,
utol,
ptol,
itr.front(),
itr.back(),
dits,
nWin,
STEPS,
extra,
315 std::printf(
" dist its:");
317 std::printf(
" %ld", v);
318 std::printf(
"\n ref its:");
320 std::printf(
" %ld", v);
328 std::printf(
"VARDENSITY MPI (np=%d): %s\n", size,
fail ?
"FAIL" :
"PASS");
void setDomainBc(int face, int type, double vx, double vy, double vz)
void exchangeField(const std::string &name)
void setAdvection(bool on)
void setPropertyModel(const std::string &target, ClosureKind kind, const std::string &in0, const std::string &in1, const std::vector< double > ¶ms)
void setPressureGeometry(const std::vector< double > &sdfInner)
void setField(const std::string &name, const std::vector< double > &v)
void setBodyForce(double fx, double fy, double fz)
Body force per unit volume, in the caller's units (e.g. a mean pressure gradient, or rho*g).
std::vector< double > getVelocity(int c)
long lastPressureIterations() const
void setDensityMode(bool variable)
void setMu(double m)
Dynamic viscosity, in the caller's units.
void setRho(double r)
Fluid density, in the caller's units.
std::vector< double > getPressure()
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
static double maxAbs(const std::vector< double > &a)
static constexpr double GRAV
static std::vector< double > blockOf(Fn f, int ox, int oy, int oz, int lnx, int lny, int lnz)
static constexpr double FX
static constexpr double RHO0
static double rhoAt(const Config &c, int x, int y, int z)
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)
static constexpr int STEPS
static double maxAbsDiff(const std::vector< double > &a, const std::vector< double > &b)
static constexpr double DT
static double pressureGradientError(const std::vector< double > &p)
static constexpr double RATIO
static constexpr std::size_t GCELLS
static void configure(IbmSolver &s, const Config &c, int ox, int oy, int oz, int lnx, int lny, int lnz)