Merge branch 'testing-uf' into master-uf
[gnucap-felix.git] / apps / d_res.cc
blobaa6e07b9027870ca3a553bf7e4042a2acbcf8fdd
1 /* -*- 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 * functions for resistor.
23 * y.x = amps, y.f0 = volts, ev = y.f1 = ohms
24 * m.x = volts, m.c0 = amps, acg = m.c1 = mhos.
26 #include "e_elemnt.h"
27 #include "u_xprobe.h"
28 /*--------------------------------------------------------------------------*/
29 namespace {
30 /*--------------------------------------------------------------------------*/
31 class DEV_RESISTANCE : public ELEMENT {
32 private:
33 explicit DEV_RESISTANCE(const DEV_RESISTANCE& p) :ELEMENT(p) {}
34 public:
35 explicit DEV_RESISTANCE() :ELEMENT() {}
36 private: // override virtual
37 char id_letter()const {return 'R';}
38 std::string value_name()const {return "r";}
39 std::string dev_type()const {return "resistor";}
40 uint_t max_nodes()const {return 2;}
41 uint_t min_nodes()const {return 2;}
42 uint_t matrix_nodes()const {return 2;}
43 uint_t net_nodes()const {return 2;}
44 bool has_iv_probe()const {return true;}
45 bool use_obsolete_callback_parse()const {return true;}
46 CARD* clone()const {return new DEV_RESISTANCE(*this);}
47 void precalc_last();
48 void tr_iwant_matrix() {tr_iwant_matrix_passive();}
49 void tr_begin();
50 bool do_tr();
51 void tr_load() {tr_load_passive();}
52 void tr_unload() {tr_unload_passive();}
53 double tr_involts()const {return tr_outvolts();}
54 double tr_input()const {untested(); return _m0.c0 + _m0.c1 * tr_involts();}
55 double tr_involts_limited()const {return tr_outvolts_limited();}
56 double tr_input_limited()const {return _m0.c0+_m0.c1*tr_involts_limited();}
57 void tr_regress();
58 void ac_iwant_matrix() {ac_iwant_matrix_passive();}
59 void ac_begin() {_ev = _y[0].f1; _acg = 1. / _ev;}
60 void do_ac();
61 void ac_load() {ac_load_passive();}
62 COMPLEX ac_involts()const {return ac_outvolts();}
63 double do_noise()const;
64 XPROBE sens_probe_ext(const std::string& x)const;
66 std::string port_name(uint_t i)const {
67 assert(i >= 0);
68 assert(i < 2);
69 static std::string names[] = {"p", "n"};
70 return names[i];
73 /*--------------------------------------------------------------------------*/
74 void DEV_RESISTANCE::precalc_last()
76 ELEMENT::precalc_last();
77 set_constant(!has_tr_eval() || (has_common() && common()->is_constant()));
78 set_converged(!has_tr_eval() || (has_common() && common()->is_constant()));
80 /*--------------------------------------------------------------------------*/
81 void DEV_RESISTANCE::tr_begin()
83 ELEMENT::tr_begin();
84 _y1.f1 = _y[0].f1 = (value() != 0.) ? value() : OPT::shortckt;
85 _m0.x = _y[0].x;
86 _m0.c1 = 1./_y[0].f1;
87 _m0.c0 = 0.;
88 _m1 = _m0;
89 assert(_loss0 == 0.);
90 assert(_loss1 == 0.);
91 if (is_constant() && using_tr_eval()) {
92 do_tr();
93 }else if (value() == 0. && !has_common()) {
94 error(bPICKY, long_label() + ": short circuit\n");
95 }else{
97 _n[0].register_prop(_n[1]);
98 _n[1]->register_prop(_n[0].operator->());
100 /*--------------------------------------------------------------------------*/
101 bool DEV_RESISTANCE::do_tr()
103 trace1("DEV_RESISTANCE::do_tr", using_tr_eval());
104 if (using_tr_eval()) {
105 _m0.x = tr_involts_limited();
106 _y[0].x = tr_input_limited();;
107 tr_eval();
108 assert(_y[0].f0 != LINEAR);
109 if (_y[0].f1 == 0.) { // leq short??
110 error(bPICKY, long_label() + ": short circuit\n");
111 _y[0].f1 = OPT::shortckt;
112 set_converged(conv_check());
113 }else{
115 store_values();
116 q_load();
117 _m0.c1 = 1./_y[0].f1;
118 _m0.c0 = _y[0].x - _y[0].f0 / _y[0].f1;
119 }else{
120 assert(_y[0].f0 == LINEAR);
121 assert(_y[0].f1 == value() || _y[0].f1 == OPT::shortckt);
122 assert(conchk(_m0.c1, 1./_y[0].f1));
123 assert(_m0.c0 == 0.);
124 assert(_y1 == _y[0]);
125 assert(converged());
127 return converged();
129 /*--------------------------------------------------------------------------*/
130 void DEV_RESISTANCE::tr_regress()
132 ELEMENT::tr_regress();
133 if (OPT::disc==dREJECT){
134 for (unsigned i=0;i < 2; ++i) {
135 if (DISCONT d=_n[i]->discont()) {
136 _n[1-i]->discont(d);
137 } else {
142 /*--------------------------------------------------------------------------*/
143 void DEV_RESISTANCE::do_ac()
145 if (using_ac_eval()) {
146 ac_eval();
147 if (_ev == 0.) {
148 error(bPICKY, long_label() + ": short circuit\n");
149 _ev = OPT::shortckt;
150 }else{
152 _acg = 1. / _ev;
153 }else{
154 assert(_ev == _y[0].f1);
155 assert(has_tr_eval() || _ev == double(value()) || _ev == OPT::shortckt);
158 /*--------------------------------------------------------------------------*/
159 double DEV_RESISTANCE::do_noise()const
161 // Assumed that everything is evaluated as AC was called just before
162 // invariant ?? :
163 double opower = 0;
164 // assert(_ev == double(value()));
165 assert(_ev == _y[0].f1);
166 assert(_acg == 1./_ev);
168 double temp = OPT::temp_c + P_CELSIUS0; // 300.15;
169 double g = real(_acg);
170 double i_noise_r = sqrt(4*P_K*temp*mfactor()*g);
171 uint_t n1 = _n[OUT1].m_();
172 uint_t n2 = _n[OUT2].m_();
173 COMPLEX v = _sim->_sens[n1] - _sim->_sens[n2];
174 double noisepow = abs(v*i_noise_r);
175 noisepow *= noisepow;
177 opower = noisepow;
179 trace4("DEV_RESISTANCE::do_noise", long_label(), opower, i_noise_r, g);
180 return opower;
182 /*--------------------------------------------------------------------------*/
183 XPROBE DEV_RESISTANCE::sens_probe_ext(const std::string& x)const
185 trace1("DEV_RESISTANCE::sens_probe_ext", x);
186 unsigned n1 = _n[OUT1].m_();
187 unsigned n2 = _n[OUT2].m_();
188 COMPLEX a = CKT_BASE::_sim->_sens[n1];
189 COMPLEX b = CKT_BASE::_sim->_sens[n2];
190 double vp = CKT_BASE::_sim->vdc()[n1];
191 double vn = CKT_BASE::_sim->vdc()[n2];
192 double dv = vp - vn;
193 double G( real(_acg) );
195 if (Umatch(x, "r{es} ")) {
196 COMPLEX ddr = (a-b) * G*G ;
197 return XPROBE( ddr*dv );
198 } else if (Umatch(x, "g ")) {
199 return XPROBE( -(a-b) * dv );
202 if (Umatch(x, "d1 ")) { // debug...
203 return XPROBE( dv );
205 return ELEMENT::sens_probe_ext(x);
207 /*--------------------------------------------------------------------------*/
208 /*--------------------------------------------------------------------------*/
209 DEV_RESISTANCE p1;
210 DISPATCHER<CARD>::INSTALL d1(&device_dispatcher, "R|resistor", &p1);
212 /*--------------------------------------------------------------------------*/
213 /*--------------------------------------------------------------------------*/
214 // vim:ts=8:sw=2:noet: