47#include <Kokkos_Core.hpp>
51#include "peclet/core/common/types.hpp"
52#include "peclet/core/decomp/block_decomposer.hpp"
56static constexpr int NX = 16,
NY = 16,
NZ = 32;
72 return (z <
NZ / 2) ? 1.0 : 0.0;
73 const double dx = x + 0.5 -
NX / 2.0, dy = y + 0.5 -
NY / 2.0, dz = z + 0.5 -
NZ / 2.0;
74 const double r = std::sqrt(dx * dx + dy * dy + dz * dz);
75 return std::fmin(1.0, std::fmax(0.0, 0.5 - (r - 4.0)));
78 return 5e-4 * std::sin(2 *
M_PI * (z + 0.5) /
NZ);
83 std::vector<double> v((std::size_t)
lnx *
lny *
lnz);
84 for (
int z = 0; z <
lnz; ++z)
85 for (
int y = 0; y <
lny; ++y)
86 for (
int x = 0; x <
lnx; ++x)
87 v[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] =
88 f(x + ox, y + oy, z + oz);
95 s.
setMu(c.walls ? 0.0 : 0.05);
103 s.
setVof(
blockOf([&](
int x,
int y,
int z) {
return colourAt(c, x, y, z); }, ox, oy, oz,
lnx,
lny,
106 {1.0, c.ratio - 1.0});
117static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
118 int lnx,
int lny,
int lnz,
int rank,
int size) {
119 std::vector<double>
global;
122 for (
int r = 0; r < size; ++r) {
126 for (
int z = 0; z <
lnz; ++z)
127 for (
int y = 0; y <
lny; ++y)
128 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
129 (std::size_t)(z + oz) *
NX *
NY],
131 (std::size_t)
lnx *
sizeof(
double));
137 }
else if (rank == 0) {
142 for (
int z = 0; z <
meta[5]; ++z)
143 for (
int y = 0; y <
meta[4]; ++y)
144 std::memcpy(&
global[(std::size_t)
meta[0] + (std::size_t)(y +
meta[1]) *
NX +
145 (std::size_t)(z +
meta[2]) *
NX *
NY],
147 (std::size_t)
meta[3] *
sizeof(
double));
153static double maxAbsDiff(
const std::vector<double>& a,
const std::vector<double>& b) {
158 for (std::size_t i = 0; i < b.size(); ++i) {
159 const double d = std::fabs(a[i] - b[i]);
166static double maxAbs(
const std::vector<double>& a) {
169 m = std::fmax(m, std::fabs(v));
172static double sumOf(
const std::vector<double>& a) {
183 for (
int z = 1; z <
NZ; ++z) {
184 const std::size_t i0 =
185 (std::size_t)(
NX / 2) + (std::size_t)(
NY / 2) *
NX + (std::size_t)(z - 1) *
NX *
NY;
186 const std::size_t i1 = i0 + (std::size_t)
NX *
NY;
187 const double rf = 0.5 * ((1.0 + (ratio - 1.0) * c[i1]) + (1.0 + (ratio - 1.0) * c[i0]));
188 perr = std::fmax(perr, std::fabs((p[i1] - p[i0]) +
GRAV * rf) / (
GRAV * ratio));
195 Kokkos::initialize(
argc, argv);
198 int rank = 0, size = 1;
202 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
203 auto blk =
dec.block(rank);
204 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
205 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
206 const int gn[3] = {
NX,
NY,
NZ};
207 bool cut[3] = {
false,
false,
false};
208 for (
const auto& sz :
dec.sizes())
209 for (
int a = 0; a < 3; ++a)
210 if ((
int)sz[a] != gn[a])
213 std::printf(
"VOF TWOPHASE MPI np=%d grid %dx%dx%d block %dx%dx%d cut axes: %s%s%s\n", size,
217 const Config configs[] = {{
"walls-z",
true, 1000.0, 1.0, 20},
218 {
"shear-per",
false, 10.0, 1.0, 40}};
224 if (size > 1 && !cut[2]) {
226 std::printf(
" [%-9s np=%d] FAIL — the decomposition does NOT cut z\n", c.name, size);
237 for (
int it = 0; it < c.steps; ++it)
243 std::vector<double>
gu[3];
244 for (
int comp = 0; comp < 3; ++comp)
246 const std::vector<double>
gp =
248 const std::vector<double> gc =
255 const double rv0 =
sumOf(ref.getVof());
256 for (
int it = 0; it < c.steps; ++it)
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)));
264 const auto refC = ref.getVof();
267 const double pmag =
maxAbs(ref.getPressure());
268 const double drift = (
v1 -
v0) /
v0;
273 const double utol = (size == 1) ? 0.0 : std::fmax(1e-12, 1e-11 *
umag);
274 const double ptol = (size == 1) ? 0.0 : std::fmax(1e-12, 1e-11 *
pmag);
275 const double ctol = (size == 1) ? 0.0 : 1e-11;
277 " [%-9s np=%d] du %.3e (tol %.1e, |u| %.2e) dp %.3e (tol %.1e, |P| %.2e) "
278 "dC %.3e (tol %.1e) dV/V %+.3e\n",
279 c.name, size, du,
utol,
umag, dp,
ptol,
pmag,
dc,
ctol, drift);
281 std::printf(
" [%-9s np=%d] FAIL — distributed vs single-rank\n", c.name, size);
292 std::printf(
" [%-9s np=%d] colour drift dist %+.4e ref %+.4e (delta %.2e)\n", c.name,
294 if (!(std::fabs(drift -
refDrift) < 1e-13)) {
295 std::printf(
" [%-9s np=%d] FAIL — colour drift is decomposition-dependent\n", c.name,
299 }
else if (!(std::fabs(drift) < 1e-11)) {
300 std::printf(
" [%-9s np=%d] FAIL — colour volume drift %.3e\n", c.name, size, drift);
306 std::printf(
" [%-9s np=%d] hydrostatic through C: max|u| %.3e dP/dz rel-err %.3e\n",
307 c.name, size,
umaxD, perr);
308 if (!(perr < 1e-11) || !(
umaxD < 1e-9)) {
309 std::printf(
" [%-9s np=%d] FAIL — hydrostatic balance through C\n", c.name, size);
317 std::printf(
fail ?
"FAILED\n" :
"OK\n");
void setDomainBc(int face, int type, double vx, double vy, double vz)
void setAdvection(bool on)
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 setVof(const std::vector< double > &c)
void setPressureGeometry(const std::vector< double > &sdfInner)
void setField(const std::string &name, const std::vector< double > &v)
std::vector< double > getVelocity(int c)
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 RHO0
static double forceXAt(int, int, 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 double colourAt(const Config &c, int x, int y, int z)
static double maxAbsDiff(const std::vector< double > &a, const std::vector< double > &b)
static double sumOf(const std::vector< double > &a)
static double pressureGradientError(const std::vector< double > &p, const std::vector< double > &c, 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)