Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
9564f20
refactor(boundary): prepare model-aware hyperbolic faces
wolf75222 Jul 28, 2026
4dcc6e2
fix(boundary): preserve 2.5D slip-wall parity
wolf75222 Jul 28, 2026
586c473
fix(boundary): retain slip walls after compile
wolf75222 Jul 28, 2026
8fa1db4
fix(physics): complete axial variable role ABI
wolf75222 Jul 28, 2026
fa28274
test: register axial boundary integration proof
wolf75222 Jul 28, 2026
bf36faa
fix(boundary): make slip-wall role lookup type-safe
wolf75222 Jul 28, 2026
8125b0c
refactor(boundary): prepare model-aware hyperbolic faces
wolf75222 Jul 28, 2026
f5a7ed6
fix(boundary): preserve 2.5D slip-wall parity
wolf75222 Jul 28, 2026
5093320
fix(boundary): retain slip walls after compile
wolf75222 Jul 28, 2026
7cf733b
fix(physics): complete axial variable role ABI
wolf75222 Jul 28, 2026
4c29008
test: register axial boundary integration proof
wolf75222 Jul 28, 2026
b399676
fix(boundary): make slip-wall role lookup type-safe
wolf75222 Jul 28, 2026
fc9bbe9
fix(boundary): preserve mapped periodic topology on master
wolf75222 Jul 29, 2026
99966df
test(boundary): migrate MPI plan to typed faces
wolf75222 Jul 29, 2026
c99b48f
fix(boundary): reject unprepared characteristic fallback
wolf75222 Jul 29, 2026
f1fa2ff
refactor(boundary): remove scalar component-count adapter
wolf75222 Jul 29, 2026
1519e61
feat(boundary): report prepared transport capabilities
wolf75222 Jul 29, 2026
033c4b3
feat(boundary): prepare primitive fixed inflow with model conversion
wolf75222 Jul 29, 2026
8d80201
fix(model): reject unequal representation arities
wolf75222 Jul 29, 2026
0190677
docs(model): state the flat conversion arity contract
wolf75222 Jul 29, 2026
6e26f98
test(boundary): qualify AMR physical and coarse-fine ownership
wolf75222 Jul 29, 2026
3ee7b77
feat(boundary): execute analytic inflow on native devices
wolf75222 Jul 29, 2026
1f84502
feat(recovery): add transactional prepared recovery chain
wolf75222 Jul 29, 2026
5d17efa
test(numerics): add fail-closed prepared provider gate
wolf75222 Jul 29, 2026
6fe34e7
fix(riemann): reject non-finite Roe candidates explicitly
wolf75222 Jul 29, 2026
c85cc18
feat(recovery): cut over primitive materialization consumer
wolf75222 Jul 29, 2026
f296e77
merge: refresh ADC-753 on current master
wolf75222 Jul 29, 2026
80463b6
fix(recovery): roll back abandoned tentative publication
wolf75222 Jul 29, 2026
a7d5b4a
Merge corrected ADC-753 recovery foundation into ADC-757 gate
wolf75222 Jul 29, 2026
c055260
Merge refreshed ADC-757 gate into ADC-755 consumer cutover
wolf75222 Jul 29, 2026
6bc8851
ci(cpp): budget variable recovery chain
wolf75222 Jul 29, 2026
35d21f8
Merge refreshed ADC-757 gate into ADC-755 consumer cutover
wolf75222 Jul 29, 2026
247f956
Merge ADC-753 CI catalog fix into ADC-757 gate
wolf75222 Jul 29, 2026
ed7e163
feat(recovery): consume typed face recovery before fluxes
wolf75222 Jul 29, 2026
efe57ea
test(recovery): prove face refusals across device and MPI
wolf75222 Jul 29, 2026
cff0b1c
docs(recovery): document face publication contract
wolf75222 Jul 29, 2026
30892c3
ci(cpp): budget prepared numerics gate
wolf75222 Jul 29, 2026
4516335
Merge ADC-757 CI catalog fix into ADC-755 face cutover
wolf75222 Jul 29, 2026
22f43a8
Merge current master into ADC-749 boundary pipeline
wolf75222 Jul 29, 2026
9d07b4e
Merge remote ADC-749 restack history
wolf75222 Jul 29, 2026
09607f6
Merge updated ADC-749 boundary pipeline into characteristic fail-closed
wolf75222 Jul 29, 2026
c4371e1
Merge updated characteristic fail-closed boundary layer into capabili…
wolf75222 Jul 29, 2026
4373d8c
Merge updated boundary capability report into primitive conversion layer
wolf75222 Jul 29, 2026
927590c
test(boundary): cover merged conversion topology and CI routing
wolf75222 Jul 29, 2026
cb8f2ed
Merge updated primitive boundary conversion into AMR qualification
wolf75222 Jul 29, 2026
cfbfd19
Merge updated AMR boundary qualification into analytic inflow
wolf75222 Jul 29, 2026
2da599f
Merge current master into ADC-753 recovery chain
wolf75222 Jul 29, 2026
9d4d2d9
Merge restacked ADC-753 into ADC-757 numerics gate
wolf75222 Jul 29, 2026
0aaf4b0
Fail closed on mapped analytic boundary coordinates
wolf75222 Jul 30, 2026
889ad00
Document mapped analytic boundary limitation
wolf75222 Jul 30, 2026
f4b0ff2
Merge remote-tracking branch 'origin/master' into codex/adc754-explic…
wolf75222 Jul 30, 2026
dc32cb4
Merge origin/master into ADC-749 boundary pipeline integration
wolf75222 Jul 30, 2026
32cd495
Merge remote-tracking branch 'origin/codex/adc757-prepared-numerics-g…
wolf75222 Jul 30, 2026
b74d08b
Merge updated ADC-749 boundary pipeline into characteristic fail-clos…
wolf75222 Jul 30, 2026
7f2a545
Merge updated characteristic fail-closed boundary layer into capabili…
wolf75222 Jul 30, 2026
a4ddf37
Merge updated boundary capability envelope into primitive conversion …
wolf75222 Jul 30, 2026
11beff7
test(solvers): fence prepared local nonlinear authority
wolf75222 Jul 30, 2026
3c8c9e5
Merge updated primitive boundary conversion into AMR qualification in…
wolf75222 Jul 30, 2026
5921937
Merge updated AMR boundary qualification into analytic inflow integra…
wolf75222 Jul 30, 2026
95a0ba4
Merge current master into ADC-753 recovery chain
wolf75222 Jul 30, 2026
6779c90
Merge refreshed ADC-753 recovery foundation into ADC-757 gate
wolf75222 Jul 30, 2026
08edcb2
Make analytic boundary installation collective
wolf75222 Jul 30, 2026
ca579ec
Merge current master into ADC-754 recovery validation
wolf75222 Jul 30, 2026
7ef3bf2
Merge refreshed ADC-757 gate into ADC-755 consumer cutover
wolf75222 Jul 30, 2026
79e0d98
Preflight analytic boundaries before halo mutation
wolf75222 Jul 30, 2026
f6de77b
Merge ADC-757 prepared numerics gate
wolf75222 Jul 30, 2026
ecb8d36
Merge ADC-749 collective analytic boundary pipeline
wolf75222 Jul 30, 2026
6b000e7
Merge ADC-754 explicit Roe recovery policy
wolf75222 Jul 30, 2026
53a6a7e
Merge ADC-755 recovery consumer cutover
wolf75222 Jul 30, 2026
0c40994
Fix Kokkos concurrency reporting compatibility
wolf75222 Jul 30, 2026
7c0f42b
Expand ADC-757 gate with delivered P2 evidence
wolf75222 Jul 30, 2026
29270af
Track ADC-752 in the prepared numerics evidence ledger
wolf75222 Jul 30, 2026
e6e8ab6
Merge ADC-750 prepared nonlinear authority guard
wolf75222 Jul 30, 2026
ac7acb4
Merge ADC-749 Kokkos compatibility follow-up
wolf75222 Jul 30, 2026
414f11a
Fix MPI execution context in axial boundary proof
wolf75222 Jul 30, 2026
96df188
Merge ADC-749 explicit MPI bind proof follow-up
wolf75222 Jul 30, 2026
d67f672
test(numerics): execute exact MPI boundary proof
wolf75222 Jul 30, 2026
7ce1952
Merge standalone Kokkos compatibility into P2
wolf75222 Jul 30, 2026
bdb662c
fix(boundary): require prepared linearization sessions
wolf75222 Jul 30, 2026
ba0b601
fix(architecture): admit analytic boundary expressions
wolf75222 Jul 30, 2026
0d2213e
fix(nonlinear): reject unpublished Newton diagnostics
wolf75222 Jul 30, 2026
ed42f91
fix(riemann): reject non-finite HLLC candidates
wolf75222 Jul 30, 2026
34b7d7f
test(numerics): admit capability-driven Riemann gate proofs
wolf75222 Jul 30, 2026
600836d
test(numerics): prove collective MPI failure handling
wolf75222 Jul 30, 2026
df6a23d
Merge current master into P2 consolidation
wolf75222 Jul 30, 2026
61bd2f3
fix(codegen): bind qualified flux provider packs (ADC-682)
wolf75222 Jul 30, 2026
d7b3401
test(codegen): prove exact flux provider identity (ADC-682)
wolf75222 Jul 30, 2026
a34649c
feat(numerics): bind generated flux provider slots
wolf75222 Jul 30, 2026
2cc1f15
tests: prove qualified native flux binding
wolf75222 Jul 30, 2026
3c33ea6
docs: record generated flux provider ABI
wolf75222 Jul 30, 2026
cae1252
test(boundary): ratchet remaining ADC-749 legacy authorities
wolf75222 Aug 1, 2026
cc76573
feat(riemann): expose recovery capability boundary
wolf75222 Aug 1, 2026
e5d0dbd
docs(riemann): state recovery policy non-claims
wolf75222 Aug 1, 2026
4b3d1fc
feat(recovery): expose consumer cutover capability boundary
wolf75222 Aug 1, 2026
9af3540
docs(recovery): state complete cutover non-claims
wolf75222 Aug 1, 2026
aef0c0f
feat(recovery): enforce model admissibility policies
wolf75222 Aug 1, 2026
b5e61e7
test(recovery): cover declared model admissibility
wolf75222 Aug 1, 2026
0249f8a
docs(recovery): document model admissibility authoring
wolf75222 Aug 1, 2026
24536d4
feat(recovery): expose admissibility on public models
wolf75222 Aug 1, 2026
f20f6fe
test(recovery): exercise public admissibility authoring
wolf75222 Aug 1, 2026
2c861e1
docs(recovery): use the public model surface
wolf75222 Aug 1, 2026
55c6513
feat(reconstruction): add prepared MC and Superbee providers (ADC-751)
wolf75222 Aug 1, 2026
4ddf094
test(reconstruction): fence MC and Superbee semantics (ADC-751)
wolf75222 Aug 1, 2026
14e426f
docs(reconstruction): document executable MC and Superbee (ADC-751)
wolf75222 Aug 1, 2026
d15fce8
Merge current master into P2 consolidation
wolf75222 Aug 1, 2026
14e47cf
Merge ADC-749 boundary authority ratchet into P2
wolf75222 Aug 1, 2026
a89910e
Merge ADC-751 MC and Superbee providers into P2
wolf75222 Aug 1, 2026
2d21b16
Merge ADC-753 model admissibility into P2
wolf75222 Aug 1, 2026
32b2d58
Merge ADC-754 recovery capability contract into P2
wolf75222 Aug 1, 2026
6d0c073
Merge ADC-755 recovery consumer contract into P2
wolf75222 Aug 1, 2026
b5cb3fc
gate(numerics): select limiter and admissibility proofs
wolf75222 Aug 1, 2026
c8c1c02
feat(time): persist cell temporal partition authority
wolf75222 Aug 1, 2026
ca4862e
test(time): cover temporal partition restart and no-bypass
wolf75222 Aug 1, 2026
653f582
docs(time): bound the ADC-756 restart foundation
wolf75222 Aug 1, 2026
13488c2
Merge ADC-756 temporal partition restart authority into P2
wolf75222 Aug 1, 2026
caf37d3
gate(numerics): select temporal partition authority
wolf75222 Aug 1, 2026
07608fb
fix(ci): classify new P2 validation files
wolf75222 Aug 1, 2026
17b6280
gate(numerics): execute Python ABI and restart parity
wolf75222 Aug 1, 2026
4fe72ac
test(numerics): qualify MC and Superbee reconstruction
wolf75222 Aug 1, 2026
7cf70d0
gate(numerics): prove host workspace reentrancy
wolf75222 Aug 1, 2026
1e2f34a
Merge current P2 gate into limiter qualification
wolf75222 Aug 1, 2026
b196bcf
test(numerics): compose limiter and workspace gate proofs
wolf75222 Aug 1, 2026
b0dcaaa
Merge ADC-682 qualified native flux packs into P2
wolf75222 Aug 1, 2026
761b106
gate(numerics): execute qualified flux provider proofs
wolf75222 Aug 1, 2026
7069df8
Merge ADC-751 reconstruction qualification into P2
wolf75222 Aug 1, 2026
37e90fb
gate(numerics): attest ADC-751 limiter proofs
wolf75222 Aug 1, 2026
b160e6a
fix(boundary): reject inert transport descriptors at resolve
wolf75222 Aug 2, 2026
d85aadf
test(boundary): ratchet resolve-time executable authority
wolf75222 Aug 2, 2026
4547c12
Merge ADC-749 resolve-time boundary authority into P2
wolf75222 Aug 2, 2026
06d6062
refactor(boundary): retain typed provider law identities
wolf75222 Aug 2, 2026
92f949a
fix(boundary): reject mismatched transport provider laws
wolf75222 Aug 2, 2026
5205134
test(boundary): ratchet provider law authentication
wolf75222 Aug 2, 2026
7c38715
test(boundary): expose typed no-flux nonclaim
wolf75222 Aug 2, 2026
6023ee5
Merge typed boundary-provider law completion into P2
wolf75222 Aug 2, 2026
cc7c8ff
feat(recovery): preserve executed method identity
wolf75222 Aug 2, 2026
cef6474
feat(boundary): define typed post-Riemann flux port
wolf75222 Aug 2, 2026
e400f2e
feat(boundary): execute post-Riemann flux transforms
wolf75222 Aug 2, 2026
7ef2b9b
Merge P1 temporal and AMR foundations into P2
wolf75222 Aug 2, 2026
07ce2e8
Merge ADC-753 recovery method identity into P2
wolf75222 Aug 2, 2026
ed41461
Merge ADC-749 post-Riemann boundary transform into P2
wolf75222 Aug 2, 2026
8697657
fix(numerics): fail closed on unqualified boundary flux routes
wolf75222 Aug 2, 2026
768ec2e
Merge master after P1 integration into P2
wolf75222 Aug 2, 2026
5cb3ebe
fix(codegen): retain resolved provider pack authority
wolf75222 Aug 2, 2026
13e93a7
test(model): migrate fixtures to equal representation arity
wolf75222 Aug 2, 2026
ffe4d92
test(amr): qualify partition restart cells with active level
wolf75222 Aug 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,38 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning

