magnelio.ports#

Ports — declarative port classes, specs, conductors and reports. PortWaveguide, PortAnalytical and PortLumped are declared on the GeometryModel before meshing; the PortSpec* family covers custom setups passed to an analysis via ports=; refine_port_modes() converges a port’s mode parameters on its own plane. The builders and runtime operators behind them are internal.

class magnelio.ports.BboxLateralConductor#

All four lateral bbox-wall nodes — the typical outer conductor.

For a port plane on (say) X_MIN, the lateral walls are the four bbox faces whose normal axis is tangential to the port plane (i.e. Y_MIN, Y_MAX, Z_MIN, Z_MAX). All primal 2D nodes that sit on any of these walls are taken to belong to this conductor — i.e. all nodes with i_u ∈ {0, Nu_node−1} or i_v ∈ {0, Nv_node−1}.

Useful for rectangular coax (the bbox itself acts as the outer conductor) and any other “outer = bbox boundary” topology.

class magnelio.ports.Mode(name, mode_type, omega_c, epsilon_r, field_evaluator, z_line=None, discrete_e_u_profile=None, discrete_e_v_profile=None, discrete_h_u_profile=None, discrete_h_v_profile=None)#

A single waveguide eigenmode with closed-form frequency dependence.

A Mode carries its transverse field information in one of two mutually exclusive forms:

  • Analytical (Phase 1) — field_evaluator is set to a closure that samples the Poynting-normalised profile at any (u, v) point. All four discrete_*_profile fields are None. Used by CoaxAnalyticalModeSolver and RectWGAnalyticalModeSolver; resampled and B-orthonormalised onto the FIT grid by discretize_modes().

  • Numerical (Phase 2) — all four discrete_*_profile arrays are set to M_ε-orthonormal edge vectors built natively on the port-plane FIT grid; field_evaluator is None. Used by Numerical2DModeSolver; discretize_modes() passes these through unchanged (no resampling, no Gram-Schmidt).

The validity invariant is enforced at construction.

Parameters:
  • name (str) – Human-readable mode identifier, e.g. "TEM" or "TE10".

  • mode_type (ModeType) – Mode classification. Drives the formulas for z_wave and gamma.

  • omega_c (float) – Cut-off angular frequency [rad/s]. Zero for TEM.

  • epsilon_r (float) – Relative permittivity of the (homogeneous) cross-section filling. Required by the wave-impedance and propagation- constant relations.

  • field_evaluator (FieldEvaluator or None) – Analytical-path closure that returns the Poynting-normalised transverse field profile at user-supplied (u, v) sample points. None on the numerical path.

  • z_line (float or None, default None) – Frequency-independent line impedance Z₀ = 2P/I·I* for multi-conductor ports (TEM/QTEM). None for hollow-pipe modes where no inner-conductor current is available. z_modal() returns this value when set; otherwise falls back to z_wave(omega).

  • discrete_e_u_profile (np.ndarray or None, default None) – Numerical-path E_u profile, sampled at the port-plane u-edge midpoints. Shape (N_u,). M_ε-orthonormal by construction.

  • discrete_e_v_profile (np.ndarray or None, default None) – Numerical-path E_v profile, shape (N_v,).

  • discrete_h_u_profile (np.ndarray or None, default None) – Numerical-path H_u profile co-located with v-edges, shape (N_v,).

  • discrete_h_v_profile (np.ndarray or None, default None) – Numerical-path H_v profile co-located with u-edges, shape (N_u,).

Notes

The Phase-1 architecture assumes a homogeneously filled cross- section (single epsilon_r). Phase 2 (QTEM) will extend this to a frequency-dependent effective permittivity.

gamma(omega)#

Propagation constant γ = α + jβ at angular frequency omega.

Above cut-off, the mode is propagating and γ = j β. Below cut-off it is evanescent and γ = α (real).

Parameters:

omega (float) – Angular frequency [rad/s].

Return type:

complex

z_modal(omega)#

Reference impedance for power-wave decomposition.

For multi-conductor modes (TEM/QTEM with z_line set), returns the line impedance Z₀ = 2P/I·I*. For hollow-pipe modes, falls back to z_wave(omega).

This is the impedance to use in V_m^± = (V_m ± Z_modal · I_m) / 2 for the modal-load absorption update.

Parameters:

omega (float) – Angular frequency [rad/s].

