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::AmrFlow< Bits > Class Template Reference

#include <flow.hpp>

Classes

struct  FaceTopologyHost
 The face CSR topology faceField() is indexed by, copied to host: start the per-cell row offsets (size n+1), then per (sub)face the neighbour leaf, the face axis (0/1/2) and the direction (+1/-1, pointing from the owning cell to the neighbour). More...
 

Public Types

enum  StepPhase {
  SP_GLUE , SP_GRAD , SP_CF , SP_OVERLAY ,
  SP_ADV , SP_MOMRHS , SP_MOMSOLVE , SP_DIV ,
  SP_PRES , SP_PRES_MV , SP_PRES_MVOV , SP_PRES_PROJ ,
  SP_PRES_PC , SP_FINISH , SP_N
}
 One incompressible step on device (Stokes, or Navier–Stokes with setAdvection). More...
 
using Octree = BlockOctree< 3, Bits >
 
using SpClock = std::chrono::steady_clock
 

Public Member Functions

void init (const Octree &t, Real h0, Vec< 3 > origin=Vec< 3 >{})
 Cubic-cell overload — the pre-Phase-3 spelling (docs/amr_anisotropic.md §2).
 
void init (const Octree &t, const Vec< 3 > &h0, Vec< 3 > origin=Vec< 3 >{})
 
void initMpi (DistributedOctree< 3, Bits > &d)
 Distributed mode (docs/amr_distributed_flow.md, rung 4): run this solver on one ORB block of a DistributedOctree — the whole step (momentum, pressure, overlays) then executes multi-rank through the LeafHalo ±2 ghost registry established in setSolid.
 
Vec< 3 > betaPerAxis () const
 The viscous coefficient of each derivative axis, mu/h0_a^2 — the octree twin of the structured solver's ‘beta_b = mu’ w_b(Phase 3,docs/amr_anisotropic.md` §4).
 
void setDensity (double rho)
 
void setViscosity (double mu)
 
void setDt (double dt)
 
void setBodyForce (double fx, double fy, double fz)
 
void setPressurePCG (bool on)
 Use MG-preconditioned CG for the pressure solve (default) vs plain V-cycles.
 
void setGhostGradient (bool on)
 Directional ghost cell-gradient for the −∇pⁿ predictor and the projection's cell correction (the AMR analog of flow's collocated set_face_interp(9) hybrid): on cut cells the ABC grad3 reads the DECOUPLED p=0 of solid-centered neighbours through partially-open faces — a gauge-dependent O(1/h) gradient error (measured in tests/study_amr_ghost_apriori.cpp).
 