### Changed

- Type-erased variable-recovery reports now retain the selected and last-attempted method kinds.
Runtime failures name the actual recovery route instead of exposing only a plan-local integer,
while rejected outcomes keep the selected method explicitly unknown.
- Capability reports now distinguish the delivered typed Riemann rejection path from an unavailable
prepared recovery policy. Rusanov, HLL, HLLC, and Roe advertise their common device-copyable
`FluxEvaluation` and transactional rejection, while ordered fallback chains,
requested-versus-used solver diagnostics, counters, and restart metadata fail closed instead of
being inferred from the selected solver.
- Variable-recovery capability reports now separate the delivered prepared closed-form consumers
from the complete ADC-755 deletion gate. System materialization and every production face route
advertise typed publication control, while the remaining source, AMR-transfer, boundary,
inverse-conversion, cache/restart, backend, and performance families fail closed as an unavailable
complete-consumer cutover.
- ADC-749 carries exact periodic face identifications through the model-aware hyperbolic boundary
plan. Uniform scalar layouts execute mapped periodic halos (including cross-axis maps); mapped
vector/axial component transforms and AMR mapped periodic fill-patch/regrid remain explicit
fail-closed capabilities until their model-aware component and hierarchy contracts are available.
- ADC-749 now makes numerical resolution the fail-closed acceptance boundary for built-in transport
descriptors. Characteristic closures without a prepared eigenstructure, forged representation
converters, unsupported analytic dependencies, and mixed logical clocks can no longer survive as
inert metadata and fail only during compile or bind.
- Boundary provider identities now retain an immutable typed law such as inflow, ghost formula,
directional transport, or no-flux. Resolution no longer has to infer semantics from a handle name
or output port, while the still-missing post-Riemann execution ABI remains explicitly unavailable.
- Strict AMR checkpoint payload v7 now persists the accepted shared-interface flux audit together
with Program clocks, histories, tagging state, conservative ledger and synchronization report.
Restart validates every fragment's topology epoch, level pair, exact clock window, resolved
rational stage weight, geometry and duration before publishing the image; rejected restart or
Program attempts leave the previous accepted report byte-exact.
- Generated physical-flux bricks now make their qualified provider requirements executable native
ABI evidence: the binder validates every row at compile time and reads only its declared storage
slots instead of scanning the model's complete auxiliary width.
- AMR checkpoint capability reports now distinguish same-rank bit-identical replay from
non-bit-identical rank-count rematerialization with Dense persisted histories. The explicit
`RegridOnRestart()` policy now restores and authenticates the recorded accepted state before one
Expand Down
59 changes: 51 additions & 8 deletions docs/ALGORITHMS.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ global auxiliary slot, or provider outside its resolved pack. It returns `FluxDe
applied exactly once by the spatial layer. A fallible evaluation maps explicitly to retry, reject or
abort transaction actions.

Primitive face reconstruction is a fallible numerical operation, not an unchecked model callback.
Every conservative-to-primitive stencil sample is evaluated through
`PreparedVariableRecovery` and returned as a `ReconstructedFaceState` carrying both the candidate
and its `RecoveryReport`. Cartesian, cached-HLL, masked, polar and embedded-boundary kernels consume
that report before calling the numerical flux. A refused candidate therefore writes only finite
transactional scratch, joins the same device/MPI failure reduction as a fallible flux, and cannot be
published. The type-erased report preserves the selected and last-attempted method kinds in addition
to their chain indices; diagnostics can therefore name the actual closed-form, nonlinear, bracketed,
repair, or custom route without reconstructing policy from an erased plan. The pointwise route is
fixed-size, `POPS_HD`, allocation-free and callback-free.

**Constraints / remarks.** CFL condition: $\Delta t \le C\,\dfrac{\min(\Delta x,\Delta y)}{\max|\lambda|}$,
where $\lambda$ is the local wave speed and $C \le 1$ at order 1; `max_wave_speed_mf` provides
$\max|\lambda|$. A model without transport ($\max|\lambda| = 0$) does not constrain the step
Expand Down Expand Up @@ -220,10 +231,17 @@ requires `m.wave_speeds`). `HLLCFlux` requires `HasHLLCStructure` (`pressure`, `
`hllc_star_state`) and `RoeFlux` requires `HasRoeDissipation` (`roe_dissipation`). Euler conforms
through those same capabilities. A missing capability is rejected during route resolution; there
is no component-count inference and no implicit HLL/Rusanov substitution. The
compatibility function `rusanov_flux` (in `spatial_operator.hpp`) delegates to `RusanovFlux{}` for serial
references. The flux is passed by template: `compute_face_fluxes<Limiter, NumericalFlux, Model>` and
`assemble_rhs<Limiter, NumericalFlux, Model>` are templated on the flux policy, chosen
independently of the limiter. The `SourceFreeModel` adapter (explicit IMEX half-step) forwards
four built-ins return the common device-copyable `FluxEvaluation`. Built-in rejection reasons use
the typed `RiemannFailureCause` vocabulary before device/MPI reduction. In particular, Roe rejects
a non-finite dissipation or final candidate flux, while HLLC attributes non-finite physical flux,
pressure, contact speed, star state, and final candidate flux separately. Neither policy publishes a
successful NaN result; the runtime rolls the owning step transaction back without selecting another
solver.
The compatibility function `rusanov_flux` (in `spatial_operator.hpp`) delegates to
`RusanovFlux{}` for serial references. The flux is passed by template:
`compute_face_fluxes<Limiter, NumericalFlux, Model>` and
`assemble_rhs<Limiter, NumericalFlux, Model>` are templated on the flux policy, chosen independently
of the limiter. The `SourceFreeModel` adapter (explicit IMEX half-step) forwards
`pressure`, `wave_speeds`, and the optional HLLC/Roe structural hooks only when the wrapped model
exposes them (`requires` clauses), so the explicit half-step keeps the selected Riemann provider.
A moment hierarchy (no fluid roles, no primitive `p`) can also
Expand Down Expand Up @@ -369,32 +387,57 @@ function weno5z(vm2, vm1, v0, vp1, vp2): # face entre v0 et vp1

