interactive testing
[gnucap-felix.git] / src / s_ttt.cc
blob191a2bc9197b04d319a28ff837a1fee70bc04a1d
1 /* -*- C++ -*-
2 * Copyright (C) 2010-2012
3 * Author: Felix Salfelder
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 53 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *------------------------------------------------------------------
22 * performs tt analysis
25 * do this in a loop:
27 * - set T, dT
28 * - tt_begin/tt_continue
29 * - tt_advance / regress
30 * - do_tt
31 * - TR::sweep (calls tr_accept)
32 * - tr_stress_last
33 * - tt_review
34 * - tt_accept (if queued?)
37 #include "declare.h" /* plclose, plclear, fft */
38 #include "u_prblst.h"
39 #include "s_tr.h"
40 #include "u_nodemap.h"
41 #include "e_node.h"
42 #include "u_sim_data.h"
43 #include "s__.h"
44 #include "u_status.h"
45 #include "u_function.h" // after?
46 #include "m_wave.h"
47 #include "u_prblst.h"
48 #include "ap.h"
49 #include "s_tt.h"
52 // #include "globals.h" ??
53 #include "e_adp.h"
54 #include "e_adplist.h"
55 using namespace std;
56 /*--------------------------------------------------------------------------*/
57 #define sanitycheck() assert ( is_almost( _sim->_Time0 , _Time1 + _sim->_dT0 ));\
58 assert ( _sim->_Time0 > _Time1 || _sim->tt_iteration_number()==0 );\
59 assert ( _sim->_dT0 == 0 || _sim->tt_iteration_number()!=0 );
60 /*--------------------------------------------------------------------------*/
61 namespace TT { //
62 /*--------------------------------------------------------------------------*/
63 OMSTREAM TTT::mstdout(stdout);
64 /*--------------------------------------------------------------------------*/
65 /*--------------------------------------------------------------------------*/
66 #define check_consistency_tt() { \
67 trace4("", __LINE__, newTime, almost_fixed_Time, fixed_Time); \
68 assert(almost_fixed_Time <= fixed_Time); \
69 assert(newTime <= fixed_Time); \
70 /*assert(newTime == fixed_Time || newTime <= fixed_Time -_dTmin);*/ \
71 assert(newTime <= almost_fixed_Time); \
72 /*assert(newTime == almost_fixed_Time || newTime <= almost_fixed_Time - _dTmin);*/ \
73 assert(newTime > _Time1); \
74 assert(newTime > refTime); \
75 assert(new_dT > 0.); \
76 assert(new_dT >= _dTmin); \
77 assert(newTime <= _Time_by_user_request); \
78 /*assert(newTime == _Time_by_user_request*/ \
79 /* || newTime < _Time_by_user_request - _dTmin); */ \
81 /*--------------------------------------------------------------------------*/
82 int TTT::step_cause()const
84 return ::status.control/100;
86 /*--------------------------------------------------------------------------*/
87 double behaviour_time()
88 { untested();
89 return 80000;
91 /*--------------------------------------------------------------------------*/
92 void TTT::set_step_cause(STEP_CAUSE C)
94 switch (C) { //
95 case scITER_A:untested();
96 case scADT:untested();
97 case scITER_R:
98 case scINITIAL:
99 case scSKIP:
100 case scTE:
101 case scAMBEVENT:
102 case scEVENTQ:
103 case scUSER:
104 case scGROW:
105 case scLAST:
106 ::status.control = 100*C;
107 break;
108 case scNO_ADVANCE: untested();
109 case scZERO: untested();
110 case scSMALL:
111 case scREJECT:
112 ::status.control += 100*C;
113 break;
116 /*--------------------------------------------------------------------------*/
117 double TTT::get_new_dT()
118 { untested();
119 double factor= (double) steps_total();
120 double buf= 100 / CKT_BASE::tt_behaviour_rel * factor;
121 return buf;
123 /*--------------------------------------------------------------------------*/
124 void TTT::rescale_behaviour()
125 { untested();
126 incomplete();
128 /*--------------------------------------------------------------------------*/
129 void TTT::first()
131 trace2("TTT::first()", _Time1, _Tstart);
132 _sim->force_tt_order(0);
133 // _sim->zero_voltages();
135 // ADP_NODE_LIST::adp_node_list.do_forall( &ADP_NODE::tt_clear );
137 // _Time1 = 0; BUG! a first after powerdown doesnt start at 0
138 _sim->_dT0 = 0;
139 _sim->_dT1 = 0;
140 _sim->_dT2 = 0;
141 _dT_by_adp = _tstop;
143 if (_sim->_loadq.size()) {
144 trace0("TTT::first loadq nonempty -- clearing");
145 _sim->_loadq.clear() ; // why?
146 } else {
149 // tell gnuplot that we start from the beginning.
150 // TRANSIENT::_out << "* newline hack\n\n";
152 assert(_sim->get_tt_order() == 0 );
154 _Time_by_user_request = _sim->_Time0 = _Tstart;
156 if (_Tstop>0) assert(_Tstep>0);
158 _sim->_tt_accepted = 0;
159 _sim->_tt_rejects = 0;
160 _sim->_tt_rejects_total = 0;
161 // _stepno_tt = 0;
163 assert(_sim->_Time0 >= 0 );
165 advance_Time();
167 _sim->set_command_tt();
169 trace1("TTT::first", _sim->_Time0);
171 if (TRANSIENT::_trace >= tDEBUG) { untested();
172 TRANSIENT::outdata(_sim->_Time0);
173 }else{
174 // outdata(_sim->_Time0);
176 ::status.tran.reset().start();
178 //CARD_LIST::card_list.tr_begin(); ///????
179 trace0("TTT::first sweep");
180 CARD_LIST::card_list.do_tt(); // before sweep_tr
181 // BUG: outdata here maybe
183 print_head_tr(); // always (no review)
184 TTT::sweep_tr();
185 print_foot_tr();
186 trace1("TTT::first sweep done", _sim->_Time0);
187 // assert (_sim->_loadq.empty());
189 ::status.hidden_steps=1;
190 ++steps_total_tt;
191 ::status.review.stop();
193 _sim->set_command_tt();
194 set_step_cause(scUSER);
196 assert(_sim->_Time0 >= 0 );
197 assert( _sim->_mode == s_TTT );
198 _accepted_tt = true;
200 // CARD_LIST::card_list.tt_review();
201 TTT::review();
202 assert(_time_by_ambiguous_event > _sim->_Time0);
203 TTT::accept();
204 outdata_tt(_sim->_Time0); // first.
206 _Time_by_user_request = _sim->_last_Time = _sim->_Time0 + _sim->last_time();
207 _sim->_dT0 = _sim->last_time();
208 _Time1 = _Tstart;
209 } //first
210 /*--------------------------------------------------------------------------*/
211 void TTT::tt_begin()
213 _sim->_dT0 = 0;
214 _sim->_dT1 = 0;
215 _sim->_dT2 = 0;
216 _sim->tr_reset(); // assert _sim->_last_time == 0;?
217 trace0("TTT::tt_begin");
218 _sim->_stepno = 0;
219 _sim->_tt_uic = false;
220 CARD_LIST::card_list.do_forall( &CARD::tt_begin );
221 // advance_time() // must be done, as tt1 is used in do_tt...
222 CARD_LIST::card_list.do_tt();
224 /*--------------------------------------------------------------*/
225 void TTT::tt_cont()
227 // continue from externally set adp_node values...
228 _sim->_dT0 = 0;
229 _sim->_dT1 = 0;
230 _sim->_dT2 = 0;
231 _sim->_time0 = 0;
232 trace0("TTT::cont");
233 _sim->_stepno = 0;
234 _sim->_tt_uic = true;
235 CARD_LIST::card_list.do_forall( &CARD::tt_begin );
236 CARD_LIST::card_list.do_tt();
238 /*--------------------------------------------------------------*/
239 void TTT::do_initial_dc()
241 trace3("TTT::do_initial_dc", _sim->_Time0, _cont, _cont_dc);
242 // set adp_nodes to initial values
243 _sim->set_inc_mode_bad();
244 CARD_LIST::card_list.do_forall( &CARD::tr_begin );
245 _sim->_phase = p_INIT_DC;
246 bool _converged = solve_with_homotopy(OPT::DCBIAS,TRANSIENT::_trace);
247 assert(_converged); USE(_converged); // incomplete(); (why?)
249 // review();
250 _accepted = true;
251 TRANSIENT::accept();
253 trace0("TTT::do_initial_dc done");
254 _sim->keep_voltages();
255 assert(_sim->last_time() == 0.);
256 _sim->set_inc_mode_yes();
257 _sim->_mode = s_TTT;
259 /*--------------------------------------------------------------*/
260 void TTT::power_down(double until)
262 _sim->_phase = p_PD;
263 // do stress apply now, then tt advance and stress_last.
265 _sim->force_tt_order(0);
266 double time = until-_sim->_last_Time;
267 trace2("TTT::power_down... ", _sim->_last_Time, until);
269 /// only if _cont?
271 for(unsigned i=0; i<_sim->_adp_nodes;i++ ){
272 trace2("TTT::power_down... ",i, _sim->_tt[i]);
274 for(unsigned i=0; i<_sim->_adp_nodes;i++ ) {
275 trace2("TTT::power_down... ",i, _sim->_tr[i]);
278 _Time1 = _sim->_last_Time;
279 _sim->_Time0 = _sim->_last_Time;
280 assert(tt_iteration_number() == 0);
281 assert(tt_iteration_number() == 0);
283 _sim->_dT0 = 0;
284 _sim->_dT1 = 0;
285 _sim->_dT2 = 0;
286 _sim->_time0 = 0;
287 _sim->force_tt_order(0); assert(_sim->get_tt_order() == 0 );
288 _time1 = 0.;
290 advance_Time(); // fix last_iter time (dT0==0);
291 assert(!_sim->_dT0);
293 // bug. too early
294 if(_trace>tDEBUG) { untested();
295 outdata_b4(_sim->_Time0);
298 // start at age stored in tt.
299 notstd::copy_n(_sim->_tt, _sim->_adp_nodes, _sim->_tt1);
301 CARD_LIST::card_list.tt_advance();
302 // CARD_LIST::card_list.do_tt(); // why?!
304 for (uint_t ii = 1; ii <= _sim->_total_nodes; ++ii) {
305 _sim->_nstat[_sim->_nm[ii]].set_last_change_time(0);
306 _sim->_nstat[_sim->_nm[ii]].store_old_last_change_time();
307 _sim->_nstat[_sim->_nm[ii]].set_final_time(0);
309 for (unsigned i=0; i<_sim->_adp_nodes; i++) {
310 trace2("TTT::power_down... ",i, _sim->_tr[i]);
313 // NOW do the powerdown.
315 _sim->zero_some_voltages();
317 assert( _sim->_mode == s_TTT );
318 print_results_tt( _sim->_Time0 );
320 trace0("TTT::power_down accept...");
321 CARD_LIST::card_list.tr_accept();
322 CARD_LIST::card_list.tr_stress_last(); // FIXME: merge into tt_review
324 for (unsigned i=0; i<_sim->_adp_nodes; i++) {
325 trace2("TTT::power_down... ",i, _sim->_tr[i]);
328 _sim->_dt0 = 0;
329 _sim->_dT0 = time;
330 _sim->_Time0 = until;
332 advance_Time(); // check: move tr->tr1 correctly...
333 _sim->force_tt_order(0);
335 for(unsigned i=0; i<_sim->_adp_nodes;i++ ) {
336 trace3("TTT::power_down advanced ",i, _sim->_tt[i], hp(_sim->_tt));
338 for(unsigned i=0; i<_sim->_adp_nodes;i++ ) {
339 trace3("TTT::power_down advanced ",i, _sim->_tt1[i], hp(_sim->_tt1));
342 CARD_LIST::card_list.do_tt();
344 trace0("TTT::power_down done");
346 // go on with old voltages (good idea?)
348 _sim->restore_voltages();
350 /*--------------------------------------------------------------------------*/
351 // FIXME:
352 // do a 2nd tt to check aging impact.
353 // ie. take some norm of node-voltage difference over time.
355 // printing (preliminary)
356 // tALL, /* all accepted time steps */
357 // tGUESS , /* show guess, (accepted only) */
358 // tREJECTED , /* show rejected time steps (+ guesses)
359 // tITERATION , /* also show corrector iterations (not yet) */
360 // tVERBOSE , /* show more stuff? */
361 /*--------------------------------------------------------------------------*/
362 static void register_status();
363 /*--------------------------------------------------------------------------*/
364 void TTT::sweep()
366 register_status();
367 assert( _sim->_mode == s_TTT );
368 assert( _sim->_Time0 >= 0 );
369 _sim->_phase = p_NONE;
370 _printed_steps = 0;
371 ::error(bLOG, "TTT sweep cont %d cont_tt %d new %d cont_dc %d\n", _cont, _cont_tt, _new, _cont_dc);
372 ::error(bLOG, "TTT sweep Tstart %f Tstop %f Tstep %f stepmode %d\n",
373 (double)_Tstart, (double)_Tstop, (double)_Tstep, (int)_stepmode);
374 assert(_sim->tt_iteration_number() == 0);
376 // sanitycheck();
377 _sim->_tt_iter = 0;
378 _sim->_tt_done = 0;
380 head_tt(_tstart, _tstop, "TTime");
382 // assert(!_new || !_cont_tt); ??
384 if(_sim->_last_Time == 0. && !_new && !_cont_tt) {
385 _new = 1;
386 } else if (_sim->last_time() != 0. && !_cont_tt) {
387 // _cont_dc = 1;
388 } else {
391 if(_no_act) { untested();
392 _out << "ttt " << string(_Tstart) << " " << string(_Tstop) << " " << string(_Tstep)
393 << " tran " << string(_tstop) << " " << string(_tstrobe) << "\n";
394 _out << "stepmode " << _stepmode << "\n";
395 return;
396 }else{
399 _sim->force_tt_order(0); //hack
401 if (_new) {
402 trace2("TTT::sweep tt_begin", _Tstart, _sim->_phase);
403 _sim->_last_Time = _Tstart;
404 tt_begin();
405 // CARD_LIST::card_list.do_tt(); BUG: not idempotent (?!)
406 set_step_cause(scUSER);
407 assert(_sim->_mode == s_TTT);
408 }else{
409 tt_cont();
412 // bug: _new not correctly processed (?)
414 if (_power_down) {
415 if (_new) {untested();
416 print_results_tt(_sim->_Time0);
418 trace1("TTT::sweep pd until", _Tstop );
419 power_down(_Tstop);
420 print_results_tt(_Tstop);
421 store_results(_Tstop);
422 _sim->_last_Time = _Tstop;
423 trace0("TTT::sweep pd done");
424 return;
425 }else if( _Tstop == _Tstart || double(_Tstop) == 0) {
426 if (_new) {
427 print_results_tt(_sim->_Time0);
429 trace0("TTT::sweep just apply");
430 advance_Time();
431 _sim->_tt_uic = 1;
432 CARD_LIST::card_list.do_tt();
433 _sim->_acceptq.clear();
434 _sim->_tt_uic = 0;
435 return;
436 }else if (_Tstop == _Tstart) { untested();
437 if (_new) {untested();
438 print_results_tt(_sim->_Time0);
440 trace0("TTT::sweep just printing");
441 outdata_b4(_sim->_Time0); // first output tt data
442 return;
443 }else if (!_cont_dc) {
444 if (_new) {
445 print_results_tt(_sim->_Time0);
447 // _cont_dc == skip initial dc
448 trace0("TTT::sweep from 0");
449 // print_head_tr(); // BUG
450 do_initial_dc();
452 // outdata_tt( _sim->_Time0); no.
453 assert( _sim->_mode == s_TTT );
454 trace0("initial done");
455 _cont = true;
457 assert(_sim->_Time0 <= _Tstart);
458 first();
459 trace2("",_Time1,_Tstart);
460 trace3("TTT::sweep first done", _sim->_Time0, _Time1, _Tstart);
461 assert (_Time1 == _Tstart);
462 }else if(_tstop==0. && _tstrobe==0. && (!_cont_tt)) { untested();
463 if (_new) {untested();
464 print_results_tt(_sim->_Time0);
466 print_head_tr();
467 untested();
468 do_initial_dc();
469 return;
470 }else if (_cont_tt) { untested();
471 if (_new) {untested();
472 print_results_tt(_sim->_Time0);
474 trace3("cont tt", _sim->last_Time(), _Tstart, _sim->_Time0);
475 _sim->_Time0 = _sim->last_Time();
476 _Tstart = _sim->last_Time();
477 _sim->_dT0 = 0.;
478 assert(_sim->_Time0 <= _Tstart);
479 first();
480 }else if (_cont_dc) {
481 _sim->restore_voltages();
482 if (_new) {
483 print_results_tt(_sim->_Time0);
485 trace3("tt after tr?", _sim->last_Time(), _sim->last_time(), _sim->last_Time());
486 _sim->_Time0 = _Tstart;
487 _sim->_dT0 = _sim->last_time();
488 //_sim->_dT1 = 0;
489 _Time1 = _Tstart;
490 assert(_sim->_Time0 <= _Tstart);
491 first();
492 } else { untested();
493 error(bDANGER, "tt, unhandled. cont_tt %d cont_dc %d new %d %f %f\n",
494 _cont_tt, _cont_dc, _new, _sim->last_time(), _sim->last_Time());
495 unreachable();
498 // assert (_sim->_loadq.empty());
499 assert(_sim->_Time0 == _Tstart);
501 //_time_by_adp=NEVER;
503 trace2("",_Time1,_Tstart);
504 assert (_Time1 == _Tstart);
505 assert( _sim->_mode == s_TTT );
507 while (next()) {
508 assert(step_cause());
509 assert( _sim->_mode == s_TTT );
510 trace8( "TTT::sweep loop start ", _sim->_Time0, _Time1, _sim->_dT0,
511 _accepted, _accepted_tt, tt_iteration_number(), _sim->_last_Time, _sim->last_time() );
512 assert(_sim->_dT0 >= _sim->last_time());
513 sanitycheck();
515 // _sim->_last_time = _tstop; // UARGH hack, should be implicit...
516 trace2("TTT::sweep CARD::do_tt", _sim->_dT0, _sim->last_time());
517 assert( _sim->_dT0 - _sim->last_time() >= 0);
519 _sim->_time0 = 0.;
520 CARD_LIST::card_list.do_tt(); // before sweep_tr
522 assert( _sim->_mode == s_TTT );
523 if(_trace >= tITERATION ) {
524 outdata_b4(_sim->_Time0);
526 store_results_tt(_sim->_Time0); // first output tt data
527 assert( _sim->_mode == s_TTT );
528 // _sim->_time0 = _sim->last_time(); // time0 does not necessarily correspond to a
529 // // computed step.
530 // assert( _sim->_time0 <= _sim->_dT0);
532 assert(step_cause());
533 TTT::sweep_tr();
534 assert(step_cause());
536 if (!_accepted) { incomplete();
537 assert(_sim->_mode==s_TTT);
538 _accepted_tt = false;
539 } else {
540 _accepted_tt = review();
543 trace4("", _sim->_Time0, _Time_by_user_request, _tstop, step_cause());
544 // assert (_sim->_Time0 <= _Time_by_user_request + _tstop * 1.0001 );
546 if (!_accepted_tt) {
547 error(bDEBUG, "rejected step at %f, want %f, delta %E\n",
548 _sim->_Time0, _Time_by_error_estimate,
549 _sim->_Time0 - _Time_by_error_estimate);
550 _sim->_tt_rejects++;
551 _sim->_tt_rejects_total++;
552 if (_trace >= tDEBUG) { untested();
553 print_stored_results_tt(-_sim->_Time0);
556 if (_trace >= tREJECTED) {
557 TRANSIENT::_out << "#r\n";
558 assert(step_cause());
559 outdata_tt(_sim->_Time0);
560 assert( _sim->_mode == s_TTT );
563 } else {
564 // accepted_tt
565 _sim->_time0 = _sim->last_time(); // time0 does not necessarily correspond to a
566 // computed step.
567 _sim->keep_voltages(); // assume that v0 is still what we want to keep...
568 assert(0.99999* _sim->last_time() <= _tstop);
569 if (_trace == tGUESS) {
570 // in verbose mode, stored data have been printed already...
571 print_stored_results_tt(_sim->_Time0);
573 TTT::accept();
574 assert( _sim->_mode == s_TTT );
577 if (!_accepted_tt) {
578 // } else if (_sim->_last_Time + 0.00001 > _Tstop) {
579 // // good idea? better leave it to next() ...
580 // _Time_by_user_request = _Tstop;
581 } else if (_sim->_Time0 >= _Time_by_user_request // incomplete
582 || step_cause() == scUSER || step_cause() == scLAST) {
583 trace3("TTT::sweep user step", _sim->_Time0, _sim->last_time(), _Time_by_user_request);
584 assert(step_cause() == scUSER || step_cause() == scINITIAL || step_cause() == scLAST);
585 outdata_tt(_sim->_Time0 );
586 _printed_steps++;
587 switch (_stepmode) { //
588 case tts_LIN:
589 _Time_by_user_request = _sim->_Time0 + _Tstep;
590 // _out << "LIN" << _Time_by_user_request << " " << _Tstep << "\n";
591 break;
592 case tts_MUL:
593 _Time_by_user_request = _sim->_Time0 + _sim->last_time() * pow((double)_Tstep, _printed_steps);
594 break;
595 default:
596 unreachable();
598 assert(_Time_by_user_request>=_sim->_last_Time);
599 // if(_Time_by_user_request > _Tstop - 2.*_tstop){ untested();
600 // _Time_by_user_request = _Tstop - _tstop;
601 // }else if(_Time_by_user_request > _Tstop - _tstop){ untested();
602 // _Time_by_user_request = _Tstop - _tstop;
603 // }else{
604 // }
605 } else if(_trace >= tALLTIME) {
606 assert(step_cause());
607 outdata_tt(_sim->_Time0);
608 } else {
609 trace1("TTT::sweep not printing", _sim->_Time0);
610 TTT::store_results( _sim->_Time0 + _tstop );
613 if (!_accepted_tt) {
614 } else {
615 _Time_by_user_request = min(_Time_by_user_request, _Tstop-_sim->last_time());
617 _sim->_last_Time = _sim->_Time0 + _sim->last_time();
618 trace5("TTT::sweep bottom loop", _sim->_last_Time, _sim->_Time0, _Time_by_user_request, _stepmode, _Tstep );
619 assert( _sim->_mode == s_TTT );
622 assert( _sim->_mode == s_TTT );
624 // _out << "* TTT::sweep =================== endof loop "<<_sim->_last_Time<<"\n";
625 _sim->_Time0 = _sim->_last_Time;
626 _sim->_dT0 = 0;
628 advance_Time();
630 #ifndef NDEBUG
631 /// invalidate history
632 std::fill_n(_sim->_tr1, _sim->_adp_nodes, NAN);
633 std::fill_n(_sim->_tt1, _sim->_adp_nodes, NAN);
634 #endif
635 _sim->set_command_tt();
637 /*--------------------------------------------------------------------------*/
638 void TTT::sweep_tr() // tr sweep wrapper.
640 _sim->_time0 = 0.;// for now?
641 _sim->keep_voltages(true); // also sets _last_time=_time0
642 unsigned hidden = ::status.hidden_steps;
643 int ttcontrol = ::status.control;
644 _sim->_mode = s_TRAN;
645 //print_head_tr(); wrong. not b4 accept
646 trace4("TTT::sweep_tr", storelist().size() , _sim->tt_iteration_number(), ttcontrol, _tstop);
647 typedef std::map<std::string, WAVE > wavemap_t;
648 for ( wavemap_t::iterator i = _sim->_waves["tran"].begin(); i != _sim->_waves["tran"].end(); ++i) {
649 i->second.initialize();
651 _sim->_mode = s_TTT;
653 trace1("TTT::sweep_tr() ", _inside_tt);
654 _sim->_time0 = 0.0;
656 try {
657 _cont = true;
658 trace4("TTT::sweep calling sweep", _sim->_time0, _sim->last_time(), _tstrobe, _sim->_phase);
659 _inside_tt = true;
660 assert(_sim->_mode == s_TTT);
661 TRANSIENT::sweep();
662 assert(_accepted);
663 assert( _sim->last_time() <= _tstop + _sim->_dtmin );
665 }catch (Exception& e) { untested();
666 assert(_sim->_mode == s_TTT);
667 error(bDANGER, "Sweep exception \"%s\" at %E, dT0 %E, step %i\n",
668 e.message().c_str(), _sim->_Time0, _sim->_dT0, tt_iteration_number());
669 assert(_sim->_dT0 > _sim->last_time()); // = means zero step
670 // if this fails, something is wrong.
671 _accepted=_accepted_tt=false;
672 ::status.review.stop();
673 // _sim->invalidate_tt();
674 // throw(e); go on with smalller step?
675 if (!tt_iteration_number()) { untested();
676 _out << "* first one must not fail\n";
677 throw(e);
681 if(_sim->_tt_accepted && _agemode == amONCE){
682 error(bNOERROR, "skipping tr_stress_last\n");
683 }else{
684 CARD_LIST::card_list.tr_stress_last(); // FIXME: merge into tt_review
687 _cont_dc = false;
688 _sim->_mode = s_TTT;
690 // restore tt status
691 ::status.control = ttcontrol;
692 ::status.hidden_steps = hidden;
694 _sim->pop_voltages();
695 _sim->_time0 = _sim->last_time();
696 _sim->keep_voltages();
697 trace4( "TTT::sweep_tr done", _sim->_Time0, _sim->_time0, _sim->last_time(), _tstop);
698 assert(_sim->_last_time *0.9999 <= _tstop);
700 /*--------------------------------------------------------------------------*/
701 void TTT::accept()
704 ADP_NODE_LIST::adp_node_list.do_forall( &ADP_NODE::tt_accept);
706 // FIXME: _tt_acceptq -> corrector?
707 if(_sim->_tt_accepted && _agemode == amONCE){
708 error(bNOERROR, "skipping tt_accept\n");
709 }else{
710 while (!_sim->_tt_acceptq.empty()) {
711 _sim->_tt_acceptq.back()->tt_accept();
712 _sim->_tt_acceptq.pop_back();
715 _sim->_tt_accepted++;
716 // _sim->_last_Time = _sim->_Time0+_tstop;
718 /*--------------------------------------------------------------------------*/
719 double TTT::time_by_voltages()
720 { untested();
721 // we started at vdc (unchanged), before keep, compare v0<->vdc
723 double d=0;
724 USE(d);
725 for (unsigned i=1; i<=_sim->_total_nodes; ++i) { untested();
726 double delta = fabs(_sim->_v0[i]-_sim->vdc()[i]);
727 double sum = fabs(_sim->_v0[i])+fabs(_sim->vdc()[i]);
728 USE(sum);
730 double err = delta ;
731 USE(err);
734 incomplete();
735 return(0);
738 /*-----------------------------------------------------------*/
739 // need to check that boundaries are consistent.
740 bool TTT::conchk() const
741 { untested();
742 double a = OPT::abstol;
743 double r = OPT::reltol;
745 for (unsigned i=1; i<=_sim->_total_nodes; ++i) { untested();
746 double n = fabs(_sim->_v0[i]);
747 double o = fabs(_sim->vdc()[i]);
749 if (std::abs(n-o) > (r * std::abs(n) + a))
750 return false;
752 return true;
754 /*--------------------------------------------------------------------------*/
755 bool TTT::review()
757 sanitycheck();
759 assert(_sim->_Time0 >= _sim->_dT0);
760 assert(_sim->_Time0 - _sim->_dT0 >=0 );
762 TIME_PAIR Time_by = CARD_LIST::card_list.tt_review();
763 _Time_by_error_estimate = Time_by._error_estimate;
765 if(Time_by._event < _Time1 + _sim->last_time()){
766 _time_by_ambiguous_event = _Time1 + _sim->last_time();
767 }else{
768 _time_by_ambiguous_event = Time_by._event;
771 trace6("TTT::review", _sim->_Time0, _sim->_dT0, _Time_by_error_estimate, _time_by_ambiguous_event, _sim->last_time(), _Time1);
773 _dT_by_adp = (ADP_NODE_LIST::adp_node_list.tt_review())._event;
775 // double _dT_by_nodes = time_by_voltages();// 1.0 / (1e-20+voltage_distance());//
777 // BUG. don't use _Time1 here.
778 _time_by_adp = _Time1 + _dT_by_adp;
780 if ((_dT_by_adp < _tstop) && (_tstop == _sim->_dT0 )) { untested();
781 return true;
784 if( _time_by_adp < _sim->_Time0 ){ untested();
785 // _out << "* tt reject (adp) timestep " << _sim->_dT0 << " want dT " << _dT_by_adp << " \n";
786 trace3( "TTT::review_tt: reject adptime", _sim->_Time0, _dT_by_adp , _sim->_dT0 );
789 bool acc = _Time_by_error_estimate + .01*_sim->_dtmin >= _sim->_Time0
790 && _time_by_ambiguous_event >= _sim->_Time0;
792 if(step_cause() == scLAST && !acc) {
793 // endless loop?
794 trace3( "TTT::review_tt: endless loop", _sim->_Time0, _sim->_dT0, _Tstop);
795 acc = true;
796 }else{
798 return acc;
800 /*--------------------------------------------------------------------------*/
801 void TTT::do_it(CS& Cmd, CARD_LIST* Scope)
803 _scope = Scope;
804 _sim->set_command_tt();
805 _sim->set_label("tt");
806 // _sim->_age = false; // a tr option
807 ::status.ttt.reset().start();
808 ::status.tt_tries = 0;
809 command_base(Cmd); // s__init.cc
810 assert(_sim->_mode==s_TTT);
811 ::status.ttt.stop();
813 ::status.four.stop(); // ?
814 ::status.total.stop(); // ?
816 /*--------------------------------------------------------------------------*/
817 void TTT::probeexpand()
819 trace0("TTT::probeexpand");
820 _sim->_mode = s_TRAN; // BUG: use phase.
821 PROBELIST* transtore = &_probe_lists->store[s_TRAN];
823 // append prior prints to store (aligned)
824 for (PROBELIST::const_iterator p=printlist().begin();
825 p!=printlist().end(); ++p) {
826 PROBE* x=((*p)->clone());
827 transtore->push_probe(x);
830 // additionally store during TR as user wishes. (if necessary)
831 for (PROBELIST::const_iterator p=oldstore.begin();
832 p!=oldstore.end(); ++p) {
833 PROBE* x=((*p)->clone());
834 transtore->merge_probe(x);
837 _sim->set_command_tt();
839 PROBELIST measstore;
840 for (PROBELIST::const_iterator
841 p=printlist().begin(); p!=printlist().end(); ++p) {
842 MEAS_PROBE* w = dynamic_cast<MEAS_PROBE*>(*p);
843 if (w) {
844 w->expand();
845 string probe_name = w->probe_name;
846 trace1("TTT::probeexpand", probe_name);
847 CS* c = new CS(CS::_STRING,probe_name);
848 measstore.add_list(*c);
849 delete c;
850 } else {
854 // merge some more measure nodes.
855 for (PROBELIST::const_iterator p=measstore.begin();
856 p!=measstore.end(); ++p) {
857 PROBE* x=((*p)->clone());
858 transtore->merge_probe(x);
861 /*--------------------------------------------------------------------------*/
862 /* allocate: allocate space for tt
864 void TTT::allocate()
866 int probes = printlist().size();
867 assert(!_tt_store);
868 trace1("TTT::allocate allocating probes ", probes);
869 _tt_store = new double[probes]; // shadows the .print tt probes
871 PROBELIST* transtore = &_probe_lists->store[s_TRAN];
873 for (PROBELIST::const_iterator p=transtore->begin();
874 p!=transtore->end(); ++p) {
875 oldstore.push_probe((*p)->clone());
877 transtore->clear();
879 probeexpand();
881 assert(_sim->_mode==s_TTT);
883 _sim->set_command_tran();
885 _sim->_waves["tran"].clear();
887 if(_wavep){
888 delete[] _wavep;
889 }else{
891 _wavep = new WAVE*[_probe_lists->store[s_TRAN].size()];
893 unsigned ii = 0;
894 for (PROBELIST::const_iterator
895 p=storelist().begin(); p!=storelist().end(); ++p) {
896 string l = (*p)->label();
897 if (OPT::case_insensitive) {
898 notstd::to_upper(&l);
900 _wavep[ii++] = &(_sim->_waves["tran"][l]);
902 _sim->set_command_tt();
904 trace1("TTT::allocate allocated transtore waves", _probe_lists->store[s_TRAN].size());
906 /*--------------------------------------------------------------------------*/
907 /* unallocate: unallocate space for tt
908 * (merge further up?)
910 void TTT::finish()
912 // int probes = printlist().size();
913 assert (_tt_store);
914 trace2("TTT::unallocate freeing _tt_store", printlist().size(), storelist().size());
915 // incomplete(); //unallocate at deconstruction...
916 // make consecutive sims faster.
917 delete[] _tt_store;
918 _tt_store = NULL;
920 _probe_lists->store[s_TRAN].clear();
921 //FIXME: delete waves;
923 // if (_fdata_tt) { untested();
924 // for (int ii = 0; ii < printlist().size(); ++ii) { untested();
925 // delete [] _fdata_tt[ii];
926 // }
927 // delete [] _fdata_tt;
928 // _fdata_tt = NULL;
929 // }else{itested();
930 // }
931 // TRANSIENT::finish?
932 _sim->unalloc_vectors();
933 _sim->_lu.unallocate();
934 _sim->_aa.unallocate();
936 PROBELIST* transtore = &_probe_lists->store[s_TRAN];
938 transtore->clear();
939 // insert previous store probes
940 for (PROBELIST::const_iterator p=oldstore.begin();
941 p!=oldstore.end(); ++p) {
942 transtore->push_probe((*p)->clone());
945 // move waves back (hack, workaround)
946 // trace1("TTT::unallocate deleting", _sim->_waves);
948 /*--------------------------------------------------------------------------*/
949 static TTT p10;
950 DISPATCHER<CMD>::INSTALL d10(&command_dispatcher, "twotimetran|ttr", &p10);
951 /*--------------------------------------------------------------------------*/
952 static void register_status()
954 static bool done;
956 if(!done) {
957 new DISPATCHER<CKT_BASE>::INSTALL(&status_dispatcher, "tt", &p10);
958 done = true;
961 /*--------------------------------------------------------------------------*/
962 /*--------------------------------------------------------------------------*/
963 double behaviour_timestep()
964 { untested();
965 return 1000000;
967 /*--------------------------------------------------------------------------*/
968 bool TTT::next()
970 if(_Time_by_user_request > _Tstop){ untested();
971 return false;
972 }else{
974 assert( _sim->_mode == s_TTT );
975 double new_dT;
976 double new_Time0;
977 double refTime = _Time1;
978 _inside_tt = true;
980 trace7( "TTT::next()", tt_iteration_number(), _sim->_Time0, _Time1,
981 _sim->_last_Time, _accepted_tt, _Time_by_user_request, _Time_by_error_estimate);
983 assert(_sim->_Time0 >=0 || tt_iteration_number() == 0);
984 STEP_CAUSE new_control = scNO_ADVANCE;
986 if (_sim->_dT0 == 0.) { unreachable();
987 // first transient. is this reachable?
988 new_dT = 0;
989 }else if (_Time1 == _sim->_Time0) {
990 // second step...
991 new_dT = _sim->last_time();
992 new_control = scINITIAL;
993 } else if (!_accepted_tt) {
994 error(bTRACE, "rejected step %f... at %f\n", _sim->_dT0, _sim->_Time0);
996 new_dT = 0.9 * ( _sim->_dT0 - _sim->last_time() ) + _sim->last_time(); // back at least this much.
997 if ( _time_by_adp < _sim->_Time0 ){ untested();
998 assert(_time_by_adp >= 0);
999 new_dT = fmin(new_dT, _dT_by_adp);
1000 } else {
1002 if ( _Time_by_error_estimate < _sim->_Time0 ){
1003 assert(_Time_by_error_estimate >= 0);
1004 new_dT = fmin(new_dT, _Time_by_error_estimate - _Time1);
1005 assert(new_dT>=0);
1006 } else {
1008 if (!_accepted) {
1009 new_dT = fmin(new_dT,.5*_sim->_dT0);
1010 } else {
1013 assert( is_number(new_dT));
1014 new_control = scREJECT;
1015 }else{
1016 // accepted step. calculating new_dT
1017 refTime = _sim->_Time0;
1019 new_dT = _Time_by_user_request - refTime;
1020 new_control = scUSER;
1022 if (new_dT > _dT_by_adp) { untested();
1024 if (new_dT > _Time_by_error_estimate - refTime) {
1025 new_control = scTE;
1026 new_dT = _Time_by_error_estimate - refTime;
1027 }else{
1029 if(OPT::ttstepgrow == 0) {
1030 // fixme: allow "inf" in u_opt
1031 }else if(new_dT > _sim->_dT0 * OPT::ttstepgrow) {
1032 new_control = scGROW;
1033 new_dT = _sim->_dT0 * OPT::ttstepgrow;
1034 } else {
1037 // new_dT = max( new_dT, (double) _tstop );
1038 new_dT = max( new_dT, (double) _sim->last_time() );
1039 assert(new_dT >= 0.);
1041 if (new_dT < _dTmin) {
1042 error(bTRACE, "step too small %e %e adp %e\n", new_dT, _dTmin, _dT_by_adp );
1043 } else {
1046 // last step handler, snap to edge
1048 assert( !OPT::ttstepgrow || new_dT < (OPT::ttstepgrow+1) * _sim->_dT0 || _sim->_dT1<=0 );
1050 ++::status.hidden_steps_tt;
1051 } // accepted
1053 double newTime = refTime + new_dT;
1054 trace8("TTT::next", _time_by_ambiguous_event, _Time1, _sim->_last_Time, _tstop, _Tstart, newTime, _Time_by_user_request, _sim->last_time());
1055 assert(_time_by_ambiguous_event > _Time1);
1057 if (!_evt) { untested();
1058 new_dT = newTime - refTime; // bug?
1059 assert(new_dT >= 0.9999 * _sim->last_time());
1060 }else if (_time_by_ambiguous_event < newTime - _sim->_dTmin) {
1061 if (_time_by_ambiguous_event < _Time1 + 2*_sim->last_time()) {
1062 double minTime = _Time1 + 2*_sim->last_time();
1063 if (newTime - _sim->last_time() < minTime) {
1064 newTime = minTime;
1065 new_control = scAMBEVENT;
1066 }else{
1068 }else{
1069 newTime = _time_by_ambiguous_event;
1070 new_control = scAMBEVENT;
1072 trace5("ambevent", _time_by_ambiguous_event, _sim->_Time0, newTime, refTime, _accepted_tt);
1073 new_dT = newTime - refTime;
1074 assert(new_dT >= 0.);
1075 }else{
1078 assert(step_cause());
1080 new_Time0 = _sim->_last_Time + new_dT - _sim->last_time();
1081 trace6("TTT::next ", new_dT, _tstop, new_dT, _Time_by_user_request, new_Time0, refTime);
1082 assert(new_Time0 > _Time1);
1083 _Time1 = refTime;
1084 assert(new_Time0 > _Time1);
1086 // hmm rethink. maybe don't shift forwards if not necessary....
1087 if ( (double)_Tstop - _sim->last_time() <= _sim->_last_Time) {
1088 // new_control = scLAST;
1089 }else if ( ( (double)_Tstop - _sim->_last_Time < 2.00001 * _tstop
1090 || new_dT + _sim->_last_Time > _Tstop ) ) {
1091 // snap forward...
1092 new_dT = _Tstop - _sim->_Time0 - _sim->last_time();
1093 assert(new_dT > 0.999*_sim->last_time()); //noise?
1094 new_Time0 = _sim->_last_Time + new_dT - _sim->last_time();
1095 new_control = scLAST;
1096 }else if(new_Time0 + _sim->last_time() >= _Time_by_user_request){
1097 new_control = scUSER;
1098 }else{
1100 set_step_cause(new_control);
1102 if (_sim->_dT1 && new_dT < _sim->last_time() ) {
1103 new_dT = _sim->last_time();
1104 assert(new_dT > 0.999*_sim->last_time()); //noise?
1105 set_step_cause(scSMALL);
1106 }else{
1109 bool another_step = true;
1111 if (! ( _Tstop - _sim->_last_Time >= _sim->last_time() )){
1112 another_step = false;
1113 }else if (! ( new_Time0 <= _Tstop - _sim->last_time() )) {untested();
1114 another_step = false;
1115 }else if (! ( new_dT != 0 || !_sim->_dT0 )){ untested();
1116 another_step = false;
1119 trace7("TTT::next", another_step, _sim->last_time(), new_Time0, new_dT, _sim->last_Time(), _Time1, step_cause());
1121 assert(new_Time0 >= new_dT);
1122 assert(new_Time0 > _Time1);
1124 if(_accepted_tt){ // fixme: obenhin, oder?
1125 _sim->_dT3 = _sim->_dT2;
1126 _sim->_dT2 = _sim->_dT1;
1127 _sim->_dT1 = _sim->_dT0;
1130 if (!another_step) {
1131 trace6( "TTT::next no next @ Time0: " , _sim->_Time0, _sim->_dT0, new_dT, _dTmin, _tstop, new_Time0 );
1132 trace5( "TTT::next no next @ Time0: " ,\
1133 _Time1, _Tstop, new_dT >= _dTmin , _Tstop - _Time1 >= _dTmin , new_Time0 + _tstop <= _Tstop );
1134 // _sim->_last_Time = _Time1 + _tstop; // FIXME
1136 return (false); // bug
1137 } else {
1138 trace8("TTT::next another step ", _sim->_Time0, new_dT, _Time1, _Tstop,
1139 _sim->_dT0, new_Time0, _Time_by_user_request, _dTmin );
1142 assert(new_dT > 0.999*_sim->last_time()); //noise?
1143 if (new_dT < _sim->last_time()) {
1144 // BUG
1145 new_dT = _sim->last_time();
1146 }else{
1148 _sim->_dT0 = new_dT;
1149 _sim->_Time0 = new_Time0;
1151 assert( _sim->_Time0 >= _sim->_dT0*0.9999 );
1152 if (_sim->_Time0 < _sim->_dT0) {
1153 // BUG
1154 _sim->_Time0 = _sim->_dT0;
1155 }else{
1158 // assert(_sim->_dT0 >= _dTmin);
1159 assert(_sim->_dT0 + 0.001*_dTmin >= _sim->last_time());
1160 assert(_sim->_dT0 >= _sim->last_time());
1162 _time1 = 0.;
1164 assert( _sim->_Time0 < 1+ _Time1 + _sim->_dT0 );
1165 assert( _sim->_Time0 >= _sim->_dT0 );
1166 assert( _sim->_Time0 > 0 || tt_iteration_number() == 0);
1168 _sim->restore_voltages();
1170 trace0("praparing nodes nodes");
1172 for (uint_t ii = 1; ii <= _sim->_total_nodes; ++ii) {
1173 _sim->_nstat[_sim->_nm[ii]].set_last_change_time(0);
1174 _sim->_nstat[_sim->_nm[ii]].store_old_last_change_time();
1175 _sim->_nstat[_sim->_nm[ii]].set_final_time(0);
1178 advance_Time();
1179 ++steps_total_tt;
1180 ++::status.hidden_steps;
1182 trace8( "TTT::next: exiting next: " , _sim->tt_iteration_number(),
1183 _sim->_Time0, _Time1, _sim->_dT0, _sim->_dT1 , _sim->_dT2, _sim->_last_Time, step_cause() );
1184 assert(_sim->_Time0 > _Time1);
1185 // assert(_sim->_dT0 >= _dTmin);
1186 assert(step_cause());
1187 return another_step;
1188 } // next
1189 /*--------------------------------------------------------------------------*/
1190 /* SIM::head: print column headings and draw plot borders
1193 void TTT::head_tt(double start, double stop, const std::string& col1)
1195 trace2("TTT::head_tt", start, stop);
1196 assert(_sim->_mode==s_TTT);
1197 //PROBELIST* transtore = &_probe_lists->store[s_TRAN];
1199 print_tr_probe_number = printlist().size();
1201 trace1("TTT::head tr ttt WAVE", storelist().size() );
1203 if (_wavep_tt) {
1204 delete[]_wavep_tt;
1205 } else {
1207 _wavep_tt = new WAVE*[storelist().size()];
1208 unsigned ii = 0;
1209 for (PROBELIST::const_iterator
1210 p=storelist().begin(); p!=storelist().end(); ++p) {
1211 string l = (*p)->label();
1212 if (OPT::case_insensitive) {
1213 notstd::to_upper(&l);
1215 _wavep_tt[ii] = &(_sim->_waves[_sim->_label][l]);
1216 _wavep_tt[ii++]->initialize();
1220 if (!plopen(start, stop, plotlist())) {
1221 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1222 int width = std::min(OPT::numdgt+5, BIGBUFLEN-10);
1223 char format[20];
1224 //sprintf(format, "%%c%%-%u.%us", width, width);
1225 sprintf(format, "%%c%%-%us", width);
1226 _out.form(format, '#', col1.c_str());
1228 for (PROBELIST::const_iterator
1229 p=printlist().begin(); p!=printlist().end(); ++p) {
1230 _out.form(format, ' ', (*p)->label().c_str());
1231 //trace1("TTT::head_tt", (*p)->label() );
1232 if ( !(--print_tr_probe_number) ) break;
1234 _out << '\n';
1235 }else{ untested();
1237 _sim->_mode=s_TRAN;
1240 trace3("TTT::tt_head probe TRAN", printlist().size(), storelist().size(), oldstore.size());
1242 // _sim->_waves = new WAVE[storelist().size()];
1244 _sim->_mode=s_TTT;
1245 for (PROBELIST::const_iterator
1246 p=printlist().begin(); p!=printlist().end(); ++p) {
1247 _sim->_mode=s_TRAN;
1248 (*p)->precalc_last();
1249 _sim->_mode=s_TTT;
1252 /*--------------------------------------------------------------------------*/
1253 /* SIM::head: initialize waves, override TRANSIENT::head()
1255 void TTT::head(double /* start */ , double /* stop */, const std::string& )
1257 trace0("TTT::head");
1258 assert(_sim->_mode==s_TTT);
1259 _sim->_mode=s_TRAN;
1260 if (_sim->tt_iteration_number() == 0) {
1261 TRANSIENT::_out.setfloatwidth(OPT::numdgt, OPT::numdgt+6);
1262 // print_head_tr();
1264 trace3("TTT::head probe TTT", printlist().size(), storelist().size(), _sim->_phase);
1266 unsigned ii = 0;
1267 for (PROBELIST::const_iterator
1268 p=storelist().begin(); p!=storelist().end(); ++p) {
1269 string l = (*p)->label();
1270 if (OPT::case_insensitive) {
1271 notstd::to_upper(&l);
1273 _wavep[ii] = &(_sim->_waves["tran"][l]);
1274 _wavep[ii++]->initialize();
1277 _sim->_mode = s_TTT;
1279 /*--------------------------------------------------------------------------*/
1280 /* SIM::print_head: print column headers TR
1282 void TTT::print_head_tr()
1284 trace0("TTT::print_head_tr");
1286 //assert( _sim->_mode==s_TRAN );
1287 _sim->_mode = s_TRAN;
1288 SIM_MODE oldmode = _sim->_mode;
1290 if (!printlist().size()) {
1291 // incomplete(); // bug: what to do with empty printlists?
1292 // for now: suppress output...
1293 _sim->_mode = oldmode;
1294 return;
1296 TRANSIENT::_out << "#TTime ";
1298 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1299 int width = std::min(OPT::numdgt+5, BIGBUFLEN-10);
1300 char format[20];
1301 sprintf(format, "%%c%%-%us", width);
1302 for (int i=0; i< OPT::numdgt; i++) {
1303 TRANSIENT::_out << " ";
1305 TRANSIENT::_out << "time";
1306 for (int i=0; i< OPT::numdgt+1; i++) {
1307 TRANSIENT::_out << " ";
1309 for (PROBELIST::const_iterator
1310 p=printlist().begin(); p!=printlist().end(); ++p) {
1311 TRANSIENT::_out.form(format, ' ', (*p)->label().c_str());
1313 TRANSIENT::_out << '\n';
1315 _sim->_mode = oldmode;
1316 TRANSIENT::_out.setfloatwidth(OPT::numdgt, OPT::numdgt+6);
1318 /*--------------------------------------------------------------------------*/
1319 void TTT::print_foot_tr()
1321 // make plotter happy. (only if _out!=TRANSIENT::_out?)
1322 _sim->set_command_tran();
1323 if (printlist().size()) {
1324 TRANSIENT::_out << '\n';
1327 /*--------------------------------------------------------------------------*/
1328 // override TRANSIENT::outdata
1329 // save things during TR.
1330 void TTT::outdata(double time0)
1332 assert(TRANSIENT::step_cause());
1333 assert(is_number(time0));
1334 _sim->_mode = s_TTT;
1335 ::status.output.start();
1336 assert( _sim->_mode == s_TTT );
1338 // SIM::alarm();
1339 _sim->_mode=s_TRAN;
1340 if ( _trace>=tDEBUG) { untested();
1341 TRANSIENT::print_results(time0);
1344 _sim->set_command_tran();
1345 if (_sim->tt_iteration_number()==0 && printlist().size() != 0) {
1346 // will always accept 1st
1347 TRANSIENT::_out << (double)_sim->_Time0;
1348 TRANSIENT::print_results(time0);
1349 } else {
1350 // store_results(time0);
1351 if (TRANSIENT::_trace >= tDEBUG){ untested();
1352 TRANSIENT::_out << "*" << (double)_sim->_Time0;
1353 TRANSIENT::print_results(time0);
1356 _sim->set_command_tt();
1358 _sim->_mode=s_TRAN;
1359 // FIXME (only > 0)?
1360 TRANSIENT::store_results(time0);
1362 _sim->_mode = s_TTT;
1363 _sim->reset_iteration_counter(iPRINTSTEP);
1364 ::status.hidden_steps = 0;
1365 ::status.output.stop();
1366 assert( _sim->_mode == s_TTT );
1368 /*--------------------------------------------------------------------------*/
1369 void TTT::outdata_b4(double time)
1371 assert( _sim->_mode == s_TTT );
1372 ::status.output.start();
1373 print_results_tt(time);
1374 ::status.output.stop();
1376 /*--------------------------------------------------------------------------*/
1377 // print at end of timeframe. "now" is begin of timeframe...
1378 void TTT::outdata_tt(double now)
1380 assert(step_cause());
1381 assert(_sim->_mode==s_TTT);
1382 if ( 0 && _accepted_tt && _sim->_dT0 && !is_almost (_sim->_dT0 + _sim->_last_Time, now + _sim->last_time() )) { untested();
1383 error(bWARNING, "EOF: %.9f, last_Time: %.9f, dT0: %f, now: %f\n", _sim->_Time0+_sim->last_time(), _sim->_last_Time, _sim->_dT0,now );
1385 ::status.output.start();
1386 assert( _sim->_mode == s_TTT );
1387 print_results_tr(now); //transient print?
1388 assert( _sim->_mode == s_TTT );
1389 print_results_tt(now + _sim->last_time());
1390 tt_alarm(_alarm, &_out);
1391 assert(_sim->_mode==s_TTT);
1392 if (!tt_iteration_number()) {
1393 TTT::store_results( now ); // store extra results.
1395 TTT::store_results( now + _sim->last_time() ); // results are stored after TRAN
1396 assert(_sim->_mode==s_TTT);
1397 _sim->reset_iteration_counter(iPRINTSTEP);
1398 ::status.hidden_steps = 0;
1399 ::status.output.stop();
1401 /*--------------------------------------------------------------------------*/
1402 // fixme: merge back to s__out.cc
1403 void TTT::tt_alarm(ALARM a, OMSTREAM* out)
1405 if (a==aNONE) {
1406 return;
1408 if (!out) { untested();
1409 out = &_out;
1411 bool abort=false;
1412 _out.setfloatwidth(OPT::numdgt, OPT::numdgt+6);
1413 for (PROBELIST::const_iterator
1414 p=alarmlist().begin(); p!=alarmlist().end(); ++p) {
1415 if (!(*p)->in_range()) {
1416 stringstream s;
1417 s << (*p)->label() << '=' << (*p)->value() << '\n';
1418 switch (a) {
1419 case aREDIR:
1420 cerr << s.str();
1421 break;
1422 case aABORT:
1423 abort = true;
1424 default:
1425 *out << string(s.str());
1429 if (abort && _accepted_tt) {
1430 throw Exception_Alarm("values out of range\n");
1433 /*--------------------------------------------------------------------------*/
1434 // print during tr. i.e. print from storelist
1435 void TTT::print_results(double time)
1436 { untested();
1437 // deprecated call.
1438 assert(false);
1439 unreachable();
1440 print_results_tr(time);
1442 /*--------------------------------------------------------------------------*/
1443 void TTT::print_results_tr(double Time ) // Time is begin of frame
1445 SIM_MODE oldmode = _sim->_mode;
1446 trace4("TTT::print_results_tr()", tt_iteration_number(), Time, _sim->_mode, oldmode);
1447 USE(Time);
1448 _sim->set_command_tran();
1449 const WAVE* w = NULL;
1451 if ( printlist().size() == 0 ) {
1452 _sim->_mode = oldmode;
1453 return;
1455 assert(_sim->_mode=s_TRAN);
1457 if (!IO::plotout.any() && _sim->tt_iteration_number() > 0 ) {
1458 // 1st step has already been printed (no need for review)
1459 TRANSIENT::_out.setfloatwidth(OPT::numdgt, OPT::numdgt+6);
1460 std::map<std::string, WAVE>::const_iterator wi = _sim->_waves["tran"].begin();
1461 assert(wi!=_sim->_waves["tran"].end());
1462 w = &wi->second;
1464 print_head_tr();
1466 int ii=0;
1467 // hmm correct?
1468 WAVE::const_iterator* myiterators = new WAVE::const_iterator[printlist().size()];
1470 for (PROBELIST::const_iterator p = printlist().begin();
1471 p!=printlist().end(); ++p) {
1472 myiterators[ii] = _wavep[ii]->begin();
1473 ii++;
1475 for (WAVE::const_iterator i = w->begin(); i != w->end(); i++) {
1476 TRANSIENT::_out << _sim->_Time0;
1477 if( i->first > _sim->last_time()) { untested();
1478 break;
1479 }else{
1481 TRANSIENT::_out << i->first;
1483 ii=0;
1484 for (PROBELIST::const_iterator
1485 p=printlist().begin(); p!=printlist().end(); ++p) {
1487 TRANSIENT::_out << myiterators[ii]->second;
1488 myiterators[ii]++;
1489 ii++;
1492 TRANSIENT::_out << '\n';
1494 delete[] myiterators;
1495 print_foot_tr();
1496 } else {
1498 _sim->set_command_tt(); // FIXME
1499 _sim->_mode = oldmode;
1500 trace3("TTT::print_results_tr done", tt_iteration_number(), Time, _sim->_mode);
1502 /*--------------------------------------------------------------------------*/
1503 void TTT::print_stored_results_tt(double x)
1506 if ( printlist().size() ==0) { untested();
1507 trace0("no ttprint");
1508 return;
1509 } else {
1511 assert( _sim->_mode == s_TTT );
1512 if (!IO::plotout.any()) {
1513 assert(x != NOT_VALID);
1514 int i;
1515 _out << x;
1516 for (i=0; i < printlist().size(); i++ ) {
1517 _out << _tt_store[i];
1519 _out << '\n';
1520 } else { untested();
1523 /*--------------------------------------------------------------------------*/
1524 // store things at begin of timeframe, so it may be printed
1525 // after/if the step is accepted.
1526 void TTT::store_results_tt(double x)
1528 trace0("TTT::store_results_tt()");
1529 if ( printlist().size() ==0) {
1530 return;
1533 int i=0;
1534 assert( _sim->_mode == s_TTT );
1535 if (!IO::plotout.any()) {
1536 assert(x != NOT_VALID); USE(x);
1537 for (PROBELIST::const_iterator
1538 p=printlist().begin(); p!=printlist().end(); ++p) {
1539 _tt_store[i++] = (*p)->value();
1541 } else { untested();
1545 /*--------------------------------------------------------------------------*/
1546 void TTT::print_results_tt(double x)
1548 if( printlist().size() == 0 && _quiet ){ untested();
1549 return;
1552 assert( _sim->_mode == s_TTT );
1553 if (!IO::plotout.any()) {
1554 _out.setfloatwidth(OPT::numdgt, OPT::numdgt+6);
1555 assert(x != NOT_VALID);
1556 _out << x;
1557 for (PROBELIST::const_iterator
1558 p=printlist().begin(); p!=printlist().end(); ++p) {
1560 if (!(*p)) { unreachable(); // ??
1561 continue;
1564 try {
1565 _out << (*p)->value();
1566 } catch( Exception_No_Match ) { untested();
1567 _out << "XXXX";
1570 _out << '\n';
1571 }else{ untested();
1574 /*--------------------------------------------------------------------------*/
1575 string TTT::status()const
1577 return "twotime timesteps: accepted=" + ::to_string(steps_accepted())
1578 + ", rejected=" + ::to_string(steps_rejected())
1579 + ", total=" + ::to_string(steps_total()) + "\n";
1581 /*--------------------------------------------------------------------------*/
1582 /* SIM::store: store data in preparation for post processing
1583 * use storelist as index for waves
1585 void TTT::store_results(double time)
1587 trace3("TTT::store_results()", tt_iteration_number(), iteration_number(), time );
1588 assert(_sim->_mode==s_TTT);
1589 int ii = 0;
1590 for (PROBELIST::const_iterator
1591 p=storelist().begin(); p!=storelist().end(); ++p) {
1592 trace3("TTT::store_results", time, (*p)->label(), (*p)->value());
1593 _wavep_tt[ii++]->push(time, (*p)->value());
1596 /*--------------------------------------------------------------------------*/
1597 void TTT::advance_Time(void)
1599 trace6("TTT::advance_Time", _sim->_tr[0], _sim->_tt[0], _sim->_Time0, _sim->_adp_nodes, _tstop, _sim->_time0);
1600 ::status.tt_advance.start();
1602 static double last_iter_time;
1603 // _sim->_time0 = 0.;
1604 assert(_sim->last_time() == _sim->_time0);
1605 _sim->keep_voltages();
1606 assert(_sim->last_time()*0.9999 <= _tstop);
1607 if (_sim->_Time0 > 0) {
1608 if (_sim->_dT0 == 0) {
1609 } else if (_sim->_Time0 > last_iter_time && _accepted_tt ) {
1610 /* moving forward */
1611 _sim->_tt_iter++;
1612 // _sim->_tt_rejects = 0;
1613 _sim->update_tt_order();
1615 // trace2("TTT::advance_Time", _sim->_tr1[0], _sim->_tt1[0]);
1617 notstd::copy_n(_sim->_tr2, _sim->_adp_nodes, _sim->_tr3);
1618 notstd::copy_n(_sim->_tr1, _sim->_adp_nodes, _sim->_tr2);
1620 assert(is_number(_sim->_tt[0]) || !_sim->_adp_nodes);
1622 notstd::copy_n(_sim->_tr, _sim->_adp_nodes, _sim->_tr1);
1623 notstd::copy_n(_sim->_tt, _sim->_adp_nodes, _sim->_tt1);
1625 // invalidate ....
1626 // std::fill_n(_sim->_tr, _sim->_adp_nodes, NAN); // no. needed if ttsteporder==0
1627 // std::fill_n(_sim->_tt, _sim->_adp_nodes, NAN); // no. needed if ttsteporder==0
1629 trace3("TTT::advance_Time done", _sim->_tr[0], _sim->_tt[0], _sim->_Time0);
1630 trace2("TTT::advance_Time done", _sim->_tr1[0], _sim->_tt1[0]);
1632 // assert(is_number(_sim->_tr1[0]) || !_sim->_adp_nodes); // BUG?
1633 assert(is_number(_sim->_tt1[0]) || !_sim->_adp_nodes);
1635 ADP_NODE_LIST::adp_node_list.do_forall( &ADP_NODE::tt_advance );
1636 /// AFTER tr and tt have been shifted.
1637 CARD_LIST::card_list.tt_advance();
1639 } else {
1641 std::fill_n(_sim->_tr, _sim->_adp_nodes, NAN); // invalidate.
1642 std::fill_n(_sim->_tt, _sim->_adp_nodes, NAN); // invalidate.
1644 _sim->restore_voltages();
1645 _sim->_time0 = 0.;
1646 CARD_LIST::card_list.tt_regress();
1647 /* moving backward */
1649 } else {
1650 trace0("TTT::advance_Time obsolete call?");
1651 ADP_NODE_LIST::adp_node_list.do_forall( &ADP_NODE::tt_advance );
1652 /// AFTER tr and tt have been shifted.
1653 CARD_LIST::card_list.tt_advance();
1655 last_iter_time = _sim->_Time0;
1656 trace0("TTT::advance_Time() done");
1657 ::status.tt_advance.stop();
1659 /*--------------------------------------------------------------------------*/
1660 /*--------------------------------------------------------------------------*/
1662 } // namespace
1663 // vim anything.