Return type:

complex

z_wave(omega)#

Modal wave impedance at angular frequency omega.

  • TEM: Z = η₀ / √ε_r (frequency-independent).

  • TE: Z = j ω μ / γ (real positive above cut-off, reactive below).

  • TM: Z = γ / (j ω ε) (real positive above cut-off, reactive below).

Parameters:

omega (float) – Angular frequency [rad/s]. Must be > 0.

Return type:

complex

class magnelio.ports.ModeReport(port_name, name, mode_type, f_cutoff, z_line, _discrete, _plane, _mirrors=(), _h_dual_lengths=(), epsilon_eff=None, termination=None, chain_spread=None)#

One solved port mode, inspectable without a TD run.

Parameters:
  • port_name (str)

  • name (str)

  • mode_type (ModeType)

  • f_cutoff (float)

  • z_line (float | None)

  • _discrete (DiscreteMode)

  • _plane (PortPlane)

  • _mirrors (tuple)

  • _h_dual_lengths (tuple)

  • epsilon_eff (float | None)

  • termination (str | None)

  • chain_spread (float | None)

port_name#

Label of the port the mode belongs to.

Type:

str

name#

Mode identifier from the 2D solver (e.g. "TE10", "TEM_lap00").

Type:

str

mode_type#

TEM / TE / TM classification.

Type:

ModeType

f_cutoff#

Cut-off frequency [Hz]; 0.0 for TEM modes.

Type:

float

z_line#

Frequency-independent line impedance Z₀ = 2P/(I·I*) for multi-conductor (TEM/QTEM) modes; None for hollow-pipe modes, whose reference impedance is the frequency-dependent wave impedance (use z_modal()).

Type:

float or None

epsilon_eff#

Effective relative permittivity of a line mode — the ε_eff of a quasi-TEM mode (C'/C'_0, one value per mode of a coupled line: even and odd travel at different speeds), the filling ε_r of a homogeneous TEM mode; None for hollow-pipe modes. The phase velocity is c / √ε_eff.

Type:

float or None

termination#

How the channel closes the domain at the port plane. 'dtbc' is the exact discrete transparent boundary condition, reflection-free to roundoff; 'mur' is the first-order absorber, a reflection floor of order −30 dB. A channel qualifies for the exact one when the feed cross-section is a uniform discrete chain; chain_spread is that measurement. None where the port reports no per-channel termination (lumped ports carry no modes at all).

Type:

{‘dtbc’, ‘mur’} or None

chain_spread#

Weighted RMS spread of the per-pair modal Courant number over the feed cross-section — 0 on a perfectly uniform chain, and the quantity chain_floor_db turns into a reflection. A value just above the acceptance threshold means a cross-section that was meant to be uniform and was not, and warns; a large one is an inhomogeneous line that never qualified for the scalar chain. None when the test does not apply: a mode with a closed-form field evaluator is ineligible by construction, and so is every channel of a port whose feed masses fail the slab consistency check upstream (both warn on their own).

Type:

float or None

gamma(f)#

Propagation constant γ = α + jβ at frequency f [Hz].

Parameters:

f (float)

Return type:

complex

plot(*, field='E', ax=None, density=20, normalize_arrows=True, threshold=0.0, flip=False, scale_mm=True, title=None, geometry=None)#

Quiver plot of the transverse mode profile on the port plane.

The discrete edge profiles (the B-orthonormal basis vectors the FIT operator actually injects and projects with) are averaged from their staggered edge positions onto the port-plane cell centres and rendered via plot_field_vector().

Parameters:
  • field ({"E", "H"}, default "E") – Which transverse field profile to draw.

  • ax (matplotlib.axes.Axes, optional) – Target axes; a new figure is created when omitted.

  • density (int, default 20) – Number of arrows along the longer axis of the cross-section; the shorter one gets the count that keeps the spacing equal. The raster is deliberately independent of the computational grid, so a locally refined region does not show up as a cluster of arrows — but it also does not gain any. Raise this to read a feature that the default spacing steps over, such as the field in a thin gap.

  • normalize_arrows (bool, default True) – Unit-length arrows with magnitude encoded in colour (port-mode style).

  • threshold (float, default 0.0) – Suppress arrows below this fraction of the peak magnitude.

  • flip (bool, default False) – Swap the horizontal and vertical plot axes.

  • scale_mm (bool, default True) – Axis coordinates in mm instead of m.

  • title (str, optional) – Axes title; default names port, mode, and field.

  • geometry (GeometryModel, optional) – Geometry model for a cross-section overlay of the port plane (conductors filled, air regions as dashed outlines).

