LCOV - code coverage report
Current view: top level - src - acsolver.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 89 101 88.1 %
Date: 2015-01-05 16:01:02 Functions: 9 15 60.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 71 138 51.4 %

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

Generated by: LCOV version 1.11