18#include <Kokkos_Core.hpp>
22#include "peclet/core/common/types.hpp"
23#include "peclet/core/common/view.hpp"
24#include "peclet/core/decomp/block_decomposer.hpp"
25#include "peclet/core/halo/grid_halo.hpp"
26#include "peclet/core/halo/grid_halo_topology.hpp"
28using peclet::core::Index;
29using peclet::core::IVec;
30using peclet::core::decomp::BlockDecomposer;
31using peclet::core::halo::GridHalo;
32using peclet::core::halo::GridHaloTopology;
42static double source(
int gx,
int gy,
int gz, IVec<kDim> gs) {
43 return std::sin(2.0 * M_PI * gx / gs[0]) +
44 std::cos(4.0 * M_PI * gy / gs[1]) * std::sin(2.0 * M_PI * gz / gs[2]);
48 std::unique_ptr<GridHaloTopology<kDim>>
halo;
49 std::unique_ptr<GridHalo<double>>
dev;
62 std::vector<Level>
lv;
68 std::array<bool, kDim>
per{
true,
true,
true};
70 for (
int L = 0;
L <
NLEV; ++
L) {
72 v.
halo = std::make_unique<GridHaloTopology<kDim>>();
75 v.
dev = std::make_unique<GridHalo<double>>();
77 const auto&
idx = v.
halo->indexer();
78 const auto eg =
idx.sizeInclGhost(),
ino =
idx.sizeInner(), o =
idx.originInclGhost();
81 v.
og = {(
int)o[0], (
int)o[1], (
int)o[2]};
83 v.
n =
idx.numCellsInclGhost();
85 v.
x = CCField(
"x", v.
n);
86 v.
rhs = CCField(
"rhs", v.
n);
87 v.
res = CCField(
"res", v.
n);
88 v.
ox = CCField(
"ox", v.
n);
89 v.
oy = CCField(
"oy", v.
n);
90 v.
oz = CCField(
"oz", v.
n);
91 Kokkos::deep_copy(v.
ox, 1.0);
92 Kokkos::deep_copy(v.
oy, 1.0);
93 Kokkos::deep_copy(v.
oz, 1.0);
96 const double s = 1.0 / (
double)(cf[0]);
98 CCConst(v.
oy), CCConst(v.
oz), v.
e,
G, 1.0 / (cf[0] * cf[0]),
99 1.0 / (cf[1] * cf[1]), 1.0 / (cf[2] * cf[2]));
101 lv.push_back(std::move(v));
102 for (
int d = 0; d < 3; ++d) {
113 Kokkos::parallel_reduce(
115 Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>(
sp, {
G,
G,
G}, {e.x -
G, e.y -
G, e.z -
G}),
117 a += f((
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y);
129 Kokkos::parallel_for(
131 Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>(
sp, {
G,
G,
G}, {e.x -
G, e.y -
G, e.z -
G}),
133 ff((
long)x + (
long)y * e.x + (
long)z * (
long)e.x * e.y) -=
mean;
140 v.
dev->exchange(v.
x);
142 FPC(v.
AS), FPC(v.
AN), FPC(v.
AB), FPC(v.
AT), v.
e, v.
og,
G,
148 if (
L + 1 == (
int)
lv.size()) {
154 v.
dev->exchange(v.
x);
156 FPC(v.
AE), FPC(v.
AS), FPC(v.
AN), FPC(v.
AB), FPC(v.
AT), v.
e,
G);
160 Kokkos::deep_copy(c.x, 0.0);
162 c.dev->exchange(c.x);
171 Kokkos::deep_copy(
l0.rhs, b);
173 Kokkos::deep_copy(
l0.x, 0.0);
174 for (
int v = 0; v <
NVCYC; ++v)
179int main(
int argc,
char** argv) {
180 MPI_Init(&argc, &argv);
181 Kokkos::initialize(argc, argv);
182 int fail = 0, size = 1, rank = 0;
184 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
185 MPI_Comm_size(MPI_COMM_WORLD, &size);
186 IVec<kDim> gs{32, 32, 32};
190 mg.
init(MPI_COMM_WORLD, gs);
192 CCField b(
"b", l0.
n);
194 auto hb = Kokkos::create_mirror_view(b);
195 for (Index c = 0; c < l0.
n; ++c)
197 mg.
lv[0].halo->indexer().forEachInner([&](
const IVec<kDim>& l) {
198 hb(mg.
lv[0].halo->indexer().localMdToLocal(l)) =
201 Kokkos::deep_copy(b, hb);
204 auto hx = Kokkos::create_mirror_view(l0.
x);
205 Kokkos::deep_copy(hx, l0.
x);
209 ref.init(MPI_COMM_SELF, gs);
210 Level& r0 = ref.lv[0];
211 CCField rb(
"rb", r0.
n);
213 auto hrb = Kokkos::create_mirror_view(rb);
214 for (Index c = 0; c < r0.
n; ++c)
216 ref.lv[0].halo->indexer().forEachInner([&](
const IVec<kDim>& l) {
217 hrb(ref.lv[0].halo->indexer().localMdToLocal(l)) =
220 Kokkos::deep_copy(rb, hrb);
223 auto hr = Kokkos::create_mirror_view(r0.
x);
224 Kokkos::deep_copy(hr, r0.
x);
227 double maxdiff = 0.0;
228 mg.
lv[0].halo->indexer().forEachInner([&](
const IVec<kDim>& l) {
229 const int gx = l[0] + l0.
og.
x, gy = l[1] + l0.
og.
y, gz = l[2] + l0.
og.
z;
230 const double a = hx(mg.
lv[0].halo->indexer().localMdToLocal(l));
232 hr((
long)(gx +
G) + (
long)(gy +
G) * re.
x + (
long)(gz +
G) * (
long)re.
x * re.
y);
233 const double d = std::fabs(a - rr);
237 if (maxdiff > 1e-11) {
239 std::fprintf(stderr,
"[rank %d] max|distributed - serial V-cycle| = %.3e\n", rank, maxdiff);
243 MPI_Allreduce(&fail, &totalFail, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
246 std::printf(
"OK (np=%d): distributed cut-cell MG V-cycle == serial reference\n", size);
248 std::fprintf(stderr,
"FAILED (np=%d): %d ranks differ\n", size, totalFail);
252 return totalFail == 0 ? 0 : 1;
flow — portable (Kokkos) geometric multigrid for the cut-cell (variable-openness) pressure Poisson.
Kokkos::View< const MReal *, CCMem > FPC
void prolongAdd(CCField fine, CCConst coarse, C3 fext, C3 cext, int g, C3 finner, C3 ratio)
void residualCutcell(CCField r, CCConst x, CCConst b, FPC AC, FPC AW, FPC AE, FPC AS, FPC AN, FPC AB, FPC AT, C3 e, int g)
void restrictAvg(CCField coarse, CCConst fine, C3 cext, C3 fext, int g, C3 cinner, C3 ratio)
void buildCutcellOp(OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, CCConst ox, CCConst oy, CCConst oz, C3 e, int g, double gfx, double gfy, double gfz)
Kokkos::View< double *, CCMem > CCField
Kokkos::View< MReal *, CCMem > FPV
void cutcellSmoothColor(CCField phi, CCConst b, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, C3 e, C3 og, int g, int color)
Kokkos::DefaultExecutionSpace CCExec
Kokkos::View< const double *, CCMem > CCConst
double meanSum(Level &v, CCField f)
void removeMean(Level &v, CCField f)
void init(MPI_Comm c, IVec< kDim > gs)
void smooth(Level &v, int sweeps)
std::unique_ptr< GridHalo< double > > dev
std::unique_ptr< GridHaloTopology< kDim > > halo
static constexpr int kDim
static constexpr int NVCYC
int main(int argc, char **argv)
static constexpr int POST
static constexpr int BOTTOM
static double source(int gx, int gy, int gz, IVec< kDim > gs)
static constexpr int NLEV