Inductor S-parameters: vector fitted model vs. Touchstone data

load "resistor.osdi"
load "capacitor.osdi"

include "inductor.inc"

model vsrc vsource
model r resistor

x1 (p1 0 p2 0) inductor

vp1 (a1 0) vsrc dc=0
rp1 (a1 p1) r r=50

vp2 (a2 0) vsrc dc=0
rp2 (a2 p2) r r=50

control
  analysis sp1 acsp ports=["vp1", "rp1", "vp2", "rp2"] from=0 to=30G mode="lin" points=400

  postprocess(PYTHON, "runme.py")
endc

embed "runme.py" <<<FILE
import os
import numpy as np
import matplotlib.pyplot as plt
import skrf as rf
from rawfile import rawread

# The Touchstone file sits next to this netlist, not necessarily in the
# simulator's working directory, so locate it via SIM_PARENT_FILE_DIR.
s2pPath = os.path.join(os.environ.get("SIM_PARENT_FILE_DIR", "."), "inductor.s2p")
network = rf.Network(s2pPath)

plot = rawread('sp1.raw').get()
freqAcsp = np.real(plot['frequency'])/1e9
freqS2p = network.f/1e9

fig, axs = plt.subplots(2, 2, figsize=(10, 8), sharex=True)
fig.suptitle('Inductor S-parameters: acsp (lines) vs. Touchstone (dots)')

for ax, (i, j) in zip(axs.flat, [(1, 1), (1, 2), (2, 1), (2, 2)]):
    sAcsp = plot[f's({i},{j})']
    sTs = network.s[:, i - 1, j - 1]
    ax.plot(freqAcsp, 20*np.log10(np.abs(sAcsp)), '-', label='acsp')
    ax.plot(freqS2p, 20*np.log10(np.abs(sTs)), '.', label='s2p')
    ax.set_title(f'S{i}{j}')
    ax.set_xlabel('f [GHz]')
    ax.set_ylabel('Magnitude [dB]')
    ax.grid(True)
    ax.legend()

fig.tight_layout()
plt.show()
>>>FILE
