viminfo
[gnucap-felix.git] / apps / s_ac.cc
blob31f6d9b902baf8674b2529072583059b261b6a13
1 /*$Id: s_ac.cc,v 26.137 2010/04/10 02:37:05 al Exp $ -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *------------------------------------------------------------------
22 * ac analysis top
24 //testing=script 2008.08.06
25 #include "globals.h"
26 #include "u_sim_data.h"
27 #include "u_status.h"
28 #include "u_parameter.h"
29 #include "u_prblst.h"
30 #include "s__.h"
31 /*--------------------------------------------------------------------------*/
32 namespace {
33 /*--------------------------------------------------------------------------*/
34 class AC : public SIM {
35 public:
36 void do_it(CS&, CARD_LIST*);
38 explicit AC():
39 SIM(),
40 _start(),
41 _stop(),
42 _step_in(),
43 _step(0.),
44 _linswp(false),
45 _prevopppoint(false),
46 _stepmode(ONE_PT)
49 ~AC() {}
50 private:
51 explicit AC(const AC&):SIM() {unreachable(); incomplete();}
52 void sweep();
53 void first();
54 bool next();
55 void solve();
56 void clear();
57 void setup(CS&);
58 private:
59 PARAMETER<double> _start; // sweep start frequency
60 PARAMETER<double> _stop; // sweep stop frequency
61 PARAMETER<double> _step_in; // step size, as input
62 double _step; // printed step size
63 bool _linswp; // flag: use linear sweep (vs log sweep)
64 bool _prevopppoint; // flag: use previous op point
65 enum {ONE_PT, LIN_STEP, LIN_PTS, TIMES, OCTAVE, DECADE} _stepmode;
67 /*--------------------------------------------------------------------------*/
68 /*--------------------------------------------------------------------------*/
69 void AC::do_it(CS& Cmd, CARD_LIST* Scope)
71 _scope = Scope;
72 _sim->set_command_ac();
73 reset_timers();
74 ::status.ac.reset().start();
76 _sim->init();
77 _sim->alloc_vectors();
78 _sim->_acx.reallocate();
79 _sim->_acx.set_min_pivot(OPT::pivtol);
81 setup(Cmd);
82 ::status.set_up.stop();
83 switch (ENV::run_mode) {
84 case rPRE_MAIN: unreachable(); break;
85 case rBATCH: itested();
86 case rINTERACTIVE: itested();
87 case rSCRIPT: sweep(); break;
88 case rPRESET: /*nothing*/ break;
90 _sim->_acx.unallocate();
91 _sim->unalloc_vectors();
92 _scope = NULL;
94 ::status.ac.stop();
95 ::status.total.stop();
97 /*--------------------------------------------------------------------------*/
98 /*--------------------------------------------------------------------------*/
99 static int needslinfix; // flag: lin option needs patch later (spice compat)
100 /*--------------------------------------------------------------------------*/
101 void AC::setup(CS& Cmd)
103 _out = IO::mstdout;
104 _out.reset(); //BUG// don't know why this is needed
106 //temp_c = OPT::temp_c;
107 // Don't set temperature. Keep whatever was there before,
108 // from "op" or whatever.
110 bool ploton = IO::plotset && plotlist().size() > 0;
112 ONE_OF
113 || (Get(Cmd, "*", &_step_in) && (_stepmode = TIMES))
114 || (Get(Cmd, "+", &_step_in) && (_stepmode = LIN_STEP))
115 || (Get(Cmd, "by", &_step_in) && (_stepmode = LIN_STEP))
116 || (Get(Cmd, "step", &_step_in) && (_stepmode = LIN_STEP))
117 || (Get(Cmd, "d{ecade}", &_step_in) && (_stepmode = DECADE))
118 || (Get(Cmd, "ti{mes}", &_step_in) && (_stepmode = TIMES))
119 || (Get(Cmd, "lin", &_step_in) && (_stepmode = LIN_PTS))
120 || (Get(Cmd, "o{ctave}", &_step_in) && (_stepmode = OCTAVE));
122 if (Cmd.match1("'\"({") || Cmd.is_float()) {
123 Cmd >> _start;
124 if (Cmd.match1("'\"({") || Cmd.is_float()) {
125 Cmd >> _stop;
126 }else{
127 _stop = _start;
129 if (Cmd.match1("'\"({") || Cmd.is_float()) {
130 _stepmode = LIN_STEP;
131 Cmd >> _step_in;
132 }else{
136 unsigned here = Cmd.cursor();
138 ONE_OF
139 || (Get(Cmd, "*", &_step_in) && (_stepmode = TIMES))
140 || (Get(Cmd, "+", &_step_in) && (_stepmode = LIN_STEP))
141 || (Get(Cmd, "by", &_step_in) && (_stepmode = LIN_STEP))
142 || (Get(Cmd, "step", &_step_in) && (_stepmode = LIN_STEP))
143 || (Get(Cmd, "d{ecade}", &_step_in) && (_stepmode = DECADE))
144 || (Get(Cmd, "ti{mes}", &_step_in) && (_stepmode = TIMES))
145 || (Get(Cmd, "lin", &_step_in) && (_stepmode = LIN_PTS))
146 || (Get(Cmd, "o{ctave}", &_step_in) && (_stepmode = OCTAVE))
147 || Get(Cmd, "dt{emp}", &_sim->_temp_c, mOFFSET, OPT::temp_c)
148 || Get(Cmd, "pl{ot}", &ploton)
149 || Get(Cmd, "pr{evoppoint}",&_prevopppoint)
150 || Get(Cmd, "sta{rt}", &_start)
151 || Get(Cmd, "sto{p}", &_stop)
152 || Get(Cmd, "te{mperature}",&_sim->_temp_c)
153 || outset(Cmd,&_out)
155 }while (Cmd.more() && !Cmd.stuck(&here));
156 Cmd.check(bWARNING, "what's this??");
158 _start.e_val(0., _scope);
159 _stop.e_val(0., _scope);
160 _step_in.e_val(0., _scope);
161 _step = _step_in;
163 switch (_stepmode) {
164 case ONE_PT:
165 case LIN_STEP:
166 needslinfix = false;
167 _linswp = true;
168 break;
169 case LIN_PTS:untested();
170 if (_step <= 2.) {untested();// need to fix step, later
171 _step = 2.; // do it at the end of setup
172 }else{untested(); // a kluge, but this is a patch
174 needslinfix = true; // and I am too lazy to do it
175 _linswp = true; // right.
176 break;
177 case TIMES:untested();
178 if (_step == 0. && _start != 0.) {untested();
179 _step = _stop / _start;
180 }else{untested();
182 needslinfix = false;
183 _linswp = false;
184 break;
185 case OCTAVE:
186 if (_step == 0.) {untested();
187 _step = 1.;
188 }else{
190 _step = pow(2.00000001, 1./_step);
191 needslinfix = false;
192 _linswp = false;
193 break;
194 case DECADE:
195 if (_step == 0.) {
196 _step = 1.;
197 }else{
199 _step = pow(10., 1./_step);
200 needslinfix = false;
201 _linswp = false;
202 break;
205 if (needslinfix) {untested(); // LIN option is # of points.
206 assert(_step >= 2); // Must compute step after
207 _step=(_stop-_start)/(_step-1.); // reading start and stop,
208 needslinfix = false; // but step must be read first
209 }else{ // for Spice compatibility
211 if (_step==0.) {
212 _step = _stop - _start;
213 _linswp = true;
214 }else{
217 IO::plotout = (ploton) ? IO::mstdout : OMSTREAM();
218 initio(_out);
220 /*--------------------------------------------------------------------------*/
221 void AC::solve()
223 _sim->_acx.zero();
224 std::fill_n(_sim->_ac, _sim->_total_nodes+1, 0.);
226 ::status.load.start();
227 _sim->count_iterations(iTOTAL);
228 CARD_LIST::card_list.do_ac();
229 CARD_LIST::card_list.ac_load();
230 ::status.load.stop();
232 ::status.lud.start();
233 _sim->_acx.lu_decomp();
234 ::status.lud.stop();
236 ::status.back.start();
237 _sim->_acx.fbsub(_sim->_ac);
238 ::status.back.stop();
240 /*--------------------------------------------------------------------------*/
241 void AC::sweep()
243 head(_start, _stop, "Freq");
244 first();
245 CARD_LIST::card_list.ac_begin();
246 do {
247 _sim->_jomega = COMPLEX(0., _sim->_freq * M_TWO_PI);
248 solve();
249 outdata(_sim->_freq);
250 } while (next());
252 /*--------------------------------------------------------------------------*/
253 void AC::first()
255 _sim->_freq = _start;
257 /*--------------------------------------------------------------------------*/
258 bool AC::next()
260 double realstop = (_linswp)
261 ? _stop - _step/100.
262 : _stop / pow(_step,.01);
263 if (!in_order(double(_start), _sim->_freq, realstop)) {
264 return false;
265 }else{
268 _sim->_freq = (_linswp)
269 ? _sim->_freq + _step
270 : _sim->_freq * _step;
271 if (in_order(_sim->_freq, double(_start), double(_stop))) {
272 return false;
273 }else{
274 return true;
277 /*--------------------------------------------------------------------------*/
278 static AC p1;
279 static DISPATCHER<CMD>::INSTALL d1(&command_dispatcher, "ac", &p1);
281 /*--------------------------------------------------------------------------*/
282 /*--------------------------------------------------------------------------*/
283 // vim:ts=8:sw=2:noet: