Main Content

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)

Figure contains an axes object. The axes object with title Data passive, max norm(H) is 1 - 4.06e-08 at 0.00054 GHz, xlabel Frequency (GHz), ylabel norm(H) contains an object of type line.

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)

Figure contains an axes object. The axes object with title Fit not passive, H indexOf infinity baseline blank n o r m blank i s blank 1 blank + blank 1 . 7 9 1 e - 0 2 blank a t blank 1 7 . 6 8 1 6 blank G H z ., xlabel Frequency (GHz), ylabel norm(H) contains 4 objects of type line. One or more of the lines displays its values using only markers

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.682e-04	282.466  MHz	-40.9167	5
2		1 + 8.490e-05	368.585  MHz	-40.9086	8
3		1 - 1.292e-06	366.212  MHz	-40.9066	9
ispassive(pfit)
ans = logical
   1

passivity(pfit)

Figure contains an axes object. The axes object with title Fit passive, H indexOf infinity baseline blank n o r m blank i s blank 1 blank - blank 1 . 2 9 2 e - 0 6 blank a t blank 3 6 6 . 2 1 2 blank M H z ., xlabel Frequency (GHz), ylabel norm(H) contains an object of type line.

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)

Figure contains an axes object. The axes object with title Fit passive, H indexOf infinity baseline blank n o r m blank i s blank 1 blank - blank 2 . 2 8 1 e - 0 6 blank a t blank 3 5 8 . 9 7 7 blank M H z ., xlabel Frequency (GHz), ylabel norm(H) contains an object of type line.

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.8746944486893
Cx1 x1 xm1 3.95175907242771e-09
Vx1 xm1 0 0
Gx1_1 x1 0 u1 0 -0.0921642171288101
Rx2 x2 0 1
Fxc2_1 x2 0 Vx1 -0.0832052508174916
Cx2 x2 xm2 3.95175907242771e-09
Vx2 xm2 0 0
Gx2_1 x2 0 u1 0 0.0076685468026004
Rx3 x3 0 1
Cx3 x3 0 2.73023891256077e-12
Gx3_1 x3 0 u1 0 -2.06202219574113
Rx4 x4 0 1
Cx4 x4 0 7.77758885464816e-12
Gx4_1 x4 0 u1 0 -2.91817148793167
Rx5 x5 0 1
Cx5 x5 0 2.29141629880011e-11
Gx5_1 x5 0 u1 0 -0.544272072855605
Rx6 x6 0 1
Cx6 x6 0 9.31845201582549e-11
Gx6_1 x6 0 u1 0 -0.654468794527287
Rx7 x7 0 1
Cx7 x7 0 4.89917765129955e-10
Gx7_1 x7 0 u1 0 -0.0811036968692825
Rx8 x8 0 1
Cx8 x8 0 1.25490425576858e-08
Gx8_1 x8 0 u1 0 -0.947597242060811
Rx9 x9 0 1
Fxc9_10 x9 0 Vx10 18.4978768308457
Cx9 x9 xm9 3.95175907242771e-09
Vx9 xm9 0 0
Gx9_2 x9 0 u2 0 -0.0931455814275563
Rx10 x10 0 1
Fxc10_9 x10 0 Vx9 -0.084900213147052
Cx10 x10 xm10 3.95175907242771e-09
Vx10 xm10 0 0
Gx10_2 x10 0 u2 0 0.00790807971690562
Rx11 x11 0 1
Cx11 x11 0 2.73023891256077e-12
Gx11_2 x11 0 u2 0 -2.08588719022003
Rx12 x12 0 1
Cx12 x12 0 7.77758885464816e-12
Gx12_2 x12 0 u2 0 -2.92842943772917
Rx13 x13 0 1
Cx13 x13 0 2.29141629880011e-11
Gx13_2 x13 0 u2 0 -0.607038260421269
Rx14 x14 0 1
Cx14 x14 0 9.31845201582549e-11
Gx14_2 x14 0 u2 0 -0.692675575156149
Rx15 x15 0 1
Cx15 x15 0 4.89917765129955e-10
Gx15_2 x15 0 u2 0 -0.0860559387439156
Rx16 x16 0 1
Cx16 x16 0 1.25490425576858e-08
Gx16_2 x16 0 u2 0 -0.948049481463788
Gyc1_1 y1 0 x1 0 -1
Gyc1_2 y1 0 x2 0 -1
Gyc1_3 y1 0 x3 0 -0.140315927859577
Gyc1_4 y1 0 x4 0 -0.0223733228877197
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.999898693316608
Gyc1_9 y1 0 x9 0 0.989978705003043
Gyc1_10 y1 0 x10 0 0.968413940149028
Gyc1_11 y1 0 x11 0 1
Gyc1_12 y1 0 x12 0 -1
Gyc1_13 y1 0 x13 0 0.810851100019631
Gyc1_14 y1 0 x14 0 0.941821809631154
Gyc1_15 y1 0 x15 0 -0.935901971027261
Gyc1_16 y1 0 x16 0 -0.99993002220679
Gyd1_1 y1 0 u1 0 0.604791040037866
Gyd1_2 y1 0 u2 0 -0.353325462334174
Gyc2_1 y2 0 x1 0 0.998776331469776
Gyc2_2 y2 0 x2 0 0.976775700981817
Gyc2_3 y2 0 x3 0 1
Gyc2_4 y2 0 x4 0 -1
Gyc2_5 y2 0 x5 0 0.900713545757646
Gyc2_6 y2 0 x6 0 0.99705813339587
Gyc2_7 y2 0 x7 0 -0.992633135383546
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.262419691080609
Gyc2_12 y2 0 x12 0 0.0673011420470885
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.338015667341436
Gyd2_2 y2 0 u2 0 0.696858329591718
.ENDS

Related Topics