1 /* $Id: d_rcd.cc,v 1.9 2010-09-07 07:46:21 felix Exp $ -*- C++ -*-
6 * (c) 2010 Felix Salfelder
17 #include "u_nodemap.h"
24 /*--------------------------------------------------------------------------*/
25 const double _default_value (1); //input scale.
26 /*--------------------------------------------------------------------------*/
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
));
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
));
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
)
67 /*--------------------------------------------------------------------------*/
68 TDP_BUILT_IN_RCD::TDP_BUILT_IN_RCD(const DEV_BUILT_IN_RCD
*)
71 /*--------------------------------------------------------------------------*/
72 MODEL_BUILT_IN_RCD::MODEL_BUILT_IN_RCD(const BASE_SUBCKT
* p
)
85 if (ENV::run_mode
!= rPRE_MAIN
) {
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
)
106 modelparm(p
.modelparm
),
109 if (ENV::run_mode
!= rPRE_MAIN
) {
114 /*--------------------------------------------------------------------------*/
115 double MODEL_BUILT_IN_RCD::P(const COMPONENT
* ) const
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
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
));
131 /*--------------------------------------------------------------------------*/
132 double MODEL_BUILT_IN_RCD::__Re(double , const COMMON_COMPONENT
* cc
)const
134 const COMMON_BUILT_IN_RCD
* c
= prechecked_cast
<const COMMON_BUILT_IN_RCD
*>(cc
);
137 // return c->__Re(uin);
139 /*--------------------------------------------------------------------------*/
140 double MODEL_BUILT_IN_RCD::__Ge(double, const COMMON_COMPONENT
* )const { untested();
143 /*--------------------------------------------------------------------------*/
144 std::string
MODEL_BUILT_IN_RCD_NET::dev_type()const
148 /*--------------------------------------------------------------------------*/
149 std::string
MODEL_BUILT_IN_RCD::dev_type()const
152 if (dummy
== true) { untested();
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
)
162 if (Umatch(new_type
, "rcdmodel ")) { 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();
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
199 if (COMMON_BUILT_IN_RCD
* cc
= dynamic_cast<COMMON_BUILT_IN_RCD
*>(c
)) {
206 return new SDP_BUILT_IN_RCD(c
);
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
)
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";
257 case 6: return "flags";
258 case 7: return "uref";
259 case 8: return "modelparm";
260 case 9: return "norm_uin";
264 /*--------------------------------------------------------------------------*/
265 std::string
MODEL_BUILT_IN_RCD::param_name(int i
, int j
)const
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();
273 case 9: return "pos";
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();
297 /*--------------------------------------------------------------------------*/
298 void MODEL_BUILT_IN_RCD::do_precalc_last(COMMON_COMPONENT
* ccc
, const CARD_LIST
* )const
300 COMMON_BUILT_IN_RCD
* cc
= dynamic_cast<COMMON_BUILT_IN_RCD
*>(ccc
);
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
;
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
;
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
343 return MODEL_CARD::is_valid(d
);
345 /*--------------------------------------------------------------------------*/
346 void MODEL_BUILT_IN_RCD::tr_eval(COMPONENT
*)const
349 /*--------------------------------------------------------------------------*/
350 /*--------------------------------------------------------------------------*/
351 /*--------------------------------------------------------------------------*/
352 COMMON_BUILT_IN_RCD::COMMON_BUILT_IN_RCD(int c
)
353 :COMMON_COMPONENT(c
),
364 dummy_capture(false),
369 trace1("COMMON_BUILT_IN_RCD::COMMON_BUILT_IN_RCD", (double) Uref
);
372 /*--------------------------------------------------------------------------*/
373 COMMON_BUILT_IN_RCD::COMMON_BUILT_IN_RCD(const COMMON_BUILT_IN_RCD
& p
)
374 :COMMON_COMPONENT(p
),
377 Recommon0(p
.Recommon0
),
378 Recommon1(p
.Recommon1
),
379 Rccommon0(p
.Rccommon0
),
380 Rccommon1(p
.Rccommon1
),
381 positive(p
.positive
),
385 dummy_capture(p
.dummy_capture
),
386 dummy_emit(p
.dummy_emit
),
388 cj_adjusted(p
.cj_adjusted
)
390 trace1("COMMON_BUILT_IN_RCD::COMMON_BUILT_IN_RCD(copy)", (double) Uref
);
393 /*--------------------------------------------------------------------------*/
394 COMMON_BUILT_IN_RCD::~COMMON_BUILT_IN_RCD()
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
);
405 && weight
== p
->weight
406 && Rccommon1
== p
->Rccommon1
407 && Rccommon0
== p
->Rccommon0
408 && Recommon1
== p
->Recommon1
409 && Recommon0
== p
->Recommon0
410 && positive
== p
->positive
413 && lambda
== p
->lambda
414 && dummy_capture
== p
->dummy_capture
415 && dummy_emit
== p
->dummy_emit
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 ")) {
468 } else if (Umatch (Name
,"re1 ")) {
470 } else if (Umatch (Name
,"re0 ")) {
472 } else if (Umatch (Name
,"rc1 ")) {
474 } else if (Umatch (Name
,"rc0 ")) {
476 } else if (Umatch (Name
,"pos{itive}")) {
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";
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
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();
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
);
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");
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
);
564 _sdp
= m
->new_sdp(this);
566 const SDP_BUILT_IN_RCD
* s
= prechecked_cast
<const SDP_BUILT_IN_RCD
*>(_sdp
);
569 // subcircuit commons, recursive
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
);
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
);
597 /*--------------------------------------------------------------------------*/
598 void COMMON_BUILT_IN_RCD::precalc_last(const CARD_LIST
* 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());
607 // final adjust: code_pre
608 trace2("COMMON_BUILT_IN_RCD::precalc_last", m
->v2(), m
->uref
);
609 // final adjust: override
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
);
630 trace2("", positive
, (bool)positive
);
632 e_val(&(this->dummy_emit
), false, par_scope
);
634 // final adjust: calculated
640 if((double)Uref
== NOT_INPUT
) {
641 trace2("nin", m
->uref
, NOT_INPUT
);
644 if((double)Uref
== NA
) {
651 _sdp
= m
->new_sdp(this);
653 const SDP_BUILT_IN_RCD
* s
= prechecked_cast
<const SDP_BUILT_IN_RCD
*>(_sdp
);
656 // subcircuit commons, recursive
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
;
670 if(Rccommon1
!= NA
&& Rccommon1
!= NOT_INPUT
) _Rc1
= Rccommon1
;
674 assert (weight
!= 0);
675 trace5("COMMON_BUILT_IN_RCD::precalc_last no uref. simple model", _Re0
, _Rc0
, _Rc1
, Re(1), Rc(0));
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
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
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 );
722 /*--------------------------------------------------------------------------*/
723 static EVAL_BUILT_IN_RCD_GRc
Eval_GRc(CC_STATIC
);
724 void EVAL_BUILT_IN_RCD_GRc::tr_eval(ELEMENT
* d
)const
727 DEV_BUILT_IN_RCD
* p
= prechecked_cast
<DEV_BUILT_IN_RCD
*>(d
->owner());
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());
732 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(cc
->model());
735 // FIXME: merge with __Rc somehow
736 double _c
[3] = { cc
->_Rc0
, cc
->_Rc1
* cc
->_lambda
, 0 };
737 double x
= (d
->_y
[0].x
);
741 for (size_t i
=1; i
>0; --i
) { untested();
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()
756 // calculated parameters,
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;
783 /*--------------------------------------------------------------------------*/
784 DEV_BUILT_IN_RCD::DEV_BUILT_IN_RCD(const DEV_BUILT_IN_RCD
& p
)
787 // calculated parameters,
797 _tr_fill(p
._tr_fill
),
798 _tr_dfill(p
._tr_dfill
),
803 assert(p
._n
[n_p
].is_adp());
804 for (uint_t ii
= 0; ii
< max_nodes() + int_nodes(); ++ii
) {
806 trace2("DEV_BUILT_IN_RCD::DEV_BUILT_IN_RCD(p)", ii
, _n
[ii
].is_adp());
808 assert(_n
[n_p
].is_adp());
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
820 const COMMON_BUILT_IN_RCD
* c
= static_cast<const COMMON_BUILT_IN_RCD
*>(common());
823 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(c
->model());
826 const SDP_BUILT_IN_RCD
* s
= prechecked_cast
<const SDP_BUILT_IN_RCD
*>(c
->sdp());
833 if (_sim
->is_first_expand()) {
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_()));
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
853 // _Udc = new ADP_NODE_UDC((const COMPONENT*) common()); //, _Ccgfill);
854 // ADP_NODE_LIST::adp_node_list.push_back( _Udc );
858 //subckt()->precalc();
859 assert(!is_constant());
860 if ( adp() == NULL
){
861 // attach_adp( m->new_adp( (COMPONENT*) this ) );
863 untested(); // rebuild circuit??
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());
877 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(c
->model());
880 /*--------------------------------------------------------------------------*/
881 double DEV_BUILT_IN_RCD::tr_probe_num(const std::string
& x
)const
884 const COMMON_BUILT_IN_RCD
* c
= prechecked_cast
<const COMMON_BUILT_IN_RCD
*>(common());
886 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(c
->model());
888 const SDP_BUILT_IN_RCD
* s
= prechecked_cast
<const SDP_BUILT_IN_RCD
*>(c
->sdp());
890 ADP_NODE
* Ccgfill
= _n
[n_p
].a_();
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);
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();
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 " )) {
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();
948 }else if (Umatch(x
, "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
;
959 }else if (Umatch(x
, "chp ")) {
961 }else if (Umatch(x
, "m{atrix} ")) {
962 return _Ccgfill
->m_();
963 }else if (Umatch(x
, "v{alue} ")) {
966 }else if (Umatch(x
, "wt ")) { untested();
968 }else if (Umatch(x
, "status ")) { untested();
969 return static_cast<double>(converged() * 2);
970 }else if (Umatch(x
, "_region ")) { untested();
974 return BASE_SUBCKT::tr_probe_num(x
);
976 /*--------------------------------------------------------------------------*/
977 double DEV_BUILT_IN_RCD::tt_probe_num(const std::string
& x
)const
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());
983 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(cc
->model());
985 const SDP_BUILT_IN_RCD
* s
= prechecked_cast
<const SDP_BUILT_IN_RCD
*>(cc
->sdp());
987 ADP_NODE
* Ccgfill
= _n
[n_p
].a_();
990 if (Umatch(x
, "P ")) {
992 } else if (Umatch(x
, "vc ")) { untested();
993 // return _Ccgfill->tt();
995 assert(is_number( ( 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();
1006 } else if (Umatch(x
, "ttf{uture} ")) { itested();
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();
1014 } else if (Umatch(x
, "s{tresslevel} ")) {
1015 return Ccgfill
->tr();
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
); }
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();
1040 return( m
->__Re(cc
->Uref
,cc
));
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 /*--------------------------------------------------------------------------*/
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
* )
1061 /*--------------------------------------------------------------------------*/
1062 region_t
MODEL_BUILT_IN_RCD::region( const COMPONENT
* )const
1066 /*--------------------------------------------------------------------------*/
1067 /*--------------------------------------------------------------------------*/
1068 int MODEL_BUILT_IN_RCD::tt_region( const COMPONENT
* )const
1072 /*--------------------------------------------------------------------------*/
1073 region_t
DEV_BUILT_IN_RCD::region( )const
1077 /*--------------------------------------------------------------------------*/
1078 int DEV_BUILT_IN_RCD::tt_region( )const
1082 /*--------------------------------------------------------------------------*/
1083 void MODEL_BUILT_IN_RCD::tt_eval(COMPONENT
* )const
1087 /*--------------------------------------------------------------------------*/
1088 void MODEL_BUILT_IN_RCD::do_tt_prepare(COMPONENT
*)const
1091 ///*--------------------------------------------------------------------------*/
1092 ADP_CARD
* MODEL_BUILT_IN_RCD::new_adp( COMPONENT
* c
)const
1094 trace0("MODEL_BUILT_IN_RCD::new_adp");
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);
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);
1114 if(cc
->positive
&& s
<0) {
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
);
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 ) ) );
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
;
1144 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(c
->model());
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();
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
);
1171 assert(is_number(eff2
));
1174 eff1
= max(eff1
,0.0L);
1175 eff2
= max(eff2
,0.0L);
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);
1187 }else if (fill_new
<0) {
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()
1203 const COMMON_BUILT_IN_RCD
* c
= static_cast<const COMMON_BUILT_IN_RCD
*>(common());
1206 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(c
->model());
1209 const SDP_BUILT_IN_RCD
* s
= prechecked_cast
<const SDP_BUILT_IN_RCD
*>(c
->sdp());
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?
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();
1231 _nodes
[n_p
].a_()->trhack
= (double) _tr_dfill
;
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());
1253 long double E_old
= _Ccgfill
->tt1() + c
->_zero
; // shifted
1254 assert(E_old
<=1+1e-9);
1255 if (E_old
>1.) { untested();
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);
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
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());
1297 ADP_NODE
* a
= _n
[n_p
].a_();
1298 set_not_converged();
1300 double stress
= involts() * value();
1302 double _dt
= _sim
->_time0
- _time1
;
1303 if(_dt
< 0){ unreachable();
1304 // BUG in tr_begin?. tt_advance?. should not be here
1307 _time0
= _sim
->_time0
;
1308 long double newtrhack
;
1311 trace3("??", _dt
, stress
, long_label());
1312 newtrhack
= m
->__step( stress
, a
->tt() + _tr_dfill
+ c
->_zero
, _dt
, c
) - c
->_zero
;
1315 newtrhack
= a
->tt() + _tr_dfill
;
1317 trace7("tradv",_sim
->_time0
, a
->trhack
, newtrhack
, _dt
, stress
, a
->tt(), _tr_dfill
);
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());
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
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()
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());
1354 _stressiter
= _sim
->iteration_tag();
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
;
1365 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(c
->model());
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());
1378 } else if ( stress
< 0 && cc
->positive
) {
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
;
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
);
1396 throw(Exception("time mismatch in %s: time0: %E lasts: %E " , long_label().c_str(), _sim
->_time0
, _lasts
));
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());
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();
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
);
1437 if (!h
) { untested();
1438 trace1("not h\n", _tr_fill
);
1441 if(_sim
->phase()==p_PD
){
1442 assert(!_c
->tr_lo
); USE(_c
);
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();
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
));
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() );
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
);
1487 //double fill = _n[n_ic].v0();
1488 assert (fill
==fill
);
1491 long double newfill
;
1492 switch(_sim
->_stepno
){ incomplete();
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();
1504 } else if(newfill
> 1.000001){ untested();
1505 error(bDANGER
, ("* RCD_V3 %f too big\n" + long_label() ).c_str() , newfill
);
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);
1514 assert(is_number(_tr_fill
));
1515 assert(_tr_dfill
<1.1);
1516 assert(_tr_fill
<=1.);
1517 assert(_tr_dfill
>-1.1);
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.);
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
);
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());
1550 const COMMON_BUILT_IN_RCD
* c
= static_cast<const COMMON_BUILT_IN_RCD
*>(common());
1553 const MODEL_BUILT_IN_RCD
* m
= prechecked_cast
<const MODEL_BUILT_IN_RCD
*>(c
->model());
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
){
1567 trace2("", a
->tr_lo
, a
->tr_hi
);
1568 // assert( a->tr_lo <= a->tr_hi );
1570 error(bTRACE
, "at %f: something wrong with _tr_fill in %s\n", _sim
->_Time0
, long_label().c_str());
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()));
1581 // calculate udc (will be put into _c->tr() ? )
1582 m
->do_tr_stress_last(_tr_fill
,_Ccgfill
, this);
1584 } catch (Exception
&e
) { untested();
1585 error(bDANGER
, "%s\n", long_label().c_str());
1588 assert(is_number(_tr_fill
));
1590 if( _sim
->phase()==p_PD
){
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?
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);
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
){
1630 /*--------------------------------------------------------------------------*/
1631 void DEV_BUILT_IN_RCD::tt_begin()
1636 ADP_NODE
* a
= _n
[n_p
].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
) {
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();
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);
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_();
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();
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()
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());
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();
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();
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
);
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)
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
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
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();
1789 if( _c
->tr_hi
- _c
->tr() < -1e-20 ){ untested();
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();
1800 if ( _c
->tr_hi
- _c
->tr() < -1e-20 ){ untested();
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;
1816 uin_low_s
= max(0.L
,uin_low_s
);
1820 uin_high_s
= max(uin_high_s
,uin_low_s
);
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
);
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
) {
1849 long double dE
= (E
-E_low
) / (E_high
-E_low
);
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
));
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
);
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
);
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());
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
);
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) {
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);
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(),
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 ){
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
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");
2015 double h
= BASE_SUBCKT::_sim
->last_time();
2017 long double Euin
= 0;
2018 long double Euin_alt
= 0;
2019 if (E
< 0.) { untested();
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
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;
2039 double ustart
= (double) s
;
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());
2049 unsigned iterlimit
=50;
2050 if (!_sim
->tt_iteration_number()){ untested();
2057 // fixme: collect min_{f positive}(s) and max_{f negative}(s)
2058 while( !S
|| B
) { untested();
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
);
2072 Edu
= m
->__dstepds(s
, E_old
, c
); // ??
2073 if(!is_number(Edu
) ){ 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
);
2079 if (i
==1) { untested();
2080 // first iteration no reliable res
2081 trace2("Guessing the nan reason",Euin
,s
);
2084 s
= s
/2; // Guess: s probably much too large
2085 } else { untested();
2088 } else { // next iterations, try half step size
2091 s
= std::max(s
,0.0L);
2098 if((Edu
==0 || fabs(Edu
) < 1E-150 ) ){ 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");
2107 assert (is_number (Euin
));
2108 assert (is_number (Edu
));
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();
2114 trace2("COMMON_BUILT_IN_RCD::__uin_iter",res
, Edu
);
2119 assert(is_number(res
));
2121 cres
= std::min( 1.L
,res
);
2122 cres
= std::max(-1.L
,res
);
2125 double uin1
= double(s
);
2128 if(( (double) s
> bound_hi
)){ untested();
2131 }else if(( (double) s
< bound_lo
)){ untested();
2137 assert(is_number(s
));
2138 if( (s
<-0.0000) && cc
->positive
) { untested();
2140 trace1( "COMMON_BUILT_IN_RCD::__uin_iter neg s ", s
);
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;
2155 if(Esign
*cres
> 0 ){ untested();
2156 d
->_iter_newton
= i
;
2157 throw(Exception("monotony violation"));
2160 if(deltaE
* deltaE_alt
< 0){ untested();
2163 } else { untested();
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();
2183 //double reltol = pow(OPT::reltol,1.2);
2184 //double abstol = OPT::abstol/10.0;
2186 B
= conchk(double(s
),uin1
);
2190 assert(s
>=-0.001 || !cc
->positive
);
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());
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
);
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
);
2220 _Ccgfill
->tt() = corr
;
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?
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
);
2243 /*-------------------------------------------------------------------------------*/
2244 TIME_PAIR
DEV_BUILT_IN_RCD::tr_review()
2249 /*-------------------------------------------------------------------------------*/
2250 void DEV_BUILT_IN_RCD::tt_regress()
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());
2262 const COMMON_BUILT_IN_RCD
* c
= prechecked_cast
<const COMMON_BUILT_IN_RCD
*>(common());
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));
2271 _Ccgfill
->tr_hi
= -inf
;
2272 _Ccgfill
->tr_lo
= inf
;
2275 /*--------------------------------------------------------------------------*/
2276 #define T long double
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
);
2286 d
->_iter_newton
= 0;
2287 d
->_iter_bisect
= 0;
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
);
2301 /*--------------------------------------------------------------------------*/
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
){
2324 T middle
= (hi
+ lo
)/2;
2325 T E_m
= m
->__step( middle
, (long double)E_old
, dT
, cc
);
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
);
2333 if(Euin_hi
< E_in
){ untested();
2335 if(Euin_lo
> E_in
){ untested();
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.) );
2355 } else if (E_m
<= E_in
) {
2361 converged
= conchk(hi
,lo
, pow(OPT::abstol
, 1.),
2362 pow(OPT::reltol
, tolex
));
2363 T oldmiddle
= middle
;
2364 middle
= (hi
+ lo
)/2.;
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
));
2374 trace5("bisect done ", long_label(), E_old
, E_m
, dT
, middle
);
2375 d
->_iter_bisect
= iter
;
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 /*-------------------------------------------------------------------------------*/