28#include <Kokkos_Core.hpp>
32#include "peclet/core/common/types.hpp"
33#include "peclet/core/decomp/block_decomposer.hpp"
37static constexpr int NX = 8,
NY = 8,
NZ = 40;
38static constexpr double Z0 = 16.25,
Z1 = 32.25;
40static constexpr int STEPS = 200;
43static double sdfAt(
int,
int,
int z) {
44 const double zc = z + 0.5;
49 std::vector<double> v((std::size_t)
lnx *
lny *
lnz);
50 for (
int z = 0; z <
lnz; ++z)
51 for (
int y = 0; y <
lny; ++y)
52 for (
int x = 0; x <
lnx; ++x)
53 v[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] =
sdfAt(0, 0, z + oz);
70static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
71 int lnx,
int lny,
int lnz,
int rank,
int size) {
72 std::vector<double>
global;
75 for (
int r = 0; r < size; ++r) {
79 for (
int z = 0; z <
lnz; ++z)
80 for (
int y = 0; y <
lny; ++y)
81 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
82 (std::size_t)(z + oz) *
NX *
NY],
84 (std::size_t)
lnx *
sizeof(
double));
90 }
else if (rank == 0) {
95 for (
int z = 0; z <
meta[5]; ++z)
96 for (
int y = 0; y <
meta[4]; ++y)
98 (std::size_t)(z +
meta[2]) *
NX *
NY],
100 (std::size_t)
meta[3] *
sizeof(
double));
106static double maxAbsDiff(
const std::vector<double>& a,
const std::vector<double>& b) {
108 for (std::size_t i = 0; i < b.size(); ++i) {
109 const double d = std::fabs(a[i] - b[i]);
116static double maxAbs(
const std::vector<double>& a) {
119 m = std::fmax(m, std::fabs(v));
125 const double H =
Z1 -
Z0;
127 for (
int z = 0; z <
NZ; ++z) {
128 const double zc = z + 0.5;
132 const std::size_t i =
133 (std::size_t)(
NX / 2) + (std::size_t)(
NY / 2) *
NX + (std::size_t)z *
NX *
NY;
134 e = std::fmax(e, std::fabs(u[i] -
ue));
135 s = std::fmax(s, std::fabs(
ue));
137 return e / (s + 1e-300);
142 Kokkos::initialize(
argc, argv);
145 int rank = 0, size = 1;
149 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
150 auto blk =
dec.block(rank);
151 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
152 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
153 const int gn[3] = {
NX,
NY,
NZ};
154 bool cut[3] = {
false,
false,
false};
155 for (
const auto& sz :
dec.sizes())
156 for (
int a = 0; a < 3; ++a)
157 if ((
int)sz[a] != gn[a])
162 "WALL-SLIP MPI np=%d grid %dx%dx%d block %dx%dx%d cut axes: %s%s%s "
163 "walls z = %.2f / %.2f z-blocks:",
165 cut[2] ?
"z" :
"",
Z0,
Z1);
166 for (
int r = 0; r < size; ++r)
168 " [%d,%d)", (
int)
dec.block((std::size_t)r).origin[2],
169 (int)(
dec.block((std::size_t)r).origin[2] +
dec.block((std::size_t)r).size[2]));
172 if (size > 1 && !cut[2]) {
175 " FAIL — the decomposition does NOT cut the walled z axis; this test exists "
176 "to gate the Navier closure across a rank boundary\n");
180 const double lambdas[] = {0.0, 0.1};
185 for (
int it = 0; it <
STEPS; ++it)
187 std::vector<double>
gu[3];
188 for (
int comp = 0; comp < 3; ++comp)
196 ref.setPressureBottomSolver(2);
197 for (
int it = 0; it <
STEPS; ++it)
199 double du = 0,
umag = 0;
200 for (
int comp = 0; comp < 3; ++comp) {
201 du = std::fmax(du,
maxAbsDiff(
gu[comp], ref.getVelocity(comp)));
204 const double tol = (size == 1) ? 0.0 : std::fmax(1e-15, 1e-11 *
umag);
209 const bool ok = du <=
tol &&
aerr < 5e-6;
211 " [lambda=%.2f np=%d] du=%.3e (|u|=%.3e, tol %.1e) | analytic rel err "
212 "%.3e (tol 5.0e-06) %s\n",
213 lam, size, du,
umag,
tol,
aerr, ok ?
"OK" :
"FAIL");
220 std::printf(
"WALL-SLIP MPI (np=%d): %s\n", size,
fail ?
"FAIL" :
"PASS");
void setSolid(const std::vector< double > &sdfInner, bool cutcellPressure)
Host entry point: upload the inner SDF once and delegate.
void setAdvection(bool on)
void setVelocityIterations(int it)
void setWallSlipLength(double lambdaCells)
WO-V6b – the VELOCITY half of the dynamic contact line.
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)
void setPressurePcg(bool on, int maxit, double rtol)
void setMu(double m)
Dynamic viscosity, in the caller's units.
void setRho(double r)
Fluid density, in the caller's units.
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
static double maxAbs(const std::vector< double > &a)
static constexpr double GFORCE
static double analyticError(const std::vector< double > &u, double lam)
static void configure(IbmSolver &s, double lam, int oz, int lnx, int lny, int lnz)
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 double Z0
static constexpr double RHO
static constexpr double MU
static constexpr int STEPS
static double maxAbsDiff(const std::vector< double > &a, const std::vector< double > &b)
static constexpr double DT
static constexpr double Z1
static double sdfAt(int, int, int z)
static constexpr std::size_t GCELLS
static std::vector< double > blockSdf(int oz, int lnx, int lny, int lnz)