Passivity: Test, Visualize, and Enforce Passivity of Rational Fit Output

This example shows how to test, visualize, and enforce the passivity of output from the `rationalfit` function.

S-Parameter Data Passivity

Time-domain analysis and simulation depends critically on being able to convert frequency-domain S-parameter data into causal, stable, and passive time-domain representations. Because the `rationalfit` function guarantees that all poles are in the left half plane,` rationalfit` output is both stable and causal by construction. The problem is passivity.

N-port S-parameter data represents a frequency-dependent transfer function H(f). You can create an S-parameters object in RF Toolbox™ by reading a Touchstone® file, such as `passive.s2p`, into the `sparameters` function.

You can use the` ispassive` function to check the passivity of the S-parameter data, and the `passivity` function to plot the 2-norm of the N x N matrices H(f) at each data frequency.

```S = sparameters('passive.s2p'); ispassive(S)```
```ans = logical 1 ```
`passivity(S)`

Testing and Visualizing `rationalfit` Output Passivity

The `rationalfit` function converts N-port sparameter data, `S` into an NxN matrix of `rfmodel.rational` objects. Using the `ispassive` function on the N x N fit output reports that even if input data `S` is passive, the output fit is not passive. In other words, the norm H(f) is greater than one at some frequency in the range [0,Inf].

The `passivity` function takes an N x N fit as input and plots its passivity. This is a plot of the upper bound of the norm(H(f)) on [0,Inf], also known as the H-infinity norm.

```fit = rationalfit(S); ispassive(fit)```
```ans = logical 0 ```
`passivity(fit)`

The `makepassive` function takes as input an N x N array of fit objects and also the original S-parameter data, and produces a passive fit by using convex optimization techniques to optimally match the data of the S-parameter input `S` while satisfying passivity constraints. The residues C and feedthrough matrix D of the output `pfit` are modified, but the poles A of the output pfit are identical to the poles A of the input fit.

`pfit = makepassive(fit,S,'Display','on');`
```ITER H-INFTY NORM FREQUENCY ERRDB CONSTRAINTS 0 1 + 1.791e-02 17.6816 GHz -40.4702 1 1 + 2.678e-04 282.601 MHz -40.9167 5 2 1 + 7.110e-05 377.139 MHz -40.9077 8 3 1 + 1.361e-06 361.144 MHz -40.9066 9 4 1 - 1.800e-06 367.533 MHz -40.9064 10 ```
`ispassive(pfit)`
```ans = logical 1 ```
`passivity(pfit)`

`all(vertcat(pfit(:).A) == vertcat(fit(:).A))`
```ans = logical 1 ```

Start `makepassive` with Prescribed Poles and Zero C and D

To demonstrate that only C and D are modified by `makepassive`, one can zero out C and D and re-run `makepassive`. The output, `pfit` still has the same poles as the input fit. The differences between `pfit` and `pfit2` arise because of the different starting points of the convex optimizations.

One can use this feature of the `makepassive` function to produce a passive fit from a prescribed set of poles without any idea of starting C and D.

```for k = 1:numel(fit) fit(k).C(:) = 0; fit(k).D(:) = 0; end pfit2 = makepassive(fit,S); passivity(pfit2)```

`all(vertcat(pfit2(:).A) == vertcat(fit(:).A))`
```ans = logical 1 ```

Generate Equivalent SPICE Circuit from Passive Fit

The `generateSPICE` function takes a passive fit and generates an equivalent circuit as a SPICE subckt file. The input fit is an N x N array of `rfmodel.rational` objects as returned by rationalfit with an S-parameters object as input. The generated file is a SPICE model constructed solely of passive R, L, C elements and controlled source elements E, F, G, and H.

