Skip to content

NEC-5 as a third engine

NEC-5 is LLNL’s modern rewrite of the NEC lineage — a mixed-potential formulation with basis functions in the RWG family, released in 2019 and distributed under an individual license. antennaknobs can drive it as a third engine beside momwire and PyNEC: it writes NEC-5-dialect decks, runs your licensed executable, and parses the printout back into the same impedance, current, pattern and power-budget readouts every other engine serves.

Why bother, when two engines already cross-check each other? Because the three implementations share almost nothing: momwire’s sinusoidal and B-spline families, NEC-2’s reduced/extended thin-wire kernels, and NEC-5’s mixed-potential formulation are independently derived and independently coded. When all three agree, the agreement means something — and when they split, the split is a finding (see the solver page for how antennaknobs treats cross-engine differences as data, not noise).

The workbench’s gear menu has Download NEC-5 .nec, and it is offered whatever engines that machine has: writing a deck needs no binary. It is the same file the corpus tool’s catalog-nec5/ ships for that design at that mesh and ground, from the same writer — so a deck you download and a deck from the published set cannot disagree. It is also the dialect that carries what NEC-2 cannot: buried wires, wires in the ground plane, and momwire’s graded meshes.

NEC-4.2 carries buried wires too, and it has its own deck download: see the NEC-4 deck. It was verified against a licensed NEC-4.2 before it was offered.

Licensing, and where the engine will not run

Section titled “Licensing, and where the engine will not run”

NEC-5 is licensed software. antennaknobs never bundles, downloads, or hosts it: the engine activates only when you point it at a binary you license yourself, and the hosted simulator can never offer it (the license forbids service use, and the hosted machines simply have no binary). What antennaknobs generates and parses — decks and printouts — are yours to keep; captured printouts in the test suite carry the LLNL-CODE-746721 citation as End-User Reports.

Point the engine at your executable with one environment variable:

Terminal window
export NEC5_EXE=~/nec5/nec5cl # your licensed binary

On Windows, in PowerShell, before starting the workbench in the same window (EZNEC Pro+ keeps its engine in its own Docs folder as NEC5CL_x13.exe — the suffix is the build; Docs\LastRun.log names the one it ran):

Terminal window
$env:NEC5_EXE = "C:\EZNEC 7.0\Docs\NEC5CL_x13.exe"

That is PowerShell syntax (its prompt starts with PS). In Command Prompt (prompt C:\Users\you>) the same line fails with “The filename, directory name, or volume label syntax is incorrect”; the Command Prompt spelling is

Terminal window
set NEC5_EXE=C:\EZNEC 7.0\Docs\NEC5CL_x13.exe

with no quotes. Either shell works; the variable lives in that window only, so set it and start the workbench in the same one.

To name the engine once for every start, put it in your settings.toml instead, as nec5_exe under [engines]. The variable wins over the file.

When a NEC-5 answer surprises you, the two things to look at are the deck antennaknobs handed the binary and the printout it got back. In the workbench, the Files view shows both for the solve on screen. Two switches also keep them, for NEC-5 and NEC-2 alike:

Terminal window
export ANTENNAKNOBS_CAPTURE_DIR=~/ak-captures # every run leaves nec5/<hash>.nec + <hash>.out
export ANTENNAKNOBS_LOG_LEVEL=DEBUG # the deck and printout in the server log as they run

The packaged workbench takes the same two as --capture-dir DIR and --log-level DEBUG. It also takes the engine itself as --nec5-exe PATH (and --nec2-exe PATH), which reads the same in PowerShell and Command Prompt and wins over NEC5_EXE, over settings.toml and over a NEC5_EXE.txt beside the program. In settings.toml the capture folder is dir under [capture]. The capture directory is the pair of files to attach to a report; the hash in the file name is the deck’s own, so two runs of the same deck share one pair. At INFO the log is one line per run (hash, seconds, printout length). For NEC-5 a captured printout is also served back for the same deck without re-running the binary; NEC-2 captures are write-only.

Everything below lights up exactly when NEC5_EXE resolves — the CLI engine name, the workbench slot entry — and disappears when it doesn’t. If you run a local web instance with the variable set, the NEC-5 slot is available to anyone who can reach that instance; keeping it off the open internet is your call to make, the same as for any local service.

nec5 joins the --engines roster:

Terminal window
# The triangle: momwire vs PyNEC vs NEC-5 on one design
python -m antennaknobs compare_patterns \
--builders beams.moxon beams.moxon beams.moxon \
--engines momwire pynec nec5 --fn triangle.png

Every solve is one run of the binary in a scratch directory — deck in, printout out, parsed and discarded. Sweeps batch uniformly-spaced frequencies into a single run using NEC-5’s linear FR stepping.

