Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
eqndefined.cpp
Go to the documentation of this file.
1 /*
2  * eqndefined.cpp - equation defined device class implementation
3  *
4  * Copyright (C) 2007 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 "equation.h"
31 #include "environment.h"
32 #include "device.h"
33 #include "eqndefined.h"
34 
35 using namespace qucs;
36 using namespace qucs::eqn;
37 
38 // Constructor for the equation defined device.
39 eqndefined::eqndefined () : circuit () {
41  setVariableSized (true);
42  veqn = NULL;
43  ieqn = NULL;
44  qeqn = NULL;
45  geqn = NULL;
46  ceqn = NULL;
47  _jstat = NULL;
48  _jdyna = NULL;
49  _charges = NULL;
50 }
51 
52 // Destructor deletes equation defined device object from memory.
54  if (veqn) free (veqn);
55  if (ieqn) free (ieqn);
56  if (geqn) free (geqn);
57  if (qeqn) free (qeqn);
58  if (ceqn) free (ceqn);
59  if (_jstat) free (_jstat);
60  if (_jdyna) free (_jdyna);
61  if (_charges) free (_charges);
62 }
63 
64 // Callback for initializing the DC analysis.
65 void eqndefined::initDC (void) {
66  allocMatrixMNA ();
67  if (ieqn == NULL) initModel ();
68  doHB = false;
69 }
70 
71 // Some help macros.
72 #define A(a) ((assignment *) (a))
73 #define C(c) ((constant *) (c))
74 #define BP(n) real (getV (n * 2 + 0) - getV (n * 2 + 1))
75 
76 // Creates a variable name from the given arguments.
77 char * eqndefined::createVariable (const char * base, int n, bool pfx) {
78  char * str = strchr (getName (), '.');
79  if (str != NULL)
80  str = strrchr (str, '.') + 1;
81  else
82  str = getName ();
83  char * txt = (char *) malloc (strlen (str) + strlen (base) + 3);
84  if (pfx)
85  sprintf (txt, "%s.%s%d", str, base, n);
86  else
87  sprintf (txt, "%s%d", base, n);
88  return txt;
89 }
90 
91 // Creates also a variable name from the given arguments.
92 char * eqndefined::createVariable (const char * base, int r, int c, bool pfx) {
93  char * str = strchr (getName (), '.');
94  if (str != NULL)
95  str = strrchr (str, '.') + 1;
96  else
97  str = getName ();
98  char * txt = (char *) malloc (strlen (str) + strlen (base) + 4);
99  if (pfx)
100  sprintf (txt, "%s.%s%d%d", str, base, r, c);
101  else
102  sprintf (txt, "%s%d%d", base, r, c);
103  return txt;
104 }
105 
106 // Saves the given value into the equation result.
107 void eqndefined::setResult (void * eqn, nr_double_t val) {
108  A(eqn)->evaluate ();
109  constant * c = A(eqn)->getResult ();
110  c->d = val;
111 }
112 
113 // Returns the result of the equation.
114 nr_double_t eqndefined::getResult (void * eqn) {
115  A(eqn)->evaluate ();
116  return A(eqn)->getResultDouble ();
117 }
118 
119 // Initializes the equation defined device.
121  int i, j, k, branches = getSize () / 2;
122  char * in, * qn, * vn, * gn, * cn, * vnold, * inold;
123  eqn::node * ivalue, * qvalue, * diff;
124 
125  // allocate space for equation pointers
126  veqn = (void **) malloc (sizeof (assignment *) * branches);
127  ieqn = (void **) malloc (sizeof (assignment *) * branches);
128  geqn = (void **) malloc (sizeof (assignment *) * branches * branches);
129  qeqn = (void **) malloc (sizeof (assignment *) * branches);
130  ceqn = (void **) malloc (sizeof (assignment *) * branches * branches);
131 
132  // allocate space for Jacobians and charges
133  _jstat = (nr_double_t *) malloc (sizeof (nr_double_t) * branches * branches);
134  _jdyna = (nr_double_t *) malloc (sizeof (nr_double_t) * branches * branches);
135  _charges = (nr_double_t *) malloc (sizeof (nr_double_t) * branches);
136 
137  // first create voltage variables
138  for (i = 0; i < branches; i++) {
139  vn = createVariable ("V", i + 1);
140  if ((veqn[i] = getEnv()->getChecker()->findEquation (vn)) == NULL) {
141  veqn[i] = getEnv()->getChecker()->addDouble ("#voltage", vn, 0);
142  A(veqn[i])->evalType ();
143  A(veqn[i])->skip = 1;
144  }
145  free (vn);
146  }
147 
148  // prepare current and charge equations
149  for (i = 0; i < branches; i++) {
150 
151  // fetch current and charge equations
152  in = createVariable ("I", i + 1);
153  ivalue = getEnv()->getChecker()->findEquation (in);
154  if (!ivalue) {
155  logprint (LOG_ERROR, "ERROR: current equation `%s' not found for "
156  "EDD `%s'\n", in, getName ());
157  }
158  qn = createVariable ("Q", i + 1);
159  qvalue = getEnv()->getChecker()->findEquation (qn);
160  if (!qvalue) {
161  logprint (LOG_ERROR, "ERROR: charge equation `%s' not found for "
162  "EDD `%s'\n", qn, getName ());
163  }
164  free (in);
165  free (qn);
166 
167  // replace voltage and current references
168  for (j = 0; j < branches; j++) {
169  in = createVariable ("I", j + 1);
170  inold = createVariable ("I", j + 1, false);
171  vn = createVariable ("V", j + 1);
172  vnold = createVariable ("V", j + 1, false);
173  if (ivalue) {
174  ivalue->replace (vnold, vn);
175  ivalue->replace (inold, in);
176  }
177  if (qvalue) {
178  qvalue->replace (vnold, vn);
179  qvalue->replace (inold, in);
180  }
181  free (vnold); free (vn);
182  free (inold); free (in);
183  }
184 
185  // setup and save equations for currents and charges
186  ieqn[i] = ivalue;
187  qeqn[i] = qvalue;
188  }
189 
190  // evaluate types of currents and charges
191  for (i = 0; i < branches; i++) {
192  if (ieqn[i]) { A(ieqn[i])->evalType (); A(ieqn[i])->skip = 1; }
193  if (qeqn[i]) { A(qeqn[i])->evalType (); A(qeqn[i])->skip = 1; }
194  }
195 
196  // create derivatives of currents
197  for (k = 0, i = 0; i < branches; i++) {
198  ivalue = A(ieqn[i]);
199 
200  // create "static" differentiations
201  for (j = 0; j < branches; j++, k++) {
202  vn = createVariable ("V", j + 1);
203 
204  // create conductance equations
205  if (ivalue) {
206  gn = createVariable ("G", i + 1, j + 1);
207  if ((geqn[k] = getEnv()->getChecker()->findEquation (gn)) == NULL) {
208  diff = ivalue->differentiate (vn);
209  getEnv()->getChecker()->addEquation (diff);
210  diff->evalType ();
211  diff->skip = 1;
212  geqn[k] = diff;
213  A(diff)->rename (gn);
214  }
215  free (gn);
216 #if DEBUG
217  logprint (LOG_STATUS, "DEBUG: %s\n", A(geqn[k])->toString ());
218 #endif
219  }
220  else geqn[k] = NULL;
221 
222  free (vn);
223  }
224  }
225 
226  // create derivatives of charges
227  for (k = 0, i = 0; i < branches; i++) {
228  qvalue = A(qeqn[i]);
229 
230  // create "dynamic" differentiations
231  for (j = 0; j < branches; j++, k++) {
232  vn = createVariable ("V", j + 1);
233 
234  // create capacitance equations
235  if (qvalue) {
236  cn = createVariable ("C", i + 1, j + 1);
237  if ((ceqn[k] = getEnv()->getChecker()->findEquation (cn)) == NULL) {
238  diff = qvalue->differentiate (vn);
239  getEnv()->getChecker()->addEquation (diff);
240  diff->evalType ();
241  ceqn[k] = diff;
242  A(diff)->rename (cn);
243 
244  // apply dQ/dI * dI/dV => dQ/dV derivatives
245  for (int l = 0; l < branches; l++) {
246  in = createVariable ("I", l + 1);
247  diff = qvalue->differentiate (in);
248  A(diff)->mul (A(geqn[l * branches + j]));
249  A(ceqn[k])->add (A(diff));
250  delete diff;
251  free (in);
252  }
253  A(ceqn[k])->evalType ();
254  A(ceqn[k])->skip = 1;
255  }
256  free (cn);
257 #if DEBUG
258  logprint (LOG_STATUS, "DEBUG: %s\n", A(ceqn[k])->toString ());
259 #endif
260  }
261  else ceqn[k] = NULL;
262 
263  free (vn);
264  }
265  }
266 }
267 
268 // Update local variable equations.
270  int i, branches = getSize () / 2;
271 
272  // update voltages for equations
273  for (i = 0; i < branches; i++) {
274  setResult (veqn[i], BP (i));
275  }
276  // get local subcircuit values
277  getEnv()->passConstants ();
278  getEnv()->equationSolver ();
279 }
280 
281 // Callback for DC analysis.
282 void eqndefined::calcDC (void) {
283  int i, j, k, branches = getSize () / 2;
284 
285  // update local equations
286  updateLocals ();
287 
288  // calculate currents and put into right-hand side
289  for (i = 0; i < branches; i++) {
290  nr_double_t c = getResult (ieqn[i]);
291  setI (i * 2 + 0, -c);
292  setI (i * 2 + 1, +c);
293  }
294 
295  // calculate derivatives and put into Jacobian and right-hand side
296  for (k = 0, i = 0; i < branches; i++) {
297  nr_double_t gv = 0;
298  // usual G (dI/dV) entries
299  for (j = 0; j < branches; j++, k++) {
300  nr_double_t g = getResult (geqn[k]);
301  setY (i * 2 + 0, j * 2 + 0, +g);
302  setY (i * 2 + 1, j * 2 + 1, +g);
303  setY (i * 2 + 0, j * 2 + 1, -g);
304  setY (i * 2 + 1, j * 2 + 0, -g);
305  gv += g * BP (j);
306  }
307  // during HB
308  if (doHB) {
309  setGV (i * 2 + 0, +gv);
310  setGV (i * 2 + 1, -gv);
311  }
312  // DC and transient analysis
313  else {
314  addI (i * 2 + 0, +gv);
315  addI (i * 2 + 1, -gv);
316  }
317  }
318 }
319 
320 // Evaluate operating points.
322  int i, j, k, branches = getSize () / 2;
323 
324  // save values for charges, conductances and capacitances
325  for (k = 0, i = 0; i < branches; i++) {
326  nr_double_t q = getResult (qeqn[i]);
327  _charges[i] = q;
328  for (j = 0; j < branches; j++, k++) {
329  nr_double_t g = getResult (geqn[k]);
330  _jstat[k] = g;
331  nr_double_t c = getResult (ceqn[k]);
332  _jdyna[k] = c;
333  }
334  }
335 }
336 
337 // Saves operating points.
339 
340  // update local equations
341  updateLocals ();
342 
343  // save values for charges, conductances and capacitances
344  evalOperatingPoints ();
345 }
346 
347 // Callback for initializing the AC analysis.
348 void eqndefined::initAC (void) {
349  allocMatrixMNA ();
350  doHB = false;
351 }
352 
353 // Callback for AC analysis.
354 void eqndefined::calcAC (nr_double_t frequency) {
355  setMatrixY (calcMatrixY (frequency));
356 }
357 
358 // Computes Y-matrix for AC analysis.
359 matrix eqndefined::calcMatrixY (nr_double_t frequency) {
360  int i, j, k, branches = getSize () / 2;
361  matrix y (2 * branches);
362  nr_double_t o = 2 * M_PI * frequency;
363 
364  // merge conductances and capacitances
365  for (k = 0, i = 0; i < branches; i++) {
366  for (j = 0; j < branches; j++, k++) {
367  int r = i * 2;
368  int c = j * 2;
369  nr_complex_t val = nr_complex_t (_jstat[k], o * _jdyna[k]);
370  y (r + 0, c + 0) = +val;
371  y (r + 1, c + 1) = +val;
372  y (r + 0, c + 1) = -val;
373  y (r + 1, c + 0) = -val;
374  }
375  }
376 
377  return y;
378 }
379 
380 // Callback for initializing the TR analysis.
381 void eqndefined::initTR (void) {
382  int branches = getSize () / 2;
383  setStates (2 * branches);
384  initDC ();
385 }
386 
387 // Callback for the TR analysis.
388 void eqndefined::calcTR (nr_double_t) {
389  int state, i, j, k, branches = getSize () / 2;
390 
391  // run usual DC iteration, then save operating points
392  calcDC ();
393 
394  // calculate Q and C
395  evalOperatingPoints ();
396 
397  // charge integrations
398  for (i = 0; i < branches; i++) {
399  int r = i * 2;
400  state = 2 * i;
401  transientCapacitanceQ (state, r + 0, r + 1, _charges[i]);
402  }
403 
404  // charge: 2-node, voltage: 2-node
405  for (k = 0, i = 0; i < branches; i++) {
406  for (j = 0; j < branches; j++, k++) {
407  int r = i * 2;
408  int c = j * 2;
409  nr_double_t v = BP (j);
410  transientCapacitanceC (r + 0, r + 1, c + 0, c + 1, _jdyna[k], v);
411  }
412  }
413 }
414 
415 // Callback for initializing the S-parameter analysis.
416 void eqndefined::initSP (void) {
417  allocMatrixS ();
418  doHB = false;
419 }
420 
421 // Callback for S-parameter analysis.
422 void eqndefined::calcSP (nr_double_t frequency) {
423  setMatrixS (ytos (calcMatrixY (frequency)));
424 }
425 
426 // Callback for initializing the HB analysis.
427 void eqndefined::initHB (int) {
428  allocMatrixHB ();
429  if (ieqn == NULL) initModel ();
430  doHB = true;
431 }
432 
433 // Callback for HB analysis.
434 void eqndefined::calcHB (int) {
435  int i, j, k, branches = getSize () / 2;
436 
437  // G's (dI/dV) into Y-Matrix and I's into I-Vector
438  calcDC ();
439 
440  // calculate Q and C
441  evalOperatingPoints ();
442 
443  // setup additional charge right-hand side
444  for (i = 0; i < branches; i++) {
445  setQ (i * 2 + 0, -_charges[i]);
446  setQ (i * 2 + 1, +_charges[i]);
447  }
448 
449  // fill in C's (dQ/dV) in QV-Matrix and CV into right hand side
450  for (k = 0, i = 0; i < branches; i++) {
451  nr_double_t cv = 0;
452  for (j = 0; j < branches; j++, k++) {
453  int r = i * 2;
454  int c = j * 2;
455  nr_double_t val = _jdyna[k];
456  setQV (r + 0, c + 0, +val);
457  setQV (r + 1, c + 1, +val);
458  setQV (r + 0, c + 1, -val);
459  setQV (r + 1, c + 0, -val);
460  cv += val * BP (j);
461  }
462  setCV (i * 2 + 0, +cv);
463  setCV (i * 2 + 1, -cv);
464  }
465 }
466 
467 // properties
468 PROP_REQ [] = {
469  { "I1", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
470  { "Q1", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
471  PROP_NO_PROP };
472 PROP_OPT [] = {
473  { "I2", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
474  { "Q2", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
475  { "I3", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
476  { "Q3", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
477  { "I4", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
478  { "Q4", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
479  { "I5", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
480  { "Q5", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
481  { "I6", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
482  { "Q6", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
483  { "I7", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
484  { "Q7", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
485  { "I8", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
486  { "Q8", PROP_REAL, { 0, PROP_NO_STR }, PROP_NO_RANGE },
487  PROP_NO_PROP };
488 struct define_t eqndefined::cirdef =
489  { "EDD",
std::complex< nr_double_t > nr_complex_t
Definition: complex.h:31
void updateLocals(void)
Definition: eqndefined.cpp:269
void initDC(void)
Definition: eqndefined.cpp:65
l
Definition: parse_vcd.y:213
matrix ytos(matrix y, qucs::vector z0)
Admittance matrix to scattering parameters.
Definition: matrix.cpp:1133
#define BP(n)
Definition: eqndefined.cpp:74
void calcHB(int)
Definition: eqndefined.cpp:434
void initTR(void)
Definition: eqndefined.cpp:381
#define PROP_DEF
Definition: netdefs.h:189
void calcTR(nr_double_t)
Definition: eqndefined.cpp:388
PROP_OPT[]
Definition: acsolver.cpp:232
#define PROP_REAL
Definition: netdefs.h:174
void calcSP(nr_double_t)
Definition: eqndefined.cpp:422
#define PROP_NO_PROP
Definition: netdefs.h:122
#define PROP_NO_RANGE
Definition: netdefs.h:126
#define PROP_NO_STR
Definition: netdefs.h:125
n
Definition: parse_citi.y:147
r
Definition: parse_mdl.y:515
#define PROP_NODES
Definition: netdefs.h:121
void calcDC(void)
Definition: eqndefined.cpp:282
i
Definition: parse_mdl.y:516
void calcAC(nr_double_t)
Definition: eqndefined.cpp:354
qucs::matrix calcMatrixY(nr_double_t)
Definition: eqndefined.cpp:359
void setResult(void *, nr_double_t)
Definition: eqndefined.cpp:107
#define PROP_COMPONENT
Definition: netdefs.h:116
free($1)
nr_double_t d
Definition: equation.h:169
nr_double_t getResult(void *)
Definition: eqndefined.cpp:114
#define M_PI
Archimedes' constant ( )
Definition: consts.h:47
void initModel(void)
Definition: eqndefined.cpp:120
void evalOperatingPoints(void)
Definition: eqndefined.cpp:321
type
Definition: parse_vcd.y:164
vector diff(vector, vector, int n=1)
Definition: vector.cpp:591
void initSP(void)
placehoder for S-Parameter initialisation function
Definition: eqndefined.cpp:416
v
Definition: parse_zvr.y:141
void saveOperatingPoints(void)
Definition: eqndefined.cpp:338
#define A(a)
Definition: eqndefined.cpp:72
virtual void initHB(void)
Definition: circuit.h:124
y
Definition: parse_mdl.y:499
The environment class definition.
#define strchr
Definition: compat.h:33
#define LOG_ERROR
Definition: logging.h:28
node
#define LOG_STATUS
Definition: logging.h:29
PROP_REQ[]
Definition: acsolver.cpp:229
void initAC(void)
Definition: eqndefined.cpp:348
void logprint(int level, const char *format,...)
Definition: logging.c:37
#define strrchr
Definition: compat.h:34
char * createVariable(const char *, int, int, bool prefix=true)
Definition: eqndefined.cpp:92
#define PROP_NO_SUBSTRATE
Definition: netdefs.h:118