Skip to content

M6d: axisymmetric relief, and reconciling the docs with the gates - #2

Merged
ggange merged 2 commits into
mainfrom
m6d-axisymmetric-relief
Aug 1, 2026
Merged

M6d: axisymmetric relief, and reconciling the docs with the gates#2
ggange merged 2 commits into
mainfrom
m6d-axisymmetric-relief

Conversation

@ggange

@ggange ggange commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Two commits: the M6d milestone, and a docs reconciliation that came out of reviewing it.

M6d — axisymmetric gas dynamics and radial relief (8c6732e)

M6c's G7 is ungated, and its spec justified that with one omission: "a planar 1-D code has no radial relief … it is the one effect the geometry has removed by assumption." This puts the effect back and measures it.

src/euler2d.rs is planar/axisymmetric Euler on annular cells, reusing euler1d's HLLC rather than carrying a second copy: a sweep packs (ρ, ρu_∥, E − ½ρv_t²) into the 1-D state and the transverse flux comes back as F_ρ·v_t with the upwind side read off sign(F_ρ). Both identities are exact. The area-weighted form means the 1/r never appears in the code — the axis interface has zero area, and the geometric source is written as the same floating-point expression as the pressure part of the flux difference, so a radially uniform state is a bit-exact fixed point. That is what lets G9 assert equality rather than a tolerance.

Verification: G9 planar limit reproduces Euler1d bit for bit over 240 cells × 40 steps; G10 Sedov–Taylor exponent 0.38628 vs the exact 2/5, level and peak compression gated as trends under refinement; G11 1.861/1.964 against a split-source contrast at 1.030/1.155; G12 conservation to <1e-13 with radial momentum deliberately not conserved plus an escape-flux leg; G13 axis entropy defect 2.99e-7 → 3.12e-8 under refinement against 3.02e-6 for an even-parity contrast; G14 wide-beam limit reproduces the 1-D column to 3.1e-13.

Sedov–Taylor is the repo's first multidimensional anchor, and ξ₀ is derived from the energy integral rather than quoted — 1.03278 against the published ≈1.033, so the literature value is a cross-check instead of an input.

The result (G15, pinned): radial relief costs δ = 1 − D/D_wide = 0.230 of the front speed at R_b·α = 3.2 and 0.305 at 1.6, monotone in beam radius. Pinned as a band of ±13 %, and that width is measured rather than chosen: grid +6 %, seed −7 %, ignition threshold ±8 %. Shown not to be a boundary effect (21.1/21.3/21.3 % at 3/5/8 beam radii). So relief is real and is not the whole ~2× gap to measurement — G7 stays ungated, but now for one reason only, the missing dataset.

The unlooked-for result: the modelled front is transversely unstable, growing cellular structure out of round-off, amplitude-proportionally, saturating at |u_r| ≈ 200–400 m/s, identically in planar and axisymmetric geometry. A 1-D solver structurally cannot show it, and it had to be separated from relief before the relief number meant anything — which is why δ is measured against the wide-beam 2-D run and not against the 1-D column.

Docs reconciliation (36f15de)

Reviewing the above turned up that MODELS.md has been written append-only: each investigation added a section and left the paragraphs above it describing a model that no longer ships. The claims ledger was kept current, so the drift hid underneath a table that looked right.

§ M6a prose said the seed was one electron in the focal volume and the multiphoton source off by default (both retired 2026-07-31 — the seed is q/ν_att and PPT is on), quoted n = 0.095 from the retired mean-trajectory closure, called the I_thr(p) slope gate RED five weeks after it went green, and carried Chylek local exponents of 1.951/1.047/0.170 against a current 0.501/0.857/0.386. Rewritten to the current model; the superseded narrative was already in M6A_SPEC.md under its own Superseded headings, so it is pointed at rather than retold (−89 lines).

The same drift had reached the source. breakdown0d.rs documented with_ppt_mpi as off by default (it is on) and with_seed_density's default as 1/V_focal (it is the ambient background); validation.rs's doc comment quoted an envelope of [0.183, 0.407] while its assertions twelve lines below pin [0.174, 0.382]. Comment changes only — no behaviour moved.

Audit. All 122 ledger rows were checked against the assert! in the gate each names. Three carried stale numbers; four that looked wrong turned out right, because several gates deliberately run seeding_suppressed to isolate one change. M1–M4, M6a.2, M6c and M6d rows all match their gates.

The census was wrong and nothing could catch it — the line claimed 118 rows (80/10/16/12) against an actual 122 (83/10/17/12). tests/docs.rs now parses the ledger, counts by status, and fails printing the corrected line; a second gate asserts every row carries one of the four statuses. Both were made to fail before being trusted.

M6c prose carried the same outward: G7 still justified by the excuse M6d retired; the lsd demo quoting a threshold of 1.14e16 that "does not fall with pulse length" when it is 8.815e15 at 6 ns converging to 6.745e15; M6a's ungated level as 4.8–7.0× in five places against a pinned 3.90–4.69×. The demo figures were re-checked by running the case: D = 5400.7 vs Raizer 5390.7 (+0.185 %), budget 1.26e-16, τ = 374.2 — all matched.

