peclet-amr 0.2.0
Block-local-Morton AMR octree + collocated cut-cell Navier–Stokes solver (header-only C++20, Kokkos + MPI)
Loading...
Searching...
No Matches
peclet::amr::detail Namespace Reference

Classes

struct  CompEnt
 
struct  GhostOverlayRef
 
struct  ScalarEnt
 

Functions

double minmod (double a, double b)
 
template<unsigned Bits, class Ent , class FluidFn >
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, scaled.
 
template<unsigned Bits, class Ent , class FluidFn >
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 divergence RHS and the advecting face field, so that D_std(Δuf) ≡ Δ_cfDiv holds entry by entry (docs/amr_cf_flux_gate.md §4, rule (I)).
 
template<class Ent , class Csr >
void compactCsr (const std::vector< std::vector< Ent > > &per, Csr &out, Index n)
 
bool gpsSolveDense (int n, double *A, double *b)
 Gaussian elimination with partial pivoting (small dense normal equations).
 
template<unsigned Bits, class WrapFn , class EmitFn >
void forEachCoveringSlot (const AmrPoisson< 3, Bits > &pres, const long lo[3], const long hi[3], WrapFn &&wrapLocal, EmitFn &&emit, bool descendPending=false)
 DD1 (docs/amr_march_perf_and_distributed_plan.md) — the LS cloud's probe descent.
 
void gpsMonomials (const double d[3], int deg, double *m, int &nm)
 
template<int Dim>
Vec< Dim > filledVec (Real v)
 Vec<Dim> with every component set to v (C++ has no aggregate-fill initializer).
 
template<int Dim>
Index maxExtent (const IVec< Dim > &G)
 
template<int Dim>
bool gridCanHalve (const IVec< Dim > &G, Index bottomExtent)
 The grid half of the §6.2 rule: stop when the bottom smoother is already exact, and when the grid cannot halve into a cube level with at least two cells per axis.
 
template<int Dim>
long long cellsOf (const IVec< Dim > &G)
 
template<int Dim>
void pushLevel (MgLadderPrediction< Dim > &p, const IVec< Dim > &G, MgLevelKind kind)
 
template<unsigned Bits>
bool seamFaceLayer (const AmrPoisson< 3, Bits > &ap, Index C, int axis, int dir, std::array< Index, 4 > &cells)
 The four sub-face neighbour leaves across C's face (axis, dir), in forEachFaceFull's own sub-face order.
 
template<int Dim>
const std::array< std::array< int, Dim >,(1<< Dim)> & vtkCorners ()
 
template<>
const std::array< std::array< int, 3 >, 8 > & vtkCorners< 3 > ()
 
template<>
const std::array< std::array< int, 2 >, 4 > & vtkCorners< 2 > ()
 

Function Documentation

◆ minmod()

double peclet::amr::detail::minmod ( double  a,
double  b 
)
inline

◆ cfAppendStencil()

template<unsigned Bits, class Ent , class FluidFn >
void peclet::amr::detail::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{} 
)
inline

Append the scheme's (coarse* − coarse_raw) substitution stencil for ONE directed C/F sub-face to out, scaled.

coarse is interpolated at fine's tangential position across the face normal axis. CfScheme::standard appends nothing (no substitution). CfScheme::quadratic is the Martin–Cartwright per-tangential-axis quadratic — the same arithmetic as AmrPoisson::coarseStar / Multigrid::addCoarseStarStencil, plus the fluid gate.

Definition at line 101 of file cf_scheme.hpp.

Referenced by peclet::amr::buildCfGradDelta(), peclet::amr::buildCfLapDelta(), and peclet::amr::buildSeamRecon().

◆ cfAppendFaceValueDelta()

template<unsigned Bits, class Ent , class FluidFn >
void peclet::amr::detail::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{} 
)
inline

THE face-value delta for ONE directed 2:1 sub-face, ×scale — the single source of truth shared by the divergence RHS and the advecting face field, so that D_std(Δuf) ≡ Δ_cfDiv holds entry by entry (docs/amr_cf_flux_gate.md §4, rule (I)).

buildCfDivDelta calls it with scale = invV·α·A·dir (its row coefficient), so its row is the divergence coefficient times the slot row buildCfUfDelta builds with scale = 1.

