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)
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
21 *------------------------------------------------------------------
24 //testing=script 2008.08.06
26 #include "u_sim_data.h"
28 #include "u_parameter.h"
31 /*--------------------------------------------------------------------------*/
33 /*--------------------------------------------------------------------------*/
34 class AC
: public SIM
{
36 void do_it(CS
&, CARD_LIST
*);
51 explicit AC(const AC
&):SIM() {unreachable(); incomplete();}
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
)
72 _sim
->set_command_ac();
74 ::status
.ac
.reset().start();
77 _sim
->alloc_vectors();
78 _sim
->_acx
.reallocate();
79 _sim
->_acx
.set_min_pivot(OPT::pivtol
);
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();
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
)
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;
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()) {
124 if (Cmd
.match1("'\"({") || Cmd
.is_float()) {
129 if (Cmd
.match1("'\"({") || Cmd
.is_float()) {
130 _stepmode
= LIN_STEP
;
136 unsigned here
= Cmd
.cursor();
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
)
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
);
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.
177 case TIMES
:untested();
178 if (_step
== 0. && _start
!= 0.) {untested();
179 _step
= _stop
/ _start
;
186 if (_step
== 0.) {untested();
190 _step
= pow(2.00000001, 1./_step
);
199 _step
= pow(10., 1./_step
);
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
212 _step
= _stop
- _start
;
217 IO::plotout
= (ploton
) ? IO::mstdout
: OMSTREAM();
220 /*--------------------------------------------------------------------------*/
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();
236 ::status
.back
.start();
237 _sim
->_acx
.fbsub(_sim
->_ac
);
238 ::status
.back
.stop();
240 /*--------------------------------------------------------------------------*/
243 head(_start
, _stop
, "Freq");
245 CARD_LIST::card_list
.ac_begin();
247 _sim
->_jomega
= COMPLEX(0., _sim
->_freq
* M_TWO_PI
);
249 outdata(_sim
->_freq
);
252 /*--------------------------------------------------------------------------*/
255 _sim
->_freq
= _start
;
257 /*--------------------------------------------------------------------------*/
260 double realstop
= (_linswp
)
262 : _stop
/ pow(_step
,.01);
263 if (!in_order(double(_start
), _sim
->_freq
, realstop
)) {
268 _sim
->_freq
= (_linswp
)
269 ? _sim
->_freq
+ _step
270 : _sim
->_freq
* _step
;
271 if (in_order(_sim
->_freq
, double(_start
), double(_stop
))) {
277 /*--------------------------------------------------------------------------*/
279 static DISPATCHER
<CMD
>::INSTALL
d1(&command_dispatcher
, "ac", &p1
);
281 /*--------------------------------------------------------------------------*/
282 /*--------------------------------------------------------------------------*/
283 // vim:ts=8:sw=2:noet: