1 /* Copyright (C) 2001 Albert Davis
2 * Author: Albert Davis <aldavis@gnu.org>
4 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
6 * This program 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 3, or (at your option)
11 * This program 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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 *------------------------------------------------------------------
22 * temporary kludge: it has resistance
25 /*--------------------------------------------------------------------------*/
27 /*--------------------------------------------------------------------------*/
28 class DEV_VCVS
: public ELEMENT
{
30 explicit DEV_VCVS(const DEV_VCVS
& p
) :ELEMENT(p
) { }
32 explicit DEV_VCVS() :ELEMENT() {} //{ _net_nodes=4; }
33 private: // override virtual
34 char id_letter()const {return 'E';}
35 std::string
value_name()const {return "gain";}
36 std::string
element_type()const {return "vcvs";}
37 bool use_obsolete_callback_parse()const {return true;}
38 CARD
* clone()const {return new DEV_VCVS(*this);}
41 void tr_iwant_matrix() {tr_iwant_matrix_extended(); if(subdev())subdev()->tr_iwant_matrix();}
45 void tr_unload() {untested();tr_unload_active();}
46 hp_float_t
tr_involts()const {return dn_diff(_n
[IN1
].v0(), _n
[IN2
].v0());}
47 hp_float_t
tr_involts_limited()const {return volts_limited(_n
[IN1
],_n
[IN2
]);}
48 void ac_iwant_matrix() {ac_iwant_matrix_extended(); if(subdev())subdev()->ac_iwant_matrix();}
51 void ac_load() {ac_load_shunt(); ac_load_active();}
52 COMPLEX
ac_involts()const {return _n
[IN1
].vac() - _n
[IN2
].vac();}
54 std::string
port_name(uint_t i
)const {
55 assert(i
!=INVALID_NODE
);
57 static std::string names
[] = {"p", "n", "ps", "ns", "ps2", "ns2"};
62 /*--------------------------------------------------------------------------*/
63 /*--------------------------------------------------------------------------*/
64 void DEV_VCVS::tr_load()
72 /*--------------------------------------------------------------------------*/
74 unsigned DEV_VCVS::min_nodes() const
76 if( const EVAL_BM_ACTION_BASE
* e
=dynamic_cast<const EVAL_BM_ACTION_BASE
*>(common())){
77 trace1("DEV_VCVS::min_nodes", e
->input_order());
78 return e
->input_order() + 2;
80 trace0("DEV_VCVS::min_nodes 4");
85 /*--------------------------------------------------------------------------*/
86 void DEV_VCVS::precalc_last()
88 ELEMENT::precalc_last();
89 set_constant(!has_tr_eval());
90 set_converged(!has_tr_eval());
92 /*--------------------------------------------------------------------------*/
93 void DEV_VCVS::expand()
95 trace3("DEV_VCVS::expand", long_label(), input_order(), hp(common()));
96 assert(!subckt() || subckt()->size() < 2);
100 if( const EVAL_BM_ACTION_BASE
* e
=dynamic_cast<const EVAL_BM_ACTION_BASE
*>(common())){
101 _master
= input_order() == e
->input_order();
105 /*--------------------------------------------------------------------------*/
106 void DEV_VCVS::tr_begin()
108 trace1("DEV_VCVS::tr_begin", long_label());
112 if (const EVAL_BM_ACTION_BASE
* e
=dynamic_cast<const EVAL_BM_ACTION_BASE
*>(common())) {
113 bm_ord
= e
->input_order();
116 _loss1
= _loss0
= bm_ord
/ OPT::shortckt
;
118 _m0
.c1
= -_loss0
* _y
[0].f1
* bm_ord
;
122 subdev()->tr_begin();
125 /*--------------------------------------------------------------------------*/
126 bool DEV_VCVS::do_tr()
130 if (const EVAL_BM_ACTION_BASE
* e
=dynamic_cast<const EVAL_BM_ACTION_BASE
*>(common())) {
131 bm_ord
= e
->input_order();
134 if (using_tr_eval()) {
135 _y
[0].x
= _m0
.x
= tr_involts_limited();
136 //_y[0].x = tr_input_limited();
137 //assert(_y[0].x == _m0.x);
139 assert(_y
[0].f0
!= LINEAR
);
141 trace5("DEV_VCVS::do_tr", long_label(), _loss0
, _y
[0].x
, _y
[0].f0
, _y
[0].f1
);
142 double oldf0
=_y
[0].f0
;
150 _m0
*= -_loss0
* bm_ord
;
152 assert(conchk(_loss0
, 1./OPT::shortckt
));
153 assert(_y
[0].f0
== LINEAR
);
154 assert(_y
[0].f1
== value());
155 assert(conchk(_m0
.c1
, -_loss0
* _y
[0].f1
));
156 assert(_m0
.c0
== 0.);
157 assert(_y1
== _y
[0]);
162 /*--------------------------------------------------------------------------*/
163 void DEV_VCVS::ac_begin()
165 _loss1
= _loss0
= 1./OPT::shortckt
;
167 _acg
= -_loss0
* _ev
;
168 if(subdev()) subdev()->ac_begin();
170 /*--------------------------------------------------------------------------*/
171 void DEV_VCVS::do_ac()
173 if (using_ac_eval()) {
175 trace2("DEV_VCVS::do_ac", _loss0
, _ev
);
176 _acg
= -_loss0
* _ev
;
178 assert(_ev
== _y
[0].f1
);
179 assert(has_tr_eval() || _ev
== hp_float_t(value()));
182 /*--------------------------------------------------------------------------*/
183 /*--------------------------------------------------------------------------*/
185 DISPATCHER
<CARD
>::INSTALL
d1(&device_dispatcher
, "E|vcvs", &p1
);
187 /*--------------------------------------------------------------------------*/
188 /*--------------------------------------------------------------------------*/
189 // vim:ts=8:sw=2:noet: