56#ifndef PECLET_AMR_CF_SCHEME_HPP
57#define PECLET_AMR_CF_SCHEME_HPP
67#include "peclet/core/common/host_parallel.hpp"
68#include "peclet/core/common/types.hpp"
100template <
unsigned Bits,
class Ent,
class Flu
idFn>
115 const double sc =
static_cast<double>(
Index(1) <<
Lc);
123 for (
int tt = 0;
tt < 3; ++
tt) {
131 ((
static_cast<double>(
bf[
tt]) + 0.5 *
sf) - (
static_cast<double>(
bc[
tt]) + 0.5 *
sc)) *
173 std::array<long, 3>
lo =
bc;
176 std::array<long, 3>
q =
lo;
177 for (
int d = 0; d < 3; ++d)
184 sm.w[
sm.n] = 1.0 /
static_cast<double>(1 << 3);
196 const double cUp =
dt / (2.0 *
H) + 0.5 *
dt *
dt / (
H *
H);
197 const double cUm = -
dt / (2.0 *
H) + 0.5 *
dt *
dt / (
H *
H);
213 const double sgn =
okP ? 1.0 : -1.0;
268template <
unsigned Bits,
class Ent,
class Flu
idFn>
273 const double wF = (0.5 *
H) / dist,
wC = (0.5 *
h) / dist;
284template <
class Ent,
class Csr>
286 out.start.assign(
static_cast<std::size_t
>(n) + 1, 0);
288 out.start[
static_cast<std::size_t
>(
i) + 1] =
289 out.start[
static_cast<std::size_t
>(
i)] +
290 static_cast<Index>(
per[
static_cast<std::size_t
>(
i)].size());
291 const Index nz =
out.start[
static_cast<std::size_t
>(n)];
292 out.slot.resize(
static_cast<std::size_t
>(nz));
293 out.coef.resize(
static_cast<std::size_t
>(nz));
296 for (
const auto&
e :
per[
static_cast<std::size_t
>(
i)]) {
297 out.slot[
static_cast<std::size_t
>(k)] =
e.cell;
298 out.coef[
static_cast<std::size_t
>(k)] =
e.w;
310template <
unsigned Bits,
class RowFn,
class Flu
idFn>
313 const Index n =
t.numLeaves();
314 std::vector<std::vector<detail::ScalarEnt>>
per(
static_cast<std::size_t
>(n));
321 const unsigned Li =
t.level(
i);
329 const double scale = factor *
invV * (
a *
c) * ((
Lj >
Li) ? 1.0 : -1.0);
349template <
unsigned Bits,
class RegularFn,
class Flu
idFn>
352 const Index n =
t.numLeaves();
353 std::vector<std::vector<detail::CompEnt>>
per(
static_cast<std::size_t
>(n));
358 const unsigned Li =
t.level(
i);
361 i, [&](
Index j,
int axis,
int dir,
double area,
double dist,
double alpha) {
368 const double scale =
invV * alpha *
area *
static_cast<double>(dir);
378 csr.comp.resize(
csr.slot.size());
381 for (
const auto&
e :
per[
static_cast<std::size_t
>(
i)])
382 csr.comp[
static_cast<std::size_t
>(k++)] =
e.comp;
396template <
unsigned Bits,
class RegularFn,
class Flu
idFn>
400 const Index n =
t.numLeaves();
401 std::array<std::vector<std::vector<detail::ScalarEnt>>, 3>
per;
402 for (
int a = 0;
a < 3; ++
a)
403 per[
static_cast<std::size_t
>(
a)].resize(
static_cast<std::size_t
>(n));
408 const unsigned Li =
t.level(
i);
412 double sdist[3][2] = {};
417 const int s = (dir > 0) ? 0 : 1;
427 for (
int a = 0;
a < 3; ++
a) {
428 if (!
cf[
a][0] && !
cf[
a][1])
430 if (
cnt[
a][0] == 0 ||
cnt[
a][1] == 0)
434 auto&
row =
per[
static_cast<std::size_t
>(
a)][
static_cast<std::size_t
>(
i)];
436 if (axis !=
a || alpha <= 1
e-12)
438 const int s = (dir > 0) ? 0 : 1;
439 const double w = (
s == 0) ?
wp :
wm;
440 const double inv = 1.0 /
static_cast<double>(
cnt[
a][
s]);
441 const double gsgn = (dir > 0) ? 1.0 : -1.0;
443 const double rw = (w - 0.5) *
inv *
gsgn / dist;
460 std::array<CfCsr, 3>
out;
461 for (
int a = 0;
a < 3; ++
a)
491template <
unsigned Bits,
class RegularFn,
class Flu
idFn>
494 const Index n =
t.numLeaves();
498 std::vector<Index>
slotCnt(
static_cast<std::size_t
>(n), 0);
502 slotCnt[
static_cast<std::size_t
>(
i)] =
c;
504 std::vector<Index>
slotBase(
static_cast<std::size_t
>(n) + 1, 0);
511 (n > 0) ?
slotBase[
static_cast<std::size_t
>(n) - 1] +
slotCnt[
static_cast<std::size_t
>(n) - 1]
521 std::vector<std::vector<detail::CompEnt>>
velPer(
static_cast<std::size_t
>(n));
523 const unsigned Li =
t.level(
i);
531 std::vector<detail::CompEnt>
ve;
536 for (
const auto&
e :
ve)
538 d.vel.start[
static_cast<std::size_t
>(slot) + 1] =
static_cast<Index>(
ve.size());
546 d.vel.start[
static_cast<std::size_t
>(
s) + 1] += d.vel.start[
static_cast<std::size_t
>(
s)];
547 d.vel.slot.reserve(
static_cast<std::size_t
>(d.vel.start[
static_cast<std::size_t
>(
nSlots)]));
548 d.vel.coef.reserve(
static_cast<std::size_t
>(d.vel.start[
static_cast<std::size_t
>(
nSlots)]));
549 d.vel.comp.reserve(
static_cast<std::size_t
>(d.vel.start[
static_cast<std::size_t
>(
nSlots)]));
551 for (
const auto&
e :
velPer[
static_cast<std::size_t
>(
i)]) {
552 d.vel.slot.push_back(
e.cell);
553 d.vel.coef.push_back(
e.w);
554 d.vel.comp.push_back(
e.comp);
569template <
unsigned Bits,
class RegularFn,
class Flu
idFn>
572 const Index n =
t.numLeaves();
575 std::vector<Index>
per(
static_cast<std::size_t
>(n), 0);
579 const unsigned Li =
t.level(
i);
588 per[
static_cast<std::size_t
>(
i)] =
c;
592 cnt +=
per[
static_cast<std::size_t
>(
i)];
600 const Index n =
static_cast<Index>(
c.start.size()) - 1;
603 for (
Index k =
c.start[
static_cast<std::size_t
>(
i)];
604 k <
c.start[
static_cast<std::size_t
>(
i) + 1]; ++k)
605 acc +=
c.coef[
static_cast<std::size_t
>(k)] *
606 f[
static_cast<std::size_t
>(
c.slot[
static_cast<std::size_t
>(k)])];
607 out[
static_cast<std::size_t
>(
i)] +=
acc;
613 std::vector<double>&
out) {
614 const Index n =
static_cast<Index>(
c.start.size()) - 1;
617 for (
Index k =
c.start[
static_cast<std::size_t
>(
i)];
618 k <
c.start[
static_cast<std::size_t
>(
i) + 1]; ++k)
619 acc +=
c.coef[
static_cast<std::size_t
>(k)] *
620 u[
static_cast<std::size_t
>(
c.comp[
static_cast<std::size_t
>(k)])]
621 [
static_cast<std::size_t
>(
c.slot[
static_cast<std::size_t
>(k)])];
622 out[
static_cast<std::size_t
>(
i)] +=
acc;
627#ifdef KOKKOS_INLINE_FUNCTION
644 d.
n =
static_cast<Index>(
h.start.size()) - 1;
645 d.
nz =
static_cast<Index>(
h.slot.size());
657 d.
n =
static_cast<Index>(
h.start.size()) - 1;
658 d.
nz =
static_cast<Index>(
h.slot.size());
677 Kokkos::parallel_for(
695 Kokkos::parallel_for(
700 const double v = (
a == 0) ?
u0(
sl(k)) : (
a == 1) ?
u1(
sl(k)) :
u2(
sl(k));
Cell-centered FV Poisson operator on one (periodic) block octree.
unsigned levelOf(Index slot) const
Octree level of an extended slot (local leaf or declared ghost).
Real cellWidth(Index i, int axis) const
Cell width along axis (Phase 3: per axis).
void forEachFaceFull(Index i, Fn &&fn) const
Like forEachFaceNeighbor but exposes geometry for a consistent FV divergence/gradient: fn(neighbour,...
const Vec< Dim > & h0() const
void forEachFaceNeighbor(Index i, Fn &&fn) const
Visit each face neighbour of leaf i: fn(neighbourSlot, coeff, axis, alpha) where coeff = A_f / d_f (p...
std::pair< Index, unsigned > probeSlot(const std::array< long, Dim > &p) const
Covering slot + level of a block-local probe (longs, possibly outside the block).
double faceOpenness(Index i, int axis, int dir) const
Openness of leaf i's face on (axis,dir); 1 if no openness has been set.
Index periodicNeighbor(Index i, int axis, int dir) const
Periodic face neighbour leaf (covering the cell just across the face).
std::array< long, Dim > loOf(Index slot) const
Block-local lo corner of an extended slot as longs (ghosts may lie outside the block).
Real cellVolume(Index i) const
Per-block adaptive octree over block-local Morton codes.
void cfAppendStencil(const AmrPoisson< 3, Bits > &ap, std::vector< Ent > &out, Index coarse, Index fine, int axis, double scale, FluidFn &&fluidOk, CfScheme scheme, const Ent &proto=Ent{})
Append the scheme's (coarse* − coarse_raw) substitution stencil for ONE directed C/F sub-face to out,...
void cfAppendFaceValueDelta(const AmrPoisson< 3, Bits > &ap, std::vector< Ent > &out, Index coarse, Index fine, int axis, double dist, double scale, FluidFn &&fluidOk, CfScheme scheme, const Ent &proto=Ent{})
THE face-value delta for ONE directed 2:1 sub-face, ×scale — the single source of truth shared by the...
void compactCsr(const std::vector< std::vector< Ent > > &per, Csr &out, Index n)
Index countCfCutFaces(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, RegularFn &®ularOk, FluidFn &&fluidOk)
The C/F CENSUS (docs/amr_cf_flux_gate.md §6.5): how many OWNED forEachFaceFull slots (i,...
CfCsrDev uploadCfCsr(const CfCsr &h, const char *name)
CfCompCsr buildCfDivDelta(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, RegularFn &®ularOk, FluidFn &&fluidOk, CfScheme scheme)
(D_scheme − D_std) for the face-average divergence div_i = invV·Σ α·A·dir·(face value).
void cfApply(const CfCsrDev &c, View< const double > f, View< double > out)
out(i) += Σ coef·f(slot).
CfCompCsrDev uploadCfCompCsr(const CfCompCsr &h, const char *name)
CfUfDelta buildCfUfDelta(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, RegularFn &®ularOk, FluidFn &&fluidOk, CfScheme scheme)
void cfApplyCompHost(const CfCompCsr &c, const std::array< std::vector< double >, 3 > &u, std::vector< double > &out)
out(i) += Σ coef·u[comp](slot) (the divergence overlay).
CfCsr buildCfLapDelta(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, double factor, RowFn &&rowOk, FluidFn &&fluidOk, CfScheme scheme)
(∇²_scheme − ∇²_std) as a scalar CSR, ×factor (pass μ for the momentum deferred-correction RHS,...
void cfApplyHost(const CfCsr &c, const std::vector< double > &f, std::vector< double > &out)
out(i) += Σ coef·f(slot) (the scalar overlay: momentum ∇² delta, gradient delta per axis).
std::array< CfCsr, 3 > buildCfGradDelta(const AmrPoisson< 3, Bits > &ap, const BlockOctree< 3, Bits > &t, RegularFn &®ularOk, FluidFn &&fluidOk, CfScheme scheme)
(G_scheme − G_std) for the ABC cell gradient gradOf/grad3.
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,...
void cfApplyComp(const CfCompCsrDev &c, View< const double > u0, View< const double > u1, View< const double > u2, View< double > out)
out(i) += Σ coef·u[comp](slot).
CfScheme
Coarse/fine interface scheme for the collocated flow operators.
@ standard
raw coarse value (two-point flux; 1st-order at 2:1 faces)
@ quadratic
Martin–Cartwright tangential quadratic (2nd-order at 2:1 faces)
Component-tagged CSR overlay (the divergence delta): out(i) += Σ_k coef·u[comp](slot).
std::vector< Index > slot
std::vector< Index > start
std::vector< int8_t > comp
std::vector< double > coef
Device mirror of a CfCsr (empty when the scheme is standard / no C/F rows).
Scalar-input CSR overlay: out(i) += Σ_k coef·f(slot) over rows with C/F faces.
std::vector< double > coef
std::vector< Index > slot
std::vector< Index > start
size n+1
(uf_scheme − uf_std) for the div-free FACE field uf_k = ½(u_i+u_j) − (φ₊−φ₋)/d, one delta row per for...
CfCompCsr vel
reads the velocity components, rows = face slots
An assembled face-CSR: row offsets (size n+1), neighbour index + coefficient per face (size nFaces).