wF = (H/2)/dist,  wC = (h/2)/dist          (dist = the face's centre-to-centre distance)
Δ = scale·[(wF−½)·u_F + (wC−½)·u_C + wC·(u_C* − u_C)]

with u_C* the scheme's tangential substitution (cfAppendStencil). Entries are pushed in the order fine, coarse, stencil — the order both builders used before they shared this code, so an inert mesh stays bit-identical.

ANISOTROPIC OCTREES (a live bug fixed here as a side effect; docs/amr_cf_flux_gate.md §6.2): the widths are taken on the FACE NORMAL axis and the distance is forEachFaceFull's dist, which is that same axis.

THE CULPRIT WAS THE FACE BUILDER. Until 2026-09-22 buildCfUfDelta took both widths on axis 0 (cellWidth(i), the cubic spelling) and divided them by the face-axis dist, mixing two axes: on h0 = (1, ½, 2) a y-directed 2:1 sub-face got wF = 4/3, wC = 2/3, i.e. wF + wC = 2 — roughly DOUBLE the velocity on every off-axis C/F sub-face of an anisotropic graded mesh. buildCfDivDelta was dimensionally right: it took H, h AND d = ½(H+h) all on axis 0, so only their (axis-free) ratios entered and its weights were correct on any mesh. The two books therefore disagreed on EVERY C/F sub-face of an anisotropic octree, cut or not — an O(1) violation of rule (I) with no cut cell in sight. Gated since 2026-09-22 by test_amr_cf_vector section 7, which reads 7.447e+02 (ref 7.766e+01) with the old builders and 4.399e-15 with this one.

BIT-IDENTITY OF THE REFACTOR IS AN ISOTROPIC STATEMENT. On an isotropic octree the two spellings of d are bitwise equal: cellWidth scales h0 by an exact power of two, and ½·(h0·2^Lc + h0·2^Lf) and (½·(2^Lc+2^Lf))·h0 are the same correctly-rounded value of 1.5·2^Lf·h0 (rounding commutes with an exact factor of 2). On an ANISOTROPIC octree Δ_cfDiv moves at ULP level wherever h0[axis]/h0[0] is not itself a power of two — fl(½·h0_a·2^Lc) / fl(1.5·h0_a·2^Lf) against the axis-0 quotient: measured, wF and wC differ in the last bit at aspect 0.3 and 0.7 and are bitwise equal at 0.5, 2 and 1/3. So the byte gate's "no hash moves" acceptance covers the isotropic case, which is every scenario it runs (all extent=[1,1,1]); an anisotropic recording would have moved in the last digits.

Definition at line 269 of file cf_scheme.hpp.

Referenced by peclet::amr::buildCfDivDelta(), and peclet::amr::buildCfUfDelta().

◆ compactCsr()

template<class Ent , class Csr >
void peclet::amr::detail::compactCsr ( const std::vector< std::vector< Ent > > &  per,
Csr &  out,
Index  n 
)
inline

◆ gpsSolveDense()

bool peclet::amr::detail::gpsSolveDense ( int  n,
double *  A,
double *  b 
)
inline

Gaussian elimination with partial pivoting (small dense normal equations).

Definition at line 89 of file ghost_projection_sampled.hpp.

References peclet::amr::transferFieldGradients().

◆ forEachCoveringSlot()

template<unsigned Bits, class WrapFn , class EmitFn >
void peclet::amr::detail::forEachCoveringSlot ( const AmrPoisson< 3, Bits > &  pres,
const long  lo[3],
const long  hi[3],
WrapFn &&  wrapLocal,
EmitFn &&  emit,
bool  descendPending = false 
)
inline

DD1 (docs/amr_march_perf_and_distributed_plan.md) — the LS cloud's probe descent.

Enumerate the DISTINCT covering slots of every fine cell in the inclusive, unwrapped, block-local fine-coord box [lo, hi], reaching the octree through pres.probeSlot ALONE — never through a search over the local leaf array — so the enumerated set is a pure function of the octree and identical under any decomposition (the D6 discipline). Probe a region's lo corner; if the covering leaf contains the whole region, emit it; otherwise split the longest axis at the COARSEST power-of-two boundary inside it (so regions stay octree-aligned) and recurse. Terminal regions partition the box and each lies inside one leaf, so every leaf overlapping the box is emitted at least once — and a leaf straddling a split is emitted several times, so callers must dedup. Cost is O(leaves overlapping the box) probes.

wrapLocal(p) returns the block-local coord of p's canonical (domain-wrapped) image — the probe frame's offset from the frame pres.loOf answers in.

A negative slot (LeafHalo::kPending during the distributed discovery fixpoint, or a non-periodic exit) is emitted as-is; by default its region is NOT descended (the leaf's extent is unknown), so the fixpoint learns one octree level per round. descendPending (discovery rounds ONLY — never the final build, whose enumeration must stay exact) splits a pending region anyway, down to 4 fine cells per axis: every lo-corner probe registers a miss, so the pending part of a box resolves at 4-cell granularity in ONE collective round and leaves finer than 4 cells take at most two more — the D3 fix for the 5–9-round setup fixpoint. The extra probes stay inside the box, and any leaf covering a coord in the box overlaps the box, which the final enumeration visits anyway — so discovery resolves a superset of nothing: the ghost set is unchanged.

Definition at line 148 of file ghost_projection_sampled.hpp.

References peclet::amr::transferFieldGradients().

◆ gpsMonomials()

void peclet::amr::detail::gpsMonomials ( const double  d[3],
int  deg,
double *  m,
int &  nm 
)
inline

◆ filledVec()

template<int Dim>
Vec< Dim > peclet::amr::detail::filledVec ( Real  v)
inline

Vec<Dim> with every component set to v (C++ has no aggregate-fill initializer).

Definition at line 26 of file leaf_field.hpp.

References peclet::amr::transferFieldGradients().

◆ maxExtent()

template<int Dim>
Index peclet::amr::detail::maxExtent ( const IVec< Dim > &  G)

Definition at line 158 of file mg_predict.hpp.

References peclet::amr::transferFieldGradients().

◆ gridCanHalve()

template<int Dim>
bool peclet::amr::detail::gridCanHalve ( const IVec< Dim > &  G,
Index  bottomExtent 
)

The grid half of the §6.2 rule: stop when the bottom smoother is already exact, and when the grid cannot halve into a cube level with at least two cells per axis.

Definition at line 168 of file mg_predict.hpp.

References peclet::amr::transferFieldGradients().

◆ cellsOf()

template<int Dim>
long long peclet::amr::detail::cellsOf ( const IVec< Dim > &  G)

Definition at line 178 of file mg_predict.hpp.

References peclet::amr::transferFieldGradients().

◆ pushLevel()

template<int Dim>
void peclet::amr::detail::pushLevel ( MgLadderPrediction< Dim > &  p,
const IVec< Dim > &  G,
MgLevelKind  kind 
)

◆ seamFaceLayer()

template<unsigned Bits>
bool peclet::amr::detail::seamFaceLayer ( const AmrPoisson< 3, Bits > &  ap,
Index  C,
int  axis,
int  dir,
std::array< Index, 4 > &  cells 
)
inline

The four sub-face neighbour leaves across C's face (axis, dir), in forEachFaceFull's own sub-face order.

False unless all four resolve and sit EXACTLY one level finer than C (the 2:1 balance guarantees that when the far side is refined at all).

Definition at line 82 of file seam_recon.hpp.

References peclet::amr::AmrPoisson< Dim, Bits >::levelOf(), peclet::amr::AmrPoisson< Dim, Bits >::loOf(), peclet::amr::AmrPoisson< Dim, Bits >::probeSlot(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::buildSeamRecon().

◆ vtkCorners()

template<int Dim>
const std::array< std::array< int, Dim >,(1<< Dim)> & peclet::amr::detail::vtkCorners ( )
inline

◆ vtkCorners< 3 >()

template<>
const std::array< std::array< int, 3 >, 8 > & peclet::amr::detail::vtkCorners< 3 > ( )
inline

Definition at line 32 of file vtu_io.hpp.

References peclet::amr::transferFieldGradients().

◆ vtkCorners< 2 >()

template<>
const std::array< std::array< int, 2 >, 4 > & peclet::amr::detail::vtkCorners< 2 > ( )
inline

Definition at line 38 of file vtu_io.hpp.

References peclet::amr::transferFieldGradients().