**Code.** Pointwise `Limiter` policies in
[`include/pops/numerics/fv/reconstruction.hpp`](../include/pops/numerics/fv/reconstruction.hpp): `NoSlope`
(`n_ghost = 1`, `operator()` returns `Real(0)`), `Minmod` and `VanLeer` (`n_ghost = 2`, `operator()(a,b)`
returns the limited slope, absolute value coded by hand to stay device-safe without `<cmath>`), `Weno5`
(`n_ghost = 1`, piecewise-constant face value), `Minmod`, `VanLeer`, `MC` and `Superbee`
(`n_ghost = 2`, `limited_slope(a,b)` returns the limited slope with device-safe scalar arithmetic), `Weno5`
(`n_ghost = 3`, a tag whose `operator()` is a no-op that just satisfies the `Limiter` concept). The
order-5 reconstruction lives in the free function `weno5z(vm2, vm1, v0, vp1, vp2)` of the same header:
it returns the value at the face between `v0` and `vp1`, and for the opposite face one passes it the
reversed stencil. All are `POPS_HD` (device-callable, static polymorphism: the limiter is a template
parameter of `assemble_rhs` / `compute_face_fluxes`, inlined on device). The mesh stencil access and the
routing by `n_ghost` are in `reconstruct` of `numerics/spatial_operator.hpp`; the policy itself
loops over no grid. The reconstruction can act on the conserved or primitive variables
(`rho, u, p`) depending on the block.
(`rho, u, p`) depending on the block. Production kernels use the typed
`reconstruct_recovered`/`reconstruct_pp_recovered` entry points and consume their `RecoveryReport`
before any face flux; the value-only wrappers remain low-level compatibility helpers.

