37#include <Kokkos_Core.hpp>
41#include "peclet/core/common/types.hpp"
42#include "peclet/core/decomp/block_decomposer.hpp"
46static constexpr int NX = 16,
NY = 16,
NZ = 32;
50static double sdfAt(
double x,
double y,
double z) {
51 const double cx[4] = {4.0, 11.0, 5.0, 12.0}, cy[4] = {4.0, 11.0, 12.0, 4.0},
52 cz[4] = {8.0, 16.0, 24.0, 30.0}, r = 4.5;
54 for (
int s = 0; s < 4; ++s)
55 for (
int a = -1; a <= 1; ++a)
56 for (
int b = -1; b <= 1; ++b)
57 for (
int c = -1; c <= 1; ++c) {
58 const double dx = x - (cx[s] + a *
NX), dy = y - (cy[s] + b *
NY),
59 dz = z - (cz[s] + c *
NZ);
60 const double d = std::sqrt(dx * dx + dy * dy + dz * dz) - r;
66 return z <
NZ / 2 ? 1.0 : 0.0;
71 std::vector<double> v((std::size_t)
lnx *
lny *
lnz);
72 for (
int z = 0; z <
lnz; ++z)
73 for (
int y = 0; y <
lny; ++y)
74 for (
int x = 0; x <
lnx; ++x)
75 v[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] =
76 f(x + ox, y + oy, z + oz);
79static std::vector<double>
sliceOf(
const std::vector<double>& g,
int ox,
int oy,
int oz,
int lnx,
82 [&](
int x,
int y,
int z) {
83 return g[(std::size_t)x + (std::size_t)y *
NX + (std::size_t)z *
NX *
NY];
88static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
89 int lnx,
int lny,
int lnz,
int rank,
int size) {
90 std::vector<double>
global;
93 for (
int r = 0; r < size; ++r) {
97 for (
int z = 0; z <
lnz; ++z)
98 for (
int y = 0; y <
lny; ++y)
99 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
100 (std::size_t)(z + oz) *
NX *
NY],
102 (std::size_t)
lnx *
sizeof(
double));
108 }
else if (rank == 0) {
113 for (
int z = 0; z <
meta[5]; ++z)
114 for (
int y = 0; y <
meta[4]; ++y)
115 std::memcpy(&
global[(std::size_t)
meta[0] + (std::size_t)(y +
meta[1]) *
NX +
116 (std::size_t)(z +
meta[2]) *
NX *
NY],
118 (std::size_t)
meta[3] *
sizeof(
double));
124static double maxAbsDiff(
const std::vector<double>& a,
const std::vector<double>& b) {
129 for (std::size_t i = 0; i < b.size(); ++i) {
130 const double d = std::fabs(a[i] - b[i]);
137static double sumOf(
const std::vector<double>& a) {
147 Kokkos::initialize(
argc, argv);
150 int rank = 0, size = 1;
153 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
154 auto blk =
dec.block(rank);
155 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
156 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
157 const int gn[3] = {
NX,
NY,
NZ};
158 bool cut[3] = {
false,
false,
false};
159 for (
const auto& sz :
dec.sizes())
160 for (
int a = 0; a < 3; ++a)
161 if ((
int)sz[a] != gn[a])
164 std::printf(
"VOF CUTCELL MPI np=%d grid %dx%dx%d block %dx%dx%d cut axes: %s%s%s\n", size,
167 if (size > 1 && !cut[2]) {
169 std::printf(
" FAIL — the decomposition does not cut z, so no sphere is cut\n");
174 [](
int x,
int y,
int z) {
return sdfAt(x + 0.5, y + 0.5, z + 0.5); }, 0, 0, 0,
NX,
NY,
NZ);
180 std::vector<double>
gU[3];
189 ref.setBodyForce(2e-3, 1e-3, 5e-4);
190 ref.setSolid(
gSdf,
true);
191 for (
int i = 0; i < 40; ++i)
193 refDiv = ref.maxOpenDivergence();
194 for (
int c = 0; c < 3; ++c)
195 gU[c] = ref.getVelocity(c);
198 const double v0 = ref.vofDiagnostics().volume;
199 const double dtA = 0.2 / ref.vofMaxCourant();
201 ref.advectVofKinematic(
dtA);
202 const auto d1 = ref.vofDiagnostics();
207 " reference (full grid, every rank): max|div(open u)| %.3e, %d kinematic steps at "
208 "dt %.4g, drift %.3e, clipped %.3e\n",
230 for (
int w = 0; w < 5; ++w) {
236 for (
int c = 0; c < 3; ++c)
268 const double drift = (
v1 -
v0) /
v0;
270 " [kinematic np=%d] geometry %.3e band fill %.3e colour %.3e "
271 "drift %.3e (ref %.3e) max|div| %.3e\n",
273 if (!(
dg == 0.0) || !(
dfill == 0.0) || !(
dc == 0.0)) {
274 std::printf(
" [kinematic np=%d] FAIL — not bitwise\n", size);
277 if (!(std::fabs(drift) <= 1e-11)) {
278 std::printf(
" [kinematic np=%d] FAIL — colour volume drift %.3e\n", size, drift);
286 const int steps = 30;
287 const double ratio = 10.0,
grav = 2e-3;
308 for (
int i = 0; i < steps; ++i) {
320 std::vector<double>
gu[3];
321 for (
int c = 0; c < 3; ++c)
326 for (
int i = 0; i < steps; ++i)
329 for (
int c = 0; c < 3; ++c)
330 du = std::fmax(du,
maxAbsDiff(
gu[c], ref.getVelocity(c)));
332 const double drift = (
v1 -
v0) /
v0;
333 const double tol = size == 1 ? 0.0 : 1e-9;
335 " [coupled np=%d] colour %.3e velocity %.3e drift %.3e solid sum C %.3e "
336 "max|div| %.3e pressure iters max %ld\n",
339 std::printf(
" [coupled np=%d] FAIL — colour %.3e velocity %.3e above tol %.1e\n", size,
343 if (!(solid == 0.0)) {
344 std::printf(
" [coupled np=%d] FAIL — colour in solid cells %.3e\n", size, solid);
347 if (!(std::fabs(drift) <= 1e-8)) {
348 std::printf(
" [coupled np=%d] FAIL — colour drift %.3e\n", size, drift);
357 std::printf(
fail ?
"VOF CUTCELL MPI: FAILED\n" :
"VOF CUTCELL MPI: all checks passed\n");
void setSolid(const std::vector< double > &sdfInner, bool cutcellPressure)
Host entry point: upload the inner SDF once and delegate.
double maxOpenDivergence()
std::vector< double > getVofFilledColour()
void setAdvection(bool on)
std::vector< double > getVofGeometry(int which)
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 setField(const std::string &name, const std::vector< double > &v)
std::vector< double > getVelocity(int c)
long lastPressureIterations() const
void setMu(double m)
Dynamic viscosity, in the caller's units.
void advectVofKinematic(double dtPhysArg)
dt is in the caller's time unit.
void setRho(double r)
Fluid density, in the caller's units.
vof::WyAdvector::Diagnostics vofDiagnostics()
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 double colourAt(int, int, int z)
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 std::vector< double > sliceOf(const std::vector< double > &g, int ox, int oy, int oz, int lnx, int lny, int lnz)
static double maxAbsDiff(const std::vector< double > &a, const std::vector< double > &b)
static double sumOf(const std::vector< double > &a)
static double sdfAt(double x, double y, double z)
static constexpr std::size_t GCELLS