43#ifndef PECLET_FLOW_GHOST_PROJECTION_HPP
44#define PECLET_FLOW_GHOST_PROJECTION_HPP
46#include <Kokkos_Core.hpp>
57#include "peclet/core/scheme/ghost_closure.hpp"
62using peclet::core::scheme::GP_THETA_MIN;
63using enum peclet::core::scheme::GpState;
64using peclet::core::scheme::GpFace;
65using peclet::core::scheme::GpState;
66using peclet::core::scheme::gpClassifyFace;
67using peclet::core::scheme::gpFillRow;
68using peclet::core::scheme::gpOrderWeights;
80 Kokkos::View<int*, Space>
cell;
83 Kokkos::View<int8_t*, Space>
state;
84 Kokkos::View<float*, Space>
th;
92 ov.
cell = Kokkos::View<int*, CCMem>(
"gp_cell", n);
93 ov.
rescale = Kokkos::View<float*, CCMem>(
"gp_rescale", n);
94 ov.
coupled = Kokkos::View<int8_t*, CCMem>(
"gp_coupled", n);
95 ov.
state = Kokkos::View<int8_t*, CCMem>(
"gp_state", 6 * n);
96 ov.
th = Kokkos::View<float*, CCMem>(
"gp_th", 6 * n);
97 ov.
w_bc = Kokkos::View<float*, CCMem>(
"gp_wbc", 6 * n);
98 ov.
w_n1 = Kokkos::View<float*, CCMem>(
"gp_wn1", 6 * n);
99 ov.
w_n2 = Kokkos::View<float*, CCMem>(
"gp_wn2", 6 * n);
100 ov.
wm_n1 = Kokkos::View<float*, CCMem>(
"gp_wmn1", 6 * n);
101 ov.
wm_n2 = Kokkos::View<float*, CCMem>(
"gp_wmn2", 6 * n);
107 return v < 0 ? v + n : v;
118 Kokkos::View<int*, CCMem> idMap, Kokkos::View<int, CCMem> counter,
123 Kokkos::deep_copy(
space, counter, 0);
124 Kokkos::deep_copy(
space, idMap, -1);
125 const bool hasEx =
tx.size() > 0;
127 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
128 Kokkos::parallel_for(
129 "peclet::flow::gp_build_overlay",
MD(
space, {0, 0, 0}, {
nn.x,
nn.y,
nn.z}),
131 auto S = [&](
int dx,
int dy,
int dz) {
135 return (
float)sdf(
i);
137 const float sc = S(0, 0, 0);
140 float F[3][4],
Cq[3][5];
141 const int d[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
142 for (
int a = 0; a < 3; ++a) {
143 for (
int q = -2;
q <= 2; ++
q)
144 Cq[a][
q + 2] = S(
q * d[a][0],
q * d[a][1],
q * d[a][2]);
145 for (
int m = -1; m <= 2; ++m)
146 F[a][m + 1] = 0.5f * (
Cq[a][m + 1] +
Cq[a][m + 2]);
150 for (
int a = 0; a < 3; ++a)
151 clean =
clean &&
F[a][1] >= 0.0f &&
F[a][2] >= 0.0f &&
Cq[a][1] >= 0.0f &&
155 const int inner = x + y *
nn.x + z *
nn.x *
nn.y;
163 for (
int a = 0; a < 3; ++a) {
164 auto T = [&](
int m) {
165 const int cx = a == 0 ?
gpWrap(x + m,
nn.x) : x;
166 const int cy = a == 1 ?
gpWrap(y + m,
nn.y) : y;
167 const int cz = a == 2 ?
gpWrap(z + m,
nn.z) : z;
170 exStd[2 * a + 1] = 1.0f -
T(0);
176 const int slot = Kokkos::atomic_fetch_add(&counter(), 1);
184 for (
int k = 0;
k < 6; ++
k) {
198 Kokkos::deep_copy(
cnt, counter);
208 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
209 Kokkos::parallel_for(
210 "peclet::flow::gp_binary_openness",
MD(
space, {0, 0, 0}, {ext.
x, ext.
y, ext.
z}),
214 auto cl = [](
int v,
int n) {
return v < 0 ? 0 : (v >= n ? n - 1 : v); };
215 auto S = [&](
int xx,
int yy,
int zz) {
218 const double sc = S(x, y, z);
219 const double sw = S(x - 1, y, z),
ss = S(x, y - 1, z),
sb = S(x, y, z - 1);
220 ox(
i) = (0.5 * (
sw + sc) >= 0.0 &&
sw >= 0.0 && sc >= 0.0) ? 1.0 : 0.0;
221 oy(
i) = (0.5 * (
ss + sc) >= 0.0 &&
ss >= 0.0 && sc >= 0.0) ? 1.0 : 0.0;
222 oz(
i) = (0.5 * (
sb + sc) >= 0.0 &&
sb >= 0.0 && sc >= 0.0) ? 1.0 : 0.0;
240 Kokkos::parallel_for(
241 "peclet::flow::gp_apply_delta", Kokkos::RangePolicy<CCExec>(
space, 0,
nOv),
243 const int inner = ov.
cell(s);
244 const int ix = inner %
nn.x,
iy = (inner /
nn.x) %
nn.y,
iz = inner / (
nn.x *
nn.y);
245 auto X = [&](
int a,
int q) {
255 for (
int k = 0;
k < 6; ++
k) {
260 const int sgn = (
k & 1) ? -1 : 1;
261 const int mn = (
k & 1) ? 1 : 0;
262 const int mf = (
k & 1) ? 2 : -1;
268 const double rho = ov.
rescale(s);
286 Kokkos::parallel_for(
287 "peclet::flow::gp_diverg_delta", Kokkos::RangePolicy<CCExec>(
space, 0,
nOv),
289 const int inner = ov.
cell(s);
290 const int ix = inner %
nn.x,
iy = (inner /
nn.x) %
nn.y,
iz = inner / (
nn.x *
nn.y);
291 auto U = [&](
int a,
int m) {
297 return a == 0 ? u(
i) : (a == 1 ? v(
i) : w(
i));
302 for (
int k = 0;
k < 6; ++
k) {
307 const int sgn = (
k & 1) ? -1 : 1;
308 const int mg = (
k & 1) ? 0 : 1;
309 const int mn = (
k & 1) ? 1 : 0;
310 const int mf = (
k & 1) ? 2 : -1;
flow — portable (Kokkos) Robust-Scaled cut-cell IBM primitives + per-cut-cell overlay build.
flow — the gauge-exact directional cell-centre pressure gradient.
flow — portable (Kokkos) cut-cell pressure-operator face openness from an SDF.
void gpApplyDelta(CCField y, CCConst x, const GpOverlay &ov, int nOv, C3 nn, C3 extY, int gbY, C3 extX, int gbX, bool useGhost=false)
Overlay matvec correction: y(r) = rho_r * (y(r) + closure-face phi terms), where y currently holds th...
void gpBinaryOpenness(CCField ox, CCField oy, CCField oz, CCConst sdf, C3 ext)
Binary openness for the symmetric MG surrogate, on the extended-block layout of buildOpenness: o(face...
GpOverlay gpMakeOverlay(long n)
void ibmFillEntry(const OV &o, int list_idx, int c_idx, float sdf_c, const float sdf_n[6], int bc_type, const float *thEx)
Kokkos::View< double *, CCMem > CCField
void gpDivergDelta(CCField d, CCConst u, CCConst v, CCConst w, const GpOverlay &ov, int nOv, C3 nn, C3 extb, int gb, bool useGhost=false)
Overlay divergence correction: d(r) = rho_r * (d(r) + closure/BC/explicit face values),...
Kokkos::DefaultExecutionSpace CCExec
Kokkos::View< const double *, CCMem > CCConst
int buildGpOverlay(CCConst sdf, C3 ext, int g, C3 nn, const GpOverlay &ov, Kokkos::View< int *, CCMem > idMap, Kokkos::View< int, CCMem > counter, int matrixOrder=2, int rhsOrder=2, CCConst tx=CCConst(), CCConst ty=CCConst(), CCConst tz=CCConst(), bool useGhost=false)
Build the overlay over the inner grid nn from the cell-centered sdf on the extended block (ext,...
Kokkos::View< int8_t *, Space > state
Kokkos::View< float *, Space > w_n1
Kokkos::View< int *, Space > cell
Kokkos::View< float *, Space > w_n2
Kokkos::View< float *, Space > wm_n1
Kokkos::View< float *, Space > rescale
Kokkos::View< float *, Space > th
Kokkos::View< int8_t *, Space > coupled
Kokkos::View< float *, Space > wm_n2
Kokkos::View< float *, Space > w_bc
static constexpr double F