**Constraints / remarks.** The reconstruction does not change the hyperbolic stability condition: the
step stays bounded by the CFL of section 1, `dt <= C dx / max|lambda|`. Limits and pitfalls:
- `Minmod` is strictly TVD but falls back to local order 1 at extrema (it erases smooth peaks);
for the Diocotron growth modes one prefers `VanLeer`, less dissipative at extrema.
- `MC` uses $\operatorname{minmod}((a+b)/2,2a,2b)$ and is a less diffusive TVD compromise;
`Superbee` uses $\operatorname{maxmod}(\operatorname{minmod}(2a,b),
\operatorname{minmod}(a,2b))$ and is the most compressive builtin MUSCL limiter. Their
implementations avoid overflowing intermediate doubled slopes for finite inputs.
- `weno5z` is smooth (no branch on the sign: the $\beta_k$ and $\tau_5$ are squares so
always $\ge 0$, and only $|\beta_0-\beta_2|$ goes through a ternary), which makes it fully
device-callable; the floor `eps = 1e-40` avoids division by zero on a constant stencil.
- Reconstructing the conserved variable rather than the primitive changes the behavior at strong shocks
(the reconstructed states can leave the admissible domain on the conserved side).
- The ghost cost drives the halo width to exchange: 1 (NoSlope), 2 (MUSCL), 3 (WENO5).