Returns:

  • fig (matplotlib.figure.Figure)

  • ax (matplotlib.axes.Axes)

Return type:

tuple[‘matplotlib.figure.Figure’, ‘matplotlib.axes.Axes’]

z_modal(f)#

Power-wave reference impedance at frequency f [Hz].

Parameters:

f (float)

Return type:

complex

z_wave(f)#

Modal wave impedance at frequency f [Hz].

Parameters:

f (float)

Return type:

complex

property chain_floor_db: float | None#

Reflection the feed cross-section’s non-uniformity can cost [dB].

An upper bound, not an estimate. The exact termination is built for the weighted-mean chain, so a spread across the cross-section leaves a residual mismatch; measured through the production chain, the worst case rises linearly with the spread at about a seventh of it, and this bound takes the coefficient as one. A channel terminated by the exact boundary contributes at most this much reflection on top of whatever else limits it — compare it against the floor the port itself reaches.

None where no spread was measured (see chain_spread), and None on a channel the first-order absorber terminates: there the floor is set by the absorber, not by the cross-section, and the spread only explains why the exact boundary was withheld. Read chain_spread in that case.

class magnelio.ports.ModeType(value)#

Mode classification for homogeneously-filled waveguides.

class magnelio.ports.PortAnalytical(name, plane, family='coax', inner_radius=None, outer_radius=None, width=None, height=None, epsilon_r=1.0, center=(0.0, 0.0, 0.0), n_modes=1)#

Declarative port with a closed-form analytical reference mode.

Parameters:
  • name (str) – Unique port name.

  • plane (BoxFace or str) – Bbox face the port lives on.

  • family ({"coax", "rect_wg"}) – Which analytical family describes the cross-section.

  • inner_radius (float, optional) – Coax conductor radii [m] (required for family="coax").

  • outer_radius (float, optional) – Coax conductor radii [m] (required for family="coax").

  • width (float, optional) – Rectangular-waveguide cross-section [m] (required for family="rect_wg"); width is the (usually broader) dimension along the lower-numbered global tangential axis.

  • height (float, optional) – Rectangular-waveguide cross-section [m] (required for family="rect_wg"); width is the (usually broader) dimension along the lower-numbered global tangential axis.

  • epsilon_r (float, default 1.0) – Relative permittivity of the (homogeneous) filling.

  • center (tuple of float, default (0.0, 0.0, 0.0)) – Cross-section anchor as an (x, y, z) world-coordinate point [m] — the coax axis, or the lower-left corner of the rectangle. The component along the face’s normal axis is fixed by plane already and is ignored (None is fine there).

  • n_modes (int, default 1) – Number of modes.

class magnelio.ports.PortDispersionReport(port_name, f_axis, z_line, epsilon_eff, gamma)#

Frequency dependence of a port’s modes on the grid.

Returned by PortReport.dispersion(). Every array is indexed [mode, frequency] in the port’s mode order; a mode that does not propagate at a frequency (below its cut-on) is NaN there. The values are those of the true discrete modes of the feed cross-section — the modes the grid actually carries, solved per frequency — not the frequency-flat mode the port’s report lists.

Parameters:
port_name#
Type:

str

f_axis#

Frequencies [Hz].

Type:

np.ndarray

z_line#

Reference impedance [Ω] the mode carries at each frequency, full-model value on a port cut by a symmetry plane: the line impedance of a TEM or quasi-TEM mode, the modal impedance of a hollow-pipe mode in the port’s V/I convention.

Type:

np.ndarray

epsilon_eff#

Effective permittivity (β c / ω)² with the grid’s own dispersion divided out — comparable with the closed-form ε_eff(f) of the microstrip literature.

Type:

np.ndarray

gamma#

Propagation constant α + jβ [1/m], complex.

Type:

np.ndarray

plot(ax=None, *, mode=None)#

Line impedance and effective permittivity against frequency.

Parameters:
  • ax (matplotlib Axes, optional) – Axes for the impedance; ε_eff goes on a twin axis.

  • mode (int, optional) – One mode; default all.

Returns:

The matplotlib figure and the impedance axes.

Return type:

