12#ifndef PECLET_AMR_MOMENTUM_HPP
13#define PECLET_AMR_MOMENTUM_HPP
23#include "peclet/core/common/view.hpp"
24#include "peclet/core/solver/coloring.hpp"
25#include "peclet/core/solver/csr_bicgstab.hpp"
26#include "peclet/core/solver/csr_operator.hpp"
27#include "peclet/core/solver/vector_ops.hpp"
31using solver::applyMom;
32using solver::bicgPUpdate;
33using solver::Coloring;
34using solver::dotPlain;
35using solver::greedyColoring;
36using solver::jacobiMom;
37using solver::MomentumOp;
39using solver::multicolorGSMom;
40using solver::residualMom;
44template <
unsigned Bits = 21u>
62template <
unsigned Bits = 21u>
72 const std::vector<Index>&
start0,
const std::vector<Index>&
nbr0,
73 const std::vector<double>&
coef0) {
79 if (
merged == 0 ||
c.numLeaves() == octs_.back().numLeaves())
82 if (
c.numLeaves() == 1)
85 const std::size_t
nl = octs_.size();
93 for (std::size_t
L = 0;
L + 1 <
nl; ++
L) {
97 std::vector<Index> c2p(
static_cast<std::size_t
>(
nf));
98 std::vector<Index>
cnt(
static_cast<std::size_t
>(
nc), 0);
103 c2p[
static_cast<std::size_t
>(
i)] =
p;
105 ++
cnt[
static_cast<std::size_t
>(
p)];
107 std::vector<Index>
cstart(
static_cast<std::size_t
>(
nc) + 1, 0);
109 cstart[
static_cast<std::size_t
>(
p) + 1] =
110 cstart[
static_cast<std::size_t
>(
p)] +
cnt[
static_cast<std::size_t
>(
p)];
111 std::vector<Index>
cidx(
static_cast<std::size_t
>(
nf));
114 Index p = c2p[
static_cast<std::size_t
>(
i)];
116 cidx[
static_cast<std::size_t
>(
cur[
static_cast<std::size_t
>(
p)]++)] =
i;
118 levels_[
L].c2p =
toDevice(c2p,
"mmg_c2p");
123 std::vector<std::map<Index, double>>
acc(
static_cast<std::size_t
>(
nc));
125 Index p = c2p[
static_cast<std::size_t
>(
i)];
128 const double w = 1.0 /
static_cast<double>(
cnt[
static_cast<std::size_t
>(
p)]);
129 acc[
static_cast<std::size_t
>(
p)][
p] += w *
hdiag[
static_cast<std::size_t
>(
i)];
132 Index q = c2p[
static_cast<std::size_t
>(
hnbr[
static_cast<std::size_t
>(k)])];
135 acc[
static_cast<std::size_t
>(
p)][
q] += w *
hcoef[
static_cast<std::size_t
>(k)];
138 std::vector<double>
cdiag(
static_cast<std::size_t
>(
nc), 0.0);
139 std::vector<Index>
cs(
static_cast<std::size_t
>(
nc) + 1, 0);
142 for (
auto&
e :
acc[
static_cast<std::size_t
>(
p)]) {
144 cdiag[
static_cast<std::size_t
>(
p)] =
e.second;
148 cs[
static_cast<std::size_t
>(
p) + 1] =
cs[
static_cast<std::size_t
>(
p)] + off;
150 std::vector<Index>
cn(
static_cast<std::size_t
>(
cs[
static_cast<std::size_t
>(
nc)]));
151 std::vector<double>
ccoef(
static_cast<std::size_t
>(
cs[
static_cast<std::size_t
>(
nc)]));
153 Index k =
cs[
static_cast<std::size_t
>(
p)];
154 for (
auto&
e :
acc[
static_cast<std::size_t
>(
p)])
156 cn[
static_cast<std::size_t
>(k)] =
e.first;
157 ccoef[
static_cast<std::size_t
>(k)] =
e.second;
167 for (
auto&
lv : levels_) {
181 Level&
lv = levels_[
L];
183 if (
L + 1 == levels_.size()) {
189 Level&
cl = levels_[
L + 1];
191 Kokkos::deep_copy(
cl.x, 0.0);
197 std::size_t
numLevels()
const {
return levels_.size(); }
201 const MomentumOp&
op(std::size_t
L = 0)
const {
return levels_[
L].op; }
217 multicolorGSMom(
lv.op,
lv.x,
bc,
lv.col, 1.0);
222 void uploadLevel(std::size_t
L,
const std::vector<double>& diag,
const std::vector<Index>& start,
223 const std::vector<Index>& nbr,
const std::vector<double>& coef) {
224 Level&
lv = levels_[
L];
225 lv.op.n =
static_cast<Index>(diag.size());
227 lv.op.faceStart =
toDevice(start,
"mmg_start");
230 lv.col = greedyColoring(start, nbr,
lv.op.n);
232 std::vector<Octree> octs_;
233 std::vector<Level> levels_;
Per-block adaptive octree over block-local Morton codes.
morton::Morton< Dim, Bits > M
typename M::code_type Code
void setGaussSeidel(bool on)
Opt-in: use multicolour Gauss–Seidel as the smoother (per-level colouring built at build) instead of ...
Index numLeaves(std::size_t L=0) const
std::size_t numLevels() const
typename Octree::Code Code
void vcycle(int pre=2, int post=2, int bottom=30, double omega=0.7, std::size_t L=0)
One V-cycle on level L solving A u = b (correction scheme).
const MomentumOp & op(std::size_t L=0) const
View< double > b(std::size_t L=0)
void build(const Octree &finest, const std::vector< double > &diag0, const std::vector< Index > &start0, const std::vector< Index > &nbr0, const std::vector< double > &coef0)
Build the Galerkin hierarchy from the finest octree + the assembled fine operator CSR (diag + face CS...
View< double > x(std::size_t L=0)
solver::MomentumSolver MomentumSolver
The BiCGStab solver never touched the octree: its Bits parameter was vestigial and is gone in core.
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,...