Skip to content

analog: linear_zoh.t27 -- exact zero-order-hold constants for the linear cell, and the h/2 convergence check (Closes #10503) - #10528

Merged
gHashTag merged 1 commit into
masterfrom
claude/analog-m1c-zoh-10503
Oct 18, 2026
Merged

gHashTag merged 1 commit into
masterfrom
claude/analog-m1c-zoh-10503

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #10503

M1c of #10486 (weaknesses W1 and W10 of docs/analog/competitors.md). New spec specs/analog/linear_zoh.t27 uses the M1 cell (specs/analog/linear.t27) and copies nothing from it. It adds a second constant set for the same step x' = x + rnd(D x + N u): the exact zero-order hold, M = exp(A_c dt), N = A_c^-1 (M - I) B_c, computed in the tests in f64 (scaling and squaring, Pade (6,6), M1's Gauss-Jordan eliminate for both solves) and quantized to Q.24 like M1. No hardware change. Files: the spec and its seal, nothing else (t27b_expectations.json untouched).

What was measured

Circuits: M0's RC; the series RLC of M1 (R = 100, Q = 1); the same with R = 5 (Q = 20); the same with R = 0.5 (Q = 200, the LC tank). States are v_C and i_L * sqrt(L/C), as M1 scales them. Every stored integer is asserted equal to round(value * 2^24) with no value within 1e-4 of a tie; M also agrees with the closed form of the RLC, with exp of the augmented matrix, and with det M = exp(-R dt / L).

Convergence, step response against the analytic solution, dt / dt/2 / dt/4, horizon 200 steps at dt (largest error over both states and all grid points):

circuit BE error at dt, dt/2, dt/4 BE measured order exact scheme, relative to full scale
RC 9.01e-3, 4.55e-3, 2.29e-3 0.985, 0.993 < 1e-12 (about 1e-15)
RLC Q = 1 1.89e-2, 9.62e-3, 4.85e-3 0.975, 0.988 < 1e-12 (3e-14)
RLC Q = 20 1.66e-1, 8.78e-2, 4.52e-2 0.915, 0.957 < 1e-12 (2e-14)

All BE orders are in [0.9, 1.1]; the exact scheme beats the issue's 1e-9 by more than four orders. Boundary stated and pinned by a test: the Q = 20 order is a statement about its horizon. Over 400 steps the first pair measures 0.84, so at dt = 5 ns that circuit is not in the asymptotic regime for three periods (W10's rule applies).

The three errors, apart (FR-001):

RC RLC Q 1 RLC Q 20 tank
arithmetic, exact scheme (fixed vs f64, LSB) 4.84 9.61 34.71 120.50
arithmetic, backward Euler (M1) 2.65 8.44 - -

Discretization is the table above. Model error is stated as not applicable (the reference is the analytic solution of the same equations; ngspice joins at M3). For the RLC, backward Euler's arithmetic error is 5.0e-7 V and its discretization error 1.89e-2 V, about 37000 times larger: a bit-exact comparison with float64 could not see it.

LC tank (Q = 200), after 100 periods (12566 steps; amplitude = largest |1 - v_C| over the last 127 steps; analytic 0.211153):

scheme amplitude ratio to analytic
exact, f64 0.211153 1.00000000000006
exact, Q.24 constants and the integer step 0.211219 1.0003
backward Euler, f64 3.75e-8 1.78e-7 (loses 99.99998 %)

The closed form (lam2 / exp(-R dt / L))^(K/2) gives 1.54e-7, within 15 % of the run. Numerical damping per step of BE is ten times the tank's physical damping at 125 steps per period.

Stability (FR-002): ||M_q^256||_inf < 1 holds for the exact RC (< 1e-5), RLC (0.0030) and Q = 20 circuit (0.877). The Q = 200 tank does not certify at K = 256 (1.17: its memory is 8000 steps) and does at K = 4096 (0.83); both are asserted. A lossless tank and a negative resistance are not certified.

Gates

  • t27c test-report specs/analog/linear_zoh.t27: 15 of 15 pass, vacuous passes 0 of 15.
  • tri test specs/analog/linear_zoh.t27: exit 0, 15/15.
  • t27c seal --save then --verify: all hashes MATCH; the seal records 15/15 and M1 in its closure.
  • python3 tools/dupe_scan.py: ok, no new duplicate body.
  • t27c frontier --only specs/analog/linear.t27 --list: M1's sealed verdict is reused, so its tests were not re-run.