tuple

summary()#

Multi-line summary at the first, middle and last frequency.

Return type:

str

property alpha: ndarray#

Attenuation constant [Np/m] — zero to roundoff on a lossless feed.

property beta: ndarray#

Phase constant [rad/m].

class magnelio.ports.PortLumped(name, start=None, end=None, Z0=50.0, element=None, path=None, samples_per_cell=4)#

Declarative lumped port on an interior path.

The high-level spelling of the lumped Thévenin port: a path through the model and a reference impedance, optionally backed by an RLC companion element. Resolved into a PortSpecLumped by the analysis.

Parameters:
  • name (str) – Unique port name.

  • start (tuple of float, optional) –

    Endpoints in metres — the two-point short form of path, and exclusive with it. Under a clipping symmetry declaration they stay in full-model coordinates: a port crossing an electric symmetry plane is clipped to the meshed half automatically.

    The port’s polarity follows start → end; the recorded V and I change sign with it.

  • end (tuple of float, optional) –

    Endpoints in metres — the two-point short form of path, and exclusive with it. Under a clipping symmetry declaration they stay in full-model coordinates: a port crossing an electric symmetry plane is clipped to the meshed half automatically.

    The port’s polarity follows start → end; the recorded V and I change sign with it.

  • path (Curve or sequence of points, optional) – The port’s path: a Curve, or a sequence of at least two (x, y, z) points [m] read as polyline vertices. Any direction is allowed — an oblique path is carried by a staircase of grid edges, which costs a little excess series inductance (see the lumped-elements guide). The path must not visit a grid edge twice: a two-terminal element is a series chain, so a self-crossing or doubled-back path is rejected.

  • samples_per_cell (int, default 4) – Path samples per smallest cell while rasterising.

  • Z0 (float, default 50.0) – Power-wave reference impedance [Ω]; without element also the internal Thévenin impedance. Always the full-model value: under symmetry the solver internally halves or doubles it, and every reported quantity stays full-model.

  • element (SeriesRLC or ParallelRLC, optional) – Companion element replacing the pure resistor as the port’s internal impedance. Also declared with full-model values.

class magnelio.ports.PortOperatorReport(z_line_num: 'Optional[float]' = None, z_line_ref: 'Optional[float]' = None, cutoff_num: 'Optional[float]' = None, cutoff_ref: 'Optional[float]' = None, symmetry_faces: 'tuple' = (), quasi_static: 'bool' = False)#
Parameters:
  • z_line_num (float | None)

  • z_line_ref (float | None)

  • cutoff_num (float | None)

  • cutoff_ref (float | None)

  • symmetry_faces (tuple)

  • quasi_static (bool)

property power_wave_full_scale: float#

Half-window → full-model scale for modal wave amplitudes.

The port modes are power-normalised on the half window, so a recorded amplitude of 1 √W accounts for the power crossing the meshed half only; the mirror half carries the same power again. Each cutting symmetry plane therefore scales the full-model wave amplitude by √2 (and the excitation by 1/√2 so that a declared injected power is a full-model watt).

property z_line_full_scale: float#

Half-window → full-model scale for the line impedance.

Each cutting magnetic symmetry plane halves the window and its capacitance, so the two halves sit in parallel (z_full = z_half / 2); an electric symmetry plane puts them in series (z_full = 2 · z_half).

class magnelio.ports.PortRefinementReport(port_name, target, mode, levels, tol, converged, extrapolated=None, order=None, reports=())#

Convergence of one port’s mode parameter under port-plane refinement.

Parameters:
  • port_name (str)

  • target (str)

  • mode (int)

  • levels (tuple[RefinementLevel, ...])

  • tol (float)

  • converged (bool)

  • extrapolated (float | None)

  • order (float | None)

  • reports (tuple)

port_name#
Type:

str

target#

"z_line", "epsilon_eff" or "f_cutoff" of mode mode – the resolved quantity, also when "auto" was asked for.

Type:

str

mode#
Type:

int

levels#

The ladder, level 0 first.

Type:

tuple of RefinementLevel

tol#

The relative change the ladder was asked to reach.

Type:

float

converged#

Whether the last change fell below tol before the level cap.

Type:

bool

extrapolated#

Richardson estimate from the last two levels (None with a single level).

Type:

float or None

order#

Observed convergence order from the last three levels (None with fewer).

Type:

float or None

