My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
acsolver.cpp
Go to the documentation of this file.
1 /*
2  * acsolver.cpp - AC solver class implementation
3  *
4  * Copyright (C) 2004, 2005, 2007, 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: acsolver.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 <math.h>
31 
32 #include "object.h"
33 #include "complex.h"
34 #include "circuit.h"
35 #include "sweep.h"
36 #include "net.h"
37 #include "netdefs.h"
38 #include "analysis.h"
39 #include "nasolver.h"
40 #include "acsolver.h"
41 
42 // Constructor creates an unnamed instance of the acsolver class.
44  swp = NULL;
45  type = ANALYSIS_AC;
46  setDescription ("AC");
47  xn = NULL;
48  noise = 0;
49 }
50 
51 // Constructor creates a named instance of the acsolver class.
53  swp = NULL;
54  type = ANALYSIS_AC;
55  setDescription ("AC");
56  xn = NULL;
57  noise = 0;
58 }
59 
60 // Destructor deletes the acsolver class object.
62  if (swp) delete swp;
63  if (xn) delete xn;
64 }
65 
66 /* The copy constructor creates a new instance of the acsolver class
67  based on the given acsolver object. */
69  swp = o.swp ? new sweep (*(o.swp)) : NULL;
70  xn = o.xn ? new tvector<nr_double_t> (*(o.xn)) : NULL;
71  noise = o.noise;
72 }
73 
74 /* This is the AC netlist solver. It prepares the circuit list for
75  each requested frequency and solves it then. */
76 int acsolver::solve (void) {
77  runs++;
78 
79  // run additional noise analysis ?
80  noise = !strcmp (getPropertyString ("Noise"), "yes") ? 1 : 0;
81 
82  // create frequency sweep if necessary
83  if (swp == NULL) {
84  swp = createSweep ("acfrequency");
85  }
86 
87  // initialize node voltages, first guess for non-linear circuits and
88  // generate extra circuits if necessary
89  init ();
91  solve_pre ();
92 
93  swp->reset ();
94  for (int i = 0; i < swp->getSize (); i++) {
95  freq = swp->next ();
96  if (progress) logprogressbar (i, swp->getSize (), 40);
97 
98 #if DEBUG && 0
99  logprint (LOG_STATUS, "NOTIFY: %s: solving netlist for f = %e\n",
100  getName (), (double) freq);
101 #endif
102 
103  // start the linear solver
105  solve_linear ();
106 
107  // compute noise if requested
108  if (noise) solve_noise ();
109 
110  // save results
111  saveAllResults (freq);
112  }
113  solve_post ();
114  if (progress) logprogressclear (40);
115  return 0;
116 }
117 
118 /* Goes through the list of circuit objects and runs its calcAC()
119  function. */
120 void acsolver::calc (acsolver * self) {
121  circuit * root = self->getNet()->getRoot ();
122  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
123  c->calcAC (self->freq);
124  if (self->noise) c->calcNoiseAC (self->freq);
125  }
126 }
127 
128 /* Goes through the list of circuit objects and runs its initAC()
129  function. */
130 void acsolver::init (void) {
131  circuit * root = subnet->getRoot ();
132  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
133  if (c->isNonLinear ()) c->calcOperatingPoints ();
134  c->initAC ();
135  if (noise) c->initNoiseAC ();
136  }
137 }
138 
139 /* This function saves the results of a single solve() functionality
140  (for the given frequency) into the output dataset. */
141 void acsolver::saveAllResults (nr_double_t freq) {
142  vector * f;
143  // add current frequency to the dependency of the output dataset
144  if ((f = data->findDependency ("acfrequency")) == NULL) {
145  f = new vector ("acfrequency");
146  data->addDependency (f);
147  }
148  if (runs == 1) f->add (freq);
149  saveResults ("v", "i", 0, f);
150 
151  // additionally save noise results if requested
152  if (noise) {
153  saveNoiseResults (f);
154  }
155 }
156 
157 /* The function computes the final noise results and puts them into
158  the output dataset. */
160  int N = countNodes ();
161  int M = countVoltageSources ();
162  for (int r = 0; r < N + M; r++) {
163  // renormalise the results
164  x->set (r, fabs (xn->get (r) * sqrt (kB * T0)));
165  }
166 
167  // apply probe data
168  circuit * root = subnet->getRoot ();
169  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
170  if (!c->isProbe ()) continue;
171  int np, nn;
172  nr_double_t vp, vn;
173  np = getNodeNr (c->getNode (NODE_1)->getName ());
174  vp = np > 0 ? xn->get (np - 1) : 0.0;
175  nn = getNodeNr (c->getNode (NODE_2)->getName ());
176  vn = nn > 0 ? xn->get (nn - 1) : 0.0;
177  c->setOperatingPoint ("Vr", fabs ((vp - vn) * sqrt (kB * T0)));
178  c->setOperatingPoint ("Vi", 0.0);
179  }
180 
181  saveResults ("vn", "in", 0, f);
182 }
183 
184 /* This function runs the AC noise analysis. It saves its results in
185  the 'xn' vector. */
187  int N = countNodes ();
188  int M = countVoltageSources ();
189 
190  // save usual AC results
191  tvector<nr_complex_t> xsave = *x;
192 
193  // create the Cy matrix
195  // create noise result vector if necessary
196  if (xn == NULL) xn = new tvector<nr_double_t> (N + M);
197 
198  // temporary result vector for transimpedances
200 
201  // create the MNA matrix once again and LU decompose the adjoint matrix
202  createMatrix ();
203  A->transpose ();
205  runMNA ();
206 
207  // ensure skipping LU decomposition
208  updateMatrix = 0;
211 
212  // compute noise voltage for each node (and voltage source)
213  for (int i = 0; i < N + M; i++) {
214  z->set (0); z->set (i, -1); // modify right hand side appropriately
215  runMNA (); // solve
216  zn = *x; // save transimpedance vector
217 
218  // compute actual noise voltage
219  xn->set (i, sqrt (real (scalar (zn * (*C), conj (zn)))));
220  }
221 
222  // restore usual AC results
223  *x = xsave;
224 }
225 
226 // properties
227 PROP_REQ [] = {
228  { "Type", PROP_STR, { PROP_NO_VAL, "lin" }, PROP_RNG_TYP },
229  PROP_NO_PROP };
230 PROP_OPT [] = {
231  { "Noise", PROP_STR, { PROP_NO_VAL, "no" }, PROP_RNG_YESNO },
232  { "Start", PROP_REAL, { 1e9, PROP_NO_STR }, PROP_POS_RANGE },
233  { "Stop", PROP_REAL, { 10e9, PROP_NO_STR }, PROP_POS_RANGE },
234  { "Points", PROP_INT, { 10, PROP_NO_STR }, PROP_MIN_VAL (2) },
235  { "Values", PROP_LIST, { 10, PROP_NO_STR }, PROP_POS_RANGE },
236  PROP_NO_PROP };
237 struct define_t acsolver::anadef =