Negative controls

In the spec, as tests: Pade order 1 changes the stored integers and misses 1e-9 by five orders; Pade order 2 rounds to the same integers for the Q = 1 RLC and is caught only by the f64 grid test (error 6e-9), so both checks are kept; wrong dt (x0.5, x2), negative resistance, the input term without the integral, a damping row divided by C instead of L, and BE constants offered as exact each fail. On scratch copies of the file, eight mutations make test-report fail: squaring loop removed (1 test fails), PADE_ORDER 2 (8), PADE_ORDER 1 (10), one stored D digit (4), dt x1.01 (7), damping sign (8), M - I dropped from the N formula (9), one pinned fold digit (1). t27c seal --verify reports MISMATCH on a mutated copy.

Notes for the reviewer

  • t27b test cannot run this spec: the JIT does not support @sin, @cos, @exp, @log2 (the analytic solution needs them). test-report and tri test are the gates used.
  • The exact RLC cell has two unknowns (v_C, i_L * ZS); the node between R and L is not a state. It is not a drop-in for M1's three-unknown tables. The general netlist reader is M2.

🤖 Generated with Claude Code

…ear cell, and the h/2 convergence check (Closes #10503)

M1c of #10486 (weaknesses W1 and W10 of docs/analog/competitors.md).
specs/analog/linear_zoh.t27 `use`s the M1 cell (linear.t27) and adds a second
constant set for the same step x' = x + rnd(D x + N u): the exact zero-order
hold, M = exp(A_c dt), N = A_c^-1 (M - I) B_c, computed in the tests in f64
(scaling and squaring, Pade (6,6), M1's Gauss-Jordan eliminate for the solves)
and quantized to Q.24 like M1. No hardware change.

Circuits: M0's RC, the series RLC of M1 (Q = 1), the same with R = 5 Ohm
(Q = 20) and R = 0.5 Ohm (Q = 200, the LC tank). Every stored integer is
asserted equal to round(value * 2^24); M agrees with the closed form of the
series RLC, with exp of the augmented matrix and with det M = exp(tr(A_c) dt).

Convergence (h, h/2, h/4 against the analytic step response): backward Euler
measures order 0.985/0.993 (RC), 0.975/0.988 (RLC Q 1), 0.915/0.957 (RLC Q 20);
the exact scheme is within 1e-12 relative of the analytic solution at every
grid point. The Q = 20 circuit leaves the asymptotic regime over 400 steps
(0.84), and a test pins that. The three errors are reported apart; the model
error is stated as not applicable.

Stability: ||M_q^256||_inf < 1 for the RC, the RLC and the Q = 20 circuit; the
Q = 200 tank needs K = 4096 (0.83; 1.17 at K = 256), asserted both ways.
LC tank after 100 periods: the exact scheme keeps the amplitude to 1.00000000000006
(f64) and 1.0003 (Q.24 constants); backward Euler keeps 1.78e-7 of it.

Negative controls are tests (Pade order 1 and 2, wrong dt, negative resistance,
dropped integral, BE constants offered as exact); eight mutations of the file
make t27c test-report fail, and t27c seal --verify refuses a mutated copy.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) October 18, 2026 16:41
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-18 16:42:15 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fad12492937a != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit 2c02386 into master Oct 18, 2026
32 of 35 checks passed
gHashTag added a commit that referenced this pull request Oct 18, 2026
… with another type named Ring and moved the types ratchet 107 -> 108 (Closes #10503) (#10539)

PR #10528 merged specs/analog/linear_zoh.t27 with `pub struct Ring`. The
corpus-ratchet job ran `tri types ratchet` and failed: ledger 107 names,
observed 108, "+ Ring NEW conflict" -- a type name with two definitions in the
corpus. The job is not a required check, so the merge went through; master is
red on it until this lands.

The struct holds the peak amplitude of the scheme and the analytic one in the
tank test. Renamed to RingPeak (no other definition of that name). Nothing
else changes: the same 15 tests pass with 0 vacuous, the seal is re-saved
(15/15), `tri types ratchet` is CLEAN at 107/107, dupe_scan says ok.

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
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.

analog M1c: exact zero-order-hold discretization for the linear cell, and the h / h/2 convergence check

2 participants