M6C_SPEC's copy of the threshold paragraph is amended in place with a dated note rather than rewritten, because the shape of the claim changed and the spec records what the milestone landed believing.

README's milestone table is compressed 30 KB → 17 KB; one cell held 10,305 characters. Every measured gate number and every ungated/pinned flag stays, per CONTRIBUTING.

Gates

All four pass locally, in order: cargo fmt --all -- --check, cargo clippy --all-targets --all-features under RUSTFLAGS="-D warnings", cargo build --all-targets, cargo test245 passed, 0 failed, 0 ignored.

Known limitation

The census gate catches structural drift only. A row whose prose quotes a stale slope is checked by nobody — the ground truth for any such number is the assert! in the gate it names, which CONTRIBUTING now says explicitly. Mechanising that would mean the ledger emitting numbers rather than quoting them.

🤖 Generated with Claude Code

ggange and others added 2 commits July 31, 2026 22:03
M6c's G7 is ungated, and the spec justifies that with one omission: "a
planar 1-D code has no radial relief ... it is the one effect the
geometry has removed by assumption". This puts the effect back.

src/euler2d.rs is planar/axisymmetric Euler on annular cells, reusing
euler1d's HLLC rather than carrying a second copy: a sweep packs
(rho, rho*u_par, E - rho*v_t^2/2) into the 1-D state, and the transverse
flux comes back as F_rho*v_t with the upwind side read off sign(F_rho).
Both identities are exact. The area-weighted form means the 1/r never
appears in the code at all -- the axis interface has zero area, and the
geometric source is written as the same floating-point expression as the
pressure part of the flux difference, so a radially uniform state is a
bit-exact fixed point.

That is what lets G9 assert equality rather than a tolerance: the planar
2-D solver reproduces Euler1d BIT FOR BIT over 240 cells and 40 steps.
The M6c lsd artifacts are byte-identical to a baseline taken before the
first line of code.

Sedov-Taylor lands as the repo's first multidimensional anchor. xi_0 is
DERIVED here from the energy integral rather than quoted -- 1.03278
against the published ~1.033 -- so the literature value is a cross-check
instead of an input. Its profile is put back into the Euler PDEs, where
the residual is 6.9e-5 and falls as the finite-difference step squared;
that verifies the hand derivation, not just the arithmetic.

Gates: G9 bit-identical; G10 exponent 0.38628 vs 2/5 with level and peak
compression gated as trends under refinement (a spherical blast's spike
is one or two cells wide at any affordable mesh); G11 1.861/1.964 against
a split-source contrast at 1.030/1.155; G12 <1e-13 with radial momentum
deliberately NOT conserved and an escape-flux leg; G13 2.99e-7 -> 3.12e-8
against 3.02e-6 for an even-parity axis; G14 3.1e-13 in the smooth
window; G16 S^0.34666 against the parameter-free 1/3.

THE RESULT (G15, pinned). Radial relief costs delta = 0.230 of the front
speed at R_b*alpha = 3.2 and 0.305 at 1.6, monotone in beam radius, with
the wide-beam limit itself within 1% of Raizer. It is pinned as a BAND of
+-13%, and that width is measured rather than chosen: grid +6% on halving
dx, seed -7% at a 1x rather than 2x CJ-pressure seed, ignition threshold
+-8% over a 4x sweep. Pinning a third digit would assert a precision
three separate knobs say is not there. Shown not to be a boundary effect:
21.1/21.3/21.3% at domain radii of 3/5/8 beam radii.

So relief is real and it is NOT the whole ~2x gap to measurement. G7
stays ungated -- but now for one reason only, the missing dataset, rather
than because the geometry removed the physics.

THE UNLOOKED-FOR RESULT. The modelled front is transversely unstable. A
radially uniform run diverges exponentially from the 1-D column out of
round-off, reaching 3% by M6c's settle. Three measurements say it is
physical rather than a defect: it is bit-identical in planar and
axisymmetric geometry, so it is not the geometric source; it is
amplitude-proportional, a 1e6x larger seed giving a 1e6x larger early
response; and it saturates at |u_r| ~ 200-400 m/s whatever the seed.
Linear growth to nonlinear saturation is the mechanism behind the
cellular structure real detonations have. A planar solver structurally
cannot show it.

That forced a change the spec did not anticipate: delta is measured
against the wide-beam 2-D run, not the 1-D column. The instability is
present at every beam radius including infinite, so a 1-D reference would
report it as relief.