reports#

The port report of every level, for the modes themselves.

Type:

tuple of PortReport

property estimated_error: float#

Conservative relative error of value — the last rung’s change.

property value: float#

the extrapolated value, else the finest level’s.

Type:

Best estimate

class magnelio.ports.PortReport(name, modes, report=None, _dispersion_factory=None, _dispersion_cache=<factory>)#

Per-port mode-solution report (no TD run required).

Parameters:
name#

Port label.

Type:

str

modes#

One entry per solved mode, in cut-off-ascending solver order (the same indexing as excited=[(port, mode_idx)]). Empty for lumped ports.

Type:

tuple[ModeReport, …]

report#

The two-path scalar summary attached by build_modal_port(); exposes z_line_num / z_line_ref / cutoff_num / cutoff_ref. For lumped ports a synthetic report carrying z_line_num = Z0.

Type:

PortOperatorReport or None

classmethod from_operator(op, mesh=None, *, dispersion_factory=None)#

Build a report from a built port operator.

Modal operators contribute one ModeReport per discrete_modes entry; lumped operators (no mode solve) yield an empty mode tuple and a synthetic PortOperatorReport with z_line_num = Z0.

Passing the mesh lets the mode plots resolve the symmetry planes cutting the port window, so they show the full cross-section instead of the solved half; without it they show the solved window. dispersion_factory — a callable returning the port’s dispersion record — enables dispersion().

Return type:

PortReport

dispersion(f_axis)#

Impedance, ε_eff and γ of the port’s modes per frequency.

Solves the true discrete modes of the feed cross-section at every point of f_axis — the modes the grid carries there, as opposed to the single frequency-flat mode the port operates with — and returns what each carries: its impedance, its effective permittivity and its propagation constant. On a quasi-TEM line these move with frequency (the impedance of the tutorial microstrip rises by 7 % over its band); on a homogeneous line they are flat, and the impedance is the exact discrete value the port’s power waves already use.

The mode order is the port’s. A mode below its cut-on at a frequency is NaN there.

Parameters:

f_axis (array_like) – Frequencies [Hz].

Return type:

PortDispersionReport

Raises:

ValueError – On a lumped port, or when the feed behind the port plane is not a uniform chain (fewer than four equidistant cells, a taper or step too close to the port).

summary()#

Multi-line human-readable summary (used by str()).

Return type:

str

class magnelio.ports.PortSpecCoax(name, plane, inner_radius, outer_radius, epsilon_r=1.0, center=(0.0, 0.0), n_modes=1)#

Coaxial-line modal port (TEM, Phase 1).

Parameters:
  • name (str) – Port label, used by the recorder and S-parameter post-processing.

  • plane (BoxFace) – Bbox face on which the port lives.

  • inner_radius (float) – Inner and outer conductor radii [m].

  • outer_radius (float) – Inner and outer conductor radii [m].

  • epsilon_r (float, default 1.0) – Relative permittivity of the dielectric.

  • center (tuple[float, float], default (0.0, 0.0)) – Coax-axis location in the global tangential frame (lower-axis first). See module docstring for the convention.

  • n_modes (int, default 1) – Phase 1 supports only n_modes = 1 (TEM).

class magnelio.ports.PortSpecLumped(name, start=None, end=None, Z0=50.0, element=None, path=None, samples_per_cell=4)#

Declarative description of a lumped discrete port / RLC element.

Parameters:
  • name (str) – Unique port identifier (used as recorder channel key).

  • start (tuple[float, float, float], optional) – Endpoints in metres — the two-point short form of path. Exclusive with it; exactly one of the two forms is required. Under a clipping symmetry declaration they stay in full-model coordinates; Z0 / element are full-model values throughout, and the builder derives the internally scaled half-model device.

  • end (tuple[float, float, float], optional) – Endpoints in metres — the two-point short form of path. Exclusive with it; exactly one of the two forms is required. Under a clipping symmetry declaration they stay in full-model coordinates; Z0 / element are full-model values throughout, and the builder derives the internally scaled half-model device.

  • path (Curve or sequence of points, optional) – The port’s path through the model: a Curve or a sequence of at least two (x, y, z) points [m] taken as polyline vertices. It may run in any direction; the rasterised staircase carries an oblique path. The chain must not visit an edge twice, so a self-crossing or doubled-back path is rejected — a two-terminal element is a series chain.

  • samples_per_cell (int, default 4) – Path samples per smallest cell while rasterising. Higher values only refine which edges a strongly curved path picks up.

  • Z0 (float) – Power-wave reference impedance [Ω] (default 50 Ω). Without an element it is also the internal Thévenin impedance — the classic discrete port.

  • element (SeriesRLC or ParallelRLC, optional) – Trapezoidal companion element replacing the pure resistor as the port’s internal impedance: an excited port becomes an RLC-backed source, an unexcited one a passive lumped RLC load. None (default) means SeriesRLC(R=Z0) — the behaviour-identical classic port. The element instance is deep-copied per run, so its transient state never leaks between excitations.

