Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* **`gshank` Shanks-tail convergence floor restored after it caused non-terminating Sommerfeld integrations:** issue #131 item 3 also raised gshank()'s convergence floor from `denm = 1e-3*den*CRIT` to `2e-1*den*CRIT_H` — 200× looser. On decks with wires close to a `GN 2` ground (e.g. a radial screen elevated 0.2 m over epsr 13 / sig 0.005 at 2.7 MHz), the truncated Shanks tail degrades the Sommerfeld tables enough that `rom2()` can never meet its `RX = 1e-4` Romberg test: the integration doubles to the 65536-subdivision cap at every step, emits an endless `ROM2 -- STEP SIZE LIMITED` stream (GB/minute into both stdout and the output file) and effectively never terminates. The same deck completes in ~14 ms with the previous floor, agreeing with `nec2c` (13.906 − j445.84 Ω). The floor is restored to `1e-3*den*CRIT_H` while the milder `CRIT_H = 1.1e-4` tail-test scaling is kept; output is byte-identical (modulo timing lines) to the pre-loosening build on `sommerfeld2/3` and `bruce_sommerfeld`. Regression decks: `testharness/data/wire_order_normal.nec`, `wire_order_reversed.nec`; unit test `[issue139]` (which also fails on this regression via timeout).
* **`nec2diff` compares negative values, reports finite sign-flip differences, and exits non-zero when results differ (#138):** the real-valued `diff()` in `BaseInput.h` tested *signed* values against the near-zero floor (`a < 1e-8 && b < 1e-8`), so any two negative numbers compared equal — a 178 Ω negative-reactance change (`−179.39 → −1.00`) or a `−1.71 → −9.71 dBi` gain change reported `Difference = 0`. A pure sign flip (`−179.39 → +179.39`) divided by `|a+b| = 0` and printed `inf`. Both `diff()` overloads now normalize by the larger magnitude (`|a−b|/max(|a|,|b|)`), keeping the near-zero early-out but keyed on absolute values. Two behavioral notes: (1) this metric is close to twice the old `|a−b|/|a+b|` for near-equal values, so the `equalto()` thresholds (sum ≤ 1e-4) now bind about twice as tightly and previously hidden last-digit engine discrepancies are visible in `nec2diff` output; (2) `main()` now tracks a flag across the three sections and returns 1 if any section differs, so scripts and harnesses can rely on the exit status. `nec2diff` with fewer than two arguments prints usage and returns 1 instead of throwing `std::logic_error` from a null `std::string` construction. Regression fixtures and an exit-code test live in `tests/data/issue138/` (ctest `necpp_nec2diff_issue138`); the four cases report 0.994, 0.824, 0.167 (control) and a finite 2.0, matching the reporter's values.

### Tests
* **Sommerfeld near-ground limit deck (`testharness/data/sommerfeld_near_ground.nec`, PR #137):** a horizontal half-wave dipole 0.02 wavelengths above a `GN 2` ground with sigma 1e10 S/m, i.e. a half-space that is effectively a perfect conductor. Over a true perfect conductor (`GN 1`, exact by image theory) the same antenna gives R = 0.9168 Ω and average power gain 1.9953 (the lossless limit is 2); at this height every SOMNEC-derived engine — nec2++, `nec2c` and the original Fortran (aegnec2) — instead returns R ≈ 1.759 Ω and gain ≈ 1.043, whose pattern integral accounts for only about half the supplied power. The deck documents a shared NEC-2 Sommerfeld limitation near ground (NEC-2 Part 3 claims the Sommerfeld/Norton method "is accurate close to the ground", which the inherited SOMNEC implementation does not achieve in the σ→PEC limit), not a translation bug. It also records that the pre-`e3f81e6` interpolation bug landed much closer to the exact limit (R = 0.924, gain = 1.980) purely because its stale coefficients pulled the near-ground values that way — verified on commit `a8e829e`. The deck joins `SOM_TESTS`; it documents current behavior on all engines and is not a pass/fail gate.

### Performance
* **`saoa` shares one `xl*xl` across all five uses:** the Sommerfeld integrand squared `xl` independently for each of `cgam1`, `cgam2` (the two complex `sqrt` arguments), the three `dgam` large-|xl| branches, and the `rho==0` transverse answer. One complex multiply per integrand evaluation is now shared (issue #131). Algebraic identity — byte-identical output on all five `GN 2` decks; benchmarked at ≤0.1% on a noisy laptop, consistent with the multiplication being a small fraction of the transcendental-dominant kernel.
* **Triangular solves now use Eigen's blocked `solveInPlace`:** `solve()` (`matrix_algebra.cpp`) replaced its hand-rolled scalar forward/back substitution with `triangularView<UnitLower>/triangularView<Upper>` `solveInPlace`, eliminating two heap temporaries per call and the cache-hostile row-walk of column-major data. Hot in plane-wave sweeps (one solve per incidence angle).
Expand Down
15 changes: 15 additions & 0 deletions testharness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,18 @@ Drop a `.nec` input file into `data/`. The harness will run it through

The `data/` directory contains over 45 models covering dipoles, patches,
helices, Sommerfeld ground, arrays, and more.

### Known-limitation decks

Some decks document behavior rather than assert correctness, so their
output files record what every engine currently produces:

- `sommerfeld_near_ground.nec` — a horizontal half-wave dipole 0.02
wavelengths above a `GN 2` ground with sigma 1e10 S/m (an effectively
perfect half-space). Over a true perfect conductor (`GN 1`) the same
antenna gives R = 0.9168 ohms and average power gain 1.9953 (the lossless
limit is 2), but every SOMNEC-derived engine — nec2++, nec2c and the
original Fortran — returns R ≈ 1.759 ohms and gain ≈ 1.043 there. This
is a shared NEC-2 Sommerfeld limitation near ground, not a translation
bug (PR #137). Compare against the `GN 1` variant of the deck to see the
gap.
Loading