21#ifndef PECLET_FLOW_SCALAR_CUTCELL_OPERATOR_HPP
22#define PECLET_FLOW_SCALAR_CUTCELL_OPERATOR_HPP
25#include <Kokkos_Core.hpp>
33#include "peclet/core/scheme/probe_flux.hpp"
65 bool hasProfile[6] = {
false,
false,
false,
false,
false,
false};
73 Kokkos::View<double*, CCMem>
cw,
rw;
74 Kokkos::View<double*, CCMem>
gFace[6];
75 bool dirFace[6] = {
false,
false,
false,
false,
false,
false};
85 double gPhys[3] = {0.0, 0.0, 0.0};
86 double gInt[3] = {0.0, 0.0, 0.0};
87 double ubar[3] = {0.0, 0.0, 0.0};
90 Kokkos::View<double*, CCMem>
ks;
91 Kokkos::View<double*, Kokkos::HostSpace>
pk;
107 std::shared_ptr<ScalarMG>
mg;
122 bool openFace[6] = {
false,
false,
false,
false,
false,
false};
123 bool openInflow[6] = {
false,
false,
false,
false,
false,
false};
144 Kokkos::View<double*, CCMem>
sS;
145 Kokkos::View<int* [8], Kokkos::LayoutLeft, CCMem>
offS;
146 Kokkos::View<double* [8], Kokkos::LayoutLeft, CCMem>
wS;
147 Kokkos::View<std::uint8_t*, CCMem>
rungS;
148 Kokkos::View<std::uint8_t*, CCMem>
conjF;
158 Kokkos::View<double*, CCMem>
cc;
169 return a == 0 ? sax(i) : (a == 1 ? say(i) : saz(i));
176 "peclet::flow::sco_zero_nonunknown",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
178 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
188 CCConst saz,
double lam,
double idt,
const double w[3],
C3 e,
int g) {
189 const double lx = lam * w[0],
ly = lam * w[1],
lz = lam * w[2];
191 "peclet::flow::sco_bands",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
193 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
194 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
195 if (!(unk(i) > 0.5)) {
197 AW(i) = AE(i) = AS(i) = AN(i) = AB(i) = AT(i) = 0.0;
200 const double tw = unk(i -
sx) > 0.5 ?
lx * sax(i) : 0.0;
201 const double te = unk(i +
sx) > 0.5 ?
lx * sax(i +
sx) : 0.0;
202 const double ts = unk(i - sy) > 0.5 ?
ly * say(i) : 0.0;
203 const double tn = unk(i + sy) > 0.5 ?
ly * say(i + sy) : 0.0;
204 const double tb = unk(i - sz) > 0.5 ?
lz * saz(i) : 0.0;
205 const double tt = unk(i + sz) > 0.5 ?
lz * saz(i + sz) : 0.0;
212 AC(i) = kappa(i) * idt + ((
tw +
te) + (ts +
tn)) + (tb +
tt);
221 "peclet::flow::sco_rhs",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
223 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
224 if (!(unk(i) > 0.5)) {
229 b(i) = kappa(i) * (idt * cOld(i) + S);
236 t1 = (a == 0) ? 1 : 0;
237 t2 = (a == 2) ? 1 : 2;
244 Kokkos::View<const double*, CCMem>
gv,
double lamW,
int a,
int side,
248 const int ext[3] = {e.x, e.y, e.z};
249 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
250 const int n1 = ext[
t1] - 2 * g,
n2 = ext[
t2] - 2 * g;
251 const long sa = st[a], s1 = st[
t1], s2 = st[
t2];
252 const int aInner = side == 0 ? g : ext[a] - g - 1;
254 Kokkos::parallel_for(
257 const long i = (
long)
aInner *
sa + (
long)(j1 + g) * s1 + (
long)(
j2 + g) * s2;
260 const double abf = side == 0 ?
saA(i) :
saA(i +
sa);
261 const double t = 2.0 *
lamW *
abf;
263 b(i) += t *
gv((
long)j1 + (
long)
j2 *
n1);
271 Kokkos::View<const double*, CCMem>
gv,
double lamW,
double vol,
272 int a,
int side,
C3 e,
int g) {
275 const int ext[3] = {e.x, e.y, e.z};
276 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
277 const int n1 = ext[
t1] - 2 * g,
n2 = ext[
t2] - 2 * g;
278 const long sa = st[a], s1 = st[
t1], s2 = st[
t2];
279 const int aInner = side == 0 ? g : ext[a] - g - 1;
280 Kokkos::View<double*, CCMem> q(
"peclet::flow::sco_face_influx", (
long)
n1 *
n2);
282 Kokkos::parallel_for(
285 const long i = (
long)
aInner *
sa + (
long)(j1 + g) * s1 + (
long)(
j2 + g) * s2;
286 const long k = (
long)j1 + (
long)
j2 *
n1;
287 if (!(unk(i) > 0.5)) {
291 const double abf = side == 0 ?
saA(i) :
saA(i +
sa);
292 q(k) = vol * (2.0 *
lamW *
abf) * (
gv(k) - c(i));
295 auto h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), q);
297 for (
long k = 0; k < (
long)h.extent(0); ++k)
311 const double w[3],
C3 e,
int g) {
312 const double lx = lam * w[0],
ly = lam * w[1],
lz = lam * w[2];
314 "peclet::flow::sco_residual_flux",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
316 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
317 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
318 if (!(unk(i) > 0.5)) {
322 const double ci = c(i);
323 const double tw = unk(i -
sx) > 0.5 ?
lx * sax(i) : 0.0;
324 const double te = unk(i +
sx) > 0.5 ?
lx * sax(i +
sx) : 0.0;
325 const double ts = unk(i - sy) > 0.5 ?
ly * say(i) : 0.0;
326 const double tn = unk(i + sy) > 0.5 ?
ly * say(i + sy) : 0.0;
327 const double tb = unk(i - sz) > 0.5 ?
lz * saz(i) : 0.0;
328 const double tt = unk(i + sz) > 0.5 ?
lz * saz(i + sz) : 0.0;
329 const double flux = ((
tw * (
ci - c(i -
sx)) +
te * (
ci - c(i +
sx))) +
330 (ts * (
ci - c(i - sy)) +
tn * (
ci - c(i + sy)))) +
331 (tb * (
ci - c(i - sz)) +
tt * (
ci - c(i + sz)));
332 r(i) = b(i) - kappa(i) * idt *
ci - flux;
339 int a,
int side,
C3 e,
int g) {
342 const int ext[3] = {e.x, e.y, e.z};
343 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
344 const int n1 = ext[
t1] - 2 * g,
n2 = ext[
t2] - 2 * g;
345 const long sa = st[a], s1 = st[
t1], s2 = st[
t2];
346 const int aInner = side == 0 ? g : ext[a] - g - 1;
348 Kokkos::parallel_for(
351 const long i = (
long)
aInner *
sa + (
long)(j1 + g) * s1 + (
long)(
j2 + g) * s2;
354 const double abf = side == 0 ?
saA(i) :
saA(i +
sa);
355 r(i) -= 2.0 *
lamW *
abf * c(i);
363 Kokkos::View<int*, CCMem>
type;
373 auto fcell =
fo.cell;
381 const int nb = wt.nb;
382 const double kInf = std::numeric_limits<double>::infinity();
384 Kokkos::parallel_for(
385 "peclet::flow::sco_facet_coeffs", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.n),
387 if (!(unk(fcell(f)) > 0.5)) {
395 const int t = type(
bd);
396 const double al =
falpha(f);
407 const double G = peclet::core::scheme::wallConductance(sF(f), lam, t == 1 ?
kInf :
kk(
bd));
409 rw(f) = al *
G *
gg(
bd);
420 Kokkos::View<const double*, CCMem> cw,
bool subtract =
false) {
421 auto cutCell =
fo.cutCell;
422 auto cfs =
fo.cellFacetStart;
426 Kokkos::parallel_for(
427 "peclet::flow::sco_overlay_apply", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.nCut),
429 const long i = cutCell(c);
431 for (
int f =
cfs(c); f <
cfs(c + 1); ++f) {
433 for (
int k = 0; k < 8; ++k)
434 up += wF(f, k) * x(i + (
long)offF(f, k));
446 Kokkos::View<const double*, CCMem> rw) {
447 auto cutCell =
fo.cutCell;
448 auto cfs =
fo.cellFacetStart;
450 Kokkos::parallel_for(
451 "peclet::flow::sco_overlay_rhs", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.nCut),
454 for (
int f =
cfs(c); f <
cfs(c + 1); ++f)
456 b(cutCell(c)) += acc;
464 Kokkos::View<const double*, CCMem> cw) {
465 Kokkos::deep_copy(
CCExec(), SAC,
AC);
466 auto cutCell =
fo.cutCell;
467 auto cfs =
fo.cellFacetStart;
469 Kokkos::parallel_for(
470 "peclet::flow::sco_surrogate_diag", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.nCut),
473 for (
int f =
cfs(c); f <
cfs(c + 1); ++f)
475 SAC(cutCell(c)) += acc;
484 Kokkos::View<const double*, CCMem> rw) {
485 auto fcell =
fo.cell;
489 Kokkos::parallel_for(
490 "peclet::flow::sco_facet_flux", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.n),
492 const long i = fcell(f);
494 for (
int k = 0; k < 8; ++k)
495 u += wF(f, k) * x(i + (
long)offF(f, k));
497 qin(f) = rw(f) - cw(f) * u;
512 "peclet::flow::sco_dot",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
514 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
526template <
class R1,
class R2>
529 Kokkos::parallel_reduce(
532 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
536 std::forward<R1>(r1), std::forward<R2>(r2));
539 double s1 = 0.0, s2 = 0.0;
550 "peclet::flow::sco_maxabs",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
552 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
553 const double v = Kokkos::fabs(a(i));
568 double s1 = 0.0, s2 = 0.0;
569 Kokkos::parallel_reduce(
570 "peclet::flow::sco_sum_unknown",
573 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
576 p2 += Kokkos::fabs(a(i));
587 "peclet::flow::sco_add_unknown",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
589 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
599 double s1 = 0.0, s2 = 0.0;
600 Kokkos::parallel_reduce(
601 "peclet::flow::sco_kappa_moments",
604 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
606 p1 += kappa(i) * c(i);
617 bool useField,
double srcFactor,
C3 e,
int g) {
620 "peclet::flow::sco_source_sum",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
622 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
643 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
644 const long s = st[a];
646 "peclet::flow::sco_face_flux",
C3{0, 0, 0}, e,
KOKKOS_LAMBDA(
int x,
int y,
int z) {
647 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
648 const int xa = a == 0 ? x : (a == 1 ? y : z);
649 if (
xa < 1 || !(unk(i) > 0.5) || !(unk(i - s) > 0.5)) {
653 phi(i) = open(i) * vel(i);
665 Kokkos::parallel_reduce(
666 "peclet::flow::sco_flux_counts",
669 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
672 else if (open(i) * vel(i) != 0.0)
684 "peclet::flow::sco_max_flux",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
686 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
687 const double v = Kokkos::fmax(Kokkos::fabs(
phx(i)),
688 Kokkos::fmax(Kokkos::fabs(
phy(i)), Kokkos::fabs(
phz(i))));
692 Kokkos::Max<double>(m));
700 const double w[3],
C3 e,
int g) {
701 const double dx = lam * w[0], dy = lam * w[1], dz = lam * w[2];
704 "peclet::flow::sco_max_cell_peclet",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
706 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
707 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
710 const double P[3] = {unk(i -
sx) > 0.5 ? Kokkos::fabs(
phx(i)) / dx : 0.0,
711 unk(i - sy) > 0.5 ? Kokkos::fabs(
phy(i)) / dy : 0.0,
712 unk(i - sz) > 0.5 ? Kokkos::fabs(
phz(i)) / dz : 0.0};
713 for (
int k = 0; k < 3; ++k)
717 Kokkos::Max<double>(m));
718 return m > 0.0 ? m : 0.0;
724 "peclet::flow::sco_clamp_omega",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
726 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
734 const CCConst&
phz,
long i,
long sy,
long sz) {
735 return ((Kokkos::fmax(
phx(i + 1), 0.0) + Kokkos::fmax(-
phx(i), 0.0)) +
736 (Kokkos::fmax(
phy(i + sy), 0.0) + Kokkos::fmax(-
phy(i), 0.0))) +
737 (Kokkos::fmax(
phz(i + sz), 0.0) + Kokkos::fmax(-
phz(i), 0.0));
746 "peclet::flow::sco_bulk_courant",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
748 const long sy = e.x, sz = (
long)e.x * e.y;
749 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
750 if (!(unk(i) > 0.5) || !(kappa(i) >= 1.0) || !(sax(i) >= 1.0) || !(sax(i + 1) >= 1.0) ||
751 !(say(i) >= 1.0) || !(say(i + sy) >= 1.0) || !(saz(i) >= 1.0) || !(saz(i + sz) >= 1.0))
757 Kokkos::Max<double>(m));
767 Kokkos::deep_copy(
CCExec(), small, 0.0);
769 "peclet::flow::sco_small_cells",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
771 const long sy = e.x, sz = (
long)e.x * e.y;
772 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
773 const double k = kappa(i);
774 if (!(unk(i) > 0.5) || !(k < 1.0))
784 "peclet::flow::sco_count_small",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
786 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
799 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
800 const long s = st[a];
803 "peclet::flow::sco_count_implicit",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
805 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
806 if (phi(i) != 0.0 && unk(i) > 0.5 && unk(i - s) > 0.5 &&
807 (steady || small(i) > 0.5 || small(i - s) > 0.5))
825 "peclet::flow::sco_adv_bands",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
827 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
828 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
829 if (!(unk(i) > 0.5)) {
833 const bool si = small(i) > 0.5;
836 const long nb[6] = {i -
sx, i +
sx, i - sy, i + sy, i - sz, i + sz};
838 for (
int f = 0; f < 6; ++f) {
839 const bool imp = (steady ||
si || small(nb[f]) > 0.5) && unk(nb[f]) > 0.5;
840 d[f] =
imp ? Kokkos::fmax(
F[f], 0.0) : 0.0;
841 o[f] =
imp ? Kokkos::fmin(
F[f], 0.0) : 0.0;
843 const double om = ((d[0] + d[1]) + (d[2] + d[3])) + (d[4] + d[5]);
863 int a,
int scheme,
bool steady,
C3 e,
int g) {
864 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
865 const long s = st[a];
866 const C3 hi{a == 0 ? e.x - g + 1 : e.x - g, a == 1 ? e.y - g + 1 : e.y - g,
867 a == 2 ? e.z - g + 1 : e.z - g};
868 Kokkos::deep_copy(
CCExec(), Phi, 0.0);
870 "peclet::flow::sco_explicit_flux",
C3{g, g, g}, hi,
KOKKOS_LAMBDA(
int x,
int y,
int z) {
871 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
872 const double v = phi(i);
873 if (v == 0.0 || steady || small(i) > 0.5 || small(i - s) > 0.5 || !(unk(i) > 0.5) ||
876 const double cLL = c(i - 2 * s),
cL = c(i - s),
cR = c(i),
cRR = c(i + s);
877 bool fou = scheme == 0;
879 fou = v > 0.0 ? !(unk(i - 2 * s) > 0.5 && unk(i - s) > 0.5 && unk(i) > 0.5)
880 : !(unk(i + s) > 0.5 && unk(i) > 0.5 && unk(i - s) > 0.5);
891 "peclet::flow::sco_explicit_rhs",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
893 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
894 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
897 b(i) -= ((
Px(i +
sx) -
Px(i)) + (
Py(i + sy) -
Py(i))) + (
Pz(i + sz) -
Pz(i));
907 "peclet::flow::sco_adv_residual",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
909 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
910 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
913 const bool si = small(i) > 0.5;
915 const long nb[6] = {i -
sx, i +
sx, i - sy, i + sy, i - sz, i + sz};
916 const double ci = c(i);
918 for (
int f = 0; f < 6; ++f) {
919 const bool imp = (steady ||
si || small(nb[f]) > 0.5) && unk(nb[f]) > 0.5;
920 q[f] =
imp ? (
F[f] > 0.0 ?
F[f] *
ci :
F[f] * c(nb[f])) : 0.0;
922 r(i) -= ((q[0] + q[1]) + (q[2] + q[3])) + (q[4] + q[5]);
944 int a,
int side,
C3 e,
int g) {
947 const int ext[3] = {e.x, e.y, e.z};
948 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
949 const long sa = st[a], s1 = st[
t1], s2 = st[
t2];
950 const int m1 = ext[
t1], m2 = ext[
t2];
951 const long bfa = side == 0 ? g : ext[a] - g;
953 Kokkos::parallel_for(
957 const long in = side == 0 ?
bf :
bf -
sa;
958 phi(
bf) = unk(
in) > 0.5 ? plane((
long)j1 + (
long)
j2 * m1) : 0.0;
970 bool inflow,
int a,
int side,
bool steady,
C3 e,
int g,
974 const int ext[3] = {e.x, e.y, e.z};
975 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
976 const int n1 = ext[
t1] - 2 * g,
n2 = ext[
t2] - 2 * g;
977 const long sa = st[a], s1 = st[
t1], s2 = st[
t2];
978 const int aInner = side == 0 ? g : ext[a] - g - 1;
980 Kokkos::parallel_for(
983 const long i = (
long)
aInner *
sa + (
long)(j1 + g) * s1 + (
long)(
j2 + g) * s2;
986 const double Fout = side == 0 ? -phi(i) : phi(i +
sa);
989 }
else if (steady || small(i) > 0.5) {
995 b(i) -=
Fout * cOld(i);
1004 bool inflow,
int a,
int side,
bool steady,
C3 e,
int g) {
1009 const int ext[3] = {e.x, e.y, e.z};
1010 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
1011 const int n1 = ext[
t1] - 2 * g,
n2 = ext[
t2] - 2 * g;
1012 const long sa = st[a], s1 = st[
t1], s2 = st[
t2];
1013 const int aInner = side == 0 ? g : ext[a] - g - 1;
1015 Kokkos::parallel_for(
1018 const long i = (
long)
aInner *
sa + (
long)(j1 + g) * s1 + (
long)(
j2 + g) * s2;
1019 if (!(unk(i) > 0.5) || !(steady || small(i) > 0.5))
1021 const double Fout = side == 0 ? -phi(i) : phi(i +
sa);
1022 r(i) -=
Fout * c(i);
1031 Kokkos::View<const double*, CCMem>
gv,
bool inflow,
double vol,
int a,
1032 int side,
bool steady,
C3 e,
int g) {
1035 const int ext[3] = {e.x, e.y, e.z};
1036 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
1037 const int n1 = ext[
t1] - 2 * g,
n2 = ext[
t2] - 2 * g;
1038 const long sa = st[a], s1 = st[
t1], s2 = st[
t2];
1039 const int aInner = side == 0 ? g : ext[a] - g - 1;
1040 Kokkos::View<double*, CCMem> q(
"peclet::flow::sco_open_face_influx", (
long)
n1 *
n2);
1042 Kokkos::parallel_for(
1045 const long i = (
long)
aInner *
sa + (
long)(j1 + g) * s1 + (
long)(
j2 + g) * s2;
1046 const long k = (
long)j1 + (
long)
j2 *
n1;
1047 if (!(unk(i) > 0.5)) {
1051 const double Fout = side == 0 ? -phi(i) : phi(i +
sa);
1052 const double cv =
inflow ?
gv(k) : ((steady || small(i) > 0.5) ? c(i) : cOld(i));
1053 q(k) = -vol * (
Fout *
cv);
1056 auto h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), q);
1058 for (
long k = 0; k < (
long)h.extent(0); ++k)
1069 int side,
bool steady,
C3 e,
int g,
long&
nFlux,
long&
nImpl,
1073 const int ext[3] = {e.x, e.y, e.z};
1074 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
1075 const int n1 = ext[
t1] - 2 * g,
n2 = ext[
t2] - 2 * g;
1076 const long sa = st[a], s1 = st[
t1], s2 = st[
t2];
1077 const int aInner = side == 0 ? g : ext[a] - g - 1;
1079 long p = 0, q = 0, r = 0;
1080 Kokkos::parallel_reduce(
1083 const long i = (
long)
aInner *
sa + (
long)(j1 + g) * s1 + (
long)(
j2 + g) * s2;
1084 const double v = side == 0 ? phi(i) : phi(i +
sa);
1085 if (!(unk(i) > 0.5) || v == 0.0)
1089 if (!
inflow && (steady || small(i) > 0.5))
1091 if (!
inflow && (side == 0 ? v > 0.0 : v < 0.0))
1103 Kokkos::parallel_reduce(
1104 "peclet::flow::sco_max_cw", Kokkos::RangePolicy<CCExec>(0, (
long)cw.extent(0)),
1109 Kokkos::Max<double>(m));
1123 double G[3] = {0.0, 0.0, 0.0};
1124 double org[3] = {0.0, 0.0, 0.0};
1125 double h[3] = {1.0, 1.0, 1.0};
1129 const long z = j /
sz, y = (j - z *
sz) /
sy, x = j - z *
sz - y *
sy;
1133 return (
G[0] * px +
G[1] * py) +
G[2] * pz;
1141 const double gf[3],
C3 e,
int g) {
1144 "peclet::flow::sco_mg_face_rhs",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1146 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
1147 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1148 if (!(unk(i) > 0.5))
1150 const double aw = unk(i -
sx) > 0.5 ? sax(i) : 0.0;
1151 const double ae = unk(i +
sx) > 0.5 ? sax(i +
sx) : 0.0;
1152 const double as = unk(i - sy) > 0.5 ? say(i) : 0.0;
1153 const double an = unk(i + sy) > 0.5 ? say(i + sy) : 0.0;
1154 const double ab = unk(i - sz) > 0.5 ? saz(i) : 0.0;
1155 const double at = unk(i + sz) > 0.5 ? saz(i + sz) : 0.0;
1165 Kokkos::View<const double*, CCMem> cw,
1167 auto fcell =
fo.cell;
1168 auto offF =
fo.offF;
1171 Kokkos::parallel_for(
1172 "peclet::flow::sco_mg_probe_shift", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.n),
1176 const long i = fcell(f);
1178 for (
int k = 0; k < 8; ++k)
1179 gxp += wF(f, k) * pos(i + (
long)offF(f, k));
1180 rw(f) -= cw(f) *
gxp;
1188 long i,
long sy,
long sz,
const double hh[3],
1190 u[0] =
hh[0] * (
phx(i + 1) +
phx(i));
1191 u[1] =
hh[1] * (
phy(i + sy) +
phy(i));
1192 u[2] =
hh[2] * (
phz(i + sz) +
phz(i));
1198 const double hh[3],
C3 e,
int g,
double s[3]) {
1200 const double h0 =
hh[0],
h1 =
hh[1], h2 =
hh[2];
1201 double a = 0.0, b = 0.0, c = 0.0;
1202 Kokkos::parallel_reduce(
1203 "peclet::flow::sco_mg_cell_velocity_sum",
1206 const long sy = e.x, sz = (
long)e.x * e.y;
1207 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1208 if (!(unk(i) > 0.5))
1210 const double hq[3] = {
h0,
h1, h2};
1228 const double hh[3],
const double ub[3],
C3 e,
int g) {
1229 const double g0 =
gi[0], g1 =
gi[1], g2 =
gi[2],
h0 =
hh[0],
h1 =
hh[1], h2 =
hh[2],
u0 =
ub[0],
1230 u1 =
ub[1], u2 =
ub[2];
1232 "peclet::flow::sco_mg_adv_rhs",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1234 const long sy = e.x, sz = (
long)e.x * e.y;
1235 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1236 if (!(unk(i) > 0.5))
1238 const double hq[3] = {
h0,
h1, h2};
1241 const double k = kappa(i);
1242 b(i) -= (g0 * (u[0] - k *
u0) + g1 * (u[1] - k * u1)) + g2 * (u[2] - k * u2);
1252 double lam,
const double gi[3],
const double hp[3],
const double ub[3],
1253 C3 e,
int g,
double diff[3],
double adv[3]) {
1255 const double g0 =
gi[0], g1 =
gi[1], g2 =
gi[2],
hp0 = hp[0],
hp1 = hp[1],
hp2 = hp[2];
1256 const double h0 = 0.5 * hp[0],
h1 = 0.5 * hp[1], h2 = 0.5 * hp[2],
u0 =
ub[0], u1 =
ub[1],
1258 double d0 = 0.0,
d1 = 0.0,
d2 = 0.0;
1259 Kokkos::parallel_reduce(
1260 "peclet::flow::sco_mean_flux_diff",
1263 const long sy = e.x, sz = (
long)e.x * e.y;
1264 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1265 if (!(unk(i) > 0.5))
1267 if (unk(i - 1) > 0.5)
1268 p1 += -lam * sax(i) * ((th(i) - th(i - 1)) + g0 *
hp0) /
hp0;
1269 if (unk(i - sy) > 0.5)
1270 p2 += -lam * say(i) * ((th(i) - th(i - sy)) + g1 *
hp1) /
hp1;
1271 if (unk(i - sz) > 0.5)
1272 p3 += -lam * saz(i) * ((th(i) - th(i - sz)) + g2 *
hp2) /
hp2;
1278 adv[0] = adv[1] = adv[2] = 0.0;
1281 double a0 = 0.0, a1 = 0.0, a2 = 0.0;
1282 Kokkos::parallel_reduce(
1283 "peclet::flow::sco_mean_flux_adv",
1286 const long sy = e.x, sz = (
long)e.x * e.y;
1287 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1288 if (!(unk(i) > 0.5))
1290 const double hq[3] = {
h0,
h1, h2};
1293 const double k = kappa(i), t = th(i);
1294 p1 += (u[0] - k *
u0) * t;
1295 p2 += (u[1] - k * u1) * t;
1296 p3 += (u[2] - k * u2) * t;
1324 const int b = (int)m;
1332 const double la = lam(
ma);
1335 const double lb = lam(
mb);
1336 return (
la +
lb) > 0.0 ? 2.0 *
la *
lb / (
la +
lb) : 0.0;
1350 Kokkos::View<const int*, CCMem> owner,
bool hasOwner,
1352 const int nx = e.x - 2 * g, ny = e.y - 2 * g;
1353 Kokkos::deep_copy(
CCExec(), mat, -1.0);
1354 Kokkos::deep_copy(
CCExec(), sunk, 0.0);
1356 "peclet::flow::sco_solid_owner",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1358 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
1362 auto cutCell =
fo.cutCell;
1363 auto cfs =
fo.cellFacetStart;
1364 auto alpha =
fo.alpha;
1365 auto body =
fo.body;
1367 const int nb =
mt.nb;
1369 Kokkos::parallel_for(
1370 "peclet::flow::sco_solid_facet_material", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.nCut),
1374 for (
int f =
cfs(c); f <
cfs(c + 1); ++f) {
1375 const int b =
bodyIndex((
double)body(f), nb);
1376 if (alpha(f) >
aAny) {
1386 sunk(cutCell(c)) =
best >= 0 ? 1.0 : 0.0;
1389 double v0 = 0.0,
v1 = 0.0;
1390 Kokkos::parallel_reduce(
1391 "peclet::flow::sco_solid_flags",
1394 const long sy = e.x, sz = (
long)e.x * e.y;
1395 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1396 const double m = mat(i);
1398 const double asSum =
1399 (((1.0 - sax(i)) + (1.0 - sax(i + 1))) + ((1.0 - say(i)) + (1.0 - say(i + sy)))) +
1400 ((1.0 - saz(i)) + (1.0 - saz(i + sz)));
1401 const bool u =
cand && (
asSum > 0.0 || sunk(i) > 0.5);
1403 pv += 1.0 - kappa(i);
1405 ps += 1.0 - kappa(i);
1407 sunk(i) = u ? 1.0 : 0.0;
1417 Kokkos::View<
int* [8], Kokkos::LayoutLeft,
CCMem> offS,
1418 Kokkos::View<
double* [8], Kokkos::LayoutLeft,
CCMem> wS,
1419 Kokkos::View<std::uint8_t*, CCMem> rungS,
1420 Kokkos::View<const std::uint8_t*, CCMem> conjF,
1422 const double hp[3]) {
1424 const long sy = e.x, sz = (
long)e.x * e.y;
1425 const double h0 = hp[0],
h1 = hp[1], h2 = hp[2];
1426 auto fcell =
fo.cell;
1429 Kokkos::parallel_for(
1430 "peclet::flow::sco_solid_probes", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.n),
1432 if (conjF(f) == 0) {
1435 for (
int k = 0; k < 8; ++k) {
1441 const double h[3] = {
h0,
h1, h2};
1445 const peclet::core::scheme::ProbeResult r = peclet::core::scheme::buildProbe(
xw, n, h, L);
1447 rungS(f) = (std::uint8_t)r.rung;
1448 for (
int k = 0; k < 8; ++k) {
1449 const bool used = k < r.n;
1451 used ? (int)((
long)r.off[k][0] + (
long)r.off[k][1] * sy + (
long)r.off[k][2] * sz) : 0;
1452 wS(f, k) =
used ? r.w[k] : 0.0;
1465 const int nb =
mt.nb;
1467 "peclet::flow::sco_solid_face_products",
C3{0, 0, 0}, e,
KOKKOS_LAMBDA(
int x,
int y,
int z) {
1468 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
1469 const long i = (
long)x + (
long)y * st[1] + (
long)z * st[2];
1470 const int xa[3] = {x, y, z};
1471 const bool ui = sunk(i) > 0.5;
1473 for (
int a = 0; a < 3; ++a) {
1474 const long j = i - st[a];
1475 if (
xa[a] < 1 || !
ui || !(sunk(j) > 0.5)) {
1479 const double ap = a == 0 ? sax(i) : (a == 1 ? say(i) : saz(i));
1490 double idt,
C3 e,
int g) {
1492 const int nb =
mt.nb;
1493 Kokkos::deep_copy(
CCExec(), ms, 0.0);
1495 "peclet::flow::sco_solid_mass",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1497 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
1499 ms(i) = ck(
bodyIndex(mat(i), nb)) * (1.0 - kappa(i)) * idt;
1507 const double w[3],
C3 e,
int g) {
1508 const double wx = w[0],
wy = w[1],
wz = w[2];
1510 "peclet::flow::sco_solid_bands",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1512 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
1513 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1514 if (!(sunk(i) > 0.5)) {
1516 AW(i) = AE(i) = AS(i) = AN(i) = AB(i) = AT(i) = 0.0;
1519 const double tw =
wx * spx(i),
te =
wx * spx(i +
sx);
1520 const double ts =
wy * spy(i),
tn =
wy * spy(i + sy);
1521 const double tb =
wz * spz(i),
tt =
wz * spz(i + sz);
1528 AC(i) = ms(i) + (((
tw +
te) + (ts +
tn)) + (tb +
tt));
1535 "peclet::flow::sco_solid_rhs",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1537 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
1538 bs(i) = ms(i) * sOld(i);
1547 Kokkos::View<const std::uint8_t*, CCMem> conjF,
1548 Kokkos::View<const double*, CCMem> sS,
CCConst unk,
CCConst sunk,
1550 auto fcell =
fo.cell;
1556 const int nb =
mt.nb;
1558 Kokkos::parallel_for(
1559 "peclet::flow::sco_conj_coeffs", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.n),
1561 const long i = fcell(f);
1562 if (conjF(f) == 0 || !(unk(i) > 0.5) || !(sunk(i) > 0.5)) {
1568 peclet::core::scheme::interfaceConductance(sF(f),
lamF, rc(b), sS(f), lam(b));
1578 Kokkos::View<const double*, CCMem> cw,
1579 Kokkos::View<const double*, CCMem> cc,
1580 Kokkos::View<
int* [8], Kokkos::LayoutLeft,
CCMem> offS,
1581 Kokkos::View<
double* [8], Kokkos::LayoutLeft,
CCMem> wS,
1583 auto cutCell =
fo.cutCell;
1584 auto cfs =
fo.cellFacetStart;
1585 auto offF =
fo.offF;
1588 Kokkos::parallel_for(
1589 "peclet::flow::sco_conj_overlay_apply", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.nCut),
1591 const long i = cutCell(c);
1592 double af = 0.0,
as = 0.0;
1593 for (
int f =
cfs(c); f <
cfs(c + 1); ++f) {
1595 for (
int k = 0; k < 8; ++k)
1596 upf += wF(f, k) * xf(i + (
long)offF(f, k));
1600 for (
int k = 0; k < 8; ++k)
1601 ups += wS(f, k) * xs(i + (
long)offS(f, k));
1602 const double q = cc(f) * (
upf -
ups);
1621 Kokkos::View<const double*, CCMem> cc) {
1623 Kokkos::deep_copy(
CCExec(), SACs, ACs);
1624 Kokkos::deep_copy(
CCExec(), W0, 0.0);
1625 auto cutCell =
fo.cutCell;
1626 auto cfs =
fo.cellFacetStart;
1628 Kokkos::parallel_for(
1629 "peclet::flow::sco_conj_surrogate", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.nCut),
1631 double aw = 0.0,
ac = 0.0;
1632 for (
int f =
cfs(c); f <
cfs(c + 1); ++f) {
1633 aw += cw(f) + cc(f);
1636 const long i = cutCell(c);
1648 Kokkos::View<const double*, CCMem> cc,
1649 Kokkos::View<
int* [8], Kokkos::LayoutLeft,
CCMem> offS,
1650 Kokkos::View<
double* [8], Kokkos::LayoutLeft,
CCMem> wS,
1652 auto cutCell =
fo.cutCell;
1653 auto cfs =
fo.cellFacetStart;
1654 auto offF =
fo.offF;
1657 Kokkos::parallel_for(
1658 "peclet::flow::sco_conj_mg_shift", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.nCut),
1660 const long i = cutCell(c);
1662 for (
int f =
cfs(c); f <
cfs(c + 1); ++f) {
1665 double gf = 0.0, gs = 0.0;
1666 for (
int k = 0; k < 8; ++k) {
1667 gf += wF(f, k) * pos(i + (
long)offF(f, k));
1668 gs += wS(f, k) * pos(i + (
long)offS(f, k));
1670 d += cc(f) * (gs -
gf);
1682 CCConst spz,
const double gs[3],
C3 e,
int g) {
1683 const double gx = gs[0],
gy = gs[1],
gz = gs[2];
1685 "peclet::flow::sco_solid_mg_face_rhs",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1687 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
1688 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1689 if (!(sunk(i) > 0.5))
1691 bs(i) += (
gx * (spx(i +
sx) - spx(i)) +
gy * (spy(i + sy) - spy(i))) +
1692 gz * (spz(i + sz) - spz(i));
1701 const double wx = w[0],
wy = w[1],
wz = w[2];
1703 "peclet::flow::sco_solid_residual_flux",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1705 const long sx = 1, sy = e.x, sz = (
long)e.x * e.y;
1707 if (!(sunk(i) > 0.5)) {
1711 const double ci = x(i);
1713 ((
wx * spx(i) * (
ci - x(i -
sx)) +
wx * spx(i +
sx) * (
ci - x(i +
sx))) +
1714 (
wy * spy(i) * (
ci - x(i - sy)) +
wy * spy(i + sy) * (
ci - x(i + sy)))) +
1715 (
wz * spz(i) * (
ci - x(i - sz)) +
wz * spz(i + sz) * (
ci - x(i + sz)));
1716 r(i) = b(i) - ms(i) *
ci - flux;
1725 const int nb =
mt.nb;
1727 double s1 = 0.0, s2 = 0.0;
1728 Kokkos::parallel_reduce(
1729 "peclet::flow::sco_solid_moments",
1732 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
1733 if (sunk(i) > 0.5) {
1734 const double wk = ck(
bodyIndex(mat(i), nb)) * (1.0 - kappa(i));
1747inline void conjFacetFlux(Kokkos::View<double*, CCMem>
up, Kokkos::View<double*, CCMem> us,
1750 Kokkos::View<const double*, CCMem> rw,
1751 Kokkos::View<const double*, CCMem> cc,
1752 Kokkos::View<
int* [8], Kokkos::LayoutLeft,
CCMem> offS,
1753 Kokkos::View<
double* [8], Kokkos::LayoutLeft,
CCMem> wS,
1755 auto fcell =
fo.cell;
1756 auto offF =
fo.offF;
1759 Kokkos::parallel_for(
1760 "peclet::flow::sco_conj_facet_flux", Kokkos::RangePolicy<CCExec>(
space, 0,
fo.n),
1762 const long i = fcell(f);
1763 double u = 0.0, v = 0.0;
1764 for (
int k = 0; k < 8; ++k)
1765 u += wF(f, k) * xf(i + (
long)offF(f, k));
1766 for (
int k = 0; k < 8; ++k)
1767 v += wS(f, k) * xs(i + (
long)offS(f, k));
1774 double gf = 0.0, gs = 0.0;
1775 for (
int k = 0; k < 8; ++k) {
1776 gf += wF(f, k) * pos(i + (
long)offF(f, k));
1777 gs += wS(f, k) * pos(i + (
long)offS(f, k));
1783 qin(f) = rw(f) - cw(f) * u;
1793 "peclet::flow::sco_dot_two",
C3{g, g, g},
C3{e.x - g, e.y - g, e.z - g},
1795 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
1796 acc +=
af(i) *
bf(i) +
as(i) *
bs(i);
1798 std::forward<R>(
result));
1807template <
class R1,
class R2>
1809 C3 e,
int g, R1&& r1, R2&& r2) {
1811 Kokkos::parallel_reduce(
1814 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
1816 p2 += cf(i) * cf(i) + cs(i) * cs(i);
1818 std::forward<R1>(r1), std::forward<R2>(r2));
1821 C3 e,
int g,
double&
ab,
double& cc) {
1822 double s1 = 0.0, s2 = 0.0;
1831 const double gi[3],
const double hp[3],
C3 e,
int g,
1834 const double g0 =
gi[0], g1 =
gi[1], g2 =
gi[2],
hp0 = hp[0],
hp1 = hp[1],
hp2 = hp[2];
1835 double d0 = 0.0,
d1 = 0.0,
d2 = 0.0;
1836 Kokkos::parallel_reduce(
1837 "peclet::flow::sco_solid_mean_flux",
1840 const long sy = e.x, sz = (
long)e.x * e.y;
1841 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
1842 if (!(sunk(i) > 0.5))
1845 p1 += -spx(i) * ((th(i) - th(i - 1)) + g0 *
hp0) /
hp0;
1847 p2 += -spy(i) * ((th(i) - th(i - sy)) + g1 *
hp1) /
hp1;
1849 p3 += -spz(i) * ((th(i) - th(i - sz)) + g2 *
hp2) /
hp2;
flow — portable (Kokkos) cut-cell pressure-operator face openness from an SDF.
double dotTwoLocal(CCConst af, CCConst bf, CCConst as, CCConst bs, C3 e, int g)
void conjugateCoefficients(Kokkos::View< double *, CCMem > cc, const scg::ScalarFacetOverlay &fo, Kokkos::View< const std::uint8_t *, CCMem > conjF, Kokkos::View< const double *, CCMem > sS, CCConst unk, CCConst sunk, const MaterialTable &mt, double lamF)
Per facet (§1.4, §4.1): cc = alpha G_c, G_c = 1/(s_f/Lam_f + R_c + s_s/Lam_s), on a facet of a conjug...
void explicitFaceFluxes(CCField Phi, CCConst phi, CCConst c, CCConst unk, CCConst small, int a, int scheme, bool steady, C3 e, int g)
The explicit face fluxes of §6.2 on the low a-faces of the cells g .
void faceFluxes(CCField phi, CCConst vel, CCConst open, CCConst unk, int a, C3 e)
phi = open * vel on every face whose two cells are inside the block (0 on the block's lowest layer),...
void openFaceResidual(CCField r, CCConst c, CCConst phi, CCConst small, CCConst unk, bool inflow, int a, int side, bool steady, C3 e, int g)
r(i) -= F_out c_i on the implicit outflow faces of (a, side) (the budget's flux-form residual; the in...
void meanFluxLocal(CCConst th, CCConst kappa, CCConst unk, CCConst sax, CCConst say, CCConst saz, CCConst phx, CCConst phy, CCConst phz, bool advecting, double lam, const double gi[3], const double hp[3], const double ub[3], C3 e, int g, double diff[3], double adv[3])
scalar_mean_flux (§8.1), this rank's sums (internal; the caller divides by the global cell count): di...
void cellVelocitySumLocal(CCConst phx, CCConst phy, CCConst phz, CCConst unk, const double hh[3], C3 e, int g, double s[3])
(sum U'_x/V, sum U'_y/V, sum U'_z/V) over the unknown inner cells (the moving frame's numerator; its ...
void zeroNonUnknown(CCField c, CCConst unk, C3 e, int g)
Zero c on every inner cell that is not a fluid unknown (§1.3: re-zeroed at the start of every advance...
double openFaceInflux(CCConst c, CCConst cOld, CCConst phi, CCConst small, CCConst unk, Kokkos::View< const double *, CCMem > gv, bool inflow, double vol, int a, int side, bool steady, C3 e, int g)
Sum over one open face of V times the advective flux INTO the domain through it, per internal time (b...
void conjOverlayApply(CCField yf, CCField ys, CCConst xf, CCConst xs, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > cw, Kokkos::View< const double *, CCMem > cc, Kokkos::View< int *[8], Kokkos::LayoutLeft, CCMem > offS, Kokkos::View< double *[8], Kokkos::LayoutLeft, CCMem > wS, bool subtract=false)
The two-field overlay (§4.1 step 3), one thread per cut cell, facets in CSR order: y_f(i) += sum cw u...
void dot2TwoReduce(CCConst af, CCConst bf, CCConst cf, CCConst as, CCConst bs, CCConst cs, C3 e, int g, R1 &&r1, R2 &&r2)
(sum a b, sum c c) over inner cells, both fields, in one pass, into (r1, r2).
double sourceSumLocal(CCConst kappa, CCConst unk, double srcConst, CCConst src, bool useField, double srcFactor, C3 e, int g)
sum over unknowns of kappa S' (the source part of the right-hand side, per unit V).
void solidFaceProducts(CCField spx, CCField spy, CCField spz, CCConst sunk, CCConst mat, CCConst sax, CCConst say, CCConst saz, const MaterialTable &mt, C3 e)
The level-0 solid face products P_a(i) = Lam_face a_s on the LOW a-face of cell i when cells i - s_a ...
long countImplicitLocal(CCConst phi, CCConst small, CCConst unk, int a, bool steady, C3 e, int g)
Faces carrying flux that are implicit, over the low faces of the inner cells (census num_implicit_fac...
void dot2Reduce(CCConst a, CCConst b, CCConst c, C3 e, int g, R1 &&r1, R2 &&r2)
(sum a b, sum c c) over inner cells in one pass, into (r1, r2).
void meanGradientFaceRhs(CCField b, CCConst unk, CCConst sax, CCConst say, CCConst saz, const double gf[3], C3 e, int g)
Faces (§1.5): b(i) += sum_a gf_a (a_a^+ - a_a^-) over the coupled faces (the bands' guard),...
void dot2Local(CCConst a, CCConst b, CCConst c, C3 e, int g, double &ab, double &cc)
void solidBands(CCField AC, CCField AW, CCField AE, CCField AS, CCField AN, CCField AB, CCField AT, CCConst ms, CCConst sunk, CCConst spx, CCConst spy, CCConst spz, const double w[3], C3 e, int g)
The solid phase's 7 bands (§4.1): AC = m_s + the six face terms w_a P, off-diagonals -w_a P; identity...
double solidFaceLam(const Kokkos::View< double *, CCMem > &lam, int ma, int mb)
Lam_face of a solid face between materials ma and mb (§1.4): Lam_s of the material when equal,...
void openFaceAdvection(CCField AC, CCField b, CCField outflow, CCConst cOld, CCConst phi, CCConst small, CCConst unk, Kokkos::View< const double *, CCMem > gv, bool inflow, int a, int side, bool steady, C3 e, int g, CCField omega=CCField(), bool wOmega=false)
The open face's row terms on the unknown inner boundary cells of (a, side) (table above): inflow b +=...
void maxabsReduce(CCConst a, C3 e, int g, Red red)
max over inner cells of |a|, through the Max reducer red (Kokkos::Max over a host double or a device ...
void conjFacetFlux(Kokkos::View< double *, CCMem > up, Kokkos::View< double *, CCMem > us, Kokkos::View< double *, CCMem > qin, CCConst xf, CCConst xs, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > cw, Kokkos::View< const double *, CCMem > rw, Kokkos::View< const double *, CCMem > cc, Kokkos::View< int *[8], Kokkos::LayoutLeft, CCMem > offS, Kokkos::View< double *[8], Kokkos::LayoutLeft, CCMem > wS, const MeanGradPosition &pos, bool mgOn)
Per facet: the probe values and the flux INTO the fluid per unit cell volume per internal time,...
long countSmallLocal(CCConst small, C3 e, int g)
Count of small inner cells (census num_small_cells).
double maxCellPecletLocal(CCConst phx, CCConst phy, CCConst phz, CCConst unk, double lam, const double w[3], C3 e, int g)
A2 census max_cell_peclet on this rank: the max over the interior flux faces (the low faces of the in...
void sumUnknownLocal(CCConst a, CCConst unk, C3 e, int g, double &sum, double &sumAbs)
(sum a, sum |a|) over the inner cells that are unknowns.
void solidRhs(CCField bs, CCConst ms, CCConst sOld, C3 e, int g)
The solid right-hand side b_s = m_s psi_s^n (no solid source in v1, §13 Q17); 0 elsewhere.
void openFaceFluxes(CCField phi, Kokkos::View< const double *, CCMem > plane, CCConst unk, int a, int side, C3 e, int g)
phi(bf) = plane value on the boundary face of (a, side), over the full transverse extent,...
double dotLocal(CCConst a, CCConst b, C3 e, int g)
double bulkCourantLocal(CCConst phx, CCConst phy, CCConst phz, CCConst kappa, CCConst unk, CCConst sax, CCConst say, CCConst saz, double dt, C3 e, int g)
C_bulk of §6.3 on this rank: max over the inner FULL cells (an unknown with kappa = 1 and all six sna...
void solidMomentsLocal(CCConst xs, CCConst kappa, CCConst sunk, CCConst mat, const MaterialTable &mt, C3 e, int g, double &m, double &w)
(sum C_s K kappa_s psi_s, sum C_s K kappa_s) over the solid unknowns (times V by the caller): the sol...
double dirichletFaceInflux(CCConst c, CCConst unk, CCConst saA, Kokkos::View< const double *, CCMem > gv, double lamW, double vol, int a, int side, C3 e, int g)
Sum over one Dirichlet domain face of V t (g_bf - c_i): the flux INTO the domain through it,...
void solidResidualFluxForm(CCField r, CCConst x, CCConst b, CCConst ms, CCConst sunk, CCConst spx, CCConst spy, CCConst spz, const double w[3], C3 e, int g)
The solid residual in FLUX form (the budget, §9): r = b - m_s psi - sum_faces t (psi_i - psi_nb); the...
void solidMeanGradientFaceRhs(CCField bs, CCConst sunk, CCConst spx, CCConst spy, CCConst spz, const double gs[3], C3 e, int g)
Mean-gradient mode, solid faces (§1.5): b_s(i) += sum_a gs_a (P_a(i + s_a) - P_a(i)),...
void dot2TwoLocal(CCConst af, CCConst bf, CCConst cf, CCConst as, CCConst bs, CCConst cs, C3 e, int g, double &ab, double &cc)
void clampNonNegative(CCField omega, C3 e, int g)
omega = max(omega, 0) on the inner cells (A2: implicit backflow never enters the coarse mass).
void buildSolidProbes(Kokkos::View< double *, CCMem > sS, Kokkos::View< int *[8], Kokkos::LayoutLeft, CCMem > offS, Kokkos::View< double *[8], Kokkos::LayoutLeft, CCMem > wS, Kokkos::View< std::uint8_t *, CCMem > rungS, Kokkos::View< const std::uint8_t *, CCMem > conjF, const scg::ScalarFacetOverlay &fo, CCConst sdf, CCConst sunk, C3 e, const double hp[3])
The solid probe ladder (§3.4): per facet of a conjugate body (conjF), the ladder of §3....
void solidMass(CCField ms, CCConst kappa, CCConst sunk, CCConst mat, const MaterialTable &mt, double idt, C3 e, int g)
The solid mass m_s = C_s K kappa_s idt on the solid unknowns, 0 elsewhere (inner cells).
void facetFlux(Kokkos::View< double *, CCMem > up, Kokkos::View< double *, CCMem > qin, CCConst x, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > cw, Kokkos::View< const double *, CCMem > rw)
Per facet: the probe value u_p of x and the wall flux INTO the fluid per unit cell volume per interna...
void cellVelocity(const CCConst &phx, const CCConst &phy, const CCConst &phz, long i, long sy, long sz, const double hh[3], double u[3])
U'_a/V of cell i (§1.5): the volume-integrated cell velocity sum_f F_out (x_f - x_i) per unit full-ce...
void overlayApply(CCField y, CCConst x, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > cw, bool subtract=false)
y(i) += sum over the facets of cut cell i of cw * (probe interpolation of x): the overlay pass of the...
double maxAbsFluxLocal(CCConst phx, CCConst phy, CCConst phz, C3 e, int g)
max |phi| over the low faces of the inner cells (0: no advection this step).
void solidMeanFluxLocal(CCConst th, CCConst sunk, CCConst spx, CCConst spy, CCConst spz, const double gi[3], const double hp[3], C3 e, int g, double diff[3])
The solid part of scalar_mean_flux's diffusive sum (§8.1): over the low faces of the inner cells whos...
void faceFluxCountsLocal(CCConst phi, CCConst vel, CCConst open, int a, C3 e, int g, long &nFlux, long &nGuarded)
(faces carrying flux, faces whose nonzero open * vel the guard zeroed) over the low faces of the inne...
double lowAp(const CCConst &sax, const CCConst &say, const CCConst &saz, int a, long i)
Face aperture of axis a at the low face of cell i (sa_a(i)).
void dotTwoReduce(CCConst af, CCConst bf, CCConst as, CCConst bs, C3 e, int g, R &&result)
sum over inner cells of af bf + as bs (the two-field dot).
void conjSurrogate(CCField SACf, CCField SACs, CCField W0, CCConst ACf, CCConst ACs, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > cw, Kokkos::View< const double *, CCMem > cc)
The two-field level-0 surrogate (§4.3): SAC_f = AC_f + sum (cw + cc), SAC_s = AC_s + sum cc,...
double cellOutflow(const CCConst &phx, const CCConst &phy, const CCConst &phz, long i, long sy, long sz)
Out_i = sum over the six faces of max(F_out, 0), per unit V (§6.3), in a fixed order.
void residualFluxForm(CCField r, CCConst c, CCConst b, CCConst kappa, CCConst unk, CCConst sax, CCConst say, CCConst saz, double lam, double idt, const double w[3], C3 e, int g)
The budget's residual r = b - A c in FLUX form (§9): r = b - kappa idt c - sum_faces t (c_i - c_nb) w...
void smallCells(CCField small, CCConst phx, CCConst phy, CCConst phz, CCConst kappa, CCConst unk, double dt, double thr, C3 e, int g)
The small-cell flags of §6.3 over the inner cells: small(i) = 1 iff i is an unknown,...
void meanGradientAdvectionRhs(CCField b, CCConst phx, CCConst phy, CCConst phz, CCConst kappa, CCConst unk, const double gi[3], const double hh[3], const double ub[3], C3 e, int g)
Advection (§1.5): b(i) -= G'.
double maxabsLocal(CCConst a, C3 e, int g)
void buildSolidMaterial(CCField mat, CCField sunk, CCConst kappa, CCConst sax, CCConst say, CCConst saz, const scg::ScalarFacetOverlay &fo, Kokkos::View< const int *, CCMem > owner, bool hasOwner, const MaterialTable &mt, C3 e, int g, double vol[2])
The material per cell and the solid-unknown flags on the inner cells (§1.3, §2.7).
void advectionBands(CCField AC, CCField AW, CCField AE, CCField AS, CCField AN, CCField AB, CCField AT, CCField outflow, CCConst phx, CCConst phy, CCConst phz, CCConst small, CCConst unk, bool steady, C3 e, int g)
The implicit FOU part of the operator (§1.4, §6.3; all faces when steady, §6.7): on every unknown inn...
void buildBands(CCField AC, CCField AW, CCField AE, CCField AS, CCField AN, CCField AB, CCField AT, CCConst kappa, CCConst unk, CCConst sax, CCConst say, CCConst saz, double lam, double idt, const double w[3], C3 e, int g)
The 7 bands (§4.1): AC = kappa idt + sum of the six face terms Lam w_a a (guarded toward a cell that ...
void dirichletFaceFold(CCField AC, CCField b, CCConst unk, CCConst saA, Kokkos::View< const double *, CCMem > gv, double lamW, int a, int side, C3 e, int g)
Dirichlet domain face (§1.4 B_i): for the inner boundary cell i of face (a, side),...
int bodyIndex(double m, int nb)
A body id clamped into the table (out of range -> 0, as facetCoefficients does).
void explicitAdvectionRhs(CCField b, CCConst Px, CCConst Py, CCConst Pz, CCConst unk, C3 e, int g)
b(i) -= the net explicit outflow sum_a (Phi_a(i + s_a) - Phi_a(i)) on the unknown inner cells.
void kappaMomentsLocal(CCConst c, CCConst kappa, CCConst unk, C3 e, int g, double &kc, double &k)
(sum kappa c, sum kappa) over the unknowns (times V by the caller).
void openFaceCountsLocal(CCConst phi, CCConst small, CCConst unk, bool inflow, int a, int side, bool steady, C3 e, int g, long &nFlux, long &nImpl, long &nBack)
The census counts of one open face over this rank's inner boundary cells: (faces carrying flux on the...
void dirichletFaceResidual(CCField r, CCConst c, CCConst unk, CCConst saA, double lamW, int a, int side, C3 e, int g)
r(i) -= 2 Lam w_a a_bf c_i on the inner boundary cells of a Dirichlet domain face (the LHS part of di...
void facetCoefficients(Kokkos::View< double *, CCMem > cw, Kokkos::View< double *, CCMem > rw, const scg::ScalarFacetOverlay &fo, CCConst unk, const WallTable &wt, double lam)
Per-facet overlay coefficients (§4.1): cw = alpha G, rw = alpha G g (Dirichlet/Robin) or cw = 0,...
double maxFacetLocal(Kokkos::View< const double *, CCMem > cw)
max over facets of cw (0 when there is no Dirichlet/Robin facet: the steady singular test).
void faceTangents(int a, int &t1, int &t2)
The tangential axes of face axis a, in x, y, z order (t1 < t2): the layout of a domain-face profile (...
void surrogateDiagonal(CCField SAC, CCConst AC, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > cw)
The level-0 surrogate diagonal (§4.3): SAC = AC + sum of the cut cell's cw (the probe weights lumped,...
void dotReduce(CCConst a, CCConst b, C3 e, int g, R &&result)
sum over inner cells of a(i) b(i), into result.
void buildRhs(CCField b, CCConst cOld, CCConst kappa, CCConst unk, double idt, double srcConst, CCConst src, bool useField, double srcFactor, C3 e, int g)
Base right-hand side: b = kappa (idt c^n + S'), identity rows 0.
void advectionResidual(CCField r, CCConst c, CCConst phx, CCConst phy, CCConst phz, CCConst small, CCConst unk, bool steady, C3 e, int g)
r(i) -= the implicit faces' net outflow sum F_out c_up at c (the budget's flux-form residual,...
void meanGradientProbeShift(Kokkos::View< double *, CCMem > rw, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > cw, const MeanGradPosition &pos)
Dirichlet/Robin probes (§1.5): rw(f) -= cw(f) sum_k w_k G.x_k, so that rw = alpha G_phi (g - sum_k w_...
void addOnUnknown(CCField a, CCConst unk, double d, C3 e, int g)
a(i) += d on the inner cells that are unknowns.
void overlayRhs(CCField b, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > rw)
b(i) += sum over the facets of cut cell i of rw (the wall part of the right-hand side).
void conjMeanGradientShift(CCField bf, CCField bs, const scg::ScalarFacetOverlay &fo, Kokkos::View< const double *, CCMem > cc, Kokkos::View< int *[8], Kokkos::LayoutLeft, CCMem > offS, Kokkos::View< double *[8], Kokkos::LayoutLeft, CCMem > wS, const MeanGradPosition &pos)
Mean-gradient mode, conjugate facets (§1.5): the fluid row carries + cc (u_pf - u_ps) with u = theta ...
CCExec::memory_space CCMem
void ccReduce3(const char *name, C3 lo, C3 hi, F f, R &&... reducers)
void ccFor3(const char *name, C3 lo, C3 hi, F f)
Kokkos::View< double *, CCMem > CCField
Kokkos::DefaultExecutionSpace CCExec
Kokkos::View< const double *, CCMem > CCConst
double fou_flux(double L, double R, double vel)
double tvd(double LL, double L, double R, double RR, double vel)
double sou(double LL, double L, double R, double RR, double vel)
flow — the multidimensional iteration policies: iteration order follows storage.
flow — portable (Kokkos) staggered MAC momentum advection (Koren TVD + FOU).
The per-cut-cell-scalar state (ScalarField::cut).
std::size_t mgN
the block size it was built for
Kokkos::View< double *, CCMem > ks
WO-9b: the resident Krylov's scalar slots.
ScalarWallSpec wallDefault
every body without an instance override
CCField outflow
lumped implicit outflow per cell (inside SAC; ScalarMG coarse mass, §5.2)
double residual
final TRUE residual max|b - A c| / ref, after any gauge shift
bool warnedKoren
the koren-above-bulk-Courant-1/2 warning was issued (once)
long numGuardedFaces
faces whose projection flux the guard zeroed (a no-op reading)
Kokkos::View< double *, CCMem > mtLamV
Kokkos::View< int *, CCMem > wtTypeV
double srcFactor
S' = S * srcFactor (tRef)
CCField Phi[3]
explicit face fluxes phi c*(c^n), 0 on implicit faces (§6.2)
CCField kq
singular case: the projected rhs, and the preconditioner's rhs copy
Kokkos::View< double *, CCMem > gFace[6]
Dirichlet domain-face value per face cell.
std::vector< int > wtType
the resolved per-body wall table of that operator
CCField spz
level-0 solid face products Lam_face a_s (guarded), low faces
Kokkos::View< double *, CCMem > rw
per facet (§4.1)
long numSmall
census num_small_cells
bool openInflow[6]
... and it is an inflow
std::vector< double > profile[6]
Dirichlet domain-face profile (t1 fastest)
bool warnedBackflow
the steady backflow warning was issued (once per scalar)
bool advecting
some face carried flux: else every advection kernel was skipped
double gPhys[3]
its G (physical, c/L)
Kokkos::View< int *, CCMem > mtConjV
CCField small
1 on a small cell (§6.3), inner cells + exchanged ghosts
long warnedGeometryVersion
The geometry version whose §9 resolution warnings were issued (WO-8: once per scalar and geometry; a ...
std::vector< double > mtLam
CCField ms
solid mass C_s K kappa_s idt on solid unknowns
Kokkos::View< double *, CCMem > wtGV
CCField mat
material (body id) per cell, haloed; -1: no solid
long numUnknowns
global fluid unknowns (the singular mean)
std::vector< double > wtK
CCField W0
solid surrogate diagonal; the same-cell coupling sum cc
CCField omegaOpen
A2 (§6.7, D-WO5-3): the implicit outflow the open-face rows add to AC, summed over the cell's open fa...
double incompatibility
steady singular case: |sum b| / sum |b| before projection
Kokkos::View< double *, CCMem > mtCKV
bool openFace[6]
open face rows built (WO-5b)
double lam
internal Lam = D tRef/hRef^2 of that operator
std::vector< std::pair< int, ScalarWallSpec > > wallInstance
instance overrides, last wins
Kokkos::View< int *[8], Kokkos::LayoutLeft, CCMem > offS
bool meanGradOn
that operator carried the mean-gradient terms (§1.5)
int profileN[6][2]
its tangential extents
long solidRungs[4]
census probe_rungs['solid'] (global)
long mgVersion
the geometry version its level table was built for
double solidVolume
census solid_volume: conjugate solid, physical
long numImplicitFaces
census num_implicit_faces (faces carrying flux, implicit)
CCField solid
the registered field <name>_solid (psi_s), when allocated
std::vector< double > mtCK
CCField phi[3]
F/V through the LOW a-face of cell i (internal 1/T), guarded (sco::faceFluxes)
std::shared_ptr< ScalarMG > mg
int maxit
BiCGStab iteration cap (§5.1)
double meanGrad[3]
Mean-gradient (closure) mode (§1.5, WO-6): the field holds theta, c = G.x + theta,...
double maxCellPeclet
census max_cell_peclet (A2): max |phi_a| / (Lam' w_a)
Kokkos::View< double *, Kokkos::HostSpace > pk
and its host packet
Kokkos::View< double *, CCMem > sS
solid probe distance per facet (conjugate facets)
CCField sunk
solid-unknown flags (haloed, 0 beyond non-periodic faces)
Kokkos::View< double *, CCMem > mtKV
long numBackflowFaces
census num_backflow_faces: outflow-face rows with F_out < 0
std::vector< double > mtK
double bulkCourant
census bulk_courant: C_bulk of §6.3 (0 steady)
double ubar[3]
its moving-frame velocity U'bar = sum U_i / sum kappa_i V
std::vector< double > wtG
bool sourceIsField
set_scalar_source was given an array (sourceField)
double sourceConst
volumetric source S (c/T), uniform part
double maxSolidD
max internal D_s' = Lam_s'/(C_s K) (the level rule)
CCField kqS
Krylov scratch, solid phase.
double rtol
max-norm relative residual tolerance (§5.1)
Kokkos::View< std::uint8_t *, CCMem > rungS
long solidVersion
geometry version of the record
Kokkos::View< double *[8], Kokkos::LayoutLeft, CCMem > wS
Kokkos::View< double *, CCMem > mtRcV
Kokkos::View< double *, CCMem > wtQV
double sealedSolidVolume
census sealed_solid_volume (D-WO7-1), physical
Kokkos::View< double *, CCMem > wtKV
std::vector< double > mtRc
internal per-body material (conjugate bodies)
Kokkos::View< double *, CCMem > cc
per facet: alpha G_c (conjugate facets, else 0)
Kokkos::View< double *, CCMem > cw
int mgLevels
levels the last solve's V-cycle used (census mg_levels)
long numFluxFaces
faces carrying flux (the implicit fraction's denominator)
Kokkos::View< std::uint8_t *, CCMem > conjF
1 on a facet of a conjugate body
double idt
1/dt' (0 steady)
CCField sourceField
or per cell (physical), when allocated
bool warnedBottom
the ScalarMG shallow-bottom warning was issued (once)
std::vector< double > wtQ
(internal k', g, q')
double gInt[3]
its G' = G hRef (c per internal length)
long numSolidUnknowns
census num_solid_unknowns (global)
std::vector< char > solidKey
the conjugate flag per body it was built for
CCField SAC
level-0 surrogate diagonal (bands + lumped wall)
Wall condition per body (§1.1, §8.1 set_scalar_wall), in the caller's PHYSICAL units; the conversion ...
int type
0 neumann, 1 dirichlet, 2 robin, 3 conjugate (WO-7)
double coefficient
robin: k (L/T)
double value
neumann: q (flux into the fluid, c L/T); dirichlet/robin: g
The block Lookup of cs::buildProbe for one facet's cell: unknown flags (haloed) at lattice offsets,...
The facet overlay (§3.5): SoA, facet index fastest. Offsets are LINEAR offsets on the block.
The per-body material of a conjugate scalar, internal units (§4.2): conj 1 on a conjugate body; lam =...
Kokkos::View< int *, CCMem > conj
Kokkos::View< double *, CCMem > lam
Kokkos::View< double *, CCMem > ck
Kokkos::View< double *, CCMem > rc
Kokkos::View< double *, CCMem > kp
G.x at the centre of extended-block cell j (physical; cellCentres' formula, unwrapped).
long sz
extended-block strides
double h[3]
the physical cell size
double org[3]
the physical lower corner of the global grid
double G[3]
the physical mean gradient (c/L)
double operator()(long j) const
long base[3]
og_a - g: global index of extended-block index 0
Device copy of the per-body wall table, resolved (instance override or default) and converted to inte...
Kokkos::View< double *, CCMem > k
Kokkos::View< double *, CCMem > gval
Kokkos::View< int *, CCMem > type
Kokkos::View< double *, CCMem > q
static constexpr double AC
static constexpr double F