```generateSPICE(pfit2,'mypassive.ckt') type mypassive.ckt```
```* Equivalent circuit model for mypassive.ckt .SUBCKT mypassive po1 po2 Vsp1 po1 p1 0 Vsr1 p1 pr1 0 Rp1 pr1 0 50 Ru1 u1 0 50 Fr1 u1 0 Vsr1 -1 Fu1 u1 0 Vsp1 -1 Ry1 y1 0 1 Gy1 p1 0 y1 0 -0.02 Vsp2 po2 p2 0 Vsr2 p2 pr2 0 Rp2 pr2 0 50 Ru2 u2 0 50 Fr2 u2 0 Vsr2 -1 Fu2 u2 0 Vsp2 -1 Ry2 y2 0 1 Gy2 p2 0 y2 0 -0.02 Rx1 x1 0 1 Fxc1_2 x1 0 Vx2 18.8608455628952 Cx1 x1 xm1 3.95175907242771e-09 Vx1 xm1 0 0 Gx1_1 x1 0 u1 0 -0.0921740428792648 Rx2 x2 0 1 Fxc2_1 x2 0 Vx1 -0.0832663456402132 Cx2 x2 xm2 3.95175907242771e-09 Vx2 xm2 0 0 Gx2_1 x2 0 u1 0 0.0076749957134407 Rx3 x3 0 1 Cx3 x3 0 2.73023891256077e-12 Gx3_1 x3 0 u1 0 -2.06195853592513 Rx4 x4 0 1 Cx4 x4 0 7.77758885464816e-12 Gx4_1 x4 0 u1 0 -2.91812992340686 Rx5 x5 0 1 Cx5 x5 0 2.29141629880011e-11 Gx5_1 x5 0 u1 0 -0.544258745379989 Rx6 x6 0 1 Cx6 x6 0 9.31845201582549e-11 Gx6_1 x6 0 u1 0 -0.654472771464866 Rx7 x7 0 1 Cx7 x7 0 4.89917765129955e-10 Gx7_1 x7 0 u1 0 -0.0811085791732396 Rx8 x8 0 1 Cx8 x8 0 1.25490425576858e-08 Gx8_1 x8 0 u1 0 -0.947597037040284 Rx9 x9 0 1 Fxc9_10 x9 0 Vx10 18.48476782415 Cx9 x9 xm9 3.95175907242771e-09 Vx9 xm9 0 0 Gx9_2 x9 0 u2 0 -0.0931554263774873 Rx10 x10 0 1 Fxc10_9 x10 0 Vx9 -0.0849604225839892 Cx10 x10 xm10 3.95175907242771e-09 Vx10 xm10 0 0 Gx10_2 x10 0 u2 0 0.00791452439102302 Rx11 x11 0 1 Cx11 x11 0 2.73023891256077e-12 Gx11_2 x11 0 u2 0 -2.08568376883053 Rx12 x12 0 1 Cx12 x12 0 7.77758885464816e-12 Gx12_2 x12 0 u2 0 -2.92831493290198 Rx13 x13 0 1 Cx13 x13 0 2.29141629880011e-11 Gx13_2 x13 0 u2 0 -0.607069609134215 Rx14 x14 0 1 Cx14 x14 0 9.31845201582549e-11 Gx14_2 x14 0 u2 0 -0.692675819285498 Rx15 x15 0 1 Cx15 x15 0 4.89917765129955e-10 Gx15_2 x15 0 u2 0 -0.0860600965539356 Rx16 x16 0 1 Cx16 x16 0 1.25490425576858e-08 Gx16_2 x16 0 u2 0 -0.948049815031899 Gyc1_1 y1 0 x1 0 -1 Gyc1_2 y1 0 x2 0 -1 Gyc1_3 y1 0 x3 0 -0.140226456003089 Gyc1_4 y1 0 x4 0 -0.0224053606295668 Gyc1_5 y1 0 x5 0 -1 Gyc1_6 y1 0 x6 0 -1 Gyc1_7 y1 0 x7 0 1 Gyc1_8 y1 0 x8 0 0.999899162849115 Gyc1_9 y1 0 x9 0 0.989768795439673 Gyc1_10 y1 0 x10 0 0.966813493274019 Gyc1_11 y1 0 x11 0 1 Gyc1_12 y1 0 x12 0 -1 Gyc1_13 y1 0 x13 0 0.810781448596926 Gyc1_14 y1 0 x14 0 0.941819403036702 Gyc1_15 y1 0 x15 0 -0.935805884074415 Gyc1_16 y1 0 x16 0 -0.999929417626443 Gyd1_1 y1 0 u1 0 0.604678443865245 Gyd1_2 y1 0 u2 0 -0.353220162701538 Gyc2_1 y2 0 x1 0 0.998563230419628 Gyc2_2 y2 0 x2 0 0.97510998663352 Gyc2_3 y2 0 x3 0 1 Gyc2_4 y2 0 x4 0 -1 Gyc2_5 y2 0 x5 0 0.900724171541662 Gyc2_6 y2 0 x6 0 0.997048499248955 Gyc2_7 y2 0 x7 0 -0.992517070282035 Gyc2_8 y2 0 x8 0 -1 Gyc2_9 y2 0 x9 0 -1 Gyc2_10 y2 0 x10 0 -1 Gyc2_11 y2 0 x11 0 -0.262633564705792 Gyc2_12 y2 0 x12 0 0.0673766779726025 Gyc2_13 y2 0 x13 0 -1 Gyc2_14 y2 0 x14 0 -1 Gyc2_15 y2 0 x15 0 1 Gyc2_16 y2 0 x16 0 1 Gyd2_1 y2 0 u1 0 -0.337987098493609 Gyd2_2 y2 0 u2 0 0.697067411175786 .ENDS ```