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}),
41 const long sx = 1,
sy = e.x,
sz = (
long)e.x * e.y;
61 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
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);
76 auto C = [&](
int xx,
int yy,
int zz) {
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}),
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}),
129 const long i = (
long)x + (
long)y * e.x + (
long)z * (
long)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),
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",
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];
197 Kokkos::parallel_for(
198 "peclet::flow::vmg_fill_bc_ghost",
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);
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",
231 std::size_t n = m.extent(0);
234 Kokkos::parallel_for(
235 "peclet::flow::vmg_threshold", Kokkos::RangePolicy<CCExec>(
space, 0, n),
240 std::size_t n = r.extent(0);
243 Kokkos::parallel_for(
244 "peclet::flow::vmg_mulmask", Kokkos::RangePolicy<CCExec>(
space, 0, n),
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();
339 v.ext = {(
int)eg[0], (
int)
eg[1], (
int)eg[2]};
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);
568#ifdef PECLET_FLOW_MPI
569 if (distributed_ && !(
isL0 && bcApplyL0_)) {
573 const C3 lo{
G + 1,
G + 1,
G + 1};
575 lv.dev->exchangeBegin(lv.
x);
578 MConst(lv.
AT), pin, lv.
ext, og,
color,
lo,
hi,
C3{0, 0, 0},
580 lv.dev->exchangeEnd(lv.
x);
584 C3{lv.ext.x - G, lv.ext.y - G, lv.ext.z - G},
lo,
hi);
589 if (
isL0 && bcApplyL0_)
601#ifdef PECLET_FLOW_MPI
602 if (distributed_ && !bcMode_) {
607 for (
int a = 0; a < 3; ++a)
608 if (!bcMode_ || (bc_[2 * a] == 0 && bc_[2 * a + 1] == 0))
616 for (
int a = 0; a < 3; ++a)
617 for (
int s = 0; s < 2; ++s) {
618 const int t = bc_[2 * a + s];
628 int dims[3] = {e.x, e.y, e.z};
629 long st[3] = {1, e.x, (
long)e.x * e.y};
630 const int a = axis, b = (axis + 1) % 3, c = (axis + 2) % 3;
631 const long sa = st[a],
sb = st[b], sc = st[c];
634 Kokkos::parallel_for(
635 "peclet::flow::vmg_pfill",
638 const long base = (
long)p0 *
sb + (
long)
p1 * sc;
639 for (
int gl = 0;
gl <
G; ++
gl) {
647 std::vector<Level> lv_;
648 int pre_ = 2, post_ = 2, bottom_ = 8;
651 bool bcMode_ =
false;
652 int bc_[6] = {0, 0, 0, 0, 0, 0};
655 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 gf, int gc, 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 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 restrictAvg(CCField coarse, CCConst fine, C3 cext, C3 fext, int gc, int gf, C3 cinner, C3 ratio)
Kokkos::View< MReal *, CCMem > FPV
void mulMask(CCField r, CCConst m)
Kokkos::DefaultExecutionSpace CCExec
void ibmRbgsStencilColorBox(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 color, C3 rlo, C3 rhi, C3 slo, C3 shi)
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