Golden impedance matrix: eleven minimal decks and two CI jobs that gate on them (#15) - #22
Merged
maurymarkowitz merged 1 commit intoSep 16, 2026
Conversation
Eleven minimal decks under tests/golden_tests/decks, one per feature axis, each with a pinned input impedance, plus run_golden.py to check onec against them. 01_dipole_free free space, the anchor case 02_gn1_pec GN 1, perfectly conducting ground 03_gn2_sommerfeld GN 2 Sommerfeld, epsr=10 sigma=0.002, a wavelength up 04_ld0_series_rlc LD 0, a series RLC lump on one segment 05_ld5_conductivity LD 5, finite wire conductivity 06_junction_three_wire three wires meeting at one point 07_tl TL, an ideal 50 ohm line between two dipoles 08_nt NT, a two-port admittance matrix 09_fr_sweep FR stepped sweep, all three frequencies pinned 10_gx_symmetry GX reflection along X 11_gn2_low_height GN 2 at 0.02 lambda, the issue maurymarkowitz#14 residual They run in two jobs against one script, so a red X names exactly one deck: golden-impedance expected.json decks 01-10, twelve points GREEN golden-open-issues expected_open.json decks on an open issue RED THE RED LIVES IN golden-open-issues, AND IT IS RED BY DESIGN. The floor job is green at acafb37 with its widest row at 4.0e-05, and it must stay that way; the open-issues job holds 11_gn2_low_height, which answers 79.228 +4.256j against a pin of 91.758 +13.222j, 1.7e-01 out, and maps to the still-open issue maurymarkowitz#14. The GN 2 sequential-path fix at 6a7a395 corrected the echoed environment block and the far-field case (deck 03 passes at 4.0e-06), but the near-ground solution is still wrong -- and deck 11 echoes RELATIVE DIELECTRIC CONST.= 10.000 correctly while getting the answer wrong, which is exactly why this matrix pins impedances and not just the echo. When maurymarkowitz#14 closes, move deck 11's entry from expected_open.json into expected.json and the floor grows by one deck. The provenance rule: every pin is nec2c 1.3.1's printed value, cross-checked against two engines that share no code with it -- PyNEC (nec2++, an independent transliteration of the same Fortran) and momwire 0.56.0 on its sinusoidal basis (an independent method-of-moments code). Each deck's CM lines carry the pin and the measured spread; PROVENANCE.md records what every engine returned, so a pin can be audited rather than trusted. It also states plainly what the tiers are: onec and nec2c agree to 1e-6 because they are the same lineage, nec2++ to ~2e-4, momwire to ~1%. 1e-4 is a regression tolerance against the pin, not a claim of absolute accuracy. Deck 11 is the tightest three-way row in the matrix -- all three engines inside 9.5e-04 of each other, with onec 1.7e-01 away from all three. Deck 10 is pinned two-way, on nec2c and momwire: PyNEC's gx_card path returns 109.563 +50.807j where its own explicit two-wire twin returns 24.897 +67.353j, so nec2++ gets the symmetric solve wrong and cannot serve as a third opinion on that axis. nec2c's GX result is bit-identical to its own explicit twin. run_golden.py is stdlib-only and Python 3.8 compatible. It parses every ANTENNA INPUT PARAMETERS block, compares at 1e-4 relative on |Z - Z_exp| / |Z_exp|, and exits 1 on a drifted impedance, a nonzero onec exit, or a missing block, naming the deck. It also carries the guard that would have caught the first half of maurymarkowitz#14: for a deck with a GN card, the echoed ANTENNA ENVIRONMENT block must match the deck's own epsr and sigma. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KGphPpW5qvL51b5xXQ8m5i
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The CI matrix offered on #15: eleven minimal decks, one per feature axis, with pinned input impedances, a stdlib compare script, and two jobs appended to
ci.yml. Nothing else in the workflow changes (37 lines added, none removed); both jobs reuse theonec-linux-openblasartifactbuild-linuxalready uploads, so they add no build.What is in it
tests/golden_tests/:decks/01_dipole_free.nec…10_gx_symmetry.nec— free-space dipole,GN 1,GN 2,LD 0,LD 5, a three-wire junction,TL,NT, a three-pointFRsweep,GXsymmetry. 10–12 lines each; every deck'sCMlines state its axis, the pin and the measured spread across engines.decks/11_gn2_low_height.nec—GN 2with the dipole 0.02 λ up: the case All GN grounds (including GN 1 PEC) silently produce free-space results on the sequential path #14's fix did not reach (see below).expected.json— pins for decks 01–10 (twelve points), tolerance 1e-4 relative.expected_open.json— pins for decks tied to an open issue (deck 11, All GN grounds (including GN 1 PEC) silently produce free-space results on the sequential path #14). When the issue closes, move the entry intoexpected.jsonand the floor grows by one deck.run_golden.py— stdlib only, Python 3.8+. Runsonecper deck, parses everyANTENNA INPUT PARAMETERSblock, fails on|Z − Z_expected| / |Z_expected| > 1e-4, on a nonzero exit, on a missing block, and — the All GN grounds (including GN 1 PEC) silently produce free-space results on the sequential path #14 guard — on an environment block that does not echo the deck's ownGNεr and σ. Each failure names the deck.PROVENANCE.md— every engine's raw number for every pin.Two jobs, both
needs: build-linux:acafb37golden-impedance05_ld5)golden-open-issuesThe floor is the regression contract and stays green; the red lives in the second job and points at exactly one deck.
Where the pins come from
I had suggested a three-way agreement at 1e-4 on #15. Measured, that does not exist between NEC-2 transliterations: nec2c 1.3.1 and nec2++ (via PyNEC) land about 2e-4 apart on these decks, and an independent MoM code (momwire, NEC-2's sinusoidal basis) about 1 % away. So every pin is nec2c 1.3.1's printed value, corroborated by nec2++ to ~2e-4 and by momwire to ~1 %, and the 1e-4 gate is a regression tolerance against the pin, not a claim of absolute accuracy. onec itself sits 1e-6 to 4e-5 from nec2c on the floor decks. Deck 10 is two-way (nec2c + momwire) because PyNEC's
gx_cardpath disagrees with its own explicit two-wire twin; deck 11 is three-way, and it is the tightest row in the matrix: nec2c, nec2++ and momwire inside 1e-3 of each other, onec 17 % away while echoingRELATIVE DIELECTRIC CONST.= 10.000correctly — the Sommerfeld path runs and returns a wrong number, which is why the matrix pins impedances rather than only the echo.Reproducing
Parser notes for anyone extending the script: a
TL/NTdeck prints aSTRUCTURE EXCITATIONtable with the same column shape as the input-parameters row, so the parser scopes to theANTENNA INPUT PARAMETERSheader; onec writes CRLF by default and packs negative fields without a separator, both handled.🤖 Generated with Claude Code
https://claude.ai/code/session_01KGphPpW5qvL51b5xXQ8m5i