My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dcsolver.cpp
Go to the documentation of this file.
1 /*
2  * dcsolver.cpp - DC solver class implementation
3  *
4  * Copyright (C) 2003-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: dcsolver.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 
31 #include "object.h"
32 #include "complex.h"
33 #include "circuit.h"
34 #include "net.h"
35 #include "netdefs.h"
36 #include "analysis.h"
37 #include "nasolver.h"
38 #include "dcsolver.h"
39 
40 // Constructor creates an unnamed instance of the dcsolver class.
41 dcsolver::dcsolver () : nasolver<nr_double_t> () {
42  saveOPs = 0;
43  type = ANALYSIS_DC;
44  setDescription ("DC");
45 }
46 
47 // Constructor creates a named instance of the dcsolver class.
48 dcsolver::dcsolver (char * n) : nasolver<nr_double_t> (n) {
49  saveOPs = 0;
50  type = ANALYSIS_DC;
51  setDescription ("DC");
52 }
53 
54 // Destructor deletes the dcsolver class object.
56 }
57 
58 /* The copy constructor creates a new instance of the dcsolver class
59  based on the given dcsolver object. */
60 dcsolver::dcsolver (dcsolver & o) : nasolver<nr_double_t> (o) {
61  saveOPs = o.saveOPs;
62 }
63 
64 /* This is the DC netlist solver. It prepares the circuit list and
65  solves it then. */
66 int dcsolver::solve (void) {
67  // fetch simulation properties
68  saveOPs |= !strcmp (getPropertyString ("saveOPs"), "yes") ? SAVE_OPS : 0;
69  saveOPs |= !strcmp (getPropertyString ("saveAll"), "yes") ? SAVE_ALL : 0;
70  char * solver = getPropertyString ("Solver");
71 
72  // initialize node voltages, first guess for non-linear circuits and
73  // generate extra circuits if necessary
74  init ();
76 
77  // start the iterative solver
78  solve_pre ();
79 
80  // choose a solver
81  if (!strcmp (solver, "CroutLU"))
83  else if (!strcmp (solver, "DoolittleLU"))
85  else if (!strcmp (solver, "HouseholderQR"))
87  else if (!strcmp (solver, "HouseholderLQ"))
89  else if (!strcmp (solver, "GolubSVD"))
91 
92  // local variables for the fallback thingies
93  int retry = -1, error, fallback = 0, preferred;
94  int helpers[] = {
100  -1 };
101 
102  // is a certain convergence helper requested?
103  char * helper = getPropertyString ("convHelper");
105  if (!strcmp (helper, "LineSearch")) {
107  } else if (!strcmp (helper, "SteepestDescent")) {
109  } else if (!strcmp (helper, "Attenuation")) {
111  } else if (!strcmp (helper, "gMinStepping")) {
113  } else if (!strcmp (helper, "SourceStepping")) {
115  }
116  preferred = convHelper;
117 
118  if (!subnet->isNonLinear ()) {
119  // Start the linear solver.
121  error = solve_linear ();
122  }
123  else do {
124  // Run the DC solver once.
125  try_running () {
126  applyNodeset ();
127  error = solve_nonlinear ();
128 #if DEBUG
129  if (!error) {
131  "NOTIFY: %s: convergence reached after %d iterations\n",
132  getName (), iterations);
133  }
134 #endif /* DEBUG */
135  if (!error) retry = -1;
136  }
137  // Appropriate exception handling.
138  catch_exception () {
140  pop_exception ();
141  if (preferred == helpers[fallback] && preferred) fallback++;
142  convHelper = helpers[fallback++];
143  if (convHelper != -1) {
144  logprint (LOG_ERROR, "WARNING: %s: %s analysis failed, using fallback "
145  "#%d (%s)\n", getName (), getDescription (), fallback,
147  retry++;
148  restart ();
149  }
150  else {
151  retry = -1;
152  }
153  break;
154  default:
155  // Otherwise return.
156  estack.print ();
157  error++;
158  break;
159  }
160  } while (retry != -1);
161 
162  // save results and cleanup the solver
164  saveResults ("V", "I", saveOPs);
165 
166  solve_post ();
167  return 0;
168 }
169 
170 /* Goes through the list of circuit objects and runs its calcDC()
171  function. */
172 void dcsolver::calc (dcsolver * self) {
173  circuit * root = self->getNet()->getRoot ();
174  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
175  c->calcDC ();
176  }
177 }
178 
179 /* Goes through the list of circuit objects and runs its initDC()
180  function. */
181 void dcsolver::init (void) {
182  circuit * root = subnet->getRoot ();
183  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
184  c->initDC ();
185  }
186 }
187 
188 /* Goes through the list of non-linear circuit objects and runs its
189  restartDC() function. */
190 void dcsolver::restart (void) {
191  circuit * root = subnet->getRoot ();
192  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
193  if (c->isNonLinear ()) c->restartDC ();
194  }
195 }
196 
197 /* Goes through the list of non-linear circuit objects and runs its
198  saveOperatingPoints() function. */
200  circuit * root = subnet->getRoot ();
201  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
202  if (c->isNonLinear ()) c->saveOperatingPoints ();
203  }
204 }
205 
206 // properties
207 PROP_REQ [] = {
208  PROP_NO_PROP };
209 PROP_OPT [] = {
210  { "MaxIter", PROP_INT, { 150, PROP_NO_STR }, PROP_RNGII (2, 10000) },
211  { "abstol", PROP_REAL, { 1e-12, PROP_NO_STR }, PROP_RNG_X01I },
212  { "vntol", PROP_REAL, { 1e-6, PROP_NO_STR }, PROP_RNG_X01I },
213  { "reltol", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_RNG_X01I },
214  { "saveOPs", PROP_STR, { PROP_NO_VAL, "no" }, PROP_RNG_YESNO },
215  { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
216  { "saveAll", PROP_STR, { PROP_NO_VAL, "no" }, PROP_RNG_YESNO },
217  { "convHelper", PROP_STR, { PROP_NO_VAL, "none" },
218  PROP_RNG_STR6 ("none", "SourceStepping", "gMinStepping",
219  "LineSearch", "Attenuation", "SteepestDescent") },
220  { "Solver", PROP_STR, { PROP_NO_VAL, "CroutLU" }, PROP_RNG_SOL },
221  PROP_NO_PROP };
222 struct define_t dcsolver::anadef =