class magnelio.ports.PortSpecMultiConductor(name, plane, conductors=None, epsilon_r=None, n_modes=1, window=None)#

Multi-conductor numerical port spec (Phase 2b/c factory cleanup).

Drives the TEM Laplace path (solve_tem_laplace(), when epsilon_r is set) or the QTEM dual-Laplace path (solve_qtem_laplace(), when epsilon_r is None — the factory builds the vacuum reference mass via build_M_eps_vacuum()). Returns the K − 1 line modes (K conductor groups): the single conductor mode for K = 2, the modal basis of the line for K > 2 — the capacitance-matrix eigenmodes (TEM) or the eigen-patterns of C v = ε_eff C_0 v (QTEM), e.g. the even/odd pair of coupled lines, ordered by descending capacitance / ε_eff.

Unified multi-mode port (WP-U2/WP-U6). On a homogeneous scalar filling (epsilon_r set), n_modes > K − 1 extends the port by the lowest TE/TM curl-curl modes of the same cross-section, merged by ascending cut-off (TEM channels first, f_c = 0) — the exact continuum decomposition TEM ⊕ TE ⊕ TM; the discrete family cross-orthogonality is at solver tolerance (WP-U1). On an inhomogeneous cross-section (epsilon_r=None, QTEM) no exact family split exists — the higher channels are the true hybrid eigenpairs of the ζ-pencil at f_calc: profiles exact at f_calc, dual-basis projections (the hybrids are not M_ε-orthogonal), termination per the standard defaults (certificates fail on inhomogeneous fillings → modal Mur-1st, loud notice; port_model="band" stays the reflection-critical opt-in for the tracked family). Mode labels stay family-explicit (TEM_lap00, TE_num00, QTEM_lap00, HYB_zp00, …).

Parameters:
  • name (str) – Port label.

  • plane (BoxFace) – Bbox face on which the port lives.

  • conductors (tuple[ConductorSpec, ...] or None, default None) – [ground, signal_1, signal_2, ...] — at least 2 entries when given. conductors[0] is the gauge reference (φ = 0); each subsequent entry spawns one TEM/QTEM mode in input order. When None, the conductor groups are auto-derived from the mesh PEC mask on the port plane via extract_conductor_groups_from_mesh() — useful for OCC geometries (cylinders, arbitrary curved cross-sections) where the declarative ConductorSpec list is awkward.

  • epsilon_r (float or None, default None) – Homogeneous-filling permittivity for the TEM path. If None, the QTEM dispatch is selected: the factory constructs the vacuum-reference mass matrix (build_M_eps_vacuum()) so the dual-Laplace solver can extract ε_eff = C' / C'_0.

  • n_modes (int, default 1) – Number of returned modes. Up to K − 1 these are the TEM (or QTEM) line modes; beyond that the port is extended by TE/TM curl-curl modes (homogeneous filling) or ζ-pencil hybrid modes (inhomogeneous filling) — see the class docstring. The QTEM extension requires the requested modes to propagate at f_calc and raises with guidance otherwise.

  • window (tuple of two corner points, optional) – Sub-rectangle of the face as two opposite corners in global tangential-axis ordering (PortPlane.from_mesh() convention). None (default) covers the whole face. A PEC window boundary (via the legacy edge rule) joins the conductor-group graph as a boundary ring, so it can act as the ground conductor of an embedded port.

Notes

Conductor groups are auto-deduplicated in input order: nodes that belong to an earlier group are removed from later groups. This matches the “ground first wins” semantic — a node on the ground plane is at φ = 0 even if a signal conductor’s region spec nominally covers it.

class magnelio.ports.PortSpecNumerical(name, plane, n_modes=1, epsilon_r=1.0, mode_type=None, window=None)#

