Branch data Line data Source code
1 : : /*
2 : : * parasweep.cpp - parameter sweep class implementation
3 : : *
4 : : * Copyright (C) 2004, 2005, 2006, 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 <stdlib.h>
31 : : #include <string.h>
32 : :
33 : : #include "logging.h"
34 : : #include "complex.h"
35 : : #include "object.h"
36 : : #include "vector.h"
37 : : #include "dataset.h"
38 : : #include "net.h"
39 : : #include "netdefs.h"
40 : : #include "ptrlist.h"
41 : : #include "analysis.h"
42 : : #include "variable.h"
43 : : #include "environment.h"
44 : : #include "sweep.h"
45 : : #include "parasweep.h"
46 : :
47 : : using namespace qucs::eqn;
48 : :
49 : : namespace qucs {
50 : :
51 : : // Constructor creates an unnamed instance of the parasweep class.
52 : 59 : parasweep::parasweep () : analysis () {
53 : 59 : var = NULL;
54 : 59 : swp = NULL;
55 : 59 : eqn = NULL;
56 : 59 : type = ANALYSIS_SWEEP;
57 : 59 : }
58 : :
59 : : // Constructor creates a named instance of the parasweep class.
60 : 0 : parasweep::parasweep (char * n) : analysis (n) {
61 : 0 : var = NULL;
62 : 0 : swp = NULL;
63 : 0 : eqn = NULL;
64 : 0 : type = ANALYSIS_SWEEP;
65 : 0 : }
66 : :
67 : : // Destructor deletes the parasweep class object.
68 : 59 : parasweep::~parasweep () {
69 [ + - ][ + - ]: 59 : if (swp) delete swp;
[ + - ][ # # ]
[ # # ][ # # ]
70 [ - + ][ # # ]: 118 : }
71 : :
72 : : /* The copy constructor creates a new instance of the parasweep class
73 : : based on the given parasweep object. */
74 : 0 : parasweep::parasweep (parasweep & p) : analysis (p) {
75 [ # # ]: 0 : var = new variable (*p.var);
[ # # # # ]
[ # # ]
76 [ # # ][ # # ]: 0 : if (p.swp) swp = new sweep (*p.swp);
[ # # ][ # # ]
[ # # ][ # # ]
77 : 0 : }
78 : :
79 : : // Short macro in order to obtain the correct constant value.
80 : : #define D(con) ((constant *) (con))->d
81 : : #define E(equ) ((eqn::node *) (equ))
82 : :
83 : : /* Initializes the parameter sweep. */
84 : 59 : int parasweep::initialize (void) {
85 : : constant * val;
86 : :
87 : : // get fixed simulation properties
88 : 59 : const char * const n = getPropertyString ("Param");
89 : :
90 : : // create sweep if necessary
91 [ + - ]: 59 : if (swp == NULL) {
92 : 59 : swp = createSweep (n);
93 : : }
94 : :
95 : : // get parameter name and the appropriate variable from the current
96 : : // environment, possibly add the variable to the environment if it
97 : : // does not exist yet (which is somehow useless at all)
98 [ - + ]: 59 : if ((var = env->getVariable (n)) == NULL) {
99 [ # # ]: 0 : var = new variable (n);
100 [ # # ]: 0 : val = new constant (TAG_DOUBLE);
101 : 0 : var->setConstant (val);
102 : 0 : env->addVariable (var);
103 : : }
104 : 59 : else val = var->getConstant ();
105 : :
106 : : // put variable also into equation checker if necessary
107 [ + - ]: 59 : if (!env->getChecker()->containsVariable (n)) {
108 : 59 : eqn = env->getChecker()->addDouble ("#sweep", n, 0);
109 : : }
110 : :
111 : : // initialize first sweep value in environment and equation checker
112 : 59 : nr_double_t v = swp->get (0);
113 : 59 : env->setDoubleConstant (n, v);
114 : 59 : env->setDouble (n, v);
115 : :
116 : : // also run initialize functionality for all children
117 [ + - ]: 59 : if (actions != nullptr) {
118 [ + + ]: 118 : for (auto *a : *actions) {
119 [ + - ]: 59 : a->initialize ();
120 : 59 : a->setProgress (false);
121 : : }
122 : : }
123 : 59 : return 0;
124 : : }
125 : :
126 : : /* Cleans the parameter sweep up. */
127 : 59 : int parasweep::cleanup (void) {
128 : :
129 : : // remove additional equation from equation checker
130 [ + - ]: 59 : if (eqn) {
131 : 59 : env->getChecker()->dropEquation (E (eqn));
132 [ + - ]: 59 : delete E (eqn);
133 : 59 : eqn = NULL;
134 : : }
135 : :
136 : : // also run cleanup functionality for all children
137 [ + - ]: 59 : if( actions != nullptr)
138 [ + + ]: 118 : for (auto *a : *actions)
139 [ + - ]: 59 : a->cleanup ();
140 : :
141 : 59 : return 0;
142 : : }
143 : :
144 : : /* This is the parameter sweep solver. */
145 : 183 : int parasweep::solve (void) {
146 : 183 : int err = 0;
147 : 183 : runs++;
148 : :
149 : : // get fixed simulation properties
150 : 183 : const char * const n = getPropertyString ("Param");
151 : :
152 : : // run the parameter sweep
153 : 183 : swp->reset ();
154 [ + + ]: 22863 : for (int i = 0; i < swp->getSize (); i++) {
155 : : // obtain next sweep point
156 : 22680 : nr_double_t v = swp->next ();
157 : : // display progress bar if requested
158 [ + + ]: 22680 : if (progress) logprogressbar (i, swp->getSize (), 40);
159 : : // update environment and equation checker, then run solver
160 : 22680 : env->setDoubleConstant (n, v);
161 : 22680 : env->setDouble (n, v);
162 : 22680 : env->runSolver ();
163 : : // save results (swept parameter values)
164 [ + + ]: 22680 : if (runs == 1) saveResults ();
165 : : #if DEBUG
166 : : logprint (LOG_STATUS, "NOTIFY: %s: running netlist for %s = %g\n",
167 : 22680 : getName (), n, v);
168 : : #endif
169 [ + + ]: 45360 : for (auto *a : *actions) {
170 [ + - ]: 22680 : err |= a->solve ();
171 : : // assign variable dataset dependencies to last order analyses
172 [ + - ]: 22680 : ptrlist<analysis> * lastorder = subnet->findLastOrderChildren (this);
173 [ + + ]: 45360 : for (auto *dep : *lastorder)
174 [ + - ]: 22680 : data->assignDependency (dep->getName (), var->getName ());
175 : : }
176 : : }
177 : : // clear progress bar
178 [ + + ]: 183 : if (progress) logprogressclear (40);
179 : 183 : return err;
180 : : }
181 : :
182 : : /* This function saves the results of a single solve() functionality
183 : : into the output dataset. */
184 : 14428 : void parasweep::saveResults (void) {
185 : : qucs::vector * v;
186 : :
187 : : // add current frequency to the dependencies of the output dataset
188 [ + + ]: 14428 : if ((v = data->findDependency (var->getName ())) == NULL) {
189 [ + - ]: 59 : v = new qucs::vector (var->getName ());
190 : 59 : v->setOrigin (getName ());
191 : 59 : data->addDependency (v);
192 : : }
193 [ + - ]: 14428 : v->add (D (var->getConstant ()));
194 : 14428 : }
195 : :
196 : : // properties
197 : : PROP_REQ [] = {
198 : : { "Type", PROP_STR, { PROP_NO_VAL, "lin" }, PROP_RNG_TYP },
199 : : { "Param", PROP_STR, { PROP_NO_VAL, "R1" }, PROP_NO_RANGE },
200 : : { "Sim", PROP_STR, { PROP_NO_VAL, "DC1" }, PROP_NO_RANGE },
201 : : PROP_NO_PROP };
202 : : PROP_OPT [] = {
203 : : { "Points", PROP_INT, { 5, PROP_NO_STR }, PROP_MIN_VAL (2) },
204 : : { "Stop", PROP_REAL, { 50, PROP_NO_STR }, PROP_NO_RANGE },
205 : : { "Start", PROP_REAL, { 5, PROP_NO_STR }, PROP_NO_RANGE },
206 : : { "Values", PROP_LIST, { 5, PROP_NO_STR }, PROP_NO_RANGE },
207 : : PROP_NO_PROP };
208 : : struct define_t parasweep::anadef =
209 : : { "SW", 0, PROP_ACTION, PROP_NO_SUBSTRATE, PROP_LINEAR, PROP_DEF };
210 : :
211 : : } // namespace qucs
|