35#include <Kokkos_Core.hpp>
39#include "peclet/core/common/types.hpp"
40#include "peclet/core/decomp/block_decomposer.hpp"
44static constexpr int NX = 16,
NY = 16,
NZ = 32;
57 const double cx =
NX / 2.0 + 0.137, cy =
NY / 2.0 - 0.311;
60 const double cz = c.walls ?
NZ / 4.0 + 0.241 :
NZ / 2.0 + 0.241;
64 for (
int k = 0; k < NS; ++k)
65 for (
int j = 0; j < NS; ++j)
66 for (
int i = 0; i < NS; ++i) {
67 const double dx = x + (i + 0.5) / NS - cx, dy = y + (j + 0.5) / NS - cy,
68 dz = z + (k + 0.5) / NS - cz;
69 if (dx * dx + dy * dy + dz * dz < R * R)
72 return static_cast<double>(
in) / (NS * NS * NS);
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);
96 s.
setVof(
blockOf([&](
int x,
int y,
int z) {
return colourAt(c, x, y, z); }, ox, oy, oz,
lnx,
lny,
101static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
102 int lnx,
int lny,
int lnz,
int rank,
int size) {
103 std::vector<double>
global;
106 for (
int r = 0; r < size; ++r) {
110 for (
int z = 0; z <
lnz; ++z)
111 for (
int y = 0; y <
lny; ++y)
112 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
113 (std::size_t)(z + oz) *
NX *
NY],
115 (std::size_t)
lnx *
sizeof(
double));
121 }
else if (rank == 0) {
126 for (
int z = 0; z <
meta[5]; ++z)
127 for (
int y = 0; y <
meta[4]; ++y)
128 std::memcpy(&
global[(std::size_t)
meta[0] + (std::size_t)(y +
meta[1]) *
NX +
129 (std::size_t)(z +
meta[2]) *
NX *
NY],
131 (std::size_t)
meta[3] *
sizeof(
double));
137static long countBitDiff(
const std::vector<double>& a,
const std::vector<double>& b,
double& mx) {
140 for (std::size_t i = 0; i < b.size(); ++i)
143 mx = std::fmax(mx, std::fabs(a[i] - b[i]));
150 Kokkos::initialize(
argc, argv);
153 int rank = 0, size = 1;
157 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
158 auto blk =
dec.block(rank);
159 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
160 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
161 const int gn[3] = {
NX,
NY,
NZ};
162 bool cut[3] = {
false,
false,
false};
163 for (
const auto& sz :
dec.sizes())
164 for (
int a = 0; a < 3; ++a)
165 if ((
int)sz[a] != gn[a])
168 std::printf(
"VOF CURVATURE MPI np=%d grid %dx%dx%d block %dx%dx%d cut axes: %s%s%s\n",
172 const Config configs[] = {{
"sphere-per",
false}, {
"sphere-walls-z",
true}};
176 if (size > 1 && !cut[2]) {
178 std::printf(
" [%-14s np=%d] FAIL — the decomposition does NOT cut z\n", c.name, size);
191 long sumCounts[7] = {0, 0, 0, 0, 0, 0, 0};
194 const std::vector<double>
gk =
196 const std::vector<double>
gb =
203 ref.computeVofCurvature();
204 const auto st = ref.vofCurvatureStats();
205 const long refCounts[7] = {st.interfacial, st.hf, st.hfMixed, st.hfFit,
206 st.pv, st.pvReduced, st.noEstimate};
207 double dk = 0.0, db = 0.0;
209 const long nb =
countBitDiff(
gb, ref.getVofCurvatureBranch(), db);
212 for (
int i = 0; i < 7; ++i)
216 " [%-14s np=%d] interfacial %ld | HF %ld HFdir %ld HFfit %ld PV %ld PVred %ld"
221 " kappa: %ld/%ld cells differ (max |d| %.3e) branch: %ld differ"
227 std::printf(
" FAIL — the curvature cascade is decomposition-DEPENDENT\n");
233 " FAIL — the PLIC-volumetric fallback never fired; this configuration "
234 "no longer gates its stencil reach\n");
238 std::printf(
" FAIL — %ld interfacial cells got NO curvature estimate\n",
246 std::printf(
"%s\n",
fail ?
"FAILED" :
"PASSED");
std::vector< double > getVofCurvature()
The interface curvature kappa = 2H in the caller's units, i.e.
void setDomainBc(int face, int type, double vx, double vy, double vz)
void computeVofCurvature()
std::vector< double > getVofCurvatureBranch()
void setVof(const std::vector< double > &c)
void setPressureGeometry(const std::vector< double > &sdfInner)
vof::VofCurvature::Stats vofCurvatureStats() const
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 std::vector< double > blockOf(Fn f, int ox, int oy, 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 long countBitDiff(const std::vector< double > &a, const std::vector< double > &b, double &mx)
static double colourAt(const Config &c, int x, int y, int z)
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)