Skip to content

SimNEC round-trip

SimNEC (AE6TY) is the successor to SimSmith: a Smith-chart station tool with NEC2 embedded behind its own MNA circuit solver. antennaknobs speaks its native .ssn circuit file in both directions — export a design for SimNEC to solve, or load a SimNEC circuit as a design — so the same antenna and matching chain can be checked by two independently written solvers without hand-entering geometry or component values in either direction.

The element mapping is validated against a real SimNEC installation (6p4d6): generated stations load with correct values, reproduce the reference impedance, and survive a SimNEC load/save round-trip without drift.

Terminal window
# Antenna alone, free space
python -m antennaknobs.simnec_export dipoles.invvee --out invvee.ssn
# A whole station — feedline, tuner tee, and the antenna in one circuit
python -m antennaknobs.simnec_export wire.doublet_ladder_tuner --out station.ssn
# Over real ground, with an armed SimNEC frequency sweep
python -m antennaknobs.simnec_export loops.skyloop_lmatch \
--ground finite:13,0.005 --sweep 6.9,7.3 --out skyloop.ssn
# A NEC card deck converted straight to a SimNEC circuit
python -m antennaknobs.simnec_export @measured/invvee.nec --out invvee.ssn

Flags: --freq (MHz, default the design’s), --ground free | pec | finite | finite:<eps_r>,<sigma>, --seg-per-wl (SimNEC re-meshes at its own segments-per-wavelength — the deck’s segment counts are advisory there), --sweep (bare for ±10% around the frequency, or LO,HI), --name, and --out (default stdout).

Antenna-only designs export as SimNEC’s canonical three-element circuit — LOAD / NETWORK / GENERATOR — with the geometry riding inside the NETWORK element as a NEC-portal script (the same GW/FR/EX/lumped-LD cards export emits, plus daemon directives for ground and mesh density).

Station designs — a build_network() ladder of feedline, tuner arms, and transformers — additionally emit the chain as SimNEC circuit elements in cascade order:

antennaknobs branchSimNEC elementcarried values
TLSERIES_TLINEZo, VFnom, length (ft), k1/k2 matched-loss coefficients (dB/100 ft = k1·√f + k2·f — the same cable-table convention both sides), loss model pinned to k0k1k2
TwoPort L/C armSERIES_IND / SERIES_CAPH / F, component Q quoted at the export frequency
Shunt L/C legSHUNT_IND / SHUNT_CAPH / F, Q likewise
ideal TransformerTRANSFORMER2 (Mdl ideal)turns ratio (SimNEC’s N is the antenna:generator voltage ratio — handled internally, validated live)
Load on a real port (traps)stays an LD card in the deckR/L/C

SimNEC’s cascade elements are purely differential: there is no common-mode knob on its transmission line. A design whose physics lives in the common mode — a BalancedLine with zcomm, a FloatingBalun, the balanced tuners built from them — cannot be faithfully represented, and the exporter raises a clear error naming the offending branch instead of silently dropping the common mode and emitting a confidently-wrong circuit. The same applies to non-ladder topologies, current sources, lossy transformers, and distributed (finite-gap) feed ports. About four in five catalog designs export; the refusals tell you exactly what construct is in the way.

Component Q deserves one note: antennaknobs models ql/qc as frequency-independent while SimNEC quotes Q at a frequency, so a lossy component is exact at the export frequency and Q-model-approximate across a SimNEC-side sweep. Q = 0 means ideal (lossless) on both sides.

The reverse direction loads a SimNEC circuit — one you built in SimNEC, or one that came back modified from a round-trip — as antenna geometry plus, for station files, the matching chain as a real build_network():

Terminal window
# Any subcommand takes an @file.ssn spec, like @file.nec
python -m antennaknobs draw --builder @station.ssn
python -m antennaknobs sweep --builder @station.ssn --swr
python -m antennaknobs compare_patterns --builders dipoles.invvee @station.ssn
# .ssn -> NEC deck conversion falls out of the pair
python -m antennaknobs export --builder @dip.ssn --out dip.nec

What the importer honours: the solve frequency comes from the Generator’s MHz (in SimNEC the deck’s FR card is advisory), an armed Generator sweep becomes the design’s measurement band, the daemon ground call surfaces as a --ground hint, wire conductivity applies per-wire, and NECUnits scales geometry to metres with NEC’s own scaling semantics. Chain elements translate back branch-for-branch through the same table as export, and a chain element outside that set makes network() refuse rather than build a station with a silently-missing tuner part.

In Python the same machinery is read_ssn(self, "circuit.ssn") / parse_ssn(text)read_ssn ships a .ssn next to a user design in ~/.antennaknobs/designs/, with the same folder confinement as read_nec.

Export → import is pinned by identity tests: a transformer’s turns ratio and every element value of the validated ladder-tuner cascade (line Zo/VF/length, loss coefficients, both capacitors, coil and its Q) survive the full cycle unchanged. If the two sides ever disagree about a convention, the suite fails rather than the circuits quietly diverging.

The round-trip above hands SimNEC a file and lets SimNEC’s own bundled NEC2 solve it. There is a second, tighter connection: momwire can be the solver SimNEC calls.

SimNEC does not link NEC2 — it shells out to a nec2c executable, starts one copy, and keeps it. Decks go down that process’s stdin framed by an NX card, printouts come back on stdout, and SimNEC’s MNA circuit solver reads two numbers per feedpoint out of each printout to build the antenna’s Y matrix. antennaknobs.nec_portal is a drop-in for that process, with momwire’s B-spline Galerkin solver behind it. Your Smith chart, tuner, and sweeps stay SimNEC’s; the electromagnetics become momwire’s.