Numerical-mode-solver port for hollow homogeneously-filled cross-sections.

Drives the numerical 2D curl-curl / node-Laplace eigenvalue solver (Numerical2DModeSolver) for hollow waveguides whose cross-section has no analytical closed form (ridged, double-ridged, elliptical, circular with PEC bbox padding, …) or where a FIT-grid-native mode is preferred over an analytical projection.

Scope: TE/TM modes on a hollow, homogeneously-filled cross-section. Multi-conductor TEM and inhomogeneous QTEM are served by PortSpecMultiConductor.

PEC walls are read from mesh.pec_mask_edges — the canonical 3D-mesh source. Production setups define the wall geometry via Mesh.from_geometry() (OCC-meshed PEC body) or Mesh.with_pec_boundaries() (BC-consolidated bbox faces); both populate mesh.pec_mask_edges automatically. For bare Mesh.from_grid setups without either, the factory falls back to the standard hollow-waveguide assumption (all four lateral bbox faces are PEC walls).

Parameters:
  • name (str) – Port label.

  • plane (BoxFace) – Bbox face on which the port lives.

  • n_modes (int, default 1) – Number of modes returned by the eigsh solver, ordered by ascending cut-off frequency.

  • epsilon_r (float, default 1.0) – Permittivity of the (homogeneous) cross-section filling. Used for the H-profile bake-in and the sigma heuristic.

  • mode_type (ModeType or None, default None) – None (default) solves both TE and TM families and keeps the n_modes lowest cut-offs, mixed types included — one operator injects/records/terminates every mode on the face (unified multi-mode port, WP-R3). Pass ModeType.TE or ModeType.TM to restrict to one family.

  • window (tuple of two corner points, optional) – Sub-rectangle of the face as two opposite corners in global tangential-axis ordering (PortPlane.from_mesh() convention). None (default) covers the whole face. The window-boundary BCs follow the legacy edge rule: a port edge on a domain boundary inherits that wall’s BC, an interior edge inherits the port face’s BC (both read from mesh.pec_mask_edges).

class magnelio.ports.PortSpecRectWG(name, plane, width_a, height_b, epsilon_r=1.0, center=(0.0, 0.0), n_modes=1)#

Rectangular-waveguide modal port (TE / TM, Phase 1).

Parameters:
  • name (str) – Port label.

  • plane (BoxFace) – Bbox face on which the port lives.

  • width_a (float) – Cross-section dimension along the lower-numbered tangential global axis [m].

  • height_b (float) – Cross-section dimension along the higher-numbered tangential global axis [m].

  • epsilon_r (float, default 1.0) – Relative permittivity.

  • center (tuple[float, float], default (0.0, 0.0)) – Lower-left corner of the cross-section in the global tangential frame (lower-axis first).

  • n_modes (int, default 1) – Number of modes returned by the analytical solver, ordered by ascending cutoff frequency.

class magnelio.ports.PortWaveguide(name, plane, corners=None, n_modes=1)#

Generic declarative waveguide port: “solve whatever is on this face”.

The mode-solver path (TEM / QTEM / TE-TM) is selected from the mesh cross-section at analysis-construction time — see the module docstring for the rules.

Parameters:
  • name (str) – Unique port name.

  • plane (BoxFace or str) – Bbox face the port lives on ("zmin", BoxFace.Z_MIN, …).

  • corners (tuple of tuple, optional) –

    Sub-rectangle of the face, given as two opposite corners ((x0, y0, z0), (x1, y1, z1)) in world coordinates [m] — the same form as from_corners(). Corner order does not matter. The component along the face’s normal axis is fixed by plane already; write it as None (or repeat the same value on both corners — differing values are rejected as a likely axis mix-up). An oversized rectangle is clipped to the domain and snapped to the nearest grid nodes, and a tangential component may be None to reach the domain boundary on that side. The window-boundary BCs follow the legacy edge rule: an edge on a domain boundary inherits that wall’s BC, an interior edge inherits the port face’s BC — so a port embedded in a PEC wall gets a PEC frame, which also counts as a conductor (ground) in the mode-path detection. None (default) covers the whole face.

    On an absorbing (CPML) face a port is the end of a conductor-enclosed guide reaching the wall — the neck of a horn, a coax entering the box: the window is required and must be enclosed by conductor on the port slab (align its corners with the guide’s inner walls), and the absorber is switched off in the columns behind it so the port’s own termination is what the guided wave meets. A whole-face port on an absorbing face, or a window whose ring lies in free space, is rejected.

  • n_modes (int, default 1) – Number of modes to solve on the port.