capabilitystatus
Impedance, currents, frequency sweepsserved
Groundsfree space, PEC, NEC-5’s native Sommerfeld (("finite", eps_r, sigma)), and EZNEC’s MININEC-type ground (("mininec", eps_r, sigma)) as GE 1 with a bare GD
Buried wiresserved over the Sommerfeld ground — the GE ground flag follows the deck: GE -1 0 where every conductor is below the plane, GE 1 0 where one stands at z = 0, which is the legal contact that joins a monopole to its detached screen. The two settings say opposite things about a wire end on the plane (bond it to ground, or leave the current expansion alone), so the flag is a property of the geometry and not a constant
Radiation patternsserved (compare_patterns, the web far-field views)
Feedsplain Wire.ex, network Driven, and DrivenCurrent via NEC-5’s native current source (EX 4 — NEC-2 has no equivalent)
LoadsLoad branches (fixed-Z and series/parallel RLC) at the port
Wire materialconductor loss natively; an insulation jacket as the same coated-wire pair momwire models, spelled in cards — the equivalent radius on GW, the jacket’s inductance as LD 2, and LD 5 rescaled so the copper loss stays the real conductor’s. NEC-5 dropped NEC-4’s insulated-wire card. A jacketed wire that is also buried gets no card for momwire’s in-soil charge correction (there is nowhere on a NEC card to put one), so its deck carries CM lines saying so — the deck models that jacket as if it were in air, and its impedance will differ from antennaknobs’ own by that correction (#1677)
Power budgetinput/radiated/wire-loss/efficiency, plus hemisphere average gain (the ground-absorption readout)
Transmission lines, transformers, two-ports, virtual drivers, ql/qc loadsserved through a multiport-Y reduction: NEC-5 solves the antenna’s admittance at its real ports, the circuit is reduced onto them, and every other reading (currents, the pattern, the power budget) runs a deck driven at the ports’ resolved voltages. NEC’s own pattern there is reported per watt the sources deliver, which is what NEC-5 prints when it carries the same network in its own cards. Two port kinds refuse loudly, each by name: a floating port, whose second terminal NEC-5 cannot expose, and a distributed port, whose knot weighting is not derived
Ground-geometry refusalsmid-span interface crossings (the binary runs them and prints garbage), wires lying in the plane, buried wires under a PEC or MININEC-type ground (image theory has no buried side), and coincident wires — each refused by name at construction

Refusals are the design: NEC-5 either solves exactly what you asked or tells you precisely why not — never a silently simplified model. The coincident-wire refusal is the buried screen’s sharp edge: momwire’s connected-radial spelling brings each radial up as one of N coincident rises, a bundle momwire regularizes exactly but NEC-5 silently prints garbage for (measured: thousands of ohms and an astronomically wrong radiated power). So the buried-radial vertical carries two variants, one per engine: the default connected screen solves through momwire and refuses here; its detached variant — the stake convention, radials lying at depth touching nothing — solves here (the momwire#567 anchor class NEC-5’s own convention serves) and refuses through momwire. The two conventions are two different structures, tens of ohms apart over average soil; comparing them compares junction physics, not solver accuracy — never expect the numbers to agree.

Two conventions worth knowing, both pinned from the NEC-5 User’s Manual during development:

  • Sources sit at segment ends (knots), not segment centers as in NEC-2. The deck writer meshes fed wires with even segment counts so the feed lands exactly at the wire’s middle knot — the same physical point the other engines drive. A PortAtVertex apex feed uses this natively: its source is the named wire’s own end knot (segment 1 end 1, or segment n end 2), so no parity coercion applies and a vertex-only wire keeps its authored segment count. A deck imported with an odd count is rounded the same way — 4nec2’s Example 2 dipole goes to NEC-5 as 10 segments with the source at the centre knot, not 9 with a centre segment — and the solver-slot label shows the requested count. At nine segments on a half-wave dipole that convention alone is worth a couple of ohms against the deck’s own spelling in the same engine; both converge as N grows. The two engines’ fed segments therefore differ in size: the catalog’s 50 mm feed-gap wire is one 50 mm segment under momwire’s default basis and two 25 mm segments under NEC-5. That is immaterial at an ordinary driving point, but near an open circuit the impedance follows the fed segment’s size, so this project’s cross-engine comparisons record each engine’s fed segment beside its impedance.
  • The “fast” ground model is served as full Sommerfeld. NEC-5 has no reflection-coefficient approximation (its IPERF 0 is the Sommerfeld solution), so asking for the fast model gets the accurate one, and the applied-model readout says so.

With NEC5_EXE set on the machine serving the web UI, NEC-5 appears in the slot A/B/C solver picker like any other backend. The natural use is A/B: the same design and mesh in two slots, momwire against NEC-5, readouts side by side. NEC-5 solves are one subprocess per request with no resident state — fine for check-this-snapshot comparisons, heavier than momwire’s in-process solves for live knob-dragging.

Cross-engine agreement on reference designs runs a few ohms of impedance (the different formulations’ genuine spread) and ~0.01 dB RMS on far-field patterns. The one apparent exception closed under study, and the closing is worth telling: the day the engine landed, NEC-5’s reactance at very low heights over lossy Sommerfeld ground (≈0.05 λ) sat ~7 Ω away from the mutually-agreeing NEC-2 lineage, and was documented here as a formulation difference. The full corpus comparison then swept a dipole from 0.02 λ to 1.0 λ and found the offset is height-independent — a feed-model term from NEC-5’s knot-source mesh march, not close-ground physics — and that Richardson-extrapolating NEC-5’s (N, 2N) pair dissolves it entirely: extrapolated NEC-5 agrees with the NEC-2 lineage to ≤ 0.17 Ω in reactance at every height. Both halves are pinned in the test suite — the raw single-mesh offset and its extrapolated resolution. That is the cross-validation triangle doing its job twice: first flagging a real discrepancy, then identifying it as convergence behaviour rather than physics.

The cause of that convergence behaviour was then pinned down in its own study. A clean first-order march is also the signature of feeding or reading a solver half a segment wrong, so every harness-side suspect got a discriminating experiment: the two spellings of the same feed knot solve bit-identically; a deliberate one-segment feed slide produces an effect one to two orders smaller than the march (and shrinking a full order faster); NEC-5’s native current source (EX 4) — whose input-parameters row carries the driven current exactly, leaving no readout convention in play — walks digit-for-digit with the voltage source; segment-parity coercion moves at most one segment on one wire, worth sub-milliohm shifts; and LLNL’s shipped sample models run through this engine’s own runner reproduce the shipped reference printouts to every printed digit. The march is NEC-5’s own knot-source discretization — first-order in segment length, converging to the same limit the other engines agree on — which is why the (N, 2N) Richardson pair is the permanent recipe for census-grade NEC-5 numbers rather than a workaround for a bug on either side of the interface. LLNL’s NEC-5 Validation Manual documents the behaviour: its introduction notes that the linear current expansion converges more slowly than the sinusoidal expansion of the earlier NEC codes, and §2.3’s dipole ladders demonstrate it, attributing an N-dependent feed term to the effective shunt capacitance of the source gap, whose width scales with segment length (Burke & Poggio, NEC 5.0, LLNL-CODE-746721).

NEC-5’s wire discretization is identified in the open — from the public User’s Manual (§1) and black-box printout comparison, with no NEC-5 source consulted: a tent (triangular) current expansion on segment knots, razor-blade mixed-potential testing between adjacent element centroids, and ∫A·dl taken as the two-point centroid trapezoid. momwire implements that exact scheme as RazorSolver with nec5_quadrature=True (momwire#309, momwire#316), and the resulting formulation twin reproduces NEC-5’s printouts to a constant ≈0.04 Ω down full convergence ladders on a thin dipole, a bend, a junction-fed apex and a closed loop; on a 10 mm wire the residual grows with a/h to ≤0.07 Ω, the signature of a kernel-evaluation nuance rather than a further quadrature difference. The validation page carries the panel. The twin is the controlled experiment behind the pair recipe: on a 14 MHz dipole the same tent basis under Galerkin testing (bs1) sits within 0.5 Ω of its converged value at 48 segments where NEC-5’s formulation is still outside that band at 96, and momwire’s degree-2 B-spline (bs2) gets there at 12 (16 on an inverted-V, 32 on the fat dipole). Eight times the segments is 64× the fill and roughly 500× the dense solve, before the second solve the (N, 2N) pair costs.

What each engine spends per solve is measured on the same footing: a matched ladder on a 2×4 bowtie array, free space, single frequency, every process capped at 8 GB of address space. NEC-5’s peak resident set converges to about 1.02× the dense N×N matrix plus ~60 MB, and nec2c’s to the matrix plus 3–5 MB — both are essentially the in-core matrix and nothing else, which puts each engine’s ceiling near 23k segments in an 8 GB budget. momwire’s B-spline path sits higher, about 1.5× dense in free space and 2.1× under full Sommerfeld (its certified figures at 8,320 basis functions), for a ceiling of 15–18k basis functions: the working copies a higher-order basis needs while it assembles in windows. Wall clock runs the other way at that size — 8,320 segments takes nec2c 466 s, NEC-5 37 s, and momwire’s bs2 29 s. NEC-5 is a lean, fast solve; what the triangle pays for it is the mesh its formulation asks for, not the code that runs it.

@file.nec import recognises NEC-5’s edge-source EX spellings (a negative segment number, or the end-selector field NEC-2 never uses) and refuses them with the dialect named rather than silently shifting the feed half a segment to the NEC-2 reading — the NEC deck import page has the details. Decks in the common NEC-2 subset load normally, and NEC5Engine itself accepts them as-is.