For a Python-authored model, finite primitive recovery can be strengthened with explicit physical
constraints after declaring the primitive layout:

```python
# after model.primitive_state(rho, u, v, p, conservative=(...))
model.recovery_admissibility(rho=rho > 0, p=p > 0)
```

Each keyword identifies the primitive component reported on failure; its value is a symbolic Boolean
expression over the primitive state. Code generation emits a device-callable
`recovery_admissible(Prim, failing_component)` method. `CompositeModel` forwards that optional
contract and `prepare_model_variable_recovery` installs it in the same ordered recovery plan as the
conversion method. A finite candidate that violates a predicate is therefore not published: the
chain proceeds to its next declared method, or finishes with `inadmissible_candidate` when no method
remains. Models that declare no policy retain the finite-only path and emit no extra method.

**Validation.** `test_weno_convergence` (the face reconstruction of a smooth function reaches order 5),
`test_primitive_recon` (conserved <-> primitive conversions and their use in the reconstruction),
`test_spatial_discretisation` (the reconstruction x numerical flux pair is a named type, exercised end
to end).
to end), and `test_weno_convergence` (MC/Superbee reference formulas, symmetry, homogeneity, TVD
bounds and finite extreme inputs in addition to WENO convergence), and
`test_variable_recovery_chain` (a model-declared physical predicate blocks publication
and preserves the typed failing component).


