Network analysis¶
2-port network parameter conversions.
Mirrors the binary’s Y/Z/S conversion machinery
(y_to_z_2port_invert, y_to_s_2port_50ohm in
asitic_kernel.c). Where the original keeps the parameters in
flat global cells, we use 2×2 NumPy complex arrays.
All matrices are indexed [port_i, port_j] (so Y[0][1] is
Y_12). Reference impedance defaults to 50 Ω which matches
the binary’s hardcoded Y_0 = 0.02 = 1/50.
The Pi-equivalent representation models a planar inductor as a
series impedance Z_s between the two ports plus shunt
admittances Y_p1 and Y_p2 to ground:
port1 ─┬─[ Z_s ]─┬─ port2
│ │
Y_p1 Y_p2
│ │
GND GND
Conversion to Y:
Y[0][0] = 1/Z_s + Y_p1
Y[1][1] = 1/Z_s + Y_p2
Y[0][1] = Y[1][0] = -1/Z_s
This is the same Pi extraction emitted by the binary’s Pi /
Pi2 REPL commands (cmd_pi3_emit, analyze_narrow_band_2port).
- reasitic.network.twoport.y_to_z(Y)[source]¶
Invert a 2×2 admittance matrix to its impedance matrix.
\[\begin{split}Z = Y^{-1} = \frac{1}{\det Y} \begin{pmatrix} Y_{22} & -Y_{12} \\ -Y_{21} & Y_{11} \end{pmatrix}\end{split}\]Example
>>> import numpy as np >>> from reasitic.network import y_to_z >>> Y = np.diag([0.02 + 0j, 0.02 + 0j]) >>> Z = y_to_z(Y) >>> round(Z[0, 0].real) 50
- reasitic.network.twoport.y_to_s(Y, y0=0.02)[source]¶
Convert a 2-port Y matrix to a scattering matrix S.
Reference admittance
y0defaults to0.02(i.e. 50 Ω), matching the binary’s hardcoded reference. The closed form is:\[S = (I + Y/Y_0)^{-1} (I - Y/Y_0)\]
- reasitic.network.twoport.s_to_y(S, y0=0.02)[source]¶
Inverse of
y_to_s().\[Y = Y_0 (I - S)(I + S)^{-1}\]
- class reasitic.network.twoport.PiModel[source]¶
Bases:
objectPi-equivalent of a 2-port network at one frequency.
All quantities are complex except
freq_ghzwhich is real.Z_sis the series impedance between the ports (Ω);Y_p1andY_p2are shunt admittances to ground at ports 1 and 2 (S).
- reasitic.network.twoport.pi_equivalent(Y, freq_ghz)[source]¶
Extract the Pi-equivalent (Z_s, Y_p1, Y_p2) from a Y-matrix.
\[Z_s = -1/Y_{12}, \quad Y_{p1} = Y_{11} + Y_{12}, \quad Y_{p2} = Y_{22} + Y_{12}\]Two ports’ shunt admittance is whatever each diagonal element has in excess of the through term. This is the same extraction the binary performs in
extract_pi_equivalent(asitic_kernel.c:8945).
- reasitic.network.twoport.deembed_pad_open(Y_meas, Y_open)[source]¶
De-embed shunt pad capacitance from measured Y using an open-only structure.
Standard “open” de-embedding: the open structure’s Y captures the pad shunts; subtract from the measured Y.
\[Y_\text{DUT} = Y_\text{meas} - Y_\text{open}\]Both arguments must be 2×2. Returns the de-embedded Y matrix.
- reasitic.network.twoport.deembed_pad_open_short(Y_meas, Y_open, Y_short)[source]¶
Open-then-short de-embedding: removes pad shunts (open) and series losses in the test-structure access lines (short).
\[Y_\text{DUT} = \bigl[(Y_\text{meas} - Y_\text{open})^{-1} - (Y_\text{short} - Y_\text{open})^{-1} \bigr]^{-1}\]All three matrices must be 2×2. Returns the de-embedded Y.
- reasitic.network.twoport.z_2port_from_y(Y, *, differential=False, port=1)[source]¶
Convert a 2-port Y matrix to a single complex impedance.
Mirrors the binary’s
z_2port_from_y(decomp0x0804e8b0):- Single-ended (
differential=False): port == 1→Z = 1 / Y[1, 1](look into port 1 with port 2 short-circuited via Y inversion convention).port != 1→Z = 1 / Y[0, 0].
- Single-ended (
Differential (
differential=True) — the LC-mode impedance of a symmetric pair underY[0,1] == Y[1,0]:\[Z_d = (Y_{11} + Y_{22} + 2 Y_{21}) / (Y_{11} Y_{22} - Y_{21}^2)\]
The binary’s globals
Y22_re/imcorrespond toY[1, 1]andg_Y11_re/imtoY[0, 0]; the matrix layout convention is the standardY[i, j]indexing here.
- reasitic.network.twoport.imag_z_2port_from_y(Y, *, differential=False, port=1)[source]¶
Imaginary part of
z_2port_from_y().Mirrors the binary’s
imag_z_2port_from_y(decomp0x0804e7c0). Convenience wrapper that takes the imaginary component directly so callers extracting a reactance don’t need to remember the indexing convention.
- reasitic.network.twoport.zin_terminated_2port(Y, Y_load, *, port=1)[source]¶
Input impedance with the other port terminated in admittance
Y_load.Mirrors the binary’s
zin_terminated_2port(decomp0x0804e9b0). Implements the standard 2-port reduction identity:Y_in = Y_ii − Y_ij · Y_ji / (Y_jj + Y_load) Z_in = 1 / Y_in
Unlike
z_2port_from_y(), this routine readsY[0, 1]independently ofY[1, 0]— it does not assume reciprocity, matching the binary’s only function in this group that pulls the Y12 slot separately.
- reasitic.network.twoport.spiral_y_at_freq(shape, tech, freq_ghz, *, y_p1=None, y_p2=None, include_substrate=True, use_segment_cap=False, n_div=2)[source]¶
Build the 2-port Y matrix for
shapeatfreq_ghz.Default series leg is
Z_s = R + jωL; default shunts come from the parallel-plate-plus-fringe approximation inreasitic.substrate.shape_shunt_capacitance(). Settinguse_segment_cap=Trueswitches the shunt path to the per-segment Maxwell cap matrix reduced viareasitic.substrate.shape_pi_capacitances()— this routes throughanalyze_capacitance_driverand is closer to the binary’sanalyze_narrow_band_2port(asitic_kernel.c:1465) pipeline. The diagonal of the underlying P matrix now uses the analytical rectangular self-tile term, but the layered-stack reflection coefficient is still a quasi-static stub — see TODO.md §3 — so the segment-cap shunt magnitudes can disagree with physical intuition (e.g. metal-layer ordering) until the Sommerfeld pipeline is ported faithfully.- Parameters:
y_p2 (complex | None) – Explicit shunt admittances overriding the substrate solve.
include_substrate (bool) – When False, both shunts default to zero.
use_segment_cap (bool) – Opt-in to the segment-cap reduction.
n_div (int) – Per-segment subdivision forwarded to the cap solver.
shape (Shape)
tech (Tech)
freq_ghz (float)
y_p1 (complex | None)
y_p2
- Return type:
Substrate-loss conductance (the imaginary frequency-dependent term in the binary’s complex P matrix) is not modelled here.
3-port to 2-port network reduction.
Mirrors the binary’s reduce_3port_z_to_2port_y
(asitic_kernel.c:8652, address 0x080881a8):
The standard reduction is to invert the full 3×3 Z, then take the 2×2 sub-block of Y between the two retained ports. That is mathematically equivalent to grounding the third port (V₃ = 0) and solving for I₁, I₂ in terms of V₁, V₂.
We also provide z_to_s_3port() corresponding to
z_to_s_3port_50ohm (0x080884b8).
- reasitic.network.threeport.reduce_3port_z_to_2port_y(Z3, ground_port=2)[source]¶
Reduce a 3×3 Z matrix to a 2×2 Y by grounding
ground_port.Returns the 2×2 Y matrix between the two non-grounded ports (with the relative ordering preserved). The default
ground_port=2matches the binary’s behaviour of grounding port 3 (zero-indexed: port 2).
- reasitic.network.threeport.z_to_s_3port(Z3, z0_ohm=50.0)[source]¶
Convert a 3×3 Z matrix to a scattering matrix S₃.
\[S = (Z - Z_0 I)(Z + Z_0 I)^{-1}\]Mirrors
z_to_s_3port_50ohm(0x080884b8).
Touchstone v1 (.sNp) writer.
Touchstone is the de-facto interchange format for n-port network
parameters; supported by virtually every RF simulator (ADS, AWR,
Sonnet, HFSS, ngspice). The format spec (IBIS-Open Forum,
v1.1, 2002) defines a simple option line followed by one row per
frequency point:
# <freq_unit> <param_type> <fmt> R <ref_impedance>
<freq> <p11_a> <p11_b> <p12_a> <p12_b> ...
For 2-port files the entries within a row are ordered
S11 S21 S12 S22 (a Touchstone v1 quirk). For higher ports the
ordering is row-major S11 S12 ... S1N S21 ... with each port row
allowed to span multiple text lines (continued by leading whitespace).
The binary’s 2Port REPL command (case 528) prints the same data
in a different textual form; we choose Touchstone because it round-
trips through standard tools and is well documented.
- class reasitic.network.touchstone.TouchstonePoint[source]¶
Bases:
objectOne entry in a Touchstone sweep: frequency and the matrix at it.
- reasitic.network.touchstone.write_touchstone(points, *, param='S', fmt='MA', z0_ohm=50.0, freq_unit='GHz')[source]¶
Serialise a sequence of
TouchstonePointrows to a Touchstone string.paramis one of"S","Y","Z".fmtis"MA"/"DB"/"RI". Z₀ defaults to 50 Ω.For 2-port matrices the entry order within a row is
11 21 12 22per Touchstone v1 convention; higher-port files use row-major orderi1 i2 ... iNfor each i.
- reasitic.network.touchstone.write_touchstone_file(path, points, **kwargs)[source]¶
Write a Touchstone file.
kwargsare forwarded towrite_touchstone().- Parameters:
points (Iterable[TouchstonePoint])
kwargs (object)
- Return type:
None
- class reasitic.network.touchstone.TouchstoneFile[source]¶
Bases:
objectResult of parsing a Touchstone v1 file.
paramis one of"S"/"Y"/"Z".pointsis the list of per-frequency matrices.z0_ohmis the reference impedance (typically 50).n_portsis the matrix dimension.- points: list[TouchstonePoint]¶
- reasitic.network.touchstone.read_touchstone(text)[source]¶
Parse a Touchstone v1 string. Detects port count from line width.
- Parameters:
text (str)
- Return type:
- reasitic.network.touchstone.read_touchstone_file(path)[source]¶
Read and parse a Touchstone file from disk.
- Parameters:
- Return type:
Frequency-swept 2-port analysis.
Drives reasitic.network.spiral_y_at_freq() over a frequency
range and packages the per-frequency Y / Z / S / Pi results into a
NetworkSweep object that can be exported to Touchstone or
inspected programmatically. Mirrors the binary’s 2Port /
2PortX / 2PortGnd family of commands (case 528, 539, 529).
- class reasitic.network.sweep.NetworkSweep[source]¶
Bases:
objectA frequency sweep of 2-port parameters for a single shape.
- reasitic.network.sweep.two_port_sweep(shape, tech, freqs_ghz, *, z0_ohm=50.0)[source]¶
Compute Y / Z / S / Pi at every frequency in
freqs_ghz.z0_ohmis used for the S-parameter conversion (defaults to 50 Ω, matching the binary’s hardcoded reference).
- reasitic.network.sweep.linear_freqs(start_ghz, stop_ghz, step_ghz)[source]¶
Generate an inclusive linear frequency list (the binary’s stride).
High-level 2-port analysis: Pi-model emission, self-resonance, input impedance, eigen-frequency search.
These functions wrap the lower-level building blocks in
reasitic.network.twoport and the per-frequency
reasitic.network.spiral_y_at_freq() into the textual /
single-number outputs that the binary’s REPL commands return.
- class reasitic.network.analysis.PiResult[source]¶
Bases:
objectPi-equivalent broken out as physical L/R/C values at one frequency.
Mirrors the textual rows that the binary’s
Pi/Pi2commands print: an inductance, a series resistance, two shunt capacitances. The conversion from Y/Z to (L, R, C) follows the standard inductor model: at the operating frequency,\[Z_s = R + j\omega L, \quad Y_p = j\omega C + g_p\]where
g_pis the substrate-loss conductance (zero for our lossless-substrate stub).
- reasitic.network.analysis.pi_model_at_freq(shape, tech, freq_ghz)[source]¶
Build the Pi-equivalent of
shapeatfreq_ghzand break out the Z_s / Y_p values into physical L, R, C, g.Mirrors the binary’s
cmd_pi_emitandextract_pi_lumped_3port(asitic_kernel.c:8945/0x080897e4).
- reasitic.network.analysis.zin_terminated(shape, tech, freq_ghz, *, z_load_ohm=50 + 0j)[source]¶
Input impedance at port 1 with port 2 terminated by
z_load.\[Z_{\text{in}} = Z_{11} - \frac{Z_{12} \cdot Z_{21}} {Z_{22} + Z_L}\]Mirrors
zin_terminated_2port(asitic_kernel.c:0x0804e9b0).
- class reasitic.network.analysis.Pi3Result[source]¶
Bases:
object3-port Pi-model with one ground spiral.
ASITIC’s Pi3 model (case 517) breaks a spiral + a separate ground spiral into a 3-port network. Ports 1, 2 are the inductor terminals; port 3 is a ground reference. The model captures the substrate-coupled paths from each terminal to the ground spiral.
- class reasitic.network.analysis.Pi4Result[source]¶
Bases:
object4-port Pi-model with two pads (case 518).
Inductor + bond-pad on each port, sharing a substrate ground. Captures: series inductance + resistance, two pad capacitances to ground, two substrate resistances.
- __init__(freq_ghz, L_series_nH, R_series_ohm, C_pad1_fF, C_pad2_fF, C_sub1_fF, C_sub2_fF, R_sub1_ohm, R_sub2_ohm)¶
- reasitic.network.analysis.pi3_model(shape, tech, freq_ghz, *, ground_shape=None)[source]¶
Compute a 3-port Pi-model for
shapewithground_shape.Ports the simpler case of
cmd_pi3_emit(asitic_repl.c:0x08050b2c) where ground_shape is None: the substrate stub provides each port’s coupling to ground via a capacitor and a substrate-loss resistance (the latter is zero in our lossless-substrate stub).When
ground_shapeis provided the symmetric case is handled by computing M(shape, ground_shape) as part of the series leg.
- reasitic.network.analysis.pi4_model(shape, tech, freq_ghz, *, pad1=None, pad2=None)[source]¶
4-port Pi-model with bond-pad capacitors on each port.
Mirrors
cmd_pi4_emit(asitic_repl.c:0x08050d10). The pad shunts add to each port’s substrate path. Pads are typically a single MIM-capacitor block; their substrate cap fromshape_shunt_capacitance()is added to the spiral’s own port shunt cap.
- class reasitic.network.analysis.PixResult[source]¶
Bases:
objectExtended Pi-X model with substrate-loss conductance broken out.
The standard
PiResultlumps the substrate path into a singleY_padmittance. PiX expresses it as a seriesR_subto aC_subto ground, which better matches the physical substrate network:port ─┬─[ R_sub ]─[ C_sub ]─ gnd │ (no direct cap to ground)The decomposition is
Y_p = jωC_sub / (1 + jωR_sub C_sub); we extract C_sub from|Y_p|at low frequencies and use the remainder as the R_sub estimate.
- reasitic.network.analysis.pix_model(shape, tech, freq_ghz)[source]¶
Extended Pi-X equivalent (case 538,
PiX).Mirrors
cmd_pix_emit(asitic_repl.c:0x080527a4). Splits the substrate-cap shunt into a series R-C network for SPICE-style substrate models.
- reasitic.network.analysis.shunt_resistance(shape, tech, freq_ghz, *, differential=False)[source]¶
Parallel-equivalent resistance of a series RL circuit.
Mirrors
cmd_shuntr_compute(asitic_repl.c:0x0804e354). For a seriesR_s + jωLthe equivalent parallel resistance is \(R_p = R_s (1 + Q^2)\). In differential mode the equivalent is the series across both arms, which doublesR_sandLfor symmetric structures.- Inputs:
shape: target spiral.tech: technology stack.freq_ghz: operating frequency.differential:Truefor theS-mode (single-ended) orD-mode in the binary’s command parsing.
- Parameters:
- Return type:
- class reasitic.network.analysis.TransformerAnalysis[source]¶
Bases:
objectOutput of the
CalcTranscommand.
- reasitic.network.analysis.calc_transformer(primary, secondary, tech, freq_ghz)[source]¶
Analyse a transformer at one frequency.
Mirrors
cmd_calctrans_emit(asitic_repl.c:0x08051280). Computes per-coil L and R, the cross-mutual M, the coupling coefficient k = M / sqrt(L₁·L₂), the ideal turns ratio n = sqrt(L₁ / L₂), and the per-coil Q.- Parameters:
- Return type:
- reasitic.network.analysis.self_resonance(shape, tech, *, f_low_ghz=0.1, f_high_ghz=50.0, n_steps=200)[source]¶
Find the lowest frequency at which Im(Z₁₁) changes sign.
Below the self-resonance Z₁₁ is inductive (positive imag); at resonance it goes through zero and turns capacitive. We use a coarse linear scan + bisection refinement.
Mirrors
cmd_selfres_compute(asitic_repl.c:0x0804e590). Note: this requires non-zero shunt capacitance; on the lossless- substrate stub the spiral has Y_p = 0 and Z₁₁ = ∞, so self-resonance is undefined. Use a substrate model that yields realistic shunt caps before calling.