Three defects the gates caught, each recorded with its before-number.
Ghost cells borrowing a neighbour's face areas leaked 3.3e-4 of the mass
-- a reflective wall is only exact when the ghost's metric mirrors too.
The Hancock predictor built its geometric source from face rather than
cell pressures, which is well-balanced and wrong: expanded against the
flux difference the pressure terms cancel identically, deleting the
gradient from the predictor, and it cost an order (0.86/1.12 against
planar's 1.71/1.89). And G13's first entropy measure was reading the
shock rather than the axis -- the broken-parity run scored LOWER than the
correct one, which is what exposed it.

Also: the lsd2d CLI case and scripts/render_lsd2d.py (the field mirrored
about r = 0, so an axis artifact would show as a seam down the centre),
MODELS.md ledger rows and census, and the M6C_SPEC amendments retiring
the two NOT-in-scope bullets this milestone closes.

Suite 219 -> 243, 0 ignored. Added CI time is ~45 s, above the ~25 s
aimed for; G14 and G15 are genuine coupled runs and further trimming
would mean dropping a leg rather than shrinking a grid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
MODELS.md has been written append-only: each investigation added a
section and left the paragraphs above it describing a model that no
longer ships. The claims ledger was kept current, so the drift hid
underneath a table that looked right.

Section M6a said the seed was one electron in the focal volume and the
multiphoton source off by default -- both retired on 2026-07-31, the seed
is q/nu_att and PPT is on. It quoted n = 0.095 from the retired
mean-trajectory closure, called the I_thr(p) slope gate RED five weeks
after it went green, carried Chylek local exponents of 1.951/1.047/0.170
against a current 0.501/0.857/0.386, and still summarised M6a as
"falsified against air on both axes" when the low-pressure branch is now
1.17x. That prose is rewritten to the current model. The superseded
narrative was already in M6A_SPEC.md under its own Superseded headings,
so it is pointed at rather than retold, and the section loses 89 lines.

The same drift had reached the source. breakdown0d.rs documented
with_ppt_mpi as off by default (it is on), with_seed_density's default as
1/V_focal (it is the ambient background), and the analytic-limits gate
said T&T's measured 0.33 sits "outside this interval entirely" -- the gap
that closed on 2026-07-30. validation.rs's own doc comment quoted an
envelope of [0.183, 0.407] and a centre of 0.279 while its assertions
twelve lines below pin [0.174, 0.382] and 0.264. Comment changes only; no
behaviour moved. The suite goes 243 -> 245, both additions being the doc
gates below.

AUDIT. All 122 ledger rows were then checked against the assert! in the
gate each one names. Three carried stale numbers -- Chylek's low-pressure
branch, the wavelength ratio, the cascade bracket -- and row 134 quoted
the two closure values from before the closure change. Four rows that
looked wrong turned out to be right: several gates deliberately run
seeding_suppressed to isolate one change, so a number that disagrees with
the shipped default can be a correct isolated measurement rather than a
stale one. M1-M4, M6a.2, M6c and M6d rows all match their gates.

THE CENSUS WAS WRONG, and nothing could catch it. The line claimed 118
rows (80 verified, 10 validated, 16 pinned, 12 ungated) against an actual
122 (83/10/17/12). CONTRIBUTING requires it to move with the row it
describes; prose cannot fail, so it did not. tests/docs.rs now parses the
ledger, counts by status, and fails printing the corrected line; a second
gate asserts every row carries one of the four statuses, since a typo
would silently skew the count. Both were made to fail before being
trusted -- reintroducing the 118/80/16 census reproduces the exact drift.

M6c prose carried the same thing outward. Its G7 entry still justified
being ungated by "a planar 1-D solver has no radial relief", the excuse
M6d retired by modelling relief and pinning it at delta = 0.230. The lsd
demonstration run quoted a threshold of 1.14e16 that "does not fall with
pulse length" when it is 8.815e15 at 6 ns converging to 6.745e15 -- a
bounded 1.31x fall, asymptotic rather than flat. M6a's ungated level
appeared as 4.8-7.0x in five places against a pinned 3.90-4.69x. And "the
threshold moves by 4% over a 500x range of spot radius" was ungated prose
in two files; measured, it is 6%.

The demonstration-run figures were checked by running the case rather
than by trusting the text: D = 5400.7 vs Raizer 5390.7 (+0.185%), budget
1.26e-16, tau = 374.2, alpha = 6.753 1/m at 1.06 um and 1.084e3 at
10.6 um. All matched.

M6C_SPEC's copy of the threshold paragraph is amended in place with a
dated note rather than rewritten, because the shape of the claim changed
and the spec records what the milestone landed believing. The two-stage
argument it supports is untouched: a bounded fall to a floor is still an
intensity criterion, not a fluence one.

README's milestone table is compressed from 30 KB to 17 KB. One cell held
10,305 characters of M6a narrative, which renders as an unreadable column
on GitHub and duplicated material that MODELS.md and M6A_SPEC.md both
carry. Every measured gate number and every ungated/pinned flag stays,
per CONTRIBUTING; the chronological narrative goes.

WHAT IS STILL NOT GATED. The census gate catches structural drift only.
A row whose prose quotes a stale slope is checked by nobody -- the ground
truth for any such number is the assert! in the gate it names, which
CONTRIBUTING now says in as many words. Mechanising that would mean the
ledger emitting numbers rather than quoting them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ggange
ggange merged commit ff0c83b into main Aug 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant