28#include <Kokkos_Core.hpp>
32#include "peclet/core/common/types.hpp"
33#include "peclet/core/decomp/block_decomposer.hpp"
38static constexpr int NX = 24,
NY = 24,
NZ = 48;
42static constexpr double RB = 4.5,
GRAV = 2.0e-3;
45static const double CX[2] = {
NX / 2.0 + 0.13,
NX / 2.0 + 0.13};
46static const double CY[2] = {
NY / 2.0 - 0.21,
NY / 2.0 - 0.21};
47static const double CZ[2] = {14.0 + 0.31, 24.0 + 0.31};
50static double bubbleAt(
int b,
int x,
int y,
int z) {
53 for (
int j = 0; j < NS; ++j)
54 for (
int i = 0; i < NS; ++i) {
55 const double px = x + (i + 0.5) / NS -
CX[b], py = y + (j + 0.5) / NS -
CY[b];
56 const double r2 =
RB *
RB - px * px - py * py;
59 const double h = std::sqrt(r2);
60 const double lo = std::fmax(
CZ[b] - h, (
double)z), hi = std::fmin(
CZ[b] + h, (
double)z + 1);
64 return acc / (NS * NS);
77 std::vector<double> c((std::size_t)
lnx *
lny *
lnz, 0.0);
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 const double v = std::fmax(
bubbleAt(0, x + ox, y + oy, z + oz),
82 bubbleAt(1, x + ox, y + oy, z + oz));
83 c[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] = v;
92 std::vector<std::array<int, 6>>
boxes;
93 for (
int b = 0; b < 2; ++b) {
95 const double c3[3] = {
CX[b],
CY[b],
CZ[b]};
96 for (
int d = 0; d < 3; ++d) {
97 q[d] = (int)std::floor(c3[d] -
RB) - 1;
98 q[3 + d] = (int)std::ceil(c3[d] +
RB) + 1;
115static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
116 int lnx,
int lny,
int lnz,
int rank,
int size) {
117 std::vector<double>
global;
120 for (
int r = 0; r < size; ++r) {
124 for (
int z = 0; z <
lnz; ++z)
125 for (
int y = 0; y <
lny; ++y)
126 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
127 (std::size_t)(z + oz) *
NX *
NY],
129 (std::size_t)
lnx *
sizeof(
double));
135 }
else if (rank == 0) {
140 for (
int z = 0; z <
meta[5]; ++z)
141 for (
int y = 0; y <
meta[4]; ++y)
142 std::memcpy(&
global[(std::size_t)
meta[0] + (std::size_t)(y +
meta[1]) *
NX +
143 (std::size_t)(z +
meta[2]) *
NX *
NY],
145 (std::size_t)
meta[3] *
sizeof(
double));
151static double maxDiff(
const std::vector<double>& a,
const std::vector<double>& b) {
153 for (std::size_t i = 0; i < b.size(); ++i)
154 m = std::fmax(m, std::fabs(a[i] - b[i]));
157static long countBitDiff(
const std::vector<double>& a,
const std::vector<double>& b,
double& mx) {
160 for (std::size_t i = 0; i < b.size(); ++i)
163 mx = std::fmax(mx, std::fabs(a[i] - b[i]));
170 Kokkos::initialize(
argc, argv);
173 int rank = 0, size = 1;
177 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
178 auto blk =
dec.block(rank);
179 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
180 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
181 const int gn[3] = {
NX,
NY,
NZ};
182 bool cut[3] = {
false,
false,
false};
183 for (
const auto& sz :
dec.sizes())
184 for (
int a = 0; a < 3; ++a)
185 if ((
int)sz[a] != gn[a])
189 "VOF BLOCK NS MPI (rung W2, WO-W12) np=%d grid %dx%dx%d block %dx%dx%d cut axes: "
191 size,
NX,
NY,
NZ,
lnx,
lny,
lnz, cut[0] ?
"x" :
"", cut[1] ?
"y" :
"", cut[2] ?
"z" :
"");
192 if (size > 1 && !cut[2]) {
194 std::printf(
" FAIL - the decomposition does NOT cut z, so no marker is cut\n");
198 const int STEPS = (
argc > 1) ? std::atoi(argv[1]) : 12;
200 const bool csf = (
cfg == 1);
202 std::printf(
" --- configuration: block advection + varRho%s\n",
203 csf ?
" + the BLOCK CSF" :
" (surface tension OFF)");
211 for (
int k = 0; k <
STEPS; ++k) {
216 nDebris += q.debrisCells + q.debrisUnresolved + (q.debrisReturned != 0.0 ? 1 : 0);
224 std::printf(
" overlap-design counters over %d steps: clipped %ld, debris cells %ld, "
226 if (
glb[0] != 0 ||
glb[1] != 0 ||
glb[2] != 0) {
228 std::printf(
" FAIL: an overlap-design rule fired on a non-colliding pair\n");
236 for (
const auto& q : stats)
237 std::printf(
" dist block %ld master %d box [%d,%d)x[%d,%d)x[%d,%d)\n", q.id, q.master,
238 q.lo[0], q.hi[0], q.lo[1], q.hi[1], q.lo[2], q.hi[2]);
239 std::vector<double>
vLoc(stats.size(), 0.0),
vAll(stats.size(), 0.0);
240 std::vector<double>
aLoc(stats.size(), 0.0),
aAll(stats.size(), 0.0);
241 for (std::size_t i = 0; i < stats.size(); ++i) {
242 vLoc[i] = stats[i].volume;
243 aLoc[i] = stats[i].area;
248 std::vector<double>
gf[3];
250 for (
int c = 0; c < 3; ++c)
252 std::vector<double> g[5];
265 ref.setPressureBottomSolver(2);
266 for (
int k = 0; k <
STEPS; ++k)
268 std::vector<double> r[5] = {ref.getVelocity(0), ref.getVelocity(1), ref.getVelocity(2),
269 ref.getPressure(), ref.getVof()};
270 const char* fn[5] = {
"u",
"v",
"w",
"P",
"C"};
274 for (
int i = 0; i < 5; ++i) {
278 std::printf(
" np=%d after %d steps:", size,
STEPS);
279 for (
int i = 0; i < 5; ++i)
280 std::printf(
" d%s %.2e", fn[i], d[i]);
282 std::printf(
" bitwise-differing cells:");
283 for (
int i = 0; i < 5; ++i)
284 std::printf(
" %s %ld", fn[i], nb[i]);
289 for (
int c = 0; c < 3; ++c) {
290 const std::vector<double> rf = ref.getVofBlockForce(c);
295 std::printf(
" scattered CSF face force vs np=1: max|d| %.3e over %ld bit-differing "
298 for (
const auto& q : ref.vofBlockStats())
299 std::printf(
" ref block %ld box [%d,%d)x[%d,%d)x[%d,%d)\n", q.id, q.lo[0], q.hi[0],
300 q.lo[1], q.hi[1], q.lo[2], q.hi[2]);
301 const auto rs = ref.vofBlockStats();
303 for (std::size_t i = 0; i <
rs.size(); ++i) {
304 dv = std::fmax(dv, std::fabs(
vAll[i] -
rs[i].volume));
305 da = std::fmax(
da, std::fabs(
aAll[i] -
rs[i].area));
308 for (
double q : r[4])
310 std::printf(
" markers: V %.6f / %.6f, area %.2f / %.2f; |dV| vs np=1 %.2e, |dA| %.2e\n",
311 rs[0].volume,
rs[1].volume,
rs[0].area,
rs[1].area, dv,
da);
312 std::printf(
" UNION deficit sum(V_marker) - sum(C_union) = %.4f cells (the shared liquid; "
313 "> 0 means the two markers OVERLAP, which a single field cannot do)\n",
317 const double tolU = (size == 1) ? 0.0 : 1e-12;
318 const double tolP = (size == 1) ? 0.0 : 1e-9;
319 const double tolC = (size == 1) ? 0.0 : 1e-12;
321 for (
int i = 0; i < 5; ++i)
322 if (!(d[i] <=
tol[i])) {
323 std::printf(
" FAIL: d%s = %.3e exceeds %.1e\n", fn[i], d[i],
tol[i]);
326 if (!(dv <= (size == 1 ? 0.0 : 1e-11))) {
327 std::printf(
" FAIL: marker volume drift %.3e\n", dv);
334 std::printf(
"%s\n",
fail ?
"FAILED" :
"PASSED");
void enableVofBlocksFromField(const std::vector< std::array< int, 6 > > &boxes)
void setDomainBc(int face, int type, double vx, double vy, double vz)
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 setSurfaceTension(double sigma)
void setPressureChebyshev(bool on, int maxit, double rtol)
double capillaryDt()
The Brackbill capillary limit in the CALLER's time unit.
void setVof(const std::vector< double > &c)
vof::VofCurvature::Stats vofBlockCurvatureStats() const
std::vector< double > getVofBlockForce(int c)
void setPressureGeometry(const std::vector< double > &sdfInner)
std::vector< double > getVelocity(int c)
VofOverlapCensus vofBlockOverlapCensus() const
void setMu(double m)
Dynamic viscosity, in the caller's units.
void setRho(double r)
Fluid density, in the caller's units.
std::vector< vof::VofBlockStats > vofBlockStats() const
std::vector< double > getPressure()
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
long cells
cells with S > 1 + 1e-8 (global)
long clipped
Cells whose curvature the admissibility clip (kappaMax) bounded this call.
static constexpr int STEPS
static constexpr double GRAV
static constexpr double MU_G
static constexpr double SIGMA
static double maxDiff(const std::vector< double > &a, const std::vector< double > &b)
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 configure(IbmSolver &s, int ox, int oy, int oz, int lnx, int lny, int lnz, bool csf)
static const double CY[2]
static long countBitDiff(const std::vector< double > &a, const std::vector< double > &b, double &mx)
static constexpr double RHO_G
static constexpr double RB
static const double CZ[2]
static double bubbleAt(int b, int x, int y, int z)
static constexpr double RHO_L
static constexpr double MU_L
static constexpr std::size_t GCELLS
static const double CX[2]