LCOV - code coverage report
Current view: top level - src - trsolver.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 353 418 84.4 %
Date: 2015-01-05 16:01:02 Functions: 30 37 81.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 176 282 62.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * trsolver.cpp - transient solver class implementation
       3                 :            :  *
       4                 :            :  * Copyright (C) 2004, 2005, 2006, 2007, 2009 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 <string.h>
      31                 :            : #include <math.h>
      32                 :            : #include <float.h>
      33                 :            : 
      34                 :            : #include "compat.h"
      35                 :            : #include "object.h"
      36                 :            : #include "logging.h"
      37                 :            : #include "complex.h"
      38                 :            : #include "circuit.h"
      39                 :            : #include "sweep.h"
      40                 :            : #include "net.h"
      41                 :            : #include "netdefs.h"
      42                 :            : #include "analysis.h"
      43                 :            : #include "nasolver.h"
      44                 :            : #include "history.h"
      45                 :            : #include "trsolver.h"
      46                 :            : #include "transient.h"
      47                 :            : #include "exception.h"
      48                 :            : #include "exceptionstack.h"
      49                 :            : 
      50                 :            : #define STEPDEBUG   0 // set to zero for release
      51                 :            : #define BREAKPOINTS 0 // exact breakpoint calculation
      52                 :            : 
      53                 :            : #define dState 0 // delta T state
      54                 :            : #define sState 1 // solution state
      55                 :            : 
      56                 :            : // Macro for the n-th state of the solution vector history.
      57                 :            : #define SOL(state) (solution[(int) getState (sState, (state))])
      58                 :            : 
      59                 :            : namespace qucs {
      60                 :            : 
      61                 :            : using namespace transient;
      62                 :            : 
      63                 :            : // Constructor creates an unnamed instance of the trsolver class.
      64                 :         38 : trsolver::trsolver ()
      65                 :         38 :     : nasolver<nr_double_t> (), states<nr_double_t> ()
      66                 :            : {
      67                 :         38 :     swp = NULL;
      68                 :         38 :     type = ANALYSIS_TRANSIENT;
      69                 :         38 :     setDescription ("transient");
      70 [ +  + ][ #  # ]:        342 :     for (int i = 0; i < 8; i++) solution[i] = NULL;
      71                 :         38 :     tHistory = NULL;
      72                 :         38 :     relaxTSR = false;
      73                 :         38 :     initialDC = true;
      74                 :         38 : }
      75                 :            : 
      76                 :            : // Constructor creates a named instance of the trsolver class.
      77                 :          0 : trsolver::trsolver (char * n)
      78                 :          0 :     : nasolver<nr_double_t> (n), states<nr_double_t> ()
      79                 :            : {
      80                 :          0 :     swp = NULL;
      81                 :          0 :     type = ANALYSIS_TRANSIENT;
      82                 :          0 :     setDescription ("transient");
      83 [ #  # ][ #  # ]:          0 :     for (int i = 0; i < 8; i++) solution[i] = NULL;
      84                 :          0 :     tHistory = NULL;
      85                 :          0 :     relaxTSR = false;
      86                 :          0 :     initialDC = true;
      87                 :          0 : }
      88                 :            : 
      89                 :            : // Destructor deletes the trsolver class object.
      90                 :         38 : trsolver::~trsolver ()
      91                 :            : {
      92 [ +  - ][ +  - ]:         38 :     if (swp) delete swp;
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
      93 [ +  + ][ #  # ]:        342 :     for (int i = 0; i < 8; i++)
      94                 :            :     {
      95 [ -  + ][ #  # ]:        304 :         if (solution[i] != NULL)
      96                 :            :         {
      97 [ #  # ][ #  # ]:          0 :             delete solution[i];
      98                 :            :         }
      99                 :            :     }
     100 [ -  + ][ #  # ]:         38 :     if (tHistory) delete tHistory;
         [ #  # ][ #  # ]
     101 [ -  + ][ #  # ]:         76 : }
     102                 :            : 
     103                 :            : /* The copy constructor creates a new instance of the trsolver class
     104                 :            :    based on the given trsolver object. */
     105                 :          0 : trsolver::trsolver (trsolver & o)
     106                 :          0 :     : nasolver<nr_double_t> (o), states<nr_double_t> (o)
     107                 :            : {
     108 [ #  # ][ #  # ]:          0 :     swp = o.swp ? new sweep (*o.swp) : NULL;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     109 [ #  # ][ #  # ]:          0 :     for (int i = 0; i < 8; i++) solution[i] = NULL;
     110 [ #  # ][ #  # ]:          0 :     tHistory = o.tHistory ? new history (*o.tHistory) : NULL;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     111                 :          0 :     relaxTSR = o.relaxTSR;
     112                 :          0 :     initialDC = o.initialDC;
     113                 :          0 : }
     114                 :            : 
     115                 :            : // This function creates the time sweep if necessary.
     116                 :         65 : void trsolver::initSteps (void)
     117                 :            : {
     118 [ +  + ][ +  - ]:         65 :     if (swp != NULL) delete swp;
     119                 :         65 :     swp = createSweep ("time");
     120                 :         65 : }
     121                 :            : 
     122                 :            : // Performs the initial DC analysis.
     123                 :         64 : int trsolver::dcAnalysis (void)
     124                 :            : {
     125                 :         64 :     int error = 0;
     126                 :            : 
     127                 :            :     // First calculate a initial state using the non-linear DC analysis.
     128                 :         64 :     setDescription ("initial DC");
     129                 :         64 :     initDC ();
     130                 :         64 :     setCalculation ((calculate_func_t) &calcDC);
     131                 :         64 :     solve_pre ();
     132                 :         64 :     applyNodeset ();
     133                 :            : 
     134                 :            :     // Run the DC solver once.
     135                 :            :     try_running ()
     136                 :            :     {
     137                 :         64 :         error = solve_nonlinear ();
     138                 :            :     }
     139                 :            :     // Appropriate exception handling.
     140 [ -  + ][ #  # ]:         64 :     catch_exception ()
     141                 :            :     {
     142                 :            :     case EXCEPTION_NO_CONVERGENCE:
     143                 :          0 :         pop_exception ();
     144                 :          0 :         convHelper = CONV_LineSearch;
     145                 :            :         logprint (LOG_ERROR, "WARNING: %s: %s analysis failed, using line search "
     146                 :          0 :                   "fallback\n", getName (), getDescription ());
     147                 :          0 :         applyNodeset ();
     148                 :          0 :         restart ();
     149                 :          0 :         error = solve_nonlinear ();
     150                 :          0 :         break;
     151                 :            :     default:
     152                 :            :         // Otherwise return.
     153                 :          0 :         estack.print ();
     154                 :          0 :         error++;
     155                 :          0 :         break;
     156                 :            :     }
     157                 :            : 
     158                 :            :     // Save the DC solution.
     159                 :         64 :     storeSolution ();
     160                 :            : 
     161                 :            :     // Cleanup nodal analysis solver.
     162                 :         64 :     solve_post ();
     163                 :            : 
     164                 :            :     // Really failed to find initial DC solution?
     165         [ -  + ]:         64 :     if (error)
     166                 :            :     {
     167                 :            :         logprint (LOG_ERROR, "ERROR: %s: %s analysis failed\n",
     168                 :          0 :                   getName (), getDescription ());
     169                 :            :     }
     170                 :         64 :     return error;
     171                 :            : }
     172                 :            : 
     173                 :            : /* This is the transient netlist solver.  It prepares the circuit list
     174                 :            :    for each requested time and solves it then. */
     175                 :         65 : int trsolver::solve (void)
     176                 :            : {
     177                 :            :     nr_double_t time, saveCurrent;
     178                 :         65 :     int error = 0, convError = 0;
     179                 :         65 :     const char * const solver = getPropertyString ("Solver");
     180                 :         65 :     relaxTSR = !strcmp (getPropertyString ("relaxTSR"), "yes") ? true : false;
     181                 :         65 :     initialDC = !strcmp (getPropertyString ("initialDC"), "yes") ? true : false;
     182                 :            : 
     183                 :         65 :     runs++;
     184                 :         65 :     saveCurrent = current = 0;
     185                 :         65 :     stepDelta = -1;
     186                 :         65 :     converged = 0;
     187                 :         65 :     fixpoint = 0;
     188                 :         65 :     statRejected = statSteps = statIterations = statConvergence = 0;
     189                 :            : 
     190                 :            :     // Choose a solver.
     191         [ +  - ]:         65 :     if (!strcmp (solver, "CroutLU"))
     192                 :         65 :         eqnAlgo = ALGO_LU_DECOMPOSITION;
     193         [ #  # ]:          0 :     else if (!strcmp (solver, "DoolittleLU"))
     194                 :          0 :         eqnAlgo = ALGO_LU_DECOMPOSITION_DOOLITTLE;
     195         [ #  # ]:          0 :     else if (!strcmp (solver, "HouseholderQR"))
     196                 :          0 :         eqnAlgo = ALGO_QR_DECOMPOSITION;
     197         [ #  # ]:          0 :     else if (!strcmp (solver, "HouseholderLQ"))
     198                 :          0 :         eqnAlgo = ALGO_QR_DECOMPOSITION_LS;
     199         [ #  # ]:          0 :     else if (!strcmp (solver, "GolubSVD"))
     200                 :          0 :         eqnAlgo = ALGO_SV_DECOMPOSITION;
     201                 :            : 
     202                 :            :     // Perform initial DC analysis.
     203         [ +  + ]:         65 :     if (initialDC)
     204                 :            :     {
     205                 :         64 :         error = dcAnalysis ();
     206         [ -  + ]:         64 :         if (error)
     207                 :          0 :             return -1;
     208                 :            :     }
     209                 :            : 
     210                 :            :     // Initialize transient analysis.
     211                 :         65 :     setDescription ("transient");
     212                 :         65 :     initTR ();
     213                 :         65 :     setCalculation ((calculate_func_t) &calcTR);
     214                 :         65 :     solve_pre ();
     215                 :            : 
     216                 :            :     // Create time sweep if necessary.
     217                 :         65 :     initSteps ();
     218                 :         65 :     swp->reset ();
     219                 :            : 
     220                 :            :     // Recall the DC solution.
     221                 :         65 :     recallSolution ();
     222                 :            : 
     223                 :            :     // Apply the nodesets and adjust previous solutions.
     224                 :         65 :     applyNodeset (false);
     225                 :         65 :     fillSolution (x);
     226                 :            : 
     227                 :            :     // Tell integrators to be initialized.
     228                 :         65 :     setMode (MODE_INIT);
     229                 :            : 
     230                 :         65 :     int running = 0;
     231                 :         65 :     rejected = 0;
     232                 :         65 :     delta /= 10;
     233                 :         65 :     fillState (dState, delta);
     234                 :         65 :     adjustOrder (1);
     235                 :            : 
     236                 :            :     // Start to sweep through time.
     237         [ +  + ]:      43242 :     for (int i = 0; i < swp->getSize (); i++)
     238                 :            :     {
     239                 :      43177 :         time = swp->next ();
     240         [ +  + ]:      43177 :         if (progress) logprogressbar (i, swp->getSize (), 40);
     241                 :            : 
     242                 :            : #if DEBUG && 0
     243                 :            :         logprint (LOG_STATUS, "NOTIFY: %s: solving netlist for t = %e\n",
     244                 :            :                   getName (), (double) time);
     245                 :            : #endif
     246                 :            : 
     247         [ +  + ]:     214485 :         do // while (saveCurrent < time), i.e. until a requested breakpoint is hit
     248                 :            :         {
     249                 :            : #if STEPDEBUG
     250                 :            :             if (delta == deltaMin)
     251                 :            :             {
     252                 :            :                 // the integrator step size has become smaller than the
     253                 :            :                 // specified allowed minimum, Qucs is unable to solve the circuit
     254                 :            :                 // while meeting the tolerance conditions
     255                 :            :                 logprint (LOG_ERROR,
     256                 :            :                           "WARNING: %s: minimum delta h = %.3e at t = %.3e\n",
     257                 :            :                           getName (), (double) delta, (double) current);
     258                 :            :             }
     259                 :            : #endif
     260                 :            :             // updates the integrator coefficients, and updates the array of prev
     261                 :            :             // 8 deltas with the new delta for this step
     262                 :     214485 :             updateCoefficients (delta);
     263                 :            : 
     264                 :            :             // Run predictor to get a start value for the solution vector for
     265                 :            :             // the successive iterative corrector process
     266                 :     214485 :             error += predictor ();
     267                 :            : 
     268                 :            :             // restart Newton iteration
     269         [ +  + ]:     214485 :             if (rejected)
     270                 :            :             {
     271                 :      22030 :                 restart ();      // restart non-linear devices
     272                 :      22030 :                 rejected = 0;
     273                 :            :             }
     274                 :            : 
     275                 :            :             // Run corrector process with appropriate exception handling.
     276                 :            :             // The corrector iterates through the solutions of the integration
     277                 :            :             // process until a certain error tolerance has been reached.
     278                 :            :             try_running () // #defined as:    do {
     279                 :            :             {
     280                 :     214485 :                 error += corrector ();
     281                 :            :             }
     282 [ +  + ][ +  - ]:     214485 :             catch_exception () // #defined as:   } while (0); if (estack.top ()) switch (estack.top()->getCode ())
     283                 :            :             {
     284                 :            :             case EXCEPTION_NO_CONVERGENCE:
     285                 :         65 :                 pop_exception ();
     286                 :            : 
     287                 :            :                 // step back from the current time value to the previous time
     288         [ +  + ]:         65 :                 if (current > 0) current -= delta;
     289                 :            :                 // Reduce step-size (by half) if failed to converge.
     290                 :         65 :                 delta /= 2;
     291         [ +  + ]:         65 :                 if (delta <= deltaMin)
     292                 :            :                 {
     293                 :            :                     // but do not reduce the step size below a specified minimum
     294                 :         14 :                     delta = deltaMin;
     295                 :            :                     // instead reduce the order of the integration
     296                 :         14 :                     adjustOrder (1);
     297                 :            :                 }
     298                 :            :                 // step forward to the new current time value
     299         [ +  + ]:         65 :                 if (current > 0) current += delta;
     300                 :            : 
     301                 :            :                 // Update statistics.
     302                 :         65 :                 statRejected++;
     303                 :         65 :                 statConvergence++;
     304                 :         65 :                 rejected++; // mark the previous step size choice as rejected
     305                 :         65 :                 converged = 0;
     306                 :         65 :                 error = 0;
     307                 :            : 
     308                 :            :                 // Start using damped Newton-Raphson.
     309                 :         65 :                 convHelper = CONV_SteepestDescent;
     310                 :         65 :                 convError = 2;
     311                 :            : #if DEBUG
     312                 :            :                 logprint (LOG_ERROR, "WARNING: delta rejected at t = %.3e, h = %.3e "
     313                 :         65 :                           "(no convergence)\n", (double) saveCurrent, (double) delta);
     314                 :            : #endif
     315                 :         65 :                 break;
     316                 :            :             default:
     317                 :            :                 // Otherwise return.
     318                 :          0 :                 estack.print ();
     319                 :          0 :                 error++;
     320                 :         65 :                 break;
     321                 :            :             }
     322                 :            :             // return if any errors occured other than convergence failure
     323         [ -  + ]:     214485 :             if (error) return -1;
     324                 :            : 
     325                 :            :             // if the step was rejected, the solution loop is restarted here
     326         [ +  + ]:     214485 :             if (rejected) continue;
     327                 :            : 
     328                 :            :             // check whether Jacobian matrix is still non-singular
     329         [ -  + ]:     214420 :             if (!A->isFinite ())
     330                 :            :             {
     331                 :            :                 logprint (LOG_ERROR, "ERROR: %s: Jacobian singular at t = %.3e, "
     332                 :            :                           "aborting %s analysis\n", getName (), (double) current,
     333                 :          0 :                           getDescription ());
     334                 :          0 :                 return -1;
     335                 :            :             }
     336                 :            : 
     337                 :            :             // Update statistics and no more damped Newton-Raphson.
     338                 :     214420 :             statIterations += iterations;
     339         [ +  + ]:     214420 :             if (--convError < 0) convHelper = 0;
     340                 :            : 
     341                 :            :             // Now advance in time or not...
     342         [ +  + ]:     214420 :             if (running > 1)
     343                 :            :             {
     344                 :     214290 :                 adjustDelta (time);
     345                 :     214290 :                 adjustOrder ();
     346                 :            :             }
     347                 :            :             else
     348                 :            :             {
     349                 :        130 :                 fillStates ();
     350                 :        130 :                 nextStates ();
     351                 :        130 :                 rejected = 0;
     352                 :            :             }
     353                 :            : 
     354                 :     214420 :             saveCurrent = current;
     355                 :     214420 :             current += delta;
     356                 :     214420 :             running++;
     357                 :     214420 :             converged++;
     358                 :            : 
     359                 :            :             // Tell integrators to be running.
     360                 :     214420 :             setMode (MODE_NONE);
     361                 :            : 
     362                 :            :             // Initialize or update history.
     363         [ +  + ]:     214420 :             if (running > 1)
     364                 :            :             {
     365                 :     214355 :                 updateHistory (saveCurrent);
     366                 :            :             }
     367                 :            :             else
     368                 :            :             {
     369                 :         65 :                 initHistory (saveCurrent);
     370                 :            :             }
     371                 :            :         }
     372                 :            :         while (saveCurrent < time); // Hit a requested time point?
     373                 :            : 
     374                 :            :         // Save results.
     375                 :            : #if STEPDEBUG
     376                 :            :         logprint (LOG_STATUS, "DEBUG: save point at t = %.3e, h = %.3e\n",
     377                 :            :                   (double) saveCurrent, (double) delta);
     378                 :            : #endif
     379                 :            : 
     380                 :            : #if BREAKPOINTS
     381                 :            :         saveAllResults (saveCurrent);
     382                 :            : #else
     383                 :      43177 :         saveAllResults (time);
     384                 :            : #endif
     385                 :            :     } // for (int i = 0; i < swp->getSize (); i++)
     386                 :            : 
     387                 :         65 :     solve_post ();
     388         [ +  + ]:         65 :     if (progress) logprogressclear (40);
     389                 :            :     logprint (LOG_STATUS, "NOTIFY: %s: average time-step %g, %d rejections\n",
     390                 :         65 :               getName (), (double) (saveCurrent / statSteps), statRejected);
     391                 :            :     logprint (LOG_STATUS, "NOTIFY: %s: average NR-iterations %g, "
     392                 :            :               "%d non-convergences\n", getName (),
     393                 :         65 :               (double) statIterations / statSteps, statConvergence);
     394                 :            : 
     395                 :            :     // cleanup
     396                 :         65 :     deinitTR ();
     397                 :         65 :     return 0;
     398                 :            : }
     399                 :            : 
     400                 :            : // The function initializes the history.
     401                 :         65 : void trsolver::initHistory (nr_double_t t)
     402                 :            : {
     403                 :            :     // initialize time vector
     404         [ +  - ]:         65 :     tHistory = new history ();
     405                 :         65 :     tHistory->append (t);
     406                 :         65 :     tHistory->self ();
     407                 :            :     // initialize circuit histories
     408                 :         65 :     nr_double_t age = 0.0;
     409                 :         65 :     circuit * root = subnet->getRoot ();
     410         [ +  + ]:        805 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     411                 :            :     {
     412         [ -  + ]:        740 :         if (c->hasHistory ())
     413                 :            :         {
     414                 :          0 :             c->applyHistory (tHistory);
     415                 :          0 :             saveHistory (c);
     416         [ #  # ]:          0 :             if (c->getHistoryAge () > age)
     417                 :            :             {
     418                 :          0 :                 age = c->getHistoryAge ();
     419                 :            :             }
     420                 :            :         }
     421                 :            :     }
     422                 :            :     // set maximum required age for all circuits
     423                 :         65 :     tHistory->setAge (age);
     424                 :         65 : }
     425                 :            : 
     426                 :            : /* The following function updates the histories for the circuits which
     427                 :            :    requested them. */
     428                 :     214355 : void trsolver::updateHistory (nr_double_t t)
     429                 :            : {
     430         [ +  + ]:     214355 :     if (t > tHistory->last ())
     431                 :            :     {
     432                 :            :         // update time vector
     433                 :     192404 :         tHistory->append (t);
     434                 :            :         // update circuit histories
     435                 :     192404 :         circuit * root = subnet->getRoot ();
     436         [ +  + ]:    1981771 :         for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     437                 :            :         {
     438         [ -  + ]:    1789367 :             if (c->hasHistory ()) saveHistory (c);
     439                 :            :         }
     440                 :     192404 :         tHistory->drop ();
     441                 :            :     }
     442                 :     214355 : }
     443                 :            : 
     444                 :            : // Stores node voltages and branch currents in the given circuits history.
     445                 :          0 : void trsolver::saveHistory (circuit * c)
     446                 :            : {
     447                 :            : 
     448                 :          0 :     int N = countNodes ();
     449                 :          0 :     int r, i, s = c->getSize ();
     450                 :            : 
     451         [ #  # ]:          0 :     for (i = 0; i < s; i++)
     452                 :            :     {
     453                 :            :         // save node voltages
     454                 :          0 :         r = findAssignedNode (c, i);
     455         [ #  # ]:          0 :         if (r < 0)
     456                 :            :             // the node was not found, append a zero to the history
     457                 :            :             // matching this index
     458                 :          0 :             c->appendHistory (i, 0.0);
     459                 :            :         else
     460                 :            :             // the node was found, append the voltage value to
     461                 :            :             // that node's history
     462                 :          0 :             c->appendHistory (i, x->get (r));
     463                 :            :     }
     464                 :            : 
     465         [ #  # ]:          0 :     for (i = 0; i < c->getVoltageSources (); i++)
     466                 :            :     {
     467                 :            :         // save branch currents
     468                 :          0 :         r = c->getVoltageSource () + i;
     469                 :          0 :         c->appendHistory (i + s, x->get (r + N));
     470                 :            :     }
     471                 :            : 
     472                 :          0 : }
     473                 :            : 
     474                 :            : /* This function predicts a start value for the solution vector for
     475                 :            :    the successive iterative corrector process. */
     476                 :     214485 : int trsolver::predictor (void)
     477                 :            : {
     478                 :     214485 :     int error = 0;
     479   [ +  +  +  - ]:     214485 :     switch (predType)
     480                 :            :     {
     481                 :            :     case INTEGRATOR_GEAR: // explicit GEAR
     482                 :       1671 :         predictGear ();
     483                 :       1671 :         break;
     484                 :            :     case INTEGRATOR_ADAMSBASHFORD: // ADAMS-BASHFORD
     485                 :     212616 :         predictBashford ();
     486                 :     212616 :         break;
     487                 :            :     case INTEGRATOR_EULER: // FORWARD EULER
     488                 :        198 :         predictEuler ();
     489                 :        198 :         break;
     490                 :            :     default:
     491                 :          0 :         *x = *SOL (1);  // This is too a simple predictor...
     492                 :          0 :         break;
     493                 :            :     }
     494                 :     214485 :     saveSolution ();
     495                 :     214485 :     *SOL (0) = *x;
     496                 :     214485 :     return error;
     497                 :            : }
     498                 :            : 
     499                 :            : // Stores the given vector into all the solution vectors.
     500                 :         65 : void trsolver::fillSolution (tvector<nr_double_t> * s)
     501                 :            : {
     502         [ +  + ]:        585 :     for (int i = 0; i < 8; i++) *SOL (i) = *s;
     503                 :         65 : }
     504                 :            : 
     505                 :            : /* The function predicts the successive solution vector using the
     506                 :            :    explicit Adams-Bashford integration formula. */
     507                 :     212616 : void trsolver::predictBashford (void)
     508                 :            : {
     509                 :     212616 :     int N = countNodes ();
     510                 :     212616 :     int M = countVoltageSources ();
     511                 :            :     nr_double_t xn, dd, hn;
     512                 :            : 
     513                 :            :     // go through each solution
     514         [ +  + ]:    2097318 :     for (int r = 0; r < N + M; r++)
     515                 :            :     {
     516                 :    1884702 :         xn = predCoeff[0] * SOL(1)->get (r); // a0 coefficient
     517         [ +  + ]:    5654106 :         for (int o = 1; o <= predOrder; o++)
     518                 :            :         {
     519                 :    3769404 :             hn = getState (dState, o);         // previous time-step
     520                 :            :             // divided differences
     521                 :    3769404 :             dd = (SOL(o)->get (r) - SOL(o + 1)->get (r)) / hn;
     522                 :    3769404 :             xn += predCoeff[o] * dd;           // b0, b1, ... coefficients
     523                 :            :         }
     524                 :    1884702 :         x->set (r, xn);                      // save prediction
     525                 :            :     }
     526                 :     212616 : }
     527                 :            : 
     528                 :            : /* The function predicts the successive solution vector using the
     529                 :            :    explicit forward Euler integration formula.  Actually this is
     530                 :            :    Adams-Bashford order 1. */
     531                 :        198 : void trsolver::predictEuler (void)
     532                 :            : {
     533                 :        198 :     int N = countNodes ();
     534                 :        198 :     int M = countVoltageSources ();
     535                 :            :     nr_double_t xn, dd, hn;
     536                 :            : 
     537         [ +  + ]:       2352 :     for (int r = 0; r < N + M; r++)
     538                 :            :     {
     539                 :       2154 :         xn = predCoeff[0] * SOL(1)->get (r);
     540                 :       2154 :         hn = getState (dState, 1);
     541                 :       2154 :         dd = (SOL(1)->get (r) - SOL(2)->get (r)) / hn;
     542                 :       2154 :         xn += predCoeff[1] * dd;
     543                 :       2154 :         x->set (r, xn);
     544                 :            :     }
     545                 :        198 : }
     546                 :            : 
     547                 :            : /* The function predicts the successive solution vector using the
     548                 :            :    explicit Gear integration formula. */
     549                 :       1671 : void trsolver::predictGear (void)
     550                 :            : {
     551                 :       1671 :     int N = countNodes ();
     552                 :       1671 :     int M = countVoltageSources ();
     553                 :            :     nr_double_t xn;
     554                 :            : 
     555                 :            :     // go through each solution
     556         [ +  + ]:      25065 :     for (int r = 0; r < N + M; r++)
     557                 :            :     {
     558                 :      23394 :         xn = 0;
     559         [ +  + ]:      70182 :         for (int o = 0; o <= predOrder; o++)
     560                 :            :         {
     561                 :            :             // a0, a1, ... coefficients
     562                 :      46788 :             xn += predCoeff[o] * SOL(o + 1)->get (r);
     563                 :            :         }
     564                 :      23394 :         x->set (r, xn); // save prediction
     565                 :            :     }
     566                 :       1671 : }
     567                 :            : 
     568                 :            : /* The function iterates through the solutions of the integration
     569                 :            :    process until a certain error tolerance has been reached. */
     570                 :     214485 : int trsolver::corrector (void)
     571                 :            : {
     572                 :     214485 :     int error = 0;
     573                 :     214485 :     error += solve_nonlinear ();
     574                 :     214485 :     return error;
     575                 :            : }
     576                 :            : 
     577                 :            : // The function advances one more time-step.
     578                 :     192455 : void trsolver::nextStates (void)
     579                 :            : {
     580                 :     192455 :     circuit * root = subnet->getRoot ();
     581         [ +  + ]:    1982427 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     582                 :            :     {
     583                 :            :         // for each circuit get the next state
     584                 :    1789972 :         c->nextState ();
     585                 :            :     }
     586                 :            : 
     587                 :     192455 :     *SOL (0) = *x; // save current solution
     588                 :     192455 :     nextState ();
     589                 :     192455 :     statSteps++;
     590                 :     192455 : }
     591                 :            : 
     592                 :            : /* This function stores the current state of each circuit into all
     593                 :            :    other states as well.  It is useful for higher order integration
     594                 :            :    methods in order to initialize the states after the initial
     595                 :            :    transient solution. */
     596                 :        130 : void trsolver::fillStates (void)
     597                 :            : {
     598                 :        130 :     circuit * root = subnet->getRoot ();
     599         [ +  + ]:       1610 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     600                 :            :     {
     601         [ +  + ]:       2708 :         for (int s = 0; s < c->getStates (); s++)
     602                 :       1228 :             c->fillState (s, c->getState (s));
     603                 :            :     }
     604                 :        130 : }
     605                 :            : 
     606                 :            : // The function modifies the circuit lists integrator mode.
     607                 :     214485 : void trsolver::setMode (int state)
     608                 :            : {
     609                 :     214485 :     circuit * root = subnet->getRoot ();
     610         [ +  + ]:    2199981 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     611                 :    1985496 :         c->setMode (state);
     612                 :     214485 : }
     613                 :            : 
     614                 :            : // The function passes the time delta array to the circuit list.
     615                 :         65 : void trsolver::setDelta (void)
     616                 :            : {
     617                 :         65 :     circuit * root = subnet->getRoot ();
     618         [ +  + ]:        805 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     619                 :        740 :         c->setDelta (deltas);
     620                 :         65 : }
     621                 :            : 
     622                 :            : /* This function tries to adapt the current time-step according to the
     623                 :            :    global truncation error. */
     624                 :     214290 : void trsolver::adjustDelta (nr_double_t t)
     625                 :            : {
     626                 :     214290 :     deltaOld = delta;
     627                 :     214290 :     delta = checkDelta ();
     628         [ +  + ]:     214290 :     if (delta > deltaMax) delta = deltaMax;
     629         [ +  + ]:     214290 :     if (delta < deltaMin) delta = deltaMin;
     630                 :            : 
     631                 :            :     // delta correction in order to hit exact breakpoint
     632                 :     214290 :     int good = 0;
     633         [ +  + ]:     214290 :     if (!relaxTSR)   // relaxed step raster?
     634                 :            :     {
     635 [ +  + ][ +  + ]:     212681 :         if (!statConvergence || converged > 64)   /* Is this a good guess? */
     636                 :            :         {
     637                 :            :             // check next breakpoint
     638         [ +  + ]:     212424 :             if (stepDelta > 0.0)
     639                 :            :             {
     640                 :            :                 // restore last valid delta
     641                 :      59546 :                 delta = stepDelta;
     642                 :      59546 :                 stepDelta = -1.0;
     643                 :            :             }
     644                 :            :             else
     645                 :            :             {
     646 [ +  + ][ +  + ]:     152878 :                 if (delta > (t - current) && t > current)
     647                 :            :                 {
     648                 :            :                     // save last valid delta and set exact step
     649                 :      59546 :                     stepDelta = deltaOld;
     650                 :      59546 :                     delta = t - current;
     651                 :      59546 :                     good = 1;
     652                 :            :                 }
     653                 :            :                 else
     654                 :            :                 {
     655                 :      93332 :                     stepDelta = -1.0;
     656                 :            :                 }
     657                 :            :             }
     658         [ -  + ]:     212424 :             if (delta > deltaMax) delta = deltaMax;
     659         [ +  + ]:     212424 :             if (delta < deltaMin) delta = deltaMin;
     660                 :            :         }
     661                 :            :     }
     662                 :            : 
     663                 :            :     // usual delta correction
     664 [ +  + ][ +  + ]:     214290 :     if (delta > 0.9 * deltaOld || good)   // accept current delta
     665                 :            :     {
     666                 :     192325 :         nextStates ();
     667                 :     192325 :         rejected = 0;
     668                 :            : #if STEPDEBUG
     669                 :            :         logprint (LOG_STATUS,
     670                 :            :                   "DEBUG: delta accepted at t = %.3e, h = %.3e\n",
     671                 :            :                   (double) current, (double) delta);
     672                 :            : #endif
     673                 :            :     }
     674         [ +  - ]:      21965 :     else if (deltaOld > delta)   // reject current delta
     675                 :            :     {
     676                 :      21965 :         rejected++;
     677                 :      21965 :         statRejected++;
     678                 :            : #if STEPDEBUG
     679                 :            :         logprint (LOG_STATUS,
     680                 :            :                   "DEBUG: delta rejected at t = %.3e, h = %.3e\n",
     681                 :            :                   (double) current, (double) delta);
     682                 :            : #endif
     683         [ +  - ]:      21965 :         if (current > 0) current -= deltaOld;
     684                 :            :     }
     685                 :            :     else
     686                 :            :     {
     687                 :          0 :         nextStates ();
     688                 :          0 :         rejected = 0;
     689                 :            :     }
     690                 :     214290 : }
     691                 :            : 
     692                 :            : /* The function can be used to increase the current order of the
     693                 :            :    integration method or to reduce it. */
     694                 :     214369 : void trsolver::adjustOrder (int reduce)
     695                 :            : {
     696 [ +  + ][ +  + ]:     214369 :     if ((corrOrder < corrMaxOrder && !rejected) || reduce)
                 [ +  + ]
     697                 :            :     {
     698         [ +  + ]:        143 :         if (reduce)
     699                 :            :         {
     700                 :         79 :             corrOrder = 1;
     701                 :            :         }
     702         [ +  - ]:         64 :         else if (!rejected)
     703                 :            :         {
     704                 :         64 :             corrOrder++;
     705                 :            :         }
     706                 :            : 
     707                 :            :         // adjust type and order of corrector and predictor
     708                 :        143 :         corrType = correctorType (CMethod, corrOrder);
     709                 :        143 :         predType = predictorType (corrType, corrOrder, predOrder);
     710                 :            : 
     711                 :            :         // apply new corrector method and order to each circuit
     712                 :        143 :         circuit * root = subnet->getRoot ();
     713         [ +  + ]:       1805 :         for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     714                 :            :         {
     715                 :       1662 :             c->setOrder (corrOrder);
     716                 :       1662 :             setIntegrationMethod (c, corrType);
     717                 :            :         }
     718                 :            :     }
     719                 :     214369 : }
     720                 :            : 
     721                 :            : /* Goes through the list of circuit objects and runs its calcDC()
     722                 :            :    function. */
     723                 :        267 : void trsolver::calcDC (trsolver * self)
     724                 :            : {
     725                 :        267 :     circuit * root = self->getNet()->getRoot ();
     726         [ +  + ]:       4525 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     727                 :            :     {
     728                 :       4258 :         c->calcDC ();
     729                 :            :     }
     730                 :        267 : }
     731                 :            : 
     732                 :            : /* Goes through the list of circuit objects and runs its calcTR()
     733                 :            :    function. */
     734                 :     483576 : void trsolver::calcTR (trsolver * self)
     735                 :            : {
     736                 :     483576 :     circuit * root = self->getNet()->getRoot ();
     737         [ +  + ]:    5148245 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     738                 :            :     {
     739                 :    4664669 :         c->calcTR (self->current);
     740                 :            :     }
     741                 :     483576 : }
     742                 :            : 
     743                 :            : /* Goes through the list of non-linear circuit objects and runs its
     744                 :            :    restartDC() function. */
     745                 :      22030 : void trsolver::restart (void)
     746                 :            : {
     747                 :      22030 :     circuit * root = subnet->getRoot ();
     748         [ +  + ]:     217710 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     749                 :            :     {
     750         [ +  + ]:     195680 :         if (c->isNonLinear ()) c->restartDC ();
     751                 :            :     }
     752                 :      22030 : }
     753                 :            : 
     754                 :            : /* Goes through the list of circuit objects and runs its initDC()
     755                 :            :    function. */
     756                 :         64 : void trsolver::initDC (void)
     757                 :            : {
     758                 :         64 :     circuit * root = subnet->getRoot ();
     759         [ +  + ]:        766 :     for (circuit * c = root; c != NULL; c = (circuit *) c->getNext ())
     760                 :            :     {
     761                 :        702 :         c->initDC ();
     762                 :            :     }
     763                 :         64 : }
     764                 :            : 
     765                 :            : /* Goes through the list of circuit objects and runs its initTR()
     766                 :            :    function. */
     767                 :         65 : void trsolver::initTR (void)
     768                 :            : {
     769                 :         65 :     const char * const IMethod = getPropertyString ("IntegrationMethod");
     770                 :         65 :     nr_double_t start = getPropertyDouble ("Start");
     771                 :         65 :     nr_double_t stop = getPropertyDouble ("Stop");
     772                 :         65 :     nr_double_t points = getPropertyDouble ("Points");
     773                 :            : 
     774                 :            :     // fetch corrector integration method and determine predicor method
     775                 :         65 :     corrMaxOrder = getPropertyInteger ("Order");
     776                 :         65 :     corrType = CMethod = correctorType (IMethod, corrMaxOrder);
     777                 :         65 :     predType = PMethod = predictorType (CMethod, corrMaxOrder, predMaxOrder);
     778                 :         65 :     corrOrder = corrMaxOrder;
     779                 :         65 :     predOrder = predMaxOrder;
     780                 :            : 
     781                 :            :     // initialize step values
     782                 :         65 :     delta = getPropertyDouble ("InitialStep");
     783                 :         65 :     deltaMin = getPropertyDouble ("MinStep");
     784                 :         65 :     deltaMax = getPropertyDouble ("MaxStep");
     785         [ +  + ]:         65 :     if (deltaMax == 0.0)
     786         [ +  + ]:         62 :         deltaMax = MIN ((stop - start) / (points - 1), stop / 200);
     787         [ -  + ]:         65 :     if (deltaMin == 0.0)
     788                 :          0 :         deltaMin = NR_TINY * 10 * deltaMax;
     789         [ -  + ]:         65 :     if (delta == 0.0)
     790         [ #  # ]:          0 :         delta = MIN (stop / 200, deltaMax) / 10;
     791         [ +  + ]:         65 :     if (delta < deltaMin) delta = deltaMin;
     792         [ +  + ]:         65 :     if (delta > deltaMax) delta = deltaMax;
     793                 :            : 
     794                 :            :     // initialize step history
     795                 :         65 :     setStates (2);
     796                 :         65 :     initStates ();
     797                 :            :     // initialise the history of states, setting them all to 'delta'
     798                 :         65 :     fillState (dState, delta);
     799                 :            : 
     800                 :            :     // copy the initialised states to the 'deltas' array
     801                 :         65 :     saveState (dState, deltas);
     802                 :            :     // copy the deltas to all the circuits
     803                 :         65 :     setDelta ();
     804                 :            :     // set the initial corrector and predictor coefficients
     805                 :         65 :     calcCorrectorCoeff (corrType, corrOrder, corrCoeff, deltas);
     806                 :         65 :     calcPredictorCoeff (predType, predOrder, predCoeff, deltas);
     807                 :            : 
     808                 :            :     // initialize history of solution vectors (solutions)
     809         [ +  + ]:        585 :     for (int i = 0; i < 8; i++)
     810                 :            :     {
     811                 :            :         // solution contains the last sets of node voltages and branch
     812                 :            :         // currents at each of the last 8 'deltas'.
     813                 :            :         // Note for convenience the definition:
     814                 :            :         //   #define SOL(state) (solution[(int) getState (sState, (state))])
     815                 :            :         // is provided and used elsewhere to update the solutions
     816                 :        520 :         solution[i] = new tvector<nr_double_t>;
     817                 :        520 :         setState (sState, (nr_double_t) i, i);
     818                 :            :     }
     819                 :            : 
     820                 :            :     // tell circuits about the transient analysis
     821                 :         65 :     circuit *c, * root = subnet->getRoot ();
     822         [ +  + ]:        805 :     for (c = root; c != NULL; c = (circuit *) c->getNext ())
     823                 :        740 :         initCircuitTR (c);
     824                 :            :     // also initialize created circuits
     825         [ +  + ]:        130 :     for (c = root; c != NULL; c = (circuit *) c->getPrev ())
     826                 :         65 :         initCircuitTR (c);
     827                 :         65 : }
     828                 :            : 
     829                 :            : // This function cleans up some memory used by the transient analysis.
     830                 :         65 : void trsolver::deinitTR (void)
     831                 :            : {
     832                 :            :     // cleanup solutions
     833         [ +  + ]:        585 :     for (int i = 0; i < 8; i++)
     834                 :            :     {
     835         [ +  - ]:        520 :         delete solution[i];
     836                 :        520 :         solution[i] = NULL;
     837                 :            :     }
     838                 :            :     // cleanup history
     839         [ +  - ]:         65 :     if (tHistory)
     840                 :            :     {
     841         [ +  - ]:         65 :         delete tHistory;
     842                 :         65 :         tHistory = NULL;
     843                 :            :     }
     844                 :         65 : }
     845                 :            : 
     846                 :            : // The function initialize a single circuit.
     847                 :        805 : void trsolver::initCircuitTR (circuit * c)
     848                 :            : {
     849                 :        805 :     c->initTR ();
     850                 :        805 :     c->initStates ();
     851                 :        805 :     c->setCoefficients (corrCoeff);
     852                 :        805 :     c->setOrder (corrOrder);
     853                 :        805 :     setIntegrationMethod (c, corrType);
     854                 :        805 : }
     855                 :            : 
     856                 :            : /* This function saves the results of a single solve() functionality
     857                 :            :    (for the given timestamp) into the output dataset. */
     858                 :      43177 : void trsolver::saveAllResults (nr_double_t time)
     859                 :            : {
     860                 :            :     qucs::vector * t;
     861                 :            :     // add current frequency to the dependency of the output dataset
     862         [ +  + ]:      43177 :     if ((t = data->findDependency ("time")) == NULL)
     863                 :            :     {
     864         [ +  - ]:         38 :       t = new qucs::vector ("time");
     865                 :         38 :         data->addDependency (t);
     866                 :            :     }
     867 [ +  + ][ +  - ]:      43177 :     if (runs == 1) t->add (time);
     868                 :      43177 :     saveResults ("Vt", "It", 0, t);
     869                 :      43177 : }
     870                 :            : 
     871                 :            : /* This function is meant to adapt the current time-step the transient
     872                 :            :    analysis advanced.  For the computation of the new time-step the
     873                 :            :    truncation error depending on the integration method is used. */
     874                 :     214290 : nr_double_t trsolver::checkDelta (void)
     875                 :            : {
     876                 :     214290 :     nr_double_t LTEreltol = getPropertyDouble ("LTEreltol");
     877                 :     214290 :     nr_double_t LTEabstol = getPropertyDouble ("LTEabstol");
     878                 :     214290 :     nr_double_t LTEfactor = getPropertyDouble ("LTEfactor");
     879                 :     214290 :     nr_double_t dif, rel, tol, lte, q, n =  std::numeric_limits<nr_double_t>::max();
     880                 :     214290 :     int N = countNodes ();
     881                 :     214290 :     int M = countVoltageSources ();
     882                 :            : 
     883                 :            :     // cec = corrector error constant
     884                 :     214290 :     nr_double_t cec = getCorrectorError (corrType, corrOrder);
     885                 :            :     // pec = predictor error constant
     886                 :     214290 :     nr_double_t pec = getPredictorError (predType, predOrder);
     887                 :            : 
     888                 :            :     // go through each solution
     889         [ +  + ]:    2122231 :     for (int r = 0; r < N + M; r++)
     890                 :            :     {
     891                 :            : 
     892                 :            :         // skip real voltage sources
     893         [ +  + ]:    1907941 :         if (r >= N)
     894                 :            :         {
     895         [ +  + ]:     798433 :             if (findVoltageSource(r - N)->isVSource ())
     896                 :     421843 :                 continue;
     897                 :            :         }
     898                 :            : 
     899                 :    1486098 :         dif = x->get (r) - SOL(0)->get (r);
     900 [ +  - ][ +  + ]:    1486098 :         if (std::isfinite (dif) && dif != 0)
                 [ +  + ]
     901                 :            :         {
     902                 :            :             // use Milne' estimate for the local truncation error
     903         [ +  + ]:    1210811 :             rel = MAX (fabs (x->get (r)), fabs (SOL(0)->get (r)));
     904                 :    1210811 :             tol = LTEreltol * rel + LTEabstol;
     905                 :    1210811 :             lte = LTEfactor * (cec / (pec - cec)) * dif;
     906                 :    1210811 :             q =  delta * exp (log (fabs (tol / lte)) / (corrOrder + 1));
     907         [ +  + ]:    1210811 :             n = MIN (n, q);
     908                 :            :         }
     909                 :            :     }
     910                 :            : #if STEPDEBUG
     911                 :            :     logprint (LOG_STATUS, "DEBUG: delta according to local truncation "
     912                 :            :               "error h = %.3e\n", (double) n);
     913                 :            : #endif
     914 [ +  + ][ +  + ]:     214290 :     delta = MIN ((n > 1.9 * delta) ? 2 * delta : delta, n);
                 [ +  + ]
     915                 :     214290 :     return delta;
     916                 :            : }
     917                 :            : 
     918                 :            : // The function updates the integration coefficients.
     919                 :     214485 : void trsolver::updateCoefficients (nr_double_t delta)
     920                 :            : {
     921                 :     214485 :     setState (dState, delta);
     922                 :     214485 :     saveState (dState, deltas);
     923                 :     214485 :     calcCorrectorCoeff (corrType, corrOrder, corrCoeff, deltas);
     924                 :     214485 :     calcPredictorCoeff (predType, predOrder, predCoeff, deltas);
     925                 :     214485 : }
     926                 :            : 
     927                 :            : // properties
     928                 :            : PROP_REQ [] =
     929                 :            : {
     930                 :            :     {
     931                 :            :         "Type", PROP_STR, { PROP_NO_VAL, "lin" },
     932                 :            :         PROP_RNG_STR2 ("lin", "log")
     933                 :            :     },
     934                 :            :     { "Start", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     935                 :            :     { "Stop", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
     936                 :            :     { "Points", PROP_INT, { 10, PROP_NO_STR }, PROP_MIN_VAL (2) },
     937                 :            :     PROP_NO_PROP
     938                 :            : };
     939                 :            : PROP_OPT [] =
     940                 :            : {
     941                 :            :     {
     942                 :            :         "IntegrationMethod", PROP_STR, { PROP_NO_VAL, "Trapezoidal" },
     943                 :            :         PROP_RNG_STR4 ("Euler", "Trapezoidal", "Gear", "AdamsMoulton")
     944                 :            :     },
     945                 :            :     { "Order", PROP_INT, { 2, PROP_NO_STR }, PROP_RNGII (1, 6) },
     946                 :            :     { "InitialStep", PROP_REAL, { 1e-9, PROP_NO_STR }, PROP_POS_RANGE },
     947                 :            :     { "MinStep", PROP_REAL, { 1e-16, PROP_NO_STR }, PROP_POS_RANGE },
     948                 :            :     { "MaxStep", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
     949                 :            :     { "MaxIter", PROP_INT, { 150, PROP_NO_STR }, PROP_RNGII (2, 10000) },
     950                 :            :     { "abstol", PROP_REAL, { 1e-12, PROP_NO_STR }, PROP_RNG_X01I },
     951                 :            :     { "vntol", PROP_REAL, { 1e-6, PROP_NO_STR }, PROP_RNG_X01I },
     952                 :            :     { "reltol", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_RNG_X01I },
     953                 :            :     { "LTEabstol", PROP_REAL, { 1e-6, PROP_NO_STR }, PROP_RNG_X01I },
     954                 :            :     { "LTEreltol", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_RNG_X01I },
     955                 :            :     { "LTEfactor", PROP_REAL, { 1, PROP_NO_STR }, PROP_RNGII (1, 16) },
     956                 :            :     { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
     957                 :            :     { "Solver", PROP_STR, { PROP_NO_VAL, "CroutLU" }, PROP_RNG_SOL },
     958                 :            :     { "relaxTSR", PROP_STR, { PROP_NO_VAL, "no" }, PROP_RNG_YESNO },
     959                 :            :     { "initialDC", PROP_STR, { PROP_NO_VAL, "yes" }, PROP_RNG_YESNO },
     960                 :            :     PROP_NO_PROP
     961                 :            : };
     962                 :            : struct define_t trsolver::anadef =
     963                 :            :     { "TR", 0, PROP_ACTION, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };
     964                 :            : 
     965                 :            : } // namespace qucs

Generated by: LCOV version 1.11