Skip to content

v1.11.0 — a Smith chart, and the measured anchor becomes a measured trend

Choose a tag to compare

@king-aj3 king-aj3 released this 29 Aug 05:01
· 9 commits to master since this release
  • ⭐ A Smith chart — Results ▸ the new "Smith" tab. The impedance locus on the unit disc with the constant-R/X grid, VSWR 2 / 1.5 / 1.2 rings, start and end markers so the direction of increasing frequency is readable, and a star on the best match. The title states Z, VSWR, return loss and whether the load is inductive or capacitive. Tutorial 37 teaches reading it — leading on the distinction the chart exists to make and an S11 dip cannot show: resonant (the locus crosses the real axis) is not matched (it crosses it at the centre). The chart is normalised to the port, and says so in the title: on a 75 Ω or 100 Ω port an unlabelled chart is actively misleading.
  • It is hand-rolled, with no new dependency, and the reason is recorded in the source. All three Smith packages on PyPI — pysmithchart, scikit-rf, mpl-smithchart — are absent from FreeCAD's bundled Python, so any of them becomes an install-time dependency on three platforms whose bundles differ, and scikit-rf pulls pandas in to draw a chart. Against that, the mathematics is a Möbius transform and two circle formulas. The deciding argument was gateability: you cannot mutation-test someone else's projection. docs/PLAN.md named scikit-rf for "S-params/Smith" at the start of this project and it was never adopted; emstudio/post/smith.py now says why, so nobody re-litigates it.
  • ⚠⚠ Gating a Smith chart is hard because almost every true statement about one is an identity — satisfied by construction, and therefore worthless as the only check. So the load-bearing tests are cross checks against numbers derived independently: the circle geometry is verified by sampling thousands of real impedances, mapping each through Γ and confirming the images land on the circle the closed form predicts (to 1e-12); VSWR is checked against SweepResult.vswr(), the number the VSWR tab has shown since v0.8.0; and return loss must be the exact negation of s11_db(), because both sign conventions are in circulation. Mutation-proven four ways — and the wrong-circle-radius mutation is caught by only the cross-check.
  • ⚠ The new GUI check for it was itself vacuous, and that is why it is worth telling you about. Its first version read ax.lines[0] — which is the real-axis rule, not the data — and reported "2 locus points, max |Γ| 1.000" for a 41-point sweep. Green, asserting nothing. It now finds the locus by label and asserts the point count equals the sweep. It was caught only because the check prints its coverage instead of just PASS, which is the habit that has now caught four hollow checks in one week.
  • ⭐⭐ The measured radiating anchor is now a measured TREND. The published anchor PIFA is solved on four ground-plane sizes and each is checked against the anechoic-chamber column of Huynh's Table 5-1: 20 mm +0.75 %, 40 mm +1.84 %, 80 mm +0.22 %, 100 mm −0.65 % — with resonance moving +29 % across the shrink, and the non-monotonic turn reproduced. ⚠ The closed form returns 1873.7 MHz for every one of them; it has no ground-size term at all. "On a handset the chassis is part of the antenna" stops being a warning printed beside a number and becomes a checked fact.
  • ⚠⚠ Two corrections that came only from reading the source, either of which would have shipped a wrong gate. The +18.3 % ground-plane shift this project has quoted since A2 is Table 5-1's computed (IE3D) column, not its measured one — and our own de-risk note claimed the table "measures" three numbers of which none came from the measured column (it publishes no measured gain at all). The measured pair is both stronger and larger: +29.0 %. And the trend is not monotonic — resonance falls as the ground grows only to a minimum near L = 100 mm and then rises again. "Bigger ground, lower resonance" is exactly what a reasonable person writes from a summary, and it is false. A summary of a source is not the source.
  • ⚠ The obvious cheap version of this gate would have measured noise. The 80 mm and 100 mm rows differ by 6 MHz, while this gate's own mesh spread across MeshResolution 20–90 is about 30 MHz — five times larger. The 20 mm rung moves 548 MHz, roughly 18× the spread, which is why the ladder is anchored there and carries an explicit floor. The ladder asserts resonance only, never match depth: the published rows re-match the probe at every ground size while the model holds the feed fixed, so comparing S11 across it would be comparing two different experiments.
  • Every GUI command is now documented, and a gate keeps it that way. Seven of the fifty registered commands had no row in HELP.md's command table, and none was described anywhere else in it either. Two were recent headline features: Solve Wind Loading, the feature v1.9.0 was named for — the file's five "wind" hits were every one coil winding — and the Filter & Diplexer Designer, which had only the word "diplexers" in a blurb and no user-manual section, so it had no user-facing command reference at all. All seven now have rows, and doc_counts now requires every "MenuText" in commands.py to be a row or to be named in a declared allow-list for rows that deliberately cover several commands.
  • ⭐ Why two documentation sweeps missed that. The previous release ran 157 subagents over the docs and confirmed 97 findings; none was this. Both rounds hunted claims that were wrong — stale versions, stale counts, tier errors. A missing row makes no false claim, so a staleness sweep is structurally blind to it. Absence is visible only against an inventory, never against a diff with reality.
  • Fixed: the gate that watches your installed copy could not see a Windows or macOS install. Its directories and its battery prerequisite both hard-coded the Linux path, so on any other platform it skipped — silently, and exit 0. Measured on a Windows box: the installed copy was at v1.0.0, ten releases behind, with every gate on that machine green. It now resolves the FreeCAD user Mod directory per platform — three branches, because os.name is "posix" on macOS and Linux — through one function that the gate, the requirement and the check tool all share, so the layout lives in a single line.

Pre-tag proof: the full SOLVER battery ran complete on this release's code — 115 ok, 0 failed, 0 skipped, 22,007.2 s (6.11 hours) — the first complete run at 115 gates. It is also the first release whose proved tree needs no argument: the only commit that landed while it ran changed a single handoff document that no gate reads, so every executable byte the battery touched is a byte in this tag.

97 automated validation gates in this repository. Full details in CHANGELOG.md.