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)
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 *------------------------------------------------------------------
22 * capacitance devices:
23 * self-capacitance (C device)
24 * trans-capacitance (non-spice charge transfer device)
25 *------------------------------------------------------------------
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
35 namespace SOME_CAP_HACK
{
36 /*--------------------------------------------------------------------------*/
37 class DEV_TRANSCAP
: public DEV_CAPACITANCE
{
39 explicit DEV_TRANSCAP(const DEV_TRANSCAP
& p
) :DEV_CAPACITANCE(p
){}
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
);
62 static std::string names
[] = {"p", "n", "ps", "ns"};
66 /*--------------------------------------------------------------------------*/
67 //BUG// doesn't model dynamic effects of control.
68 class DEV_VCCAP
: public DEV_CAPACITANCE
{
70 explicit DEV_VCCAP(const DEV_VCCAP
& p
) :DEV_CAPACITANCE(p
) {}
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();}
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
);
94 static std::string names
[] = {"p", "n", "ps", "ns"};
99 /*--------------------------------------------------------------------------*/
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;
108 /*--------------------------------------------------------------------------*/
109 bool DEV_CAPACITANCE::do_tr()
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();
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
;
125 trace3("DEV_CAPACITANCE::do_tr ", _y
[0].f1
, _sim
->uic_now(), is_constant() );
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_*
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
);
152 trace4("DEV_CAPACITANCE::do_tr done", long_label(), value(), _m0
, _m1
);
155 /*--------------------------------------------------------------------------*/
156 void DEV_CAPACITANCE::tr_accept()
158 ELEMENT::tr_accept(); // commmon->accept..
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
167 trace2("DEV_CAPACITANCE::tr_accept ddc", _m0
, _m1
);
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 ...
175 m
.f0
= - _loss0
* tr_outvolts() - _m0
.c0
;
183 set_converged(false);
187 /*--------------------------------------------------------------------------*/
188 void DEV_CAPACITANCE::do_ac()
190 if (using_ac_eval()) {
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} ")) {
205 }else if (Umatch(x
, "c{apacitance} ")) {
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
);
216 return STORAGE::tr_probe_num(x
);
219 /*--------------------------------------------------------------------------*/
220 bool DEV_VCCAP::do_tr()
222 _y
[0].x
= tr_input_limited();
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
);
235 _m0
.c0
= _i
[0].f0
- _i
[0].x
* _i
[0].f1
;
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
250 if (using_tr_eval()) {
251 assert(_y
[0].f1
== value());
254 // BUG: compute _y[0].f1 from OP?
255 _y
[0].f0
= _y
[0].x
* _y
[0].f1
; // charge
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
) );
263 trace3("DEV_CAPACITANCE::tr_restore from freeze", _y
[0], _i
[0], _i
[1]);
264 STORAGE::tr_restore();
265 _time
[1] = 0.; /// hmm hack.
267 STORAGE::tr_restore();
271 /*--------------------------------------------------------------------------*/
272 /*--------------------------------------------------------------------------*/
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: