My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
rfedd.cpp
Go to the documentation of this file.
1 /*
2  * rfedd.cpp - equation defined RF device class implementation
3  *
4  * Copyright (C) 2008 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: rfedd.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include "component.h"
30 #include "equation.h"
31 #include "environment.h"
32 #include "rfedd.h"
33 
34 using namespace eqn;
35 
36 // Constructor for the equation defined RF device.
37 rfedd::rfedd () : circuit () {
38  type = CIR_RFEDD;
39  setVariableSized (true);
40  peqn = NULL;
41 }
42 
43 // Destructor deletes equation defined RF device object from memory.
45  if (peqn) free (peqn);
46 }
47 
48 // Callback for initializing the DC analysis.
49 void rfedd::initDC (void) {
50 
51  // get appropriate property value
52  char * dc = getPropertyString ("duringDC");
53 
54  // a short during DC
55  if (!strcmp (dc, "short")) {
56  int v, n, lastnode = getSize () - 1;
57  setVoltageSources (lastnode);
58  allocMatrixMNA ();
59  // place zero voltage sources
60  for (v = VSRC_1, n = NODE_1; n < lastnode; n++, v++) {
61  voltageSource (v, n, lastnode);
62  }
63  return;
64  }
65  // an open during DC
66  else if (!strcmp (dc, "open")) {
68  allocMatrixMNA ();
69  return;
70  }
71  // zero frequency evaluation
72  else if (!strcmp (dc, "zerofrequency")) {
73  prepareModel ();
74  initMNA ();
75  calcMNA (0);
76  return;
77  }
78  // none specified, DC value of IDFT ?
79  else {
81  allocMatrixMNA ();
82  }
83 }
84 
85 // Some help macros.
86 #define A(a) ((assignment *) (a))
87 
88 // Creates a parameter variable name from the given arguments.
89 char * rfedd::createVariable (const char * base, int r, int c, bool pfx) {
90  char * str = strchr (getName (), '.');
91  if (str != NULL)
92  str = strrchr (str, '.') + 1;
93  else
94  str = getName ();
95  char * txt = (char *) malloc (strlen (str) + strlen (base) + 4);
96  if (pfx)
97  sprintf (txt, "%s.%s%d%d", str, base, r, c);
98  else
99  sprintf (txt, "%s%d%d", base, r, c);
100  return txt;
101 }
102 
103 // Creates a variable name from the given arguments.
104 char * rfedd::createVariable (const char * base, bool pfx) {
105  char * str = strchr (getName (), '.');
106  if (str != NULL)
107  str = strrchr (str, '.') + 1;
108  else
109  str = getName ();
110  char * txt = (char *) malloc (strlen (str) + strlen (base) + 2);
111  if (pfx)
112  sprintf (txt, "%s.%s", str, base);
113  else
114  sprintf (txt, "%s", base);
115  return txt;
116 }
117 
118 // Saves the given real value into the equation result.
119 void rfedd::setResult (void * eqn, nr_double_t val) {
120  A(eqn)->evaluate ();
121  constant * c = A(eqn)->getResult ();
122  c->d = val;
123 }
124 
125 // Saves the given complex value into the equation result.
126 void rfedd::setResult (void * eqn, nr_complex_t val) {
127  A(eqn)->evaluate ();
128  constant * c = A(eqn)->getResult ();
129  *(c->c) = val;
130 }
131 
132 // Returns the result of the equation.
133 nr_complex_t rfedd::getResult (void * eqn) {
134  A(eqn)->evaluate ();
135  return A(eqn)->getResultComplex ();
136 }
137 
138 // Initializes the equation defined device.
139 void rfedd::initModel (void) {
140  int i, j, k, ports = getSize ();
141  char * type, * pn, * sn, * snold, * fn, * fnold, * vr;
142  eqn::node * pvalue;
143 
144  // allocate space for equation pointers
145  peqn = (void **) malloc (sizeof (assignment *) * ports * ports);
146 
147  // first create frequency variables
148  sn = createVariable ("S");
149  snold = createVariable ("S", false);
150  fn = createVariable ("F");
151  fnold = createVariable ("F", false);
152  seqn = getEnv()->getChecker()->addComplex ("#laplace", sn, rect (0, 0));
153  feqn = getEnv()->getChecker()->addDouble ("#frequency", fn, 0);
154  A(seqn)->evalType (); A(seqn)->skip = 1;
155  A(feqn)->evalType (); A(feqn)->skip = 1;
156 
157  // obtain type of parameters
158  type = getPropertyString ("Type");
159 
160  // prepare device equations
161  for (k = 0, i = 0; i < ports; i++) {
162  for (j = 0; j < ports; j++, k++) {
163  // find equation referenced in property
164  pn = createVariable ("P", i + 1, j + 1, false);
165  vr = getPropertyReference (pn);
166  pvalue = getEnv()->getChecker()->findEquation (vr);
167  if (!pvalue) {
168  logprint (LOG_ERROR, "ERROR: %s-parameter equation `%s' not found for "
169  "RFEDD `%s'\n", type, vr, getName ());
170  }
171  else {
172  // replace references to S and F by local references
173  pvalue->replace (snold, sn);
174  pvalue->replace (fnold, fn);
175  // evaluate types of parameters
176  A(pvalue)->evalType ();
177  A(pvalue)->skip = 1;
178  }
179  // save equations for parameters
180  peqn[k] = pvalue;
181  free (pn);
182  }
183  }
184 
185  free (sn); free (snold);
186  free (fn); free (fnold);
187 }
188 
189 // Prepares model equations if necessary.
190 void rfedd::prepareModel (void) {
191  if (peqn == NULL) initModel ();
192 }
193 
194 // Update local variable equations.
195 void rfedd::updateLocals (nr_double_t frequency) {
196 
197  // update frequency variables for equations
198  setResult (seqn, rect (0, 2 * M_PI * frequency));
199  setResult (feqn, frequency);
200 
201  // get local subcircuit values
202  getEnv()->passConstants ();
203  getEnv()->equationSolver ();
204 }
205 
206 // Callback for DC analysis.
207 void rfedd::calcDC (void) {
208 }
209 
210 // Initializes MNA representation depending on parameter type.
211 void rfedd::initMNA (void) {
212  int i, ports = getSize ();
213  char * type = getPropertyString ("Type");
214  switch (type[0]) {
215  case 'Y':
216  setVoltageSources (0);
217  allocMatrixMNA ();
218  break;
219  case 'Z':
220  setVoltageSources (ports);
221  allocMatrixMNA ();
222  for (i = 0; i < ports; i++) setC (i, i, -1);
223  for (i = 0; i < ports; i++) setB (i, i, +1);
224  break;
225  case 'S':
226  setVoltageSources (ports);
227  allocMatrixMNA ();
228  for (i = 0; i < ports; i++) setB (i, i, +1);
229  break;
230  case 'H':
231  setVoltageSources (1);
232  allocMatrixMNA ();
233  setB (0, 0, +1); setC (0, 0, -1);
234  break;
235  case 'G':
236  setVoltageSources (1);
237  allocMatrixMNA ();
238  setB (1, 0, +1); setC (0, 1, -1);
239  break;
240  case 'A':
241  setVoltageSources (1);
242  allocMatrixMNA ();
243  setB (1, 0, -1); setC (0, 0, -1);
244  break;
245  case 'T':
246  setVoltageSources (2);
247  allocMatrixMNA ();
248  setB (0, 0, +1); setB (1, 1, +1);
249  setC (0, 0, -1); setC (1, 0, -1);
250  break;
251  }
252 }
253 
254 // Calculates MNA representation depending on parameter type.
255 void rfedd::calcMNA (nr_double_t frequency) {
256  char * type = getPropertyString ("Type");
257  int r, c, ports = getSize ();
258  matrix p = calcMatrix (frequency);
259  switch (type[0]) {
260  case 'Y':
261  setMatrixY (p);
262  break;
263  case 'Z':
264  for (r = 0; r < ports; r++)
265  for (c = 0; c < ports; c++)
266  setD (r, c, p (r, c));
267  break;
268  case 'S':
269  for (r = 0; r < ports; r++)
270  for (c = 0; c < ports; c++) {
271  if (r == c) {
272  setC (r, c, p (r, c) - 1.0);
273  setD (r, c, z0 * (p (r, c) + 1.0));
274  }
275  else {
276  setC (r, c, p (r, c));
277  setD (r, c, z0 * p (r, c));
278  }
279  }
280  break;
281  case 'H':
282  setY (1, 1, p (1, 1)); setB (1, 0, p (1, 0));
283  setC (0, 1, p (0, 1)); setD (0, 0, p (0, 0));
284  break;
285  case 'G':
286  setY (0, 0, p (0, 0)); setB (0, 0, p (0, 1));
287  setC (0, 0, p (1, 0)); setD (0, 0, p (1, 1));
288  break;
289  case 'A':
290  setY (0, 1, p (1, 0)); setB (0, 0, p (1, 1));
291  setC (0, 1, p (0, 0)); setD (0, 0, p (0, 1));
292  break;
293  case 'T':
294  setC (0, 1, p (0, 1) + p (0, 0));
295  setC (1, 1, p (1, 1) + p (1, 0));
296  setD (0, 0, -z0);
297  setD (1, 0, +z0);
298  setD (0, 1, z0 * (p (0, 1) - p (0, 0)));
299  setD (1, 1, z0 * (p (1, 1) - p (1, 0)));
300  break;
301  }
302 }
303 
304 // Callback for initializing the AC analysis.
305 void rfedd::initAC (void) {
306  initMNA ();
307  prepareModel ();
308 }
309 
310 // Callback for AC analysis.
311 void rfedd::calcAC (nr_double_t frequency) {
312  calcMNA (frequency);
313 }
314 
315 // Computes parameter matrix.
316 matrix rfedd::calcMatrix (nr_double_t frequency) {
317  int i, j, k, ports = getSize ();
318  matrix p (ports);
319 
320  // update local equations
321  updateLocals (frequency);
322 
323  // calculate parameters and put into Jacobian
324  for (k = 0, i = 0; i < ports; i++) {
325  for (j = 0; j < ports; j++, k++) {
326  p (i, j) = getResult (peqn[k]);
327  }
328  }
329 
330  return p;
331 }
332 
333 // Callback for initializing the TR analysis.
334 void rfedd::initTR (void) {
335  initDC ();
336 }
337 
338 // Callback for the TR analysis.
339 void rfedd::calcTR (nr_double_t) {
340  calcDC ();
341 }
342 
343 // Callback for initializing the S-parameter analysis.
344 void rfedd::initSP (void) {
345  allocMatrixS ();
346  prepareModel ();
347 }
348 
349 // Callback for S-parameter analysis.
350 void rfedd::calcSP (nr_double_t frequency) {
351  char * type = getPropertyString ("Type");
352  matrix p = calcMatrix (frequency);
353  switch (type[0]) {
354  case 'Y':
355  setMatrixS (ytos (p));
356  break;
357  case 'Z':
358  setMatrixS (ztos (p));
359  break;
360  case 'S':
361  setMatrixS (p);
362  break;
363  case 'H':
364  setMatrixS (twoport (p, 'H', 'S'));
365  break;
366  case 'G':
367  setMatrixS (twoport (p, 'G', 'S'));
368  break;
369  case 'A':
370  setMatrixS (twoport (p, 'A', 'S'));
371  break;
372  case 'T':
373  setMatrixS (twoport (p, 'T', 'S'));
374  break;
375  }
376 }
377 
378 // properties
379 PROP_REQ [] = {
380  { "Type", PROP_STR, { PROP_NO_VAL, "Y" },
381  PROP_RNG_STR7 ("Y", "Z", "S", "H", "G", "A", "T") },
382  { "duringDC", PROP_STR, { PROP_NO_VAL, "open" },
383  PROP_RNG_STR4 ("open", "short", "unspecified", "zerofrequency") },
384  { "P11", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
385  PROP_NO_PROP };
386 PROP_OPT [] = {
387  { "P12", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
388  { "P13", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
389  { "P14", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
390  { "P15", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
391  { "P16", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
392  { "P17", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
393  { "P18", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
394  { "P21", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
395  { "P22", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
396  { "P23", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
397  { "P24", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
398  { "P25", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
399  { "P26", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
400  { "P27", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
401  { "P28", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
402  { "P31", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
403  { "P32", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
404  { "P33", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
405  { "P34", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
406  { "P35", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
407  { "P36", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
408  { "P37", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
409  { "P38", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
410  { "P41", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
411  { "P42", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
412  { "P43", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
413  { "P44", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
414  { "P45", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
415  { "P46", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
416  { "P47", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
417  { "P48", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
418  { "P51", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
419  { "P52", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
420  { "P53", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
421  { "P54", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
422  { "P55", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
423  { "P56", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
424  { "P57", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
425  { "P58", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
426  { "P61", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
427  { "P62", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
428  { "P63", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
429  { "P64", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
430  { "P65", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
431  { "P66", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
432  { "P67", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
433  { "P68", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
434  { "P71", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
435  { "P72", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
436  { "P73", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
437  { "P74", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
438  { "P75", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
439  { "P76", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
440  { "P77", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
441  { "P78", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
442  { "P81", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
443  { "P82", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
444  { "P83", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
445  { "P84", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
446  { "P85", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
447  { "P86", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
448  { "P87", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
449  { "P88", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
450  PROP_NO_PROP };
451 struct define_t rfedd::cirdef =
452  { "RFEDD",