Install antennaknobs anywhere with a Python environment; the package ships a console script:

Terminal window
pip install antennaknobs
which momwire-nec2c # e.g. ~/.venvs/ak/bin/momwire-nec2c
momwire-nec2c -version # nec2c.ae6ty.9.1

Then open SimNEC’s NEC portal dialog and paste that path in as the NEC command. Two rules decide whether SimNEC accepts it, and both are worth knowing because the failure modes look nothing like their causes:

  • The filename must contain nec2c. SimNEC picks the engine’s dialect off the command’s file name, lowercased — a name with none of nec2c / nec5 / nec42 in it is refused outright with NO NEC Command Available. That is why the script is called momwire-nec2c and not something tidier; if you wrap it in a shell script or a symlink, keep nec2c in the name.
  • The version probe must answer. SimNEC runs <command> -version and reads the first line, which has to be nec2c.ae6ty. followed by a plain number it can parse as a decimal. The portal answers nec2c.ae6ty.9.1. It cannot say “momwire” there — an extra dot makes the parse fail and SimNEC reports nec2c version too old — so the engine puts its real identity in the printout banner instead, where every SimNEC session logs it: VERSION:nec2c.ae6ty.momwire.9.1.

Before a live session, run the built-in smoke — it needs no checkout, spawns one resident copy of itself, runs embedded decks through it the way SimNEC does, and prints PASS or FAIL:

Terminal window
momwire-nec2c --selftest

SimNEC launches engines through the shell, so the command you paste into the portal dialog can carry arguments. The portal accepts a --basis flag:

momwire-nec2c --basis bspline # the default
momwire-nec2c --basis sinusoidal-galerkin # closest to NEC's own formulation
momwire-nec2c --basis sinusoidal-galerkin-converged # recommended for near-open high-Q feeds

Paste two portal entries that differ only in --basis and you have cross-basis validation inside SimNEC itself — switch engines from the dialog and watch whether the answer holds. The printout banner records which physics answered (VERSION:...momwire.9.1+sgc), a mistyped basis fails the version probe loudly at configure time, and the -converged variant is the documented setting for feeds near a current null — the one antenna class where bases legitimately disagree at coarse segmentation.

Everything SimNEC’s portal actually emits for wire antennas:

Feedpoint impedanceEX 0 voltage sources, one or many, and the YY report card SimNEC probes multi-port antennas with
Frequency sweepsmulti-point FR, the whole sweep in one deck
GeometryGW wires with GM / GX / GR / GS / GA / GH transforms
Groundfree space, GE ±1 perfect ground, GN 0 reflection-coefficient and GN 2 Sommerfeld finite ground
LoadingLD 0 / 1 / 4 / 5 — series RLC traps, distributed loading, wire conductivity
PatternsRP 0 far-field grids, gain and polarisation, normalised to input power
Near fieldsNE / NH rectangular grids in free space or over perfect ground
NetworksNT two-port admittance branches and TL transmission lines between segments
HousekeepingEK extended-kernel, MP multicore hints, PT print control, GD second-medium parameters — accepted and echoed exactly as nec2c does (advisory where momwire’s own physics governs)

One thing is faster than the engine it replaces, structurally. SimNEC probes an N-port antenna by sending N excitation groups in one deck, and a stock nec2c refills and refactors the whole moment matrix for each — N fills for one matrix. The portal takes the union of every group’s ports, fills and factors once per geometry and frequency, and answers each group by back-substitution on the cached factors. A three-port deck costs one fill, not three.

A deck the engine cannot model is reported and stepped over, never guessed at: the printout names the offending card and why, and still carries the NX sentinel that SimNEC blocks in readLine() waiting for. (An engine that dies or forgets the sentinel hangs SimNEC’s UI with no timeout, which is strictly worse than an error message.) The daemon survives it and runs the next deck.

Refused today:

  • Surface patches (SP, SM) — momwire is a wire solver.
  • IS — NEC-4.2 wire insulation; momwire’s insulation model is not wired through the portal.
  • RP modes 1–6 and the gain-only form — mode 0 is the only one SimNEC’s own path emits; the others print different tables (they are what the GD cliff parameters feed, so a deck asking a cliff question refuses rather than answering it as flat ground).
  • Spherical NE / NH grids (I1 = 1) — rectangular only.
  • Near fields over finite ground — the near field of a Sommerfeld half-space is not an image, and pretending otherwise would be quietly wrong. Far-field patterns over finite ground are fine.
  • GN radial-wire ground screens (a non-zero radial count) — momwire has no screen model, and ignoring the field would silently change the answer.

SimNEC keeps a crew of engine processes and hands decks out among them. A momwire process is not a 2 MB C binary: each one carries NumPy, SciPy and momwire — about 90 MB resident before it solves anything — plus the dense complex matrix and its factors, which grow as the square of the segment count. It is also much quicker per deck once warm (a 106-segment design solves in ~130 ms, a small dipole in ~2 ms), so a smaller crew keeps up with a larger one of the C engine.

On a 16 GB machine, set the NEC crew size to 4. Larger crews buy little, because the win here is the single fill per geometry rather than parallelism across decks, and they multiply the per-process floor by the segment count you are least expecting.

SimNEC is proprietary freeware. antennaknobs emits and parses its open file format for interoperability — like emitting a NEC deck or a Touchstone file — and copies none of SimNEC’s bundled assets. The engine portal is the same kind of interoperability in the other direction: it reproduces the printout layout SimNEC’s reader expects, worked out from observed output, and contains no nec2c code.