12#ifndef PECLET_FLOW_MAC_APPROX_PROJECTION_HPP
13#define PECLET_FLOW_MAC_APPROX_PROJECTION_HPP
15#include <Kokkos_Core.hpp>
23using MConst = Kokkos::View<const float*, CCMem>;
34 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
36 "peclet::flow::center_to_face",
MD(
space, {1, 1, 1}, {e.x, e.y, e.z}),
38 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
40 uf(
i) = 0.5 * (U(
i) + U(
i -
sx));
69 double xcen,
long idx[3],
double w[3]) {
70 const double sm = sdf(
i -
sa),
sp = sdf(
i);
71 const bool fm =
sm >= 0.0,
fp =
sp >= 0.0;
83 double th = sc / (sc -
ss);
84 th = th < 1e-4 ? 1e-4 : (th > 1.0 ? 1.0 : th);
92 const double xe = (
xcen >= 0.0) ?
xcen : th - 0.5;
96 const int up =
fp ? 1 : -1;
101 w[0] = Kokkos::fmin(
xe / th, 2.0);
105 const double wc = th * th / (th * th + 0.0225);
106 const double w2 =
ok2 ? 0.25 : 0.0;
107 const double xc = th,
xf = th + 1.0,
xg = th + 2.0;
132 for (
int k = 0;
k < n; ++
k)
133 v += w[
k] * U(
idx[
k]);
145 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
146 Kokkos::parallel_for(
147 "peclet::flow::face_centroid_dist",
MD(
space, {1, 1, 1}, {e.x, e.y, e.z}),
149 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
153 const double fc[3][3] = {{x - 0.5, (
double)y, (
double)z},
154 {(
double)x, y - 0.5, (
double)z},
155 {(
double)x, (
double)y, z - 0.5}};
156 const long st[3] = {
sx,
sy,
sz};
158 for (
int a = 0; a < 3; ++a) {
159 const double sm = sdf(
i - st[a]),
sp = sdf(
i);
160 if ((
sm >= 0.0) == (
sp >= 0.0)) {
164 const double dir = (
sm < 0.0) ? -1.0 : 1.0;
165 const int t1 = (a + 1) % 3,
t2 = (a + 2) % 3;
166 double c1 = 0.0, c2 = 0.0;
168 for (
int j1 = 0; j1 < 4; ++j1)
169 for (
int j2 = 0;
j2 < 4; ++
j2) {
170 const double o1 = -0.375 + 0.25 * j1,
o2 = -0.375 + 0.25 *
j2;
171 double p[3] = {fc[a][0], fc[a][1], fc[a][2]};
184 double p0[3] = {fc[a][0], fc[a][1], fc[a][2]};
187 double p1[3] = {p0[0], p0[1], p0[2]};
189 const double s0 =
ccSampleExt(sdf, e, p0[0], p0[1], p0[2]);
191 double d = (s0 > 0.0 && s0 - s1 > 1e-12) ? s0 / (s0 - s1) : 0.0;
192 out[a](
i) = d < 0.0 ? 0.0 : (d > 2.0 ? 2.0 : d);
207 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
208 Kokkos::parallel_for(
209 "peclet::flow::center_to_face_wall",
MD(
space, {1, 1, 1}, {e.x, e.y, e.z}),
211 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
236 bool useCen,
int axis,
C3 e,
int g) {
238 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
239 Kokkos::parallel_for(
240 "peclet::flow::transpose_grad_wall",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
242 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
244 const long sa = (axis == 0) ?
sx : (axis == 1) ?
sy :
sz;
245 const int eA = (axis == 0) ? e.x : (axis == 1) ? e.y : e.z;
246 const int ca = (axis == 0) ? x : (axis == 1) ? y : z;
250 for (
int m = -2; m <= 3; ++m) {
251 const int cf = ca + m;
254 const long f =
i + (
long)m *
sa;
256 for (
int k = 0;
k < n; ++
k)
258 acc += w[
k] * o(f) * (p(f) - p(f -
sa));
270 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
271 Kokkos::parallel_for(
272 "peclet::flow::cell_fraction",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
274 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
275 const double sc = sdf(
i);
277 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
278 const bool f0 = sc >= 0.0;
279 const bool cut = (sdf(
i +
sx) >= 0.0) !=
f0 || (sdf(
i -
sx) >= 0.0) !=
f0 ||
280 (sdf(
i +
sy) >= 0.0) !=
f0 || (sdf(
i -
sy) >= 0.0) !=
f0 ||
281 (sdf(
i +
sz) >= 0.0) !=
f0 || (sdf(
i -
sz) >= 0.0) !=
f0;
283 cs(
i) = sc >= 0.0 ? 1.0 : 0.0;
287 for (
int j0 = 0; j0 < 4; ++j0)
288 for (
int j1 = 0; j1 < 4; ++j1)
289 for (
int j2 = 0;
j2 < 4; ++
j2) {
290 const double o0 = -0.375 + 0.25 * j0,
o1 = -0.375 + 0.25 * j1,
291 o2 = -0.375 + 0.25 *
j2;
307 CCConst oz,
double mu,
double idt,
C3 e,
int g) {
309 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
310 Kokkos::parallel_for(
311 "peclet::flow::fv_viscous_apply",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
313 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
314 const long st[3] = {
sx,
sy,
sz};
318 double diag = 0.0,
offs = 0.0,
aw = 0.0;
319 for (
int a = 0; a < 3; ++a) {
320 const double om =
oa[a](
i), op =
oa[a](
i + st[a]);
324 offs +=
om * U(
i - st[a]) + op * U(
i + st[a]);
325 aw += (
W[a] < 0.0 ? -
W[a] :
W[a]);
330 double nx = 0.5 * (sdf(
i +
sx) - sdf(
i -
sx));
331 double ny = 0.5 * (sdf(
i +
sy) - sdf(
i -
sy));
332 double nz = 0.5 * (sdf(
i +
sz) - sdf(
i -
sz));
333 double nn = Kokkos::sqrt(nx * nx + ny * ny + nz * nz);
338 const double nv[3] = {nx, ny, nz};
339 const double sdi = sdf(
i);
343 auto cl = [](
double v,
double hi) {
return v < 1.0 ? 1.0 : (v >
hi ?
hi : v); };
344 const double px =
cl(x -
sdi * nx, e.x - 2.0);
345 const double py =
cl(y -
sdi * ny, e.y - 2.0);
346 const double pz =
cl(z -
sdi * nz, e.z - 2.0);
347 for (
int a = 0; a < 3; ++a) {
348 const double sg =
nv[a] >= 0.0 ? 1.0 : -1.0;
350 py + (a == 1 ? sg : 0.0),
pz + (a == 2 ? sg : 0.0));
352 ccSampleExt(U, e,
px + (a == 0 ? 2.0 * sg : 0.0),
py + (a == 1 ? 2.0 * sg : 0.0),
353 pz + (a == 2 ? 2.0 * sg : 0.0));
354 wall +=
W[a] * sg * (2.0 *
u1 - 0.5 *
u2);
369 return (
a1 * (
xx - 1.0) +
a3 * (
xx + 1.0)) *
xx * 0.5 -
a2 * (
xx - 1.0) * (
xx + 1.0);
384 int z,
double nx,
double ny,
double nz,
385 double px,
double py,
double pz) {
386 const double nv[3] = {nx, ny, nz},
pv[3] = {
px,
py,
pz};
387 const int ci[3] = {x, y, z}, ext[3] = {e.x, e.y, e.z};
388 const long st[3] = {1, (
long)e.x, (
long)e.x * e.y};
390 double best = Kokkos::fabs(
nv[0]);
391 if (Kokkos::fabs(
nv[1]) >
best) {
392 best = Kokkos::fabs(
nv[1]);
395 if (Kokkos::fabs(
nv[2]) >
best)
397 const int t1 = (
da + 1) % 3,
t2 = (
da + 2) % 3;
398 const double sgn =
nv[
da] >= 0.0 ? 1.0 : -1.0;
399 auto clampi = [](
int v,
int n) {
return v < 0 ? 0 : (v >= n ? n - 1 : v); };
400 auto rd = [](
double v) {
401 double r = v >= 0.0 ? Kokkos::floor(v + 0.5) : Kokkos::ceil(v - 0.5);
402 return r > 1.0 ? 1.0 : (r < -1.0 ? -1.0 : r);
406 for (
int l = 0;
l < 2; ++
l) {
407 const int io = (
l + 1) * (
int)
sgn;
414 for (
int dk = -1; dk <= 1; ++dk)
415 for (
int dj = -1;
dj <= 1; ++
dj) {
423 sf[
dj + 1][dk + 1] = sdf(
idx) >= 0.0;
426 for (
int a2 = 0;
a2 < 3; ++
a2)
427 for (
int b2 = 0;
b2 < 3; ++
b2)
429 const bool home = sf[1][1];
433 double vbl =
vv[1][1];
435 const int fp =
ly >= 0.0 ? 2 : 0,
fm =
ly >= 0.0 ? 0 : 2;
442 const int fp =
lz >= 0.0 ? 2 : 0,
fm =
lz >= 0.0 ? 0 : 2;
454 return (
v0 *
d1 / d0 -
v1 * d0 /
d1) / (
d1 - d0);
457 return vL[0] /
dL[0];
458 double d0 = Kokkos::fabs(
pv[
da] /
nv[
da]);
469 const long ii = (
long)
ci[0] * st[0] + (
long)
ci[1] * st[1] + (
long)
ci[2] * st[2];
483 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
484 Kokkos::parallel_for(
485 "peclet::flow::embed_viscous_apply",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
487 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
488 const long st[3] = {
sx,
sy,
sz};
492 double diag = 0.0,
offs = 0.0;
493 for (
int a = 0; a < 3; ++a) {
494 const double om =
oa[a](
i), op =
oa[a](
i + st[a]);
497 offs +=
om * U(
i - st[a]) + op * U(
i + st[a]);
499 const double area = Kokkos::sqrt(
Wv[0] *
Wv[0] +
Wv[1] *
Wv[1] +
Wv[2] *
Wv[2]);
502 double nx = 0.5 * (sdf(
i +
sx) - sdf(
i -
sx));
503 double ny = 0.5 * (sdf(
i +
sy) - sdf(
i -
sy));
504 double nz = 0.5 * (sdf(
i +
sz) - sdf(
i -
sz));
505 const double nn = Kokkos::sqrt(nx * nx + ny * ny + nz * nz);
510 const double sdi = sdf(
i);
511 const double dudn =
embedDirichletGradient(U, sdf, e, x, y, z, nx, ny, nz, -
sdi * nx,
526 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
527 Kokkos::parallel_for(
528 "peclet::flow::stencil_matvec",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
530 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
541 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
542 Kokkos::parallel_for(
543 "peclet::flow::subtract_field",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
545 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y;
560 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
561 Kokkos::parallel_for(
562 "peclet::flow::center_grad_open",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
564 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
566 const long sa = (axis == 0) ?
sx : (axis == 1) ?
sy :
sz;
567 const double om = o(
i), op = o(
i +
sa);
568 out(
i) = (
om * (p(
i) - p(
i -
sa)) + op * (p(
i +
sa) - p(
i))) / (
om + op + 1e-12);
584 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
585 Kokkos::parallel_for(
586 "peclet::flow::center_grad_aperture",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
588 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
590 const long sa = (axis == 0) ?
sx : (axis == 1) ?
sy :
sz;
591 out(
i) = 0.5 * (o(
i) * (p(
i) - p(
i -
sa)) + o(
i +
sa) * (p(
i +
sa) - p(
i)));
604 int axis,
C3 e,
int g) {
606 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
607 Kokkos::parallel_for(
608 "peclet::flow::center_grad_aperture_scaled",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
610 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
612 const long sa = (axis == 0) ?
sx : (axis == 1) ?
sy :
sz;
613 CCConst o = (axis == 0) ? ox : (axis == 1) ? oy : oz;
617 out(
i) = (6.0 /
osum) * 0.5 *
618 (o(
i) * (p(
i) - p(
i -
sa)) + o(
i +
sa) * (p(
i +
sa) - p(
i)));
633 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
634 Kokkos::parallel_for(
635 "peclet::flow::center_grad_open_capped",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
637 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
639 const long sa = (axis == 0) ?
sx : (axis == 1) ?
sy :
sz;
640 const double om = o(
i), op = o(
i +
sa);
641 double den =
om + op;
644 out(
i) = (
om * (p(
i) - p(
i -
sa)) + op * (p(
i +
sa) - p(
i))) /
den;
654 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
655 Kokkos::parallel_for(
656 "peclet::flow::correct_center_open",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
658 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
687 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
688 Kokkos::parallel_for(
689 "peclet::flow::correct_center",
MD(
space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
691 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
693 const double gm_x = (ox(
i) > 1e-12) ? (phi(
i) - phi(
i -
sx)) : 0.0;
694 const double gp_x = (ox(
i +
sx) > 1e-12) ? (phi(
i +
sx) - phi(
i)) : 0.0;
695 const double gm_y = (oy(
i) > 1e-12) ? (phi(
i) - phi(
i -
sy)) : 0.0;
696 const double gp_y = (oy(
i +
sy) > 1e-12) ? (phi(
i +
sy) - phi(
i)) : 0.0;
697 const double gm_z = (oz(
i) > 1e-12) ? (phi(
i) - phi(
i -
sz)) : 0.0;
698 const double gp_z = (oz(
i +
sz) > 1e-12) ? (phi(
i +
sz) - phi(
i)) : 0.0;
flow — portable (Kokkos) cut-cell pressure-operator face openness from an SDF.
void transposeGradWallAware(CCField out, CCConst p, CCConst sdf, CCConst o, CCConst xc, bool useCen, int axis, C3 e, int g)
void projectCorrectCenterOpen(CCField u, CCField v, CCField w, CCConst phi, CCConst ox, CCConst oy, CCConst oz, C3 e, int g)
double eQuad(double xx, double a1, double a2, double a3)
void buildFaceCentroidDist(CCField xcx, CCField xcy, CCField xcz, CCConst sdf, C3 e)
void subtractField(CCField u, CCConst d, C3 e, int g)
void stencilMatvec(CCField y, CCConst u, MConst AC, MConst AW, MConst AE, MConst AS, MConst AN, MConst AB, MConst AT, C3 e, int g)
void buildCellFraction(CCField cs, CCConst sdf, C3 e, int g)
void centerGradApertureScaled(CCField out, CCConst p, CCConst ox, CCConst oy, CCConst oz, int axis, C3 e, int g)
double embedDirichletGradient(CCConst U, CCConst sdf, C3 e, int x, int y, int z, double nx, double ny, double nz, double px, double py, double pz)
void centerToFaceWallAware(CCField uf, CCField vf, CCField wf, CCConst U, CCConst V, CCConst W, CCConst sdf, CCConst xcx, CCConst xcy, CCConst xcz, bool useCen, C3 e, int g)
void fvViscousApply(CCField Lu, CCConst U, CCConst sdf, CCConst cs, CCConst ox, CCConst oy, CCConst oz, double mu, double idt, C3 e, int g)
void centerGradOpen(CCField out, CCConst p, CCConst o, int axis, C3 e, int g)
void centerGradAperture(CCField out, CCConst p, CCConst o, int axis, C3 e, int g)
void embedViscousApply(CCField Lu, CCConst U, CCConst sdf, CCConst cs, CCConst ox, CCConst oy, CCConst oz, double mu, double idt, C3 e, int g)
void centerToFace(CCField uf, CCField vf, CCField wf, CCConst U, CCConst V, CCConst W, C3 e, int g)
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)
int wallAwareFaceStencil(CCConst sdf, long i, long sa, int cFace, int eAxis, double xcen, long idx[3], double w[3])
Kokkos::View< double *, CCMem > CCField
Kokkos::DefaultExecutionSpace CCExec
void projectCorrectCenter(CCField u, CCField v, CCField w, CCConst phi, CCConst ox, CCConst oy, CCConst oz, C3 e, int g)
Kokkos::View< const float *, CCMem > MConst
double ccSampleExt(CCConst sdf, C3 ext, double x, double y, double z)
double wallAwareFaceValue(CCConst U, CCConst sdf, long i, long sa, int cFace, int eAxis, double xcen)
void centerGradOpenCapped(CCField out, CCConst p, CCConst o, int axis, double omin, C3 e, int g)
Kokkos::View< const double *, CCMem > CCConst
static constexpr double AC