---
Expand Down
5 changes: 5 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,11 @@ model-qualified `FaceTrace` values plus `FaceContext` and returns a typed densit
`SpatialOperator` alone applies face and cell measures. Provider packs are selected from exact
`(owner, space kind, space name, component)` identities. Missing, unavailable or contract-mismatched
providers fail during selection; homonymous components from different owners never alias.
Generated physical models carry those qualified rows as `flux_provider_requirements`. The native
binder validates their count, qualification, availability, unique in-range storage slots and then
loads only those declared slots into the model-qualified device pack. Hand-written C++ test models
that do not declare this generated ABI retain the full-width fixture path; generated PoPS models
never use that route.

## Limitations

Expand Down
5 changes: 3 additions & 2 deletions docs/design/external-component-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ are reused only when their bytes authenticate to the same binary identity.
table layouts, plus the version of the common request/value ABI. The complete declaration feeds the
catalog digest. The generator emits `pops.interfaces`, the Python route data and
`generated_component_abi.hpp` together; `--check` makes any hand-edited drift fail CI. The current
protocol includes separate tables for numerical flux, ghost boundary, field-boundary closure,
tagging, clustering, transfer, reflux, field solve, writer and field topology. Adding an
protocol includes separate tables for numerical flux, ghost boundary, post-Riemann boundary-flux
transformation, field-boundary closure, tagging, clustering, transfer, reflux, field solve, writer
and field topology. Adding an
implementation requires no central scientific switch.

