Branch data Line data Source code
1 : : /*
2 : : * spfile.cpp - S-parameter file class implementation
3 : : *
4 : : * Copyright (C) 2004, 2005, 2006, 2008, 2009 Stefan Jahn <stefan@lkcc.org>
5 : : *
6 : : * This is free software; you can redistribute it and/or modify
7 : : * it under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation; either version 2, or (at your option)
9 : : * any later version.
10 : : *
11 : : * This software is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : * GNU General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with this package; see the file COPYING. If not, write to
18 : : * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19 : : * Boston, MA 02110-1301, USA.
20 : : *
21 : : * $Id$
22 : : *
23 : : */
24 : :
25 : : #if HAVE_CONFIG_H
26 : : # include <config.h>
27 : : #endif
28 : :
29 : : #include "component.h"
30 : : #include "matvec.h"
31 : : #include "dataset.h"
32 : : #include "strlist.h"
33 : : #include "poly.h"
34 : : #include "spline.h"
35 : : #include "interpolator.h"
36 : : #include "spfile.h"
37 : :
38 : : using namespace qucs;
39 : :
40 : : // Constructor for S-parameter file vector.
41 : 0 : spfile_vector::spfile_vector () {
42 : 0 : v = f = 0;
43 : 0 : isreal = 1;
44 : 0 : inter = NULL;
45 : 0 : r = c = 0;
46 : 0 : }
47 : :
48 : : // Destructor for S-parameter file vector.
49 : 0 : spfile_vector::~spfile_vector () {
50 [ # # ][ # # ]: 0 : if (inter) delete inter;
[ # # ][ # # ]
51 : 0 : }
52 : :
53 : : // Passes vectors and their data types to the S-parameter file vector.
54 : 0 : void spfile_vector::prepare (qucs::vector * _v, qucs::vector * _f,
55 : : bool _isreal, int it, int dt) {
56 : 0 : v = _v;
57 : 0 : f = _f;
58 : 0 : isreal = _isreal;
59 [ # # ]: 0 : inter = new interpolator ();
60 [ # # ]: 0 : if (isreal) {
61 : 0 : inter->rvectors (v, f);
62 : 0 : inter->prepare (it, REPEAT_NO, dt | DATA_REAL);
63 : : }
64 : : else {
65 : 0 : inter->cvectors (v, f);
66 : 0 : inter->prepare (it, REPEAT_NO, dt | DATA_COMPLEX);
67 : : }
68 : 0 : }
69 : :
70 : : // Returns interpolated data.
71 : 0 : nr_complex_t spfile_vector::interpolate (nr_double_t x) {
72 [ # # ]: 0 : if (isreal)
73 : 0 : return inter->rinterpolate (x);
74 : : else
75 : 0 : return inter->cinterpolate (x);
76 : : }
77 : :
78 : : // Constructor creates an empty and unnamed instance of the spfile class.
79 : 0 : spfile::spfile () : circuit () {
80 : 0 : data = NULL;
81 : 0 : sfreq = nfreq = NULL;
82 : 0 : spara = FMIN = SOPT = RN = NULL;
83 : 0 : interpolType = dataType = 0;
84 : 0 : type = CIR_SPFILE;
85 : 0 : setVariableSized (true);
86 : 0 : }
87 : :
88 : : // Destructor deletes spfile object from memory.
89 : 0 : spfile::~spfile () {
90 [ # # ][ # # ]: 0 : if (spara) delete[] spara;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
91 [ # # ][ # # ]: 0 : if (RN) delete RN;
[ # # ][ # # ]
[ # # ][ # # ]
92 [ # # ][ # # ]: 0 : if (FMIN) delete FMIN;
[ # # ][ # # ]
[ # # ][ # # ]
93 [ # # ][ # # ]: 0 : if (SOPT) delete SOPT;
[ # # ][ # # ]
[ # # ][ # # ]
94 : : #if DEBUG && 0
95 : : if (data) {
96 : : data->setFile ("spfile.dat");
97 : : data->print ();
98 : : }
99 : : #endif
100 [ # # ][ # # ]: 0 : if (data) delete data;
[ # # ][ # # ]
[ # # ][ # # ]
101 [ # # ][ # # ]: 0 : }
102 : :
103 : 0 : void spfile::calcSP (nr_double_t frequency) {
104 : :
105 : : // nothing to do if the given file type had errors
106 [ # # ][ # # ]: 0 : if (spara == NULL || sfreq == NULL) return;
107 : :
108 : : // set interpolated S-parameters
109 [ # # ][ # # ]: 0 : setMatrixS (expandSParaMatrix (getInterpolMatrixS (frequency)));
[ # # ]
110 : : }
111 : :
112 : : /* This function returns the S-parameter matrix of the circuit for the
113 : : given frequency. It uses interpolation for frequency points which
114 : : are not part of the original touchstone file. */
115 : 0 : matrix spfile::getInterpolMatrixS (nr_double_t frequency) {
116 : :
117 : : // first interpolate the matrix values
118 : 0 : matrix s (getSize () - 1);
119 [ # # ]: 0 : for (int r = 0; r < getSize () - 1; r++) {
120 [ # # ]: 0 : for (int c = 0; c < getSize () - 1; c++) {
121 : 0 : int i = r * getSize () + c;
122 [ # # ][ # # ]: 0 : s.set (r, c, spara[i].interpolate (frequency));
123 : : }
124 : : }
125 : :
126 : : // then convert them to S-parameters if necessary
127 [ # # # # : 0 : switch (paraType) {
# ]
128 : : case 'Y':
129 [ # # ][ # # ]: 0 : s = ytos (s);
[ # # ][ # # ]
[ # # ]
130 : 0 : break;
131 : : case 'Z':
132 [ # # ][ # # ]: 0 : s = ztos (s);
[ # # ][ # # ]
[ # # ]
133 : 0 : break;
134 : : case 'H':
135 [ # # ][ # # ]: 0 : s = htos (s);
[ # # ][ # # ]
[ # # ]
136 : 0 : break;
137 : : case 'G':
138 [ # # ][ # # ]: 0 : s = gtos (s);
[ # # ][ # # ]
[ # # ]
139 : 0 : break;
140 : : }
141 : 0 : return s;
142 : : }
143 : :
144 : 0 : void spfile::calcNoiseSP (nr_double_t frequency) {
145 : : // nothing to do if the given file type had errors
146 [ # # ][ # # ]: 0 : if (spara == NULL || nfreq == NULL) return;
147 [ # # ]: 0 : setMatrixN (calcMatrixCs (frequency));
148 : : }
149 : :
150 : 0 : matrix spfile::calcMatrixCs (nr_double_t frequency) {
151 : : // set interpolated noise correlation matrix
152 [ # # ]: 0 : nr_double_t r = real (RN->interpolate (frequency));
153 [ # # ]: 0 : nr_double_t f = real (FMIN->interpolate (frequency));
154 [ # # ]: 0 : nr_complex_t g = SOPT->interpolate (frequency);
155 [ # # ]: 0 : matrix s = getInterpolMatrixS (frequency);
156 [ # # ][ # # ]: 0 : matrix n = correlationMatrix (f, g, r, s);
[ # # ]
157 [ # # ][ # # ]: 0 : matrix c = expandNoiseMatrix (n, expandSParaMatrix (s));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
158 [ # # ][ # # ]: 0 : return c;
159 : : }
160 : :
161 : : /* This function expands the actual S-parameter file data stored
162 : : within the touchstone file to have an additional reference one-port
163 : : whose S-parameter is -1 (i.e. ground). */
164 : 0 : matrix spfile::expandSParaMatrix (matrix s) {
165 [ # # ]: 0 : assert (s.getCols () == s.getRows ());
166 : 0 : int r, c, ports = s.getCols () + 1;
167 : 0 : nr_double_t g = -1;
168 : 0 : nr_complex_t fr, ss, sr, sc, sa;
169 [ # # ]: 0 : matrix res (ports);
170 : :
171 : : // compute S'mm
172 [ # # ]: 0 : for (sa = 0, r = 0; r < ports - 1; r++)
173 [ # # ][ # # ]: 0 : for (c = 0; c < ports - 1; c++) sa += s.get (r, c);
174 [ # # ]: 0 : ss = (2 - g - ports + sa) / (1 - ports * g - sa);
175 [ # # ]: 0 : res.set (ports - 1, ports - 1, ss);
176 : 0 : fr = (1.0 - g * ss) / (1.0 - g);
177 : :
178 : : // compute S'im
179 [ # # ]: 0 : for (r = 0; r < ports - 1; r++) {
180 [ # # ][ # # ]: 0 : for (sc = 0, c = 0; c < ports - 1; c++) sc += s.get (r, c);
181 [ # # ][ # # ]: 0 : res.set (r, ports - 1, fr * (1.0 - sc));
182 : : }
183 : :
184 : : // compute S'mj
185 [ # # ]: 0 : for (c = 0; c < ports - 1; c++) {
186 [ # # ][ # # ]: 0 : for (sr = 0, r = 0; r < ports - 1; r++) sr += s.get (r, c);
187 [ # # ][ # # ]: 0 : res.set (ports - 1, c, fr * (1.0 - sr));
188 : : }
189 : :
190 : : // compute S'ij
191 [ # # ]: 0 : for (r = 0; r < ports - 1; r++) {
192 [ # # ]: 0 : for (c = 0; c < ports - 1; c++) {
193 [ # # ][ # # ]: 0 : fr = g * res (r, ports - 1) * res (ports - 1, c) / (1.0 - g * ss);
194 [ # # ][ # # ]: 0 : res.set (r, c, s.get (r, c) - fr);
[ # # ]
195 : : }
196 : : }
197 : :
198 : 0 : return res;
199 : : }
200 : :
201 : : /* The function is the counterpart of the above expandSParaMatrix()
202 : : function. It shrinks the S-parameter matrix by removing the
203 : : reference port. */
204 : 0 : matrix spfile::shrinkSParaMatrix (matrix s) {
205 [ # # ][ # # ]: 0 : assert (s.getCols () == s.getRows () && s.getCols () > 0);
[ # # ]
206 : 0 : int r, c, ports = s.getCols ();
207 : 0 : nr_double_t g = -1;
208 [ # # ]: 0 : matrix res (ports - 1);
209 : :
210 : : // compute S'ij
211 [ # # ]: 0 : for (r = 0; r < ports - 1; r++) {
212 [ # # ]: 0 : for (c = 0; c < ports - 1; c++) {
213 : 0 : res.set (r, c, s (r, c) + g * s (r, ports - 1) *
214 [ # # ]: 0 : s (ports - 1, c) / (1.0 - g * s (ports - 1, ports - 1)));
[ # # # # ]
215 : : }
216 : : }
217 : 0 : return res;
218 : : }
219 : :
220 : : /* This function expands the actual noise correlation matrix to have an
221 : : additional reference one-port whose S-parameter is -1
222 : : (i.e. ground). The given S-parameter matrix is required to perform
223 : : this transformation and is obtained using the expandSParaMatrix()
224 : : function. */
225 : 0 : matrix spfile::expandNoiseMatrix (matrix n, matrix s) {
226 [ # # ][ # # ]: 0 : assert (s.getCols () == s.getRows () && n.getCols () == n.getRows () &&
[ # # ]
227 [ # # ]: 0 : n.getCols () == s.getCols () - 1);
228 [ # # ]: 0 : nr_double_t T = getPropertyDouble ("Temp");
229 : 0 : int r, c, ports = n.getCols () + 1;
230 : 0 : nr_double_t g = -1;
231 : :
232 : : // create K matrix
233 [ # # ]: 0 : matrix k (ports, ports - 1);
234 [ # # ]: 0 : for (r = 0; r < ports - 1; r++) {
235 [ # # ]: 0 : for (c = 0; c < ports - 1; c++) {
236 [ # # ]: 0 : if (r == c)
237 [ # # ][ # # ]: 0 : k.set (r, c, 1.0 + g * (s.get (r, ports - 1) - 1.0));
238 : : else
239 [ # # ][ # # ]: 0 : k.set (r, c, g * s.get (r, ports - 1));
240 : : }
241 : : }
242 [ # # ]: 0 : for (c = 0; c < ports - 1; c++)
243 [ # # ][ # # ]: 0 : k.set (ports - 1, c, g * s.get (ports - 1, ports - 1) - 1.0);
244 : :
245 : : // create D vector
246 [ # # ]: 0 : matrix d (ports, 1);
247 [ # # ][ # # ]: 0 : for (r = 0; r < ports - 1; r++) d.set (r, 0, s.get (r, ports - 1));
[ # # ]
248 [ # # ][ # # ]: 0 : d.set (ports - 1, 0, s.get (ports - 1, ports - 1) - 1.0);
249 : :
250 : : // expand noise correlation matrix
251 [ # # ]: 0 : matrix res (ports);
252 [ # # ]: 0 : res = (k * n * adjoint (k) - kelvin (T) / T0 * fabs (1 - norm (g)) *
253 [ # # ][ # # ]: 0 : d * adjoint (d)) * norm (1 / (1 - g));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
254 [ # # ][ # # ]: 0 : return res;
255 : : }
256 : :
257 : : /* The function is the counterpart of the above expandNoiseMatrix()
258 : : function. It shrinks the noise correlation matrix by removing the
259 : : reference port. The given S-parameter matrix is required to perform
260 : : this transformation and is obtained using the expandSParaMatrix()
261 : : function. */
262 : 0 : matrix spfile::shrinkNoiseMatrix (matrix n, matrix s) {
263 [ # # ][ # # ]: 0 : assert (s.getCols () == s.getRows () && n.getCols () == n.getRows () &&
[ # # ][ # # ]
264 [ # # ]: 0 : n.getCols () == s.getCols () && n.getCols () > 0);
265 : 0 : int r, ports = n.getCols ();
266 : 0 : nr_double_t g = -1;
267 [ # # ]: 0 : nr_double_t T = getPropertyDouble ("Temp");
268 : :
269 : : // create K' matrix
270 [ # # ]: 0 : matrix k (ports - 1, ports);
271 [ # # ][ # # ]: 0 : for (r = 0; r < ports - 1; r++) k.set (r, r, 1);
272 [ # # ]: 0 : for (r = 0; r < ports - 1; r++)
273 [ # # ]: 0 : k.set (r, ports - 1, g * s.get (r, ports - 1) /
274 [ # # ][ # # ]: 0 : (1.0 - g * s.get (ports - 1, ports - 1)));
[ # # ]
275 : :
276 : : // create D' vector
277 [ # # ]: 0 : matrix d (ports - 1, 1);
278 [ # # ][ # # ]: 0 : for (r = 0; r < ports - 1; r++) d.set (r, 0, s.get (r, ports - 1));
[ # # ]
279 : :
280 : : // shrink noise correlation matrix
281 [ # # ]: 0 : matrix res (ports - 1);
282 [ # # ]: 0 : res = k * n * adjoint (k) + kelvin (T) / T0 * fabs (1.0 - norm (g)) /
283 [ # # ][ # # ]: 0 : norm (1.0 - g * s.get (ports - 1, ports - 1)) * d * adjoint (d);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
284 [ # # ][ # # ]: 0 : return res;
285 : : }
286 : :
287 : 0 : void spfile::prepare (void) {
288 : :
289 : : // check type of data
290 : 0 : const char * const dtype = getPropertyString ("Data");
291 [ # # ]: 0 : if (!strcmp (dtype, "rectangular")) {
292 : : // rectangular data
293 : 0 : dataType = DATA_RECTANGULAR;
294 : : }
295 [ # # ]: 0 : else if (!strcmp (dtype, "polar")) {
296 : : // polar data
297 : 0 : dataType = DATA_POLAR;
298 : : }
299 : :
300 : : // check type of interpolator
301 : 0 : const char * const itype = getPropertyString ("Interpolator");
302 [ # # ]: 0 : if (!strcmp (itype, "linear")) {
303 : 0 : interpolType = INTERPOL_LINEAR;
304 : : }
305 [ # # ]: 0 : else if (!strcmp (itype, "cubic")) {
306 : 0 : interpolType = INTERPOL_CUBIC;
307 : : }
308 : :
309 : : // load S-parameter file
310 : 0 : const char * file = getPropertyString ("File");
311 [ # # ]: 0 : if (data == NULL) data = dataset::load_touchstone (file);
312 [ # # ]: 0 : if (data != NULL) {
313 : : // determine the number of ports defined by that file
314 : 0 : int ports = (int) std::sqrt ((double) data->countVariables ());
315 [ # # ]: 0 : if (ports == getSize () - 1) {
316 [ # # ]: 0 : if (spara == NULL) {
317 : : // find matrix vector entries in touchstone dataset
318 : 0 : createIndex ();
319 : : }
320 [ # # ]: 0 : if (sfreq == NULL) {
321 : : logprint (LOG_ERROR, "ERROR: file `%s' contains no `frequency' "
322 : 0 : "vector\n", file);
323 : : }
324 : : }
325 : : else {
326 : : logprint (LOG_ERROR, "ERROR: file `%s' specifies a %d-port, `%s' "
327 : : "requires a %d-port\n", file, ports, getName (),
328 : 0 : getSize () - 1);
329 : : }
330 : : }
331 : 0 : }
332 : :
333 : 0 : void spfile::initSP (void) {
334 : : // allocate S-parameter matrix
335 : 0 : allocMatrixS ();
336 : : // initialize data
337 : 0 : prepare ();
338 : 0 : }
339 : :
340 : : /* The function creates an additional data vector for the given matrix
341 : : entry and adds it to the dataset. */
342 : 0 : void spfile::createVector (int r, int c) {
343 : 0 : int i = r * getSize () + c;
344 : 0 : spara[i].r = r;
345 : 0 : spara[i].c = c;
346 : : qucs::vector * v = new qucs::vector (matvec::createMatrixString ("S", r, c),
347 [ # # ]: 0 : sfreq->getSize ());
348 [ # # ]: 0 : v->setDependencies (new strlist ());
349 : 0 : v->getDependencies()->add (sfreq->getName ());
350 : 0 : data->addVariable (v);
351 : 0 : spara[i].v = v;
352 : 0 : }
353 : :
354 : : /* This function goes through the dataset stored within the original
355 : : touchstone file and looks for the S-parameter matrices and
356 : : frequency vector. It also tries to find the noise parameter
357 : : data. */
358 : 0 : void spfile::createIndex (void) {
359 : 0 : qucs::vector * v; int s = getSize (); char * n;
360 : : int r, c, i;
361 : :
362 : : // go through list of dependency vectors and find frequency vectors
363 [ # # ]: 0 : for (v = data->getDependencies (); v != NULL; v = (::vector *) v->getNext ()) {
364 [ # # ]: 0 : if ((n = v->getName ()) != NULL) {
365 [ # # ]: 0 : if (!strcmp (n, "frequency")) sfreq = v;
366 [ # # ]: 0 : else if (!strcmp (n, "nfreq")) nfreq = v;
367 : : }
368 : : }
369 : :
370 : : // create vector index
371 [ # # ][ # # ]: 0 : spara = new spfile_vector[s * s] ();
372 : :
373 : : // go through list of variable vectors and find matrix entries
374 [ # # ]: 0 : for (v = data->getVariables (); v != NULL; v = (::vector *) v->getNext ()) {
375 [ # # ][ # # ]: 0 : if ((n = matvec::isMatrixVector (v->getName (), r, c)) != NULL) {
376 : : // save matrix vector indices
377 : 0 : i = r * s + c;
378 : 0 : spara[i].r = r;
379 : 0 : spara[i].c = c;
380 [ # # ]: 0 : spara[i].prepare (v, sfreq, false, interpolType, dataType);
381 : 0 : paraType = n[0]; // save type of touchstone data
382 : 0 : free (n);
383 : : }
384 [ # # ]: 0 : if ((n = v->getName ()) != NULL) {
385 : : // find noise parameter vectors
386 [ # # ]: 0 : if (!strcmp (n, "Rn")) {
387 [ # # ]: 0 : RN = new spfile_vector ();
388 [ # # ]: 0 : RN->prepare (v, nfreq, true, interpolType, dataType);
389 : : }
390 [ # # ]: 0 : else if (!strcmp (n, "Fmin")) {
391 [ # # ]: 0 : FMIN = new spfile_vector ();
392 [ # # ]: 0 : FMIN->prepare (v, nfreq, true, interpolType, dataType);
393 : : }
394 [ # # ]: 0 : else if (!strcmp (n, "Sopt")) {
395 [ # # ]: 0 : SOPT = new spfile_vector ();
396 [ # # ]: 0 : SOPT->prepare (v, nfreq, false, interpolType, dataType);
397 : : }
398 : : }
399 : : }
400 : 0 : }
401 : :
402 : : /* This function computes the noise correlation matrix of a twoport
403 : : based upon the noise parameters and the given S-parameter
404 : : matrix. */
405 : 0 : matrix spfile::correlationMatrix (nr_double_t Fmin, nr_complex_t Sopt,
406 : : nr_double_t Rn, matrix s) {
407 [ # # ][ # # ]: 0 : assert (s.getCols () == s.getRows () && s.getCols () == 2);
[ # # ]
408 [ # # ]: 0 : matrix c (2);
409 [ # # ]: 0 : nr_complex_t Kx = 4 * Rn / z0 / norm (1.0 + Sopt);
410 [ # # ][ # # ]: 0 : c.set (0, 0, (Fmin - 1) * (norm (s.get (0, 0)) - 1) +
411 [ # # ][ # # ]: 0 : Kx * norm (1.0 - s.get (0, 0) * Sopt));
[ # # ][ # # ]
412 [ # # ][ # # ]: 0 : c.set (1, 1, norm (s.get (1, 0)) * ((Fmin - 1) + Kx * norm (Sopt)));
[ # # ][ # # ]
413 [ # # ][ # # ]: 0 : c.set (0, 1, s.get (0, 0) / s.get (1, 0) * c.get (1, 1) -
[ # # ][ # # ]
414 [ # # ][ # # ]: 0 : conj (s.get (1, 0)) * conj (Sopt) * Kx);
[ # # ][ # # ]
[ # # ][ # # ]
415 [ # # ][ # # ]: 0 : c.set (1, 0, conj (c.get (0, 1)));
416 : 0 : return c;
417 : : }
418 : :
419 : : /* The function computes the noise figure and noise parameters for the
420 : : given S-parameter and noise correlation matrices of a twoport. */
421 : 0 : nr_double_t spfile::noiseFigure (matrix s, matrix c, nr_double_t& Fmin,
422 : : nr_complex_t& Sopt, nr_double_t& Rn) {
423 [ # # ][ # # ]: 0 : assert (s.getCols () == s.getRows () && c.getCols () == c.getRows () &&
[ # # ][ # # ]
424 [ # # ]: 0 : s.getCols () == 2 && c.getCols () == 2);
425 : 0 : nr_complex_t n1, n2;
426 [ # # ][ # # ]: 0 : n1 = c.get (0, 0) * norm (s.get (1, 0)) -
[ # # ]
427 [ # # ][ # # ]: 0 : 2 * real (c.get (0, 1) * s.get (1, 0) * conj (s.get (0, 0))) +
[ # # ][ # # ]
[ # # ]
428 [ # # ][ # # ]: 0 : c.get (1, 1) * norm (s.get (0, 0));
[ # # ]
429 [ # # ][ # # ]: 0 : n2 = 2.0 * (c.get (1, 1) * s.get (0, 0) -
430 [ # # ][ # # ]: 0 : c.get (0, 1) * s.get (1, 0)) / (c.get (1, 1) + n1);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
431 : :
432 : : // optimal source reflection coefficient
433 [ # # ]: 0 : Sopt = 1 - norm (n2);
434 [ # # ]: 0 : if (real (Sopt) < 0.0)
435 [ # # ]: 0 : Sopt = (1.0 + std::sqrt (Sopt)) / n2; // avoid a negative radicant
436 : : else
437 [ # # ]: 0 : Sopt = (1.0 - std::sqrt (Sopt)) / n2;
438 : :
439 : : // minimum noise figure
440 [ # # ][ # # ]: 0 : Fmin = real (1.0 + (c.get (1, 1) - n1 * norm (Sopt)) /
441 [ # # ][ # # ]: 0 : norm (s.get (1, 0)) / (1.0 + norm (Sopt)));
[ # # ][ # # ]
442 : :
443 : : // equivalent noise resistance
444 : 0 : Rn = real ((c (0, 0) - 2.0 *
445 [ # # ][ # # ]: 0 : real (c (0, 1) * conj ((1.0 + s (0, 0)) / s (1, 0))) +
446 [ # # ][ # # ]: 0 : c (1, 1) * norm ((1.0 + s (0, 0)) / s (1, 0))) / 4.0);
447 : 0 : Rn = Rn * z0;
448 : :
449 : : // noise figure itself
450 [ # # ][ # # ]: 0 : return real (1.0 + c.get (1, 1) / norm (s.get (1, 0)));
[ # # ]
451 : : }
452 : :
453 : 0 : void spfile::initDC (void) {
454 : : // get appropriate property value
455 : 0 : const char * const dc = getPropertyString ("duringDC");
456 : :
457 : : // a short during DC including the reference node
458 [ # # ]: 0 : if (!strcmp (dc, "shortall")) {
459 : 0 : int v, n, lastnode = getSize () - 1;
460 : 0 : setVoltageSources (lastnode);
461 : 0 : allocMatrixMNA ();
462 : : // place zero voltage sources
463 [ # # ]: 0 : for (v = VSRC_1, n = NODE_1; n < lastnode; n++, v++) {
464 : 0 : voltageSource (v, n, lastnode);
465 : : }
466 : 0 : return;
467 : : }
468 : : // a short during DC excluding the reference node
469 [ # # ]: 0 : if (!strcmp (dc, "short")) {
470 : 0 : int v, n, lastnode = getSize () - 2;
471 : 0 : setVoltageSources (lastnode);
472 : 0 : allocMatrixMNA ();
473 : : // place zero voltage sources
474 [ # # ]: 0 : for (v = VSRC_1, n = NODE_1; n < lastnode; n++, v++) {
475 : 0 : voltageSource (v, n, lastnode);
476 : : }
477 : 0 : return;
478 : : }
479 : : // an open during DC
480 [ # # ]: 0 : else if (!strcmp (dc, "open")) {
481 : 0 : setVoltageSources (0);
482 : 0 : allocMatrixMNA ();
483 : 0 : return;
484 : : }
485 : : // none specified, DC value of IDFT ?
486 : : else {
487 : 0 : setVoltageSources (0);
488 : 0 : allocMatrixMNA ();
489 : : }
490 : : }
491 : :
492 : 0 : void spfile::initAC (void) {
493 : 0 : setVoltageSources (0);
494 : 0 : allocMatrixMNA ();
495 : 0 : initSP ();
496 : 0 : }
497 : :
498 : 0 : void spfile::calcAC (nr_double_t frequency) {
499 : : // nothing to do if the given file type had errors
500 [ # # ][ # # ]: 0 : if (spara == NULL || sfreq == NULL) return;
501 : : // calculate interpolated S-parameters
502 : 0 : calcSP (frequency);
503 : : // convert S-parameters to Y-parameters
504 [ # # ][ # # ]: 0 : setMatrixY (stoy (getMatrixS ()));
[ # # ][ # # ]
[ # # ]
505 : : }
506 : :
507 : 0 : void spfile::calcNoiseAC (nr_double_t frequency) {
508 : : // nothing to do if the given file type had errors
509 [ # # ][ # # ]: 0 : if (spara == NULL || nfreq == NULL) return;
510 [ # # ][ # # ]: 0 : setMatrixN (cstocy (calcMatrixCs (frequency), getMatrixY () * z0) / z0);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
511 : : }
512 : :
513 : 0 : void spfile::initTR (void) {
514 : 0 : initDC ();
515 : 0 : }
516 : :
517 : : // properties
518 : : PROP_REQ [] = {
519 : : { "File", PROP_STR, { PROP_NO_VAL, "spfile.snp" }, PROP_NO_RANGE },
520 : : PROP_NO_PROP };
521 : : PROP_OPT [] = {
522 : : { "Data", PROP_STR, { PROP_NO_VAL, "polar" },
523 : : PROP_RNG_STR2 ("rectangular", "polar") },
524 : : { "Interpolator", PROP_STR, { PROP_NO_VAL, "linear" },
525 : : PROP_RNG_STR2 ("linear", "cubic") },
526 : : { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
527 : : { "duringDC", PROP_STR, { PROP_NO_VAL, "open" },
528 : : PROP_RNG_STR4 ("open", "short", "shortall", "unspecified") },
529 : : PROP_NO_PROP };
530 : : struct define_t spfile::cirdef =
531 : : { "SPfile",
532 : : PROP_NODES, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };
|