# Ex4: Passivity Evaluation and Enforcement¶

To demonstrate the passivity evaluation and enforcement features of the vector fitting class, the ring slot example 2-port is used, once again. Have a look at the other vector fitting example notebooks for more general explanations of the fitting process.

:

import skrf
import numpy as np
import matplotlib.pyplot as mplt

# load and fit the ring slot network with 3 poles
nw = skrf.data.ring_slot
vf = skrf.VectorFitting(nw)
vf.vector_fit(n_poles_real=3, n_poles_cmplx=0)

# plot fitting results
freqs = np.linspace(0, 200e9, 201)
fig, ax = mplt.subplots(2, 2)
fig.set_size_inches(12, 8)
vf.plot_s_mag(0, 0, freqs=freqs, ax=ax) # s11
vf.plot_s_mag(0, 1, freqs=freqs, ax=ax) # s12
vf.plot_s_mag(1, 0, freqs=freqs, ax=ax) # s21
vf.plot_s_mag(1, 1, freqs=freqs, ax=ax) # s22
fig.tight_layout()
mplt.show() The fitting result does not look too bad, but is the model still passive at all frequencies?

:

print(vf.is_passive())

False


It’s not passive? What’s going on? Was the original data of the ring slot representing a passive network?

:

print(nw.is_passive())

True


The network data was passive, but the vector fitted model is not. Let’s investigate (and correct?) the problem.

:

# plot singular values of vector fitted scattering matrix
freqs = np.linspace(0, 200e9, 201)
fig, ax = mplt.subplots(1, 1)
fig.set_size_inches(6, 4)
vf.plot_s_singular(freqs=freqs, ax=ax)
fig.tight_layout()
mplt.show() One of the singular values of the fitted scattering matrix is greater than 1 at some frequencies. This indeed indicates a non-passive model. For further analysis, you can get a list of all frequency bands with passivity violations:

:

print(vf.passivity_test())

[[0.00000000e+00 5.97242674e+09]
[8.43154893e+10 9.83151113e+10]]


The network is not passive in two frequency bands: From dc to about 6 GHz, and from 84.3 GHz to 98.3 GHz. Luckily, passivity can be enforced, if a passive vector fitted model is desired:

:

vf.passivity_enforce()


After passivity enforcement, the network should be passive at all frequencies. Let’s check ourselves:

:

print(vf.is_passive())

True

:

print(vf.passivity_test())

[]

:

# plot singular values of vector fitted scattering matrix
freqs = np.linspace(0, 200e9, 201)
fig, ax = mplt.subplots(1, 1)
fig.set_size_inches(6, 4)
vf.plot_s_singular(freqs=freqs, ax=ax)
fig.tight_layout()
mplt.show() Alright, the model is finally passive. But does it still fit the original network data?

:

# plot fitting results again after passivity enforcement
freqs = np.linspace(0, 200e9, 201)
fig, ax = mplt.subplots(2, 2)
fig.set_size_inches(12, 8)
vf.plot_s_mag(0, 0, freqs=freqs, ax=ax) # s11
vf.plot_s_mag(0, 1, freqs=freqs, ax=ax) # s12
vf.plot_s_mag(1, 0, freqs=freqs, ax=ax) # s21
vf.plot_s_mag(1, 1, freqs=freqs, ax=ax) # s22
fig.tight_layout()
mplt.show() Yes, the model still fits the original data very well and the differences to the first non-passive fit from above are insignificant.