Qucs-core  0.0.19
parasweep.cpp
Go to the documentation of this file.
00001 /*
00002  * parasweep.cpp - parameter sweep class implementation
00003  *
00004  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Stefan Jahn <stefan@lkcc.org>
00005  *
00006  * This is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2, or (at your option)
00009  * any later version.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this package; see the file COPYING.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  *
00021  * $Id$
00022  *
00023  */
00024 
00025 #if HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 
00033 #include "logging.h"
00034 #include "complex.h"
00035 #include "object.h"
00036 #include "vector.h"
00037 #include "dataset.h"
00038 #include "net.h"
00039 #include "netdefs.h"
00040 #include "ptrlist.h"
00041 #include "analysis.h"
00042 #include "variable.h"
00043 #include "environment.h"
00044 #include "sweep.h"
00045 #include "parasweep.h"
00046 
00047 using namespace qucs::eqn;
00048 
00049 namespace qucs {
00050 
00051 // Constructor creates an unnamed instance of the parasweep class.
00052 parasweep::parasweep () : analysis () {
00053   var = NULL;
00054   swp = NULL;
00055   eqn = NULL;
00056   type = ANALYSIS_SWEEP;
00057 }
00058 
00059 // Constructor creates a named instance of the parasweep class.
00060 parasweep::parasweep (char * n) : analysis (n) {
00061   var = NULL;
00062   swp = NULL;
00063   eqn = NULL;
00064   type = ANALYSIS_SWEEP;
00065 }
00066 
00067 // Destructor deletes the parasweep class object.
00068 parasweep::~parasweep () {
00069   delete swp;
00070 }
00071 
00072 /* The copy constructor creates a new instance of the parasweep class
00073    based on the given parasweep object. */
00074 parasweep::parasweep (parasweep & p) : analysis (p) {
00075   var = new variable (*p.var);
00076   if (p.swp) swp = new sweep (*p.swp);
00077 }
00078 
00079 // Short macro in order to obtain the correct constant value.
00080 #define D(con) ((constant *) (con))->d
00081 #define E(equ) ((eqn::node *) (equ))
00082 
00083 /* Initializes the parameter sweep. */
00084 int parasweep::initialize (void) {
00085   constant * val;
00086 
00087   // get fixed simulation properties
00088   const char * const n = getPropertyString ("Param");
00089 
00090   // create sweep if necessary
00091   if (swp == NULL) {
00092     swp = createSweep (n);
00093   }
00094 
00095   // get parameter name and the appropriate variable from the current
00096   // environment, possibly add the variable to the environment if it
00097   // does not exist yet (which is somehow useless at all)
00098   if ((var = env->getVariable (n)) == NULL) {
00099     var = new variable (n);
00100     val = new constant (TAG_DOUBLE);
00101     var->setConstant (val);
00102     env->addVariable (var);
00103   }
00104   else val = var->getConstant ();
00105 
00106   // put variable also into equation checker if necessary
00107   if (!env->getChecker()->containsVariable (n)) {
00108     eqn = env->getChecker()->addDouble ("#sweep", n, 0);
00109   }
00110 
00111   // initialize first sweep value in environment and equation checker
00112   nr_double_t v = swp->get (0);
00113   env->setDoubleConstant (n, v);
00114   env->setDouble (n, v);
00115 
00116   // also run initialize functionality for all children
00117   if (actions != nullptr) {
00118     for (auto *a : *actions) {
00119       a->initialize ();
00120       a->setProgress (false);
00121     }
00122   }
00123   return 0;
00124 }
00125 
00126 /* Cleans the parameter sweep up. */
00127 int parasweep::cleanup (void) {
00128 
00129   // remove additional equation from equation checker
00130   if (eqn) {
00131     env->getChecker()->dropEquation (E (eqn));
00132     delete E (eqn);
00133     eqn = NULL;
00134   }
00135 
00136   // also run cleanup functionality for all children
00137   if( actions != nullptr)
00138     for (auto *a : *actions)
00139       a->cleanup ();
00140 
00141   return 0;
00142 }
00143 
00144 /* This is the parameter sweep solver. */
00145 int parasweep::solve (void) {
00146   int err = 0;
00147   runs++;
00148 
00149   // get fixed simulation properties
00150   const char * const n = getPropertyString ("Param");
00151 
00152   // run the parameter sweep
00153   swp->reset ();
00154   for (int i = 0; i < swp->getSize (); i++) {
00155     // obtain next sweep point
00156     nr_double_t v = swp->next ();
00157     // display progress bar if requested
00158     if (progress) logprogressbar (i, swp->getSize (), 40);
00159     // update environment and equation checker, then run solver
00160     env->setDoubleConstant (n, v);
00161     env->setDouble (n, v);
00162     env->runSolver ();
00163     // save results (swept parameter values)
00164     if (runs == 1) saveResults ();
00165 #if DEBUG
00166     logprint (LOG_STATUS, "NOTIFY: %s: running netlist for %s = %g\n",
00167               getName (), n, v);
00168 #endif
00169     for (auto *a : *actions) {
00170       err |= a->solve ();
00171       // assign variable dataset dependencies to last order analyses
00172       ptrlist<analysis> * lastorder = subnet->findLastOrderChildren (this);
00173       for (auto *dep : *lastorder)
00174         data->assignDependency (dep->getName (), var->getName ());
00175     }
00176   }
00177   // clear progress bar
00178   if (progress) logprogressclear (40);
00179   return err;
00180 }
00181 
00182 /* This function saves the results of a single solve() functionality
00183    into the output dataset. */
00184 void parasweep::saveResults (void) {
00185   qucs::vector * v;
00186 
00187   // add current frequency to the dependencies of the output dataset
00188   if ((v = data->findDependency (var->getName ())) == NULL) {
00189     v = new qucs::vector (var->getName ());
00190     v->setOrigin (getName ());
00191     data->addDependency (v);
00192   }
00193   v->add (D (var->getConstant ()));
00194 }
00195 
00196 // properties
00197 PROP_REQ [] = {
00198   { "Type", PROP_STR, { PROP_NO_VAL, "lin" }, PROP_RNG_TYP },
00199   { "Param", PROP_STR, { PROP_NO_VAL, "R1" }, PROP_NO_RANGE },
00200   { "Sim", PROP_STR, { PROP_NO_VAL, "DC1" }, PROP_NO_RANGE },
00201   PROP_NO_PROP };
00202 PROP_OPT [] = {
00203   { "Points", PROP_INT, { 5, PROP_NO_STR }, PROP_MIN_VAL (2) },
00204   { "Stop", PROP_REAL, { 50, PROP_NO_STR }, PROP_NO_RANGE },
00205   { "Start", PROP_REAL, { 5, PROP_NO_STR }, PROP_NO_RANGE },
00206   { "Values", PROP_LIST, { 5, PROP_NO_STR }, PROP_NO_RANGE },
00207   PROP_NO_PROP };
00208 struct define_t parasweep::anadef =
00209   { "SW", 0, PROP_ACTION, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };
00210 
00211 } // namespace qucs