The installed CPU route proves 2D, `float64`, host execution. It supports source/header payloads and
Expand Down
55 changes: 54 additions & 1 deletion docs/design/native-capability-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,58 @@ Supported native routes include:
interpolation are cell-centered on the supplied route. Derived fields use `elliptic_solve` and
caches use `patch_topology`; unsupported provider contracts fail before artifact creation.
- Finite-volume spatial discretisation on the 2D core.
- One prepared, model-aware 2D transport-boundary plan shared by Uniform and AMR native/compiled
routes. The capability matrix marks this route `partial` and names its exact built-ins:
periodicity, extrapolation, constant or `RuntimeParam` fixed state, conservative device-side
analytic fixed state over typed `(x,y,t,params)`, fixed-state primitive inflow converted once
through the exact compiled block-model `to_conservative` provider, and typed-role slip wall.
Analytic programs are immutable postfix tables evaluated in native device kernels at the exact
`BoundaryEvaluationPoint`; no Python callback or hot-loop allocation is retained. The analytic
finite-value contract is strictly non-mutating: one device preflight and one communicator
reduction complete before any same-level, periodic, MPI or physical halo write. The commit kernel
then evaluates the program again; this deliberate two-pass route avoids a per-cell scratch field
but retains one blocking collective per analytic boundary fill.
The analytic route remains `partial`: primitive per-point conversion and discrete state/field/input reads are
rejected, as is an analytic ghost depth larger than the normal domain extent. Analytic faces with
axis-permuted periodic coordinates also fail closed until a prepared coordinate map exists. The
conversion route is explicitly `partial`: conservative-to-primitive recovery and arbitrary
representation components remain unavailable, and conversion does not invent a boundary
admissibility projection. A separate `unavailable` row exposes the missing characteristic
no-inflow kernel. Post-Riemann transformation is instead an explicit `partial` route: a typed
`BoundaryFlux` component receives the already evaluated outward-normal flux and executes between
the Riemann solve and divergence/reflux through the same prepared Uniform/AMR plan. The runtime
converts lower and upper faces to outward orientation before the call and converts the result
back to canonical positive-axis face storage afterwards. This route is currently 2D Cartesian
host-batch execution; it has no device-native or embedded/cut-cell metric ABI, and the ordinary
Uniform route materializes face fields when selected.
These requests fail during resolution or lowering; none silently degrades to component-wise
ghost filling. A native rank-1/2/4 regrid fixture removes and recreates the fine hierarchy, then
proves that uncovered internal fine ghosts retain the conservative coarse-fine transfer and are
never treated as physical faces by the rematerialized prepared boundary session. The explicit
public route is
`Inflow(state=U, value=primitive_values, representation=Primitive(),
converter=pops.boundary.model_primitive_to_conservative(U))`; the converter is derived from the
authenticated block state and cannot name an unrelated callback or kernel.
`primitive_values` follows the model's declared primitive-variable order.
- Native Riemann routes: Rusanov, HLL, HLLC, Roe, subject to model capability requirements.
`riemann:typed_failure_outcome` is deliberately `partial`: every built-in returns the common
device-copyable `FluxEvaluation` with typed status, stability bound, and reason code, and a
reduced failure rejects the owning transaction instead of publishing a candidate or silently
selecting another solver. `riemann:prepared_recovery_policy` is separately `unavailable`:
there is no prepared ordered solver chain, requested-versus-used solver outcome, block counter,
or restart metadata yet. Callers can therefore request the single-solver typed-rejection route
explicitly, but cannot claim a configured fallback policy.
- Prepared variable recovery is explicitly `partial`. One block-prepared closed-form method returns
a device-copyable `RecoveryOutcome`/`RecoveryReport`. Type erasure retains both the selected and
last-attempted method kinds, so a successful fallback or a refusal cannot be reported as an opaque
chain index. System conservative-to-primitive
materialization and Cartesian, polar, masked, and embedded-boundary face reconstruction consume
publication permission before copying a candidate or evaluating a flux. This route adds no
implicit repair, fallback, or mutable cache. The separate
`recovery:complete_consumer_cutover` capability remains `unavailable`: initial/analytic and
model/source conversion, AMR transfer/regrid, primitive boundary traces, fallible
primitive-to-conservative conversion, persistent warm starts, cache/restart, backend parity, and
performance evidence do not yet share that authority.
- Native reconstruction routes: first-order, MUSCL, WENO5/WENO5-Z.
- Elliptic GeometricMG on Uniform/AMR and FFT on uniform periodic constant-coefficient grids.
- Matrix-free Krylov descriptors: CG, BiCGStab, GMRES, Richardson.
Expand Down Expand Up @@ -180,10 +231,12 @@ Supported native routes include:
artifact creation until their adapter contract owns the same persistent-state route. MPI capture
validates the rank-independent accepted-state image on every producer before sealing or
publication; disagreement fails collectively and cannot leave a partial checkpoint.
- The prepared limiter registry exposes native `Minmod`, `VanLeer`, `MC`, and `Superbee` MUSCL
policies. Each is a stateless `POPS_HD` compile-time provider with formal order 2 and exactly two
ghost layers; Uniform, AMR, MPI and supported device targets consume the same route identity.

Explicit unsupported rows include:

- `limiter:mc` and `limiter:superbee`: catalogued descriptors with no native C++ symbol.
- `elliptic:fft_amr`: FFT requires a single uniform periodic mesh; AMR uses GeometricMG.
- `checkpoint:parallel_hdf5`: parallel HDF5 is a scientific-output route, not a restartable checkpoint
encoding; `RuntimeInstance.checkpoint()` and the typed `Checkpoint` consumer use uniform v5 or AMR
Expand Down
Loading
Loading