9#ifndef PECLET_FLOW_MAC_MG_HPP
10#define PECLET_FLOW_MAC_MG_HPP
12#include <Kokkos_Core.hpp>
24 int dims[3] = {e.x, e.y, e.z};
25 long st[3] = {1, e.x, (
long)e.x * e.y};
26 for (
int axis = 0; axis < 3; ++axis) {
27 const int b = (axis + 1) % 3, c = (axis + 2) % 3;
28 const long sa = st[axis],
sb = st[b], sc = st[c];
34 const long base = (
long)p0 *
sb + (
long)
p1 * sc;
35 for (
int gl = 0;
gl < g; ++
gl) {
37 ff(base + (
long)(g +
N +
gl) *
sa) =
ff(base + (
long)(g +
gl) *
sa);
53 L.e =
I3{n + 2 *
G, n + 2 *
G, n + 2 *
G};
54 const std::size_t
ne = (std::size_t)L.e.x * L.e.y * L.e.z;
59 if (n % 2 != 0 || n / 2 <
minN)
74 "peclet::flow::mg_negd", Kokkos::RangePolicy<SExec>(
space, 0,
f0.extent(0)),
77 Kokkos::deep_copy(
lv_[0].phi, phi);
82 Kokkos::deep_copy(phi,
lv_[0].phi);
93 static constexpr int G = 1;
106 const double h2 = L.h2;
107 SField phi = L.phi, f = L.f;
109 Kokkos::parallel_for(
110 "peclet::flow::mg_smooth",
MD(
space, {
G,
G,
G}, {e.x -
G, e.y -
G, e.z -
G}),
112 if (((x + y + z) & 1) !=
color)
114 const long i =
L3(x, y, z, e),
sx = 1, sy = e.x, sz = (
long)e.x * e.y;
116 phi(i +
sx) + phi(i -
sx) + phi(i + sy) + phi(i - sy) + phi(i + sz) + phi(i - sz);
117 phi(i) = (s + h2 * f(i)) / 6.0;
121 for (
int it = 0; it < sweeps; ++it) {
133 const double h2 = L.h2;
134 SField phi = L.phi, f = L.f, r = L.r;
136 Kokkos::parallel_for(
137 "peclet::flow::mg_resid",
MD(
space, {
G,
G,
G}, {e.x -
G, e.y -
G, e.z -
G}),
139 const long i =
L3(x, y, z, e),
sx = 1, sy = e.x, sz = (
long)e.x * e.y;
141 phi(i +
sx) + phi(i -
sx) + phi(i + sy) + phi(i - sy) + phi(i + sz) + phi(i - sz);
142 r(i) = f(i) - (6.0 * phi(i) - s) / h2;
147 if (l == (
int)
lv_.size() - 1) {
155 Kokkos::deep_copy(C.phi, 0.0);
157 T3{C.N, C.N, C.N},
T3{2, 2, 2});
162 T3{L.N, L.N, L.N},
T3{2, 2, 2});
170 Kokkos::parallel_reduce(
171 "peclet::flow::mg_mean", Kokkos::RangePolicy<SExec>(
space, 0, (
long)
N *
N *
N),
173 const int ix = (int)(c %
N),
iy = (int)((c /
N) %
N),
iz = (
int)(c / ((
long)
N *
N));
178 Kokkos::parallel_for(
179 "peclet::flow::mg_submean", Kokkos::RangePolicy<SExec>(
space, 0, f.extent(0)),
187 Kokkos::parallel_reduce(
188 "peclet::flow::mg_maxabs", Kokkos::RangePolicy<SExec>(
space, 0, (
long)
N *
N *
N),
190 const int ix = (int)(c %
N),
iy = (int)((c /
N) %
N),
iz = (
int)(c / ((
long)
N *
N));
191 double v = Kokkos::fabs(f(
L3(
ix +
G,
iy +
G,
iz +
G, e)));
195 Kokkos::Max<double>(m));
double finestResidualMax()
double maxAbsInner(SField f, Level &L)
MgPoisson(int N, int minN=4)
void smoothColor(Level &L, int color)
void vcycle(int l, int nu1, int nu2)
void removeMean(SField f, Level &L)
void computeResidual(int l)
void smooth(Level &L, int sweeps)
void solve(SField phi, SConst d, int nVcycles, int nu1=2, int nu2=2)
flow — portable (Kokkos) MAC stencil operators: Red-Black Gauss-Seidel smoothers + divergence.
flow — portable (Kokkos) multigrid transfer operators + projection velocity correction.
long L3(int x, int y, int z, I3 e)
void restrict_(TField coarse, TConst fine, T3 cext, T3 fext, int g, T3 cinner, T3 ratio)
void prolong(TField fine, TConst coarse, T3 fext, T3 cext, int g, T3 finner, T3 ratio)
Kokkos::View< const double *, SMem > SConst
void mgPeriodicFill(SField f, I3 e, int N, int g)
Kokkos::DefaultExecutionSpace SExec
Kokkos::View< double *, SMem > SField
flow — the multidimensional iteration policies: iteration order follows storage.
static double mean(const std::vector< double > &a)