Merge branch 'testing-uf' into master-uf
[gnucap-felix.git] / apps / d_cap.cc
blob854a479cfcccffd019c67e291daa74738693cfd8
1 /*$Id: d_cap.cc,v 1.10 2010-08-26 09:07:17 felix 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 * capacitance devices:
23 * self-capacitance (C device)
24 * trans-capacitance (non-spice charge transfer device)
25 *------------------------------------------------------------------
26 * capacitor models
27 * y.x = volts, y.f0 = coulombs, ev = y.f1 = farads
28 * q = y history in time
29 * i.x = volts, i.f0 = amps, i.f1 = mhos
30 * m.x = volts, m.c0 = amps, acg = m.c1 = mhos
32 //testing=script 2006.07.17
33 #include "d_cap.h"
34 #include "e_storag.h"
35 namespace SOME_CAP_HACK {
36 /*--------------------------------------------------------------------------*/
37 class DEV_TRANSCAP : public DEV_CAPACITANCE {
38 private:
39 explicit DEV_TRANSCAP(const DEV_TRANSCAP& p) :DEV_CAPACITANCE(p){}
40 public:
41 explicit DEV_TRANSCAP() :DEV_CAPACITANCE() {}
42 private: // override virtual
43 char id_letter()const {untested();return '\0';}
44 std::string value_name()const {untested(); return "c";}
45 std::string dev_type()const {return "tcap";}
46 uint_t max_nodes()const {return 4;}
47 uint_t min_nodes()const {return 4;}
48 uint_t matrix_nodes()const {return 4;}
49 uint_t net_nodes()const {return 4;}
50 bool has_iv_probe()const {untested(); return false;}
51 bool f_is_value()const {untested();return true;}
52 CARD* clone()const {return new DEV_TRANSCAP(*this);}
53 void tr_iwant_matrix() {tr_iwant_matrix_active();}
54 void tr_load() {tr_load_active();}
55 hp_float_t tr_involts()const {return dn_diff(_n[IN1].v0(),_n[IN2].v0());}
56 hp_float_t tr_involts_limited()const {return volts_limited(_n[IN1],_n[IN2]);}
57 void ac_iwant_matrix() {ac_iwant_matrix_active();}
58 void ac_load() {untested(); ac_load_active();}
59 std::string port_name(uint_t i)const {untested();
60 assert(i != INVALID_NODE);
61 assert(i < 4);
62 static std::string names[] = {"p", "n", "ps", "ns"};
63 return names[i];
66 /*--------------------------------------------------------------------------*/
67 //BUG// doesn't model dynamic effects of control.
68 class DEV_VCCAP : public DEV_CAPACITANCE {
69 private:
70 explicit DEV_VCCAP(const DEV_VCCAP& p) :DEV_CAPACITANCE(p) {}
71 public:
72 explicit DEV_VCCAP() :DEV_CAPACITANCE() {}
73 private: // override virtual
74 char id_letter()const {untested();return '\0';}
75 std::string value_name()const {untested(); return "c";}
76 std::string dev_type()const {return "vccap";}
77 uint_t max_nodes()const {return 4;}
78 uint_t min_nodes()const {return 4;}
79 uint_t matrix_nodes()const {return 4;}
80 uint_t net_nodes()const {return 4;}
81 bool has_iv_probe()const {untested(); return false;}
82 bool f_is_value()const {untested();return true;}
83 CARD* clone()const {return new DEV_VCCAP(*this);}
84 void tr_iwant_matrix() {tr_iwant_matrix_extended();}
85 bool do_tr();
86 void uic_clanup();
87 hp_float_t tr_involts()const {return dn_diff(_n[IN1].v0(),_n[IN2].v0());}
88 hp_float_t tr_involts_limited()const {return volts_limited(_n[IN1],_n[IN2]);}
89 void ac_iwant_matrix() {ac_iwant_matrix_extended();}
91 std::string port_name(uint_t i)const {untested();
92 assert(i != INVALID_NODE);
93 assert(i < 4);
94 static std::string names[] = {"p", "n", "ps", "ns"};
95 return names[i];
99 /*--------------------------------------------------------------------------*/
100 // obsolete
101 bool DEV_CAPACITANCE::has_ic() const
103 if ( const EVAL_BM_ACTION_BASE* x = dynamic_cast<const EVAL_BM_ACTION_BASE*>(common()) ){
104 if (x->_ic != NOT_INPUT) return 1;
106 return 0;
108 /*--------------------------------------------------------------------------*/
109 bool DEV_CAPACITANCE::do_tr()
111 // FPOLY1* q=_y;
112 //trace0(("DEV_CAPACITANCE::do_tr " + long_label()));
113 //trace3(("DEV_CAPACITANCE::do_tr " + long_label()).c_str(), _y[0].f1, value(), tr_input() );
114 if (using_tr_eval()) {
115 trace1("DEV_CAPACITANCE::do_tr, tr_eval", has_tr_eval());
116 _y[0].x = tr_input_limited();
117 tr_eval();
118 }else{
119 trace1("DEV_CAPACITANCE::do_tr, no tr_eval", tr_input());
120 _y[0].x = tr_input(); // tr_involts();
121 assert(_y[0].f1 == value());
122 _y[0].f0 = _y[0].x * _y[0].f1;
123 assert(converged());
125 trace3("DEV_CAPACITANCE::do_tr ", _y[0].f1, _sim->uic_now(), is_constant() );
126 store_values();
127 q_load();
129 if (_sim->uic_now() && has_ic()) {
130 double G = 1./OPT::shortckt;
131 assert(_time[0] == 0.);
133 trace1("DEV_CAPACITANCE::do_tr: desired capacitance is ", _y[0].f1);
134 trace1("DEV_CAPACITANCE::do_tr: desired charge is ", _y[0].f0);
135 trace1("DEV_CAPACITANCE::do_tr: desired voltage is ", _y[0].x);
137 // imitate voltage source... (d_vs.cc)
138 _i[0] = FPOLY1( CPOLY1( 0., -_y[0].x * G, G ) );
139 // trace2("2 quotienten", ( -_y[0].f0 / (OPT::shortckt) ) /-_y[0].x / (OPT::shortckt) ,
140 // (_y[0].f1 / (OPT::shortckt))/ 1/(OPT::shortckt) );
142 // picked up by tr_load_*
143 _loss0 = G;
145 } else {
146 trace4("q", _y[0].x, _y[0].f0, _y[0].f1, _sim->_phase);
147 trace3("i", _i[0].x, _i[0].f0, _i[0].f1);
148 _i[0] = differentiate(_y, _i, _time, _method_a);
149 trace3("i", _i[0].x, _i[0].f0, _i[0].f1);
151 _m0 = CPOLY1(_i[0]);
152 trace4("DEV_CAPACITANCE::do_tr done", long_label(), value(), _m0, _m1);
153 return converged();
155 /*--------------------------------------------------------------------------*/
156 void DEV_CAPACITANCE::tr_accept()
158 ELEMENT::tr_accept(); // commmon->accept..
160 if (_loss0!=0) {
161 // _loss0 should be irrelevant
162 // sources might have been abused to enforce initial conditions
163 // during dc analysis (otherwise this should be unreachable)
165 if (0 && !_sim->uic_now()) { // s_ddc
166 _m0.c0 = 0;
167 trace2("DEV_CAPACITANCE::tr_accept ddc", _m0, _m1);
168 } else {
169 trace3("DEV_CAPACITANCE::tr_accept ddc", _m0, _m1, _sim->_uic);
170 // vera hack. something about qdot
171 // also used in dc uic + tr cont ...
172 FPOLY1 m(_m0);
174 m.x = tr_input();
175 m.f0 = - _loss0 * tr_outvolts() - _m0.c0;
176 m.f1 = 0;
177 _m0 = CPOLY1(m);
178 _i[0].f0=0;
179 _i[0].f1=0;
182 _loss0 = 0.;
183 set_converged(false);
184 } else {
187 /*--------------------------------------------------------------------------*/
188 void DEV_CAPACITANCE::do_ac()
190 if (using_ac_eval()) {
191 ac_eval();
192 }else{
193 assert(_ev == _y[0].f1);
194 assert(has_tr_eval() || _ev == hp_float_t(value()));
196 trace1("DEV_CAPACITANCE::do_ac", _sim->_jomega);
197 _acg = (COMPLEX)_ev * _sim->_jomega;
200 /*--------------------------------------------------------------------------*/
201 double DEV_CAPACITANCE::tr_probe_num(const std::string& x)const
203 if (Umatch(x, "q{cap} |ch{arge} ")) {
204 return _y[0].f0;
205 }else if (Umatch(x, "c{apacitance} ")) {
206 return _y[0].f1;
207 }else if (Umatch(x, "dcdt ")) {untested();
208 return (_y[0].f1 - _y[1].f1) / _dt;
209 }else if (Umatch(x, "dc ")) {untested();
210 return (_y[0].f1 - _y[1].f1);
211 }else if (Umatch(x, "dqdt ")) {
212 return (_y[0].f0 - _y[1].f0) / _dt;
213 }else if (Umatch(x, "dq ")) {
214 return (_y[0].f0 - _y[1].f0);
215 }else{
216 return STORAGE::tr_probe_num(x);
219 /*--------------------------------------------------------------------------*/
220 bool DEV_VCCAP::do_tr()
222 _y[0].x = tr_input_limited();
223 tr_eval();
225 store_values();
226 q_load();
228 _y[0].x = tr_outvolts();
229 _y[0].f1 = _y[0].f0; // self capacitance
230 _y[0].f0 = _y[0].x * _y[0].f1; // charge
232 _i[0] = differentiate(_y, _i, _time, _method_a);
233 _m0.x = _i[0].x;
234 _m0.c1 = _i[0].f1;
235 _m0.c0 = _i[0].f0 - _i[0].x * _i[0].f1;
236 return converged();
238 /*--------------------------------------------------------------------------*/
239 void DEV_CAPACITANCE::tr_restore()
242 if(_sim->_time0 < _time[0]){
243 // recover from _freezetime ...
245 _y[0].x = tr_input();
246 // _i[0].x = tr_input();
247 // _i[0].f0 = 0.; // amps
248 // _i[0].f1 = 1./OPT::shortckt; // mhos
249 // _i[1] = _i[0];
250 if (using_tr_eval()) {
251 assert(_y[0].f1 == value());
252 }else{incomplete();
254 // BUG: compute _y[0].f1 from OP?
255 _y[0].f0 = _y[0].x * _y[0].f1; // charge
256 _y[1] = _y[0];
257 _y1 = _y[0];
258 _method_a = mINVALID;
259 // _i[0] = differentiate(_y, _i, _time, _method_a);
260 double G = 1./OPT::shortckt;
261 _i[0] = FPOLY1( CPOLY1( 0., -_y[0].x * G, G ) );
262 _m0 = CPOLY1(_i[0]);
263 trace3("DEV_CAPACITANCE::tr_restore from freeze", _y[0], _i[0], _i[1]);
264 STORAGE::tr_restore();
265 _time[1] = 0.; /// hmm hack.
266 }else{
267 STORAGE::tr_restore();
271 /*--------------------------------------------------------------------------*/
272 /*--------------------------------------------------------------------------*/
273 DEV_CAPACITANCE p1;
274 DEV_TRANSCAP p2;
275 DEV_VCCAP p3;
276 DISPATCHER<CARD>::INSTALL
277 d1(&device_dispatcher, "C|capacitor", &p1),
278 d2(&device_dispatcher, "tcap|tcapacitor", &p2),
279 d3(&device_dispatcher, "vccap", &p3);
280 /*------------------------------------------------------------------------*/
281 /*------------------------------------------------------------------------*/
283 /*--------------------------------------------------------------------------*/
284 /*--------------------------------------------------------------------------*/
285 // vim:ts=8:sw=2:noet: