Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
net.cpp
Go to the documentation of this file.
1 /*
2  * net.cpp - net class implementation
3  *
4  * Copyright (C) 2003, 2004, 2005, 2006, 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 <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 "node.h"
38 #include "circuit.h"
39 #include "strlist.h"
40 #include "vector.h"
41 #include "dataset.h"
42 #include "net.h"
43 #include "tee.h"
44 #include "open.h"
45 #include "itrafo.h"
46 #include "ptrlist.h"
47 #include "analysis.h"
48 #include "nodelist.h"
49 #include "nodeset.h"
50 #include "equation.h"
51 #include "environment.h"
52 #include "component_id.h"
53 
54 namespace qucs {
55 
56 // Constructor creates an unnamed instance of the net class.
57 net::net () : object () {
58  root = drop = NULL;
59  nPorts = nCircuits = nSources = 0;
61  actions = new ptrlist<analysis> ();
62  orgacts = new ptrlist<analysis> ();
63  env = NULL;
64  nset = NULL;
65  srcFactor = 1;
66 }
67 
68 // Constructor creates a named instance of the net class.
69 net::net (const char * n) : object (n) {
70  root = drop = NULL;
71  nPorts = nCircuits = nSources = 0;
73  actions = new ptrlist<analysis> ();
74  orgacts = new ptrlist<analysis> ();
75  env = NULL;
76  nset = NULL;
77  srcFactor = 1;
78 }
79 
80 // Destructor deletes the net class object.
82  circuit * n;
83  // delete each and every circuit
84  for (circuit * c = root; c != NULL; c = n) {
85  n = (circuit *) c->getNext ();
86  delete c;
87  }
88  // delete original actions
89  for (int i = 0; i < orgacts->length (); i++) delete orgacts->get (i);
90  delete orgacts;
91  // delete nodeset
92  delNodeset ();
93  delete actions;
94 }
95 
96 /* The copy constructor creates a new instance of the net class based
97  on the given net object. */
98 net::net (net & n) : object (n) {
99  root = drop = NULL;
100  nPorts = nCircuits = nSources = 0;
102  actions = n.actions ? new ptrlist<analysis> (*n.actions) : NULL;
103  orgacts = new ptrlist<analysis> ();
104  env = n.env;
105  nset = NULL;
106  srcFactor = 1;
107 }
108 
109 /* This function prepends the given circuit to the list of registered
110  circuits. */
112 #if 0
113  assert (!containsCircuit (c));
114 #endif
115 
116  // chain circuit appropriately
117  if (root) root->setPrev (c);
118  c->setNext (root);
119  c->setPrev (NULL);
120  root = c;
121  nCircuits++;
122  c->setEnabled (1);
123  c->setNet (this);
124 
125  /* handle AC power sources as s-parameter ports if it is not part of
126  a subcircuit */
127  if (c->getType () == CIR_PAC && c->getSubcircuit () == NULL) {
128  nPorts++;
129  if (!c->getPort ()) c->setPort (c->getPropertyInteger ("Num"));
130  }
131  // handle DC voltage sources
132  if (c->getVoltageSources () > 0) {
133  if (c->getVoltageSource () < 0) c->setVoltageSource (nSources);
134  nSources += c->getVoltageSources ();
135  }
136 }
137 
138 /* The function removes the given circuit from the list of registered
139  circuits. */
140 void net::removeCircuit (circuit * c, int dropping) {
141 #if 0
142  assert (containsCircuit (c));
143 #endif
144 
145  // adjust the circuit chain appropriately
146  if (c == root) {
147  root = (circuit *) c->getNext ();
148  if (root) root->setPrev (NULL);
149  }
150  else {
151  if (c->getNext ()) c->getNext()->setPrev (c->getPrev ());
152  c->getPrev()->setNext (c->getNext ());
153  }
154  nCircuits--;
155  c->setEnabled (0);
156  c->setNet (NULL);
157  if (c->getPort ()) nPorts--;
158  if (c->getVoltageSource () >= 0) nSources -= c->getVoltageSources ();
159 
160  // shift the circuit object to the drop list
161  if (c->isOriginal ()) {
162  if (dropping) {
163  if (drop) drop->setPrev (c);
164  c->setNext (drop);
165  c->setPrev (NULL);
166  drop = c;
167  }
168  }
169  // really destroy the circuit object
170  else delete c;
171 }
172 
173 /* The function returns non-zero if the given circuit is already part
174  of the netlist. It returns zero if not. */
176  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
177  if (c == cand) return 1;
178  return 0;
179 }
180 
181 /* This function prepends the given analysis to the list of registered
182  analyses. */
183 void net::insertAnalysis (analysis * a) {
184  orgacts->add (a);
185  actions->add (a);
186 }
187 
188 /* The function removes the given analysis from the list of registered
189  analyses. */
190 void net::removeAnalysis (analysis * a) {
191  actions->del (a);
192 }
193 
194 /* The function returns the analysis associated with the netlist
195  object specified by the given instance name and returns NULL if
196  there is no such analysis. */
197 analysis * net::findAnalysis (char * n) {
198  if (n == NULL) return NULL;
199  for (int i = 0; i < actions->length (); i++) {
200  analysis * a = actions->get (i);
201  if (!strcmp (a->getName (), n))
202  return a;
203  }
204  return NULL;
205 }
206 
207 /* The function returns the analysis associated with the netlist
208  object specified by the given type of analysis and returns NULL if
209  there is no such analysis. */
210 analysis * net::findAnalysis (int type) {
211  for (int i = 0; i < actions->length (); i++) {
212  analysis * a = actions->get (i);
213  if (a->getType () == type)
214  return a;
215  }
216  return NULL;
217 }
218 
219 /* Looks recursively for a type of analysis. */
220 int net::containsAnalysis (analysis * child, int type) {
221  ptrlist<analysis> * alist = child->getAnalysis ();
222  for (int i = 0; alist && i < alist->length (); i++) {
223  analysis * a = alist->get (i);
224  if (a->getType () == type)
225  return 1;
226  else if (a->getType () == ANALYSIS_SWEEP)
227  return containsAnalysis (a, type);
228  }
229  return 0;
230 }
231 
232 /* This function runs all registered analyses applied to the current
233  netlist, except for external analysis types. */
234 dataset * net::runAnalysis (int &err) {
235  dataset * out = new dataset ();
236  analysis * a;
237  int i;
238 
239  // apply some data to all analyses
240  for (i = 0; i < actions->length (); i++) {
241  a = actions->get (i);
242  if (!a->isExternal ())
243  {
244  a->setNet (this);
245  a->setData (out);
246  }
247  }
248 
249  // re-order analyses
250  orderAnalysis ();
251 
252  // initialize analyses
253  for (i = 0; i < actions->length (); i++) {
254  a = actions->get (i);
255  if (!a->isExternal ())
256  {
257  err |= a->initialize ();
258  }
259  }
260 
261  // solve the analyses
262  for (i = 0; i < actions->length (); i++) {
263  a = actions->get (i);
264  if (!a->isExternal ())
265  {
266  a->getEnv()->runSolver ();
267  err |= a->solve ();
268  }
269  }
270 
271  // cleanup analyses
272  for (i = 0; i < actions->length (); i++) {
273  a = actions->get (i);
274  if (!a->isExternal ())
275  {
276  err |= a->cleanup ();
277  }
278  }
279 
280  return out;
281 }
282 
283 /* The function returns the analysis with the second lowest order. If
284  there is no recursive sweep it returns NULL. */
285 analysis * net::findSecondOrder (void) {
286  analysis * parent = NULL;
287  for (int i = 0; i < actions->length (); i++) {
288  analysis * a = actions->get (i);
289  // parameter sweeps are potential parent sweeps
290  if (a->getType () == ANALYSIS_SWEEP) {
291  // find the appropriate sub analysis
292  analysis * child = getChildAnalysis (a);
293  if (child != NULL) {
294  // check if child is not another variable sweep
295  if (child->getType () != ANALYSIS_SWEEP) {
296  parent = a;
297  break;
298  }
299  // check if the child's child is still in the analysis list
300  else if (getChildAnalysis (child) == NULL) {
301  parent = a;
302  break;
303  }
304  }
305  }
306  }
307  return parent;
308 }
309 
310 /* The function reorders (prioritizes) the registered analysis to the
311  netlist object. In fact it chains the analyses to be executed in
312  a certain order. */
313 void net::orderAnalysis (void) {
314  analysis * parent, * child, * a;
315  analysis * dc = findAnalysis (ANALYSIS_DC);
316  int i, dcApplied = 0;
317  do {
318  // get second order sweep
319  if ((parent = findSecondOrder ()) != NULL) {
320  child = getChildAnalysis (parent);
321  removeAnalysis (child);
322  // apply sub-analysis to each parent analysis if any
323  for (i = 0; i < actions->length (); i++) {
324  a = actions->get (i);
325  char * cn = getChild (a);
326  if (cn != NULL && !strcmp (cn, child->getName ())) {
327  a->addAnalysis (child);
328  // apply DC analysis if necessary
329  if (child->getType () != ANALYSIS_DC &&
330  child->getType () != ANALYSIS_SWEEP && dc != NULL) {
331  if (!dcApplied) removeAnalysis (dc);
332  a->addAnalysis (dc);
333  dcApplied++;
334  }
335  }
336  }
337  // sort the sub-analysis of each parent
338  for (i = 0; i < actions->length (); i++) {
339  a = actions->get (i);
340  sortChildAnalyses (a);
341  }
342  }
343  } while (parent != NULL);
344 
345  // sort the parent analyses
346  parent = new analysis ();
347  parent->setAnalysis (actions);
348  sortChildAnalyses (parent);
349  actions = new ptrlist<analysis> (*(parent->getAnalysis ()));
350  delete parent;
351 }
352 
353 // This function sorts the analyses of the given parent analysis.
354 void net::sortChildAnalyses (analysis * parent) {
355  ptrlist<analysis> * alist = parent->getAnalysis ();
356  for (int i = 0; alist && i < alist->length (); i++) {
357  analysis * a = alist->get (i);
358  if (a->getType () == ANALYSIS_DC
359  || containsAnalysis (a, ANALYSIS_DC)) {
360  parent->delAnalysis (a);
361  parent->addAnalysis (a);
362  }
363  }
364 }
365 
366 // Returns the instance name of the given parents child analysis.
367 char * net::getChild (analysis * parent) {
368  char * child = NULL;
369  if (parent != NULL && parent->getType () == ANALYSIS_SWEEP)
370  child = parent->getPropertyString ("Sim");
371  return child;
372 }
373 
374 // Returns the child analysis of the given parent if possible.
375 analysis * net::getChildAnalysis (analysis * parent) {
376  return findAnalysis (getChild (parent));
377 }
378 
379 // Returns the last order sweep being not an parameter sweep.
380 analysis * net::findLastOrder (analysis * a) {
381  ptrlist<analysis> * alist = a->getAnalysis ();
382  analysis * child = alist ? alist->get (0) : NULL;
383  if (child != NULL && child->getType () == ANALYSIS_SWEEP) {
384  return findLastOrder (child);
385  }
386  return child ? child : a;
387 }
388 
389 // Returns the last order sweep being not an parameter sweep.
390 ptrlist<analysis> * net::findLastOrderChildren (analysis * a) {
391  ptrlist<analysis> * alist = a->getAnalysis ();
392  analysis * child = alist ? alist->get (0) : NULL;
393  if (child != NULL && child->getType () == ANALYSIS_SWEEP) {
394  return findLastOrderChildren (child);
395  }
396  return alist;
397 }
398 
399 /* The function re-shifts all circuits in the drop list to the actual
400  list of circuit objects. */
402  circuit * n;
403  for (circuit * c = drop; c != NULL; c = n) {
404  n = (circuit *) c->getNext ();
405  if (nodes) nodes->insert (c);
406  insertCircuit (c);
407  }
408  drop = NULL;
409 }
410 
411 /* This function deletes all unnecessary circuits in the list of
412  registered circuit objects. */
414  circuit * n;
415  for (circuit * c = root; c != NULL; c = n) {
416  n = (circuit *) c->getNext ();
417  if (!c->isOriginal ()) {
418  if (nodes) nodes->remove (c);
419  removeCircuit (c);
420  }
421  }
422 }
423 
424 /* Returns the first node in the list of real circuit objects
425  connected to the given node. If there is no such node (unconnected
426  node) the function returns NULL. */
428 
429  char * _name = n->getName ();
430  node * _node;
431 
432  // through the list of circuit objects
433  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
434  // skip signal circuits
435  if (c->getPort ()) continue;
436  // through the list of nodes in a circuit
437  for (int i = 0; i < c->getSize (); i++) {
438  _node = c->getNode (i);
439  if (!strcmp (_node->getName (), _name)) {
440  if (_node != n) {
441  return _node;
442  }
443  }
444  }
445  }
446  return NULL;
447 }
448 
449 /* Returns the first node in the list of circuit objects (including
450  signals) connected to the given node. If there is no such node
451  (unconnected node) the function returns NULL. */
453 
454  char * _name = n->getName ();
455  node * _node;
456 
457  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
458  for (int i = 0; i < c->getSize (); i++) {
459  _node = c->getNode (i);
460  if (!strcmp (_node->getName (), _name)) {
461  if (_node != n) {
462  return _node;
463  }
464  }
465  }
466  }
467  return NULL;
468 }
469 
470 // Rename the given circuit and mark it as being a reduced one.
472  char n[32];
473  sprintf (n, "reduced%d", reduced++);
474  c->setName (n);
475 }
476 
477 /* Rename the given circuit and mark it as being a inserted one and
478  remember when it was inserted. */
480  char n[32];
481  sprintf (n, "inserted%d", inserted);
482  c->setName (n);
483  c->setInserted (inserted);
484  inserted++;
485 }
486 
487 // Rename the given node and mark it as being a inserted one.
489  char n[32];
490  sprintf (n, "inode%d", insertedNodes++);
491  c->setName (n);
492 }
493 
494 /* This helper function checks whether the circuit chain of the
495  netlist is properly working. It returns the number of errors or
496  zero if there are no errors. */
498  int error = 0;
499  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
500  if (c->getPrev ())
501  if (c->getPrev()->getNext () != c) {
502  error++;
503  logprint (LOG_ERROR, "ERROR: prev->next != circuit '%s'\n",
504  c->getName ());
505  }
506  if (c->getNext ())
507  if (c->getNext()->getPrev () != c) {
508  error++;
509  logprint (LOG_ERROR, "ERROR: next->prev != circuit '%s'\n",
510  c->getName ());
511  }
512  }
513  return error;
514 }
515 
516 /* This function counts the number of signals (ports) within the list
517  of registerd circuits. */
518 int net::countPorts (void) {
519  int count = 0;
520  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
521  if (c->getPort ()) count++;
522  }
523  return count;
524 }
525 
526 /* This function counts the number of circuits within the list of
527  registered circuits. */
528 int net::countNodes (void) {
529  int count = 0;
530  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
531  if (!c->getPort ()) count += c->getSize ();
532  }
533  return count;
534 }
535 
536 /* The function returns the number of non-linear circuits within the
537  list of registered circuits. */
538 int net::isNonLinear (void) {
539  int count = 0;
540  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
541  if (c->isNonLinear ()) count++;
542  }
543  return count;
544 }
545 
546 /* The function adds the given nodeset object to the netlist's nodeset
547  list. */
549  n->setNext (nset);
550  nset = n;
551 }
552 
553 /* The following function deletes all the nodeset list of the netlist
554  object. Called from the destructor. */
555 void net::delNodeset (void) {
556  nodeset * next;
557  for (nodeset * n = nset; n != NULL; n = next) {
558  next = n->getNext ();
559  delete n;
560  }
561  nset = NULL;
562 }
563 
564 /* sets the net of the action with a given index to the supplied net */
565 void net::setActionNet(int index, net * subnet)
566 {
567  analysis * a;
568  if (index < actions->length())
569  {
570  a = actions->get (index);
571  a->setNet(subnet);
572  }
573 }
574 
575 /* sets the net of the action with a given index to the supplied net */
577 {
578  return actions->length();
579 }
580 
581 #if DEBUG
582 // DEBUG function: Lists the netlist.
583 void net::list (void) {
584  logprint (LOG_STATUS, "DEBUG: netlist `%s' (%d circuits, "
585  "%d ports, %d nodes)\n", getName (), countPorts (),
586  countPorts (), countNodes ());
587  // go through circuit list
588  for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ()) {
589  // list each circuit
590  logprint (LOG_STATUS, " %s[", c->getName ());
591  for (int i = 0; i < c->getSize (); i++) {
592  logprint (LOG_STATUS, "%s-%d",
593  c->getNode(i)->getName (), c->getNode(i)->getNode ());
594  if (i < c->getSize () - 1)
595  logprint (LOG_STATUS, ",");
596  }
597  logprint (LOG_STATUS, "] { %s }\n", c->propertyList ());
598  }
599 }
600 #endif /* DEBUG */
601 
602 } // namespace qucs
int nCircuits
Definition: net.h:100
circuit * drop
Definition: net.h:93
void removeAnalysis(analysis *)
Definition: net.cpp:190
int containsCircuit(circuit *)
Definition: net.cpp:175
environment * env
Definition: net.h:97
void insertAnalysis(analysis *)
Definition: net.cpp:183
void remove(char *)
Definition: nodelist.cpp:162
virtual int initialize(void)
placehoder for initialization function
Definition: analysis.h:132
net()
Definition: net.cpp:57
int nSources
Definition: net.h:99
void setEnabled(bool e)
Set a circuit element to be enabled or diabled.
Definition: circuit.h:167
void add(type_t *)
Definition: ptrlist.cpp:69
analysis * findSecondOrder(void)
Definition: net.cpp:285
void deleteUnusedCircuits(nodelist *nodes=NULL)
Definition: net.cpp:413
int getPropertyInteger(const char *)
Definition: object.cpp:198
void setNext(object *o)
Definition: object.h:60
object * next
Definition: object.h:88
int getVoltageSource(void)
Definition: circuit.h:187
ptrlist< analysis > * findLastOrderChildren(analysis *)
Definition: net.cpp:390
int checkCircuitChain(void)
Definition: net.cpp:497
void setVoltageSource(int s)
Definition: circuit.h:186
n
Definition: parse_citi.y:147
object * getNext(void)
Definition: object.h:59
int nPorts
Definition: net.h:98
int getNActions(void)
Definition: net.cpp:576
type_t * get(int)
Definition: ptrlist.cpp:147
ptrlist< analysis > * orgacts
Definition: net.h:96
i
Definition: parse_mdl.y:516
nodeset * nset
Definition: net.h:92
int getVoltageSources(void)
Definition: circuit.cpp:602
analysis * findAnalysis(char *)
Definition: net.cpp:197
dataset * runAnalysis(int &)
Definition: net.cpp:234
void setPort(int p)
Definition: circuit.h:229
void setNext(nodeset *p)
Definition: nodeset.h:39
void list(void)
void setPrev(object *o)
Definition: object.h:62
void setName(const char *)
Definition: object.cpp:78
base class for qucs circuit elements.
Definition: circuit.h:92
int getType(void)
Definition: circuit.h:137
char * getSubcircuit(void)
Definition: circuit.h:176
analysis * getChildAnalysis(analysis *)
Definition: net.cpp:375
virtual int cleanup(void)
placehoder for cleanup function
Definition: analysis.h:143
environment * getEnv(void)
Definition: analysis.h:180
int countPorts(void)
Definition: net.cpp:518
ptrlist< analysis > * getAnalysis(void)
Definition: analysis.h:190
The analysis class header file.
parent
Definition: parse_vcd.y:126
void sortChildAnalyses(analysis *)
Definition: net.cpp:354
void insertCircuit(circuit *)
Definition: net.cpp:111
void setInserted(int i)
Definition: circuit.h:231
node * findConnectedCircuitNode(node *)
Definition: net.cpp:427
void del(type_t *)
Definition: ptrlist.cpp:106
void setNet(net *n)
Definition: circuit.h:172
The circuit class header file.
int isNonLinear(void)
Definition: net.cpp:538
generic object class.
Definition: object.h:52
int reduced
Definition: net.h:101
void removeCircuit(circuit *, int dropping=1)
Definition: net.cpp:140
int length(void)
Definition: ptrlist.cpp:100
int containsAnalysis(analysis *, int)
Definition: net.cpp:220
nodes
type
Definition: parse_vcd.y:164
int getPort(void)
Definition: circuit.h:228
void insertedCircuit(circuit *)
Definition: net.cpp:479
node * findConnectedNode(node *)
Definition: net.cpp:452
int countNodes(void)
Definition: net.cpp:528
void getDroppedCircuits(nodelist *nodes=NULL)
Definition: net.cpp:401
Definition: net.h:39
ptrlist< analysis > * actions
Definition: net.h:95
analysis * findLastOrder(analysis *)
Definition: net.cpp:380
object * getPrev(void)
Definition: object.h:61
void insertedNode(node *)
Definition: net.cpp:488
The environment class definition.
nr_double_t srcFactor
Definition: net.h:104
void addNodeset(nodeset *)
Definition: net.cpp:548
void setActionNet(int, net *)
Definition: net.cpp:565
#define LOG_ERROR
Definition: logging.h:28
char * getName(void)
Definition: object.cpp:84
char * getChild(analysis *)
Definition: net.cpp:367
circuit * root
Definition: net.h:94
void setNet(net *netlist)
Definition: analysis.h:175
void delNodeset(void)
Definition: net.cpp:555
#define LOG_STATUS
Definition: logging.h:29
int inserted
Definition: net.h:102
void insert(struct nodelist_t *)
Definition: nodelist.cpp:358
void logprint(int level, const char *format,...)
Definition: logging.c:37
void orderAnalysis(void)
Definition: net.cpp:313
int insertedNodes
Definition: net.h:103
bool isOriginal(void)
Definition: circuit.h:232
~net()
Definition: net.cpp:81
void reducedCircuit(circuit *)
Definition: net.cpp:471