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 (5.1a0): generated stations load with correct values, reproduce the reference impedance, and survive a SimNEC load/save round-trip without drift.
Exporting: design → .ssn
Section titled “Exporting: design → .ssn”# Antenna alone, free spacepython -m antennaknobs.simnec_export dipoles.invvee --out invvee.ssn
# A whole station — feedline, tuner tee, and the antenna in one circuitpython -m antennaknobs.simnec_export wire.doublet_ladder_tuner --out station.ssn
# Over real ground, with an armed SimNEC frequency sweeppython -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 circuitpython -m antennaknobs.simnec_export @measured/invvee.nec --out invvee.ssnFrom the workbench, with no terminal: open the Files view and pick the
SimNEC tab. It holds the same circuit for the design on screen — its knobs,
its frequency, its ground — with Copy and Download beside it, the way
the Source and engine-deck tabs work. That is the whole export step on Windows,
where the packaged workbench is the only interface there is. The tab is offered
for every design and needs no engine installed; a design SimNEC cannot carry
shows the same refusal the command prints, naming the construct in the way. The
Generator’s frequency is the solve frequency and no sweep is armed — arming one
is --sweep below, on the command line.
Flags: --freq (MHz, default the design’s), --ground free | pec | finite | finite:<eps_r>,<sigma> | mininec:<eps_r>,<sigma> (the last as SimNEC’s own
MiniNECGround), --seg-per-wl (skip the per-wire mesh pin described below
and ask for SimNEC’s own re-mesh at NECOptions.segmentsPerWavelength
instead — for a convergence comparison against SimNEC’s own density),
--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).
SimNEC’s NEC2 reader ignores everything in that block but GW/GM/GS/EX/NT, so three more things travel as daemon directives rather than cards:
the wire conductivity as one NECOptions.mhosPerMeter for the whole
block (refused by name when the design’s wires do not all share one value);
each wire’s mesh, as a $GW_<tag>.JamSegments(N) carrying the deck’s own
segment count, so SimNEC solves the mesh you asked for instead of
re-meshing it away — unless --seg-per-wl is given, which skips these and
asks for SimNEC’s own density instead; and an insulation jacket, as
NECOptions.Insulation("W7EL", thickness, εr, 0) — the EZNEC correction
model, set inside if (NECOptions.Engine == 2) since it applies on SimNEC’s
NEC2 engine only, with an errorOutln for any other engine. A jacket is one
value for every wire, so a design whose wires carry different jackets is
refused by name.
Station designs — a build_network() ladder of feedline, tuner arms, and
transformers — additionally emit the chain as SimNEC circuit elements in
cascade order:
| antennaknobs branch | SimNEC element | carried values |
|---|---|---|
TL | SERIES_TLINE | Zo, 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 arm | SERIES_IND / SERIES_CAP | H / F, component Q quoted at the export frequency |
Shunt L/C leg | SHUNT_IND / SHUNT_CAP | H / F, Q likewise |
ideal Transformer | TRANSFORMER2 (Mdl ideal) | turns ratio (SimNEC’s N is the antenna:generator voltage ratio — handled internally, validated live) |
Load off the fed segment (traps) | SimNEC’s own NECSource load on the $GW_<tag> wire, at the load’s segment centre | R/L/C, a fixed z, series or parallel |
Load on the fed segment | SERIES_IND / SERIES_CAP between the antenna and the generator (SimNEC turns the EX card into its own source there, so the load has to be a series circuit element instead) | H / F |
self-tuning l_network_tuner(tune_to=…), "low" / "high" | XMATCH (the LC matching component, mode auto) | pass, R = the target (X 0), Qc / Ql, MHz = the tune frequency |
A self-tuning tuner exports as SimNEC’s own element, not as numbers: SimNEC
tunes it against its antenna solve, as antennaknobs tunes it against its own,
and importing the file gives the same tuner back. What that element cannot
say is refused by name: a T network, "ll" / "cc" parts, component ranges,
and a tuner with a fixed shunt side that found no match (SimNEC’s automatic
element picks its side, and would). For those, --freeze-tuners
(freeze_tuners=True) tunes the box first and writes the parts it chose as
ordinary SERIES_* / SHUNT_* elements, which import back as fixed values.
What refuses to export — and why
Section titled “What refuses to export — and why”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. A finite-Q Load
is refused by name too: SimNEC’s series elements take a fixed R/L/C, not a Q
that would need re-deriving per frequency. And a Load that lands on the fed
segment can only leave as a series L and/or C (the row above) — a resistor, a
fixed z, or a parallel pair there is refused by name, since SimNEC’s own
source already owns that spot. 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.
Importing: .ssn → design
Section titled “Importing: .ssn → design”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(). A
re-imported .ssn is a file deck like a .nec: its segment counts are what
the file says, so export → import → export is a fixed point — the export’s
one-time re-mesh of a fed wire, which puts the feed exactly at its stated
position, does not repeat on every hop.
# Any subcommand takes an @file.ssn spec, like @file.necpython -m antennaknobs draw --builder @station.ssnpython -m antennaknobs sweep --builder @station.ssn --swrpython -m antennaknobs compare_patterns --builders dipoles.invvee @station.ssn
# .ssn -> NEC deck conversion falls out of the pairpython -m antennaknobs export --builder @dip.ssn --out dip.necWhat the importer honours: the solve frequency comes from the Generator’s
MHz (in SimNEC the deck’s FR card is advisory), the Generator’s own sweep
expression is read (14 : 14.35 : 0.025, lin or log spacing honoured) and
becomes the design’s measurement band, the daemon ground call surfaces as a
--ground hint (PerfectGround, SommerfeldGround, and MiniNECGround as
the MININEC-type ground), and wire conductivity applies to every wire alike, one value for the circuit. NECUnits is read
but not applied: in SimNEC it only sets the units wire dimensions are
displayed in, and the NEC cards are metres whatever it says. NECOptions.fieldStep
(SimNEC’s far-field display step, in degrees) is likewise read and accepted
quietly rather than reported as skipped — it is a display resolution, and no
solved number depends on it — though a malformed value still refuses. Values
are read the way SimNEC writes them: component values with its SI suffixes (37.52p,
731.9n, 2K; its g is a wire gauge and is not a multiplier), and a wire
material by name (NECOptions.mhosPerMeter = Conductivities.aluminum;, with
SimNEC’s own values). An automatic XMATCH imports as a self-tuning
l_network_tuner, which tunes for the solving
engine’s own antenna impedance; SimNEC’s MHz 0 (retune at every frequency)
tunes once, at the Generator’s frequency, and the import note says so.
A $GW_<tag>.JamSegments(N) is honoured exactly: the file’s N replaces
that wire’s GW count and pins it there, so no engine’s even-count rule
moves it. An attachment that JamSegments leaves off a segment site — a feed
at the middle of an odd-count wire, say — is fed exactly where it is by
splitting the wire at that point, never snapped to a neighbouring site.
JamSegments(0) means “auto-segment as usual”, so the GW count stands,
unpinned. Short of that, SimNEC still re-meshes every wire by its own rules
before it solves, so its numbers differ from an import’s by the mesh alone;
for a same-mesh comparison, import lastConstructedNEC.nec from
~/.SimNEC/<version>/ instead — the deck SimNEC actually solved.
Each SimNEC block is its own measurement plane: the Generator is "rig"
(the far end of the feed system, not the antenna), the deck’s fed wire is
"feed" (the antenna’s own terminals) — the same two names EZNEC’s virtual-wire
idiom uses in the NEC importer — and every chain
block in between gets a node of its own, named after its label, so every
block SimNEC reports an impedance at is a measurement plane here too.
Chain elements
translate back branch-for-branch through the same table as export, plus one
import-only case: a SERIES_Z — SimNEC’s fixed complex impedance — becomes a
frequency-independent 2-port Admittance. A SERIES_TLINE’s Mdl simplified
loss model (SimNEC’s default: one dB/100-length figure at one frequency) is
read and kept as the matched-loss coefficient it implies, exact at that
frequency; any other line model is refused by name rather than approximated.
A chain element outside the translated set makes network() refuse rather
than build a station with a silently-missing tuner part.
Which .ssn files import. SimNEC lets a circuit hold its antenna two
ways, and antennaknobs reads one of them: NEC cards between a NEC2 line
and a NECEND line, inside a NETWORK element’s script. That is what
SimNEC’s NEC portal accepts and what the export above writes, so every
round-tripped file qualifies.
The other way is a script — NECWire and NECSource calls against
declared variables, which SimNEC evaluates itself, leaving no cards in the
saved file. antennaknobs does not evaluate SimNEC’s scripting language, and
says so by name rather than reporting a missing block. To bring such an
antenna in, either write its cards into a NEC2 … NECEND block in the NETWORK
script, or export a design from antennaknobs to .ssn and edit that.
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.
The round-trip guarantee
Section titled “The round-trip guarantee”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.
Using momwire as SimNEC’s engine
Section titled “Using momwire as SimNEC’s engine”momwire is the solver SimNEC calls — pip install momwire provides the
momwire-nec2c drop-in engine, and the portal lives in momwire itself.
Install, wrapper-script recipe, --basis selection, the probe/version
contract, and the dialect it serves are documented on momwire’s own site:
The .ssn export/import above is antennaknobs’ side of the pairing: build
or import the antenna here, hand SimNEC the circuit, and point SimNEC’s
engine at momwire.
Licensing
Section titled “Licensing”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 (now part of momwire) 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.