51#include <Kokkos_Core.hpp>
55#include "peclet/core/common/types.hpp"
56#include "peclet/core/decomp/block_decomposer.hpp"
61static constexpr int NX = 16,
NY = 16,
NZ = 32;
63static constexpr double WIN = 1.0;
64static constexpr double DT = 0.2;
66static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
67 int lnx,
int lny,
int lnz,
int rank,
int size) {
68 std::vector<double>
global;
71 for (
int r = 0; r < size; ++r) {
75 for (
int z = 0; z <
lnz; ++z)
76 for (
int y = 0; y <
lny; ++y)
77 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
78 (std::size_t)(z + oz) *
NX *
NY],
80 (std::size_t)
lnx *
sizeof(
double));
86 }
else if (rank == 0) {
91 for (
int z = 0; z <
meta[5]; ++z)
92 for (
int y = 0; y <
meta[4]; ++y)
94 (std::size_t)(z +
meta[2]) *
NX *
NY],
96 (std::size_t)
meta[3] *
sizeof(
double));
104static double maxAbsDiff(
const std::vector<double>& a,
const std::vector<double>& b) {
106 for (std::size_t i = 0; i < b.size(); ++i) {
107 const double d = std::fabs(a[i] - b[i]);
118static double signedSumDiff(
const std::vector<double>& a,
const std::vector<double>& b) {
120 for (std::size_t i = 0; i < b.size(); ++i)
131static double sumOf(
const std::vector<double>& a) {
143 for (
int f = 0; f < 4; ++f)
157 const double rhoG = 1.0, rhoL = 100.0;
161 for (
int f = 0; f < 4; ++f)
172 {rhoG, rhoL - rhoG, 0.0, 0.0});
190 for (
int f = 0; f < 4; ++f)
199 std::vector<double> c0((std::size_t)
lnx *
lny *
lnz, 0.0);
200 for (
int z = 0; z <
lnz; ++z)
201 if (z + oz >=
NZ / 2)
202 for (
int y = 0; y <
lny; ++y)
203 for (
int x = 0; x <
lnx; ++x)
204 c0[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] = 1.0;
215 const double sp[5][4] = {{4.5, 4.5, 11, 3.4},
216 {11.5, 11.5, 11, 3.4},
217 {4.5, 11.5, 20, 3.4},
218 {11.5, 4.5, 20, 3.4},
220 std::vector<double> f((std::size_t)
lnx *
lny *
lnz, 1
e30);
221 for (
int z = 0; z <
lnz; ++z)
222 for (
int y = 0; y <
lny; ++y)
223 for (
int x = 0; x <
lnx; ++x) {
225 for (
const auto& q : sp) {
226 const double dx = x + ox + 0.5 - q[0], dy = y + oy + 0.5 - q[1], dz = z + oz + 0.5 - q[2];
227 d = std::fmin(d, std::sqrt(dx * dx + dy * dy + dz * dz) - q[3]);
229 f[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] = d;
240 const double pi = 3.14159265358979323846;
242 for (
int z = 0; z <
lnz; ++z)
243 for (
int y = 0; y <
lny; ++y)
244 for (
int x = 0; x <
lnx; ++x) {
245 const std::size_t k = (std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny;
246 const double gx = x + ox + 0.5,
gy = y + oy + 0.5,
gz = z + oz + 0.5;
248 0.10 * std::sin(2 *
pi *
gx /
NX) * std::cos(2 *
pi *
gy /
NY) * std::cos(
pi *
gz /
NZ);
250 0.10 * std::cos(2 *
pi *
gx /
NX) * std::sin(2 *
pi *
gy /
NY) * std::cos(
pi *
gz /
NZ);
251 fw[k] = 0.50 + 0.10 * std::cos(2 *
pi *
gx /
NX) * std::cos(2 *
pi *
gy /
NY) *
263 for (
int f = 0; f < 4; ++f)
272 std::vector<double> c0((std::size_t)
lnx *
lny *
lnz, 0.0);
273 for (
int z = 0; z <
lnz; ++z)
274 if (z + oz >=
NZ / 2)
275 for (
int y = 0; y <
lny; ++y)
276 for (
int x = 0; x <
lnx; ++x)
277 c0[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] = 1.0;
285 Kokkos::initialize(
argc, argv);
288 int rank = 0, size = 1;
291 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
292 auto blk =
dec.block(rank);
293 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
294 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
295 const int gn[3] = {
NX,
NY,
NZ};
296 bool cut[3] = {
false,
false,
false};
297 for (
const auto& sz :
dec.sizes())
298 for (
int a = 0; a < 3; ++a)
299 if ((
int)sz[a] != gn[a])
302 std::printf(
"VOF BC MPI np=%d grid %dx%dx%d block %dx%dx%d cut axes: %s%s%s\n", size,
NX,
303 NY,
NZ,
lnx,
lny,
lnz, cut[0] ?
"x" :
"", cut[1] ?
"y" :
"", cut[2] ?
"z" :
"");
304 if (size > 1 && !cut[2]) {
306 std::printf(
" FAIL — the decomposition does NOT cut z (the inflow/outflow axis)\n");
331 if (std::getenv(
"PECLET_VOF_BC_TRACE") && rank == 0) {
336 std::printf(
" trace step %3d: face %.6g %.6g | C sum %.6g nonfinite %ld\n", i, v[4],
339 for (
int f = 0; f < 6; ++f)
348 double lIn = tot[4],
lOut = -tot[5];
351 const std::vector<double> gc =
359 ref.setVofInflow(4, 0.0);
361 const auto v = ref.vofBcVolumes();
362 for (
int f = 0; f < 6; ++f)
369 std::printf(
" [slug-kin np=%d] FAIL — %ld non-finite colour cells\n", size,
nbad);
373 std::printf(
" [slug-kin np=%d] FAIL — the boundary ledger is not finite\n", size);
377 std::printf(
" [slug-kin np=%d] colour vs single-rank %.3e (BITWISE required)\n", size,
380 " [slug-kin np=%d] ledger vs single-rank %.3e; global budget "
381 "|sum(C) - ledger| %.3e; in %.10g out %.10g\n",
384 std::printf(
" [slug-kin np=%d] FAIL — colour is not bitwise\n", size);
388 std::printf(
" [slug-kin np=%d] FAIL — the global budget does not close\n", size);
392 std::printf(
" [slug-kin np=%d] FAIL — in/out do not balance\n", size);
400 const int steps = 30;
406 for (
int i = 0; i < steps; ++i) {
413 auto hr = Kokkos::create_mirror_view(
rv);
414 Kokkos::deep_copy(
hr,
rv);
415 const int G = 2, ex =
lnx + 2 *
G, ey =
lny + 2 *
G;
416 const double ghost =
hr((std::size_t)(
G +
lnx / 2) + (std::size_t)(
G +
lny / 2) * ex +
417 (std::size_t)(
G - 1) * ex * ey);
418 const bool owns = (oz == 0);
419 int bad = (
owns && std::fabs(ghost - 100.0) > 1e-9) ? 1 : 0;
422 const std::vector<double> gc =
429 for (
int i = 0; i < steps; ++i)
435 " [jet-coupl np=%d] colour vs single-rank %.3e (signed sum %.3e); inflow rho ghost "
436 "owners wrong on %d rank(s); pressure %ld/400, max|div| %.3e\n",
444 const double tol = (size == 1) ? 0.0 : 1e-6;
446 std::printf(
" [jet-coupl np=%d] FAIL — the colour field is wrong (tol %.1e)\n", size,
450 const double tolSum = (size == 1) ? 0.0 : 1e-11 * std::fabs(
csum);
453 " [jet-coupl np=%d] FAIL — the colour difference does not CANCEL: signed sum %.3e "
459 std::printf(
" [jet-coupl np=%d] FAIL — the inflow rho ghost is not the inlet fluid's\n",
464 std::printf(
" [jet-coupl np=%d] FAIL — the pressure solve CAPPED (run invalid)\n", size);
488 const int steps = 20;
495 for (
int i = 0; i < steps; ++i) {
498 for (
int f = 0; f < 6; ++f)
508 const std::vector<double> gc =
514 for (
int i = 0; i < steps; ++i)
517 const double budget = std::fabs((g1 - g0) -
gLed);
527 " [packing-kin np=%d] colour vs single-rank %.3e (BITWISE required); budget "
528 "|d sum(eps_eff C) - ledger| %.3e (rel %.3e, NOT gated — the prescribed field is not "
529 "discretely solenoidal); solid colour %.3e\n",
532 std::printf(
" [packing-kin np=%d] FAIL — the composed colour is not bitwise\n", size);
536 std::printf(
" [packing-kin np=%d] FAIL — %ld non-finite colour cells\n", size,
nbad);
540 std::printf(
" [packing-kin np=%d] FAIL — colour leaked into solid cells\n", size);
556 const int steps = 40;
563 for (
int i = 0; i < steps; ++i) {
567 for (
int f = 0; f < 6; ++f)
579 const std::vector<double> gc =
584 for (
int i = 0; i < steps; ++i)
587 const double budget = std::fabs((g1 - g0) -
gLed);
591 " [packing np=%d] colour vs single-rank %.3e (signed sum %.3e, rel %.3e); budget "
592 "|d sum(eps_eff C) - ledger| %.3e (rel %.3e); solid colour %.3e; "
593 "pressure %ld/400\n",
643 const double tol = (size == 1) ? 0.0 : 1e-6;
645 std::printf(
" [packing np=%d] FAIL — the colour field is wrong (tol %.1e)\n", size,
652 const double tolSum = (size == 1) ? 0.0 : 1e-11 * std::fabs(
csum);
655 " [packing np=%d] FAIL — the colour difference does not CANCEL: signed sum %.3e "
656 "> %.3e (colour created or destroyed, not moved)\n",
660 if (!(
budget / g0 < 1e-10)) {
661 std::printf(
" [packing np=%d] FAIL — the composed budget does not close\n", size);
665 std::printf(
" [packing np=%d] FAIL — colour leaked into solid cells\n", size);
669 std::printf(
" [packing np=%d] FAIL — the pressure solve CAPPED (run invalid)\n", size);
689 const int steps = 30;
696 for (
int i = 0; i < steps; ++i) {
700 for (
int f = 0; f < 6; ++f)
710 const std::vector<double>
gcol =
715 for (
int i = 0; i < steps; ++i)
721 " [colo-jet np=%d] colour vs single-rank %.3e; budget |d sum(C) - ledger| %.3e "
722 "(rel %.3e); pressure %ld/400\n",
724 const double tolCol = (size == 1) ? 0.0 : 1e-9 * std::fabs(
csum);
726 std::printf(
" [colo-jet np=%d] FAIL — the colour field is wrong (tol %.1e)\n", size,
731 std::printf(
" [colo-jet np=%d] FAIL — the boundary budget does not close\n", size);
735 std::printf(
" [colo-jet np=%d] FAIL — the pressure solve CAPPED (run invalid)\n", size);
744 std::printf(
fail ?
"FAILED\n" :
"OK\n");
void setSolid(const std::vector< double > &sdfInner, bool cutcellPressure)
Host entry point: upload the inner SDF once and delegate.
void setDomainBc(int face, int type, double vx, double vy, double vz)
double maxOpenDivergence()
std::vector< double > vofBcVolumes() const
Signed liquid volume that crossed each of the six domain faces during the LAST colour advection,...
std::vector< double > getVof()
void setPropertyModel(const std::string &target, ClosureKind kind, const std::string &in0, const std::string &in1, const std::vector< double > ¶ms)
void setVelocityIterations(int it)
void setVof(const std::vector< double > &c)
void setPressureLevels(int levels)
void setPressureGeometry(const std::vector< double > &sdfInner)
void setVofBackflow(int f, double value)
inletOutlet backflow colour on outflow face f (default 0 = gas): where the boundary face velocity poi...
void setField(const std::string &name, const std::vector< double > &v)
std::vector< double > vofBcVolumesTotal() const
The same, accumulated since enable_vof() (or the last resetVofBcVolumes()).
void setVofInflow(int f, double value)
Colour of the fluid entering through inflow face f (0..5 = -x,+x,-y,+y,-z,+z), in [0,...
long lastPressureIterations() const
void setMu(double m)
Dynamic viscosity, in the caller's units.
void setPressureIterations(int it)
CCField fieldView(const std::string &name)
void setRho(double r)
Fluid density, in the caller's units.
vof::WyAdvector::Diagnostics vofDiagnostics()
void setPressureFcg(bool on, int maxit, double rtol)
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
double solidSumC
filled by the SOLVER from the canonical G=2 colour field
double volume
sum of eps_eff*C over inner FLUID cells: the EXACTLY conserved functional of the cut-cell scheme (cut...
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 void configureSlug(IbmSolver &s, int lnx, int lny, int lnz)
static void configureJet(IbmSolver &s, int lnx, int lny, int lnz)
static double signedSumDiff(const std::vector< double > &a, const std::vector< double > &b)
static long countNonFinite(const std::vector< double > &a)
static double maxAbsDiff(const std::vector< double > &a, const std::vector< double > &b)
static void packingVelocity(IbmSolver &s, int ox, int oy, int oz, int lnx, int lny, int lnz)
static double sumOf(const std::vector< double > &a)
static std::vector< double > packingSdf(int ox, int oy, int oz, int lnx, int lny, int lnz)
static constexpr double DT
static void configurePacking(IbmSolver &s, int ox, int oy, int oz, int lnx, int lny, int lnz)
static constexpr double WIN
static void configureColoJet(Colo &s, int oz, int lnx, int lny, int lnz)
static constexpr std::size_t GCELLS
static std::vector< double > ledger(IbmSolver &s)