18#ifndef PECLET_FLOW_MAC_VELOCITY_MG_HPP
19#define PECLET_FLOW_MAC_VELOCITY_MG_HPP
22#include <Kokkos_Core.hpp>
36 const bool hasPin = (pin.extent(0) != 0);
37 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
39 "peclet::flow::vmg_resid", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
40 KOKKOS_LAMBDA(
int lx,
int ly,
int lz) {
41 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
42 const long i = (long)lx + (
long)ly * sy + (long)lz * sz;
43 if (hasPin && pin(i) > 0.5) {
47 const double Ax = (double)
AC(i) * x(i) + (double)AE(i) * x(i + sx) +
48 (double)AW(i) * x(i - sx) + (double)AN(i) * x(i + sy) +
49 (double)AS(i) * x(i - sy) + (double)AT(i) * x(i + sz) +
50 (double)AB(i) * x(i - sz);
59 C3 finner,
C3 ratio,
double eps) {
61 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
63 "peclet::flow::vmg_prolong_masked", MD(space, {0, 0, 0}, {finner.
x, finner.
y, finner.
z}),
64 KOKKOS_LAMBDA(
int ifx,
int ify,
int ifz) {
66 (long)(ifx + g) + (long)(ify + g) * fext.
x + (long)(ifz + g) * (long)fext.
x * fext.
y;
69 const double cx = (ratio.
x == 2) ? 0.5 * ifx - 0.25 + g : ifx + g;
70 const double cy = (ratio.
y == 2) ? 0.5 * ify - 0.25 + g : ify + g;
71 const double cz = (ratio.
z == 2) ? 0.5 * ifz - 0.25 + g : ifz + g;
72 const double fxw = Kokkos::floor(cx), fyw = Kokkos::floor(cy), fzw = Kokkos::floor(cz);
73 const double wx = cx - fxw, wy = cy - fyw, wz = cz - fzw;
74 const int x0 = (int)fxw, y0 = (
int)fyw, z0 = (int)fzw;
75 const long sy = cext.
x, sz = (long)cext.
x * cext.
y;
76 auto C = [&](
int xx,
int yy,
int zz) {
77 return coarse((
long)xx + (
long)yy * sy + (
long)zz * sz);
79 const double c00 = C(x0, y0, z0) * (1 - wx) + C(x0 + 1, y0, z0) * wx;
80 const double c10 = C(x0, y0 + 1, z0) * (1 - wx) + C(x0 + 1, y0 + 1, z0) * wx;
81 const double c01 = C(x0, y0, z0 + 1) * (1 - wx) + C(x0 + 1, y0, z0 + 1) * wx;
82 const double c11 = C(x0, y0 + 1, z0 + 1) * (1 - wx) + C(x0 + 1, y0 + 1, z0 + 1) * wx;
83 const double c0 = c00 * (1 - wy) + c10 * wy, c1 = c01 * (1 - wy) + c11 * wy;
84 fine(fi) += c0 * (1 - wz) + c1 * wz;
92 CCConst theta,
C3 e,
int g,
double bx,
double by,
double bz,
93 double thresh,
double idiag) {
95 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
97 "peclet::flow::vmg_staircase", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
98 KOKKOS_LAMBDA(
int lx,
int ly,
int lz) {
99 const long i = (long)lx + (
long)ly * e.x + (long)lz * (
long)e.x * e.y;
103 AW(i) = AE(i) = AS(i) = AN(i) = AB(i) = AT(i) = 0.0f;
106 AC(i) = (float)(idiag + 2.0 * (bx + by + bz));
107 AW(i) = (float)(-bx);
108 AE(i) = (float)(-bx);
109 AS(i) = (float)(-by);
110 AN(i) = (float)(-by);
111 AB(i) = (float)(-bz);
112 AT(i) = (float)(-bz);
123 double bz,
double fouw,
double sx,
double sy,
double sz,
double idiag) {
125 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
126 Kokkos::parallel_for(
127 "peclet::flow::vmg_adv_coarse", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
128 KOKKOS_LAMBDA(
int x,
int y,
int z) {
129 const long i = (long)x + (
long)y * e.x + (long)z * (
long)e.x * e.y;
130 double cC = idiag + 2.0 * (bx + by + bz), cxm = -bx, cxp = -bx, cym = -by, cyp = -by,
131 czm = -bz, czp = -bz;
132 sadv::ViewAcc Ua{U, e.x, e.y}, Va{V, e.x, e.y}, Wa{W, e.x, e.y};
133 sadv::fou_operator_aniso(comp, x, y, z, Ua, Va, Wa, fouw, sx, sy, sz, cC, cxm, cxp, cym,
149 double by,
double bz,
double idiag) {
151 const std::size_t n = (std::size_t)e.x * e.y * e.z;
152 const float c = (float)(idiag + 2.0 * (bx + by + bz)), nx = (
float)(-bx), ny = (
float)(-by),
154 Kokkos::parallel_for(
155 "peclet::flow::vmg_const_aniso", Kokkos::RangePolicy<CCExec>(space, 0, n),
156 KOKKOS_LAMBDA(std::size_t i) {
173 int dims[3] = {e.x, e.y, e.z};
174 long st[3] = {1, e.x, (long)e.x * e.y};
175 const int b = (a + 1) % 3, c = (a + 2) % 3;
176 const long sa = st[a], sb = st[b], sc = st[c];
177 const int bic = (s == 0) ? g : (dims[a] - g - 1);
178 Kokkos::parallel_for(
179 "peclet::flow::vmg_bc_fold",
180 Kokkos::MDRangePolicy<
CCExec, Kokkos::Rank<2>>(space, {0, 0}, {dims[b], dims[c]}),
181 KOKKOS_LAMBDA(
int p0,
int p1) {
182 const long i = (long)p0 * sb + (
long)p1 * sc + (long)bic * sa;
183 AC(i) = (float)((
double)
AC(i) + beta);
192 int dims[3] = {e.x, e.y, e.z};
193 long st[3] = {1, e.x, (long)e.x * e.y};
194 const int b = (a + 1) % 3, c = (a + 2) % 3;
195 const long sa = st[a], sb = st[b], sc = st[c];
196 const int na = dims[a];
197 Kokkos::parallel_for(
198 "peclet::flow::vmg_fill_bc_ghost",
199 Kokkos::MDRangePolicy<
CCExec, Kokkos::Rank<2>>(space, {0, 0}, {dims[b], dims[c]}),
200 KOKKOS_LAMBDA(
int p0,
int p1) {
201 const long base = (long)p0 * sb + (
long)p1 * sc;
203 const double v = dirichlet ? 0.0 : x(base + (
long)g * sa);
204 for (
int ia = 0; ia < g; ++ia)
205 x(base + (
long)ia * sa) = v;
207 const double v = dirichlet ? 0.0 : x(base + (
long)(na - g - 1) * sa);
208 for (
int ia = na - g; ia < na; ++ia)
209 x(base + (
long)ia * sa) = v;
218 int dims[3] = {e.x, e.y, e.z};
219 long st[3] = {1, e.x, (long)e.x * e.y};
220 const int b = (axis + 1) % 3, c = (axis + 2) % 3;
221 const long sa = st[axis], sb = st[b], sc = st[c];
222 Kokkos::parallel_for(
223 "peclet::flow::vmg_zero_plane",
224 Kokkos::MDRangePolicy<
CCExec, Kokkos::Rank<2>>(space, {0, 0}, {dims[b], dims[c]}),
225 KOKKOS_LAMBDA(
int p0,
int p1) { m((
long)p0 * sb + (
long)p1 * sc + (
long)idx * sa) = 0.0; });
231 std::size_t n = m.extent(0);
234 Kokkos::parallel_for(
235 "peclet::flow::vmg_threshold", Kokkos::RangePolicy<CCExec>(space, 0, n),
236 KOKKOS_LAMBDA(std::size_t i) { mm(i) = (th(i) < thresh) ? 1.0 : 0.0; });
240 std::size_t n = r.extent(0);
243 Kokkos::parallel_for(
244 "peclet::flow::vmg_mulmask", Kokkos::RangePolicy<CCExec>(space, 0, n),
245 KOKKOS_LAMBDA(std::size_t i) { rr(i) *= mm(i); });
252 static constexpr int G = 2;
260#ifdef PECLET_FLOW_MPI
261 std::shared_ptr<GridHaloTopology<3>> halo;
262 std::shared_ptr<GridHalo<double>> dev;
269 C3 inner{nx, ny, nz}, cf{1, 1, 1};
273 v.
ext =
C3{inner.
x + 2 *
G, inner.y + 2 *
G, inner.z + 2 *
G};
276 auto can = [&](
int d) {
return (d % 2 == 0) && (d / 2 >= 2); };
282 next.x = inner.x / 2;
286 next.y = inner.y / 2;
290 next.z = inner.z / 2;
305 *p =
FPV(
"vmg_A", v.
n);
307 if (
next.x == inner.x &&
next.y == inner.y &&
next.z == inner.z)
310 cf =
C3{cf.x * ratio.x, cf.y * ratio.y, cf.z * ratio.z};
313 CCField(
"vmg_resmask0", lv_[0].n);
315#ifdef PECLET_FLOW_MPI
323 int rank = 0, size = 1;
326 std::array<bool, 3>
per{
true,
true,
true};
328 auto can = [&](
int d) {
return (d % 2 == 0) && (d / 2 >= 2); };
331 v.
halo = std::make_shared<GridHaloTopology<3>>();
332 peclet::core::decomp::BlockDecomposer<3>
dec(
static_cast<std::size_t
>(size),
333 peclet::core::IVec<3>{
gs.x,
gs.y,
gs.z});
335 v.
dev = std::make_shared<GridHalo<double>>();
337 const auto&
idx = v.
halo->indexer();
338 const auto eg =
idx.sizeInclGhost(),
ino =
idx.sizeInner(),
oig =
idx.originInclGhost();
343 v.
n =
idx.numCellsInclGhost();
344 C3
next =
gs, ratio{1, 1, 1};
371 *p =
FPV(
"vmg_A", v.
n);
376 cf = C3{
cf.x * ratio.x,
cf.y * ratio.y,
cf.z * ratio.z};
378 lv_[0].resMask =
CCField(
"vmg_resmask0", lv_[0].n);
381 int nLevels()
const {
return (
int)lv_.size(); }
387 Kokkos::deep_copy(f.AC,
AC);
388 Kokkos::deep_copy(f.AW, AW);
389 Kokkos::deep_copy(f.AE, AE);
390 Kokkos::deep_copy(f.AS, AS);
391 Kokkos::deep_copy(f.AN, AN);
392 Kokkos::deep_copy(f.AB, AB);
393 Kokkos::deep_copy(f.AT, AT);
404 Kokkos::deep_copy(f.theta,
theta0);
405 Kokkos::deep_copy(f.pin,
solid0);
406 Kokkos::deep_copy(f.resMask,
resmask0);
407 for (
int L = 1;
L < (
int)lv_.size(); ++
L) {
416 buildVelocityStaircase(c.AC, c.AW, c.AE, c.AS, c.AN, c.AB, c.AT,
CCConst(c.theta), c.ext,
G,
426 for (
int L = 1;
L < (
int)lv_.size(); ++
L) {
446 for (
int L = 1;
L < (
int)lv_.size(); ++
L) {
451 const double sx = 1.0 / (
double)c.cfac.x,
sy = 1.0 / (
double)c.cfac.y,
454 CCConst(c.advW),
comp, c.ext,
G,
bx,
by,
bz,
fouw,
sx,
sy,
sz, idiag);
464 for (
int i = 0;
i < 6; ++
i) {
486 Kokkos::deep_copy(f.resMask, 1.0);
488 for (
int s = 0;
s < 1;
490 const int t = bc_[2 *
comp +
s];
491 if (
t == 1 ||
t == 2) {
496 for (
int L = 0;
L < (
int)lv_.size(); ++
L) {
501 buildConstAniso(c.AC, c.AW, c.AE, c.AS, c.AN, c.AB, c.AT, c.ext,
bx,
by,
bz, idiag);
502 for (
int f = 0; f < 6; ++f) {
503 const int a = f / 2,
s = f % 2;
504 const double ba = (
a == 0) ?
bx : (
a == 1) ?
by :
bz;
508 else if ((bc_[f] == 1 || bc_[f] == 2) &&
a !=
comp)
523 Kokkos::deep_copy(
l0.rhs, b);
524 Kokkos::deep_copy(
l0.x, x);
525 for (
int v = 0; v <
nvc; ++v)
527 Kokkos::deep_copy(x,
l0.x);
533 const bool l0 = (
L == 0);
534 if (
L + 1 == (
int)lv_.size()) {
540 if (
l0 && bcApplyL0_)
546 useResMask_ && (lv.
resMask.extent(0) == lv.
n);
551 Kokkos::deep_copy(
cs.x, 0.0);
569 if (
isL0 && bcApplyL0_)
581#ifdef PECLET_FLOW_MPI
582 if (distributed_ && !bcMode_) {
587 for (
int a = 0;
a < 3; ++
a)
588 if (!bcMode_ || (bc_[2 *
a] == 0 && bc_[2 *
a + 1] == 0))
596 for (
int a = 0;
a < 3; ++
a)
597 for (
int s = 0;
s < 2; ++
s) {
598 const int t = bc_[2 *
a +
s];
608 int dims[3] = {e.x, e.y, e.z};
609 long st[3] = {1, e.x, (
long)e.x * e.y};
614 Kokkos::parallel_for(
615 "peclet::flow::vmg_pfill",
619 for (
int gl = 0;
gl <
G; ++
gl) {
627 std::vector<Level> lv_;
628 int pre_ = 2, post_ = 2, bottom_ = 8;
631 bool bcMode_ =
false;
632 int bc_[6] = {0, 0, 0, 0, 0, 0};
635 bool distributed_ =
false;
void setFineStencil(FPC AC, FPC AW, FPC AE, FPC AS, FPC AN, FPC AB, FPC AT)
void fillProlongBcGhosts(Level &lv)
void buildUpwindCoarse(int comp, double nu_dt, double idiag, double fouw)
void fillAxis(Level &lv, CCField f, int axis)
void setBcApplyL0(std::function< void(CCField)> fn)
void setDomainBcOp(int comp, double nu_dt, double idiag)
void smooth(Level &lv, int sweeps, bool isL0)
void solve(CCConst b, CCField x, int nvc, int pre, int post, int bottom)
void restrictAdvVelocities(CCConst u0, CCConst v0, CCConst w0)
void fill(Level &lv, CCField f)
void setStaircase(CCConst theta0, CCConst solid0, CCConst resmask0, double nu_dt, double idiag, double thresh)
void setBC(const int bc[6])
void init(int nx, int ny, int nz, int nLevels)
flow — portable (Kokkos) geometric multigrid for the cut-cell (variable-openness) pressure Poisson.
flow — portable (Kokkos) IBM geometric fields + variable-coefficient RB-GS smoother.
void zeroPlane(CCField m, C3 e, int axis, int idx)
void buildConstAniso(FPV AC, FPV AW, FPV AE, FPV AS, FPV AN, FPV AB, FPV AT, C3 e, double bx, double by, double bz, double idiag)
void buildVelocityStaircase(FPV AC, FPV AW, FPV AE, FPV AS, FPV AN, FPV AB, FPV AT, CCConst theta, C3 e, int g, double bx, double by, double bz, double thresh, double idiag)
void thresholdMask(CCField m, CCConst theta, double thresh)
Kokkos::View< const MReal *, CCMem > FPC
void prolongAdd(CCField fine, CCConst coarse, C3 fext, C3 cext, int g, C3 finner, C3 ratio)
void residualVarPin(CCField r, CCConst x, CCConst b, FPC AC, FPC AW, FPC AE, FPC AS, FPC AN, FPC AB, FPC AT, CCConst pin, C3 e, int g)
void boundaryFold(FPV AC, C3 e, int g, int a, int s, double beta)
void ibmRbgsStencilColor(CCField x, CCConst b, MConst AC, MConst AW, MConst AE, MConst AS, MConst AN, MConst AB, MConst AT, CCConst solidmask, C3 ext, C3 og, int g, int color)
void fillBcGhost(CCField x, C3 e, int g, int a, int s, int dirichlet)
void restrictAvg(CCField coarse, CCConst fine, C3 cext, C3 fext, int g, C3 cinner, C3 ratio)
Kokkos::View< double *, CCMem > CCField
Kokkos::View< MReal *, CCMem > FPV
void mulMask(CCField r, CCConst m)
Kokkos::DefaultExecutionSpace CCExec
Kokkos::View< const float *, CCMem > MConst
void prolongMasked(CCField fine, CCConst coarse, CCConst mask, C3 fext, C3 cext, int g, C3 finner, C3 ratio, double eps)
void buildAdvCoarse(FPV AC, FPV AW, FPV AE, FPV AS, FPV AN, FPV AB, FPV AT, CCConst U, CCConst V, CCConst W, int comp, C3 e, int g, double bx, double by, double bz, double fouw, double sx, double sy, double sz, double idiag)
Kokkos::View< const double *, CCMem > CCConst
void fou_operator_aniso(int comp, int x, int y, int z, A U, A V, A W, double dt, double sx, double sy, double sz, double &cC, double &cxm, double &cxp, double &cym, double &cyp, double &czm, double &czp)
flow — portable (Kokkos) staggered MAC momentum advection (Koren TVD + FOU).
std::unique_ptr< GridHalo< double > > dev
std::unique_ptr< GridHaloTopology< kDim > > halo
static constexpr double AC