21#ifndef PECLET_FLOW_VOF_BLOCK_BATCH_HPP
22#define PECLET_FLOW_VOF_BLOCK_BATCH_HPP
24#include <Kokkos_Core.hpp>
34 const unsigned char*
p;
71 while (t >= off[b + 1])
80 for (
int k = 0; k < T.nj; ++k)
81 T.off[k + 1] = T.off[k] + size(T.job[k]);
83 T.off[k + 1] = T.off[T.nj];
88 return static_cast<long>(
J.e.x) *
J.e.y *
J.e.z;
91 return static_cast<long>(
J.n.x) *
J.n.y *
J.n.z;
95 return static_cast<long>(
J.n.x + 2) * (
J.n.y + 2) * (
J.n.z + 2);
112inline constexpr bool kVofHostExec = std::is_same_v<typename Exec::memory_space, Kokkos::HostSpace>;
123template <
class Exec,
class Cnt,
class F>
128 for (
int k = 0; k < nj; ++k) {
129 const long n = cnt(k);
130 C.o[k + 1] = C.o[k] + (n > 0 ? n : 0);
133 C.o[k + 1] = C.o[nj];
134 Kokkos::RangePolicy<Exec, Kokkos::Schedule<Kokkos::Dynamic>>
pol(
Exec(), 0, C.o[nj]);
135 pol.set_chunk_size(16);
136 Kokkos::parallel_for(name,
pol, [=](
const long t) {
145 return [=](
int k) {
return end(T.base + k) -
start(T.base + k); };
152#ifndef PECLET_FLOW_OMP_SIMD
154#define PECLET_FLOW_OMP_SIMD _Pragma("omp simd")
156#define PECLET_FLOW_OMP_SIMD
168template <
class Exec,
class Rows,
class F>
172 for (
int k = 0; k < nj; ++k)
173 R.off[k + 1] = R.off[k] + rows(k);
175 R.off[k + 1] = R.off[nj];
176 Kokkos::parallel_for(name, Kokkos::RangePolicy<Exec>(
Exec(), 0, R.off[nj]), [=](
const long t) {
177 const int k = vofJobOf(R.off, t);
178 row(k, t - R.off[k]);
186template <
class Exec,
class Rows,
class RowOf,
class Hit>
191 for (
int k = 0; k < nj; ++k)
192 R.off[k + 1] = R.off[k] + rows(k);
194 R.off[k + 1] = R.off[nj];
195 Kokkos::parallel_scan(name, Kokkos::RangePolicy<Exec>(
Exec(), 0, R.off[nj]),
196 [=](
const long t,
long&
upd,
const bool final) {
197 const int k = vofJobOf(R.off, t);
198 const long r = t - R.off[k];
200 const long i0 = rowOf(k, r, x0, x1);
205 for (int x = x0; x < x1; ++x)
208 if (t + 1 == R.off[k + 1])
211 for (int x = x0; x < x1; ++x)
226 using Team = Kokkos::TeamPolicy<SExec>;
227 Kokkos::parallel_for(
228 "vof::block::batch_cfl",
Team(
SExec(), T.nj, Kokkos::AUTO),
230 const int k = tm.league_rank();
232 const I3 e =
J.e, n =
J.n;
234 const long sx = 1, sy = e.x, sz =
static_cast<long>(e.x) * e.y;
235 const long region =
static_cast<long>(n.x) * n.y * n.z;
237 const double weps =
J.weps;
238 const bool band0 =
J.interfaceCfl;
240 Kokkos::parallel_reduce(
241 Kokkos::TeamThreadRange(tm,
region),
242 [&](
const long r,
double& acc) {
243 const int x =
static_cast<int>(r % n.x) + g;
244 const int y =
static_cast<int>((r / n.x) % n.y) + g;
245 const int z =
static_cast<int>(r / (
static_cast<long>(n.x) * n.y)) + g;
246 const long i =
L3(x, y, z, e);
248 acc = Kokkos::fmax(acc, Kokkos::fabs(u(i)));
249 acc = Kokkos::fmax(acc, Kokkos::fabs(v(i)));
250 acc = Kokkos::fmax(acc, Kokkos::fabs(w(i)));
254 const double ci = c(i);
262 acc = Kokkos::fmax(acc, Kokkos::fabs(u(i)));
263 acc = Kokkos::fmax(acc, Kokkos::fabs(u(i -
sx)));
264 acc = Kokkos::fmax(acc, Kokkos::fabs(v(i)));
265 acc = Kokkos::fmax(acc, Kokkos::fabs(v(i - sy)));
266 acc = Kokkos::fmax(acc, Kokkos::fabs(w(i)));
267 acc = Kokkos::fmax(acc, Kokkos::fabs(w(i - sz)));
269 Kokkos::Max<double>(m));
270 Kokkos::single(Kokkos::PerTeam(tm), [&]() {
272 out(T.base + k) =
band0 ? Kokkos::fmax(m, 0.0) *
J.dth : m *
J.dth;
281template <
class Exec = SExec>
285 "vof::block::batch_freeze", T.nj,
286 [&](
const int k) { return static_cast<long>(T.job[k].e.y) * T.job[k].e.z; },
287 [=](
const int k,
const long r) {
288 const VofBlockJob& J = T.job[k];
289 const long i0 = r * J.e.x;
290 const double* c = J.c;
291 unsigned char* cc = J.cc;
293 for (int x = 0; x < J.e.x; ++x)
294 cc[i0 + x] = c[i0 + x] > 0.5 ? 1u : 0u;
298 Kokkos::parallel_for(
299 "vof::block::batch_freeze", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
303 const long i = t - T.off[k];
304 J.cc[i] =
J.c[i] > 0.5 ? 1u : 0u;
314template <
class Exec = SExec>
318 "vof::block::batch_worklist", T.nj, T.base,
319 [&](
const int k) { return static_cast<long>(T.job[k].n.y + 2) * (T.job[k].n.z + 2); },
320 [=](
const int k,
const long r,
int& x0,
int&
x1) {
321 const VofBlockJob& J = T.job[k];
322 const int ry = J.n.y + 2, g = J.g;
325 return L3(0, g - 1 + static_cast<int>(r % ry), g - 1 + static_cast<int>(r / ry), J.e);
327 [=](
const int k,
const long i) { return wyIsMixed(T.job[k].c[i], T.job[k].weps); }, list,
331 Kokkos::parallel_scan(
332 "vof::block::batch_worklist", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
336 const long r = t - T.off[k];
337 const int rx =
J.n.x + 2,
ry =
J.n.y + 2;
338 const int ix =
static_cast<int>(r %
rx);
339 const int iy =
static_cast<int>((r /
rx) %
ry);
340 const int iz =
static_cast<int>(r / (
static_cast<long>(
rx) *
ry));
342 const long i =
L3(g - 1 +
ix, g - 1 +
iy, g - 1 +
iz,
J.e);
349 if (t + 1 == T.off[k + 1])
350 end(T.base + k) =
upd + (mixed ? 1 : 0);
359template <
class Exec = SExec>
363 [=](
const int k,
const long t) {
364 const long q =
start(T.base + k) + t;
366 const long sy =
J.e.x, sz =
static_cast<long>(
J.e.x) *
J.e.y;
373 Kokkos::parallel_for(
374 "vof::block::batch_plic", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
377 const long s0 =
start(T.base + k);
378 const long q = s0 + (t - T.off[k]);
379 if (q >=
end(T.base + k))
382 const long sy =
J.e.x, sz =
static_cast<long>(
J.e.x) *
J.e.y;
392 return static_cast<long>(
J.n.x + (d == 0)) * (
J.n.y + (d == 1)) * (
J.n.z + (d == 2));
398 const long sd = d == 0 ? 1 : (d == 1 ?
static_cast<long>(e.x) :
static_cast<long>(e.x) * e.y);
400 if (
J.outside !=
nullptr) {
402 wyFaceFluxBc(u(p) *
J.dth, p,
sd, d, c, mx, my, mz, al,
VofRawMask{J.outside},
J.weps);
405 J.fl[p] =
wyFaceFlux(u(p) *
J.dth, p,
sd, d, c, mx, my, mz, al,
J.weps);
411template <
class Exec = SExec>
415 "vof::block::batch_flux", T.nj,
417 const VofBlockJob& J = T.job[k];
418 return static_cast<long>(J.n.y + (d == 1)) * (J.n.z + (d == 2));
420 [=](
const int k,
const long r) {
421 const VofBlockJob& J = T.job[k];
422 const int ay = J.n.y + (d == 1), g = J.g;
423 const int y = static_cast<int>(r % ay) + g - (d == 1);
424 const int z = static_cast<int>(r / ay) + g - (d == 2);
425 const long i0 = L3(0, y, z, J.e);
426 const int x0 = g - (d == 0), x1 = g + J.n.x;
428 for (int x = x0; x < x1; ++x)
429 vofBatchFluxCell(J, d, i0 + x);
433 Kokkos::parallel_for(
434 "vof::block::batch_flux", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
438 const long r = t - T.off[k];
439 const int ax =
J.n.x + (d == 0), ay =
J.n.y + (d == 1);
441 const int x =
static_cast<int>(r % ax) + g - (d == 0);
442 const int y =
static_cast<int>((r / ax) % ay) + g - (d == 1);
443 const int z =
static_cast<int>(r / (
static_cast<long>(ax) * ay)) + g - (d == 2);
454 Kokkos::parallel_for(
455 "vof::block::batch_bcvol", Kokkos::RangePolicy<SExec>(
SExec(), 0, 2 * T.nj),
457 const int k =
static_cast<int>(t / 2), s =
static_cast<int>(t % 2);
459 const int f = 2 * d + s;
460 if (
J.outside ==
nullptr || !
J.bcOwn[f])
462 const I3 e =
J.e, n =
J.n;
464 const int b = (d + 1) % 3, c2 = (d + 2) % 3;
465 const long st[3] = {1, e.x,
static_cast<long>(e.x) * e.y};
466 const long sd = st[d],
sb = st[b], sc = st[c2];
467 const int nn[3] = {n.x, n.y, n.z};
468 const int fa = (s == 0) ? (g - 1) : (g +
nn[d] - 1);
470 for (
int p1 = g;
p1 < g +
nn[c2]; ++
p1)
471 for (
int p0 = g; p0 < g +
nn[b]; ++p0)
472 acc +=
J.fl[
static_cast<long>(p0) *
sb +
static_cast<long>(
p1) * sc +
473 static_cast<long>(
fa) *
sd];
474 out(
static_cast<long>(
stride) * (T.base + k) +
slot0 + f) += (s == 0) ? acc : -acc;
481 const long sd = d == 0 ? 1 : (d == 1 ?
static_cast<long>(e.x) :
static_cast<long>(e.x) * e.y);
482 const double dth =
J.dth;
484 const unsigned char* cc =
J.cc;
487 const double aP = u(i) * dth,
aM = u(i -
sd) * dth;
488 const double dil = cc[i] ? (
aP -
aM) : 0.0;
489 c(i) = c(i) + (fl(i -
sd) - fl(i)) +
dil;
494template <
class Exec = SExec>
498 "vof::block::batch_update", T.nj,
499 [&](
const int k) { return static_cast<long>(T.job[k].n.y) * T.job[k].n.z; },
500 [=](
const int k,
const long r) {
501 const VofBlockJob& J = T.job[k];
504 L3(0, static_cast<int>(r % J.n.y) + g, static_cast<int>(r / J.n.y) + g, J.e);
506 for (int x = g; x < g + J.n.x; ++x)
507 vofBatchUpdateCell(J, d, i0 + x);
511 Kokkos::parallel_for(
512 "vof::block::batch_update", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
516 const long r = t - T.off[k];
517 const I3 e =
J.e, n =
J.n;
519 const int x =
static_cast<int>(r % n.x) + g;
520 const int y =
static_cast<int>((r / n.x) % n.y) + g;
521 const int z =
static_cast<int>(r / (
static_cast<long>(n.x) * n.y)) + g;
531template <
class Exec = SExec>
535 "vof::block::batch_ghost_zero", T.nj,
537 const VofBlockJob& J = T.job[k];
538 return static_cast<long>(J.e.z - J.n.z) * J.e.y +
539 static_cast<long>(J.n.z) * (J.e.y - J.n.y) + static_cast<long>(J.n.z) * J.n.y;
541 [=](
const int k,
const long r) {
542 const VofBlockJob& J = T.job[k];
543 const I3 e = J.e, n = J.n;
545 const long rZ = static_cast<long>(e.z - n.z) * e.y,
546 rY = static_cast<long>(n.z) * (e.y - n.y);
551 const int l = static_cast<int>(r / e.y);
552 y = static_cast<int>(r - static_cast<long>(l) * e.y);
553 z = l < g ? l : n.z + l;
555 const long t2 = r - rZ;
556 const int zi = static_cast<int>(t2 / (e.y - n.y));
557 const int l = static_cast<int>(t2 - static_cast<long>(zi) * (e.y - n.y));
558 y = l < g ? l : n.y + l;
561 const long i0 = L3(0, y, z, e);
563 for (int x = 0; x < e.x; ++x)
567 const long t3 = r -
rZ -
rY;
568 const int zi =
static_cast<int>(
t3 / n.y),
569 yi =
static_cast<int>(
t3 -
static_cast<long>(
zi) * n.y);
570 const long i0 =
L3(0, g +
yi, g +
zi, e);
571 for (
int x = 0; x < g; ++x)
573 for (
int x = g + n.x; x < e.x; ++x)
578 Kokkos::parallel_for(
579 "vof::block::batch_ghost_zero", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
581 const int k = vofJobOf(T.off, t);
582 const VofBlockJob&
J = T.job[k];
583 const long i = t - T.off[k];
584 const I3 e =
J.e, n =
J.n;
586 const int x =
static_cast<int>(i % e.x);
587 const int y =
static_cast<int>((i / e.x) % e.y);
588 const int z =
static_cast<int>(i / (
static_cast<long>(e.x) * e.y));
600template <
class Exec = SExec>
604 "vof::block::batch_periodic", T.nj,
606 const I3 e = T.job[k].e;
607 const int g = T.job[k].g;
608 return a == 0 ? static_cast<long>(e.y) * e.z
609 : (a == 1 ? 2L * g * e.z : static_cast<long>(e.y) * 2 * g);
611 [=](
const int k,
const long r) {
612 const VofBlockJob& J = T.job[k];
617 const int N = e.x - 2 * g;
618 const long base = r * e.x;
619 for (int gl = 0; gl < g; ++gl) {
620 f[base + gl] = f[base + gl + N];
621 f[base + g + N + gl] = f[base + g + gl];
627 const int N = e.y - 2 * g;
628 const int z =
static_cast<int>(r / (2 * g)), l =
static_cast<int>(r % (2 * g));
629 const int y = l < g ? l :
N + l, sy = l < g ? l +
N : l;
630 dst =
L3(0, y, z, e);
631 src =
L3(0, sy, z, e);
633 const int N = e.z - 2 * g;
634 const int l =
static_cast<int>(r / e.y), y =
static_cast<int>(r % e.y);
635 const int z = l < g ? l :
N + l, sz = l < g ? l +
N : l;
636 dst =
L3(0, y, z, e);
637 src =
L3(0, y, sz, e);
640 for (
int x = 0; x < e.x; ++x)
641 f[dst + x] = f[src + x];
645 Kokkos::parallel_for(
646 "vof::block::batch_periodic", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
648 const int k = vofJobOf(T.off, t);
649 const VofBlockJob&
J = T.job[k];
650 const long r = t - T.off[k];
653 const long st[3] = {1, e.x,
static_cast<long>(e.x) * e.y};
654 const int dims[3] = {e.x, e.y, e.z};
655 const int b = (a + 1) % 3, c = (a + 2) % 3;
656 const long sa = st[a], sb = st[b], sc = st[c];
657 const int N = dims[a] - 2 * g;
658 const int p0 =
static_cast<int>(r % dims[b]);
659 const int p1 =
static_cast<int>(r / dims[b]);
660 const VofRawField f{J.c};
661 const long base =
static_cast<long>(
p0) * sb +
static_cast<long>(p1) *
sc;
662 for (
int gl = 0; gl <
g; ++gl) {
663 f(base +
static_cast<long>(gl) * sa) =
f(base +
static_cast<long>(gl +
N) * sa);
664 f(base +
static_cast<long>(g +
N + gl) * sa) =
f(base +
static_cast<long>(g + gl) * sa);
671 int q1,
int q2,
bool p0,
bool p1,
bool p2) {
672 const I3 e =
J.e, o =
J.o;
674 const int gx = x - g + o.x,
gy = y - g + o.y,
gz = z - g + o.z;
675 const int cx = p0 ?
gx : (
gx < 0 ? 0 : (
gx >=
q0 ?
q0 - 1 :
gx));
678 if (cx !=
gx || cy !=
gy || cz !=
gz)
679 J.c[
L3(x, y, z, e)] =
J.c[
L3(cx - o.x + g, cy - o.y + g, cz - o.z + g, e)];
686template <
class Exec = SExec>
688 const bool p0 = px,
p1 = py,
p2 = pz;
689 const int q0 = gs.x,
q1 = gs.y,
q2 = gs.z;
692 "vof::block::batch_clamp", T.nj,
693 [&](
const int k) { return static_cast<long>(T.job[k].e.y) * T.job[k].e.z; },
694 [=](
const int k,
const long r) {
695 const VofBlockJob& J = T.job[k];
696 const I3 e = J.e, o = J.o;
698 const int y = static_cast<int>(r % e.y), z = static_cast<int>(r / e.y);
699 const int gy = y - g + o.y, gz = z - g + o.z, gx0 = o.x - g, gx1 = o.x - g + e.x;
700 if ((p1 || (gy >= 0 && gy < q1)) && (p2 || (gz >= 0 && gz < q2)) &&
701 (p0 || (gx0 >= 0 && gx1 <= q0)))
703 for (int x = 0; x < e.x; ++x)
704 vofBatchClampCell(J, x, y, z, q0, q1, q2, p0, p1, p2);
708 Kokkos::parallel_for(
709 "vof::block::batch_clamp", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
713 const long i = t - T.off[k];
715 const int x =
static_cast<int>(i % e.x);
716 const int y =
static_cast<int>((i / e.x) % e.y);
717 const int z =
static_cast<int>(i / (
static_cast<long>(e.x) * e.y));
732 for (
int oz = -2; oz <= 2; ++oz)
733 for (
int oy = -2; oy <= 2; ++oy)
734 for (
int ox = -2; ox <= 2; ++ox)
735 if (c(i + ox + oy * sy + oz * sz) >=
cfull)
747 for (
int oz = -2; oz <= 2 && !
attached; ++oz)
748 for (
int oy = -2; oy <= 2 && !
attached; ++oy)
749 for (
int ox = -2; ox <= 2 && !
attached; ++ox)
756 return ci != 0.0 && Kokkos::fabs(
ci) <= weps;
762template <
class Exec = SExec>
767 "vof::block::batch_debris_mark", T.nj, T.base,
768 [&](
const int k) { return static_cast<long>(T.job[k].n.y) * T.job[k].n.z; },
769 [=](
const int k,
const long r,
int& x0,
int&
x1) {
770 const VofBlockJob& J = T.job[k];
774 return L3(0, g + static_cast<int>(r % J.n.y), g + static_cast<int>(r / J.n.y), J.e);
776 [=](
const int k,
const long i) {
777 const VofBlockJob& J = T.job[k];
778 const long sy = J.e.x, sz = static_cast<long>(J.e.x) * J.e.y;
779 const VofRawField c{J.c};
787 Kokkos::parallel_scan(
788 "vof::block::batch_debris_mark", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
790 const int k = vofJobOf(T.off, t);
791 const VofBlockJob&
J = T.job[k];
792 const long r = t - T.off[k];
793 const int nx =
J.n.x, ny =
J.n.y, g =
J.g;
794 const int ix =
static_cast<int>(r % nx);
795 const int iy =
static_cast<int>((r / nx) % ny);
796 const int iz =
static_cast<int>(r / (
static_cast<long>(nx) * ny));
797 const long i =
L3(g +
ix, g +
iy, g +
iz,
J.e);
798 const long sy =
J.e.x, sz =
static_cast<long>(
J.e.x) *
J.e.y;
799 const VofRawField c{
J.c};
800 const bool hit = kind == 0 ? vofDebrisCell(c, i, sy, sz, ieps, cfull)
801 : kind == 1 ? vofResidueCell(c(i), weps)
802 : vofAttachedCell(c, i, sy, sz, ieps, cfull);
805 start(T.base + k) = upd;
808 if (t + 1 == T.off[k + 1])
809 end(T.base + k) = upd + (hit ? 1 : 0);
841 Kokkos::parallel_for(
842 "vof::block::batch_debris_sums", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.nj),
844 const int j = T.base +
static_cast<int>(q);
846 const long nD =
F.doDebris ?
eD0(j) -
sD0(j) : 0;
847 const long nR =
F.doResidue ?
eR0(j) -
sR0(j) : 0;
848 const bool removeD =
F.doDebris &&
F.remove &&
nD > 0;
849 const bool pending =
removeD || nR > 0;
851 double sD = 0.0,
sR = 0.0, W = 0.0,
VA = 0.0, dV = 0.0;
852 const long d0 =
F.doDebris ?
sD0(j) : 0;
853 for (
long t = 0; t <
nD; ++t)
854 sD += c(listD(d0 + t));
857 const long r0 =
F.doResidue ?
sR0(j) : 0, a0 =
sA0(j), nA =
eA0(j) -
sA0(j);
858 for (
long t = 0; t < nR; ++t)
859 sR += c(listR(r0 + t));
860 for (
long t = 0; t < nA; ++t) {
861 const double ca = c(listA(a0 + t));
862 W += ca * (1.0 - ca);
865 acted = (
VA <
F.vaMin || !(W > 0.0)) ? 0.0 : 1.0;
868 for (
long t = 0; t < nDr; ++t)
869 dV += c(listD(d0 + t));
870 for (
long t = 0; t < nR; ++t)
871 dV += c(listR(r0 + t));
879 out(
ob +
kDbND) =
static_cast<double>(
nD);
880 out(
ob +
kDbNR) =
static_cast<double>(nR);
891 const long nD =
static_cast<long>(out(
ob +
kDbND)), nR =
static_cast<long>(out(
ob +
kDbNR));
892 const bool removeD =
F.doDebris &&
F.remove &&
nD > 0;
894 return nDr + nR + nA;
904 const int j = T.base + k;
908 const long nD =
static_cast<long>(out(
ob +
kDbND)), nR =
static_cast<long>(out(
ob +
kDbNR));
909 const bool removeD =
F.doDebris &&
F.remove &&
nD > 0;
911 const long nZ = nDr + nR,
nTot =
nZ + nA;
916 c(listD(
sD0(j) + t)) = 0.0;
920 c(listR(
sR0(j) + t - nDr)) = 0.0;
924 const long ta = t -
nZ;
925 const long i = listA(
sA0(j) + ta);
926 const double ca = c(i);
927 const double d = dV * (ca * (1.0 - ca)) / W;
933 Kokkos::atomic_max(&
capf(j), 1);
935 ex(T.off[k] + ta) = e;
943template <
class Exec = SExec>
947 Kokkos::View<int*, SMem>
capf) {
950 "vof::block::batch_debris_write", T.nj,
952 const int j = T.base + k;
953 return vofDebrisActCount(F, sA0, eA0, out, static_cast<long>(stride) * j + slot0, j);
955 [=](
const int k,
const long t) {
956 vofDebrisActEntry(T, F, k, t, listD, listR, listA, sD0, sR0, sA0, eA0, out, stride, slot0,
961 Kokkos::parallel_for(
962 "vof::block::batch_debris_write", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
965 vofDebrisActEntry(T,
F, k,
tt - T.off[k], listD, listR, listA,
sD0,
sR0,
sA0,
eA0, out,
974 Kokkos::parallel_for(
975 "vof::block::batch_debris_lost", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.nj),
977 const int j = T.base +
static_cast<int>(q);
983 const long nA =
eA0(j) -
sA0(j), e0 = T.off[q];
985 for (
long t = 0; t < nA; ++t)
1003template <
class Exec = SExec>
1007 for (
int k = 0; k < T.nj; ++k)
1008 for (
int a = 0; a < 6; ++a)
1010 a < 3 ? Kokkos::reduction_identity<int>::min() : Kokkos::reduction_identity<int>::max();
1013 "vof::block::batch_bbox", T.nj,
1014 [&](
const int k) { return static_cast<long>(T.job[k].n.y) * T.job[k].n.z; },
1015 [=](
const int k,
const long r) {
1016 const VofBlockJob& J = T.job[k];
1017 const I3 e = J.e, n = J.n;
1019 const int py = static_cast<int>(r % n.y), pz = static_cast<int>(r / n.y);
1020 const long i0 = L3(g, py + g, pz + g, e);
1021 const VofRawField c{J.c};
1022 int lo = -1, hi = -1;
1023 for (
int px = 0; px < n.x; ++px)
1024 if (Kokkos::fabs(c(i0 + px)) > eps) {
1031 int* s =
bx + 6 * k;
1032 Kokkos::atomic_min(&s[0], lo);
1033 Kokkos::atomic_min(&s[1], py);
1034 Kokkos::atomic_min(&s[2], pz);
1035 Kokkos::atomic_max(&s[3], hi);
1036 Kokkos::atomic_max(&s[4], py);
1037 Kokkos::atomic_max(&s[5], pz);
1040 for (
int k = 0; k < T.nj; ++k) {
1041 const long ob =
static_cast<long>(
stride) * (T.base + k) +
slot0;
1042 for (
int a = 0; a < 6; ++a)
1043 out(
ob + a) =
static_cast<double>(box[6 * k + a]);
1047 using Team = Kokkos::TeamPolicy<SExec>;
1048 Kokkos::parallel_for(
1049 "vof::block::batch_bbox",
Team(
SExec(), T.nj, Kokkos::AUTO),
1051 const int k = tm.league_rank();
1052 const VofBlockJob&
J = T.job[k];
1053 const I3 e =
J.e, n =
J.n;
1055 const long region =
static_cast<long>(n.x) * n.y * n.z;
1056 const VofRawField c{
J.c};
1058 for (
int a = 0; a < 6; ++a) {
1060 auto body = [&](
const long q,
int& acc) {
1061 const int px =
static_cast<int>(q % n.x);
1062 const int py =
static_cast<int>((q / n.x) % n.y);
1063 const int pz =
static_cast<int>(q / (
static_cast<long>(n.x) * n.y));
1064 if (!(Kokkos::fabs(c(L3(px + g, py + g, pz + g, e))) > eps))
1066 const int p = (a % 3 == 0) ? px : (a % 3 == 1 ? py : pz);
1068 acc = p < acc ? p : acc;
1070 acc = p > acc ? p : acc;
1073 Kokkos::parallel_reduce(Kokkos::TeamThreadRange(tm, region), body, Kokkos::Min<int>(r));
1075 Kokkos::parallel_reduce(Kokkos::TeamThreadRange(tm, region), body, Kokkos::Max<int>(r));
1078 Kokkos::single(Kokkos::PerTeam(tm), [&]() {
1079 const long ob =
static_cast<long>(stride) * (
T.base + k) + slot0;
1080 for (
int a = 0;
a < 6; ++
a)
1081 out(ob + a) =
static_cast<double>(
v[
a]);
1093 double *c, *mx, *my, *mz, *
al, *kap, *br;
1098 double ieps, mtol, ptW, peps, dW,
cmin, km;
1114 for (
int k = 0; k < T.nj; ++k)
1115 T.off[k + 1] = T.off[k] + size(T.job[k]);
1117 T.off[k + 1] = T.off[T.nj];
1121 return static_cast<long>(
J.n.x) *
J.n.y *
J.n.z;
1130 const int gr = grown ?
kPvHalf : 0;
1131 const int rx =
J.n.x + 2 * gr,
ry =
J.n.y + 2 * gr;
1132 const int ix =
static_cast<int>(r %
rx);
1133 const int iy =
static_cast<int>((r /
rx) %
ry);
1134 const int iz =
static_cast<int>(r / (
static_cast<long>(
rx) *
ry));
1135 return L3(
J.g - gr +
ix,
J.g - gr +
iy,
J.g - gr +
iz,
J.e);
1140 const int gr = grown ?
kPvHalf : 0;
1141 return static_cast<long>(
J.n.y + 2 * gr) * (
J.n.z + 2 * gr);
1146 const int gr = grown ?
kPvHalf : 0;
1147 const int ry =
J.n.y + 2 * gr;
1149 x1 =
J.g +
J.n.x + gr;
1150 return L3(0,
J.g - gr +
static_cast<int>(r %
ry),
J.g - gr +
static_cast<int>(r /
ry),
J.e);
1155template <
class Exec = SExec>
1160 "vof::block::batch_curv_compact", T.nj, T.base,
1161 [&](
const int k) { return vofCurvRows(T.job[k], grown); },
1162 [=](
const int k,
const long r,
int& x0,
int&
x1) {
1163 return vofCurvRow(T.job[k], r, grown, x0, x1);
1165 [=](
const int k,
const long i) { return vofIsInterface(T.job[k].c[i], T.job[k].ieps); },
1169 Kokkos::parallel_scan(
1170 "vof::block::batch_curv_compact", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
1174 const long r = t - T.off[k];
1182 if (t + 1 == T.off[k + 1])
1192template <
class Exec = SExec>
1196 "vof::block::batch_curv_planes_zero", T.nj,
1197 [&](
const int k) { return vofCurvRows(T.job[k], true); },
1198 [=](
const int k,
const long r) {
1199 const VofCurvJob& J = T.job[k];
1201 const long i0 = vofCurvRow(J, r, true, x0, x1);
1202 PECLET_FLOW_OMP_SIMD
1203 for (int x = x0; x < x1; ++x) {
1208 J.slot[i0 + x] = -1;
1213 Kokkos::parallel_for(
1214 "vof::block::batch_curv_planes_zero", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
1216 const int k = vofJobOf(T.off, t);
1217 const VofCurvJob&
J = T.job[k];
1218 const long i = vofCurvCell(
J, t - T.off[k],
true);
1230 const long sy =
J.e.x, sz =
static_cast<long>(
J.e.x) *
J.e.y;
1231 const long i = list(q);
1235 J.slot[i] =
static_cast<int>(q);
1241template <
class Exec = SExec>
1249 Kokkos::parallel_for(
1250 "vof::block::batch_curv_planes", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
1253 const long q =
start(T.base + k) + (t - T.off[k]);
1254 if (q >=
end(T.base + k))
1262template <
class Exec = SExec>
1266 "vof::block::batch_curv_hf_reset", T.nj,
1267 [&](
const int k) { return vofCurvRows(T.job[k], false); },
1268 [=](
const int k,
const long r) {
1269 const VofCurvJob& J = T.job[k];
1271 const long i0 = vofCurvRow(J, r, false, x0, x1);
1272 PECLET_FLOW_OMP_SIMD
1273 for (int x = x0; x < x1; ++x) {
1274 J.kap[i0 + x] = 0.0;
1275 J.br[i0 + x] = static_cast<double>(kCurvNone);
1280 Kokkos::parallel_for(
1281 "vof::block::batch_curv_hf_reset", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
1283 const int k = vofJobOf(T.off, t);
1284 const VofCurvJob&
J = T.job[k];
1285 const long i = vofCurvCell(
J, t - T.off[k],
false);
1305 using Policy = Kokkos::TeamPolicy<SExec>;
1306 constexpr int side = 2 *
kPvHalf + 1,
nk = side * side * side;
1310 pol.set_scratch_size(0, Kokkos::PerTeam(VofPvTeamScratch::shmem(
nk)));
1311 Kokkos::parallel_for(
1312 "vof::block::batch_curv_pv_team",
pol,
KOKKOS_LAMBDA(
const typename Policy::member_type& tm) {
1316 for (
int k = 0; k < T.nj; ++k)
1318 for (
long g = tm.league_rank(); g <
cum[T.nj]; g += tm.league_size()) {
1320 while (g >=
cum[k + 1])
1323 const long i = list(
start(T.base + k) + (g -
cum[k]));
1324 const long sy =
J.e.x, sz =
static_cast<long>(
J.e.x) *
J.e.y;
1339 const long i = list(q);
1340 const long sy =
J.e.x, sz =
static_cast<long>(
J.e.x) *
J.e.y;
1341 const VofRawField c{
J.c}, mx{
J.mx}, my{
J.my}, mz{
J.mz}, al{
J.al}, kap{
J.kap}, br{
J.br};
1342 const bool all =
pass == 4;
1343 if (
pass == 0 || all) {
1344 curvHeightCell(i, c, mx, my, mz, al, kap, br, 1L, sy, sz,
J.mtol,
J.ptW,
J.ieps,
J.forceFb,
1345 J.oneDir,
J.useFit,
J.gm,
J.peps);
1349 if (
pass == 1 || all) {
1350 curvFallbackCell(i,
VofPvCached{
J.slot, T.cache}, kap, br, sy, sz,
kPvHalf,
J.dW,
J.cmin,
J.gm);
1354 long*
ct = &cnt(8 * (T.base + k));
1355 if (
pass == 2 || all) {
1356 const double km =
J.km;
1360 if (km > 0.0 &&
csfKappaDefined(br(i)) && !(Kokkos::fabs(kap(i)) <= km)) {
1361 kap(i) = (kap(i) == kap(i)) ? Kokkos::copysign(km, kap(i)) : km;
1362 Kokkos::atomic_add(&
ct[7], 1L);
1367 const int b =
static_cast<int>(br(i));
1370 Kokkos::atomic_add(&
ct[0], 1L);
1372 Kokkos::atomic_add(&
ct[1], 1L);
1374 Kokkos::atomic_add(&
ct[2], 1L);
1376 Kokkos::atomic_add(&
ct[3], 1L);
1378 Kokkos::atomic_add(&
ct[4], 1L);
1380 Kokkos::atomic_add(&
ct[5], 1L);
1382 Kokkos::atomic_add(&
ct[6], 1L);
1390template <
class Exec = SExec>
1395 [=](
const int k,
const long t) {
1400 if constexpr (!Kokkos::SpaceAccessibility<Kokkos::HostSpace, SField::memory_space>::accessible) {
1406 Kokkos::parallel_for(
1407 "vof::block::batch_curv_list", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
1410 const long q =
start(T.base + k) + (t - T.off[k]);
1411 if (q >=
end(T.base + k))
1423template <
class Exec = SExec>
1440 double w1,
double w2) {
1441 const long sy =
J.e.x, sz =
static_cast<long>(
J.e.x) *
J.e.y;
1443 for (
int cc = 0; cc < 3; ++cc) {
1444 const double wc = cc == 0 ? w0 : (cc == 1 ?
w1 :
w2);
1445 const long strd = (cc == 0) ? 1 : (cc == 1 ? sy : sz);
1450 vof::csfFaceCurvature(kp(i -
strd), kb(i -
strd), kp(i), kb(i), kf);
1451 f = vof::csfFaceForce(sig, kf,
dC,
wc);
1460template <
class Exec = SExec>
1464 "vof::block::batch_csf_force", T.nj,
1465 [&](
const int k) { return vofCurvRows(T.job[k], false); },
1466 [=](
const int k,
const long r) {
1467 const VofCurvJob& J = T.job[k];
1469 const long i0 = vofCurvRow(J, r, false, x0, x1);
1470 PECLET_FLOW_OMP_SIMD
1471 for (int x = x0; x < x1; ++x)
1472 vofCsfForceCell(J, i0 + x, sig, w0, w1, w2);
1476 Kokkos::parallel_for(
1477 "vof::block::batch_csf_force", Kokkos::RangePolicy<SExec>(
SExec(), 0, T.off[T.nj]),
1491 for (
int i = 0; i <
N; ++i)
1495 for (
int i = 0; i <
N; ++i)
1505struct reduction_identity<
peclet::flow::vof::VofSumN<N>> {
1531 double dt,
SField out,
long off) {
1532 using Team = Kokkos::TeamPolicy<SExec>;
1533 Kokkos::parallel_for(
1534 "vof::block::batch_stats",
Team(
SExec(), T.nj, Kokkos::AUTO),
1536 const int k = tm.league_rank();
1538 const I3 e =
J.e, n =
J.n, o =
J.o;
1540 const long sy = e.x, sz =
static_cast<long>(e.x) * e.y;
1541 const long region =
static_cast<long>(n.x) * n.y * n.z;
1543 double*
q0 = out.data() + off +
static_cast<long>(
kVofStats) * (T.base + k);
1545 Kokkos::parallel_reduce(
1546 Kokkos::TeamThreadRange(tm,
region),
1548 const int x =
static_cast<int>(r % n.x) + g;
1549 const int y =
static_cast<int>((r / n.x) % n.y) + g;
1550 const int z =
static_cast<int>(r / (
static_cast<long>(n.x) * n.y)) + g;
1551 const double q = c(
L3(x, y, z, e));
1553 a.v[1] += q * (x - g + o.x + 0.5) *
hh;
1554 a.v[2] += q * (y - g + o.y + 0.5) *
hh;
1555 a.v[3] += q * (z - g + o.z + 0.5) *
hh;
1557 Kokkos::Sum<VofSumN<4>>(m1));
1558 const double v = m1.v[0];
1560 Kokkos::single(Kokkos::PerTeam(tm), [&]() {
1567 const double cx = m1.v[1] / v, cy = m1.v[2] / v, cz = m1.v[3] / v;
1569 Kokkos::parallel_reduce(
1570 Kokkos::TeamThreadRange(tm,
region),
1572 const int x =
static_cast<int>(r % n.x) + g;
1573 const int y =
static_cast<int>((r / n.x) % n.y) + g;
1574 const int z =
static_cast<int>(r / (
static_cast<long>(n.x) * n.y)) + g;
1575 const long i =
L3(x, y, z, e);
1576 const double q = c(i);
1577 const double px = (x - g + o.x + 0.5) *
hh - cx, py = (y - g + o.y + 0.5) *
hh - cy,
1578 pz = (z - g + o.z + 0.5) *
hh - cz;
1579 a.v[0] += q * px * px;
1580 a.v[1] += q * py * py;
1581 a.v[2] += q * pz * pz;
1582 a.v[3] += q * px * py;
1583 a.v[4] += q * px * pz;
1584 a.v[5] += q * py * pz;
1585 if (!(q >
aeps) || !(q < 1.0 -
aeps))
1588 for (
int dz = -1; dz <= 1; ++dz)
1589 for (
int dy = -1; dy <= 1; ++dy)
1590 for (
int dx = -1; dx <= 1; ++dx)
1591 st[vof::plicSt(dx + 1, dy + 1, dz + 1)] = c(i + dx + dy * sy + dz * sz);
1593 vof::mycNormal(st, m);
1594 const double al = vof::plicAlpha(m[0], m[1], m[2], q);
1595 double pv[8][3],
ctr[3],
ar = 0.0;
1596 const int nv = vof::plicPolygon(m[0], m[1], m[2], al, pv);
1597 vof::polygonAreaCentroid(pv,
nv,
ctr,
ar);
1600 Kokkos::Sum<VofSumN<7>>(m2));
1601 Kokkos::single(Kokkos::PerTeam(tm), [&]() {
1602 const double nc[3] = {cx, cy, cz};
1604 for (
int d = 0; d < 3; ++d) {
1606 q0[4 + d] = (P.
valid[k] && dt > 0.0) ? (nc[d] - P.
c[k][d]) / dt : 0.0;
1609 const double iv = 1.0 / v;
1610 for (
int d = 0; d < 6; ++d)
1611 q0[8 + d] = m2.v[d] *
iv;
flow — VoF rung V1: Weymouth & Yue (2010) directionally-split, exactly volume-conserving geometric ad...
#define PECLET_FLOW_OMP_SIMD
flow — VoF rung V3 (WO-O): the view-level driver for the curvature cascade.
flow — portable (Kokkos) MAC stencil operators: Red-Black Gauss-Seidel smoothers + divergence.
int vofJobOf(const long *off, long t)
Job of flat index t (off[0] <= t < off[nj]): a walk over at most 16 offsets.
constexpr bool kVofHostExec
The host branches select on this (§14.2).
long vofJobGrown1(const VofBlockJob &J)
The inner region grown by one cell per side: WyAdvector::reconstructImpl's range.
void vofCurvCompact(const VofCurvTable &T, bool grown, LField list, LField start, LField end)
VofCurvature::compact: the interfacial cells of the grown (grown) or inner region,...
bool vofDebrisCell(const SF &c, long i, long sy, long sz, double ieps, double cfull)
The debris predicate of doc/vof_overlap_design.md §11 on cell i: interfacial, and NO cell of the mark...
void vofBatchFlux(const VofBlockTable &T, int d)
WyAdvector::computeFluxesImpl (uncut): one flux per d-face, wyFaceFlux (or, for a job carrying the WO...
Kokkos::View< long *, SMem > LField
void vofCurvListPasses(const VofCurvTable &T, bool anyClip, LField list, LField start, LField end, LField cnt)
The whole cascade list stage of a chunk: tiers 1-2, tier 3, the clip (only if some job clips),...
void vofBatchCfl(const VofBlockTable &T, SField out)
One team per job: WyAdvector::maxCourant or maxCourantInterface (per the job's interfaceCfl),...
bool csfKappaDefined(double branch)
Is the curvature of a cell carrying branch code branch usable?
void vofCsfForceCell(const VofCurvJob &J, long i, double sig, double w0, double w1, double w2)
The three CSF face-force components at the low faces of inner cell i of job J (the per-cell body of v...
long vofSetOffsets(VofBlockTable &T, F size)
Fill T.off from a per-job range size.
constexpr int kVofWarp
The team size of a device tier-3 launch: one warp / wavefront.
bool vofIsInterface(double c, double eps)
wyIsMixed with a wisp threshold: the cell carries an interface only while eps < C < 1 - eps.
void vofBatchClamp(const VofBlockTable &T, I3 gs, bool px, bool py, bool pz)
Pass 3 (colour_field.hpp::clampFill, skip = 0): the part of each extended block outside a NON-periodi...
void vofBatchPeriodic(const VofBlockTable &T, int a)
Pass 2 on axis a (colour_field.hpp::periodicFill, one axis): only the jobs whose block spans the peri...
double wyFaceFluxBc(double a, long p, long sd, int dir, const SF &c, const SF &mx, const SF &my, const SF &mz, const SF &alpha, const MF &outside, double eps=0.0)
WO-R sibling of wyFaceFlux for a face whose DONOR lies outside the global domain.
void vofBatchGhostZero(const VofBlockTable &T)
Pass 1: every ghost cell of every job -> 0.
constexpr int kVofStats
Doubles per job in the statistics packet: volume, centroid[3], velocity[3], area, moment[6].
constexpr int kVofBlockBatch
Jobs per launch; a container with more master blocks runs each stage in chunks.
void vofCurvFallbackTeams(const VofCurvTable &T, LField list, LField start, LField end)
VofDebrisSlot
The per-job slots of the debris packet (out(stride * (base + k) + slot)).
@ kDbActed
1 when the return ran (pending and VA >= kDebrisMinAttached and W > 0)
@ kDbSumR
sum_R C in list order (signed residue)
@ kDbPending
1 when there was something to remove (removeD or nR > 0)
@ kDbSumD
sum_D C in list order (the removed / census debris volume)
@ kDbDV
the volume to return (D if removing, then R); replaced by lost once acted
void vofBatchDebrisSums(const VofBlockTable &T, VofDebrisFlags F, LField listD, LField listR, LField listA, LField sD0, LField eD0, LField sR0, LField eR0, LField sA0, LField eA0, SField out, int stride, int slot0)
Step 2 of the pass: one thread per job, every sum in list order (the per-block kernel's single thread...
void wyReconstructCell(const SF &c, long i, long sy, long sz, SF mx, SF my, SF mz, SF alpha)
PLIC reconstruction of one cell: MYC normal from the 3^3 colour stencil + the analytic plane offset.
long vofJobFaces(const VofBlockJob &J, int d)
A sweep's face range of one job: the inner region with one extra layer on the low side of d.
void vofCurvHfReset(const VofCurvTable &T)
heightPass (worklist mode), part 1: every inner cell to kappa = 0, branch = kCurvNone.
long vofJobInner(const VofBlockJob &J)
void vofCurvPlanesList(const VofCurvTable &T, LField list, LField start, LField end)
Part 2: wyReconstructCell over the grown interfacial list (upper bound: the grown region),...
void vofHostRowScan(const char *name, int nj, int base, Rows rows, RowOf rowOf, Hit hit, LField list, LField start, LField end)
H-4(d): a host compaction scan over ROWS.
void vofBatchMark(const VofBlockTable &T, int kind, double ieps, double cfull, double weps, LField list, LField start, LField end)
One mark scan over the concatenated inner regions (T.off = vofJobInner), in each block's inner-box in...
void vofBatchFluxCell(const VofBlockJob &J, int d, long p)
The flux of d-face p of job J (the per-cell body of vofBatchFlux, both launch forms).
void vofCsfForceBatch(const VofCurvTable &T, double sig, double w0, double w1, double w2)
VofBlockSet::buildCsfForce for every job, the three components per cell: the V4 balanced-force CSF at...
void vofBatchBox(const VofBlockTable &T, double eps, SField out, int stride, int slot0)
One team per job: the tight box of |C| > eps over the inner region, in the block's LOCAL inner frame ...
void vofCurvListEntry(const VofCurvTable &T, int pass, int k, long q, LField list, LField cnt)
Entry q (an absolute list position) of job k of a cascade list pass (see below): the body shared by t...
bool wyColourJump(double a, double b, double eps)
The interface-BAND jump test of maxCourantInterface: two neighbouring cells carry a DIFFERENT colour.
void vofBatchPlic(const VofBlockTable &T, LField list, LField start, LField end)
wyReconstructCell over each job's compacted list: launched over the upper bound (the job's region),...
bool wyIsMixed(double c)
The mixed-cell predicate.
void vofCurvPlanesZero(const VofCurvTable &T)
reconstructPlanes (worklist mode), part 1: zero the four plane fields and clear the slot map (design ...
void vofBatchDebrisLost(const VofBlockTable &T, LField sA0, LField eA0, SField out, int stride, int slot0, SField ex, Kokkos::View< int *, SMem > capf)
lost: the capped excess of an acted job summed in list order on one thread (only where a cap fired,...
void vofBatchBcLedger(const VofBlockTable &T, int d, SField out, int stride, int slot0)
The WO-R boundary ledger (WyAdvector::accumulateBcFaceVolume) of the jobs carrying the mask: one thre...
long vofJobLen(const VofBlockJob &J)
long vofCurvCell(const VofCurvJob &J, long r, bool grown)
Cell r of job J's grown (grown) or inner region, in the region's x-fastest order.
void curvFallbackCell(long i, const Acc &acc, SF kap, SF br, long sy, long sz, int gr, double dW, double cmin, VofMetric g)
Tier 3 for one target, one thread (host): the frame from the target's entry (pvFrameMoments: the phys...
long vofCurvRow(const VofCurvJob &J, long r, bool grown, int &x0, int &x1)
The first cell of row r of job J's grown or inner region, and the region's x range.
auto vofListCount(const Tab &T, LField start, LField end)
The [start, end) count of job k of a list launch.
bool vofAttachedCell(const SF &c, long i, long sy, long sz, double ieps, double cfull)
The ATTACHED predicate (§5.3 step 2): interfacial with a cell at or above cfull within two.
long vofCurvRows(const VofCurvJob &J, bool grown)
Rows of job J's grown (grown) or inner region, for the host row forms (H-4b).
void curvHeightCell(long i, SF c, SF mx, SF my, SF mz, SF al, SF kap, SF br, long s0, long s1, long s2, double mtol, double ptW, double ieps, bool forceFb, bool oneDir, bool useFit, VofMetric g, double peps)
WO-V9 — the per-cell bodies of the two cascade tiers, lifted VERBATIM out of the kernels they used to...
void vofHostRowFor(const char *name, int nj, Rows rows, F row)
H-4(b): a host region kernel over ROWS – rows(k) x-runs for job k, row(k, r) handling job k's local r...
PECLET_VOF_DEVICE_NOINLINE void curvMomentsBuild(double mx, double my, double mz, double alpha, const VofMetric &g, PvMoments &P)
pvMomentsBuild, the one call every planes pass and the dense accessor make (out of line on a device,...
void vofBatchClampCell(const VofBlockJob &J, int x, int y, int z, int q0, int q1, int q2, bool p0, bool p1, bool p2)
The clamp of extended cell (x, y, z) of job J (the per-cell body of vofBatchClamp).
void vofBatchWorklist(const VofBlockTable &T, LField list, LField start, LField end)
WyAdvector::reconstructImpl's worklist scan, over the concatenated grown-by-one regions (T....
long vofCurvInner(const VofCurvJob &J)
double wyFaceFlux(double a, long p, long sd, int dir, const SF &c, const SF &mx, const SF &my, const SF &mz, const SF &alpha, double eps=0.0)
Signed Eulerian donor-cell flux through the dir-face between cell p and cell p + sd,...
PECLET_VOF_DEVICE_NOINLINE void curvFallbackTeam(const Member &tm, const VofPvTeamScratch &sc, long i, const Acc &acc, SF kap, SF br, long sy, long sz, int gr, double dW, double cmin, VofMetric g)
curvFallbackCell for one target on a whole team (design G §5.4; the team shape of C3,...
void vofBatchStats(const VofBlockTable &T, const VofStatsPrev &P, double hh, double aeps, double dt, SField out, long off)
VofBlockSet::measure for every job in one launch, one team per job: the first moments,...
void vofCurvPlaneEntry(const VofCurvTable &T, int k, long q, LField list)
Entry q (an absolute grown-list position) of job k of the planes pass (below).
void vofBatchFreeze(const VofBlockTable &T)
WyAdvector::freezeDilationFlag over every job's extended block.
void vofBatchUpdate(const VofBlockTable &T, int d)
WyAdvector::applySweepImpl (uncut) over the inner regions (T.off = vofJobInner); the expression verba...
bool vofResidueCell(double ci, double weps)
The residue predicate (§13): 0 < |C| <= wispEps.
void vofDebrisActEntry(const VofBlockTable &T, const VofDebrisFlags &F, int k, long t, LField listD, LField listR, LField listA, LField sD0, LField sR0, LField sA0, LField eA0, SField out, int stride, int slot0, SField ex, Kokkos::View< int *, SMem > capf)
Act entry t of job k (the per-block write kernel's expressions verbatim); t past the job's count,...
void vofCurvListPass(const VofCurvTable &T, int pass, LField list, LField start, LField end, LField cnt)
The per-list-cell passes of the cascade over the inner interfacial list (upper bound: the inner regio...
void vofHostListFor(const char *name, int nj, Cnt cnt, F body)
H-4(a): a host list kernel over the EXACT entry counts, cnt(k) (read directly: the count Views are Ho...
long vofDebrisActCount(const VofDebrisFlags &F, LField sA0, LField eA0, SField out, long ob, int j)
The number of act entries of job j (its D removed, then R, then A), 0 when it did not act: the per-bl...
constexpr int kVofTier3MaxTeams
Tier 3 of the batched cascade on a DEVICE (C3, doc/vof_step_performance_design.md §4....
long vofCurvGrown(const VofCurvJob &J)
The inner region grown by kPvHalf: every cell VofCurvature::reconstructPlanes writes.
void vofBatchUpdateCell(const VofBlockJob &J, int d, long i)
The sweep update of inner cell i of job J (the per-cell body of vofBatchUpdate).
void vofBatchDebrisWrite(const VofBlockTable &T, VofDebrisFlags F, LField listD, LField listR, LField listA, LField sD0, LField sR0, LField sA0, LField eA0, SField out, int stride, int slot0, SField ex, Kokkos::View< int *, SMem > capf)
Step 4, the act: removed cells -> 0, attached C += dV C(1-C)/W capped at 1 (the per-block write kerne...
long L3(int x, int y, int z, I3 e)
Kokkos::DefaultExecutionSpace Exec
Kokkos::DefaultExecutionSpace SExec
Kokkos::View< double *, SMem > SField
static peclet::flow::vof::VofSumN< N > sum()
One master block's share of a batched container launch.
unsigned char * cc
the frozen dilation flag
double dth
dt / h of this block's advector
double weps
the advector's wisp tolerance
double * u[3]
face velocities uf, vf, wf
bool interfaceCfl
interfaceLocalCfl: maxCourantInterface, else maxCourant
bool span[3]
the block spans this globally periodic axis (wrap in-block)
I3 o
extended extent, inner counts, global index of inner (0,0,0)
const unsigned char * outside
the WO-R out-of-domain mask; null when there is none
unsigned char bcOwn[6]
WO-R: the global domain faces this block owns.
The job table of one launch, by value.
long off[kVofBlockBatch+1]
VofBlockJob job[kVofBlockBatch]
The exact offset table of a host list launch: job k's entries are [o[k], o[k + 1]).
One master block's cascade (VofCurvature, worklist mode) for the batched launches: its planes,...
int * slot
the block's slot map (design G §5.2): absolute cListG_ positions
PvMoments * cache
the chunk's moment cache, indexed like the grown list (design G §5.2)
Flags of the pass, uniform over the blocks.
The cache-backed accessor: slot[j] >= 0 iff cell j of the grown region is interfacial,...
A raw-pointer field accessor with the View<double*> call syntax, for kernels that walk SEVERAL blocks...
Read-only raw accessor of an unsigned-char field (the WO-R out-of-domain mask).
unsigned char operator()(long i) const
The row offsets of a host region launch: job k's rows are [off[k], off[k + 1]).
long off[kVofBlockBatch+1]
What measure() reads besides the colour: each job's previous centroid and whether it is valid (the ho...
double c[kVofBlockBatch][3]
unsigned char valid[kVofBlockBatch]
N double sums in one team reduction (Kokkos::Sum<VofSumN<N>>).
VofSumN & operator+=(const VofSumN &o)
static constexpr double F