Merge branch 'fixes' into testing-uf
[gnucap-felix.git] / modules / d_rcd.cc
blob806f4b0d424321b7fa7d3cf283329167e5512cc3
1 /* $Id: d_rcd.cc,v 1.9 2010-09-07 07:46:21 felix Exp $ -*- C++ -*-
2 * vim:ts=8:sw=2:et:
4 * RCD device ...
6 * (c) 2010 Felix Salfelder
8 * GPLv3
9 */
11 #include "e_aux.h"
12 #include "e_adp.h"
13 #include "e_storag.h"
14 #include "globals.h"
15 #include "e_elemnt.h"
16 #include "d_rcd.h"
17 #include "u_nodemap.h"
18 #include <iomanip>
19 #ifdef DO_TRACE
20 # include "io_misc.h"
21 #endif
23 using namespace std;
24 /*--------------------------------------------------------------------------*/
25 const double _default_value (1); //input scale.
26 /*--------------------------------------------------------------------------*/
27 class ADP_NODE;
28 static bool dummy=false;
29 const double NA(NOT_INPUT);
30 const double INF(BIGBIG);
31 /*--------------------------------------------------------------------------*/
32 int DEV_BUILT_IN_RCD::_count = -1;
33 int COMMON_BUILT_IN_RCD::_count = -1;
34 static COMMON_BUILT_IN_RCD Default_BUILT_IN_RCD(CC_STATIC);
35 /*--------------------------------------------------------------------------*/
36 int MODEL_BUILT_IN_RCD::_count = 0;
37 /*--------------------------------------------------------------------------*/
38 namespace MODEL_BUILT_IN_RCD_DISPATCHER { //
39 static DEV_BUILT_IN_RCD p1d;
40 static MODEL_BUILT_IN_RCD_NET p1(&p1d);
41 static DISPATCHER<MODEL_CARD>::INSTALL
42 d1(&model_dispatcher, "rcdnet|rcdmodel", &p1);
44 /*--------------------------------------------------------------------------*/
45 void DEV_BUILT_IN_RCD::tr_accept()
47 //trace3("DEV_BUILT_IN_RCD::tr_accept", long_label(), _n[n_u].m_(), _n[n_u].v0());
48 //trace3("DEV_BUILT_IN_RCD::tr_accept", _sim->_time0, _sim->_Time0, involts());
49 // assert(subckt()); subckt()->tr_accept();
50 assert(is_number((double)_tr_fill));
51 if (_sim->_dt0){
52 tr_stress();
53 }else{
55 _Ccgfill->tr_lo = min(involts(), _Ccgfill->tr_lo);
56 _Ccgfill->tr_hi = max(involts(), _Ccgfill->tr_hi);
57 assert(is_number((double)_tr_fill));
58 // q_eval();
59 //trace5("DEV_BUILT_IN_RCD::tr_accept", _sim->_time0, _sim->_Time0, involts(), _Ccgfill->tr_lo, _Ccgfill->tr_hi);
61 /*--------------------------------------------------------------------------*/
62 void SDP_BUILT_IN_RCD::init(const COMMON_COMPONENT* cc)
64 assert(cc);
65 SDP_CARD::init(cc);
67 /*--------------------------------------------------------------------------*/
68 TDP_BUILT_IN_RCD::TDP_BUILT_IN_RCD(const DEV_BUILT_IN_RCD*)
69 { untested();
71 /*--------------------------------------------------------------------------*/
72 MODEL_BUILT_IN_RCD::MODEL_BUILT_IN_RCD(const BASE_SUBCKT* p)
73 :MODEL_CARD(p),
74 anneal(true),
75 Remodel(1e6),
76 Re1(1),
77 Re0(1e6),
78 Rc1(1),
79 Rc0(1e6),
80 flags(int(USE_OPT)),
81 uref(0),
82 modelparm(0),
83 norm_uin(false)
85 if (ENV::run_mode != rPRE_MAIN) {
86 ++_count;
87 }else{
89 set_default(&_tnom_c, OPT::tnom_c);
91 /*--------------------------------------------------------------------------*/
92 void MODEL_BUILT_IN_RCD::do_tr_stress( const COMPONENT* ) const { untested();
93 unreachable(); // stress done by device.
95 /*--------------------------------------------------------------------------*/
96 MODEL_BUILT_IN_RCD::MODEL_BUILT_IN_RCD(const MODEL_BUILT_IN_RCD& p)
97 :MODEL_CARD(p),
98 anneal(p.anneal),
99 Remodel(p.Remodel),
100 Re1(p.Re1),
101 Re0(p.Re0),
102 Rc1(p.Rc1),
103 Rc0(p.Rc0),
104 flags(p.flags),
105 uref(p.uref),
106 modelparm(p.modelparm),
107 norm_uin(p.norm_uin)
109 if (ENV::run_mode != rPRE_MAIN) {
110 ++_count;
111 }else{untested();
114 /*--------------------------------------------------------------------------*/
115 double MODEL_BUILT_IN_RCD::P(const COMPONENT* ) const
116 { untested();
117 assert(false);
118 return ( NAN ); //c->_Ccgfill->get()+ _tr_fill ) * cc->_weight * cc->_wcorr;
120 /*--------------------------------------------------------------------------*/
121 double MODEL_BUILT_IN_RCD::__Rc(double s, const COMMON_COMPONENT* ccmp)const
122 { untested();
123 const COMMON_BUILT_IN_RCD* cc = prechecked_cast<const COMMON_BUILT_IN_RCD*>(ccmp);
124 double ret = ( cc->_Rc0 + s * cc->_lambda * cc->_Rc1 );
125 assert (is_number(cc->_lambda));
126 assert (is_number(cc->_Rc0));
127 assert (is_number(cc->_Rc1));
128 assert (is_number(ret));
129 return ret;
131 /*--------------------------------------------------------------------------*/
132 double MODEL_BUILT_IN_RCD::__Re(double , const COMMON_COMPONENT* cc)const
133 { untested();
134 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(cc);
136 return c->_Re0;
137 // return c->__Re(uin);
139 /*--------------------------------------------------------------------------*/
140 double MODEL_BUILT_IN_RCD::__Ge(double, const COMMON_COMPONENT* )const { untested();
141 return NAN;
143 /*--------------------------------------------------------------------------*/
144 std::string MODEL_BUILT_IN_RCD_NET::dev_type()const
145 { untested();
146 return "rcdnet";
148 /*--------------------------------------------------------------------------*/
149 std::string MODEL_BUILT_IN_RCD::dev_type()const
150 { untested();
151 unreachable();
152 if (dummy == true) { untested();
153 return "rcdmodel?";
154 }else{untested();//235
155 return MODEL_CARD::dev_type();
158 /*--------------------------------------------------------------------------*/
159 void MODEL_BUILT_IN_RCD::set_dev_type(const std::string& new_type)
160 { untested();
161 untested();
162 if (Umatch(new_type, "rcdmodel ")) { untested();
163 dummy = true;
164 }else{ untested();
165 MODEL_CARD::set_dev_type(new_type);
168 /*--------------------------------------------------------------------------*/
169 void MODEL_BUILT_IN_RCD::precalc_first()
171 const CARD_LIST* par_scope = scope();
172 assert(par_scope);
173 MODEL_CARD::precalc_first();
174 e_val(&(this->anneal), true, par_scope);
175 e_val(&(this->Remodel), 1e6, par_scope);
176 e_val(&(this->Re0), 1.0, par_scope);
177 e_val(&(this->Rc0), 1.0, par_scope);
178 e_val(&(this->Re1), 1.0, par_scope);
179 e_val(&(this->Rc1), 1.0, par_scope);
180 e_val(&(this->flags), int(USE_OPT), par_scope);
181 e_val(&(this->uref), NA, par_scope);
182 e_val(&(this->modelparm), 0, par_scope);
183 e_val(&(this->norm_uin), false, par_scope);
185 /*--------------------------------------------------------------------------*/
186 void MODEL_BUILT_IN_RCD::precalc_last()
188 MODEL_CARD::precalc_last();
189 const CARD_LIST* par_scope = scope();
190 e_val(&(this->Re0), 1.0, par_scope);
191 e_val(&(this->Rc0), 1.0, par_scope);
192 e_val(&(this->Re1), 1.0, par_scope);
193 e_val(&(this->Rc1), 1.0, par_scope);
195 /*--------------------------------------------------------------------------*/
196 SDP_CARD* MODEL_BUILT_IN_RCD::new_sdp(COMMON_COMPONENT* c)const
198 assert(c);
199 if (COMMON_BUILT_IN_RCD* cc = dynamic_cast<COMMON_BUILT_IN_RCD*>(c)) {
200 if (cc->_sdp) {
201 cc->_sdp->init(cc);
202 assert(cc->_sdp);
203 return cc->_sdp;
204 }else{
205 delete cc->_sdp;
206 return new SDP_BUILT_IN_RCD(c);
208 }else{ untested();
209 trace0("MODEL_BUILT_IN_RCD::new_sdp, MODEL_CARD");
210 return MODEL_CARD::new_sdp(c);
213 /*--------------------------------------------------------------------------*/
214 void MODEL_BUILT_IN_RCD::set_param_by_index(int i, std::string& value, int offset)
215 { untested();
216 switch (MODEL_BUILT_IN_RCD::param_count() - 1 - i) { untested();
217 case 0: untested(); break;
218 case 1: _tnom_c = value; break;
219 case 2: anneal = value; break;
220 case 3: Remodel = value; break;
221 case 4: Re0 = value; break; // former Re
222 case 5: Rc0 = value; break;
223 case 6: flags = value; break;
224 case 7: uref = value; break;
225 case 8: modelparm = value; break;
226 case 9: norm_uin = value; break;
227 default: throw Exception_Too_Many(unsigned(i), 7u, offset); break;
230 /*--------------------------------------------------------------------------*/
231 bool MODEL_BUILT_IN_RCD::param_is_printable(int i)const
233 switch (MODEL_BUILT_IN_RCD::param_count() - 1 - i) { untested();
234 case 0: return (false);
235 case 1: return (true);
236 case 2: return (true);
237 case 3: return (true);
238 case 4: return (true); // Re
239 case 5: return (true); //Rc
240 case 6: return (!(flags & USE_OPT));
241 case 7: return (uref.has_hard_value());
242 case 8: return (modelparm.has_hard_value());
243 case 9: return (norm_uin.has_hard_value());
244 default: return false;
247 /*--------------------------------------------------------------------------*/
248 std::string MODEL_BUILT_IN_RCD::param_name(int i)const
250 switch (MODEL_BUILT_IN_RCD::param_count() - 1 - i) { untested();
251 case 0: return "=====";
252 case 1: return "tnom";
253 case 2: return "anneal";
254 case 3: return "rem";
255 case 4: return "Re";
256 case 5: return "Rc";
257 case 6: return "flags";
258 case 7: return "uref";
259 case 8: return "modelparm";
260 case 9: return "norm_uin";
261 default: return "";
264 /*--------------------------------------------------------------------------*/
265 std::string MODEL_BUILT_IN_RCD::param_name(int i, int j)const
266 { untested();
267 if (j == 0) { untested();
268 return param_name(i);
269 }else if (j == 1) { untested();
270 switch (MODEL_BUILT_IN_RCD::param_count() - 1 - i) { untested();
271 case 4: return "Re";
272 case 5: return "Rc";
273 case 9: return "pos";
274 default: return "";
276 }else{ untested();
277 return "";
280 /*--------------------------------------------------------------------------*/
281 std::string MODEL_BUILT_IN_RCD::param_value(int i)const
283 switch (MODEL_BUILT_IN_RCD::param_count() - 1 - i) { untested();
284 case 0: unreachable(); return "";
285 case 1: return _tnom_c.string();
286 case 2: return anneal.string();
287 case 3: return Remodel.string();
288 case 4: return Re0.string(); // former Re
289 case 5: return Rc0.string(); // former Rc
290 case 6: return flags.string();
291 case 7: return uref.string();
292 case 8: return modelparm.string();
293 case 10: return norm_uin.string();
294 default: return "";
297 /*--------------------------------------------------------------------------*/
298 void MODEL_BUILT_IN_RCD::do_precalc_last(COMMON_COMPONENT* ccc, const CARD_LIST* )const
299 { untested();
300 COMMON_BUILT_IN_RCD* cc = dynamic_cast<COMMON_BUILT_IN_RCD*>(ccc);
301 assert(cc);
302 //const MODEL_BUILT_IN_RCD* m = this;
304 if (is_number(cc->Uref)) { untested();
305 assert( is_number( cc->Rccommon0 ) && (double)cc->Rccommon0 != NA );
306 assert( is_number( cc->Rccommon1 ) );
309 trace3("MODEL_BUILT_IN_RCD::do_precalc_last", cc->Uref, cc->Recommon0, cc->Rccommon0);
310 long double ueff = cc->Uref; // ( exp ( lambda * Uref ) - 1 );
312 double up = cc->Recommon0;
313 double down = cc->Rccommon0;
315 double rad = double(ueff*ueff*up*up + 2.0*(up*up + up*down)*ueff + up*up - 2*up*down + down*down);
316 //double s = ueff*up + up - down;
317 double up_res = double ( 1.0/2.0*(ueff*up + up - down + sqrt(rad))/ueff );
318 double down_res = down;
320 cc->_Re0 = up_res;
321 cc->_Rc0 = down_res;
322 cc->_Rc1 = up_res;
323 // double _rr = _rr_.subs(runter=runter, u_gate_=uref)
325 // double _rh = _rh_.subs(runter=runter, u_gate_=uref)
326 double Eend_bad = (cc->Uref / (cc->Re(cc->Uref) / cc->Rc(cc->Uref) +1));
328 cc->_wcorr = double ( cc->Uref / Eend_bad );
329 cc->_weight = cc->weight;
330 // sanity check.
331 trace3("MODEL_BUILT_IN_RCD::do_precalc_last", cc->__tau_up(cc->Uref), cc->Recommon0, cc->Rccommon0);
332 trace3("MODEL_BUILT_IN_RCD::do_precalc_last",cc->_Rc1, cc->_Re0, cc->_Rc0);
333 assert( cc->weight != 0 );
334 assert( cc->_weight != 0 );
335 assert( abs( cc->__tau_up(cc->Uref) - cc->Recommon0)/cc->Recommon0 <1e-6 );
336 assert( is_number( cc->_Rc1 ) );
337 assert( is_number( cc->_Rc0 ) );
339 /*--------------------------------------------------------------------------*/
340 bool MODEL_BUILT_IN_RCD::is_valid(const COMPONENT* d)const
342 assert(d);
343 return MODEL_CARD::is_valid(d);
345 /*--------------------------------------------------------------------------*/
346 void MODEL_BUILT_IN_RCD::tr_eval(COMPONENT*)const
347 {untested();//425
349 /*--------------------------------------------------------------------------*/
350 /*--------------------------------------------------------------------------*/
351 /*--------------------------------------------------------------------------*/
352 COMMON_BUILT_IN_RCD::COMMON_BUILT_IN_RCD(int c)
353 :COMMON_COMPONENT(c),
354 perim(0.0),
355 weight(1.0),
356 Recommon0(NA),
357 Recommon1(NA),
358 Rccommon0(NA),
359 Rccommon1(NA),
360 positive(true),
361 Uref(0.0),
362 mu(1.0),
363 lambda(1.0),
364 dummy_capture(false),
365 dummy_emit(false),
366 _sdp(0),
367 cj_adjusted(NA)
369 trace1("COMMON_BUILT_IN_RCD::COMMON_BUILT_IN_RCD", (double) Uref);
370 ++_count;
372 /*--------------------------------------------------------------------------*/
373 COMMON_BUILT_IN_RCD::COMMON_BUILT_IN_RCD(const COMMON_BUILT_IN_RCD& p)
374 :COMMON_COMPONENT(p),
375 perim(p.perim),
376 weight(p.weight),
377 Recommon0(p.Recommon0),
378 Recommon1(p.Recommon1),
379 Rccommon0(p.Rccommon0),
380 Rccommon1(p.Rccommon1),
381 positive(p.positive),
382 Uref(p.Uref),
383 mu(p.mu),
384 lambda(p.lambda),
385 dummy_capture(p.dummy_capture),
386 dummy_emit(p.dummy_emit),
387 _sdp(0),
388 cj_adjusted(p.cj_adjusted)
390 trace1("COMMON_BUILT_IN_RCD::COMMON_BUILT_IN_RCD(copy)", (double) Uref);
391 ++_count;
393 /*--------------------------------------------------------------------------*/
394 COMMON_BUILT_IN_RCD::~COMMON_BUILT_IN_RCD()
396 --_count;
397 delete _sdp;
399 /*--------------------------------------------------------------------------*/
400 bool COMMON_BUILT_IN_RCD::operator==(const COMMON_COMPONENT& x)const
402 const COMMON_BUILT_IN_RCD* p = dynamic_cast<const COMMON_BUILT_IN_RCD*>(&x);
403 return (p
404 && perim == p->perim
405 && weight == p->weight
406 && Rccommon1 == p->Rccommon1
407 && Rccommon0 == p->Rccommon0
408 && Recommon1 == p->Recommon1
409 && Recommon0 == p->Recommon0
410 && positive == p->positive
411 && Uref == p->Uref
412 && mu == p->mu
413 && lambda == p->lambda
414 && dummy_capture == p->dummy_capture
415 && dummy_emit == p->dummy_emit
416 && _sdp == p->_sdp
417 && COMMON_COMPONENT::operator==(x));
419 /*--------------------------------------------------------------------------*/
420 int COMMON_BUILT_IN_RCD::param_count()const
422 return (10 + COMMON_COMPONENT::param_count());
424 /*--------------------------------------------------------------------------*/
425 void COMMON_BUILT_IN_RCD::set_param_by_index(int I, std::string& Value, int Offset)
427 trace3("COMMON_BUILT_IN_RCD::set_param_by_index ",I, COMMON_BUILT_IN_RCD::param_count() - 1 - I, Value );
428 switch (COMMON_BUILT_IN_RCD::param_count() - 1 - I) { untested();
429 case 0: perim = Value; break;
430 case 1: weight = Value; trace1("wt", Value); break;
431 // order double _hl, double _hc, double _rl, double _rc)
432 case 2: Rccommon1 = Value; break; // swapped
433 case 3: Rccommon0 = Value; break;
434 case 4: Recommon1 = Value; break;
435 case 5: Recommon0 = Value; break;
436 case 6: itested(); positive = Value; break;
437 case 7: untested(); Uref = Value; break;
438 case 8: untested(); mu = Value; break;
439 case 9: untested(); lambda = Value; break;
440 case 10: untested(); Uref = Value; break;
441 case 11: untested(); dummy_emit = Value; break;
442 default: untested(); COMMON_COMPONENT::set_param_by_index(I, Value, Offset);
445 /*--------------------------------------------------------------------------*/
446 bool COMMON_BUILT_IN_RCD::param_is_printable(int i)const
448 switch (COMMON_BUILT_IN_RCD::param_count() - 1 - i) { untested();
449 case 0: return (perim != 0.);
450 case 1: return (true);
451 case 2: return (true);
452 case 3: return (true);
453 case 4: return (true);
454 case 5: return (true);
455 case 6: return positive.has_hard_value();
456 case 7: return (true);
457 case 8: return mu.has_hard_value();
458 case 9: return lambda.has_hard_value();
459 case 10: return Uref.has_hard_value();
460 default: return COMMON_COMPONENT::param_is_printable(i);
463 /*--------------------------------------------------------------------------*/
464 void COMMON_BUILT_IN_RCD::set_param_by_name(std::string Name, std::string Value)
466 if (Umatch (Name,"weight ")) {
467 weight = Value;
468 } else if (Umatch (Name,"re1 ")) {
469 Recommon1 = Value;
470 } else if (Umatch (Name,"re0 ")) {
471 Recommon0 = Value;
472 } else if (Umatch (Name,"rc1 ")) {
473 Rccommon1 = Value;
474 } else if (Umatch (Name,"rc0 ")) {
475 Rccommon0 = Value;
476 } else if (Umatch (Name,"pos{itive}")) {
477 positive = Value;
478 } else { untested();
479 incomplete();
480 trace2("COMMON_BUILT_IN_RCD::set_param_by_name", Name, Value);
481 COMMON_COMPONENT::set_param_by_name(Name, Value);
484 /*--------------------------------------------------------------------------*/
485 std::string COMMON_BUILT_IN_RCD::param_name(int i)const
487 trace1("COMMON_BUILT_IN_RCD::param_name", i);
488 switch (COMMON_BUILT_IN_RCD::param_count() - 1 - i) { untested();
489 case 0: return "perim";
490 case 1: return "weight";
491 case 2: return "rc1";
492 case 3: return "rc0";
493 case 4: return "re1";
494 case 5: return "re0";
495 case 6: return "positive";
496 case 7: return "mu";
497 case 8: return "lam";
498 case 9: return "rcdummy";
499 case 10: return "uref";
500 //case 10: return "norm_uin";
501 default: return COMMON_COMPONENT::param_name(i);
504 /*--------------------------------------------------------------------------*/
505 std::string COMMON_BUILT_IN_RCD::param_name(int i, int j)const
506 { untested();
507 if (j == 0) { untested();
508 return param_name(i);
509 }else if (j == 1) { untested();
510 switch (COMMON_BUILT_IN_RCD::param_count() - 1 - i) { untested();
511 case 0: return "";
512 case 1: return "";
513 case 2: return "";
514 case 3: return "";
515 case 4: return "";
516 case 5: return "";
517 case 6: return "";
518 case 7: return "";
519 case 8: return "";
520 default: return "";
522 }else{untested();//281
523 return COMMON_COMPONENT::param_name(i, j);
526 /*--------------------------------------------------------------------------*/
527 std::string COMMON_BUILT_IN_RCD::param_value(int i)const
529 switch (COMMON_BUILT_IN_RCD::param_count() - 1 - i) { untested();
530 case 0: return perim.string();
531 case 1: return weight.string();
532 case 2: return Rccommon1.string();
533 case 3: return Rccommon0.string();
534 case 4: return Recommon1.string();
535 case 5: return Recommon0.string();
536 case 6: return positive.string();
537 case 7: return Uref.string();
538 case 8: return mu.string();
539 case 9: return lambda.string();
540 case 10: return Uref.string();
541 case 11: return dummy_emit.string();
542 default: return COMMON_COMPONENT::param_value(i);
545 /*--------------------------------------------------------------------------*/
546 void COMMON_BUILT_IN_RCD::expand(const COMPONENT* d)
548 COMMON_COMPONENT::expand(d);
549 attach_model(d);
550 COMMON_BUILT_IN_RCD* c = this; USE(c);
551 const MODEL_BUILT_IN_RCD* m = dynamic_cast<const MODEL_BUILT_IN_RCD*>(model());
552 if (!m) { untested();
553 throw Exception_Model_Type_Mismatch(d->long_label(), modelname(), "rcd");
554 }else{
557 if ((double)Recommon0 == NA) { Recommon0 = m->Re0;}
558 if ((double)Rccommon0 == NA) { Rccommon0 = m->Rc0;}
560 trace6(("COMMON_BUILT_IN_RCD::expand" + d->short_label()).c_str(), Rccommon0,
561 Recommon0, m->Re0, m->Rc0, Uref, m->uref );
562 // size dependent
563 //delete _sdp;
564 _sdp = m->new_sdp(this);
565 assert(_sdp);
566 const SDP_BUILT_IN_RCD* s = prechecked_cast<const SDP_BUILT_IN_RCD*>(_sdp);
567 assert(s); USE(s);
569 // subcircuit commons, recursive
570 assert(c == this);
572 /*--------------------------------------------------------------------------*/
573 /* calculate before model? */
574 /*--------------------------------------------------------------------------*/
575 void COMMON_BUILT_IN_RCD::precalc_first(const CARD_LIST* par_scope)
577 trace2("precalc_first", *(par_scope->params()), weight);
578 assert(par_scope);
579 COMMON_COMPONENT::precalc_first(par_scope);
580 e_val(&(this->perim), 0.0, par_scope);
581 e_val(&(this->weight), 1.0, par_scope); // fixme: oscale?
582 e_val(&(this->Recommon0), 1.0, par_scope);
583 e_val(&(this->Recommon1), 1.0, par_scope);
584 e_val(&(this->Rccommon0), 1.0, par_scope);
585 e_val(&(this->Rccommon1), 1.0, par_scope);
586 e_val(&(this->Uref), 0.00001, par_scope);
587 trace3("uref...", Uref, NOT_INPUT, Uref );
588 e_val(&(this->mu), 1.0, par_scope);
589 e_val(&(this->lambda), 1.0, par_scope);
590 e_val(&(this->dummy_capture), false, par_scope);
591 e_val(&(this->dummy_emit), false, par_scope);
592 e_val(&(this->positive), true, par_scope);
593 if(!positive){
594 }else{
597 /*--------------------------------------------------------------------------*/
598 void COMMON_BUILT_IN_RCD::precalc_last(const CARD_LIST* par_scope)
600 assert(par_scope);
601 trace2("precalc_last", *(par_scope->params()), weight);
602 COMMON_COMPONENT::precalc_last(par_scope);
603 COMMON_BUILT_IN_RCD* cc = this;
604 COMMON_BUILT_IN_RCD* c = this;
605 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(model());
606 assert(m);
607 // final adjust: code_pre
608 trace2("COMMON_BUILT_IN_RCD::precalc_last", m->v2(), m->uref);
609 // final adjust: override
610 // final adjust: raw
611 e_val(&(this->weight), 1.0, par_scope); // fixme: oscale?
612 e_val(&(this->perim), 0.0, par_scope);
613 e_val(&(this->weight), 1.0, par_scope);
614 e_val(&(this->Recommon0), m->Re0, par_scope);
615 e_val(&(this->Recommon1), m->Re1, par_scope);
616 e_val(&(this->Rccommon0), m->Rc0, par_scope);
617 e_val(&(this->Rccommon1), m->Rc1, par_scope);
618 e_val(&(this->Uref), m->uref, par_scope);
620 trace4("uref...", m->uref, NOT_INPUT, Uref , double (Uref));
621 Uref.e_val( (double)m->uref, par_scope);
622 trace3("uref...", m->uref, NOT_INPUT, Uref );
624 e_val(&(this->mu), 1.0, par_scope);
625 e_val(&(this->lambda), 1.0, par_scope);
626 e_val(&(this->dummy_capture), false, par_scope);
627 e_val(&(this->positive), true, par_scope);
628 if(!positive){
629 }else{
630 trace2("", positive, (bool)positive);
632 e_val(&(this->dummy_emit), false, par_scope);
633 // final adjust: mid
634 // final adjust: calculated
635 cj_adjusted = 19.0;
637 _lambda = 1;
638 lambda=1;
640 if((double)Uref == NOT_INPUT) {
641 trace2("nin", m->uref, NOT_INPUT );
642 Uref = 0.0;
644 if((double)Uref == NA) {
645 trace0("na");
646 Uref = 0.0;
649 // size dependent
650 //delete _sdp;
651 _sdp = m->new_sdp(this);
652 assert(_sdp);
653 const SDP_BUILT_IN_RCD* s = prechecked_cast<const SDP_BUILT_IN_RCD*>(_sdp);
654 assert(s); USE(s);
656 // subcircuit commons, recursive
657 c->_wcorr = 0;
658 c->_zero = 0;
661 if(m->v2()){
662 m->do_precalc_last(cc, par_scope );
663 } else if (Uref!=0.0 ){ untested();
664 m->do_precalc_last(cc, par_scope );
665 } else { // no uref...
666 cc->_Re0 = Recommon0;
667 cc->_Rc0 = Rccommon0;
668 cc->_Rc1 = _Re0;
670 if(Rccommon1 != NA && Rccommon1 != NOT_INPUT ) _Rc1 = Rccommon1;
672 _weight = weight;
673 _wcorr = 1;
674 assert (weight != 0);
675 trace5("COMMON_BUILT_IN_RCD::precalc_last no uref. simple model", _Re0, _Rc0, _Rc1, Re(1), Rc(0));
676 Uref=1;
678 trace3("COMMON_BUILT_IN_RCD::precalc_last", Uref*weight, _Re0, _Rc0 );
679 trace1("COMMON_BUILT_IN_RCD::precalc_last", cc->_Re0);
680 trace1("COMMON_BUILT_IN_RCD::precalc_last done", m->v2());
682 if (cc->_Re1 < 0) { untested(); // turnt
683 throw Exception_Precalc("nonnegative Re1: " + ::to_string(cc->_Re1) + "\n");
685 if (cc->_Rc1 > 0) { untested(); // turnt
686 throw Exception_Precalc("nonpositive Rc1: " + ::to_string(cc->_Rc1) + "\n");
689 /*--------------------------------------------------------------------------*/
690 //double MODEL_BUILT_IN_RCD::__tau_up ( double uin, const COMMON_BUILT_IN_RCD* cc ) const{ untested();
691 // return cc->__tau_up(uin);
693 /*--------------------------------------------------------------------------*/
694 double COMMON_BUILT_IN_RCD::__tau_up ( double uin ) const{ untested();
695 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(model());
696 double rc = m->__Rc(uin, this);
697 double re = m->__Re(uin, this);
698 return float( rc / ( 1 + rc/re ) ) ;
700 /*--------------------------------------------------------------------------*/
701 namespace DEV_BUILT_IN_RCD_DISPATCHER {
702 static DEV_BUILT_IN_RCD p0;
703 static DISPATCHER<CARD>::INSTALL
704 d0(&device_dispatcher, "Z|rcd", &p0);
706 /*--------------------------------------------------------------------------*/
707 double COMMON_BUILT_IN_RCD::Re(double uin) const
708 { untested();
709 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(model());
710 return m->__Re(uin,this);
712 /*--------------------------------------------------------------------------*/
713 double COMMON_BUILT_IN_RCD::Rc(double uin) const
714 { untested();
715 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(model());
716 return m->__Rc(uin,this);
718 //double ret = ( _Rc0 + uin * _lambda * _Rc1 );
719 //assert (ret==ret);
720 //return ret;
722 /*--------------------------------------------------------------------------*/
723 static EVAL_BUILT_IN_RCD_GRc Eval_GRc(CC_STATIC);
724 void EVAL_BUILT_IN_RCD_GRc::tr_eval(ELEMENT* d)const
725 { untested();
726 assert(d);
727 DEV_BUILT_IN_RCD* p = prechecked_cast<DEV_BUILT_IN_RCD*>(d->owner());
728 assert(p);
729 const COMMON_BUILT_IN_RCD* cc = prechecked_cast<const COMMON_BUILT_IN_RCD*>(p->common());
730 const SDP_BUILT_IN_RCD* s = prechecked_cast<const SDP_BUILT_IN_RCD*>(cc->sdp());
731 assert(s); USE(s);
732 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(cc->model());
733 assert(m); USE(m);
735 // FIXME: merge with __Rc somehow
736 double _c[3] = { cc->_Rc0, cc->_Rc1 * cc->_lambda, 0 };
737 double x = (d->_y[0].x);
738 // trace1("Rc", x);
739 double f0 = 0.;
740 double f1 = 0.;
741 for (size_t i=1; i>0; --i) { untested();
742 f0 += _c[i];
743 f0 *= x;
744 f1 *= x;
745 f1 += _c[i]*int(i);
747 f0 += _c[0];
748 d->_y[0] = FPOLY1(x, f0, f1);
750 // d->set_converged(d->conv_check());
752 /*--------------------------------------------------------------------------*/
753 DEV_BUILT_IN_RCD::DEV_BUILT_IN_RCD()
754 :BASE_SUBCKT(),
755 // input parameters,
756 // calculated parameters,
757 _lasts(-inf),
758 _region(UNKNOWN),
759 // netlist,
760 _Ccg(0),
761 _Ye(0),
762 _Re(0),
763 _Rc(0),
764 _GRc(0),
765 _Ccgfill(0),
766 _tr_fill(0),
767 _tr_dfill(0),
768 _iter_newton(0),
769 _iter_bisect(0)
772 _n = _nodes;
773 _nodes[n_p].set_adp();
774 assert(_n[n_p].is_adp());
775 assert(_n[n_u].is_electrical());
776 attach_common(&Default_BUILT_IN_RCD);
777 // _nodes[n_p].a_()->trhack = 0;
779 ++_count;
780 // overrides
781 set_value(1);
783 /*--------------------------------------------------------------------------*/
784 DEV_BUILT_IN_RCD::DEV_BUILT_IN_RCD(const DEV_BUILT_IN_RCD& p)
785 :BASE_SUBCKT(p),
786 // input parameters,
787 // calculated parameters,
788 _lasts(-inf),
789 _region(p._region),
790 // netlist,
791 _Ccg(0),
792 _Ye(0),
793 _Re(0),
794 _Rc(0),
795 _GRc(0),
796 _Ccgfill(0),
797 _tr_fill(p._tr_fill),
798 _tr_dfill(p._tr_dfill),
799 _iter_newton(0),
800 _iter_bisect(0)
802 _n = _nodes;
803 assert(p._n[n_p].is_adp());
804 for (uint_t ii = 0; ii < max_nodes() + int_nodes(); ++ii) {
805 _n[ii] = p._n[ii];
806 trace2("DEV_BUILT_IN_RCD::DEV_BUILT_IN_RCD(p)", ii, _n[ii].is_adp());
808 assert(_n[n_p].is_adp());
809 ++_count;
810 // overrides
812 /*--------------------------------------------------------------------------*/
813 void DEV_BUILT_IN_RCD::expand()
815 trace1("DEV_BUILT_IN_RCD::expand", long_label());
816 assert(_n[n_p].is_adp());
817 BASE_SUBCKT::expand(); // calls common->expand, attaches model
818 assert(_n);
819 assert(common());
820 const COMMON_BUILT_IN_RCD* c = static_cast<const COMMON_BUILT_IN_RCD*>(common());
821 assert(c);
822 assert(c->model());
823 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
824 assert(m); USE(m);
825 assert(c->sdp());
826 const SDP_BUILT_IN_RCD* s = prechecked_cast<const SDP_BUILT_IN_RCD*>(c->sdp());
827 assert(s); USE(s);
829 if (!subckt()) {
830 new_subckt();
831 }else{ untested();
833 if (_sim->is_first_expand()) {
834 precalc_first();
835 precalc_last();
836 trace4("DEV_BUILT_IN_RCD::expand, first", long_label(), hp(this), _n[n_p].n_(), _n[n_p].is_adp());
837 assert(_n[n_p].is_adp());
838 assert(!(_n[n_p].n_())); // n_ is electrical
839 if (!(_n[n_p].a_())){
840 trace1("DEV_BUILT_IN_RCD::expand, no 3rd external node connected", hp(_n));
841 _n[n_p].new_model_adp_node("c", this);
842 trace1("DEV_BUILT_IN_RCD::expand have new adpnode", hp(_n[n_p].a_()));
843 } else { itested();
844 trace1("DEV_BUILT_IN_RCD::expand, 3rd node present, external", long_label());
848 _Ccgfill = _n[n_p].a_(); assert(_Ccgfill);
850 // idee: _Ccgfill:: tr_value <= udc
851 // tt_value <= E
853 // _Udc = new ADP_NODE_UDC((const COMPONENT*) common()); //, _Ccgfill);
854 // ADP_NODE_LIST::adp_node_list.push_back( _Udc );
856 //precalc();
857 subckt()->expand();
858 //subckt()->precalc();
859 assert(!is_constant());
860 if ( adp() == NULL ){
861 // attach_adp( m->new_adp( (COMPONENT*) this ) );
862 }else{ untested();
863 untested(); // rebuild circuit??
866 if (m->v2()){
867 // incomplete();
868 // do_tt?
869 // _Ccgfill->tt_set( -c->_wcorr );
872 /*--------------------------------------------------------------------------*/
873 double DEV_BUILT_IN_RCD::P()const {
874 const COMMON_BUILT_IN_RCD* c = static_cast<const COMMON_BUILT_IN_RCD*>(common());
875 assert(c);
876 assert(c->model());
877 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
878 return m->P(this);
880 /*--------------------------------------------------------------------------*/
881 double DEV_BUILT_IN_RCD::tr_probe_num(const std::string& x)const
883 assert(_n);
884 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
885 assert(c);
886 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
887 assert(m);
888 const SDP_BUILT_IN_RCD* s = prechecked_cast<const SDP_BUILT_IN_RCD*>(c->sdp());
889 assert(s); USE(s);
890 ADP_NODE* Ccgfill = _n[n_p].a_();
891 assert(Ccgfill);
893 if (Umatch(x, "region ")) { untested();
894 return static_cast<double>(region());
895 }else if (Umatch(x, "ulo |vlo ")) {
896 return ( Ccgfill->tr_lo );
897 }else if (Umatch(x, "uin |vin ")) {
898 // assert (involts() <= _Ccgfill->tr_hi || _sim->_time0==0);
899 // assert (involts() >= _Ccgfill->tr_lo || _sim->_time0==0);
900 return involts();
901 }else if (Umatch(x, "s{tresslevel} ")) {
902 // assert(involts() * value() == _Ccgfill->tr());
903 // return Ccgfill->tr(); (hmmm.)
904 return involts() * value();
905 }else if (Umatch(x, "uhi |vhi ")) {
906 return ( Ccgfill->tr_hi );
907 }else if (Umatch(x, "tra ")) { untested();
908 return ( Ccgfill->tr_abs_err() );
909 }else if (Umatch(x, "noise ")) { untested();
910 assert(Ccgfill);
911 return 0; // ( Ccgfill->get_tr_noise() );
912 }else if (Umatch(x, "udc |ueff")) {
913 return (_Ccgfill->tr());
914 }else if (Umatch(x, "dudc ")) {
915 return(_Ccgfill->tr1() - _Ccgfill->tr());
916 }else if (Umatch(x, "udc1 ")) {
917 return(_Ccgfill->tr1());
918 }else if (Umatch(x, "trr ")) { untested();
919 return ( _Ccgfill->tr_rel_err() );
920 } else if (Umatch(x, "RE0 " )) { return( c->_Re1 );}
921 else if (Umatch(x, "RE1 " )) { return( c->_Re0 );}
922 else if (Umatch(x, "RC0 " )) { return( c->_Rc1 );}
923 else if (Umatch(x, "RC1 " )) { return( c->_Rc0 );}
924 else if (Umatch(x, "E0|zero " )) {
925 return ( c->_zero );
926 }else if (Umatch(x, "dE ")) { untested();
927 return (double)_tr_fill; // shifted
928 }else if (Umatch(x, "E ")) {
929 return (double)_tr_fill; // shifted == unshifted
930 }else if (Umatch(x, "E{end} |E_end ")) { itested();
931 if(is_number(_Ccgfill->tr()))
932 return double(m->E_end((long double)(value()*_Ccgfill->tr()),c));
933 return double(m->E_end((long double)(value()*involts()),c));
934 }else if (Umatch(x, "te ")) { untested();
935 return ( c->__tau_up(c->Uref) );
936 }else if (Umatch(x, "tc ")) { untested();
937 return ( m->__Rc(0., c) );
938 }else if (Umatch(x, "re ")) { untested();
939 return ( m->__Re(c->Uref, c) );
940 }else if (Umatch(x, "rc ")) { untested();
941 return ( m->__Rc(0. , c) );
942 }else if (Umatch(x, "tau ")) {
943 return ( double(m->__tau((long double)(value()*involts()),c)));
944 }else if (Umatch(x, "tra ")) { untested();
945 return ( _Ccgfill->tr_abs_err() );
946 }else if (Umatch(x, "uref ")) { untested();
947 return ( c->Uref );
948 }else if (Umatch(x, "P ")) {
949 return ( P() );
950 }else if (Umatch(x, "vw{v} ")) { untested();
951 assert (c->_weight != .0);
952 return _Ccgfill->get_total() * c->_weight * c->_wcorr;
953 }else if (Umatch(x, "tt ")) { itested();
954 return (double)_Ccgfill->tt();
955 }else if (Umatch(x, "order " )) { return( _Ccgfill->order() );
956 }else if (Umatch(x, "fill ")) { untested();
957 return (double)_tr_fill;
958 #ifndef NDEBUG
959 }else if (Umatch(x, "chp ")) {
960 return hp(_Ccgfill);
961 }else if (Umatch(x, "m{atrix} ")) {
962 return _Ccgfill->m_();
963 }else if (Umatch(x, "v{alue} ")) {
964 return value();
965 #endif
966 }else if (Umatch(x, "wt ")) { untested();
967 return c->_weight;
968 }else if (Umatch(x, "status ")) { untested();
969 return static_cast<double>(converged() * 2);
970 }else if (Umatch(x, "_region ")) { untested();
971 return _region;
974 return BASE_SUBCKT::tr_probe_num(x);
976 /*--------------------------------------------------------------------------*/
977 double DEV_BUILT_IN_RCD::tt_probe_num(const std::string& x)const
979 assert(_n);
980 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
981 const COMMON_BUILT_IN_RCD* cc = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
982 assert(c);
983 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(cc->model());
984 assert(m);
985 const SDP_BUILT_IN_RCD* s = prechecked_cast<const SDP_BUILT_IN_RCD*>(cc->sdp());
986 assert(s); USE(s);
987 ADP_NODE* Ccgfill = _n[n_p].a_();
988 assert(Ccgfill);
990 if (Umatch(x, "P ")) {
991 return P();
992 } else if (Umatch(x, "vc ")) { untested();
993 // return _Ccgfill->tt();
994 // depends on model!
995 assert(is_number( ( P() )));
996 return ( P() );
998 else if (Umatch(x, "tr ")) {
999 return( _Ccgfill->tr_get() );
1000 } else if (Umatch(x, "tt ")) { itested();
1001 return( _Ccgfill->tt() );
1002 } else if (Umatch(x, "dtt ")) { untested();
1003 return( _Ccgfill->tt()-_Ccgfill->tt1());
1004 } else if (Umatch(x, "ttg{ain} ")) { itested();
1005 return _ttgain;
1006 } else if (Umatch(x, "ttf{uture} ")) { itested();
1007 return _ttfuture;
1008 } else if (Umatch(x, "ttr ")) { untested();
1009 return( _Ccgfill->tt_rel_err() );
1010 } else if (Umatch(x, "trr " )) { untested();
1011 return( _Ccgfill->tr_rel_err() ); }
1012 else if (Umatch(x, "v{alue} " )) { untested();
1013 return value();
1014 } else if (Umatch(x, "s{tresslevel} ")) {
1015 return Ccgfill->tr();
1017 #ifndef NDEBUG
1018 else if (Umatch(x, "iter " )) { return( _iter_newton ); }
1019 else if (Umatch(x, "in " )) { return( _iter_newton ); }
1020 else if (Umatch(x, "ib " )) { return( _iter_bisect ); }
1021 #endif
1022 else if (Umatch(x, "tra " )) { return( _Ccgfill->tr_abs_err() ); }
1023 else if (Umatch(x, "Rc " )) { return( c->_Rc0 ); }
1024 else if (Umatch(x, "wt " )) { return( c->_weight ); }
1025 else if (Umatch(x, "region ")) { return( m->tt_region( this ) ); }
1026 else if (Umatch(x, "uref " )) { return( c->Uref ); }
1027 else if (Umatch(x, "udc ")) { return( _Ccgfill->tr() ); }
1028 else if (Umatch(x, "tauinv ")) { untested();
1029 long double n = _Ccgfill->tr();
1030 if(!is_number(n)) return NOT_VALID;
1031 return( double(m->__tau_inv( value()*n,cc))); }
1032 else if (Umatch(x, "tau ")) {
1033 long double n = _Ccgfill->tr();
1034 if(!is_number(n)) return NOT_VALID;
1035 return( double(m->__tau( value()*n,cc))); }
1036 else if (Umatch(x, "uend " )) { return( c->Uref / (c->Re(c->Uref) / c->Rc(c->Uref) +1) * c->_wcorr ) * c->_weight; }
1037 else if (Umatch(x, "tc " )) { return( c->Rc(0) ); }
1038 else if (Umatch(x, "te ")) { untested();
1039 if (m->v2())
1040 return( m->__Re(cc->Uref,cc));
1041 else
1042 return ( c->__tau_up( c->Uref ) );
1044 else if (Umatch(x, "vwtr ")) { untested();
1045 return ( _Ccgfill->tr_get() * c->_weight );
1047 return BASE_SUBCKT::tt_probe_num(x);
1049 /*--------------------------------------------------------------------------*/
1050 /*--------------------------------------------------------------------------*/
1051 // cc_direct
1053 double ADP_BUILT_IN_RCD::tt_probe_num(const std::string& )const
1054 {untested(); return 888;}
1055 double ADP_BUILT_IN_RCD::tr_probe_num(const std::string& )const
1056 {untested(); return 888;}
1057 void ADP_BUILT_IN_RCD::init(const COMPONENT* )
1058 { untested();
1059 untested();
1061 /*--------------------------------------------------------------------------*/
1062 region_t MODEL_BUILT_IN_RCD::region( const COMPONENT* )const
1063 { untested();
1064 return UNKNOWN;
1066 /*--------------------------------------------------------------------------*/
1067 /*--------------------------------------------------------------------------*/
1068 int MODEL_BUILT_IN_RCD::tt_region( const COMPONENT* )const
1069 { untested();
1070 return 179;
1072 /*--------------------------------------------------------------------------*/
1073 region_t DEV_BUILT_IN_RCD::region( )const
1074 { untested();
1075 return UNKNOWN;
1077 /*--------------------------------------------------------------------------*/
1078 int DEV_BUILT_IN_RCD::tt_region( )const
1079 { untested();
1080 return 14;
1082 /*--------------------------------------------------------------------------*/
1083 void MODEL_BUILT_IN_RCD::tt_eval(COMPONENT* )const
1084 { untested();
1085 untested();
1087 /*--------------------------------------------------------------------------*/
1088 void MODEL_BUILT_IN_RCD::do_tt_prepare(COMPONENT*)const
1089 { untested();
1091 ///*--------------------------------------------------------------------------*/
1092 ADP_CARD* MODEL_BUILT_IN_RCD::new_adp( COMPONENT* c)const
1093 { untested();
1094 trace0("MODEL_BUILT_IN_RCD::new_adp");
1095 assert(c);
1096 return MODEL_CARD::new_adp(c);
1098 /*--------------------------------------------------------------------------*/
1099 bool DEV_BUILT_IN_RCD::tr_needs_eval()const
1101 return 0; // not needed to call q_accept.
1103 /*--------------------------------------------------------------------------*/
1104 long double MODEL_BUILT_IN_RCD::__step(long double s, long double cur, double deltat, const COMMON_COMPONENT* c ) const
1106 // trace3("MODEL_BUILT_IN_RCD::__step", s, cur, deltat);
1107 assert(deltat>=0.);
1108 assert(is_number(s));
1109 assert(is_number(cur));
1110 assert(cur>-.1 && cur <1.1);
1111 const COMMON_BUILT_IN_RCD* cc = dynamic_cast<const COMMON_BUILT_IN_RCD*>(c);
1112 const MODEL_BUILT_IN_RCD* m = static_cast<const MODEL_BUILT_IN_RCD*>(this);
1113 USE(m);
1114 if(cc->positive && s<0) {
1115 s = 0;
1116 }else if (s<0) {
1117 }else{
1119 trace3("", s, E_end(s,cc), E_end(-s,cc));
1120 assert ( s >= -0.001 || !cc->positive);
1121 long double Eend = E_end(s,cc);
1122 assert(Eend<=1.);
1123 long double tauinv = __tau_inv(s,cc);
1124 long double ret = (cur-Eend) * expl( -deltat*tauinv ) + Eend;
1126 assert(ret<=1.0000001);
1128 // trace5("MODEL_BUILT_IN_RCD::__step", Eend, deltat, s, ret, logl(fabsl(cur-Eend ) ) );
1130 assert(ret>=0.);
1131 if (ret>1) {
1132 return 1;
1133 }else{
1134 return ret;
1137 ///*--------------------------------------------------------------------------*/
1138 long double DEV_BUILT_IN_RCD::extrapolate(const double* tr0)const
1140 if(tr0) assert(is_number(*tr0));
1141 const COMMON_BUILT_IN_RCD* c = static_cast<const COMMON_BUILT_IN_RCD*>(common());
1142 const COMMON_BUILT_IN_RCD* cc = c;
1143 assert(c);
1144 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
1145 assert(m);
1146 long double E_old = _Ccgfill->tt1() + c->_zero; // E at Time1 or last_Time
1147 long double fill_new = E_old;
1148 double toT = _sim->_Time0;
1149 double fromT = _sim->_Time0 - _sim->_dT0 + _sim->last_time();
1150 if (!tr0) {
1151 //pred mode
1152 }else{
1153 trace1("", *tr0);
1154 toT += _sim->last_time();
1156 double ex_time = toT - fromT;
1158 trace8("DEV_BUILT_IN_RCD::extrapolate", ex_time, _sim->_dT0, _sim->last_time(), _sim->last_Time(), fromT, toT, E_old, tr0);
1159 if( ex_time < 1e-18 ){
1160 assert(is_almost(double(fill_new) , double (E_old)));
1162 assert(ex_time >= 0);
1164 long double eff1 = value()*_Ccgfill->tr( fromT + ex_time/3.0, tr0);
1165 long double eff2 = value()*_Ccgfill->tr( fromT + ex_time*2.0/3.0, tr0);
1167 if(!is_number(eff1)){
1168 error(bDANGER, "nan bug %d %f\n", _Ccgfill->order(), tr0);
1169 assert(0);
1171 assert(is_number(eff2));
1173 if(cc->positive) {
1174 eff1 = max(eff1,0.0L);
1175 eff2 = max(eff2,0.0L);
1176 }else{ itested();
1179 fill_new = m->__step( eff1, fill_new, ex_time*.5, c );
1180 assert(is_number(fill_new));
1181 fill_new = m->__step( eff2, fill_new, ex_time*.5, c );
1182 assert(is_number(fill_new));
1183 assert(1.01 > fill_new && fill_new > -.01);
1185 if (fill_new>1) {
1186 return 1.;
1187 }else if (fill_new<0) {
1188 return 0.;
1189 }else {
1190 return fill_new;
1193 ///*--------------------------------------------------------------------------*/
1194 // dashier funktioniert (aus e_subckt.h)
1195 // void tr_queue_eval() {assert(subckt()); subckt()->tr_queue_eval();}
1196 // dashier macht der modelgen:
1197 // void tr_queue_eval() {if(tr_needs_eval()){q_eval();}}
1198 ///*--------------------------------------------------------------------------*/
1199 void DEV_BUILT_IN_RCD::do_tt()
1201 assert(_n);
1202 assert(common());
1203 const COMMON_BUILT_IN_RCD* c = static_cast<const COMMON_BUILT_IN_RCD*>(common());
1204 assert(c);
1205 assert(c->model());
1206 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
1207 assert(m); USE(m);
1208 assert(c->sdp());
1209 const SDP_BUILT_IN_RCD* s = prechecked_cast<const SDP_BUILT_IN_RCD*>(c->sdp());
1210 assert(s); USE(s);
1212 assert(_sim->_time0 == 0 || _sim->_mode==s_TRAN ); //?
1214 trace5("DEV_BUILT_IN_RCD::do_tt", long_label(), _sim->_dT0, _Ccgfill->tt(), _sim->_Time0, _Ccgfill->tr() );
1215 if(_sim->phase() == p_PD){
1216 // assert(!_Ccgfill->tr());
1217 _Ccgfill->tr() = 0; // check: what is tr()?
1218 // why not use tr(0) and leave tr alone?
1219 assert(_sim->_dT0);
1222 if (_sim->_dT0==0.) {
1223 assert(c->_zero); // 0 is very unlikely...
1224 _tr_fill = _Ccgfill->tt() + c->_zero; // shifted
1225 assert(is_number(_tr_fill));
1226 assert(_tr_fill<=1+1e-9);
1227 if (_tr_fill>1.) { untested();
1228 _tr_fill = 1.;
1230 _tr_dfill = 0;
1231 _nodes[n_p].a_()->trhack = (double) _tr_dfill;
1232 return;
1233 } else {
1234 assert(is_number(_tr_fill));
1237 double Time1 = _sim->_Time0 - _sim->_dT0;
1239 trace5("DEV_BUILT_IN_RCD::do_tt", _sim->_Time0, _sim->_dT0, tt_iteration_number(), _sim->_Time0, _sim->_time0);
1240 trace4("DEV_BUILT_IN_RCD::do_tt ", _Ccgfill->tr() , _Ccgfill->tr(_sim->_Time0 ), _Ccgfill->order(), _sim->_time0);
1242 if (! ( is_almost( _Ccgfill->tr1() , _Ccgfill->tr(Time1) ))) {
1243 error(bDANGER, "DEV_BUILT_IN_RCD::tr_stress !almost tr1 %E tr(T1) %E T1 %f. order %d\n",
1244 double(_Ccgfill->tr1()) , double(_Ccgfill->tr(Time1)), Time1, _Ccgfill->order() );
1247 if (!is_number(_Ccgfill->tr_rel(_sim->_dT0 ))) { unreachable();
1248 error(bDANGER, "DEV_BUILT_IN_RCD::do_tt tr_rel nan at %f dT %f, order %d\n",
1249 _sim->_Time0, _sim->_dT0, _Ccgfill->order());
1250 // assert(0);
1253 long double E_old = _Ccgfill->tt1() + c->_zero; // shifted
1254 assert(E_old<=1+1e-9);
1255 if (E_old>1.) { untested();
1256 E_old = 1.;
1258 _tr_fill = E_old;
1259 assert(_tr_fill<=1);
1261 assert (is_number(E_old));
1263 long double fill_new = extrapolate();
1264 assert(fill_new <= 1);
1266 trace3("DEV_BUILT_IN_RCD::do_tt", fill_new, E_old, fill_new-_tr_fill );
1268 assert(is_number(fill_new));
1270 trace3("DEV_BUILT_IN_RCD::do_tt", _tr_fill, _sim->tt_iteration_number(), c->_zero );
1272 assert(is_number(fill_new));
1273 _Ccgfill->tt() = (double) fill_new - c->_zero;
1274 assert(_Ccgfill->tt() > -.01);
1275 assert(_Ccgfill->tt() <= 1.);
1276 _tr_fill = fill_new;
1277 assert(is_number(_tr_fill));
1278 assert(_tr_fill<=1);
1279 _tr_dfill = 0;
1280 _nodes[n_p].a_()->trhack = (double) _tr_dfill;
1281 trace2("DEV_BUILT_IN_RCD::do_tt done", fill_new, _tr_fill );
1283 // print something useful for "stress" (BUG?)
1284 _Ccgfill->tr() = _Ccgfill->tr(_sim->_Time0);
1286 ///*--------------------------------------------------------------------------*/
1287 void MODEL_BUILT_IN_RCD_NET::do_stress_apply( COMPONENT* ) const
1288 { untested();
1290 ///*--------------------------------------------------------------------------*/
1291 void DEV_BUILT_IN_RCD::tr_advance()
1293 BASE_SUBCKT::tr_advance(); //?
1294 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
1295 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
1296 assert(c);
1297 ADP_NODE* a = _n[n_p].a_();
1298 set_not_converged();
1299 assert(a);
1300 double stress = involts() * value();
1301 _time1 = _time0;
1302 double _dt = _sim->_time0 - _time1;
1303 if(_dt < 0){ unreachable();
1304 // BUG in tr_begin?. tt_advance?. should not be here
1305 _dt = 0.;
1307 _time0 = _sim->_time0;
1308 long double newtrhack;
1309 assert(_dt>=0.);
1310 if(_dt){
1311 trace3("??", _dt, stress, long_label());
1312 newtrhack = m->__step( stress, a->tt() + _tr_dfill + c->_zero, _dt, c ) - c->_zero;
1313 }else{
1314 // BUG?!
1315 newtrhack = a->tt() + _tr_dfill;
1317 trace7("tradv",_sim->_time0, a->trhack, newtrhack, _dt, stress, a->tt(), _tr_dfill);
1319 // predictor...
1320 if (_dt) {
1321 a->trhack = (double) newtrhack - a->tt();
1324 ///*--------------------------------------------------------------------------*/
1325 void DEV_BUILT_IN_RCD::tr_regress()
1327 BASE_SUBCKT::tr_regress(); //??
1328 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
1329 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
1330 assert(c);
1331 ADP_NODE* a = _n[n_p].a_();
1332 set_not_converged();
1333 double stress = involts() * value();
1334 _time0 = _sim->_time0;
1335 double _dt = _sim->_time0 - _time1;
1336 trace8("",_sim->_time0, a->trhack, a->State(), _dt, a->tr(), stress, a->tt(), _tr_dfill);
1338 if(_dt < 0){ unreachable();
1339 // BUG in tr_begin?. tt_advance?. should not be here
1340 _dt = 0.;
1342 // predictor...
1343 a->trhack = double(m->__step( stress, a->tt() + _tr_dfill + c->_zero, _dt, c ) - c->_zero);
1345 ///*--------------------------------------------------------------------------*/
1346 void DEV_BUILT_IN_RCD::tr_stress()
1348 #ifndef NDEBUG
1349 if (_stressiter == (unsigned)(_sim->iteration_tag())){ untested();
1350 error(bDANGER, "double stress at %E in %s, %i %i\n", _sim->_time0,
1351 long_label().c_str(), _stressiter, _sim->iteration_tag());
1352 assert(0);
1354 _stressiter = _sim->iteration_tag();
1355 #endif
1357 // fixme: assert (TTT || trage)
1358 const DEV_BUILT_IN_RCD* rcd = this;
1359 double h = _sim->_dt0;
1360 assert(h || !_sim->_time0);
1361 const COMMON_BUILT_IN_RCD* c = static_cast<const COMMON_BUILT_IN_RCD*>(common());
1362 const COMMON_BUILT_IN_RCD* cc = c;
1363 assert(c);
1364 assert(c->model());
1365 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
1366 assert(m);
1367 assert(c->sdp());
1368 assert(_Ccgfill);
1369 ADP_NODE* _c = _Ccgfill;
1371 long double stress = rcd->involts() * value();
1373 if( stress < -0.001 && cc->positive ) {
1374 error(bLOG, "at %f, %f in %s: stress too small: %f, u %f b %f\n",
1375 _sim->_Time0, _sim->_time0,
1376 long_label().c_str(), (double)stress, _n[n_u].v0(), _n[n_b].v0());
1377 stress = 0.;
1378 } else if ( stress < 0 && cc->positive ) {
1379 stress = 0.;
1380 }else{
1383 assert(value());
1384 assert (stress==stress);
1385 // trace7("DEV_BUILT_IN_RCD::tr_stress", long_label(), stress, _sim->_time0, _lasts, _tr_fill, h, value());
1387 if( _sim->_time0 > _lasts ){
1388 _lasts = _sim->_time0;
1389 }else {
1390 trace1("DEV_BUILT_IN_RCD::tr_stress again?? bug??", _sim->_time0 );
1391 if (! (_sim->_time0 == _lasts) ){
1392 error(bDANGER,"DEV_BUILT_IN_RCD::tr_stress critically unequal now: %E lasts: %E at %E\n",
1393 _sim->_time0, _lasts, _sim->_Time0 );
1394 unreachable();
1395 assert(0);
1396 throw(Exception("time mismatch in %s: time0: %E lasts: %E " , long_label().c_str(), _sim->_time0, _lasts));
1398 return;
1401 assert(is_number(involts()));
1402 assert(fabs(involts()<1e3));
1404 if( _sim->_time0==0 ){
1405 assert( _Ccgfill->tr_lo == inf );
1406 assert( _Ccgfill->tr_hi == -inf );
1407 // assert !tran_dynamic()?
1409 _Ccgfill->tr_lo = min(involts(), _Ccgfill->tr_lo);
1410 _Ccgfill->tr_hi = max(involts(), _Ccgfill->tr_hi);
1412 // _Ccgfill->set_tr(_Ccgfill->tt());
1414 } else {
1415 // do not update tr_lo, tr_hi. could be wrong!
1417 // assert tran_dynamic()?
1419 _Ccgfill->tr_lo = min(involts(), _Ccgfill->tr_lo);
1420 _Ccgfill->tr_hi = max(involts(), _Ccgfill->tr_hi);
1422 assert( is_number(_Ccgfill->tr_lo) );
1423 assert( is_number(_Ccgfill->tr_hi) );
1424 assert(fabs(_Ccgfill->tr_lo) < 1e5);
1425 assert(fabs(_Ccgfill->tr_hi) < 1e5);
1427 if( -15< _Ccgfill->tr_hi && _Ccgfill->tr_hi < 100 &&
1428 -15< _Ccgfill->tr_lo && _Ccgfill->tr_lo < 100 ){
1429 }else{unreachable();
1430 #ifndef NDEBUG
1431 error(bDANGER, "%s something wrong with input range %f %f at time %E\n",
1432 long_label().c_str(), _Ccgfill->tr_lo, _Ccgfill->tr_hi, _sim->_time0 );
1433 assert(false);
1434 #endif
1437 if (!h) { untested();
1438 trace1("not h\n", _tr_fill);
1439 return;
1441 if(_sim->phase()==p_PD){
1442 assert(!_c->tr_lo); USE(_c);
1443 assert(!_c->tr_hi);
1446 if (stress >= 0) {
1447 if (m->E_end(stress,c) <= -1e-16) { // shifted. untested();
1448 error(bDANGER, "nonmonotony at %f: %f < %f\n", stress, c->_zero, m->E_end(stress,c) );
1450 assert(m->E_end(stress,c) > -1e-15); // shifted
1451 }else if (cc->positive && stress < -1e-14) { itested();
1452 error(bTRACE, "in %s not positive uin_s=%LE, value %f\n", long_label().c_str(), stress, double(value()));
1453 }else if(cc->positive) { untested();
1454 stress = 0;
1455 }else{
1457 assert(double(value()));
1459 assert( is_almost(double(m->E_end_0(c)), c->_zero ));
1460 assert( is_almost(double(m->E_end(0.l,c)), c->_zero ));
1462 if( cc->positive) {
1463 if (_tr_fill < 0) { untested();
1464 trace1(("DEV_BUILT_IN_RCD::tr_stress fill is negative: " +
1465 short_label()).c_str() , _Ccgfill->get_total() );
1467 if (value() * involts() < -2e-1) {
1468 error(bTRACE, "DEV_BUILT_IN_RCD::tr_stress input %s is negative: %f."
1469 " overshoot?\n", long_label().c_str(), value()*involts() );
1471 } else {
1474 /*----------------------------------------------------------------------------*/
1476 long double fill = _tr_fill;
1478 fill = _tr_dfill + _Ccgfill->tt() + c->_zero; // shifted, unshifted?
1480 // trace5("DEV_BUILT_IN_RCD::tr_stress", _tr_dfill, fill, stress, rcd->involts(), iteration_number());
1481 assert(fill<1.1 && fill>-.1);
1482 if (fill >= 1.001 ){ untested();
1483 error(bDANGER, "DEV_BUILT_IN_RCD::tr_stress %s fill %LE big stress=%f\n", long_label().c_str(), _tr_fill, stress );
1484 fill = 1;
1487 //double fill = _n[n_ic].v0();
1488 assert (fill==fill);
1490 //tr_stress...
1491 long double newfill;
1492 switch(_sim->_stepno){ incomplete();
1493 case 0:
1494 case 1:
1495 default:
1496 // trace1("DEV_BUILT_IN_RCD::tr_stress calling __step", _sim->_stepno);
1497 assert(fill<1.1 && fill>-.1);
1498 newfill = m->__step(stress, fill, h, c);
1499 assert(newfill<= 1. && newfill>= 0);
1501 assert( newfill > -0.01 || !cc->positive);
1502 if (newfill <= 0 && cc->positive) { untested();
1503 newfill = 0.0;
1504 } else if(newfill > 1.000001){ untested();
1505 error(bDANGER, ("* RCD_V3 %f too big\n" + long_label() ).c_str() , newfill );
1506 newfill=1;
1508 assert(newfill==newfill);
1510 _tr_dfill += newfill - _tr_fill;
1511 _nodes[n_p].a_()->trhack = (double) _tr_dfill;
1512 // trace7("DEV_BUILT_IN_RCD::tr_stress ", fill, h, (newfill-fill)/h, newfill-fill, _tr_dfill, newfill, _tr_fill);
1513 _tr_fill = newfill;
1514 assert(is_number(_tr_fill));
1515 assert(_tr_dfill<1.1);
1516 assert(_tr_fill<=1.);
1517 assert(_tr_dfill>-1.1);
1519 if (_tr_dfill>1) {
1520 assert(false);
1521 } else if (_tr_dfill>.5) {
1522 error(bWARNING, "at %f: _tr_fill very high in %s: %f\n", _sim->_Time0, long_label().c_str(), (double)_tr_dfill);
1525 assert(_tr_fill<=1.);
1526 assert(_tr_fill>=0.);
1528 assert(h > 0);
1530 /*----------------------------------------------------------------------------*/
1531 double DEV_BUILT_IN_RCD::involts() const
1533 double v = _n[n_u].v0() - _n[n_b].v0();
1534 assert(is_number(v));
1535 assert(fabs(v) < 1e5);
1536 return v;
1538 /*----------------------------------------------------------------------------*/
1539 // FIXME: move pred/corr to here.
1540 /*----------------------------------------------------------------------------*/
1541 void DEV_BUILT_IN_RCD::tr_stress_last() // "tt_review?".
1543 ADP_NODE* a = _n[n_p].a_();
1544 trace6("DEV_BUILT_IN_RCD::tr_stress_last", short_label(), _tr_fill,
1545 _sim->_adp_nodes, _sim->_time0,
1546 _Ccgfill->tt()+_tr_dfill, _sim->tt_iteration_number());
1547 assert(_n[n_p].tt() == _n[n_p].tt());
1548 assert(_n[n_p].tt() == a->tt());
1549 assert(a);
1550 const COMMON_BUILT_IN_RCD* c = static_cast<const COMMON_BUILT_IN_RCD*>(common());
1551 assert(c);
1552 assert(c->model());
1553 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
1554 assert(m);
1555 assert(c->sdp());
1558 assert(is_number(_tr_dfill));
1559 _tr_fill = _Ccgfill->tt() + c->_zero + _tr_dfill; // shifted
1560 assert(is_number(_tr_fill));
1561 _nodes[n_p].a_()->trhack = (double) _tr_dfill;
1563 if( _sim->phase()==p_PD){
1564 assert(!a->tr_lo);
1565 assert(!a->tr_hi);
1567 trace2("", a->tr_lo, a->tr_hi );
1568 // assert( a->tr_lo <= a->tr_hi );
1569 if(_tr_fill>1){
1570 error(bTRACE, "at %f: something wrong with _tr_fill in %s\n", _sim->_Time0, long_label().c_str());
1571 _tr_fill = 1;
1574 trace5("DEV_BUILT_IN_RCD::tr_stress_last s ", _n[n_p].a_()->tt(),
1575 _n[n_p].a_()->get_tr(), a->get_total(), _n[n_p].m_(), _n[n_p].t_() );
1576 // fixme. move to common.
1577 assert(is_number(_tr_fill));
1578 assert(is_number(a->tt()));
1579 double uin_eff;
1580 try {
1581 // calculate udc (will be put into _c->tr() ? )
1582 m->do_tr_stress_last(_tr_fill,_Ccgfill, this);
1583 uin_eff = a->tr();
1584 } catch (Exception &e) { untested();
1585 error(bDANGER, "%s\n", long_label().c_str());
1586 throw(e);
1588 assert(is_number(_tr_fill));
1590 if( _sim->phase()==p_PD ){
1591 assert(!a->tr());
1594 if (uin_eff==0) {
1595 }else if ((uin_eff < a->tr_lo) || (uin_eff > a->tr_hi )) { untested();
1596 if ( uin_eff - a->tr_lo < -1e-20 || a->tr_hi - uin_eff < -1e-20 ){ untested();
1597 error(bDANGER, "Time %E: %s order broken, should be %E < %E < %E, is %E %E\n",
1598 (double)_sim->_Time0,
1599 long_label().c_str(),
1600 a->tr_lo, uin_eff, a->tr_hi,
1601 (uin_eff - a->tr_lo ), (a->tr_hi - uin_eff) );
1603 a->set_new_order(1); // hmm better 1?
1604 } else { // tested.
1607 assert( a->tr_lo <= a->tr_hi );
1609 if (a->tr_lo > a->tr() ) {
1610 a->tr() = a->tr_lo ;
1611 a->set_new_order(1);
1612 }else if ( a->tr() > a->tr_hi ) { untested();
1613 a->tr() = a->tr_hi ;
1614 a->set_new_order(1);
1615 } else { // tested.
1618 trace3("DEV_BUILT_IN_RCD::tr_stress_last done", a->tr_lo , a->tr(), a->tr_hi ) ;
1620 assert(is_number(a->tr()));
1621 assert(is_number(a->tt()));
1623 // tt_value not needed for rollback.
1624 _n[n_p].tt() = double(_tr_fill) - c->_zero; // shifted.
1625 assert(_n[n_p].tt() > -.01);
1626 if( _sim->phase()==p_PD ){
1627 assert(!a->tr());
1630 /*--------------------------------------------------------------------------*/
1631 void DEV_BUILT_IN_RCD::tt_begin()
1633 #ifndef NDEBUG
1634 _stressiter=0;
1635 #endif
1636 ADP_NODE* a = _n[n_p].a_();
1637 assert(a); USE(a);
1638 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
1639 trace1("DEV_BUILT_IN_RCD::tt_begin()", _sim->_tt_uic);
1641 if (_sim->_tt_uic) {
1642 } else {
1643 trace3("DEV_BUILT_IN_RCD::tt_begin()", c->_zero, _n[n_p].m_(), hp(_Ccgfill));
1644 _n[n_p].tt() = 0; // shifted
1646 assert(is_number(a->tt()));
1648 _tr_fill = _n[n_p].tt() + c->_zero;
1649 assert(_tr_fill<=1.001);
1650 assert(is_number(_tr_fill));
1651 if(_tr_fill>1){untested();
1652 _tr_fill = 1;
1653 }else{
1656 _tr_dfill = 0;
1657 _nodes[n_p].a_()->trhack = (double) _tr_dfill;
1658 _Ccgfill->set_tr(-inf);
1660 _Ccgfill->tr_lo = inf;
1661 _Ccgfill->tr_hi = -inf;
1663 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(c->model());
1664 m->do_tt_prepare(this);
1666 _lasts = -inf;
1667 // q_eval(); untested();
1669 trace4("DEV_BUILT_IN_RCD::tt_begin done", long_label(), c->_zero, _sim->_tt_uic, _n[n_p].tt() );
1671 ///*--------------------------------------------------------------------------*/
1672 void DEV_BUILT_IN_RCD::tr_restore()
1674 ADP_NODE* a = _n[n_p].a_();
1675 assert(a);
1676 a->trhack = 0;
1678 ///*--------------------------------------------------------------------------*/
1679 void DEV_BUILT_IN_RCD::tr_begin()
1681 BASE_SUBCKT::tr_begin();
1682 trace3("DEV_BUILT_IN_RCD::tr_begin()", _n[n_u].v0(), _n[n_b].v0(), _n[n_u].m_());
1684 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
1685 assert(c->_zero); // 0 is very unlikely...
1686 _tr_fill = _Ccgfill->tt() + c->_zero; // shifted
1687 if(_tr_fill>1){untested();
1688 _tr_fill = 1;
1689 }else{
1691 _lasts = -inf; // must be -inf, so time0==0 works out
1692 _Ccgfill->tr_hi = -inf;
1693 _Ccgfill->tr_lo = inf;
1695 // _Ccgfill->tr() = 0; untested();
1697 // BUG: only do if inside .tw
1698 // or trage flag set
1699 // q_eval(); untested();
1700 _time0 = _time1 = _sim->_time0;
1702 ///*--------------------------------------------------------------------------*/
1703 bool DEV_BUILT_IN_RCD::do_tr()
1704 { untested();
1705 // is this needed?
1706 trace3("DEV_BUILT_IN_RCD::do_tr", long_label(), _sim->_time0, _sim->iteration_tag());
1707 const COMMON_BUILT_IN_RCD* c = static_cast<const COMMON_BUILT_IN_RCD*>(common());
1708 assert(c); USE(c);
1709 assert(c->model());
1710 assert(c->sdp());
1712 return true;
1715 /*--------------------------------------------------------------------------*/
1716 /*--------------------------------------------------------------------------*/
1717 void DEV_BUILT_IN_RCD::precalc_last()
1719 trace1("DEV_BUILT_IN_RCD::precalc_last", value());
1720 COMPONENT::precalc_last();
1721 if (!double(value())) { itested();
1722 set_value(1);
1725 /*--------------------------------------------------------------------------*/
1726 /*--------------------------------------------------------------------------*/
1727 void MODEL_BUILT_IN_RCD::do_tr_stress_last( long double E, ADP_NODE* _c,
1728 COMPONENT* dd ) const
1730 DEV_BUILT_IN_RCD* d = prechecked_cast<DEV_BUILT_IN_RCD*>(dd);
1731 const COMMON_BUILT_IN_RCD* cc = prechecked_cast<const COMMON_BUILT_IN_RCD*>(d->common());
1732 const COMMON_BUILT_IN_RCD* c = cc;
1733 assert(is_number(_c->tt()));
1734 double E_old = _c->tt() + cc->_zero;
1735 double trtime = CKT_BASE::_sim->last_time();
1736 assert(trtime>=0);
1738 if (_c->tr() == -inf) _c->tr() = ( _c->tr_lo+_c->tr_hi)/2.0;
1739 if (!is_number(_c->tr())) _c->tr() = (_c->tr_lo+_c->tr_hi)/2.0;
1741 long double uin_eff = _c->tr(); // 0 == current estimate
1743 double v = dd->value(); assert(v);
1744 trace8("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last ", _c->label(), E_old,
1745 tt_iteration_number(), uin_eff, _sim->_time0, _c->tr_lo, _c->tr_hi, v);
1747 assert(E_old<E_max);
1748 assert(E<=E_max);
1750 assert(E<=1);
1752 long double E_high;
1753 long double E_test;
1754 long double E_low;
1755 long double uin_high_s = (v>0)? _c->tr_hi*v : _c->tr_lo*v;
1756 long double uin_low_s = (v>0)? _c->tr_lo*v : _c->tr_hi*v;
1757 assert(uin_high_s>=uin_low_s);
1758 if( _c->tr_hi == _c->tr_lo) {
1759 // do a sanity check and return
1760 // incomplete(); possibly ok (constant stress)
1761 } else {
1764 if( uin_low_s < -0.001 && cc->positive ){
1765 // probably numerical problem in transient
1766 error(bLOG,"%s s too small: %f value %f\n", dd->long_label().c_str(), (double)uin_low_s, double(v));
1768 if (uin_high_s < -0.001 && cc->positive) {
1769 error(bLOG,"s too small: %f, value %f\n", (double)uin_high_s, v);
1772 E_high = __step( uin_high_s, E_old, trtime, c );
1773 E_low = __step( uin_low_s, E_old, trtime, c );
1775 // catch numerical problems in __step
1776 if (E_high<E_low){
1777 error(bNOERROR,"%s weird. %f>%f\n", dd->long_label().c_str(), (double)E_low, (double)E_high);
1778 _c->set_new_order(1); // hmmm
1779 _c->set_tr(double((uin_low_s+uin_high_s)/(2*v))); // assume low ueff
1780 return;
1781 } else if (E_low > E) {
1782 error(bNOERROR,"%s weird. %f>%f\n", dd->long_label().c_str(), (double)E_low, (double)E);
1783 // low stress ages more than transient.
1784 _c->set_new_order(1); // hmmm
1785 _c->set_tr(double((uin_low_s+uin_high_s)/(2*v))); // assume low ueff
1786 if ( _c->tr() - _c->tr_lo < -1e-20) { untested();
1787 unreachable();
1789 if( _c->tr_hi - _c->tr() < -1e-20 ){ untested();
1790 unreachable();
1792 return;
1793 } else if (E_high < E) {
1794 error(bNOERROR,"%s weird. %f<%f\n", dd->long_label().c_str(), (double)E_high, (double)E);
1795 _c->set_new_order(1); // hmmm
1796 _c->set_tr(double((uin_low_s+uin_high_s)/(2*v))); // assume low ueff
1797 if ( _c->tr() - _c->tr_lo < -1e-20 ){ untested();
1798 unreachable();
1800 if ( _c->tr_hi - _c->tr() < -1e-20 ){ untested();
1801 unreachable();
1803 return;
1806 if (_c->tr_lo > uin_eff) {
1807 error(bNOERROR,"%s do_tr_stress_last uin_eff too low, %f below %f\n", dd->long_label().c_str(), (double)uin_eff, _c->tr_lo);
1808 uin_eff = ( _c->tr_lo+_c->tr_hi)/2.0;
1809 } else if (uin_eff > _c->tr_hi) {
1810 error(bNOERROR,"%s do_tr_stress_last uin_eff too high, %f above %f\n", dd->long_label().c_str(), (double)uin_eff, _c->tr_hi);
1811 uin_eff = ( _c->tr_lo+_c->tr_hi)/2.0;
1812 }else{
1815 if (cc->positive ){
1816 uin_low_s = max(0.L,uin_low_s);
1817 if(uin_low_s==0){
1818 uin_eff=0;
1820 uin_high_s = max(uin_high_s,uin_low_s);
1821 }else{untested();
1824 assert(uin_high_s>=uin_low_s);
1825 assert(v*uin_eff>=uin_low_s);
1826 assert(uin_high_s>=v*uin_eff);
1827 assert(uin_low_s>=-0.001 || !cc->positive);
1828 assert(uin_high_s>=-0.001 || !cc->positive);
1830 E_high = __step( uin_high_s, E_old, trtime, c );
1831 E_test = __step( v*uin_eff, E_old, trtime, c );
1832 E_low = __step( uin_low_s, E_old, trtime, c );
1834 assert (E_low>=0);
1836 if((double(E_high-E_low) < - 1e-18)){ untested();
1837 error(bDANGER,"%s do_tr_stress_last uin_high=%LE uin_low_s=%LE deltaE= %LE; %LE>%LE\n",
1838 dd->long_label().c_str(),
1839 uin_high_s, uin_low_s, E_high - E_low, E_high, E_low );
1841 // this is very bad...
1842 throw(Exception("monotony violation in __step"));
1845 bool tight_bounds = false; // effective uin is close to last (within noise margin)
1847 if ( E_low <= E && E <= E_high ) {
1848 // invert linearly
1849 long double dE = (E-E_low) / (E_high-E_low);
1850 assert(! (dE<0));
1852 uin_eff = uin_low_s + (uin_high_s - uin_low_s) * dE;
1853 trace5("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last linv", 1-E_low, 1-E, E_high-E_low, uin_low_s, uin_high_s );
1854 if (!(is_number(uin_eff))) {
1855 uin_eff = (uin_high_s+uin_low_s)/2.; // stupid fallback
1856 } else if ((uin_eff <= uin_high_s) && (uin_low_s <= uin_eff)) {
1857 tight_bounds = true;
1858 } else { untested();
1859 error(bDANGER, "unreachable? %E %E %E %E %E\n", (double)uin_eff, (double)uin_high_s, (double)uin_low_s,
1860 double(uin_high_s - uin_eff), double(uin_eff - uin_low_s));
1861 assert(false);
1863 uin_eff /= v;
1865 // error(bDANGER,"%s weird uin_high_s=%LE uin_low_s=%LE dus=%LE deltaE= %LE; %LE>%LE %LE %LE uin_eff_s %LE E %LE\n",
1866 // dd->long_label().c_str(),
1867 // uin_high_s, uin_low_s,
1868 // uin_high_s-uin_low_s,
1869 // E_high - E_low, E_high, E_low ,E-E_low, E_high-E, uin_eff*v, E);
1871 long double uin_eff_s = uin_eff * v;
1872 if(cc->positive && uin_eff_s<0){ untested();
1873 error(bWARNING, "uin_eff_s too small: %f in [%f, %f]\n", (double) uin_eff_s, _c->tr_lo, _c->tr_hi );
1874 assert(uin_eff_s >= -.001 || !cc->positive);
1876 if (tight_bounds){
1877 uin_eff *= v;
1878 trace3("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last tight", uin_low_s, uin_eff_s, uin_high_s);
1879 assert(double(uin_eff_s)<=double(uin_high_s));
1880 assert(double(uin_eff_s)>=double(uin_low_s));
1881 // FIXME: obsolete call? compare
1882 uin_eff_s = d->seff_bisect( uin_eff_s, (long double)E_old, E, double(uin_low_s), double(uin_high_s));
1883 assert(uin_low_s <= (double)uin_eff_s);
1884 assert(uin_high_s >= (double)uin_eff_s);
1885 trace2("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last tight", _c->tr_lo, _c->tr_hi);
1886 assert(uin_eff_s >= -.001 || !cc->positive);
1887 }else{
1888 try{
1889 trace3("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last", uin_low_s, uin_eff_s, uin_high_s);
1890 uin_eff_s = d->__uin_iter(uin_eff_s, (long double)E_old, E, double(uin_low_s), double(uin_high_s));
1891 assert(uin_eff_s >= -.001 || !cc->positive);
1893 assert(uin_eff_s >= uin_low_s);
1894 assert(uin_eff_s <= uin_high_s);
1896 } catch (Exception &e) { untested();
1897 error(bDANGER, "Exception in %s\n", long_label().c_str());
1898 throw(e);
1900 trace4("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last iteration", E_old, E, uin_eff, E-E_old);
1902 uin_eff = uin_eff_s/v;
1904 if(uin_eff > _c->tr_hi){ untested();
1905 error(bWARNING, "uin_eff too big?? %f in [%f, %f] \n", (double) uin_eff, _c->tr_lo, _c->tr_hi );
1906 itested();
1907 uin_eff = _c->tr_hi;
1910 if (uin_eff < _c->tr_lo) {
1911 uin_eff = _c->tr_lo;
1912 uin_eff_s = uin_eff*v;
1913 //assert(v*uin_eff >= -.001 || !cc->positive);
1916 if (cc->positive && uin_eff*v<0) {
1917 uin_eff = 0;
1920 // sanitycheck (monotonicity)
1921 E_test = this->__step( v*uin_eff, E_old, trtime, c );
1924 if ( tight_bounds && ((E_low > E_test) || ( E_test > E_high) )){ untested();
1925 trace3("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last monotonicity check ",
1926 uin_low_s, uin_high_s, uin_eff );
1927 assert( v*uin_eff<=uin_high_s && uin_low_s<=v*uin_eff);
1928 trace5("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last ", 1-E, 1-E_test,
1929 E_test-E_low, E_high-E_test, tight_bounds );
1931 if ( E_test - E_high <= 1e-30 && E_low - E_test <= 1e-30 ) { untested();
1933 } else { untested();
1934 error(bDANGER, "rcd E order problem, %LE, %LE, %LE\n", E_low ,E_test , E_high);
1936 //assert( E_test - E_high <= 1e-30 );
1937 //assert( E_low - E_test <= 1e-30);
1940 uin_high_s = max ( v*uin_eff + OPT::abstol, v*uin_eff * (1 + OPT::reltol) );
1941 uin_low_s = min ( v*uin_eff - OPT::abstol, v*uin_eff * (1-OPT::reltol) );
1943 // FIXME: get rid of __ prefix
1944 E_high = __step( uin_high_s, E_old, trtime, c );
1945 E_low = __step( uin_low_s, E_old, trtime, c );
1947 if( ( E_old < E_high ) && ( E_low <= E_old )) {
1948 _c->set_new_order(1);
1949 }else if (tight_bounds) {
1950 // _c->set_new_order(1);
1951 }else{
1954 if (double(E_high-E_low) < - 1.5e-19){ untested();
1955 error( bDANGER, "MODEL_BUILT_IN_RCD_EXP:: sanitycheck (delta %LE ) in %s\n",
1956 E_high - E_low, dd->long_label().c_str());
1957 error( bDANGER, "MODEL_BUILT_IN_RCD_EXP:: sanitycheck (abs %LE ) in %s\n",
1958 E_high, dd->long_label().c_str());
1959 throw(Exception("sanitycheck failed"));
1962 //assert ( uin_eff == _c->get_tr());
1966 assert(is_number(E_high-E_low));
1967 assert(is_number(E));
1968 //assert( (double) E_high-(double) E_low >= 0);
1969 ///assert((double) E_high>= (double) E_low);
1970 if (!(E_low <= E + 1.5e-19 || double(E)==1.0 || double(E_high)==1.0 || !tight_bounds)){ untested();
1971 error(bWARNING,"someting wrong with bounds in %s, %LE, %LE, %LE\n", dd->long_label().c_str(),
1972 E_low, E, E_high);
1975 if(E > E_high && E!=1){
1976 // this is due to double <=> long double discrepancy
1977 trace1("MODEL_IN_RCD_EXP::", tight_bounds);
1978 error( bNOERROR, "%s: Sanitycheck failed ( %LE =E > E_high=%LE ) del %LE\n",
1979 dd->long_label().c_str(),
1980 E, E_high, E_high-E);
1983 _c->set_tr_noise(0); //(double)E_high-(double)E_low);
1984 _c->set_tr((double)uin_eff);
1985 if (CKT_BASE::_sim->tt_iteration_number()>1) {
1986 if ((_c->tr()-_c->tr1())*(_c->tr1()-_c->tr2())<=0) {
1987 _c->set_new_order(1);
1991 trace2("MODEL_BUILT_IN_RCD_EXP::do_tr_stress_last done", _c->get_tr_noise(), uin_eff);
1992 assert(is_number(uin_eff));
1994 if ( uin_eff - _c->tr_lo < -1e-20 || _c->tr_hi - uin_eff < -1e-20 ){
1995 unreachable();
1998 /*--------------------------------------------------------------------------*/
1999 long double MODEL_BUILT_IN_RCD::__uin_iter(long double& s, double E_old, long double E_in,
2000 double bound_lo, double bound_hi, const COMPONENT* dd ) const
2001 { untested();
2002 assert(0); //dead code;
2003 long double E = (long double) E_in;
2004 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(dd->common());
2005 const COMMON_BUILT_IN_RCD* cc = c;
2006 const MODEL_BUILT_IN_RCD* m = dynamic_cast<const MODEL_BUILT_IN_RCD*>(c->model());
2007 const DEV_BUILT_IN_RCD* d = prechecked_cast<const DEV_BUILT_IN_RCD*>(dd);
2008 trace5("COMMON_BUILT_IN_RCD::__uin_iter: ", s, E_old, E, E-E_old, CKT_BASE::_sim->last_time() );
2009 assert (E<1.000001);
2011 if (E>1) { untested();
2012 trace0("COMMON_BUILT_IN_RCD::__uin_iter aligned E");
2013 E = 1;
2015 double h = BASE_SUBCKT::_sim->last_time();
2017 long double Euin = 0;
2018 long double Euin_alt = 0;
2019 if (E < 0.) { untested();
2020 E = 0.;
2021 }else{
2023 // E = max(E,0.0);
2024 //if(E<1e-12) return 0;
2026 assert(( -1 < E ) && (E < 2) ) ;
2028 long double res=1; // dx
2029 long double deltaE =1; // df
2030 long double deltaE_alt = 0; // dfold
2031 long double damp=1;
2032 long double fu =1; // function we try to find zero of, at u
2033 long double cres; // cut res
2034 long double dx_res=1;
2035 unsigned i=0;
2036 int hhack=0;
2037 long double Edu=0;
2039 double ustart = (double) s;
2040 bool B=true;
2042 assert(s>=-0.001 || !cc->positive);
2043 Euin = m->__step( s, E_old, h, c );
2044 if(!is_number(Euin)) { untested();
2045 error( bDANGER, "COMMON_BUILT_IN_RCD::__uin_iter pl cannot evaluate E "
2046 "at s=%LE (E_old=%E) %i\n", s, E_old, CKT_BASE::_sim->tt_iteration_number());
2047 assert(false);
2049 unsigned iterlimit=50;
2050 if (!_sim->tt_iteration_number()){ untested();
2051 iterlimit = 500;
2054 double Esign;
2055 bool S=false;
2057 // fixme: collect min_{f positive}(s) and max_{f negative}(s)
2058 while( !S || B ) { untested();
2059 i++;
2060 trace7("COMMON_BUILT_IN _RCD::__uin_iter loop", (double)s, (double)res, (double)deltaE, Edu, E, i,Euin);
2061 if( i >= iterlimit ){ untested();
2062 d->_iter_newton = i;
2063 error( bDANGER, "newton does not converge after %u in [%f,%f]: %s in tt %i, s %f", i, dd->long_label().c_str(), bound_lo, bound_hi,_sim->tt_iteration_number(), (double)s );
2064 throw(Exception("does not converge after %u in [%f,%f]: %s in tt %i", i, dd->long_label().c_str(), bound_lo, bound_hi,_sim->tt_iteration_number() ));
2066 if(!is_number(s)){ untested();
2067 error( bDANGER, "COMMON_BUILT_IN_RCD::__uin_iter s wrong %E diff "
2068 "%E loking for %E \n", Euin, Edu, E );
2069 assert(false);
2070 return( inf );
2072 Edu = m->__dstepds(s, E_old, c); // ??
2073 if(!is_number(Edu) ){ untested();
2074 untested();
2075 error( bDANGER, "COMMON_BUILT_IN_RCD::__uin_iter step %i:%i Edu nan at %LE Euin=%LE C=%LE diff "
2076 "%LE looking for %E, start %E res %LE\n", CKT_BASE::_sim->tt_iteration_number(),i,
2077 s, Euin, 1-Euin, Edu, E, ustart, res );
2078 // assert(false);
2079 if (i==1) { untested();
2080 // first iteration no reliable res
2081 trace2("Guessing the nan reason",Euin,s);
2082 if ( Euin >= 0.5 )
2083 { untested();
2084 s = s/2; // Guess: s probably much too large
2085 } else { untested();
2086 s = s*2; //
2088 } else { // next iterations, try half step size
2089 res /= 2.0;
2090 s += res;
2091 s = std::max(s,0.0L);
2092 untested();
2093 hhack++;
2095 continue;
2097 assert(Edu>=0);
2098 if((Edu==0 || fabs(Edu) < 1E-150 ) ){ untested();
2099 untested();
2100 // error( bDANGER, "COMMON_BUILT_IN_RCD::__uin_iter step %i:%i Edu 0 at %LE Euin=%LE C=%LE diff "
2101 // "%LE looking for %LE, start %E res %LE\n", CKT_BASE::_sim->tt_iteration_number(),i,
2102 // s, Euin, 1-Euin, Edu, E, ustart, res );
2103 trace0("COMMON_BUILT_IN_RCD::__uin_iter Edu 0");
2104 // assert(false);
2105 Edu=1;
2107 assert (is_number (Euin));
2108 assert (is_number (Edu));
2109 fu = Euin-E;
2110 res = damp*fu/Edu; // dx, Das ist die Differenz in x also: delta x
2112 if(!is_number(res) && fabs(Edu) < 1E-150 ) { untested();
2113 untested();
2114 trace2("COMMON_BUILT_IN_RCD::__uin_iter",res, Edu);
2115 Edu=Edu*1E10;
2116 res = fu/Edu;
2119 assert(is_number(res));
2121 cres= std::min( 1.L,res);
2122 cres= std::max(-1.L,res);
2124 dx_res = s;
2125 double uin1 = double(s);
2126 s -= cres;
2127 bool edge = false;
2128 if(( (double) s > bound_hi )){ untested();
2129 edge = true;
2130 s = bound_hi;
2131 }else if(( (double) s < bound_lo )){ untested();
2132 edge = true;
2133 s = bound_lo;
2135 USE(edge);
2137 assert(is_number(s));
2138 if( (s<-0.0000) && cc->positive ) { untested();
2139 untested();
2140 trace1( "COMMON_BUILT_IN_RCD::__uin_iter neg s ", s );
2141 cres = s;
2142 s = .00;
2144 dx_res -= s; // Effektives dx da es durch Numerik kaputt gehen kann
2147 assert(s>=-0.001 || !cc->positive);
2148 Euin = m->__step( s, E_old, h, c );
2149 deltaE_alt = deltaE;
2150 deltaE = Euin - Euin_alt; // Effektive Veraenderung
2151 if (deltaE > 0) Esign=1; else Esign=-1;
2152 Euin_alt = Euin;
2154 // monotony check.
2155 if(Esign*cres > 0 ){ untested();
2156 d->_iter_newton = i;
2157 throw(Exception("monotony violation"));
2160 if(deltaE * deltaE_alt < 0){ untested();
2161 damp *= 0.8;
2162 S = true;
2163 } else { untested();
2164 S = 0;
2165 damp *= 1.2;
2168 damp=max(damp,0.01L);
2169 //damp=min(damp,5.L);
2172 if( !is_number( Euin ) ){ untested();
2173 error( bDANGER, "COMMON_BUILT_IN_RCD::__uin_iter cannot evaluate E "
2174 "at s=%LE (E_old=%E) %i:%i\n", s, E_old, CKT_BASE::_sim->tt_iteration_number(), i);
2175 assert(is_number(Euin)); break;
2178 // FIXME: use bounds to zero step and break.
2179 if (Euin > E && s==0 && cc->positive ){ untested();
2180 break;
2183 //double reltol = pow(OPT::reltol,1.2);
2184 //double abstol = OPT::abstol/10.0;
2186 B = conchk(double(s),uin1);
2188 d->_iter_newton=i;
2190 assert(s>=-0.001 || !cc->positive);
2191 return s;
2193 /*-------------------------------------------------------------------------------*/
2194 TIME_PAIR DEV_BUILT_IN_RCD::tt_review()
2196 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
2197 assert(c);
2199 if (_sim->_Time0<=0) {
2200 return TIME_PAIR(_sim->_dT0, NEVER);
2203 { // move to tt_accept eventually
2204 double ueff_guessed = _Ccgfill->tr(_sim->_Time0);
2205 double ueff_sim = _Ccgfill->tr();
2207 long double E_from_ueff;
2209 if (_Ccgfill->order()==1) {
2210 long double E_sim = _Ccgfill->tt() + c->_zero;
2211 E_from_ueff = extrapolate(&ueff_sim);
2212 assert(is_number(E_sim));
2213 trace5("correct", _sim->_Time0, ueff_guessed, ueff_sim, E_from_ueff, E_sim);
2214 if(OPT::ttcorr){
2215 _Ccgfill->tr() = (ueff_guessed + ueff_sim)*.5;
2216 long double E_new = (E_from_ueff + E_sim)*.5;
2217 double corr = (double) E_new - c->_zero;
2218 trace2("correct replacing", _Ccgfill->tt(), corr);
2219 assert(corr>-.1);
2220 _Ccgfill->tt() = corr;
2222 }else{
2226 double delta = fabs(_Ccgfill->tr1() - _Ccgfill->tr());
2227 double tol = OPT::tttol * (1./14.);
2229 if (_Ccgfill->order()==0) {
2230 /// uuh ooh let simulator decide?
2231 return TIME_PAIR();
2232 } else if (delta) {
2233 error(bNOERROR, "tt step contr" + long_label()
2234 + " old " + ::to_string(_Ccgfill->tr1()) + " new " + ::to_string(_Ccgfill->tr()) + '\n');
2235 double timestep = _sim->_dT0 * tol / delta;
2236 _ttgain = timestep/_sim->_dT0;
2237 _ttfuture = tt_review_check_and_convert(timestep);
2238 return TIME_PAIR(_ttfuture,NEVER);
2239 } else {
2240 return TIME_PAIR();
2243 /*-------------------------------------------------------------------------------*/
2244 TIME_PAIR DEV_BUILT_IN_RCD::tr_review()
2246 q_accept();
2247 return TIME_PAIR();
2249 /*-------------------------------------------------------------------------------*/
2250 void DEV_BUILT_IN_RCD::tt_regress()
2252 _lasts = -inf;
2253 _Ccgfill->tr_hi = -inf;
2254 _Ccgfill->tr_lo = inf;
2256 /*-------------------------------------------------------------------------------*/
2257 void DEV_BUILT_IN_RCD::tt_advance()
2259 trace1("DEV_BUILT_IN_RCD::tt_advance", _n[n_p].tt());
2261 // hmmm
2262 const COMMON_BUILT_IN_RCD* c = prechecked_cast<const COMMON_BUILT_IN_RCD*>(common());
2263 USE(c);
2264 assert(c->_zero); // 0 is very unlikely...
2266 // _tr_fill = _Ccgfill->tt() + c->_zero; // tt is not valid (should be?!)
2267 // assert(is_number(_tr_fill));
2269 // tr_begin();?
2270 _lasts = -inf;
2271 _Ccgfill->tr_hi = -inf;
2272 _Ccgfill->tr_lo = inf;
2273 // q_eval();
2275 /*--------------------------------------------------------------------------*/
2276 #define T long double
2277 template<>
2278 T DEV_BUILT_IN_RCD::__uin_iter<T>(T& uin, T E_old, T E_in, double bound_lo, double bound_hi) const
2280 const DEV_BUILT_IN_RCD* d = this;
2281 const COMMON_COMPONENT* cc = common();
2282 const MODEL_BUILT_IN_RCD* m = dynamic_cast<const MODEL_BUILT_IN_RCD*>(cc->model()); USE(m);
2283 assert(d);
2285 long double res;
2286 d->_iter_newton = 0;
2287 d->_iter_bisect = 0;
2289 try{
2290 //res = m->__uin_iter( uin, (double) E_old, E_in, bound_lo, bound_hi, this );
2291 res = d->seff_bisect( uin, E_old, E_in, bound_lo, bound_hi);
2293 } catch( Exception e ){ untested();
2294 assert(uin<=bound_hi);
2295 assert(uin>=bound_lo);
2296 res = seff_bisect( uin, E_old, E_in, bound_lo, bound_hi);
2299 return res;
2301 /*--------------------------------------------------------------------------*/
2302 template<>
2303 T DEV_BUILT_IN_RCD::seff_bisect<T>(T& uin, T E_old, T E_in, double bound_lo, double bound_hi) const
2305 assert(bound_lo<=bound_hi);
2306 assert(bound_hi>=double(uin));
2307 assert(bound_lo<=double(uin));
2308 const COMMON_COMPONENT* cc = common();
2309 const MODEL_BUILT_IN_RCD* m = prechecked_cast<const MODEL_BUILT_IN_RCD*>(cc->model());
2310 bool converged = false;
2311 const DEV_BUILT_IN_RCD* d = this;
2313 double dT = BASE_SUBCKT::_sim->last_time();
2314 trace5("bisect", long_label(), dT, E_old, bound_hi, bound_lo);
2316 if(bound_lo==bound_hi){
2317 return uin;
2320 T hi = bound_hi;
2321 T lo = bound_lo;
2322 assert(hi>lo);
2324 T middle = (hi + lo)/2;
2325 T E_m = m->__step( middle, (long double)E_old, dT, cc );
2326 #ifndef NDEBUG
2327 #ifdef DO_TRACE
2328 T Euin_hi = m->__step( hi, (long double)E_old, dT, cc );
2329 T Euin_lo = m->__step( lo, (long double)E_old, dT, cc );
2330 USE(Euin_hi);
2331 USE(Euin_lo);
2333 if(Euin_hi < E_in){ untested();
2335 if(Euin_lo > E_in){ untested();
2337 #endif
2338 #endif
2340 unsigned iter = 0;
2341 double tolex = 5.;
2342 while(!converged){
2344 if (iter++>1000) { untested();
2345 cerr<<converged<<"\n";
2346 error(bDANGER, "seff_bisect fail %s, %E, %E, %E, %E, %E\n", d->long_label().c_str(),
2347 double(lo), double(middle), double(hi), std::abs(double(hi)-double(lo)),
2348 pow(OPT::abstol, 1.) );
2349 break;
2351 assert(hi>=lo);
2353 if (E_in < E_m) {
2354 hi = middle;
2355 } else if (E_m <= E_in) {
2356 lo = middle;
2357 }else{ untested();
2358 unreachable();
2361 converged = conchk(hi,lo, pow(OPT::abstol, 1.),
2362 pow(OPT::reltol, tolex));
2363 T oldmiddle = middle;
2364 middle = (hi + lo)/2.;
2365 T E_m1 = E_m;
2366 E_m = m->__step( middle, E_old, dT, cc);
2367 if((oldmiddle-middle)*(E_m1-E_m) < 0){
2368 error(bWARNING,"%s: bisect monotony violation at %f, delta %f\n",
2369 d->long_label().c_str(),
2370 (double)middle, double(oldmiddle-middle));
2371 break;
2374 trace5("bisect done ", long_label(), E_old, E_m, dT, middle);
2375 d->_iter_bisect = iter;
2376 return middle;
2378 #undef T
2379 /*-------------------------------------------------------------------------------*/
2380 MODEL_BUILT_IN_RCD_NET::MODEL_BUILT_IN_RCD_NET(const BASE_SUBCKT* p)
2381 : MODEL_BUILT_IN_RCD(p){ }
2382 /*-------------------------------------------------------------------------------*/
2383 MODEL_BUILT_IN_RCD_NET::MODEL_BUILT_IN_RCD_NET(const MODEL_BUILT_IN_RCD_NET& p)
2384 : MODEL_BUILT_IN_RCD(p){ }
2385 /*-------------------------------------------------------------------------------*/
2386 /*-------------------------------------------------------------------------------*/