My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
circuit.cpp
Go to the documentation of this file.
1 /*
2  * circuit.cpp - circuit class implementation
3  *
4  * Copyright (C) 2003, 2004, 2005, 2006, 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: circuit.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 <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 
34 #include "logging.h"
35 #include "complex.h"
36 #include "object.h"
37 #include "matrix.h"
38 #include "node.h"
39 #include "property.h"
40 #include "valuelist.h"
41 #include "tvector.h"
42 #include "history.h"
43 #include "circuit.h"
44 #include "microstrip/substrate.h"
45 #include "operatingpoint.h"
46 #include "characteristic.h"
47 #include "component_id.h"
48 
49 // normalising impedance
50 const nr_double_t circuit::z0 = 50.0;
51 
52 // Constructor creates an unnamed instance of the circuit class.
54  size = 0;
55  MatrixN = MatrixS = MatrixY = NULL;
56  MatrixB = MatrixC = MatrixD = NULL;
57  VectorQ = VectorE = VectorI = VectorV = VectorJ = NULL;
58  MatrixQV = NULL;
59  VectorCV = VectorGV = NULL;
60  nodes = NULL;
61  pacport = 0;
62  pol = 1;
64  subst = NULL;
65  vsource = -1;
66  vsources = 0;
67  nsources = 0;
68  inserted = -1;
69  subcircuit = NULL;
70  subnet = NULL;
71  deltas = NULL;
72  histories = NULL;
73  nHistories = 0;
74  type = CIR_UNKNOWN;
75 }
76 
77 /* Constructor creates an unnamed instance of the circuit class with a
78  certain number of ports. */
80  assert (s >= 0);
81  size = s;
82  if (size > 0) nodes = new node[s];
83  MatrixN = MatrixS = MatrixY = NULL;
84  MatrixB = MatrixC = MatrixD = NULL;
85  VectorQ = VectorE = VectorI = VectorV = VectorJ = NULL;
86  MatrixQV = NULL;
87  VectorCV = VectorGV = NULL;
88  pacport = 0;
89  pol = 1;
91  subst = NULL;
92  vsource = -1;
93  vsources = 0;
94  nsources = 0;
95  inserted = -1;
96  subcircuit = NULL;
97  subnet = NULL;
98  deltas = NULL;
99  histories = NULL;
100  nHistories = 0;
101  type = CIR_UNKNOWN;
102 }
103 
104 /* The copy constructor creates a new instance based on the given
105  circuit object. */
107  size = c.size;
108  pol = c.pol;
109  pacport = c.pacport;
110  flag = c.flag;
111  type = c.type;
112  subst = c.subst;
113  vsource = c.vsource;
114  vsources = c.vsources;
115  nsources = c.nsources;
116  inserted = c.inserted;
117  subnet = c.subnet;
118  deltas = c.deltas;
119  nHistories = c.nHistories;
120  histories = NULL;
121  subcircuit = c.subcircuit ? strdup (c.subcircuit) : NULL;
122 
123  if (size > 0) {
124  // copy each node and set its circuit to the current circuit object
125  nodes = new node[size];
126  for (int i = 0; i < size; i++) {
127  nodes[i] = node (c.nodes[i]);;
128  nodes[i].setCircuit (this);
129  }
130  // copy each s-parameter
131  if (c.MatrixS) {
132  allocMatrixS ();
133  memcpy (MatrixS, c.MatrixS, size * size * sizeof (nr_complex_t));
134  }
135  // copy each noise-correlation parameter
136  if (c.MatrixN) {
137  allocMatrixN (nsources);
138  int i = size + nsources;
139  memcpy (MatrixN, c.MatrixN, i * i * sizeof (nr_complex_t));
140  }
141  // copy each HB-matrix entry
142  if (c.MatrixQV) {
143  allocMatrixHB ();
144  memcpy (MatrixQV, c.MatrixQV, size * size * sizeof (nr_complex_t));
145  memcpy (VectorGV, c.VectorGV, size * sizeof (nr_complex_t));
146  memcpy (VectorCV, c.VectorCV, size * sizeof (nr_complex_t));
147  memcpy (VectorQ, c.VectorQ, size * sizeof (nr_complex_t));
148  }
149  // copy each G-MNA matrix entry
150  if (c.MatrixY) {
151  allocMatrixMNA ();
152  memcpy (MatrixY, c.MatrixY, size * size * sizeof (nr_complex_t));
153  memcpy (VectorI, c.VectorI, size * sizeof (nr_complex_t));
154  memcpy (VectorV, c.VectorV, size * sizeof (nr_complex_t));
155  if (vsources > 0) {
156  memcpy (MatrixB, c.MatrixB, vsources * size * sizeof (nr_complex_t));
157  memcpy (MatrixC, c.MatrixC, vsources * size * sizeof (nr_complex_t));
158  memcpy (MatrixD, c.MatrixD, vsources * vsources * sizeof (nr_complex_t));
159  memcpy (VectorE, c.VectorE, vsources * sizeof (nr_complex_t));
160  memcpy (VectorJ, c.VectorJ, vsources * sizeof (nr_complex_t));
161  }
162  }
163  }
164  else {
165  nodes = NULL;
166  MatrixS = MatrixN = MatrixY = NULL;
167  MatrixB = MatrixC = MatrixD = NULL;
168  VectorQ = VectorE = VectorI = VectorV = VectorJ = NULL;
169  MatrixQV = NULL;
170  VectorCV = VectorGV = NULL;
171  }
172 
173  // copy operating points
174  oper = valuelist<operatingpoint> (c.oper);
175 }
176 
177 // Destructor deletes a circuit object.
179  if (size > 0) {
180  if (MatrixS) delete[] MatrixS;
181  if (MatrixN) delete[] MatrixN;
182  freeMatrixMNA ();
183  freeMatrixHB ();
184  delete[] nodes;
185  }
186  if (subcircuit) free (subcircuit);
187  deleteHistory ();
188 }
189 
190 /* With this function the number of ports of the circuit object can be
191  changed. Previously stored node and matrix information gets
192  completely lost except the current size equals the given size. */
193 void circuit::setSize (int s) {
194  // nothing to do here
195  if (size == s) return;
196  assert (s >= 0);
197 
198  if (size > 0) {
199  // destroy any matrix and node information
200  if (MatrixS) delete[] MatrixS;
201  if (MatrixN) delete[] MatrixN;
202  MatrixS = MatrixN = NULL;
203  freeMatrixMNA ();
204  delete[] nodes; nodes = NULL;
205  }
206 
207  if ((size = s) > 0) {
208  // re-create matrix and node information space
209  nodes = new node[size];
210  allocMatrixS ();
211  allocMatrixN (nsources);
212  allocMatrixMNA ();
213  }
214 }
215 
216 /* Destroys the HB-matrix memory. */
218  if (VectorQ) { delete[] VectorQ; VectorQ = NULL; }
219  if (MatrixQV) { delete[] MatrixQV; MatrixQV = NULL; }
220  if (VectorCV) { delete[] VectorCV; VectorCV = NULL; }
221  if (VectorGV) { delete[] VectorGV; VectorGV = NULL; }
222 }
223 
224 /* Allocates the HB-matrix memory. */
226  if (VectorQ) {
227  memset (VectorQ, 0, size * sizeof (nr_complex_t));
228  } else {
229  VectorQ = new nr_complex_t[size];
230  }
231  if (MatrixQV) {
232  memset (MatrixQV, 0, size * size * sizeof (nr_complex_t));
233  } else {
234  MatrixQV = new nr_complex_t[size * size];
235  }
236  if (VectorCV) {
237  memset (VectorCV, 0, size * sizeof (nr_complex_t));
238  } else {
239  VectorCV = new nr_complex_t[size];
240  }
241  if (VectorGV) {
242  memset (VectorGV, 0, size * sizeof (nr_complex_t));
243  } else {
244  VectorGV = new nr_complex_t[size];
245  }
246 }
247 
248 /* Allocates the S-parameter matrix memory. */
250  if (MatrixS) {
251  memset (MatrixS, 0, size * size * sizeof (nr_complex_t));
252  } else {
253  MatrixS = new nr_complex_t[size * size];
254  }
255 }
256 
257 /* Allocates the noise correlation matrix memory. */
258 void circuit::allocMatrixN (int sources) {
259  nsources = sources;
260  if (MatrixN) delete[] MatrixN;
261  MatrixN = new nr_complex_t[(size + sources) * (size + sources)];
262 }
263 
264 /* Allocates the matrix memory for the MNA matrices. */
266  freeMatrixMNA ();
267  if (size > 0) {
268  MatrixY = new nr_complex_t[size * size];
269  VectorI = new nr_complex_t[size];
270  VectorV = new nr_complex_t[size];
271  if (vsources > 0) {
272  MatrixB = new nr_complex_t[vsources * size];
273  MatrixC = new nr_complex_t[vsources * size];
274  MatrixD = new nr_complex_t[vsources * vsources];
275  VectorE = new nr_complex_t[vsources];
276  VectorJ = new nr_complex_t[vsources];
277  }
278  }
279 }
280 
281 /* Free()'s all memory used by the MNA matrices. */
283  if (MatrixY) { delete[] MatrixY; MatrixY = NULL; }
284  if (MatrixB) { delete[] MatrixB; MatrixB = NULL; }
285  if (MatrixC) { delete[] MatrixC; MatrixC = NULL; }
286  if (MatrixD) { delete[] MatrixD; MatrixD = NULL; }
287  if (VectorE) { delete[] VectorE; VectorE = NULL; }
288  if (VectorI) { delete[] VectorI; VectorI = NULL; }
289  if (VectorV) { delete[] VectorV; VectorV = NULL; }
290  if (VectorJ) { delete[] VectorJ; VectorJ = NULL; }
291 }
292 
293 /* This function sets the name and port number of one of the circuit's
294  nodes. It also tells the appropriate node about the circuit it
295  belongs to. The optional 'intern' argument is used to mark a node
296  to be for internal use only. */
297 void circuit::setNode (int i, const char * n, int intern) {
298  nodes[i].setName (n);
299  nodes[i].setCircuit (this);
300  nodes[i].setPort (i);
301  nodes[i].setInternal (intern);
302 }
303 
304 // Returns one of the circuit's nodes.
306  return &nodes[i];
307 }
308 
309 // Sets the subcircuit reference for the circuit object.
310 void circuit::setSubcircuit (char * n) {
311  if (subcircuit) free (subcircuit);
312  subcircuit = n ? strdup (n) : NULL;
313 }
314 
315 #if DEBUG
316 // DEBUG function: Prints the S parameters of this circuit object.
317 void circuit::print (void) {
318  for (int i = 0; i < getSize (); i++) {
319  for (int j = 0; j < getSize (); j++) {
320  logprint (LOG_STATUS, "%s S%d%d(%+.3e,%+.3e) ", getName (), i, j,
321  (double) real (getS (i, j)), (double) imag (getS (i, j)));
322  }
323  logprint (LOG_STATUS, "\n");
324  }
325 }
326 #endif /* DEBUG */
327 
328 /* Returns the current substrate of the circuit object. Used for
329  microstrip components only. */
331  return subst;
332 }
333 
334 // Sets the substrate of the circuit object.
336  subst = s;
337 }
338 
339 /* Returns the circuits B-MNA matrix value of the given voltage source
340  built in the circuit depending on the port number. */
341 nr_complex_t circuit::getB (int port, int nr) {
342  return MatrixB[(nr - vsource) * size + port];
343 }
344 
345 /* Sets the circuits B-MNA matrix value of the given voltage source
346  built in the circuit depending on the port number. */
347 void circuit::setB (int port, int nr, nr_complex_t z) {
348  MatrixB[nr * size + port] = z;
349 }
350 
351 /* Returns the circuits C-MNA matrix value of the given voltage source
352  built in the circuit depending on the port number. */
353 nr_complex_t circuit::getC (int nr, int port) {
354  return MatrixC[(nr - vsource) * size + port];
355 }
356 
357 /* Sets the circuits C-MNA matrix value of the given voltage source
358  built in the circuit depending on the port number. */
359 void circuit::setC (int nr, int port, nr_complex_t z) {
360  MatrixC[nr * size + port] = z;
361 }
362 
363 /* Returns the circuits D-MNA matrix value of the given voltage source
364  built in the circuit. */
366  return MatrixD[(r - vsource) * vsources + c - vsource];
367 }
368 
369 /* Sets the circuits D-MNA matrix value of the given voltage source
370  built in the circuit. */
371 void circuit::setD (int r, int c, nr_complex_t z) {
372  MatrixD[r * vsources + c] = z;
373 }
374 
375 /* Returns the circuits E-MNA matrix value of the given voltage source
376  built in the circuit. */
378  return VectorE[nr - vsource];
379 }
380 
381 /* Sets the circuits E-MNA matrix value of the given voltage source
382  built in the circuit. */
383 void circuit::setE (int nr, nr_complex_t z) {
384  VectorE[nr] = z;
385 }
386 
387 /* Returns the circuits I-MNA matrix value of the current source built
388  in the circuit. */
390  return VectorI[port];
391 }
392 
393 /* Sets the circuits I-MNA matrix value of the current source built in
394  the circuit depending on the port number. */
395 void circuit::setI (int port, nr_complex_t z) {
396  VectorI[port] = z;
397 }
398 
399 /* Modifies the circuits I-MNA matrix value of the current source
400  built in the circuit depending on the port number. */
401 void circuit::addI (int port, nr_complex_t i) {
402  VectorI[port] += i;
403 }
404 
405 /* Same as above with different argument type. */
406 void circuit::addI (int port, nr_double_t i) {
407  VectorI[port] += i;
408 }
409 
410 /* Returns the circuits Q-HB vector value. */
412  return VectorQ[port];
413 }
414 
415 /* Sets the circuits Q-HB vector value. */
416 void circuit::setQ (int port, nr_complex_t q) {
417  VectorQ[port] = q;
418 }
419 
420 /* Returns the circuits J-MNA matrix value of the given voltage source
421  built in the circuit. */
423  return VectorJ[nr];
424 }
425 
426 /* Sets the circuits J-MNA matrix value of the given voltage source
427  built in the circuit. */
428 void circuit::setJ (int nr, nr_complex_t z) {
429  VectorJ[nr - vsource] = z;
430 }
431 
432 // Returns the circuits voltage value at the given port.
434  return VectorV[port];
435 }
436 
437 // Sets the circuits voltage value at the given port.
438 void circuit::setV (int port, nr_complex_t z) {
439  VectorV[port] = z;
440 }
441 
442 /* Returns the circuits G-MNA matrix value depending on the port
443  numbers. */
445  return MatrixY[r * size + c];
446 }
447 
448 /* Sets the circuits G-MNA matrix value depending on the port
449  numbers. */
450 void circuit::setY (int r, int c, nr_complex_t y) {
451  MatrixY[r * size + c] = y;
452 }
453 
454 /* Modifies the circuits G-MNA matrix value depending on the port
455  numbers. */
456 void circuit::addY (int r, int c, nr_complex_t y) {
457  MatrixY[r * size + c] += y;
458 }
459 
460 /* Same as above with different argument type. */
461 void circuit::addY (int r, int c, nr_double_t y) {
462  MatrixY[r * size + c] += y;
463 }
464 
465 /* Returns the circuits G-MNA matrix value depending on the port
466  numbers. */
467 nr_double_t circuit::getG (int r, int c) {
468  return real (MatrixY[r * size + c]);
469 }
470 
471 /* Sets the circuits G-MNA matrix value depending on the port
472  numbers. */
473 void circuit::setG (int r, int c, nr_double_t y) {
474  MatrixY[r * size + c] = y;
475 }
476 
477 /* Returns the circuits C-HB matrix value depending on the port
478  numbers. */
480  return MatrixQV[r * size + c];
481 }
482 
483 /* Sets the circuits C-HB matrix value depending on the port
484  numbers. */
485 void circuit::setQV (int r, int c, nr_complex_t qv) {
486  MatrixQV[r * size + c] = qv;
487 }
488 
489 /* Returns the circuits GV-HB vector value depending on the port
490  number. */
492  return VectorGV[port];
493 }
494 
495 /* Sets the circuits GV-HB matrix value depending on the port
496  number. */
497 void circuit::setGV (int port, nr_complex_t gv) {
498  VectorGV[port] = gv;
499 }
500 
501 /* Returns the circuits CV-HB vector value depending on the port
502  number. */
504  return VectorCV[port];
505 }
506 
507 /* Sets the circuits CV-HB matrix value depending on the port
508  number. */
509 void circuit::setCV (int port, nr_complex_t cv) {
510  VectorCV[port] = cv;
511 }
512 
513 /* This function adds a operating point consisting of a key and a
514  value to the circuit. */
515 void circuit::addOperatingPoint (const char * n, nr_double_t val) {
516  operatingpoint * p = new operatingpoint (n, val);
517  oper.add (n, p);
518 }
519 
520 /* Returns the requested operating point value which has been
521  previously added as its double representation. If there is no such
522  operating point the function returns zero. */
523 nr_double_t circuit::getOperatingPoint (const char * n) {
524  operatingpoint * p = oper.get (n);
525  if (p != NULL) return p->getValue ();
526  return 0.0;
527 }
528 
529 /* This function sets the operating point specified by the given name
530  to the value passed to the function. */
531 void circuit::setOperatingPoint (const char * n, nr_double_t val) {
532  operatingpoint * p = oper.get (n);
533  if (p != NULL)
534  p->setValue (val);
535  else
536  addOperatingPoint (n, val);
537 }
538 
539 /* The function checks whether the circuit has got a certain operating
540  point value. If so it returns non-zero, otherwise it returns
541  zero. */
543  return (oper.get (n)) ? 1 : 0;
544 }
545 
546 /* This function adds a characteristic point consisting of a key and a
547  value to the circuit. */
548 void circuit::addCharacteristic (const char * n, nr_double_t val) {
549  characteristic * p = new characteristic (n, val);
550  charac.add (n, p);
551 }
552 
553 /* Returns the requested characteristic value which has been
554  previously added as its double representation. If there is no such
555  characteristic value the function returns zero. */
556 nr_double_t circuit::getCharacteristic (char * n) {
557  characteristic * p = charac.get (n);
558  if (p != NULL) return p->getValue ();
559  return 0.0;
560 }
561 
562 /* This function sets the characteristic value specified by the given
563  name to the value passed to the function. */
564 void circuit::setCharacteristic (const char * n, nr_double_t val) {
565  characteristic * p = charac.get (n);
566  if (p != NULL)
567  p->setValue (val);
568  else
569  addCharacteristic (n, val);
570 }
571 
572 /* The function checks whether the circuit has got a certain
573  characteristic value. If so it returns non-zero, otherwise it
574  returns zero. */
576  return (charac.get (n)) ? 1 : 0;
577 }
578 
579 // Returns the S-parameter at the given matrix position.
580 nr_complex_t circuit::getS (int x, int y) {
581  return MatrixS[y + x * size];
582 }
583 
584 // Sets the S-parameter at the given matrix position.
585 void circuit::setS (int x, int y, nr_complex_t z) {
586  MatrixS[y + x * size] = z;
587 }
588 
589 // Returns the noise-correlation-parameter at the given matrix position.
590 nr_complex_t circuit::getN (int r, int c) {
591  return MatrixN[c + r * (size + nsources)];
592 }
593 
594 // Sets the noise-correlation-parameter at the given matrix position.
595 void circuit::setN (int r, int c, nr_complex_t z) {
596  MatrixN[c + r * (size + nsources)] = z;
597 }
598 
599 // Returns the number of internal voltage sources for DC analysis.
601  return vsources;
602 }
603 
604 // Sets the number of internal voltage sources for DC analysis.
606  assert (s >= 0);
607  vsources = s;
608 }
609 
610 // Returns the number of internal noise sources for AC analysis.
612  return nsources;
613 }
614 
615 // Sets the number of internal noise voltage sources for AC analysis.
617  assert (s >= 0);
618  nsources = s;
619 }
620 
621 /* The function returns an internal node or circuit name with the
622  given prefix and based on the given circuits name. The caller is
623  responsible to free() the returned string. */
624 char * circuit::createInternal (const char * prefix, const char * obj) {
625  char * n = (char *) malloc (strlen (prefix) + strlen (obj) + 3);
626  sprintf (n, "_%s#%s", prefix, obj);
627  return n;
628 }
629 
630 /* Creates an internal node given the node number as well as the name
631  suffix. An appropriate node name is constructed from the circuits
632  name and the suffix. */
633 void circuit::setInternalNode (int node, const char * suffix) {
634  char * n = createInternal (getName (), suffix);
635  setNode (node, n, 1);
636  free (n);
637 }
638 
639 /* This function copies the matrix elements inside the given matrix to
640  the internal S-parameter matrix of the circuit. */
642  int r = s.getRows ();
643  int c = s.getCols ();
644  // copy matrix elements
645  if (r > 0 && c > 0 && r * c == size * size) {
646  memcpy (MatrixS, s.getData (), sizeof (nr_complex_t) * r * c);
647  }
648 }
649 
650 /* The function return a matrix containing the S-parameters of the
651  circuit. */
653  matrix res (size);
654  memcpy (res.getData (), MatrixS, sizeof (nr_complex_t) * size * size);
655  return res;
656 }
657 
658 /* This function copies the matrix elements inside the given matrix to
659  the internal noise correlation matrix of the circuit. */
661  int r = n.getRows ();
662  int c = n.getCols ();
663  // copy matrix elements
664  if (r > 0 && c > 0 && r * c == size * size) {
665  memcpy (MatrixN, n.getData (), sizeof (nr_complex_t) * r * c);
666  }
667 }
668 
669 /* The function return a matrix containing the noise correlation
670  matrix of the circuit. */
672  matrix res (size);
673  memcpy (res.getData (), MatrixN, sizeof (nr_complex_t) * size * size);
674  return res;
675 }
676 
677 /* This function copies the matrix elements inside the given matrix to
678  the internal G-MNA matrix of the circuit. */
680  int r = y.getRows ();
681  int c = y.getCols ();
682  // copy matrix elements
683  if (r > 0 && c > 0 && r * c == size * size) {
684  memcpy (MatrixY, y.getData (), sizeof (nr_complex_t) * r * c);
685  }
686 }
687 
688 /* The function return a matrix containing the G-MNA matrix of the
689  circuit. */
691  matrix res (size);
692  memcpy (res.getData (), MatrixY, sizeof (nr_complex_t) * size * size);
693  return res;
694 }
695 
696 // The function cleans up the B-MNA matrix entries.
697 void circuit::clearB (void) {
698  memset (MatrixB, 0, sizeof (nr_complex_t) * size * vsources);
699 }
700 
701 // The function cleans up the C-MNA matrix entries.
702 void circuit::clearC (void) {
703  memset (MatrixC, 0, sizeof (nr_complex_t) * size * vsources);
704 }
705 
706 // The function cleans up the D-MNA matrix entries.
707 void circuit::clearD (void) {
708  memset (MatrixD, 0, sizeof (nr_complex_t) * vsources * vsources);
709 }
710 
711 // The function cleans up the E-MNA matrix entries.
712 void circuit::clearE (void) {
713  memset (VectorE, 0, sizeof (nr_complex_t) * vsources);
714 }
715 
716 // The function cleans up the J-MNA matrix entries.
717 void circuit::clearJ (void) {
718  memset (VectorJ, 0, sizeof (nr_complex_t) * vsources);
719 }
720 
721 // The function cleans up the I-MNA matrix entries.
722 void circuit::clearI (void) {
723  memset (VectorI, 0, sizeof (nr_complex_t) * size);
724 }
725 
726 // The function cleans up the V-MNA matrix entries.
727 void circuit::clearV (void) {
728  memset (VectorV, 0, sizeof (nr_complex_t) * size);
729 }
730 
731 // The function cleans up the G-MNA matrix entries.
732 void circuit::clearY (void) {
733  memset (MatrixY, 0, sizeof (nr_complex_t) * size * size);
734 }
735 
736 /* This function can be used by several components in order to place
737  the n-th voltage source between node 'pos' and node 'neg' with the
738  given value. Remember to indicate this voltage source using the
739  function setVoltageSources(). */
740 void circuit::voltageSource (int n, int pos, int neg, nr_double_t value) {
741  setC (n, pos, +1.0); setC (n, neg, -1.0);
742  setB (pos, n, +1.0); setB (neg, n, -1.0);
743  setD (n, n, 0.0);
744  setE (n, value);
745 }
746 
747 /* The function runs the necessary calculation in order to perform a
748  single integration step of a voltage controlled capacitance placed
749  in between the given nodes. It is assumed that the appropiate
750  charge only depends on the voltage between these nodes. */
751 void circuit::transientCapacitance (int qstate, int pos, int neg,
752  nr_double_t cap, nr_double_t voltage,
753  nr_double_t charge) {
754  nr_double_t g, i;
755  int cstate = qstate + 1;
756  setState (qstate, charge);
757  integrate (qstate, cap, g, i);
758  addY (pos, pos, +g); addY (neg, neg, +g);
759  addY (pos, neg, -g); addY (neg, pos, -g);
760  i = pol * (getState (cstate) - g * voltage);
761  addI (pos , -i);
762  addI (neg , +i);
763 }
764 
765 /* This is the one-node variant of the above function. It performs
766  the same steps for a single node related to ground. */
767 void circuit::transientCapacitance (int qstate, int node, nr_double_t cap,
768  nr_double_t voltage, nr_double_t charge) {
769  nr_double_t g, i;
770  int cstate = qstate + 1;
771  setState (qstate, charge);
772  integrate (qstate, cap, g, i);
773  addY (node, node, +g);
774  i = pol * (getState (cstate) - g * voltage);
775  addI (node , -i);
776 }
777 
778 /* The function performs a single integration step of the given charge
779  located between the given nodes. It saves the current
780  contributions of the charge itself and considers the polarity of
781  the circuit. */
782 void circuit::transientCapacitanceQ (int qstate, int qpos, int qneg,
783  nr_double_t charge) {
784  nr_double_t unused, i;
785  int cstate = qstate + 1;
786  setState (qstate, charge);
787  integrate (qstate, 0, unused, unused);
788  i = pol * getState (cstate);
789  addI (qpos , -i);
790  addI (qneg , +i);
791 }
792 
793 /* This is the one-node variant of the above function. It performs
794  the same steps for a single node related to ground. */
795 void circuit::transientCapacitanceQ (int qstate, int qpos,
796  nr_double_t charge) {
797  nr_double_t unused, i;
798  int cstate = qstate + 1;
799  setState (qstate, charge);
800  integrate (qstate, 0, unused, unused);
801  i = pol * getState (cstate);
802  addI (qpos , -i);
803 }
804 
805 /* This function stores the Jacobian entries due to the C = dQ/dV
806  value. The nodes where the charge is located as well as those of
807  the voltage dependency, the appropiate capacitance value and the
808  voltage across the the controlling branch must be given. It also
809  saves the current contributions which are necessary for the NR
810  iteration and considers the polarity of the circuit. */
811 void circuit::transientCapacitanceC (int qpos, int qneg, int vpos, int vneg,
812  nr_double_t cap, nr_double_t voltage) {
813  nr_double_t g, i;
814  conductor (cap, g);
815  addY (qpos, vpos, +g); addY (qneg, vneg, +g);
816  addY (qpos, vneg, -g); addY (qneg, vpos, -g);
817  i = pol * (g * voltage);
818  addI (qpos , +i);
819  addI (qneg , -i);
820 }
821 
822 /* This is the one-node variant of the transientCapacitanceC()
823  function. It performs the same steps for a single charge node
824  related to ground. */
825 void circuit::transientCapacitanceC2V (int qpos, int vpos, int vneg,
826  nr_double_t cap, nr_double_t voltage) {
827  nr_double_t g, i;
828  conductor (cap, g);
829  addY (qpos, vpos, +g);
830  addY (qpos, vneg, -g);
831  i = pol * (g * voltage);
832  addI (qpos , +i);
833 }
834 
835 /* This is the one-node variant of the transientCapacitanceC()
836  function. It performs the same steps for a single voltage node
837  related to ground. */
838 void circuit::transientCapacitanceC2Q (int qpos, int qneg, int vpos,
839  nr_double_t cap, nr_double_t voltage) {
840  nr_double_t g, i;
841  conductor (cap, g);
842  addY (qpos, vpos, +g); addY (qneg, vpos, -g);
843  i = pol * (g * voltage);
844  addI (qpos , +i);
845  addI (qneg , -i);
846 }
847 
848 /* This is the one-node variant of the transientCapacitanceC()
849  function. It performs the same steps for a single voltage node and
850  charge node related to ground. */
851 void circuit::transientCapacitanceC (int qpos, int vpos,
852  nr_double_t cap, nr_double_t voltage) {
853  nr_double_t g, i;
854  conductor (cap, g);
855  addY (qpos, vpos, +g);
856  i = pol * (g * voltage);
857  addI (qpos , +i);
858 }
859 
860 // The function initializes the histories of a circuit having the given age.
861 void circuit::initHistory (nr_double_t age) {
862  nHistories = getSize () + getVoltageSources ();
863  histories = new history[nHistories];
864  for (int i = 0; i < nHistories; i++) histories[i].setAge (age);
865 }
866 
867 // The function deletes the histories for the transient analysis.
869  if (histories != NULL) {
870  delete[] histories;
871  histories = NULL;
872  }
873  setHistory (false);
874 }
875 
876 // Appends a history value.
877 void circuit::appendHistory (int n, nr_double_t val) {
878  histories[n].append (val);
879 }
880 
881 // Returns the required age of the history.
882 nr_double_t circuit::getHistoryAge (void) {
883  if (histories) return histories[0].getAge ();
884  return 0.0;
885 }
886 
887 /* This function should be used to apply the time vector history to
888  the value histories of a circuit. */
891  for (int i = 0; i < nHistories; i++) histories[i].setTvector (t);
892 }
893 
894 // Returns voltage at the given time for the given node.
895 nr_double_t circuit::getV (int port, nr_double_t t) {
896  return histories[port].nearest (t);
897 }
898 
899 // Returns current at the given time for the given voltage source.
900 nr_double_t circuit::getJ (int nr, nr_double_t t) {
901  return histories[nr + getSize ()].nearest (t);
902 }