28#include <Kokkos_Core.hpp>
48 std::fprintf(stderr, "CHECK failed: %s\n at %s:%d\n", #cond, __FILE__, __LINE__); \
53std::size_t idx(
int x,
int y,
int z,
int nx,
int ny) {
54 return (std::size_t)x + (std::size_t)y * nx + (std::size_t)z * (std::size_t)nx * ny;
64 double cx[8], cy[8], cz[8],
r[8];
66 double sdfAt(
double x,
double y,
double z)
const {
68 for (
int s = 0;
s <
n; ++
s)
69 for (
int px = -1; px <= 1; ++px)
70 for (
int py = -1; py <= 1; ++py)
71 for (
int pz = -1; pz <= 1; ++pz) {
72 const double dx =
x - (cx[
s] + px *
N), dy = y - (cy[s] + py * N),
73 dz =
z - (cz[
s] + pz *
N);
74 const double d = std::sqrt(dx * dx + dy * dy + dz * dz) -
r[
s];
75 best =
d < best ?
d : best;
81SphereArray makeArray(
int N) {
85 const double f =
N / 32.0;
86 const double px[4] = {6.0, 20.0, 11.0, 26.0}, py[4] = {7.0, 9.0, 24.0, 22.0},
87 pz[4] = {8.0, 23.0, 19.0, 6.0};
88 for (
int s = 0;
s < 4; ++
s) {
97std::vector<double> arraySdfInner(
const SphereArray& a,
int N) {
98 std::vector<double> sd((std::size_t)
N *
N *
N);
99 for (
int z = 0;
z <
N; ++
z)
100 for (
int y = 0;
y <
N; ++
y)
101 for (
int x = 0;
x <
N; ++
x)
102 sd[idx(x, y, z,
N,
N)] =
a.sdfAt(x + 0.5, y + 0.5, z + 0.5);
107void arraySdfBlock(
const SphereArray& a, CCField dst, I3 e,
int g) {
108 auto h = Kokkos::create_mirror_view(dst);
109 for (
int z = 0;
z <
e.z; ++
z)
110 for (
int y = 0;
y <
e.y; ++
y)
111 for (
int x = 0;
x <
e.x; ++
x)
112 h(
L3(x, y, z, e)) =
a.sdfAt(x - g + 0.5, y - g + 0.5, z - g + 0.5);
113 Kokkos::deep_copy(dst, h);
116std::vector<double> hostOf(SField v) {
117 auto h = Kokkos::create_mirror_view(v);
118 Kokkos::deep_copy(h, v);
119 std::vector<double>
out(
v.extent(0));
120 for (std::size_t i = 0;
i <
out.size(); ++
i)
127 for (
int i = 0;
i <
steps; ++
i)
132void bridgeWithGeometry() {
134 const SphereArray arr = makeArray(
N);
139 s.setBodyForce(2e-3, 1e-3, 0.0);
140 s.setSolid(arraySdfInner(arr,
N),
true);
143 CHECK(
s.vofHasGeometry());
147 const I3 e3{
N + 2 *
g,
N + 2 *
g,
N + 2 *
g};
148 const long len = (long)e3.x * e3.y * e3.z;
149 CCField sdf3(
"t::sdf3", len), ox3(
"t::ox3", len), oy3(
"t::oy3", len), oz3(
"t::oz3", len),
151 arraySdfBlock(arr, sdf3, e3, g);
152 peclet::flow::buildOpenness(ox3, oy3, oz3,
CCConst(sdf3), C3{e3.x, e3.y, e3.z}, 1.0, 1.0, 1.0,
155 const std::vector<double> refO[3] = {hostOf(ox3), hostOf(oy3), hostOf(oz3)};
156 const auto refE = hostOf(cs3);
157 const long sd3[3] = {1, (long)e3.x, (
long)e3.x * e3.y};
159 const auto& adv =
s.vofAdvector();
160 double dOpen = 0.0, dEps = 0.0;
161 for (
int d = 0;
d < 3; ++
d) {
162 const auto got = hostOf(adv.faceOpenness(d));
163 for (
int z = g;
z <
g +
N; ++
z)
164 for (
int y = g;
y <
g +
N; ++
y)
165 for (
int x = g;
x <
g +
N; ++
x) {
166 const long i =
L3(x, y, z, e3);
170 dOpen = std::fmax(dOpen, std::fabs(got[i] - refO[d][i + sd3[d]]));
174 const auto got = hostOf(adv.epsFraction());
175 for (
int z = g;
z <
g +
N; ++
z)
176 for (
int y = g;
y <
g +
N; ++
y)
177 for (
int x = g;
x <
g +
N; ++
x) {
178 const long i =
L3(x, y, z, e3);
179 dEps = std::fmax(dEps, std::fabs(got[i] - refE[i]));
183 "G3a geometry embed: max|openness - independent| %.3e max|eps - independent| %.3e\n", dOpen,
190 std::vector<double> c0((std::size_t)
N *
N *
N, 0.0);
191 for (
int z = 0;
z <
N; ++
z)
192 for (
int y = 0;
y <
N; ++
y)
193 for (
int x = 0;
x <
N; ++
x)
194 c0[idx(x, y, z,
N,
N)] = (
z <
N / 2) ? 1.0 : ((
z ==
N / 2) ? 0.37 : 0.0);
198 ref.init(
N,
N,
N, 1.0, g);
202 ref.interfaceLocalCfl =
true;
203 ref.enableGeometry();
206 auto ho = Kokkos::create_mirror_view(
ref.faceOpenness(0));
207 for (
int d = 0;
d < 3; ++
d) {
208 auto hd = Kokkos::create_mirror_view(
ref.faceOpenness(d));
209 for (
long i = 0;
i < len; ++
i)
210 hd(i) = (
i + sd3[
d] < len) ? refO[d][i + sd3[d]] : 0.0;
211 Kokkos::deep_copy(
ref.faceOpenness(d), hd);
213 auto he = Kokkos::create_mirror_view(
ref.epsFraction());
214 for (
long i = 0;
i < len; ++
i)
216 Kokkos::deep_copy(
ref.epsFraction(), he);
221 if (
ref.hasGeometry() &&
f.data() ==
ref.colour().data()) {
230 ref.classifyGeometry();
232 ref.finalizeGeometry();
234 auto hc = Kokkos::create_mirror_view(
ref.colour());
235 auto hk = Kokkos::create_mirror_view(
ref.kindDouble());
236 Kokkos::deep_copy(hk,
ref.kindDouble());
237 for (
long i = 0;
i < len; ++
i)
239 for (
int z = 0;
z <
N; ++
z)
240 for (
int y = 0;
y <
N; ++
y)
241 for (
int x = 0;
x <
N; ++
x) {
242 const long i =
L3(x + g, y + g, z + g, e3);
243 hc(i) = hk(i) > 0.5 ? 0.0 : c0[idx(x, y, z,
N,
N)];
245 Kokkos::deep_copy(
ref.colour(), hc);
249 const auto uu =
s.getVelocity(0), vv =
s.getVelocity(1), ww =
s.getVelocity(2);
251 auto hu = Kokkos::create_mirror_view(
ref.faceU());
252 auto hv = Kokkos::create_mirror_view(
ref.faceV());
253 auto hw = Kokkos::create_mirror_view(
ref.faceW());
254 for (
int z = 0;
z < e3.z; ++
z)
255 for (
int y = 0;
y < e3.y; ++
y)
256 for (
int x = 0;
x < e3.x; ++
x) {
257 const int gx = ((
x -
g) %
N +
N) %
N, gy = ((
y -
g) %
N +
N) %
N,
258 gz = ((
z -
g) %
N +
N) %
N;
259 const long i =
L3(x, y, z, e3);
260 hu(i) = uu[idx((gx + 1) %
N, gy, gz,
N,
N)];
261 hv(i) = vv[idx(gx, (gy + 1) %
N, gz,
N,
N)];
262 hw(i) = ww[idx(gx, gy, (gz + 1) %
N,
N,
N)];
264 Kokkos::deep_copy(
ref.faceU(), hu);
265 Kokkos::deep_copy(
ref.faceV(), hv);
266 Kokkos::deep_copy(
ref.faceW(), hw);
268 const double dth = 1.0;
269 double cflRef =
ref.maxCourantInterfaceAuto(dth);
270 const double dtA = cflRef > 0 ? 0.2 / cflRef : 1.0;
272 const int steps = 20;
273 for (
int t = 0;
t <
steps; ++
t) {
275 s.advectVofKinematic(dtA);
277 const auto cs =
s.getVof();
278 const auto cr = hostOf(
ref.colour());
279 const auto kr = hostOf(
ref.kindDouble());
282 double dmax = 0.0, fillMax = 0.0;
283 for (
int z = 0;
z <
N; ++
z)
284 for (
int y = 0;
y <
N; ++
y)
285 for (
int x = 0;
x <
N; ++
x) {
286 const long i =
L3(x + g, y + g, z + g, e3);
288 fillMax = std::fmax(fillMax, cr[i]);
291 dmax = std::fmax(dmax, std::fabs(cs[idx(x, y, z,
N,
N)] - cr[i]));
294 "G3b solver vs standalone through the packing (%d steps, cfl 0.2, dt %.4g): max|dC| over "
295 "fluid cells %.3e (standalone band fill reaches %.3f)\n",
296 steps, dtA, dmax, fillMax);
301void conservationThroughPacking(
int N,
int nAdv) {
302 const SphereArray arr = makeArray(
N);
307 s.setBodyForce(2e-3, 1e-3, 5e-4);
308 s.setSolid(arraySdfInner(arr,
N),
true);
310 const double div =
s.maxOpenDivergence();
311 const long pit =
s.lastPressureIterations();
313 std::vector<double> c0((std::size_t)
N *
N *
N, 0.0);
314 for (
int z = 0;
z <
N; ++
z)
315 for (
int y = 0;
y <
N; ++
y)
316 for (
int x = 0;
x <
N; ++
x)
317 c0[idx(x, y, z,
N,
N)] = (
z <
N / 2) ? 1.0 : 0.0;
320 const auto d0 =
s.vofDiagnostics();
321 const double cfl =
s.vofMaxCourant();
322 const double dtA = cfl > 0 ? 0.2 / cfl : 1.0;
323 double clip = 0.0, mnF = 1e30, mxF = -1e30, solidSum = 0.0;
324 for (
int t = 0;
t < nAdv; ++
t) {
325 s.advectVofKinematic(dtA);
326 const auto d =
s.vofDiagnostics();
327 clip +=
d.clippedVolume;
328 mnF = std::fmin(mnF,
d.minCFluid);
329 mxF = std::fmax(mxF,
d.maxCFluid);
330 solidSum = std::fmax(solidSum, std::fabs(
d.solidSumC));
332 const auto d1 =
s.vofDiagnostics();
333 const double drift = std::fabs(d1.volume -
d0.volume) /
d0.volume;
334 const double rawDrift = std::fabs(d1.rawVolume -
d0.rawVolume) /
d0.rawVolume;
336 "G2 packing %d^3, %d kinematic steps at cfl 0.2 (dt %.4g):\n"
337 " max|div(open u)| %.3e (pressure iters %ld)\n"
338 " sum eps_eff C: %.15e -> %.15e relative drift %.3e\n"
339 " sum eps C: %.15e -> %.15e relative drift %.3e\n"
340 " solid cells %ld, cut cells %ld, max|sum C over solid| %.3e\n"
341 " min/max C over UNCUT fluid cells %.3e / %.15e\n"
342 " clipped liquid volume, total over the run %.6e (%.3e of the liquid volume)\n",
343 N, nAdv, dtA, div, pit,
d0.volume, d1.volume, drift,
d0.rawVolume, d1.rawVolume, rawDrift,
344 d1.solidCells, d1.cutCells, solidSum, mnF, mxF, clip, clip /
d0.volume);
346 CHECK(drift <= 1e-11);
347 CHECK(solidSum == 0.0);
348 CHECK(mnF >= -1e-12);
349 CHECK(mxF <= 1.0 + 1e-12);
350 CHECK(d1.solidCells > 0);
351 CHECK(d1.cutCells > 0);
359void neutralFillCap(
int steps,
bool zeroSolid =
true) {
360 const int NX = 40,
NY = 40,
NZ = 28;
361 const double zw = 3.5;
362 const double R = 12.0;
363 const double sigma = 1.0;
364 std::vector<double> sd((std::size_t)
NX *
NY *
NZ);
365 for (
int z = 0;
z <
NZ; ++
z)
366 for (
int y = 0;
y <
NY; ++
y)
367 for (
int x = 0;
x <
NX; ++
x)
368 sd[idx(x, y, z,
NX,
NY)] = (
z + 0.5) - zw;
371 const double cx =
NX * 0.5, cy =
NY * 0.5;
372 std::vector<double> c0((std::size_t)
NX *
NY *
NZ, 0.0);
373 for (
int z = 0;
z <
NZ; ++
z)
374 for (
int y = 0;
y <
NY; ++
y)
375 for (
int x = 0;
x <
NX; ++
x) {
377 for (
int a = 0;
a < 4; ++
a)
378 for (
int b = 0;
b < 4; ++
b)
379 for (
int c = 0;
c < 4; ++
c) {
380 const double px =
x + (
a + 0.5) / 4.0, py = y + (b + 0.5) / 4.0,
381 pz =
z + (
c + 0.5) / 4.0;
385 const double dx = px - cx,
dy = py - cy,
dz = pz - zw;
386 if (dx * dx + dy * dy + dz * dz < R * R)
389 c0[idx(x, y, z,
NX,
NY)] =
tot ? (double)in / tot : 0.0;
395 s.setSolid(sd,
true);
397 s.setVofSolidColourZero(zeroSolid);
399 s.setSurfaceTension(sigma);
400 const double dtSig =
s.capillaryDt();
401 s.setDt(0.5 * dtSig);
402 const double V00 =
s.vofDiagnostics().volume;
404 double uTrace[4] = {0, 0, 0, 0};
405 for (
int i = 0;
i <
steps; ++
i) {
407 maxIt = std::max(maxIt,
s.lastPressureIterations());
408 if ((i + 1) % (steps / 4) == 0) {
409 const int slot = std::min(3, (i + 1) / (steps / 4) - 1);
411 for (
int c = 0;
c < 3; ++
c)
412 for (
double v :
s.getVelocity(
c))
413 m = std::fmax(
m, std::fabs(
v));
419 const auto cens = [&] {
420 s.computeVofCurvature();
421 return s.vofCurvatureStats();
423 const auto kap =
s.getVofCurvature();
424 const auto kbr =
s.getVofCurvatureBranch();
425 double kmaxWall = 0.0;
426 long brWall[7] = {0, 0, 0, 0, 0, 0, 0};
427 for (
int z = (
int)std::ceil(zw);
z < (
int)std::ceil(zw) + 2; ++
z)
428 for (
int y = 0;
y <
NY; ++
y)
429 for (
int x = 0;
x <
NX; ++
x) {
430 const std::size_t
i = idx(x, y, z,
NX,
NY);
431 const int b = (
int)kbr[i];
435 kmaxWall = std::fmax(kmaxWall, std::fabs(kap[i]));
437 const auto d =
s.vofDiagnostics();
438 const auto cc =
s.getVof();
442 const int x0 =
NX / 2, y0 =
NY / 2;
443 for (
int z = 0;
z <
NZ; ++
z)
444 h += cc[idx(x0, y0, z,
NX,
NY)] * ((
z + 1 <= zw) ? 0.0 : std::fmin(1.0,
z + 1 - zw));
448 const int z0 = (
int)std::ceil(zw);
450 for (
int y = 0;
y <
NY; ++
y)
451 for (
int x = 0;
x <
NX; ++
x)
452 area += cc[idx(x, y, z0,
NX,
NY)];
453 const double a = std::sqrt(area / M_PI);
454 const double theta = 2.0 * std::atan2(h, a) * 180.0 / M_PI;
455 const double Rc = (
a *
a +
h *
h) / (2.0 * h);
456 const double V =
d.volume;
457 const double V0 = 2.0 * M_PI *
R *
R *
R / 3.0;
459 const auto pf =
s.getField(
"p");
460 double pIn = 0.0, pOut = 0.0;
461 int nIn = 0, nOut = 0;
462 for (
int z = 0;
z <
NZ; ++
z)
463 for (
int y = 0;
y <
NY; ++
y)
464 for (
int x = 0;
x <
NX; ++
x) {
465 const double dx =
x + 0.5 - cx,
dy =
y + 0.5 - cy,
dz =
z + 0.5 - zw;
466 const double r = std::sqrt(dx * dx + dy * dy + dz * dz);
470 pIn += pf[idx(x, y, z,
NX,
NY)];
472 }
else if (r > 1.5 * R && r < 1.8 * R) {
473 pOut += pf[idx(x, y, z,
NX,
NY)];
477 const double dP = (nIn ? pIn / nIn : 0.0) - (nOut ? pOut / nOut : 0.0);
481 double umax = 0.0, umaxAll = 0.0;
482 for (
int c = 0;
c < 3; ++
c) {
483 const auto v =
s.getVelocity(c);
484 for (
int z = 0;
z <
NZ; ++
z)
485 for (
int y = 0;
y <
NY; ++
y)
486 for (
int x = 0;
x <
NX; ++
x) {
487 const double a = std::fabs(v[idx(x, y, z,
NX,
NY)]);
488 umaxAll = std::fmax(umaxAll, a);
489 if (z >= (
int)std::ceil(zw) + 1)
490 umax = std::fmax(umax, a);
493 const double Ca = 0.05 *
umax / sigma;
495 "G5 cap on a cut wall (D/dx %.0f, %d steps at 0.5 dt_sigma = %.4g, solid colour %s), "
496 "pressure iters max %ld:\n"
497 " volume %.6f -> %.6f (drift %.3e); analytic hemisphere %.6f\n"
498 " h %.4f a %.4f -> apparent theta %.3f deg (target 90)\n"
499 " cap sphere radius %.4f (target %.1f); Young-Laplace dP %.6f vs 2 sigma/R %.6f "
501 " max|u| (open fluid) %.3e -> spurious Ca %.3e ; max|u| incl. the wall band %.3e ;\n"
502 " trace of max|u| (all cells) over the run %.2e %.2e %.2e %.2e\n"
503 " wall band: max|kappa| %.4f, branches 0/1/2/3/4/5/6 = %ld/%ld/%ld/%ld/%ld/%ld/%ld "
504 "(global no_estimate %ld)\n"
505 " clipped volume last step %.3e ; clamped faces %ld ; solid sum C %.3e\n",
506 2 * R, steps, 0.5 * dtSig, zeroSolid ?
"ZERO" :
"band fill", maxIt, V00,
V,
507 std::fabs(
V - V00) / V00, V0,
h,
a,
theta, Rc,
R,
dP, 2.0 * sigma / Rc,
508 std::fabs(
dP - 2.0 * sigma / Rc) / (2.0 * sigma / Rc),
umax, Ca, umaxAll, uTrace[0],
509 uTrace[1], uTrace[2], uTrace[3], kmaxWall, brWall[0], brWall[1], brWall[2], brWall[3],
510 brWall[4], brWall[5], brWall[6], cens.noEstimate,
d.clippedVolume,
d.clampedFaces,
512 CHECK(std::fabs(theta - 90.0) <= 3.0);
513 CHECK(std::fabs(dP - 2.0 * sigma / Rc) / (2.0 * sigma / Rc) <= 0.01);
515 CHECK(
d.solidSumC == 0.0);
516 CHECK(std::fabs(V - V00) / V00 <= 1e-9);
530void momentumCutCells() {
532 const SphereArray arr = makeArray(
N);
533 const auto sdf = arraySdfInner(arr,
N);
534 const double U[3] = {1.0, 0.6, -0.4};
536 for (
double R : {10.0, 1
e2, 1e3}) {
544 s.setSolid(sdf,
true);
545 s.setPressureChebyshev(
true, 300, 1e-13);
547 std::vector<double> c0((std::size_t)
N *
N *
N);
548 for (
int z = 0;
z <
N; ++
z)
549 for (
int y = 0;
y <
N; ++
y)
550 for (
int x = 0;
x <
N; ++
x)
551 c0[idx(x, y, z,
N,
N)] = peclet::flow::vof::sphereCellFraction(0.5 *
N, 0.5 *
N, 0.5 *
N,
552 0.28 *
N, x, y, z, 1.0, 4);
555 s.enableVofMomentum(1.0, R);
556 const std::size_t
nc = (std::size_t)
N *
N *
N;
557 s.uploadVelocity(std::vector<double>(nc,
U[0]), std::vector<double>(nc,
U[1]),
558 std::vector<double>(nc,
U[2]));
559 s.advectVofMomentum();
561 for (
int c = 0;
c < 3; ++
c)
562 for (
double v :
s.getVofAdvectedVelocity(
c))
563 dev = std::fmax(dev, std::fabs(
v -
U[
c]));
564 const auto md =
s.vofMomentumDiagnostics();
566 "G8a packing + uniform U, ratio %-6g: max|u_adv - U| = %.17g%s (rho^e floor hit %ld, "
567 "flux clamps %ld)\n",
568 R, dev, dev == 0.0 ?
" BITWISE" :
"", md.floored, md.clamped);
570 CHECK(md.floored == 0);
586 for (
int momentumOn = 1; momentumOn >= 0; --momentumOn) {
587 const double R = 10.0, grav = 2
e-3;
588 const double liq = 0.25, rhoMean = liq *
R + (1.0 - liq);
593 s.setSolid(sdf,
true);
595 std::vector<double> c0((std::size_t)
N *
N *
N, 0.0);
596 for (
int z = 0;
z <
N; ++
z)
597 for (
int y = 0;
y <
N; ++
y)
598 for (
int x = 0;
x <
N; ++
x)
599 c0[idx(x, y, z,
N,
N)] = (
z >= 3 *
N / 4) ? 1.0 : 0.0;
603 const bool nonZeroMean = std::getenv(
"PECLET_VOF_CUTCELL_NONZERO_FORCE") !=
nullptr;
605 {nonZeroMean ? 0.0 : grav * rhoMean, -grav});
607 s.enableVofMomentum(1.0, R);
608 const double v0 =
s.vofDiagnostics().volume;
610 const int steps = 200;
611 double umax = 0.0, clip = 0.0, mn = 1e30,
mx = -1e30;
612 for (
int i = 0;
i <
steps; ++
i) {
614 maxIt = std::max(maxIt,
s.lastPressureIterations());
615 const auto d =
s.vofDiagnostics();
616 clip +=
d.clippedVolume;
617 mn = std::fmin(mn,
d.minCFluid);
618 mx = std::fmax(mx,
d.maxCFluid);
619 if (std::getenv(
"PECLET_VOF_CUTCELL_TRACE") && (i % 5) == 0) {
621 for (
int c = 0;
c < 3; ++
c)
622 for (
double v :
s.getVelocity(
c))
623 um = um > std::fabs(
v) ? um : std::fabs(
v);
624 double mnCc = 0, mxCc = 0, mnRho = 0;
627 const auto md =
s.vofMomentumDiagnostics();
628 for (
int c = 0;
c < 3; ++
c) {
629 mnCc = std::fmin(mnCc, md.minCc[c]);
630 mxCc = std::fmax(mxCc, md.maxCc[c]);
633 floored = md.floored;
636 " trace %3d vol %.12e minC %.3e maxC %.6f max|u| %.4e cfl %.4f iters %ld "
637 "C^e [%.3e, %.6f] minRho^e %.4e floored %ld\n",
638 i,
d.volume,
d.minCFluid,
d.maxCFluid, um,
s.vofLastCourant(),
639 s.lastPressureIterations(), mnCc, mxCc, mnRho, floored);
642 for (
int c = 0;
c < 3; ++
c)
643 for (
double v :
s.getVelocity(
c))
645 const auto d1 =
s.vofDiagnostics();
646 const double drift = (d1.volume - v0) / v0;
648 "G8b packing draining, ratio %g, %d coupled steps, momentum consistency %s:\n"
649 " colour drift %.3e (%.3e per step), max|div(open u)| %.3e, pressure iters max %ld\n"
650 " min/max C over uncut fluid %.3e / %.15f, clipped volume total %.3e, max|u| %.3e, "
651 "solid sum C %.3e\n",
652 R, steps, momentumOn ?
"ON" :
"off", drift, drift /
steps,
s.maxOpenDivergence(), maxIt, mn,
653 mx, clip,
umax, d1.solidSumC);
654 CHECK(!std::isnan(umax) && !std::isnan(drift));
655 CHECK(std::fabs(drift) / steps <= 1e-10);
656 CHECK(d1.solidSumC == 0.0);
663int main(
int argc,
char** argv) {
664 std::setvbuf(stdout,
nullptr, _IONBF, 0);
665 Kokkos::initialize(argc, argv);
668 if (
const char* e = std::getenv(
"PECLET_VOF_CUTCELL_LONG"))
669 quick = (e[0] ==
'0');
670 bridgeWithGeometry();
671 conservationThroughPacking(quick ? 24 : 48, quick ? 200 : 500);
672 if (!std::getenv(
"PECLET_VOF_CUTCELL_SKIP_G5")) {
673 neutralFillCap(quick ? 120 : 200);
677 if (std::getenv(
"PECLET_VOF_CUTCELL_FILL_ABLATION"))
678 neutralFillCap(quick ? 120 : 200,
false);
684 std::fprintf(stderr,
"%d check(s) FAILED\n",
failures);
686 std::printf(
"all vof cut-cell checks passed\n");
static constexpr int kVofG
static constexpr double defaultVofWispEps()
The value enableVof starts from.
Weymouth-Yue split advection of a colour field on an extended (inner + ghost) block.
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
Slot slot(const Kokkos::View< double *, CCMem > &ks, int k)
long L3(int x, int y, int z, I3 e)
void buildCellFraction(CCField cs, CCConst sdf, C3 e, int g)
Kokkos::View< double *, CCMem > CCField
void buildOpenness(CCField ox, CCField oy, CCField oz, CCConst sdf, C3 ext, double dx, double dy, double dz, int order=1)
Kokkos::View< const double *, CCMem > CCConst
Kokkos::View< double *, SMem > SField
void periodicFill(SField f, I3 e, int g, bool px, bool py, bool pz)
Periodic wrap of a single-block extended field (serial reference path; the MPI path uses core's GridH...
flow — thin shim: the container-free VoF PLIC geometric toolbox (rung V0) now live in core.
static double sdfAt(int gx, int gy, int gz, int nx, int ny, int nz, double dref)
static constexpr double U