void setApertureOrder (int order)
 FULL directional ghost-cell projection (the AMR port of flow's collocated set_ghost_projection): the pressure system becomes rho·(L_bin + Delta) phi = rho·D_g(u*) — the BINARY-openness FV Laplacian (a face is open iff its sample + both adjacent centers are fluid; preconditioned by the UNCHANGED openness-MG hierarchy built on that openness) plus the wall-anchored closure overlay on the finest-band rows (peclet::core::scheme, shared with flow), solved by MG-preconditioned BiCGStab on the coupled subspace; the constraint is the ghost-closed divergence of the ½/½ face-averaged field.
 
void setGhostProjection (bool on, int matrixOrder=2, int rhsOrder=2)
 
void setGhostSampled (bool on, double rho=2.2, long maxSamples=0)
 SAMPLED ghost projection: the mixed-level cut-band mode (docs/amr_mixed_level_cut_band_plan.md — cut cells at MULTIPLE octree levels; chain entries across 2:1 boundaries become degree-2 LS virtual samples; no finest-band contract / band throw; level-aware canonical openness; momentum ξ-row seam correction rides along).
 
void setCfScheme (int scheme)
 Coarse/fine (2:1) interface scheme (cf_scheme.hpp): 1 = Martin–Cartwright tangential quadratic, THE DEFAULT since 2026-09-21; 0 = the standard two-point flux (the legacy path, and first-order at level boundaries).
 
void setAdvection (bool on)
 Enable momentum advection ∇·(u u) (default OFF ⇒ Stokes).
 
void setImplicitAdvection (bool on)
 Implicit-FOU deferred correction (default ON).
 
void setAdvectionScheme (int s)
 High-order advection scheme: 0 = second-order upwind (SOU, default), 1 = Koren TVD.
 
void setMomentumTol (double tol)
 Relative tolerance for the per-step momentum BiCGStab solve (default 1e-8).
 
void setPressureTol (double tol)
 Relative tolerance of the PRESSURE solve, for both drivers: the MG-PCG (the default) and the ghost projection's BiCGStab, exactly as flow's set_pressure_pcg tolerance is shared with its ghost BiCGStab.
 
void setUfAdvection (bool on)
 ABLATION (developer tier).
 
void setSeamReconstruction (bool on)
 ABLATION (docs/amr_cf_convective.md §5.5, Q-C).
 
void setMomentumMG (bool on)
 Use the Galerkin velocity multigrid (MomentumMG) as the momentum BiCGStab preconditioner.
 
void setVelocityMGStaircase (bool on)
 Choose the momentum-MG coarse-operator strategy: false (default) = Galerkin (MomentumMG, A_c = R·A·P of the exact cut-cell operator); true = rediscretized staircase (VelocityMG, mirroring flow's VelocityMG).
 
void setVelocityMGMinCoarse (Index m)
 Pore-scale cap for the staircase velocity-MG: the coarsest level keeps ≥ this many cells, so it still resolves the immersed feature (a small object that vanishes from the coarse κ classification leaves an inconsistent operator that diverges).
 
void setMomentumGS (bool on)
 Opt-in: use the multicolour Gauss–Seidel smoother in the momentum MG (Galerkin or staircase) instead of weighted Jacobi — ~2× better smoothing (fewer V-cycles / BiCGStab iters), and the strong fine smoother the staircase needs on the cut band.
 
void setMomentumMGSolver (bool on)
 Opt-in (P4): solve the momentum predictor with the velocity multigrid used as the solver — MG-preconditioned defect correction u ← u + M⁻¹(b − A u) iterated to tolerance — instead of BiCGStab with the same MG as a preconditioner.
 
void setOuterIterations (int n, double tol=1e-6)
 Optional Picard outer loop over the lagged advection (mirror of flow's outerIters_): each outer iteration re-freezes the advecting velocity at the latest u and re-solves the predictor, stopping early when the max |Δu| between successive outer iterates falls below tol.
 
template<class SdfFn >
void setSolid (SdfFn &&sdfFn)
 Build the cut-cell operators (host) + upload all device structures.
 
SpClock::time_point spMark () const
 
void spAdd (int ph, SpClock::time_point t0)
 
void spEndStep ()
 Close a profiled step; print + reset when the window fills.
 
void requireOperator (const char *what) const
 Every solve entry point needs the cut-cell operators that setSolid builds; without them the state views are unallocated and the kernels dereference null (measured: a segfault from Python's Flow.step() before set_solid).
 
void step (int momIters=100, int presIters=60)
 
void project (int presIters=60)
 Pressure projection of the current velocity in place.
 
void finishProjection (Index n)
 Shared projection tail: build the div-free face field from u* + φ, correct the cell velocities (ABC / ghost gradient), rotational pressure update.
 
void beginAdapt ()
 Snapshot the octree topology + (u, p) ahead of an external mesh mutation.
 
template<class SdfFn >
void finishAdapt (SdfFn &&sdfFn)
 Rebuild on the mutated octree and transfer the snapshotted fields onto it.
 
template<class SdfFn >
void rebalanceMpi (SdfFn &&sdfFn)
 Distributed load rebalance (docs/amr_distributed_flow.md, rung 6): re-decompose the octree by leaf count (weighted ORB) and migrate the leaves WITH the state (u, p) to the new owners, then rebuild every solver structure on the new block (full distributed setSolid: new ±2 registry, halos, operators, pressure hierarchy).
 
void setPressure (const std::vector< double > &h)
 Write the accumulated rotational pressure from host (restart / finishAdapt).
 
void zeroSolid (View< double > v)
 Zero a per-leaf field on non-fluid cells (the transferred fields' solid cleanup).
 
std::vector< double > debugSou (int comp)
 DEBUG: the raw high-order advection ∇·(u u_comp) per cell from the current velocity (== host oracle::AmrFlow::advectTerm).
 
template<class MG >
void runMgVcycle (MG &mg, View< const double > r, View< double > z)
 Run one V-cycle of a momentum MG as a preconditioner: z = M⁻¹ r.
 
void copyToHost (const View< double > &d, std::vector< double > &h) const
 Copy a device View into a host vector (sized n_).
 
void setVelocity (int c, const std::vector< double > &h)
 Set a velocity component from host (testing / initial conditions).
 
std::vector< double > velocity (int c) const
 Copy a velocity component back to host (single D2H, no host loop — S2a).
 
std::vector< double > pressure () const
 Copy the pressure field back to host (single D2H), (num_leaves,) — the incremental-rotational p.
 
std::vector< double > localVector (const View< double > &v) const
 Host copy of the LOCAL rows of a (possibly ghost-extended) per-cell field.
 
std::vector< double > velocities () const
 All three velocity components interleaved as a flat (n,3) row-major host buffer (out[i*3+c]) with a single device→host transfer (G6): the three independent component Views are packed on-device first (cheap), so the boundary is crossed once rather than three times as repeated velocity(c) calls would.
 
double divNormL2 ()
 L2 norm of the (openness-weighted) divergence of the current velocity — the ghost-closed divergence when the ghost projection is on (its constraint IS the residual diagnostic).
 
double divNormFace ()
 L2 norm of the APERTURE-weighted divergence of the ABC face field uf_ (built each project()).
 
std::vector< Index > pressureMgLevels () const
 The pressure multigrid's ladder as BUILT on this rank: per-level leaf counts, level 0 first (docs/amr_mg_depth.md §6.7).
 
std::string pressureMgBottom () const
 What actually solves the coarsest pressure level (docs/amr_mg_depth.md §6.6/§6.7): "jacobi" (60 damped-Jacobi sweeps) | "amg" (the agglomerated GraphAMG-PCG bottom, amg_bottom.hpp), with the suffix "+tail" when the coarsest in-place level is gathered and continued redundantly (§6.5).
 
void setPressureBottom (const std::string &kind)
 What solves the coarsest pressure level (docs/amr_mg_depth.md §6.6/§11.6): "auto" (the default — the agglomerated GraphAMG-PCG bottom engages iff the coarsest global extent exceeds pressureBottomExtent(), where 60 damped-Jacobi sweeps stop being a solve), "smoother" (always the sweeps), "agglomerated" (always the exact solve).
 
void setPressureBottomExtent (Index e)
 Where the pressure ladder stops lifting the root and hands over to the bottom (docs/amr_mg_depth.md §6.2/§11.4), in CELLS PER AXIS of the coarsest level: the ladder stops once no axis has more than e cells, and "auto" engages the exact bottom where it stopped above it.
 
Index pressureBottomExtent () const
 The bottom extent the next setSolid builds the ladder with (default 4).
 
std::vector< double > faceField () const
 Copy the divergence-free face field to host (one value per CSR (sub)face, forEachFaceFull order).
 
FaceTopologyHost faceTopology () const
 
std::vector< double > slotCenters () const
 World centre of every slot of the extended (local + ghost) leaf array, row-major (nExt, 3).
 
Index numSeamSampleRecords () const
 Seam-reconstruction census (docs/amr_cf_convective.md §5.2): how many sample records (one per 2:1 sub-face pair that passes the C/F gate) this rank built.
 
Index numSeamLayerRecords () const
 The face-layer half of the census: one record per (regular coarse cell, face) whose far side is refined into four fluid cells — the upstream probe of case 3.
 
Index numLeaves () const
 
Index numGhostCells () const
 Distributed: number of ghost slots in the ±2 registry (0 single-rank).
 
Index numCfGhostColumns () const
 Developer diagnostic: entries of the four C/F-scheme overlays that read a GHOST slot (0 single-rank, 0 with CfScheme::standard).
 
Index numCfCutFaces () const
 The C/F census (docs/amr_cf_flux_gate.md §6.5): owned forEachFaceFull slots on a 2:1 sub-face between two FLUID cells where at least one incident cell is CUT, i.e.
 
bool isFluid (Index i) const
 Per-leaf fluid mask (false inside the solid) — for host-side post-processing / bindings.
 
int lastMomIters () const
 Total momentum BiCGStab iterations (summed over the 3 components) of the last step.
 
int lastPresIters () const
 Pressure PCG iterations of the last step.
 
int lastOuterIters () const
 Picard outer iterations actually run in the last step (1 unless setOuterIterations(>1)).
 
void syncVel ()
 Refresh the ghost tails of the three velocity components (one batched message round).
 
void syncScalar (View< double > v)
 Refresh the ghost tail of one cell scalar (p, φ, Krylov scratch).
 
double allSum (double s) const
 Global sum (identity single-rank).
 
std::array< long, 3 > globalFineExtent () const
 The DOMAIN's fine extent (D1): the block's own single-rank, where block == domain.
 
const FvOp & gpOp0 ()
 The pressure operator the ghost solver runs on (distributed MG level 0 or presMG_'s).
 
template<class SdfFn >
void prepareDistributed (SdfFn &&sdfFn)
 Install the resolver seams, run every prober to the miss-collect fixpoint, freeze the ±2 halo, hook the solvers.
 
void probeCfScheme ()
 Discovery arm for the C/F quadratic scheme (cf_scheme.hpp), run inside prepareDistributed's miss-collect fixpoint so the REAL build in setSolid — after the fixpoint, with every ghost resolved — finds every coordinate already in the registry.
 
void probeCfTangential (Index coarse, int axis)
 Every coordinate cfAppendStencil can probe from the coarse cell of one C/F face: the tangential ± neighbours on the two tangential axes, plus the 2^Dim children covering each coarse-size tangential region (the finer-neighbour branch).
 
void probeSeamLayer ()
 Discovery arm for the SEAM builder (seam_recon.hpp), run beside probeCfScheme() inside prepareDistributed's miss-collect fixpoint.
 
void installGhostMeta ()
 Mirror the halo registry's ghost metadata (block-local lo + level) into mom_ and pres_.
 
void gpProject (View< double > v)
 
void ghostMatvec (View< const double > x, View< double > y)
 
void ghostPrec (View< const double > r, View< double > z)
 
int solveGhostBiCGStab (View< double > x, View< const double > b, int maxIters, double tol=1e-10)
 

Static Public Member Functions

static double maxAbsDiff (View< const double > a, View< const double > b, Index n)
 Max |a − b| over all cells (the Picard outer-loop convergence measure).
 

Detailed Description

template<unsigned Bits = 21u>
class peclet::amr::AmrFlow< Bits >

Definition at line 510 of file flow.hpp.

Member Typedef Documentation

◆ Octree

template<unsigned Bits = 21u>
using peclet::amr::AmrFlow< Bits >::Octree = BlockOctree<3, Bits>

Definition at line 512 of file flow.hpp.

◆ SpClock

template<unsigned Bits = 21u>
using peclet::amr::AmrFlow< Bits >::SpClock = std::chrono::steady_clock

Definition at line 1211 of file flow.hpp.

Member Enumeration Documentation

◆ StepPhase

One incompressible step on device (Stokes, or Navier–Stokes with setAdvection).

momIters BiCGStab iterations for each momentum component; presIters PCG iterations for the pressure solve.

Enumerator
SP_GLUE 
SP_GRAD 
SP_CF 
SP_OVERLAY 
SP_ADV 
SP_MOMRHS 
SP_MOMSOLVE 
SP_DIV 
SP_PRES 
SP_PRES_MV 
SP_PRES_MVOV 
SP_PRES_PROJ 
SP_PRES_PC 
SP_FINISH 
SP_N 

Definition at line 1194 of file flow.hpp.

Member Function Documentation

◆ init() [1/2]

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::init ( const Octree &  t,
Real  h0,
Vec< 3 >  origin = Vec<3>{} 
)
inline

Cubic-cell overload — the pre-Phase-3 spelling (docs/amr_anisotropic.md §2).

Definition at line 515 of file flow.hpp.

Referenced by peclet::amr::pybind::Flow::Flow(), and peclet::amr::AmrFlow< Bits >::initMpi().

◆ init() [2/2]

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::init ( const Octree &  t,
const Vec< 3 > &  h0,
Vec< 3 >  origin = Vec<3>{} 
)
inline

Definition at line 518 of file flow.hpp.

◆ initMpi()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::initMpi ( DistributedOctree< 3, Bits > &  d)
inline

Distributed mode (docs/amr_distributed_flow.md, rung 4): run this solver on one ORB block of a DistributedOctree — the whole step (momentum, pressure, overlays) then executes multi-rank through the LeafHalo ±2 ghost registry established in setSolid.

The octree must be graded + cross-block 2:1 balanced; the origin is the GLOBAL one (every rank samples the geometry at bit-identical world points). Periodic domains only. All the set* configuration calls apply as usual (before setSolid); setSolid / step / project are COLLECTIVE over the octree's communicator. np=1 is bit-identical to init() + the single-rank path on the same octree by construction.

Definition at line 533 of file flow.hpp.

References peclet::amr::DistributedOctree< Dim, Bits >::globalGeometry(), peclet::amr::DistributedOctree< Dim, Bits >::h0(), peclet::amr::AmrFlow< Bits >::init(), and peclet::amr::DistributedOctree< Dim, Bits >::local().

Referenced by peclet::amr::pybind::Flow::Flow().

◆ betaPerAxis()

template<unsigned Bits = 21u>
Vec< 3 > peclet::amr::AmrFlow< Bits >::betaPerAxis ( ) const
inline

The viscous coefficient of each derivative axis, mu/h0_a^2 — the octree twin of the structured solver's ‘beta_b = mu’ w_b(Phase 3,docs/amr_anisotropic.md` §4).

Every entry is the same double on a cubic octree.

Definition at line 540 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::prepareDistributed(), and peclet::amr::AmrFlow< Bits >::setSolid().

◆ setDensity()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setDensity ( double  rho)
inline

◆ setViscosity()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setViscosity ( double  mu)
inline

Definition at line 547 of file flow.hpp.

Referenced by peclet::amr::pybind::Flow::Flow(), and peclet::amr::pybind::Flow::Flow().

◆ setDt()

◆ setBodyForce()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setBodyForce ( double  fx,
double  fy,
double  fz 
)
inline

◆ setPressurePCG()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setPressurePCG ( bool  on)
inline

Use MG-preconditioned CG for the pressure solve (default) vs plain V-cycles.

Definition at line 551 of file flow.hpp.

Referenced by peclet::amr::pybind::Flow::set_pressure_pcg().

◆ setGhostGradient()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setGhostGradient ( bool  on)
inline

Directional ghost cell-gradient for the −∇pⁿ predictor and the projection's cell correction (the AMR analog of flow's collocated set_face_interp(9) hybrid): on cut cells the ABC grad3 reads the DECOUPLED p=0 of solid-centered neighbours through partially-open faces — a gauge-dependent O(1/h) gradient error (measured in tests/study_amr_ghost_apriori.cpp).

The directional gradient is central where both axis neighbours are fluid-centered and 2nd-order one-sided toward the fluid else — O(h²), gauge-exact. The aperture projection (divergence + φ solve + uf) is UNCHANGED (throat-safe).

DEFAULT ON since 2026-08-18, mirroring flow's collocated default set_collocated_scheme("gauge-exact"). Measured there on two periodic sphere beds (peclet-examples benchmarks/porous-scaling): second order at phi=0.50 AND at a contact-tight phi=0.60, against first order for the plain gradient — which additionally failed to reach steady state within 800 steps on three of five rungs of the dense bed. setGhostGradient(false) restores the legacy path. Call before setSolid.

Definition at line 566 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::set_ghost_gradient().

◆ setApertureOrder()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setApertureOrder ( int  order)
inline

FULL directional ghost-cell projection (the AMR port of flow's collocated set_ghost_projection): the pressure system becomes rho·(L_bin + Delta) phi = rho·D_g(u*) — the BINARY-openness FV Laplacian (a face is open iff its sample + both adjacent centers are fluid; preconditioned by the UNCHANGED openness-MG hierarchy built on that openness) plus the wall-anchored closure overlay on the finest-band rows (peclet::core::scheme, shared with flow), solved by MG-preconditioned BiCGStab on the coupled subspace; the constraint is the ghost-closed divergence of the ½/½ face-averaged field.

Implies setGhostGradient. (matrixOrder, rhsOrder) = closure orders for the implicit matrix vs the RHS divergence; PRODUCTION CANDIDATE (re-framed 2026-08-24 after flow's attractor campaign, flow/doc/collocated_invisible_subspace.md + fluid_only_constraint_plan.md): the ghost projection is the FLUID-ONLY constraint scheme — the only measured collocated architecture that is stable, unique (no attractor family: the aperture scheme's solid-centered pressure DOFs are constraint multipliers its gauge-exact gradient never reads, giving an affine family of steady states selected by march protocol) AND converging (flow clean ladders both beds; Z&H −0.018% at N=128). Default remains OFF (aperture, matching flow's gauge-exact default) until the suite-wide flip decision; select with setGhostProjection(true) == flow's set_collocated_scheme("ghost").

Closure orders: (2, 2) is the DEFAULT and the only order pair cleared for production — flow's hardening Phase A measured the (1, 2) mixed form march-UNSTABLE above ~2000 spheres (an operator/RHS mismatch re-injected each step through the rotational pressure accumulation; flow/doc/ghost_hardening_findings_A.md). (1, 2) stays callable for the existing parity records only. Throws in setSolid if an overlay row's ±2 reach crosses a 2:1 level boundary (finest-band margin). The 2026-08-19 advection-economics retirement (aperture MG-PCG cheaper per step, docs/amr_aperture_advection_plan.md §RESOLVED) still holds as a COST statement; the scheme choice is now a robustness/uniqueness decision. Call before setSolid. Aperture estimator order for the (fallback) aperture projection: 2 = analytic marching-squares (DEFAULT since 2026-08-26), 1 = legacy one-sample model. Before setSolid.

Definition at line 596 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::FlowDiagnostics::set_aperture_order().

◆ setGhostProjection()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setGhostProjection ( bool  on,
int  matrixOrder = 2,
int  rhsOrder = 2 
)
inline

◆ setGhostSampled()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setGhostSampled ( bool  on,
double  rho = 2.2,
long  maxSamples = 0 
)
inline

SAMPLED ghost projection: the mixed-level cut-band mode (docs/amr_mixed_level_cut_band_plan.md — cut cells at MULTIPLE octree levels; chain entries across 2:1 boundaries become degree-2 LS virtual samples; no finest-band contract / band throw; level-aware canonical openness; momentum ξ-row seam correction rides along).

Implies the ghost projection (engages when the resolved scheme is ghost — the AUTO default or an explicit setGhostProjection(true)). Single-rank only (the distributed sample halo is a later rung). Call before setSolid. Mixed-level sampled cut band. rho is the least-squares cloud radius factor (rho = factor * max(h, H); default 2.2 = the shipped behaviour) and maxSamples the nearest-N candidate cap (0 = uncapped, the default) — the two cloud-economy knobs of the M2a study (docs/archive/amr_march_perf_and_distributed_plan.md); until 2026-09-10 they were the PECLET_CORE_GPS_RHO / _MAXN environment variables. Call before setSolid.

Definition at line 613 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::set_ghost_sampled().

◆ setCfScheme()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setCfScheme ( int  scheme)
inline

Coarse/fine (2:1) interface scheme (cf_scheme.hpp): 1 = Martin–Cartwright tangential quadratic, THE DEFAULT since 2026-09-21; 0 = the standard two-point flux (the legacy path, and first-order at level boundaries).

Order at C/F rows: divergence 1.95, cell gradient 1.95, momentum SOLUTION 2.0 (test_amr_cf_vector). End to end on a self-similar graded ladder (docs/amr_graded_convergence.md §3) the DEFAULT matters where the interface has tangential variation — order 1.60 (quadratic) against 0.41 (standard) — and is inert by geometry where it does not, so cf=0 is kept only for reproducing pre-2026-09-21 graded results. Applied to everything the STEADY solution feels: the momentum diffusion (lagged deferred-correction RHS term), the RHS divergence constraint, and the pressure gradients (predictor + cell correction). The pressure MATRIX / MG rails / PCG / ghost BiCGStab stay on the standard consistent operator (at the fixed point φ→0, the matrix C/F order does not move the steady solution — the (1,2)-mixed philosophy). Works in both aperture and ghost-projection modes. Call before setSolid.

Definition at line 631 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::set_cf_scheme().

◆ setAdvection()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setAdvection ( bool  on)
inline

Enable momentum advection ∇·(u u) (default OFF ⇒ Stokes).

The high-order flux is second-order upwind (SOU) by default; the first-order-upwind part is solved implicitly (folded into the momentum operator) and the (SOU−FOU) difference is the explicit deferred correction — unconditionally stable for the FOU part, exact-SOU at steady state. This is the same implicit-FOU + deferred-SOU scheme as the host oracle::AmrFlow and flow's collocated grid (set_implicit_advection).

Definition at line 638 of file flow.hpp.

Referenced by peclet::amr::pybind::Flow::set_advection().

◆ setImplicitAdvection()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setImplicitAdvection ( bool  on)
inline

Implicit-FOU deferred correction (default ON).

OFF ⇒ the whole high-order advection is explicit (no FOU in the operator) — only conditionally stable.

Definition at line 641 of file flow.hpp.

Referenced by peclet::amr::pybind::Flow::set_implicit_advection().

◆ setAdvectionScheme()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setAdvectionScheme ( int  s)
inline

High-order advection scheme: 0 = second-order upwind (SOU, default), 1 = Koren TVD.

Definition at line 643 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::set_advection_scheme().

◆ setMomentumTol()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setMomentumTol ( double  tol)
inline

Relative tolerance for the per-step momentum BiCGStab solve (default 1e-8).

The momentum predictor is one step of a pseudo-transient outer iteration to steady state, so it need not be solved to round-off — a looser tolerance bounds the per-step cost. NOTE on the cost regime: the momentum operator is the Helmholtz (ρ/dt)I − μ∇²; for a physical dt the (ρ/dt) mass term dominates and it is cheap (diagonally dominant). At the large dt used for steady drag, ρ/dt → 0 and it degrades to a bare elliptic Laplacian (a saddle-point Stokes problem) — as hard as the pressure Poisson and, unlike the pressure, solved here per velocity component. Bounding the tolerance (this knob) caps the over-solve; making it actually scale needs the velocity multigrid (setMomentumMG).

Definition at line 653 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::set_momentum_tolerance().

◆ setPressureTol()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setPressureTol ( double  tol)
inline

Relative tolerance of the PRESSURE solve, for both drivers: the MG-PCG (the default) and the ghost projection's BiCGStab, exactly as flow's set_pressure_pcg tolerance is shared with its ghost BiCGStab.

Default 1e-10 — the value hard-coded here until 2026-09-21, so the default path is unchanged. The iteration CAP is the presIters argument of step()/project(); this is the accuracy it works to. Tightening past the momentum tolerance buys nothing (the predictor is what the projection is cleaning up); loosening it is the cheapest cost knob in the step.

Definition at line 660 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::set_pressure_tolerance().

◆ setUfAdvection()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setUfAdvection ( bool  on)
inline

ABLATION (developer tier).

The advecting velocity of the momentum advection: the projected, divergence-free face field uf (ON, the shipped Almgren–Bell–Colella scheme — the face field the projection just made solenoidal IS the conservative advecting flux) or, with on=false, the un-projected ½(u_i+u_j) cell→face average that the first step uses before any projection has run. Exists to A/B exactly this choice: it is the ONE discretization difference between this solver and peclet.flow's SolverColocated on a uniform grid (flow's cadv::adv_vel still averages the cell velocities — the swap its own design note prescribes was never made). See docs/amr_flow_uniform_parity.md.

Definition at line 669 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::set_uf_advection().

◆ setSeamReconstruction()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setSeamReconstruction ( bool  on)
inline

ABLATION (docs/amr_cf_convective.md §5.5, Q-C).

Reconstruct the ADVECTED value with level-aware probes at every face whose upwind-side stencil crosses a 2:1 octree seam — default ON. The tables are built either way (setSolid); this captures one bool in the two advective kernels, so false is TODAY'S arithmetic bit for bit (gate G0) and the switch can be flipped between steps. Inert without advection, with CfScheme::standard (no tables are built), and on any mesh with no 2:1 face. Leave it on in production: it exists for the A/B of §12, where it cuts the one-step seam truncation 7.9e-3 → 2.0e-3 at no measurable cost. Local (every rank must pass the same value, as for every scheme switch).

Definition at line 678 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::set_seam_reconstruction().

◆ setMomentumMG()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setMomentumMG ( bool  on)
inline

Use the Galerkin velocity multigrid (MomentumMG) as the momentum BiCGStab preconditioner.

This is the scalable momentum solver: the coarse operators are the exact assembled cut-cell operator coarsened by R·A·P, so the V-cycle is a consistent preconditioner and the momentum iteration count stays ~flat with N instead of growing like the Jacobi-preconditioned BiCGStab (the dominant cost at scale and large dt). It only changes the preconditioner (the matvec is the exact operator) ⇒ identical converged step. Call before setSolid (the hierarchy is built there). Default ON.

Definition at line 686 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::set_momentum_mg().

◆ setVelocityMGStaircase()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setVelocityMGStaircase ( bool  on)
inline

Choose the momentum-MG coarse-operator strategy: false (default) = Galerkin (MomentumMG, A_c = R·A·P of the exact cut-cell operator); true = rediscretized staircase (VelocityMG, mirroring flow's VelocityMG).

Call before setSolid. Both are device-resident BiCGStab preconditioners; this lets the two be benchmarked head-to-head.

Definition at line 692 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::set_velocity_mg_staircase().

◆ setVelocityMGMinCoarse()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setVelocityMGMinCoarse ( Index  m)
inline

Pore-scale cap for the staircase velocity-MG: the coarsest level keeps ≥ this many cells, so it still resolves the immersed feature (a small object that vanishes from the coarse κ classification leaves an inconsistent operator that diverges).

Feature-dependent — raise it for small immersed objects. Only affects the staircase strategy.

Definition at line 697 of file flow.hpp.

◆ setMomentumGS()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setMomentumGS ( bool  on)
inline

Opt-in: use the multicolour Gauss–Seidel smoother in the momentum MG (Galerkin or staircase) instead of weighted Jacobi — ~2× better smoothing (fewer V-cycles / BiCGStab iters), and the strong fine smoother the staircase needs on the cut band.

Default off. Call before setSolid.

Definition at line 701 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::set_momentum_gs().

◆ setMomentumMGSolver()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setMomentumMGSolver ( bool  on)
inline

Opt-in (P4): solve the momentum predictor with the velocity multigrid used as the solver — MG-preconditioned defect correction u ← u + M⁻¹(b − A u) iterated to tolerance — instead of BiCGStab with the same MG as a preconditioner.

This is the faithful mirror of flow's velocity solve, which uses no Krylov method at all (RB-GS smoother / velocity-MG directly): the momentum operator is diagonally dominant and invertible, so the stationary iteration converges, and unlike BiCGStab it cannot break down on the strongly non-symmetric (D_rescale + FOU) operator (no bi-orthogonal recurrence to lose — the failure mode P5 had to symmetrise the smoother to avoid). With the GS smoother (setMomentumGS) and a velocity-MG (setMomentumMG, default on) this is the full RB-GS/MG flow path; with MG off it degrades to plain damped-Jacobi sweeps (flow's smoothComp). Default off (BiCGStab stays the validated default). Requires setMomentumMG to actually be multigrid-accelerated; otherwise the Richardson iteration converges only slowly.

Definition at line 715 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::set_momentum_mg_solver().

◆ setOuterIterations()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setOuterIterations ( int  n,
double  tol = 1e-6 
)
inline

Optional Picard outer loop over the lagged advection (mirror of flow's outerIters_): each outer iteration re-freezes the advecting velocity at the latest u and re-solves the predictor, stopping early when the max |Δu| between successive outer iterates falls below tol.

n = 1 (default) is the single lagged step used until now (no extra cost). Only meaningful with advection on; for Stokes the loop converges in one iteration. n ≥ 1.

Definition at line 722 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::set_outer_iterations().

◆ setSolid()

template<unsigned Bits = 21u>
template<class SdfFn >
void peclet::amr::AmrFlow< Bits >::setSolid ( SdfFn &&  sdfFn)
inline

Build the cut-cell operators (host) + upload all device structures.

Requires the density / viscosity / dt to be set first (the momentum operator carries ρ/dt and μ).

Definition at line 730 of file flow.hpp.

References peclet::amr::AmrFlow< Bits >::betaPerAxis(), peclet::amr::buildCfDivDelta(), peclet::amr::buildCfGradDelta(), peclet::amr::buildCfLapDelta(), peclet::amr::buildCfUfDelta(), peclet::amr::buildFaceGeom(), peclet::amr::buildGhostOverlay(), peclet::amr::buildGhostOverlaySampled(), peclet::amr::buildMomSeamDelta(), peclet::amr::AmrPoisson< Dim, Bits >::buildOpenness(), peclet::amr::buildSampledGradCsr(), peclet::amr::buildSeamRecon(), peclet::amr::countCfCutFaces(), peclet::amr::findPocketCells(), peclet::amr::FaceGeom::fluid, peclet::amr::AmrFlow< Bits >::globalFineExtent(), peclet::amr::AmrPoisson< Dim, Bits >::init(), peclet::amr::AmrPoisson< Dim, Bits >::levelOf(), peclet::amr::makeBinaryOpenFn(), peclet::amr::makeBinaryOpenFnMixed(), peclet::amr::FaceGeom::nbr, peclet::amr::BlockOctree< Dim, Bits >::numLeaves(), peclet::amr::AmrFlow< Bits >::prepareDistributed(), peclet::amr::quadratic, peclet::amr::AmrFlow< Bits >::runMgVcycle(), peclet::amr::AmrPoisson< Dim, Bits >::setOrigin(), peclet::amr::standard, peclet::amr::FaceGeom::start, peclet::amr::AmrFlow< Bits >::syncScalar(), peclet::amr::transferFieldGradients(), peclet::amr::BlockOctreeView< Dim, Bits >::upload(), peclet::amr::uploadCfCompCsr(), peclet::amr::uploadCfCsr(), peclet::amr::uploadGhostGradCsr(), peclet::amr::uploadGhostOverlay(), and peclet::amr::uploadGhostOverlaySampled().

Referenced by peclet::amr::AmrFlow< Bits >::finishAdapt(), peclet::amr::AmrFlow< Bits >::rebalanceMpi(), peclet::amr::pybind::Flow::set_solid(), and peclet::amr::pybind::Flow::set_solid_spheres().

◆ spMark()

◆ spAdd()

◆ spEndStep()

◆ requireOperator()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::requireOperator ( const char *  what) const
inline

Every solve entry point needs the cut-cell operators that setSolid builds; without them the state views are unallocated and the kernels dereference null (measured: a segfault from Python's Flow.step() before set_solid).

Throw a named error instead.

Definition at line 1274 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::beginAdapt(), peclet::amr::AmrFlow< Bits >::project(), and peclet::amr::AmrFlow< Bits >::step().

◆ step()

◆ project()

◆ finishProjection()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::finishProjection ( Index  n)
inline

Shared projection tail: build the div-free face field from u* + φ, correct the cell velocities (ABC / ghost gradient), rotational pressure update.

div_ holds the projection's RHS divergence (aperture or ghost-closed).

Definition at line 1552 of file flow.hpp.

References peclet::amr::applyGhostGrad(), peclet::amr::applyGhostGradCsr(), peclet::amr::buildFaceField(), peclet::amr::cfApply(), peclet::amr::cfApplyComp(), peclet::amr::correct(), peclet::amr::grad3(), peclet::amr::presUpdate(), peclet::amr::AmrFlow< Bits >::syncScalar(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::project().

◆ beginAdapt()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::beginAdapt ( )
inline

Snapshot the octree topology + (u, p) ahead of an external mesh mutation.

Distributed: the mutation is distributedAdapt (+ the driver's geometry-band re-refinement + balance), which KEEPS the ORB ownership — so the snapshot, the conservative transferField in finishAdapt and the field restore are all block-local per rank, and finishAdapt's setSolid rebuilds the ±2 halo/operators on the new local mesh (collective). For OWNERSHIP changes use rebalanceMpi instead.

Definition at line 1611 of file flow.hpp.

References peclet::amr::AmrFlow< Bits >::pressure(), peclet::amr::AmrFlow< Bits >::requireOperator(), peclet::amr::transferFieldGradients(), peclet::amr::transferGradients(), and peclet::amr::AmrFlow< Bits >::velocity().

Referenced by peclet::amr::pybind::Flow::begin_adapt().

◆ finishAdapt()

template<unsigned Bits = 21u>
template<class SdfFn >
void peclet::amr::AmrFlow< Bits >::finishAdapt ( SdfFn &&  sdfFn)
inline

◆ rebalanceMpi()

template<unsigned Bits = 21u>
template<class SdfFn >
void peclet::amr::AmrFlow< Bits >::rebalanceMpi ( SdfFn &&  sdfFn)
inline

Distributed load rebalance (docs/amr_distributed_flow.md, rung 6): re-decompose the octree by leaf count (weighted ORB) and migrate the leaves WITH the state (u, p) to the new owners, then rebuild every solver structure on the new block (full distributed setSolid: new ±2 registry, halos, operators, pressure hierarchy).

Pure redistribution — every cell's u/p value is preserved bit-for-bit; uf restarts from the ½-average fallback for one step (as after finishAdapt). Collective; distributed mode only.

Definition at line 1661 of file flow.hpp.

References peclet::amr::AmrFlow< Bits >::pressure(), peclet::amr::AmrFlow< Bits >::setPressure(), peclet::amr::AmrFlow< Bits >::setSolid(), peclet::amr::AmrFlow< Bits >::setVelocity(), peclet::amr::transferFieldGradients(), peclet::amr::AmrFlow< Bits >::velocity(), and peclet::amr::AmrFlow< Bits >::zeroSolid().

Referenced by peclet::amr::pybind::Flow::rebalance_mpi().

◆ setPressure()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setPressure ( const std::vector< double > &  h)
inline

Write the accumulated rotational pressure from host (restart / finishAdapt).

Definition at line 1679 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::finishAdapt(), peclet::amr::AmrFlow< Bits >::rebalanceMpi(), and peclet::amr::pybind::Flow::set_pressure().

◆ zeroSolid()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::zeroSolid ( View< double >  v)
inline

Zero a per-leaf field on non-fluid cells (the transferred fields' solid cleanup).

Definition at line 1687 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::finishAdapt(), and peclet::amr::AmrFlow< Bits >::rebalanceMpi().

◆ debugSou()

template<unsigned Bits = 21u>
std::vector< double > peclet::amr::AmrFlow< Bits >::debugSou ( int  comp)
inline

DEBUG: the raw high-order advection ∇·(u u_comp) per cell from the current velocity (== host oracle::AmrFlow::advectTerm).

Isolates the SOU kernel from the solve.

Definition at line 1698 of file flow.hpp.

References peclet::amr::advectExplicit(), peclet::amr::AmrFlow< Bits >::syncVel(), and peclet::amr::transferFieldGradients().

◆ runMgVcycle()

template<unsigned Bits = 21u>
template<class MG >
void peclet::amr::AmrFlow< Bits >::runMgVcycle ( MG &  mg,
View< const double >  r,
View< double >  z 
)
inline

Run one V-cycle of a momentum MG as a preconditioner: z = M⁻¹ r.

Templated on the MG type (MomentumMG or VelocityMG — both expose b(0)/x(0)/vcycle), so the BiCGStab preconditioner is decoupled from the coarse-operator strategy.

Definition at line 1715 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::setSolid().

◆ maxAbsDiff()

template<unsigned Bits = 21u>
static double peclet::amr::AmrFlow< Bits >::maxAbsDiff ( View< const double >  a,
View< const double >  b,
Index  n 
)
inlinestatic

Max |a − b| over all cells (the Picard outer-loop convergence measure).

Definition at line 1732 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::step().

◆ copyToHost()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::copyToHost ( const View< double > &  d,
std::vector< double > &  h 
) const
inline

Copy a device View into a host vector (sized n_).

Definition at line 1747 of file flow.hpp.

References peclet::amr::transferFieldGradients().

◆ setVelocity()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setVelocity ( int  c,
const std::vector< double > &  h 
)
inline

Set a velocity component from host (testing / initial conditions).

Definition at line 1754 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::finishAdapt(), peclet::amr::AmrFlow< Bits >::rebalanceMpi(), and peclet::amr::pybind::Flow::set_velocity().

◆ velocity()

template<unsigned Bits = 21u>
std::vector< double > peclet::amr::AmrFlow< Bits >::velocity ( int  c) const
inline

Copy a velocity component back to host (single D2H, no host loop — S2a).

Local rows only (the distributed ghost tail is an implementation detail).

Definition at line 1762 of file flow.hpp.

References peclet::amr::AmrFlow< Bits >::localVector(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::beginAdapt(), peclet::amr::AmrFlow< Bits >::rebalanceMpi(), and peclet::amr::pybind::Flow::velocity().

◆ pressure()

template<unsigned Bits = 21u>
std::vector< double > peclet::amr::AmrFlow< Bits >::pressure ( ) const
inline

Copy the pressure field back to host (single D2H), (num_leaves,) — the incremental-rotational p.

Local rows only.

Definition at line 1765 of file flow.hpp.

References peclet::amr::AmrFlow< Bits >::localVector().

Referenced by peclet::amr::AmrFlow< Bits >::beginAdapt(), peclet::amr::pybind::Flow::pressure(), and peclet::amr::AmrFlow< Bits >::rebalanceMpi().

◆ localVector()

template<unsigned Bits = 21u>
std::vector< double > peclet::amr::AmrFlow< Bits >::localVector ( const View< double > &  v) const
inline

Host copy of the LOCAL rows of a (possibly ghost-extended) per-cell field.

Definition at line 1768 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::pressure(), and peclet::amr::AmrFlow< Bits >::velocity().

◆ velocities()

template<unsigned Bits = 21u>
std::vector< double > peclet::amr::AmrFlow< Bits >::velocities ( ) const
inline

All three velocity components interleaved as a flat (n,3) row-major host buffer (out[i*3+c]) with a single device→host transfer (G6): the three independent component Views are packed on-device first (cheap), so the boundary is crossed once rather than three times as repeated velocity(c) calls would.

Definition at line 1781 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::velocities().

◆ divNormL2()

template<unsigned Bits = 21u>
double peclet::amr::AmrFlow< Bits >::divNormL2 ( )
inline

L2 norm of the (openness-weighted) divergence of the current velocity — the ghost-closed divergence when the ghost projection is on (its constraint IS the residual diagnostic).

Definition at line 1795 of file flow.hpp.

References peclet::amr::AmrFlow< Bits >::allSum(), peclet::amr::cfApplyComp(), peclet::amr::divergence(), peclet::amr::ghostDivergDelta(), peclet::amr::ghostDivergDeltaSampled(), peclet::amr::AmrFlow< Bits >::syncVel(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::divergence_norm().

◆ divNormFace()

template<unsigned Bits = 21u>
double peclet::amr::AmrFlow< Bits >::divNormFace ( )
inline

L2 norm of the APERTURE-weighted divergence of the ABC face field uf_ (built each project()).

MEANINGFUL ON THE APERTURE PATH ONLY. There it is the φ-solve residual, far below the cell field's O(h²) divNormL2 — including across 2:1 interfaces — and test_amr_face_field pins it.

Under the GHOST projection it is NOT the residual of the constraint that was solved, and reads O(1) on a perfectly healthy solve (measured on the Z&H sphere: 34 at N=32, 184 at N=64, while the velocities match peclet.flow to 1e-6 — docs/amr_flow_uniform_parity.md §2a). The reason is that the ghost scheme's constraint is this divergence PLUS the overlay delta (ghostDivergDelta, folded into div_ by project() before the solve), and that delta is a functional of the CELL velocities, not of uf — so the ghost residual cannot be written as a norm of uf at all. divNormL2() already adds it and IS the right residual there; use that. Note also that this is an unnormalized sum over fluid cells, so it grows with resolution and with velocity magnitude and cannot be read as an absolute number.

Definition at line 1824 of file flow.hpp.

References peclet::amr::AmrFlow< Bits >::allSum(), peclet::amr::divFaceNorm(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::FlowDiagnostics::divergence_norm_face().

◆ pressureMgLevels()

template<unsigned Bits = 21u>
std::vector< Index > peclet::amr::AmrFlow< Bits >::pressureMgLevels ( ) const
inline

The pressure multigrid's ladder as BUILT on this rank: per-level leaf counts, level 0 first (docs/amr_mg_depth.md §6.7).

Levels below the root brick are lifted levels; tail levels are appended when the redundant tail engages (WO4) — GLOBAL counts, identical on every rank, the first of them the moved coarsest in-place level itself. Empty before setSolid. Local (no communication). Compare against peclet.amr.predict_hierarchy rather than against a literal.

Definition at line 1834 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::FlowDiagnostics::pressure_mg_levels(), and peclet::amr::AmrFlow< Bits >::spEndStep().

◆ pressureMgBottom()

template<unsigned Bits = 21u>
std::string peclet::amr::AmrFlow< Bits >::pressureMgBottom ( ) const
inline

What actually solves the coarsest pressure level (docs/amr_mg_depth.md §6.6/§6.7): "jacobi" (60 damped-Jacobi sweeps) | "amg" (the agglomerated GraphAMG-PCG bottom, amg_bottom.hpp), with the suffix "+tail" when the coarsest in-place level is gathered and continued redundantly (§6.5).

Under the default "auto" it matches predict_hierarchy's bottom; "jacobi" before setSolid. Local.

Definition at line 1852 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::pressure_mg_bottom(), and peclet::amr::AmrFlow< Bits >::spEndStep().

◆ setPressureBottom()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setPressureBottom ( const std::string &  kind)
inline

What solves the coarsest pressure level (docs/amr_mg_depth.md §6.6/§11.6): "auto" (the default — the agglomerated GraphAMG-PCG bottom engages iff the coarsest global extent exceeds pressureBottomExtent(), where 60 damped-Jacobi sweeps stop being a solve), "smoother" (always the sweeps), "agglomerated" (always the exact solve).

Flow's three spellings. Changes the preconditioner, never the converged pressure; §11.4(a) measured identical iteration counts for smoother and agglomerated in all nine cases at the default extent.

Takes effect AT ONCE on the hierarchy already built (the bottom is re-decided in place) and is kept for every later setSolid, so it may be called before or after it. Distributed it is COLLECTIVE — the re-decision may build the replicated stage (DistributedFlowMultigrid:: setBottom) — so call it on every rank.

Exceptions
std::runtime_erroron any other string.

Definition at line 1868 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::set_pressure_bottom().

◆ setPressureBottomExtent()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::setPressureBottomExtent ( Index  e)
inline

Where the pressure ladder stops lifting the root and hands over to the bottom (docs/amr_mg_depth.md §6.2/§11.4), in CELLS PER AXIS of the coarsest level: the ladder stops once no axis has more than e cells, and "auto" engages the exact bottom where it stopped above it.

Default 4, where the 60 sweeps are exact; Python spells it Flow.set_pressure_bottom_extent(cells=), a count, not a length. The shipped default is measured, not preferred (§11.4: 8 moves the iteration count by ~1 on one case in three; tests/study/amr_pressure_depth.py –sweep). Only STORED here: it takes effect at the next setSolid, where the ladder is built. Local.

Exceptions
std::runtime_errorif e < 1.

Definition at line 1894 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::set_pressure_bottom_extent().

◆ pressureBottomExtent()

template<unsigned Bits = 21u>
Index peclet::amr::AmrFlow< Bits >::pressureBottomExtent ( ) const
inline

The bottom extent the next setSolid builds the ladder with (default 4).

Definition at line 1900 of file flow.hpp.

Referenced by peclet::amr::pybind::Flow::pressure_bottom_extent().

◆ faceField()

template<unsigned Bits = 21u>
std::vector< double > peclet::amr::AmrFlow< Bits >::faceField ( ) const
inline

Copy the divergence-free face field to host (one value per CSR (sub)face, forEachFaceFull order).

Definition at line 1904 of file flow.hpp.

Referenced by peclet::amr::pybind::Flow::face_field().

◆ faceTopology()

◆ slotCenters()

template<unsigned Bits = 21u>
std::vector< double > peclet::amr::AmrFlow< Bits >::slotCenters ( ) const
inline

World centre of every slot of the extended (local + ghost) leaf array, row-major (nExt, 3).

Built from the block-local anchors the halo registry mirrors into pres_, plus the block's own fine-grid origin, so a ghost's centre is its OWNER's centre — the global identity a decomposition-independence check needs.

Definition at line 1959 of file flow.hpp.

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

Referenced by peclet::amr::AmrFlow< Bits >::faceTopology().

◆ numSeamSampleRecords()

template<unsigned Bits = 21u>
Index peclet::amr::AmrFlow< Bits >::numSeamSampleRecords ( ) const
inline

Seam-reconstruction census (docs/amr_cf_convective.md §5.2): how many sample records (one per 2:1 sub-face pair that passes the C/F gate) this rank built.

LOCAL under MPI, like numCfGhostColumns; 0 with CfScheme::standard and on any mesh without a 2:1 face.

Definition at line 1973 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::num_seam_sample_records().

◆ numSeamLayerRecords()

template<unsigned Bits = 21u>
Index peclet::amr::AmrFlow< Bits >::numSeamLayerRecords ( ) const
inline

The face-layer half of the census: one record per (regular coarse cell, face) whose far side is refined into four fluid cells — the upstream probe of case 3.

LOCAL under MPI.

Definition at line 1976 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::num_seam_layer_records().

◆ numLeaves()

template<unsigned Bits = 21u>
Index peclet::amr::AmrFlow< Bits >::numLeaves ( ) const
inline

◆ numGhostCells()

template<unsigned Bits = 21u>
Index peclet::amr::AmrFlow< Bits >::numGhostCells ( ) const
inline

Distributed: number of ghost slots in the ±2 registry (0 single-rank).

Definition at line 1979 of file flow.hpp.

◆ numCfGhostColumns()

template<unsigned Bits = 21u>
Index peclet::amr::AmrFlow< Bits >::numCfGhostColumns ( ) const
inline

Developer diagnostic: entries of the four C/F-scheme overlays that read a GHOST slot (0 single-rank, 0 with CfScheme::standard).

Nonzero is the evidence that the quadratic closure actually reaches across a block seam instead of falling back there.

Definition at line 1983 of file flow.hpp.

◆ numCfCutFaces()

template<unsigned Bits = 21u>
Index peclet::amr::AmrFlow< Bits >::numCfCutFaces ( ) const
inline

The C/F census (docs/amr_cf_flux_gate.md §6.5): owned forEachFaceFull slots on a 2:1 sub-face between two FLUID cells where at least one incident cell is CUT, i.e.

the sub-faces on which the per-face gate withholds the quadratic face value and the scheme falls back to the standard two-point one (§7: an O(h) face value, on a codimension-2 set for the production graded meshes). 0 on every uniform or finest-band mesh. LOCAL under MPI, like numCfGhostColumns; Σ_ranks is exactly the single-rank count.

Definition at line 1990 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::num_cf_cut_faces().

◆ isFluid()

template<unsigned Bits = 21u>
bool peclet::amr::AmrFlow< Bits >::isFluid ( Index  i) const
inline

Per-leaf fluid mask (false inside the solid) — for host-side post-processing / bindings.

Definition at line 1992 of file flow.hpp.

References peclet::amr::transferFieldGradients().

Referenced by peclet::amr::pybind::Flow::is_fluid().

◆ lastMomIters()

template<unsigned Bits = 21u>
int peclet::amr::AmrFlow< Bits >::lastMomIters ( ) const
inline

Total momentum BiCGStab iterations (summed over the 3 components) of the last step.

Definition at line 1994 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::last_mom_iters().

◆ lastPresIters()

template<unsigned Bits = 21u>
int peclet::amr::AmrFlow< Bits >::lastPresIters ( ) const
inline

Pressure PCG iterations of the last step.

Definition at line 1996 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::last_pres_iters().

◆ lastOuterIters()

template<unsigned Bits = 21u>
int peclet::amr::AmrFlow< Bits >::lastOuterIters ( ) const
inline

Picard outer iterations actually run in the last step (1 unless setOuterIterations(>1)).

Definition at line 1998 of file flow.hpp.

Referenced by peclet::amr::pybind::FlowDiagnostics::last_outer_iters().

◆ syncVel()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::syncVel ( )
inline

Refresh the ghost tails of the three velocity components (one batched message round).

Definition at line 2003 of file flow.hpp.

References peclet::amr::LeafHaloExchange::exchange3().

Referenced by peclet::amr::AmrFlow< Bits >::debugSou(), peclet::amr::AmrFlow< Bits >::divNormL2(), peclet::amr::AmrFlow< Bits >::project(), and peclet::amr::AmrFlow< Bits >::step().

◆ syncScalar()

◆ allSum()

◆ globalFineExtent()

template<unsigned Bits = 21u>
std::array< long, 3 > peclet::amr::AmrFlow< Bits >::globalFineExtent ( ) const
inline

The DOMAIN's fine extent (D1): the block's own single-rank, where block == domain.

The sampled overlay's minimum-image period must be this and never the block's, or the cloud metric would differ per rank (finding F2 in decomposition-dependent form).

Definition at line 2023 of file flow.hpp.

References peclet::amr::AmrPoisson< Dim, Bits >::fineExt(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::prepareDistributed(), and peclet::amr::AmrFlow< Bits >::setSolid().

◆ gpOp0()

template<unsigned Bits = 21u>
const FvOp & peclet::amr::AmrFlow< Bits >::gpOp0 ( )
inline

The pressure operator the ghost solver runs on (distributed MG level 0 or presMG_'s).

Definition at line 2032 of file flow.hpp.

Referenced by peclet::amr::AmrFlow< Bits >::ghostMatvec(), and peclet::amr::AmrFlow< Bits >::gpProject().

◆ prepareDistributed()

◆ probeCfScheme()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::probeCfScheme ( )
inline

Discovery arm for the C/F quadratic scheme (cf_scheme.hpp), run inside prepareDistributed's miss-collect fixpoint so the REAL build in setSolid — after the fixpoint, with every ghost resolved — finds every coordinate already in the registry.

It is a LIGHT, GATE-FREE traversal, not the builders in a probe mode, for two reasons. (a) The builders' row/fluid predicates come from mom_, and mom_ is mid-build during the fixpoint (on the sampled path it is not built at all until after it) — a probe sequence short-circuited by a gate that is not yet valid would leave a coordinate undiscovered, and LeafHalo::resolve THROWS on an unknown coord after finalize(). Issuing the full set unconditionally is a strict superset of what any gating can ask for. (b) It is far cheaper than four CSR builds per round.

The extra probes cost no ghosts: a child coordinate that lands inside a same-level or coarser neighbour canonicalizes to that neighbour's own leaf anchor in LeafHalo::resolveMisses, so the registry gains map entries, never slots.

One traversal covers all four builders: buildCfLapDelta walks mom_.lap() and the other three walk pres_, but both are AmrPoisson over the SAME octree with the same resolver and the same ghost list, their face enumerations visit the identical neighbour set, and cfAppendStencil's probe pattern depends only on the C/F pair and the face axis.

Host-parallel, like the FaceGeom face sweep above: LeafHalo::resolve's miss registration is mutex-guarded and the miss SET is coord-keyed, so ghost-slot numbering stays canonical under any schedule (docs/amr_setup_parallel_plan.md, F1).

Definition at line 2151 of file flow.hpp.

References peclet::amr::AmrPoisson< Dim, Bits >::forEachFaceFull(), peclet::amr::AmrPoisson< Dim, Bits >::levelOf(), peclet::amr::BlockOctree< Dim, Bits >::numLeaves(), peclet::amr::AmrFlow< Bits >::probeCfTangential(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::prepareDistributed().

◆ probeCfTangential()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::probeCfTangential ( Index  coarse,
int  axis 
)
inline

Every coordinate cfAppendStencil can probe from the coarse cell of one C/F face: the tangential ± neighbours on the two tangential axes, plus the 2^Dim children covering each coarse-size tangential region (the finer-neighbour branch).

Definition at line 2167 of file flow.hpp.

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

Referenced by peclet::amr::AmrFlow< Bits >::probeCfScheme(), and peclet::amr::AmrFlow< Bits >::probeSeamLayer().

◆ probeSeamLayer()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::probeSeamLayer ( )
inline

Discovery arm for the SEAM builder (seam_recon.hpp), run beside probeCfScheme() inside prepareDistributed's miss-collect fixpoint.

Everything the builder reaches from a LOCAL cell is already registered — the face sweep probes every sub-face neighbour of every local row and probeCfScheme the tangential reach from the coarse cell of every local C/F face. What is NOT is what it reaches from the NEIGHBOUR j of a local face when j is a ghost, because then j owns no local row: (case 3) the four fine cells of the face layer BEYOND j, and (case 2) the tangential reach of cfAppendStencil from j's own coarser upstream cell. Both are what the J-side of a face descriptor reads, so without them the record would be withheld at a block seam and np = 1 would stop being bitwise against single-rank.

Like probeCfScheme it is GATE-FREE on the layer probes (issuing them for every face, not only the refined ones, is a strict superset and costs no ghosts: a coordinate inside a same-level or coarser neighbour canonicalizes to that neighbour's own anchor, which the face sweep has already registered). The case-2 tangential probes DO reach one cell further, so they are issued only where the upstream really is coarser; an upstream that is still unresolved this round resolves in the next one and the fixpoint picks it up then.

Definition at line 2205 of file flow.hpp.

References peclet::amr::AmrPoisson< Dim, Bits >::forEachFaceFull(), peclet::amr::AmrPoisson< Dim, Bits >::levelOf(), peclet::amr::AmrPoisson< Dim, Bits >::loOf(), peclet::amr::BlockOctree< Dim, Bits >::numLeaves(), peclet::amr::AmrPoisson< Dim, Bits >::periodicNeighbor(), peclet::amr::AmrFlow< Bits >::probeCfTangential(), peclet::amr::AmrPoisson< Dim, Bits >::probeSlot(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::prepareDistributed().

◆ installGhostMeta()

template<unsigned Bits = 21u>
void peclet::amr::AmrFlow< Bits >::installGhostMeta ( )
inline

Mirror the halo registry's ghost metadata (block-local lo + level) into mom_ and pres_.

Definition at line 2239 of file flow.hpp.

References peclet::amr::AmrPoisson< Dim, Bits >::setGhosts(), and peclet::amr::transferFieldGradients().

Referenced by peclet::amr::AmrFlow< Bits >::prepareDistributed().

◆ gpProject()

◆ ghostMatvec()

◆ ghostPrec()

◆ solveGhostBiCGStab()


The documentation for this class was generated from the following file: