22#ifndef PECLET_CORE_AMR_ADAPT_HPP
23#define PECLET_CORE_AMR_ADAPT_HPP
25#ifdef PECLET_CORE_HAVE_MORTON
40inline double minmod(
double a,
double b) {
43 return (std::fabs(a) < std::fabs(b)) ? a : b;
52template <
int Dim,
unsigned Bits>
54 const std::vector<double>& oldF) {
56 using Coord =
typename BO::Coord;
57 using M =
typename BO::M;
58 auto centroid = [](
const BO& t,
Index i) {
59 auto o = M::from_code(t.code(i)).decode();
60 const double s =
static_cast<double>(Coord(1) << t.level(i));
61 std::array<double, Dim> c{};
62 for (
int d = 0; d < Dim; ++d)
63 c[d] =
static_cast<double>(o[d]) + 0.5 * s;
67 std::vector<std::array<double, Dim>> grad(
static_cast<std::size_t
>(no),
68 std::array<double, Dim>{});
69 for (
Index i = 0; i < no; ++i) {
70 auto ci = centroid(oldT, i);
71 const double ui = oldF[
static_cast<std::size_t
>(i)];
72 for (
int axis = 0; axis < Dim; ++axis) {
77 auto cp = centroid(oldT, jp);
78 auto cm = centroid(oldT, jm);
79 const double sp = (oldF[
static_cast<std::size_t
>(jp)] - ui) / (cp[axis] - ci[axis]);
80 const double sm = (ui - oldF[
static_cast<std::size_t
>(jm)]) / (ci[axis] - cm[axis]);
92template <
int Dim,
unsigned Bits>
97 const std::type_identity_t<std::vector<std::array<double, Dim>>>* gradIn =
nullptr) {
99 using Code =
typename BO::Code;
100 using Coord =
typename BO::Coord;
101 using M =
typename BO::M;
103 auto centroid = [](
const BO& t,
Index i) {
104 auto o = M::from_code(t.code(i)).decode();
105 const double s =
static_cast<double>(Coord(1) << t.level(i));
106 std::array<double, Dim> c{};
107 for (
int d = 0; d < Dim; ++d)
108 c[d] =
static_cast<double>(o[d]) + 0.5 * s;
114 std::vector<std::array<double, Dim>> grad;
115 if (linear && gradIn) {
122 std::vector<double>
nf(
static_cast<std::size_t
>(
nn), 0.0);
123 std::vector<Index>
n2o(
static_cast<std::size_t
>(
nn), -1);
126 const unsigned Lj =
newT.level(
j);
130 const unsigned Lo =
oldT.level(
o);
132 nf[
static_cast<std::size_t
>(
j)] =
oldF[
static_cast<std::size_t
>(
o)];
133 }
else if (
Lo >
Lj) {
135 n2o[
static_cast<std::size_t
>(
j)] =
o;
137 nf[
static_cast<std::size_t
>(
j)] =
oldF[
static_cast<std::size_t
>(
o)];
141 double v =
oldF[
static_cast<std::size_t
>(
o)];
142 for (
int d = 0; d < Dim; ++d)
143 v +=
grad[
static_cast<std::size_t
>(
o)][d] * (
cn[d] -
co[d]);
144 nf[
static_cast<std::size_t
>(
j)] =
v;
149 auto oj = M::from_code(
cj).decode();
150 const Coord
sj = Coord(Coord(1) <<
Lj);
151 double vol = 0.0,
acc = 0.0;
153 auto ok = M::from_code(
oldT.code(k)).decode();
155 for (
int d = 0; d < Dim; ++d)
162 const double w = std::pow(2.0,
static_cast<double>(Dim *
static_cast<int>(
oldT.level(k))));
163 acc += w *
oldF[
static_cast<std::size_t
>(k)];
166 nf[
static_cast<std::size_t
>(
j)] = (
vol > 0.0) ?
acc /
vol : 0.0;
176 std::vector<double>
sv(
static_cast<std::size_t
>(
no), 0.0),
177 vv(
static_cast<std::size_t
>(
no), 0.0);
179 const Index o =
n2o[
static_cast<std::size_t
>(
j)];
182 const double w = std::pow(2.0,
static_cast<double>(Dim *
static_cast<int>(
newT.level(
j))));
183 sv[
static_cast<std::size_t
>(
o)] += w *
nf[
static_cast<std::size_t
>(
j)];
184 vv[
static_cast<std::size_t
>(
o)] += w;
187 const Index o =
n2o[
static_cast<std::size_t
>(
j)];
188 if (
o < 0 ||
vv[
static_cast<std::size_t
>(
o)] <= 0.0)
190 nf[
static_cast<std::size_t
>(
j)] +=
191 oldF[
static_cast<std::size_t
>(
o)] -
192 sv[
static_cast<std::size_t
>(
o)] /
vv[
static_cast<std::size_t
>(
o)];
203template <
int Dim,
unsigned Bits>
207 const Index n =
t.numLeaves();
208 std::vector<int>
f(
static_cast<std::size_t
>(n),
kKeep);
210 const unsigned L =
t.level(
i);
211 const double e =
ind[
static_cast<std::size_t
>(
i)];
213 f[
static_cast<std::size_t
>(
i)] =
kRefine;
220template <
int Dim,
unsigned Bits>
230template <
int Dim,
unsigned Bits>
232 const std::vector<int>&
flags,
bool linear =
true) {
234 using Code =
typename BO::Code;
235 using M =
typename BO::M;
239 for (
unsigned oct = 0;
oct < (1u << Dim); ++
oct) {
240 Code cc = M::from_code(
parent).child(
pl,
oct).code();
248 nt.refineIf([&](Code
c,
unsigned) {
258template <
int Dim,
unsigned Bits>
Per-block adaptive octree over block-local Morton codes.
Index coarsenIf(Pred &&pred)
Merge complete sibling groups (all 2^Dim children present, all at the same level) whose parent satisf...
Index faceNeighbor(Index i, int axis, int dir) const
The leaf across leaf i's face on axis in direction dir (±1), or -1 if it lies outside the block.
double minmod(double a, double b)
std::vector< int > flagByIndicator(const BlockOctree< Dim, Bits > &t, const std::vector< double > &ind, double refineThresh, double coarsenThresh, unsigned finestLevel=0)
AdaptResult< Dim, Bits > adaptField(const BlockOctree< Dim, Bits > &t, const std::vector< double > &f, const std::vector< int > &flags, bool linear=true)
Apply adaptation flags (one level of refine/coarsen) to t carrying field f, then 2:1-balance and rema...
AdaptFlag
Per-leaf adaptation flags from an indicator: refine where ind > refineThresh (and the leaf can go fin...
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,...
AdaptResult< Dim, Bits > adapt(const BlockOctree< Dim, Bits > &t, const std::vector< double > &f, double refineThresh, double coarsenThresh, unsigned finestLevel=0, double eps=0.01, bool linear=true)
All-in-one solution-adaptive step: Löhner indicator → flags → adaptField.
std::vector< double > transferField(const BlockOctree< Dim, Bits > &oldT, const std::vector< double > &oldF, const BlockOctree< Dim, Bits > &newT, bool linear=true, const std::type_identity_t< std::vector< std::array< double, Dim > > > *gradIn=nullptr)
Conservative remap of a leaf field from oldT to newT (same domain).
std::vector< double > lohnerIndicator(const BlockOctree< Dim, Bits > &t, const std::vector< double > &u, double eps=0.01)
Löhner normalized second-difference indicator E_i ∈ [0,1], per leaf, for scalar u (indexed by leaf sl...
std::int64_t Index
Signed index type for grids and particles (supersedes block_decomposer's long int IndxT).
std::vector< double > field
BlockOctree< Dim, Bits > octree