82#include <Kokkos_Core.hpp>
86#include "peclet/core/common/types.hpp"
87#include "peclet/core/decomp/block_decomposer.hpp"
107 double f[3] = {0.0, 0.0, 0.0};
125 for (
int n = 0; n <
STEPS; ++n)
131static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
132 int lnx,
int lny,
int lnz,
int rank,
int size) {
133 std::vector<double>
global;
136 for (
int r = 0; r < size; ++r) {
140 for (
int z = 0; z <
lnz; ++z)
141 for (
int y = 0; y <
lny; ++y)
142 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
143 (std::size_t)(z + oz) *
NX *
NY],
145 (std::size_t)
lnx *
sizeof(
double));
151 }
else if (rank == 0) {
156 for (
int z = 0; z <
meta[5]; ++z)
157 for (
int y = 0; y <
meta[4]; ++y)
158 std::memcpy(&
global[(std::size_t)
meta[0] + (std::size_t)(y +
meta[1]) *
NX +
159 (std::size_t)(z +
meta[2]) *
NX *
NY],
161 (std::size_t)
meta[3] *
sizeof(
double));
167static double maxAbsDiff(
const std::vector<double>& a,
const std::vector<double>& b) {
172 for (std::size_t i = 0; i < b.size(); ++i) {
173 const double d = std::fabs(a[i] - b[i]);
180static double maxAbs(
const std::vector<double>& a) {
183 m = std::fmax(m, std::fabs(v));
190static int worstPlane(
const std::vector<double>& u,
int axis) {
191 const int n[3] = {
NX,
NY,
NZ};
198 for (
int p = 0; p < n[axis]; ++p) {
200 for (
int b = 0; b < n[(axis + 2) % 3]; ++b)
201 for (
int a = 0; a < n[(axis + 1) % 3]; ++a) {
204 idx[(axis + 1) % 3] = a;
205 idx[(axis + 2) % 3] = b;
209 u[(std::size_t)
idx[0] + (std::size_t)
idx[1] *
NX + (std::size_t)
idx[2] *
NX *
NY] -
222 Kokkos::initialize(
argc, argv);
225 int rank = 0, size = 1;
229 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
230 auto blk =
dec.block(rank);
231 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
232 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
233 const int gn[3] = {
NX,
NY,
NZ};
234 bool cut[3] = {
false,
false,
false};
235 for (
const auto& sz :
dec.sizes())
236 for (
int a = 0; a < 3; ++a)
237 if ((
int)sz[a] != gn[a])
240 std::printf(
"DRAGBETA-GHOST MPI np=%d grid %dx%dx%d block %dx%dx%d cut axes: %s%s%s\n",
245 {
"per-z", 2,
false,
true}, {
"per-x", 0,
false,
false}, {
"cons-z", 2,
true,
true}};
249 if (c.needCut && size > 1 && !cut[c.comp]) {
252 " [%-6s np=%d] FAIL — the decomposition does NOT cut the forced axis %d; "
253 "this test exists to gate the drag_beta ghost ACROSS a rank boundary (WO-I)\n",
254 c.name, size, c.comp);
262 for (
int it = 0; it <
STEPS; ++it) {
271 std::vector<double>
gu[3];
272 for (
int comp = 0; comp < 3; ++comp)
274 const std::vector<double>
gp =
284 for (
int it = 0; it <
STEPS; ++it)
286 double du = 0,
umag = 0;
287 for (
int comp = 0; comp < 3; ++comp) {
288 du = std::fmax(du,
maxAbsDiff(
gu[comp], ref.getVelocity(comp)));
292 const double pmag =
maxAbs(ref.getPressure());
293 const double utol = (size == 1) ? 0.0 : std::fmax(1e-15, 1e-11 *
umag);
294 const double ptol = (size == 1) ? 0.0 : std::fmax(1e-12, 1e-11 *
pmag);
299 const std::vector<double>&
uf =
gu[c.comp];
300 double lo =
uf[0], hi =
uf[0];
301 for (
double v :
uf) {
302 lo = std::fmin(lo, v);
303 hi = std::fmax(hi, v);
305 const double spread = hi - lo,
verr = std::fabs(0.5 * (hi + lo) - want) / want;
309 for (
int comp = 0; comp < 3; ++comp)
316 for (
double v :
gd) {
325 " [%-6s np=%d] du=%.3e dp=%.3e (tol %.1e/%.1e) | diag [%.17g, %.17g] "
326 "(want %.17g, worst plane %d) | u spread=%.3e (want 0) value=%.17g "
327 "(want %.17g) cross=%.2e max|P|=%.2e %s\n",
328 c.name, size, du, dp,
utol,
ptol,
dlo,
dhi,
wantDiag,
worstPlane(
gd, c.comp),
spread,
329 0.5 * (hi + lo), want,
cross,
pabs, ok ?
"OK" :
"FAIL");
336 std::printf(
"DRAGBETA-GHOST MPI (np=%d): %s\n", size,
fail ?
"FAIL" :
"PASS");
void setAdvection(bool on)
void setPressureGeometry(const std::vector< double > &sdfInner)
std::vector< double > getMomentumDiagonal(int c)
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)
void setPorousConservative(bool on)
void setMu(double m)
Dynamic viscosity, in the caller's units.
void setPorousContinuity(bool on)
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 RHO0
static int worstPlane(const std::vector< double > &u, int axis)
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 FORCE
static double analyticVelocity()
static constexpr int STEPS
static double maxAbsDiff(const std::vector< double > &a, const std::vector< double > &b)
static constexpr double DT
static void configure(IbmSolver &s, const Config &c, int lnx, int lny, int lnz)
static constexpr double BETA
static constexpr std::size_t GCELLS
static double mean(const std::vector< double > &a)