43#ifndef PECLET_AMR_DISTRIBUTED_FLOW_MG_HPP
44#define PECLET_AMR_DISTRIBUTED_FLOW_MG_HPP
62#include "peclet/core/common/mpi.hpp"
63#include "peclet/core/common/view.hpp"
64#include "peclet/core/decomp/redistribute_topology.hpp"
65#include "peclet/core/decomp/stage_comm.hpp"
66#include "peclet/core/decomp/stage_target.hpp"
77 double sx = 0.0,
sv = 0.0;
78 Kokkos::parallel_reduce(
79 "amr::fv_rmean", op.
n,
85 an +=
u(
i) / invVol(
i);
86 ad += 1.0 / invVol(
i);
105template <
int Dim,
unsigned Bits>
106class DistributedStage;
108template <
int Dim,
unsigned Bits = (Dim == 2 ? 32u : (Dim == 3 ? 21u : 16u))>
114 using M =
typename Octree::M;
115 using Code =
typename Octree::Code;
130 template <
class OpenFn>
133 Index bottomExtent = 4) {
138 template <
class OpenFn>
141 Index bottomExtent = 4) {
146 levels_[0]->ap.buildOpenness(
openFn);
147 for (std::size_t
L = 0;
L + 1 < levels_.size(); ++
L)
148 coarsenOpennessTo(
L);
160 bool liftRoot =
true,
Index bottomExtent = 4) {
161 buildImpl(
finest, h0,
nullptr, liftRoot, bottomExtent);
163 for (std::size_t
L = 0;
L + 1 < levels_.size(); ++
L)
164 coarsenOpennessTo(
L);
186 stage_->setRemoveMean(on);
189 std::size_t
numLevels()
const {
return levels_.size(); }
202 bool hasStage()
const {
return stage_ !=
nullptr; }
204 const char*
stageKind()
const {
return stage_ ? stage_->kind() :
"none"; }
223 return stage_->bottomName() + stage_->diagnosticSuffix();
224 return bottomAmg_ ? std::string(
"amg") : std::string(
"jacobi");
240 stage_->setBottom(
b);
248 const FvOp&
op(std::size_t
L = 0)
const {
return levels_[
L]->op; }
260 Level&
lv = *levels_[
L];
262 if (
L + 1 == levels_.size()) {
269 lv.ex.exchange(
lv.x);
274 Kokkos::parallel_for(
276 }
else if (bottomAmg_) {
277 bottomAmg_->solve(
bc,
lv.x);
279 for (
int s = 0;
s < bottom; ++
s) {
280 lv.ex.exchange(
lv.x);
288 for (
int s = 0;
s <
pre; ++
s) {
289 lv.ex.exchange(
lv.x);
292 lv.ex.exchange(
lv.x);
294 Level&
cl = *levels_[
L + 1];
296 Kokkos::deep_copy(
cl.x, 0.0);
299 for (
int s = 0;
s <
post; ++
s) {
300 lv.ex.exchange(
lv.x);
315 Index n = 0, nExt = 0;
323 std::vector<Index> c2pHost;
344 Level&
lt = *levels_.back();
345 stageFrom_ =
lt.d.globalRootSize();
349 for (
int a = 0;
a < Dim; ++
a)
350 mx = std::max(
mx, stageFrom_[
a]);
359 const auto A =
lt.ap.assembleFv();
361 for (
double d :
A.bcDiag)
366 bottomAmg_ = std::make_unique<AmgBottom<Dim, Bits>>();
370 if (resolved_.
enabled &&
mx > bottomExtent_) {
371 namespace cd = core::decomp;
372 auto liftable = [](
const cd::BlockDecomposer<Dim>&
dec) {
375 const cd::StageTarget<Dim>
t = cd::chooseStageTarget(
377 if (
t.kind == cd::StageKind::SiblingMerge ||
t.kind == cd::StageKind::Repartition) {
378 using Topo = cd::RedistributeTopology<Dim, double>;
380 static_cast<int>((levels_.size() - 1) %
static_cast<std::size_t
>(Topo::kTagSpan));
381 auto st = std::make_unique<DistributedStage<Dim, Bits>>();
382 st->build(
lt.d, h0_,
lt.ap,
lt.n,
t,
id, bottomExtent_, resolved_, bottomKind_,
384 stage_ = std::move(
st);
388 auto tail = std::make_unique<ReplicatedTailStage<Dim, Bits>>();
389 tail->build(
lt.d, h0_,
lt.ap,
lt.n,
lt.nExt, bottomExtent_,
lt.comm);
390 tail->setRemoveMean(removeMean_);
391 tail->setBottom(bottomKind_);
392 stage_ = std::move(tail);
398 void setOpennessLocalRows(std::size_t
L,
const std::vector<double>&
alphaLocal) {
399 Level&
lv = *levels_[
L];
400 const int F = 2 * Dim;
404 throw std::invalid_argument(
405 "amr::DistributedFlowMultigrid::buildRaw: alpha must hold numLeaves()*2*Dim local rows");
406 std::vector<double>
ca(
static_cast<std::size_t
>(
nl +
ng) *
F, 1.0);
408 std::vector<double> col(
static_cast<std::size_t
>(
lv.nExt), 0.0);
409 for (
int fi = 0;
fi <
F; ++
fi) {
411 col[
static_cast<std::size_t
>(
i)] =
ca[
static_cast<std::size_t
>(
i) *
F +
fi];
412 lv.hp->exchangeHost(col);
414 ca[
static_cast<std::size_t
>(
nl + g) *
F +
fi] = col[
static_cast<std::size_t
>(
nl + g)];
416 lv.ap.setOpennessRaw(std::move(
ca));
420 bool liftRoot,
Index bottomExtent) {
423 bottomExtent_ = bottomExtent;
425 resolved_ = stagePolicy_;
427 long long nl =
static_cast<long long>(
finest.local().numLeaves()),
mx = 0;
433 auto l0 = std::make_unique<Level>();
435 levels_.push_back(std::move(
l0));
437 Octree c = levels_.back()->d.local();
442 auto lv = std::make_unique<Level>();
443 lv->d = levels_.back()->d;
444 lv->d.local() = std::move(
c);
445 levels_.push_back(std::move(
lv));
446 if (levels_.back()->d.local().numLeaves() == 1)
452 int nl =
static_cast<int>(levels_.size()),
gnl =
nl;
454 while (
static_cast<int>(levels_.size()) <
gnl) {
455 auto lv = std::make_unique<Level>();
456 lv->d = levels_.back()->d;
457 levels_.push_back(std::move(
lv));
466 liftDepth_ = allowedLiftDepth(levels_.back()->d, bottomExtent);
467 for (
Index j = 0;
j < liftDepth_; ++
j) {
468 auto lv = std::make_unique<Level>();
469 lv->d = levels_.back()->d;
472 const Index merged =
lv->d.local().coarsenIf([](
Code,
unsigned) {
return true; });
475 levels_.push_back(std::move(
lv));
480 int nlv =
static_cast<int>(levels_.size()),
lo = 0,
hi = 0;
484 throw std::runtime_error(
485 "amr::DistributedFlowMultigrid: the pressure ladder has different level counts on "
486 "different ranks (the lift is not lockstep)");
493 std::array<long, Dim>
shift{};
494 for (
int a = 0;
a < Dim; ++
a)
498 for (
auto&
lvp : levels_) {
501 lv.n =
lv.d.local().numLeaves();
502 lv.ap.init(
lv.d.local(), h0_);
507 std::vector<std::array<long, Dim>>
glo(
static_cast<std::size_t
>(
h.numGhosts()));
508 std::vector<unsigned>
glv(
static_cast<std::size_t
>(
h.numGhosts()));
509 for (
Index g = 0; g <
h.numGhosts(); ++g) {
510 for (
int a = 0;
a < Dim; ++
a)
511 glo[
static_cast<std::size_t
>(g)][
a] =
static_cast<long>(
h.ghostCoord(g)[
a]) -
shift[
a];
512 glv[
static_cast<std::size_t
>(g)] =
static_cast<unsigned>(
h.level(
h.numLocal() + g));
514 lv.ap.setGhosts(std::move(
glo), std::move(
glv));
521 std::array<long, Dim> g =
p;
522 for (
int a = 0;
a < Dim; ++
a)
524 return shared0->lookupGlobal(g);
530 LeafHalo<Dim, Bits>* hp = &
lv.halo;
531 lv.ap.setResolver([hp,
shift](
const std::array<long, Dim>&
p) ->
Index {
532 std::array<long, Dim> g =
p;
533 for (
int a = 0;
a < Dim; ++
a)
535 return hp->resolveGlobal(g);
544 lv.ap.forEachFaceNeighbor(
i, [](
Index,
Real,
int,
double) {});
545 if (
lv.halo.resolveMisses() == 0)
550 lv.nExt =
lv.hp->extendedSize();
555 for (std::size_t
L = 0;
L + 1 < levels_.size(); ++
L) {
556 const Octree&
f = levels_[
L]->d.local();
557 const Octree&
c = levels_[
L + 1]->d.local();
558 const Index nf =
f.numLeaves(),
nc =
c.numLeaves();
559 std::vector<Index>& c2p = levels_[
L]->c2pHost;
560 c2p.assign(
static_cast<std::size_t
>(
nf), -1);
561 std::vector<Index>
cnt(
static_cast<std::size_t
>(
nc), 0);
564 c2p[
static_cast<std::size_t
>(
i)] =
p;
566 ++
cnt[
static_cast<std::size_t
>(
p)];
568 std::vector<Index> start(
static_cast<std::size_t
>(
nc) + 1, 0);
570 start[
static_cast<std::size_t
>(
p) + 1] =
571 start[
static_cast<std::size_t
>(
p)] +
cnt[
static_cast<std::size_t
>(
p)];
572 std::vector<Index> idx(
static_cast<std::size_t
>(start[
static_cast<std::size_t
>(
nc)]));
573 std::vector<Index>
cur(start.begin(), start.end() - 1);
575 const Index p = c2p[
static_cast<std::size_t
>(
i)];
577 idx[
static_cast<std::size_t
>(
cur[
static_cast<std::size_t
>(
p)]++)] =
i;
579 levels_[
L]->c2p =
toDevice(c2p,
"dfmg_c2p");
580 levels_[
L]->childStart =
toDevice(start,
"dfmg_cstart");
581 levels_[
L]->childIdx =
toDevice(idx,
"dfmg_cidx");
589 void coarsenOpennessTo(std::size_t
L) {
590 const Octree&
f = levels_[
L]->d.local();
591 const Octree&
c = levels_[
L + 1]->d.local();
593 const int F = 2 * Dim;
595 const Index ngc = levels_[
L + 1]->hp->numGhosts();
596 std::vector<double>
ca(
static_cast<std::size_t
>(
nc +
ngc) *
F, 0.0);
597 std::vector<int>
cnt(
static_cast<std::size_t
>(
nc) *
F, 0);
598 const std::vector<Index>& c2p = levels_[
L]->c2pHost;
599 for (
Index i = 0;
i <
f.numLeaves(); ++
i) {
600 const Index p = c2p[
static_cast<std::size_t
>(
i)];
603 const std::size_t base =
static_cast<std::size_t
>(
p) *
F;
604 if (
c.level(
p) ==
f.level(
i)) {
605 for (
int axis = 0; axis < Dim; ++axis)
606 for (
int dir = -1; dir <= 1; dir += 2) {
608 ca[base +
static_cast<std::size_t
>(
fi)] +=
capL.faceOpenness(
i, axis, dir);
609 cnt[base +
static_cast<std::size_t
>(
fi)] += 1;
612 const unsigned oct = M::from_code(
f.code(
i)).child_index(
f.level(
i));
613 for (
int axis = 0; axis < Dim; ++axis) {
614 const int dir = ((
oct >> axis) & 1) ? +1 : -1;
616 ca[base +
static_cast<std::size_t
>(
fi)] +=
capL.faceOpenness(
i, axis, dir);
617 cnt[base +
static_cast<std::size_t
>(
fi)] += 1;
624 const LeafHalo<Dim, Bits>&
h = *levels_[
L + 1]->hp;
625 std::vector<double> col(
static_cast<std::size_t
>(levels_[
L + 1]->nExt), 0.0);
626 for (
int fi = 0;
fi <
F; ++
fi) {
628 col[
static_cast<std::size_t
>(
i)] =
ca[
static_cast<std::size_t
>(
i) *
F +
fi];
631 ca[
static_cast<std::size_t
>(
nc + g) *
F +
fi] = col[
static_cast<std::size_t
>(
nc + g)];
633 levels_[
L + 1]->ap.setOpennessRaw(std::move(
ca));
639 for (
auto&
lvp : levels_) {
641 auto A =
lv.ap.assembleFv();
652 Kokkos::deep_copy(
lv.x, 0.0);
653 Kokkos::deep_copy(
lv.b, 0.0);
659 static Index allowedLiftDepth(
const DO& d,
Index bottomExtent) {
660 IVec<Dim> G = d.globalRootSize(),
o = d.blockOriginRoot(),
b = d.blockBrick();
664 for (
int a = 0;
a < Dim; ++
a)
666 if (
mx <= bottomExtent)
669 for (
int a = 0;
a < Dim; ++
a)
670 if ((
G[
a] % 2) != 0 || (
G[
a] / 2) < 2 || (
o[
a] % 2) != 0 || (
b[
a] % 2) != 0) {
676 for (
int a = 0;
a < Dim; ++
a) {
689 Vec<Dim> h0_ = detail::filledVec<Dim>(1.0);
690 Index bottomExtent_ = 4;
691 Index liftDepth_ = 0;
694 std::unique_ptr<MgStage<Dim, Bits>> stage_;
697 std::unique_ptr<AmgBottom<Dim, Bits>> bottomAmg_;
698 std::array<long, Dim> shift_{};
699 std::vector<std::unique_ptr<Level>> levels_;
700 bool removeMean_ =
false;
722template <
int Dim,
unsigned Bits>
743 const core::decomp::StageTarget<Dim>&
target,
int id,
Index bottomExtent,
745 namespace cd = core::decomp;
746 if (
target.kind != cd::StageKind::SiblingMerge &&
target.kind != cd::StageKind::Repartition)
747 throw std::invalid_argument(
748 "amr::DistributedStage: only sibling-merge and repartition targets continue a "
749 "distributed ladder");
750 for (
int a = 0;
a < Dim; ++
a)
752 throw std::runtime_error(
753 "amr::DistributedStage: periodic-only (as the whole distributed pressure path is)");
755 for (
int a = 0;
a < Dim; ++
a)
758 throw std::runtime_error(
759 "amr::DistributedStage: the moved level does not tile its block with root cells (the "
760 "lift is not nested)");
764 comm_ = cd::makeStageComm<Dim>(parent_, target_);
772 throw std::runtime_error(
773 "amr::DistributedStage: a cell of this rank's block is not one of its root leaves (the "
774 "lift is not nested)");
781 const int F = 2 * Dim;
783 std::vector<std::vector<double>>
aCol(
static_cast<std::size_t
>(
F),
784 std::vector<double>(
static_cast<std::size_t
>(n), 1.0));
787 for (
int f = 0;
f <
F; ++
f)
788 aCol[
static_cast<std::size_t
>(
f)][
static_cast<std::size_t
>(
i)] =
789 aloc[
static_cast<std::size_t
>(
i) *
F +
static_cast<std::size_t
>(
f)];
790 std::vector<std::vector<double>>
tCol(
static_cast<std::size_t
>(
F),
791 std::vector<double>(
static_cast<std::size_t
>(nT_), 1.0));
792 std::vector<const double*>
aSrc(
static_cast<std::size_t
>(
F));
793 std::vector<double*>
aDst;
794 for (
int f = 0;
f <
F; ++
f)
795 aSrc[
static_cast<std::size_t
>(
f)] =
aCol[
static_cast<std::size_t
>(
f)].data();
797 for (
int f = 0;
f <
F; ++
f)
798 aDst.push_back(
tCol[
static_cast<std::size_t
>(
f)].data());
803 std::vector<double>
aT(
static_cast<std::size_t
>(nT_) *
F);
805 for (
int f = 0;
f <
F; ++
f)
806 aT[
static_cast<std::size_t
>(
r) *
F +
static_cast<std::size_t
>(
f)] =
807 tCol[
static_cast<std::size_t
>(
f)][
static_cast<std::size_t
>(
r)];
808 cont_ = std::make_unique<MG>();
809 cont_->setStagePolicy(
policy);
810 cont_->setBottom(bottom);
811 cont_->buildRaw(tdo_, h0,
aT,
true, bottomExtent);
812 cont_->setRemoveMean(removeMean);
816 dSrc_ =
View<double>(
"dstage_src",
static_cast<std::size_t
>(n));
817 dDst_ =
View<double>(
"dstage_dst",
static_cast<std::size_t
>(n));
818 dT_ =
View<double>(
"dstage_t",
static_cast<std::size_t
>(nT_));
819 srcMirror_ = Kokkos::View<double*, Kokkos::HostSpace>(
"dstage_hs",
static_cast<std::size_t
>(n));
820 dstMirror_ = Kokkos::View<double*, Kokkos::HostSpace>(
"dstage_hd",
static_cast<std::size_t
>(n));
821 tMirror_ = Kokkos::View<double*, Kokkos::HostSpace>(
"dstage_ht",
static_cast<std::size_t
>(nT_));
824 const char*
kind()
const override {
825 return target_.kind == core::decomp::StageKind::SiblingMerge ?
"sibling" :
"repartition";
828 return target_.kind == core::decomp::StageKind::SiblingMerge ?
"+sibling" :
"+repartition";
832 bool active()
const override {
return comm_.active; }
835 std::size_t
numLevels()
const override {
return numLevels_; }
839 const std::size_t k = cont_->numInPlaceLevels();
840 return L < k ? cont_->numLeaves(
L) : cont_->stageLeaves(
L - k);
842 std::string
bottomName()
const override {
return bottomName_; }
845 cont_->setRemoveMean(on);
861 Kokkos::parallel_for(
863 Kokkos::deep_copy(srcMirror_, dSrc_);
864 std::vector<double*>
to;
866 to.push_back(tMirror_.data());
867 topo_.forward({srcMirror_.data()},
to);
869 Kokkos::deep_copy(dT_, tMirror_);
870 auto b = cont_->b(0);
873 Kokkos::deep_copy(cont_->x(0), 0.0);
882 std::vector<const double*>
from;
884 auto x = cont_->x(0);
887 Kokkos::deep_copy(tMirror_, dT_);
888 from.push_back(tMirror_.data());
890 topo_.backward(
from, {dstMirror_.data()});
891 Kokkos::deep_copy(dDst_, dstMirror_);
893 Kokkos::parallel_for(
904 nl =
static_cast<long long>(cont_->numInPlaceLevels() + cont_->numStageLevels());
905 nm = cont_->bottomName();
908 int len =
static_cast<int>(
nm.size());
910 nm.resize(
static_cast<std::size_t
>(
len));
912 numLevels_ =
static_cast<std::size_t
>(
nl);
917 core::decomp::StageTarget<Dim> target_;
918 core::decomp::StageComm comm_;
919 core::decomp::RedistributeTopology<Dim, double> topo_;
921 std::unique_ptr<MG> cont_;
922 Index n_ = 0, nT_ = 0;
923 std::size_t numLevels_ = 0;
924 std::string bottomName_;
926 Kokkos::View<double*, Kokkos::HostSpace> srcMirror_, dstMirror_, tMirror_;
static int faceIndex(int axis, int dir)
const std::vector< double > & opennessRaw() const
unsigned level(Index i) const
const char * stageKind() const
"replicated", "sibling" or "repartition", or "none" without a stage.
Index extendedSize(std::size_t L=0) const
std::size_t numLevels() const
std::size_t numStageLevels() const
Levels of the continued ladder (its level 0 IS the moved level, so the full ladder is numInPlaceLevel...
Index liftDepth() const
How many levels the ladder gained BELOW the root brick by lifting (§6.2).
DistributedOctree< Dim, Bits > DO
Index numLeaves(std::size_t L=0) const
std::string bottomName() const
"jacobi" | "amg", suffixed by the stage's own spelling — "+tail" for the replicated one (docs/amr_mg_...
const StagePolicy & stagePolicy() const
View< double > stageSolution()
The moved level's solution on THIS rank's target block.
Index stageLeaves(std::size_t L=0) const
Cells of continued-ladder level L on this rank's target block (GLOBAL counts for the replicated stage...
View< double > b(std::size_t L=0)
View< double > x(std::size_t L=0)
const FvOp & op(std::size_t L=0) const
typename DO::Octree Octree
AmrPoisson< Dim, Bits > Poisson
void setBottom(typename Multigrid< Dim, Bits >::Bottom b)
Select what solves the coarsest level (docs/amr_mg_depth.md §6.6).
bool hasStage() const
Whether a STAGE fires below the in-place ladder (docs/amr_mg_depth.md §5.6/§6.5): the coarsest in-pla...
void setRemoveMean(bool on)
Per-level nullspace projection for the singular (periodic pure-Neumann) pressure.
void build(const DO &finest, const Vec< Dim > &h0, OpenFn &&openFn, const LeafHalo< Dim, Bits > *shared0=nullptr, bool liftRoot=true, Index bottomExtent=4)
Phase 3: the finest spacing per axis; every level inherits the aspect ratio (AM1).
void setStagePolicy(const StagePolicy &p)
MgStage< Dim, Bits > & stage()
The stage itself, for tests and diagnostics.
void vcycle(int pre=2, int post=2, int bottom=40, double omega=0.8, std::size_t L=0)
One V-cycle on level L (correction scheme), the distributed mirror of Multigrid::vcycle: ghost refres...
PressureStagePolicy StagePolicy
Which stage fires where the in-place ladder blocks (docs/amr_mg_core_boundary.md §11....
const LeafHalo< Dim, Bits > & halo(std::size_t L=0) const
void sync(std::size_t L, View< double > v) const
Refresh the ghost tail of a level-L vector (the PCG matvec hook uses level 0).
const Poisson & poisson(std::size_t L=0) const
std::size_t numInPlaceLevels() const
How many of those levels are IN PLACE — octree coarsenings plus lifted levels, i.e.
void buildRaw(const DO &finest, const Vec< Dim > &h0, const std::vector< double > &alphaLocal, bool liftRoot=true, Index bottomExtent=4)
Build on finest with its level-0 openness GIVEN as raw rows (AmrPoisson::opennessRaw() layout,...
void build(const DO &finest, double h0, OpenFn &&openFn, const LeafHalo< Dim, Bits > *shared0=nullptr, bool liftRoot=true, Index bottomExtent=4)
Build with cut-cell openness openFn(faceCentreWorld, axis) → [0,1] on the flow's distributed octree (...
typename Octree::Code Code
const IVec< Dim > & stageFrom() const
The global grid the stage moves (the coarsest in-place level's extent).
const AmrGeometry< Dim > & globalGeometry() const
const std::array< bool, Dim > & periodic() const
void initDecomposed(const decomp::BlockDecomposer< Dim > &dec, unsigned lmax, AmrGeometry< Dim > globalGeo, std::array< bool, Dim > periodic, MPI_Comm comm)
As init, but on a GIVEN decomposition of the global root grid dec.globalSize() instead of the proport...
Index findGlobalRoot(const IVec< Dim > &g) const
Local leaf covering global root-cell g, or -1 if not owned by this rank (lmax==0).
BlockOctree< Dim, Bits > Octree
const decomp::BlockDecomposer< Dim > & decomposition() const
The ORB over the global ROOT grid in the CURRENT root units — rank r owns block r.
const IVec< Dim > & blockBrick() const
A SIBLING-MERGE or REPARTITION stage (docs/amr_mg_depth.md §5.6, WO4b; docs/amr_mg_core_boundary....
Index numLeaves(std::size_t L) const override
Cells of continued-ladder level L on this rank's target block — the GLOBAL count for the replicated s...
void build(const DO &d, const Vec< Dim > &h0, const Poisson &ap, Index n, const core::decomp::StageTarget< Dim > &target, int id, Index bottomExtent, const Policy &policy, typename Multigrid< Dim, Bits >::Bottom bottom, bool removeMean)
Build the stage from the level it fires at (d, ap, n as for ReplicatedTailStage) onto target,...
typename Base::Octree Octree
a level's cells on one block
DistributedOctree< Dim, Bits > DO
the level the stage fires at
View< double > targetX() override
The continued ladder's level-0 solution — what moveDown reads.
typename Base::Decomposition Decomposition
the target partition's type
const char * kind() const override
"replicated" | "sibling" | "repartition".
bool active() const override
Whether THIS rank owns a target block, i.e.
std::size_t numLevels() const override
Levels of the continued ladder, its level 0 (the moved level) included. Local.
typename MG::StagePolicy Policy
inherited by the continued ladder
std::string bottomName() const override
"jacobi" | "amg": what solves the continued ladder's coarsest level, WITHOUT the stage's diagnosticSu...
void setRemoveMean(bool on) override
Per-level constant-nullspace projection for the singular periodic pressure; the owner forwards its ow...
void moveUp(View< const double > src, Index nSrc) override
src (this rank's rows of the moved level, device; may be longer than nSrc) → the target's level-0 rhs...
void cycle(int pre, int post, int bottom, double omega) override
One cycle of the continued ladder on targetComm(). Called on active ranks only.
MPI_Comm targetComm() const override
The communicator every collective of the continued ladder runs on.
const Decomposition & targetDecomposition() const override
The decomposition of the moved level's grid this stage targets.
const char * diagnosticSuffix() const override
What pressure_mg_bottom appends for this stage — "+tail" for the replicated one, which is the spellin...
const Octree & targetOctree() const override
The moved level's cells on this rank's target block.
void setBottom(typename Multigrid< Dim, Bits >::Bottom b) override
Collective on the PARENT communicator (it re-publishes the continued ladder's shape,...
MG & multigrid()
The continued ladder (active ranks only).
void moveDown(View< double > dst, Index nDst) override
The target's level-0 solution → the first nDst rows of dst.
Device-resident value refresh over a finalized LeafHalo: pack the owner's local values as a Kokkos ke...
One stage of the pressure hierarchy (docs/amr_mg_depth.md §6.5).
BlockOctree< Dim, Bits > Octree
a level's cells on one block
core::decomp::BlockDecomposer< Dim > Decomposition
the target partition's type
Bottom
What solves the coarsest level (docs/amr_mg_depth.md §6.6).
void removeMeanFvDist(const FvOp &op, View< double > u, MPI_Comm comm)
removeMeanFv with the two mean sums folded across ranks (identical kernels; the Allreduce sits betwee...
void residualFv(const FvOp &op, View< const double > u, View< const double > rhs, View< double > res)
res = rhs − H u.
void jacobiFv(const FvOp &op, View< double > u, View< const double > rhs, View< double > tmp, double omega)
One weighted-Jacobi sweep of H u = rhs (in place).
void restrictField(View< const Index > childStart, View< const Index > childIdx, View< const double > fine, View< double > coarse, Index nCoarse)
Restrict: coarse(p) = mean over p's children (CSR fixed order ⇒ deterministic).
void prolongAdd(View< const Index > c2p, View< const double > coarse, View< double > fine, Index nFine)
Prolong (piecewise-constant) + correct: fine(i) += coarse(c2p(i)).
std::vector< std::array< double, Dim > > transferFieldGradients(const BlockOctree< Dim, Bits > &oldT, const std::vector< double > &oldF)
Per-old-leaf minmod prolongation gradients (per fine-coordinate unit) — transferField's stencil,...
View< Index > faceStart
CSR row offsets, size n+1.
View< double > bcDiag
Dirichlet boundary diagonal per cell (0 if periodic), size n.
View< double > invVol
1/V_i, size n
View< double > faceW
w_f = openness·A_f/d_f per face, size nFaces
Which stage the distributed pressure ladder uses where its in-place lift blocks (docs/amr_mg_depth....
bool enabled
false: the replicated tail only (WO4)
Index maxBlockCells
Core's bound on a target block's cells.
int minExtent
Core's economic trigger / extent cap.