65#ifndef PECLET_FLOW_GHOST_PROJECTION_HPP
66#define PECLET_FLOW_GHOST_PROJECTION_HPP
69#include <Kokkos_Core.hpp>
79#include "peclet/core/scheme/ghost_closure.hpp"
84using peclet::core::scheme::GP_THETA_MIN;
85using enum peclet::core::scheme::GpState;
86using peclet::core::scheme::gpClassifyFace;
87using peclet::core::scheme::GpFace;
88using peclet::core::scheme::gpFillRow;
89using peclet::core::scheme::gpOrderWeights;
90using peclet::core::scheme::GpState;
100template <
class Space,
class Real =
float>
102 Kokkos::View<int*, Space>
cell;
106 Kokkos::View<Real*, Space>
th;
114template <
class Real =
float>
117 ov.cell = Kokkos::View<int*, CCMem>(
"gp_cell", n);
118 ov.rescale = Kokkos::View<Real*, CCMem>(
"gp_rescale", n);
119 ov.coupled = Kokkos::View<int8_t*, CCMem>(
"gp_coupled", n);
120 ov.state = Kokkos::View<int8_t*, CCMem>(
"gp_state", 6 * n);
121 ov.th = Kokkos::View<Real*, CCMem>(
"gp_th", 6 * n);
122 ov.w_bc = Kokkos::View<Real*, CCMem>(
"gp_wbc", 6 * n);
123 ov.w_n1 = Kokkos::View<Real*, CCMem>(
"gp_wn1", 6 * n);
124 ov.w_n2 = Kokkos::View<Real*, CCMem>(
"gp_wn2", 6 * n);
125 ov.wm_n1 = Kokkos::View<Real*, CCMem>(
"gp_wmn1", 6 * n);
126 ov.wm_n2 = Kokkos::View<Real*, CCMem>(
"gp_wmn2", 6 * n);
132 return v < 0 ? v + n : v;
144 Kokkos::View<int*, CCMem> idMap, Kokkos::View<int, CCMem> counter,
148 Kokkos::deep_copy(
space, counter, 0);
149 Kokkos::deep_copy(
space, idMap, -1);
150 const bool hasEx =
tx.size() > 0;
153 Kokkos::parallel_for(
154 "peclet::flow::gp_build_overlay",
MD(
space, {0, 0, 0}, {
nn.x,
nn.y,
nn.z}),
156 auto S = [&](
int dx,
int dy,
int dz) {
160 return (
float)sdf(i);
162 const float sc = S(0, 0, 0);
165 float F[3][4],
Cq[3][5];
166 const int d[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
167 for (
int a = 0; a < 3; ++a) {
168 for (
int q = -2; q <= 2; ++q)
169 Cq[a][q + 2] = S(q * d[a][0], q * d[a][1], q * d[a][2]);
170 for (
int m = -1; m <= 2; ++m)
171 F[a][m + 1] = 0.5f * (
Cq[a][m + 1] +
Cq[a][m + 2]);
175 for (
int a = 0; a < 3; ++a)
177 clean &&
F[a][1] >= 0.0f &&
F[a][2] >= 0.0f &&
Cq[a][1] >= 0.0f &&
Cq[a][3] >= 0.0f;
180 const int inner = x + y *
nn.x + z *
nn.x *
nn.y;
188 for (
int a = 0; a < 3; ++a) {
189 auto T = [&](
int m) {
190 const int cx = a == 0 ?
gpWrap(x + m,
nn.x) : x;
191 const int cy = a == 1 ?
gpWrap(y + m,
nn.y) : y;
192 const int cz = a == 2 ?
gpWrap(z + m,
nn.z) : z;
194 return (
float)(*ta[a])(
ii);
196 exStd[2 * a + 1] = 1.0f - T(0);
202 const int slot = Kokkos::atomic_fetch_add(&counter(), 1);
207 ov.cell(slot) = inner;
208 ov.rescale(slot) = 1.0f;
209 ov.coupled(slot) = 1;
210 for (
int k = 0; k < 6; ++k) {
212 ov.th(slot * 6 + k) = 1.0f;
213 ov.w_bc(slot * 6 + k) = 0.0f;
214 ov.w_n1(slot * 6 + k) = 0.0f;
215 ov.w_n2(slot * 6 + k) = 0.0f;
216 ov.wm_n1(slot * 6 + k) = 0.0f;
217 ov.wm_n2(slot * 6 + k) = 0.0f;
224 Kokkos::deep_copy(cnt, counter);
235 Kokkos::parallel_for(
236 "peclet::flow::gp_binary_openness",
MD(
space, {0, 0, 0}, {ext.
x, ext.
y, ext.
z}),
238 const long sy = ext.
x, sz = (
long)ext.
x * ext.
y;
239 const long i = (
long)x + (
long)y * sy + (
long)z * sz;
240 auto cl = [](
int v,
int n) {
return v < 0 ? 0 : (v >= n ? n - 1 : v); };
241 auto S = [&](
int xx,
int yy,
int zz) {
242 return sdf((
long)
cl(
xx, ext.
x) + (
long)
cl(
yy, ext.
y) * sy + (
long)
cl(
zz, ext.
z) * sz);
244 const double sc = S(x, y, z);
245 const double sw = S(x - 1, y, z), ss = S(x, y - 1, z),
sb = S(x, y, z - 1);
246 ox(i) = (0.5 * (
sw + sc) >= 0.0 &&
sw >= 0.0 && sc >= 0.0) ? 1.0 : 0.0;
247 oy(i) = (0.5 * (ss + sc) >= 0.0 && ss >= 0.0 && sc >= 0.0) ? 1.0 : 0.0;
248 oz(i) = (0.5 * (
sb + sc) >= 0.0 &&
sb >= 0.0 && sc >= 0.0) ? 1.0 : 0.0;
267 Kokkos::parallel_for(
268 "peclet::flow::gp_apply_delta", Kokkos::RangePolicy<CCExec>(
space, 0,
nOv),
270 const int inner = ov.cell(s);
271 const int ix = inner %
nn.x,
iy = (inner /
nn.x) %
nn.y,
iz = inner / (
nn.x *
nn.y);
272 auto X = [&](
int a,
int q) {
276 return x((
long)(cx +
gbX) + (
long)(cy +
gbX) *
extX.x +
282 for (
int k = 0; k < 6; ++k) {
283 const int8_t st = ov.state(s * 6 + k);
287 const int sgn = (k & 1) ? -1 : 1;
288 const int mn = (k & 1) ? 1 : 0;
289 const int mf = (k & 1) ? 2 : -1;
290 const double w1 = ov.wm_n1(s * 6 + k),
w2 = ov.wm_n2(s * 6 + k);
291 delta += sgn *
w1 * (X(a,
mn - 1) - X(a,
mn));
293 delta += sgn *
w2 * (X(a,
mf - 1) - X(a,
mf));
295 const double rho = ov.rescale(s);
296 y(r) = ov.coupled(s) ? rho * (y(r) + delta) : 0.0;
314 Kokkos::parallel_for(
315 "peclet::flow::gp_diverg_delta", Kokkos::RangePolicy<CCExec>(
space, 0,
nOv),
317 const int inner = ov.cell(s);
318 const int ix = inner %
nn.x,
iy = (inner /
nn.x) %
nn.y,
iz = inner / (
nn.x *
nn.y);
319 auto U = [&](
int a,
int m) {
325 return a == 0 ? u(i) : (a == 1 ? v(i) : w(i));
330 for (
int k = 0; k < 6; ++k) {
331 const int8_t st = ov.state(s * 6 + k);
335 const int sgn = (k & 1) ? -1 : 1;
336 const int mg = (k & 1) ? 0 : 1;
337 const int mn = (k & 1) ? 1 : 0;
338 const int mf = (k & 1) ? 2 : -1;
340 dd += sgn *
U(a, mg);
345 double val = ov.w_n1(s * 6 + k) *
U(a,
mn);
347 val += ov.w_n2(s * 6 + k) *
U(a,
mf);
350 d(r) = ov.coupled(s) ? ov.rescale(s) * dd : 0.0;
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 gpDivergDelta(CCField d, CCConst u, CCConst v, CCConst w, const GpOverlayReal< Real > &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),...
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...
GpOverlayReal< Real > gpMakeOverlay(long n)
void gpApplyDelta(CCField y, CCConst x, const GpOverlayReal< Real > &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...
int buildGpOverlay(CCConst sdf, C3 ext, int g, C3 nn, const GpOverlayReal< Real > &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< double *, CCMem > CCField
Kokkos::DefaultExecutionSpace CCExec
Kokkos::View< const double *, CCMem > CCConst
flow — the multidimensional iteration policies: iteration order follows storage.
Kokkos::View< Real *, Space > th
Kokkos::View< int8_t *, Space > state
Kokkos::View< Real *, Space > w_n2
Kokkos::View< int8_t *, Space > coupled
Kokkos::View< int *, Space > cell
Kokkos::View< Real *, Space > wm_n2
Kokkos::View< Real *, Space > rescale
Kokkos::View< Real *, Space > w_n1
Kokkos::View< Real *, Space > w_bc
Kokkos::View< Real *, Space > wm_n1
static constexpr double F
static constexpr double U