class magnelio.ports.RefinementLevel(level, n_cells_port_plane, n_cells_3d, value, rel_change)#

One rung of the refinement ladder.

Parameters:
  • level (int)

  • n_cells_port_plane (int)

  • n_cells_3d (int)

  • value (float)

  • rel_change (float)

level#

0 is the user’s port-plane grid; level k bisects it k times along both tangential axes.

Type:

int

n_cells_port_plane#

Cross-section cell count on the port plane.

Type:

int

n_cells_3d#

Cell count of the slab mesh.

Type:

int

value#

The target quantity at this level (full-model value).

Type:

float

rel_change#

|value − value_prev| / |value|; nan at level 0.

Type:

float

class magnelio.ports.RegionConductor(axis_a_range, axis_b_range)#

Axis-aligned rectangular conductor region on the port plane.

The two ranges are given in the global axis ordering — the same convention as PortSpecCoax.center and PortSpecRectWG.width_a. Concretely:

  • X-face port (u/v axes are y, z): (y_range, z_range).

  • Y-face port (u/v axes are x, z): (x_range, z_range).

  • Z-face port (u/v axes are x, y): (x_range, y_range).

The factory swaps the pair internally on MAX faces so the user description does not depend on whether the port is MIN or MAX.

Primal 2D nodes whose physical (u, v) coordinate falls inside [range_a_lo, range_a_hi] × [range_b_lo, range_b_hi] (with a small tolerance relative to the port-plane extent) are taken to belong to this conductor.

Typical uses: rectangular inner conductor of rect coax; the strip of a microstrip; a square bond pad.

Parameters:
  • axis_a_range (tuple[float, float])

  • axis_b_range (tuple[float, float])

class magnelio.ports.WallConductor(face)#

Single bbox-wall PEC conductor (e.g. microstrip ground plane).

face must be a bbox face whose normal axis is tangential to the port plane (a “lateral” face from the port plane’s perspective). All primal 2D nodes lying on that wall are taken to belong to this conductor. Mirrors the validation in _build_lateral_pec_edge_mask().

Parameters:

face (BoxFace)

magnelio.ports.refine_port_modes(model, control, mesh, port, *, levels=3, target='auto', mode=0, tol=0.001, slab_cells=6, verbose=None)#

Converge a port mode’s parameter by refining the port plane alone.

Builds a slab of the model behind the port face — the model’s shapes, materials and lateral closure, cut slab_cells of the user’s mesh in with the mesher’s own domain clip — and meshes it with the user’s mesh control at level 0 and every tangential cell split 2^k ways at level k. Level 0 reproduces the port report of mesh; the ladder converges the cross-section at 4× the cells per level instead of the 8× a 3D refinement costs, on a slab a few cells deep.

Parameters:
  • model (GeometryModel) – The model mesh was generated from, ports declared.

  • control (MeshControl) – The mesh control mesh was generated with; every level keeps it and sets its subdivide on the tangential axes.

  • mesh (Mesh) – The user’s mesh (supplies the level-0 grid, f_max and the port declaration).

  • port (str) – Name of a declared waveguide port.

  • levels (int, default 3) – Number of ladder rungs including level 0 (at most).

  • target ({"auto", "z_line", "epsilon_eff", "f_cutoff"}) – Quantity to converge. "auto" (default) follows the mode family: the line impedance of a TEM or quasi-TEM mode, the cut-off frequency of a TE or TM mode, which has no line impedance. The report names the quantity it converged.

  • mode (int, default 0) – Mode index on the port.

  • tol (float, default 1e-3) – Stop once the relative change between rungs falls below it.

  • slab_cells (int, default 6) – Depth of the slab in cells of the user’s mesh behind the port face (at least four: the port’s equidistant buffer).

  • verbose (bool, optional) – Report each level as it runs — the mesh build and port solve of the rung in progress, then its converged value. None (the default) follows magnelio.set_verbosity().

Return type:

PortRefinementReport

Raises:

ValueError – If the port is not declared on the mesh, the model declares a symmetry plane on the port’s axis, or the target is not defined for the mode.