1 /*$Id: s_tr_swp.cc 2016/09/20 al $ -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
22 * sweep time and simulate. output results.
25 #include "u_time_pair.h"
26 #include "u_sim_data.h"
28 #include "e_card.h" // debugging...
29 #include "declare.h" /* gen */
31 #include "e_adp.h" // hack. see below
33 //#define ALT_CQ // alternatively clear queue (experimental)
34 /*--------------------------------------------------------------------------*/
35 // void TRANSIENT::sweep(void);
36 // void TRANSIENT::first(void);
37 // bool TRANSIENT::next(void);
38 // void TRANSIENT::accept(void);
39 // void TRANSIENT::reject(void);
40 /*--------------------------------------------------------------------------*/
41 /*--------------------------------------------------------------------------*/
43 static std::string step_cause
[] = {
47 "command line \"skip\"",
48 "convergence failure, reducing (itl4)",
49 "slow convergence, holding (itl3)",
56 /*--------------------------------------------------------------------------*/
57 void TRANSIENT::sweep()
59 trace2("TRANSIENT::sweep", _cont
, _cont_dc
);
60 _sim
->_phase
= p_INIT_DC
;
61 head(_tstart
, _tstop
, "Time");
62 _sim
->_bypass_ok
= false;
63 _sim
->set_inc_mode_bad();
66 _sim
->_phase
= p_RESTORE
;
67 _sim
->restore_voltages();
68 CARD_LIST::card_list
.tr_restore();
69 outdata(_sim
->_time0
);
72 } else if (_inside_tt
&& _cont_dc
) {
73 _sim
->restore_voltages(); // required by some tr_begins.
74 // might be possible to move
75 // node dependency into tr_accept
76 _sim
->_cont
= true; // keep coil from overwriting current
77 _sim
->_phase
= p_RESTORE
; // short cut differentiate
78 CARD_LIST::card_list
.tr_restore();
79 CARD_LIST::card_list
.do_tr();
83 _sim
->reset_iteration_counter(iSTEP
);
84 CARD_LIST::card_list
.do_tr();
85 } else if (_cont_dc
) {
86 // continue from DC point.
87 _sim
->restore_voltages(); // required by some tr_begins.
88 // might be possible to move
89 // node dependency into tr_accept
90 if(_inside_tt
){ untested();
91 }else if(_edge_detect
& edYES
){
92 _sim
->keep_voltages(true);
94 _sim
->_cont
= true; // keep coil from overwriting current
95 _sim
->_phase
= p_RESTORE
; // short cut differentiate
96 CARD_LIST::card_list
.tr_begin();
100 _sim
->reset_iteration_counter(iSTEP
);
101 CARD_LIST::card_list
.do_tr();
103 }else if (_inside_tt
) {
104 trace0("TRANSIENT::sweep inside tt");
105 assert( _sim
->_mode
== s_TTT
);
107 _sim
->restore_voltages();
108 _sim
->_phase
= p_RESTORE
;
109 // CARD_LIST::card_list.tr_restore(); no. tt_advance takes care of it.
110 CARD_LIST::card_list
.do_tr();
113 // use the data from last time
114 _sim
->_phase
= p_RESTORE
;
115 _sim
->restore_voltages();
116 CARD_LIST::card_list
.tr_restore();
117 if(_edge_detect
& edYES
){
118 _sim
->keep_voltages(true);
123 CARD_LIST::card_list
.tr_begin();
127 _sim
->_genout
= gen();
129 // assert (_sim->_loadq.empty());
130 if ( /*_sim->more_uic_now() */ 0 ) {
131 trace0("TRAN: more UIC now ");
133 _sim
->zero_voltages();
134 CARD_LIST::card_list
.do_tr();
135 while (!_sim
->_late_evalq
.empty()) {itested(); //BUG// encapsulation violation
136 _sim
->_late_evalq
.front()->do_tr_last();
137 _sim
->_late_evalq
.pop_front();
139 // _converged = true;
140 _converged
= solve_with_homotopy(OPT::DCBIAS
,_trace
);
143 } else if (_sim
->uic_now() || _inside_tt
) {
144 trace3("TRANSIENT::sweep uic_now solve", _time1
, _sim
->_time0
, _inside_tt
);
146 trace0("TRANSIENT::sweep advanced");
148 _sim
->zero_voltages(); // ?
150 CARD_LIST::card_list
.do_tr(); //evaluate_models
151 while (!_sim
->_late_evalq
.empty()) {untested(); //BUG// encapsulation violation
152 _sim
->_late_evalq
.front()->do_tr_last();
153 _sim
->_late_evalq
.pop_front();
156 } else if (_cont_dc
) {
157 // continue from DC point.
159 assert(_sim
->_late_evalq
.empty());
160 while (!_sim
->_late_evalq
.empty()) {itested(); //BUG// encapsulation violation
161 _sim
->_late_evalq
.front()->do_tr_last();
162 _sim
->_late_evalq
.pop_front();
165 } else if (_cont_dc
&& _sim
->analysis_is_static()) { untested();
167 _converged
= solve_with_homotopy(OPT::DCBIAS
,_trace
);
169 error(bWARNING
, "did not converge\n");
173 trace0("TRANSIENT::sweep review...");
175 trace0("TRANSIENT::sweep reviewed");
178 trace0("TRANSIENT::sweep accepted");
181 bool printnow
= (_sim
->_time0
== _tstart
|| _trace
>= tALLTIME
);
183 _sim
->keep_voltages();
184 outdata(_sim
->_time0
);
186 ++::status
.hidden_steps
;
190 assert(_tstrobe
>=OPT::dtmin
); // == wont work because of CAUSE
191 // we do only increase _time_by_user_request if
193 // the second step is always caused by initial guess...
195 trace3("TRANSIENT::sweep entering loop", (STEP_CAUSE
)step_cause(), _sim
->_time0
, _sim
->last_time());
197 _dt_by_edge1
= -NEVER
;
198 _dt_by_edge0
= -NEVER
;
200 trace3("TRANSIENT::sweep loop ... ", (STEP_CAUSE
)step_cause(), _sim
->_time0
, _sim
->last_time());
201 _sim
->_bypass_ok
= false;
202 _sim
->_phase
= p_TRAN
;
203 _sim
->_genout
= gen();
204 _converged
= solve(OPT::TRHIGH
,_trace
);
206 _accepted
= _converged
&& review();
209 trace1("TRANSIENT::sweep accepted", (STEP_CAUSE
)step_cause());
212 if (step_cause() == scUSER
) {
213 trace3("up order", _sim
->_time0
-_sim
->_dtmin
, _time_by_user_request
, _sim
->_time0
+_sim
->_dtmin
);
214 assert( up_order(_sim
->_time0
-_sim
->_dtmin
, _time_by_user_request
, _sim
->_time0
+_sim
->_dtmin
)
215 || _sim
->_time0
== _tstop
);
217 trace1("TRANSIENT::sweep delivered req", _time_by_user_request
);
218 if (_time_by_user_request
<_tstop
){
219 _time_by_user_request
+= _tstrobe
; /* advance user time */
220 // _time_by_user_request = min(_time_by_user_request, (double)_tstop+_sim->_dtmin);
222 _time_by_user_request
+= _tstrobe
; /* advance user time */
226 assert(_sim
->_time0
<= _time_by_user_request
);
228 trace2("TRANSIENT::sweep NOT accepted", _sim
->_time0
, _trace
);
230 assert(_time1
< _time_by_user_request
);
234 (_trace
>= tREJECTED
)
235 || (_accepted
&& (_trace
>= tALLTIME
236 || step_cause() == scUSER
237 || (!_tstrobe
.has_hard_value() && _sim
->_time0
+_sim
->_dtmin
> _tstart
)));
239 _sim
->keep_voltages();
240 trace2("TRANSIENT::sweep" ,_sim
->last_time(), (double)_tstop
);
241 assert(_sim
->last_time() < _tstop
+_sim
->_dtmin
|| _sim
->_freezetime
);
243 outdata(_sim
->_time0
);
244 CKT_BASE::tr_behaviour_del
= 0;
245 CKT_BASE::tr_behaviour_rel
= 0;
247 ++::status
.hidden_steps
;
251 if (!_converged
&& OPT::quitconvfail
) { untested();
252 outdata(_sim
->_time0
);
253 throw Exception("convergence failure, giving up");
258 // _sim->_time0 = _sim->last_time(); // hack?
259 // // this is required because keep_voltage
260 // // calls set last_time to time0
262 for (uint_t ii
= _sim
->_lu
.size(); ii
> 0; --ii
) {
263 _sim
->_nstat
[ii
].set_discont(disNONE
);
265 assert(!_sim
->_nstat
[0].discont());
267 /*--------------------------------------------------------------------------*/
268 void TRANSIENT::set_step_cause(STEP_CAUSE C
)
271 case scITER_A
:untested();
272 case scADT
:untested();
280 ::status
.control
= C
;
282 case scNO_ADVANCE
:untested();
283 case scZERO
:untested();
286 ::status
.control
+= C
;
293 /*--------------------------------------------------------------------------*/
294 int TRANSIENT::step_cause()const
296 return ::status
.control
;
298 /*--------------------------------------------------------------------------*/
299 void TRANSIENT::first()
301 /* usually, _sim->_time0, time1 == 0, from setup */
302 assert(_sim
->_time0
== _time1
);
303 // assert(_sim->_time0 <= _tstart); // oops?
304 ::status
.review
.start();
306 //_eq.Clear(); /* empty the queue */
307 while (!_sim
->_eq
.empty()) {untested();
312 //_time_by_user_request = _sim->_time0 + _tstrobe; /* set next user step */
313 //set_step_cause(scUSER);
315 if (_sim
->_time0
< _tstart
) { // skip until _tstart
316 set_step_cause(scINITIAL
); // suppressed
317 _time_by_user_request
= _tstart
; // set first strobe
319 set_step_cause(scUSER
); // strobe here
320 _time_by_user_request
= _sim
->_time0
+ _tstrobe
; // set next strobe
323 ::status
.hidden_steps
= 0;
324 ::status
.review
.stop();
326 /*--------------------------------------------------------------------------*/
327 #define check_consistency() { \
328 trace4("", __LINE__, newtime, almost_fixed_time, fixed_time); \
329 assert(almost_fixed_time <= fixed_time); \
330 assert(newtime <= fixed_time); \
331 /*assert(newtime == fixed_time || newtime <= fixed_time -_sim->_dtmin);*/ \
332 assert(newtime <= almost_fixed_time); \
333 /*assert(newtime == almost_fixed_time || newtime <= almost_fixed_time - _sim->_dtmin);*/ \
334 assert(newtime > _time1); \
335 assert(newtime > reftime); \
336 assert(new_dt > 0.); \
337 assert(new_dt >= _sim->_dtmin); \
338 /*assert(new_dt == 0 || new_dt / _sim->_dtmin > 0.999999);*/ \
339 /* assert(newtime <= _time_by_user_request); */ \
340 /*assert(newtime == _time_by_user_request*/ \
341 /* || newtime < _time_by_user_request - _sim->_dtmin); */ \
343 #define check_consistency2() { \
344 assert(newtime > _time1); \
345 assert(new_dt > 0.); \
346 assert(new_dt >= _sim->_dtmin); \
347 assert(newtime <= _time_by_user_request); \
348 /*assert(newtime == _time_by_user_request */ \
349 /* || newtime < _time_by_user_request - _sim->_dtmin);*/ \
351 /*--------------------------------------------------------------------------*/
352 /* next: go to next time step
353 * Set _sim->_time0 to the next time step, store the old one in time1.
354 * Try several methods. Take the one that gives the shortest step.
356 bool TRANSIENT::next()
358 ::status
.review
.start();
360 double old_dt
= _sim
->_time0
- _time1
;
364 double newtime
= NEVER
;
365 double new_dt
= NEVER
;
366 STEP_CAUSE new_control
= scNO_ADVANCE
;
368 if (_sim
->_time0
== _time1
) {
369 // initial step -- could be either t==0 or continue
370 // for the first time, just guess
371 // make it 100x smaller than expected
372 new_dt
= std::max(_dtmax
/100., _sim
->_dtmin
);
373 newtime
= _sim
->_time0
+ new_dt
;
374 new_control
= scINITIAL
;
376 if (_time_by_ambiguous_event
< newtime
) {
377 newtime
= _time_by_ambiguous_event
;
378 new_dt
= _time_by_ambiguous_event
- _time1
;
379 new_control
= scAMBEVENT
;
384 if (up_order(newtime
-_sim
->_dtmin
, _time_by_user_request
, newtime
+_sim
->_dtmin
)) {
385 new_control
= scUSER
;
387 }else if (!_converged
) {
388 new_dt
= old_dt
/ OPT::trstepshrink
;
389 newtime
= _time_by_iteration_count
= _time1
+ new_dt
;
390 new_control
= scITER_R
;
391 // fprintf(stderr,".");
398 reftime
= _sim
->_time0
;
403 trace2("TRANSIENT::next ", step_cause(), old_dt
);
404 trace3("TRANSIENT::next ", _time1
, _sim
->_time0
, reftime
);
405 trace2("TRANSIENT::next ", _time_by_user_request
, _sim
->_dtmin
);
407 if (_time_by_user_request
< newtime
) {
408 newtime
= _time_by_user_request
;
409 new_dt
= newtime
- reftime
;
410 if (new_dt
< _sim
->_dtmin
) { itested();
411 // last step handler?
412 new_dt
= _sim
->_dtmin
;
413 newtime
= reftime
+ _sim
->_dtmin
;
416 new_control
= scUSER
;
419 double fixed_time
= newtime
;
420 double almost_fixed_time
= newtime
;
421 trace2("TRANSIENT::next", _time_by_user_request
, newtime
);
425 // event queue, events that absolutely will happen
426 // exact time. NOT ok to move or omit, even by _sim->_dtmin
427 // some action is associated with it.
428 if (!_sim
->_eq
.empty() && _sim
->_eq
.top() < newtime
) {
429 trace2("TRANSIENT eventq", newtime
, _time1
);
430 newtime
= _sim
->_eq
.top();
431 assert( newtime
>= _time1
);
432 new_dt
= newtime
- reftime
;
433 if (new_dt
< _sim
->_dtmin
) {untested();
434 //new_dt = _sim->_dtmin;
435 //newtime = reftime + new_dt;
438 new_control
= scEVENTQ
;
439 fixed_time
= newtime
;
440 almost_fixed_time
= newtime
;
441 trace2("checking", reftime
, newtime
);
443 }else if ( !_sim
->_eq
.empty() ) {
444 trace2("TRANSIENT skipping non empty eq", _time1
, _sim
->_eq
.top() );
446 trace0("TRANSIENT no events pending");
448 // device events that may not happen
449 // not sure of exact time. will be rescheduled if wrong.
450 // ok to move by _sim->_dtmin. time is not that accurate anyway.
451 trace1("next ambevt", _time_by_ambiguous_event
);
452 if (_time_by_ambiguous_event
< newtime
- _sim
->_dtmin
) {
453 if (_time_by_ambiguous_event
< _time1
+ 2*_sim
->_dtmin
) {untested();
454 double mintime
= _time1
+ 2*_sim
->_dtmin
;
455 if (newtime
- _sim
->_dtmin
< mintime
) {untested();
457 new_control
= scAMBEVENT
;
461 newtime
= _time_by_ambiguous_event
;
462 new_control
= scAMBEVENT
;
464 new_dt
= newtime
- reftime
;
465 almost_fixed_time
= newtime
;
470 // device error estimates
471 if (_time_by_error_estimate
< newtime
- _sim
->_dtmin
) {
472 newtime
= _time_by_error_estimate
;
473 new_dt
= newtime
- reftime
;
476 trace3("TRANSIENT::next err", newtime
, new_dt
, _time_by_error_estimate
);
478 trace3("TRANSIENT::next", newtime
, new_dt
, _time_by_error_estimate
);
482 if (new_dt
> _dtmax
) {
483 if (new_dt
> _dtmax
+ _sim
->_dtmin
) {
484 new_control
= scSKIP
;
488 newtime
= reftime
+ new_dt
;
489 assert(newtime
<= _time_by_user_request
);
494 // converged but with more iterations than we like
495 if ((new_dt
> (old_dt
+ _sim
->_dtmin
) * OPT::trstephold
)
496 && _sim
->exceeds_iteration_limit(OPT::TRLOW
)) { untested();
498 new_dt
= old_dt
* OPT::trstephold
;
499 newtime
= reftime
+ new_dt
;
500 new_control
= scITER_A
;
506 if (_sim
->analysis_is_tran_dynamic() && new_dt
> old_dt
* OPT::trstepgrow
) { untested();
507 new_dt
= old_dt
* OPT::trstepgrow
;
508 newtime
= reftime
+ new_dt
;
515 if (newtime
< almost_fixed_time
) {
517 if (newtime
< _sim
->_time0
) {
518 assert(reftime
== _time1
);
519 assert(reftime
< _sim
->_time0
); // not moving forward
520 // try to pick a step that will end up repeating the rejected step
521 // with an integer number of same size steps
522 double target_dt
= _sim
->_time0
- reftime
;
523 assert(target_dt
> new_dt
);
524 double steps
= 1 + floor((target_dt
- _sim
->_dtmin
) / new_dt
);
526 new_dt
= target_dt
/ steps
;
527 newtime
= reftime
+ new_dt
;
529 }else if (newtime
> reftime
+ old_dt
*.8
530 && newtime
< reftime
+ old_dt
*1.5
531 && reftime
+ old_dt
<= almost_fixed_time
) {
532 // new_dt is close enough to old_dt.
533 // use old_dt, to avoid a step change.
534 old_dt
= max(_sim
->_dtmin
,old_dt
); // eliminate numerical noise to pass assertion
535 assert(reftime
== _sim
->_time0
); // moving forward
536 assert(reftime
> _time1
);
538 newtime
= reftime
+ new_dt
;
539 if (newtime
> almost_fixed_time
) { untested();
540 new_control
= scAMBEVENT
;
541 newtime
= almost_fixed_time
;
542 new_dt
= newtime
- reftime
;
545 trace4("TRANSIENT::next quantized", new_dt
, _sim
->_dtmin
, _sim
->_dtmin
-new_dt
, new_control
);
548 // There will be a step change.
549 // Try to choose one that we will keep for a while.
550 // Choose new_dt to be in integer fraction of target_dt.
551 assert(reftime
== _sim
->_time0
); // moving forward
552 if(reftime
<= _time1
){ unreachable();
553 // this is a weird bug.
557 double target_dt
= fixed_time
- reftime
;
558 assert(target_dt
>= new_dt
);
559 double steps
= 1 + floor((target_dt
- _sim
->_dtmin
) / new_dt
);
561 new_dt
= target_dt
/ steps
;
562 trace3("TRANSIENT::next step change", reftime
, new_dt
, reftime
+new_dt
);
563 newtime
= reftime
+ new_dt
;
567 assert(newtime
== almost_fixed_time
);
570 // trap time step too small
571 if (!_accepted
&& new_dt
< _sim
->_dtmin
) { untested();
572 new_dt
= _sim
->_dtmin
;
573 newtime
= reftime
+ new_dt
;
574 new_control
= scSMALL
;
579 // if all that makes it close to user_requested, make it official
580 if (up_order(newtime
-_sim
->_dtmin
, _time_by_user_request
, newtime
+_sim
->_dtmin
)) {
581 //newtime = _time_by_user_request;
582 //new_dt = newtime - reftime;
583 new_control
= scUSER
;
585 } // end of else converged
587 set_step_cause(new_control
);
589 trace4("TRANSIENT::next got it i think", newtime
, new_control
, newtime
-_sim
->_time0
, _time_by_user_request
);
591 /* check to be sure */
592 if (newtime
< _time1
+ _sim
->_dtmin
) {
593 /* It's really bad. */
594 /* Reject the most recent step, back up as much as possible, */
595 /* and creep along */
596 trace3("TRANSIENT::next ", newtime
, _time1
, _sim
->_dtmin
);
598 assert(step_cause() < scREJECT
);
599 assert(step_cause() >= 0);
600 error(bDANGER
,"non-recoverable: " + TR::step_cause
[step_cause()] + "\n");
601 error(bDANGER
, "newtime=%e rejectedtime=%e oldtime=%e using=%e\n",
602 newtime
, _sim
->_time0
, _time1
, _time1
+ _sim
->_dtmin
);
603 newtime
= _time1
+ _sim
->_dtmin
;
604 assert(newtime
<= _time_by_user_request
);
605 set_step_cause(scSMALL
);
606 //check_consistency2();
607 throw Exception("tried everything, still doesn't work, giving up");
608 }else if (newtime
< _sim
->_time0
) {
609 /* Reject the most recent step. */
610 /* We have faith that it will work with a smaller time step. */
612 assert(newtime
>= _time1
+ _sim
->_dtmin
);
613 error(bLOG
, "backwards time step\n");
614 error(bLOG
, "newtime=%e rejectedtime=%e oldtime=%e\n", newtime
, _sim
->_time0
, _time1
);
615 set_step_cause(scREJECT
);
616 _sim
->mark_inc_mode_bad();
617 check_consistency2();
619 }else if (_sim
->_time0
>= _time_by_user_request
) {
620 trace3("TRANSIENT::next: already there", _sim
->_time0
, _time1
, newtime
);
621 _time1
= _sim
->_time0
;
623 check_consistency2();
625 }else if (newtime
< _sim
->_time0
+ _sim
->_dtmin
) { untested();
626 /* Another evaluation at the same time. */
627 /* Keep the most recent step, but creep along. */
628 assert(newtime
> _sim
->_time0
- _sim
->_dtmin
);
629 error(bDANGER
, "zero time step\n");
630 error(bDANGER
, "newtime=%e rejectedtime=%e delta=%e time1=%e requested=%e dtmin=%e, control=%d\n",
631 newtime
, _sim
->_time0
, newtime
-_sim
->_time0
, _time1
, _time_by_user_request
, _sim
->_dtmin
, step_cause());
632 if (_accepted
) {untested();
633 _time1
= _sim
->_time0
;
637 trace3( "TRANSIENT::next:", newtime
, _time1
, new_dt
);
638 check_consistency2();
639 newtime
= _sim
->_time0
+ _sim
->_dtmin
;
640 if (newtime
> _time_by_user_request
) { untested();
641 newtime
= _time_by_user_request
;
642 set_step_cause(scUSER
);
645 assert (newtime
<=_tstop
);
646 set_step_cause(scZERO
);
647 check_consistency2();
650 assert(newtime
>= _sim
->_time0
+ _sim
->_dtmin
);
651 /* All is OK. Moving on. */
652 /* Keep value of newtime */
653 _time1
= _sim
->_time0
;
654 check_consistency2();
656 _sim
->_time0
= newtime
;
657 assert(_sim
->_time0
<= _time_by_user_request
);
659 /* advance event queue (maybe) */
660 /* We already looked at it. Dump what's on top if we took it. */
664 while (!_sim
->_eq
.empty() && _sim
->_eq
.top() <= _sim
->_time0
) {
665 trace1("eq", _sim
->_eq
.top());
668 while (!_sim
->_eq
.empty() && _sim
->_eq
.top() < _sim
->_time0
+ _sim
->_dtmin
) {
669 trace1("eq-extra", _sim
->_eq
.top());
673 // event queue cleanup moved....
674 //BUG// what if it is later rejected? It's lost!
675 // -> why not move to tr_advance? tr_accept? hmmm
678 if(_time1
< _tstop
- _sim
->_dtmin
679 && _sim
->_time0
> _tstop
+ _sim
->_dtmin
) {
680 _sim
->_time0
= _tstop
;
681 check_consistency2();
683 check_consistency2();
685 assert(_sim
->_time0
<= _time_by_user_request
);
687 check_consistency2();
689 ::status
.review
.stop();
690 bool ret
= _sim
->_time0
<= _tstop
; // throw away last step if it helps. + _sim->_dtmin;
691 ret
= _sim
->_time0
< _tstop
+ _sim
->_dtmin
; // this once worked
692 if(_accepted
&& _edge_break
){
693 trace3("accepted edge", _sim
->_time0
, _time1
, _sim
->_time0
- _time1
);
695 }else if(_edge_break
){
696 trace5("unaccepted edge", _sim
->_time0
, _sim
->v0dist_min(), _time1
, _time_by_ambiguous_event
, STEP_CAUSE(step_cause()));
701 /*--------------------------------------------------------------------------*/
702 bool TRANSIENT::review()
704 ::status
.review
.start();
705 _sim
->count_iterations(iTOTAL
);
707 TIME_PAIR time_by
= CARD_LIST::card_list
.tr_review();
708 _time_by_error_estimate
= time_by
._error_estimate
;
709 _time_by_ambiguous_event
= time_by
._event
;
712 double dt0
= _sim
->_time0
- _time1
;
713 trace3("review times", _sim
->_time0
, dt0
, _time1
);
715 // fixme: move to a component (?)... maybe later.
716 if (_sim
->_time0
== 0.){
717 }else if (dt0
== 0. ){
718 }else if (_sim
->_time0
< _tstop
* .2){
720 }else if (_edge_detect
& edEVT
){
722 double dt_factor
= _sim
->v0dist_min(&dist
);
723 double dt_by_edge
= dt_factor
* dt0
;
724 // if(dt_by_edge < 0. && dtedge1 > 0){ untested();
725 // dt_by_edge = (dt_by_edge + dtedge1)*.5;
728 double time_by_edge
= dt_by_edge
+ _time1
;
729 trace4("edge", time_by_edge
, _sim
->_time0
, dt_by_edge
, dist
);
732 time_by_edge
= NEVER
;
733 }else if(fabs(dt_by_edge
) > 10 * fabs(_dt_by_edge1
)){
734 time_by_edge
= NEVER
;
735 }else if(_dt_by_edge1
< 0.){
736 time_by_edge
= NEVER
;
737 }else if(_dt_by_edge1
< dt0
){
738 time_by_edge
= NEVER
;
740 }else if(dt_by_edge
< 0. && _dt_by_edge1
> 0. ){
741 trace3("negative", dt_by_edge
, _sim
->_time0
, _dt_by_edge1
);
742 time_by_edge
= _time1
+ dt0
* .3;
743 _edge_break
= _edge_detect
& edBREAK
;
744 }else if(dt_by_edge
< 0. ){ untested();
745 time_by_edge
= _sim
->_dt0
* .5 + _time1
;
746 }else if(dt_by_edge
< dt0
&& _dt_by_edge1
> dt0
){
747 trace4("got edge", dt_by_edge
, _sim
->_time0
, _dt_by_edge1
, dt_factor
);
748 _edge_break
= _edge_detect
& edBREAK
; // edge between time0 and time1.
749 // if it gets accepted, we are done
750 // time_by_edge = dt_by_edge * .5 + _time1;
751 }else if(dt_by_edge
> dt0
){
752 // everything fine. edge is far ahead.
753 }else if(dt_by_edge
+ _sim
->_dtmin
> dt0
&& _dt_by_edge1
> dt0
){ untested();
754 trace4("close to edge", dt0
, dt_by_edge
, _sim
->_time0
, _dt_by_edge1
);
755 _edge_break
= _edge_detect
& edBREAK
; // edge close enogh
756 }else if(dt_by_edge
< dt0
){ untested();
758 time_by_edge
= NEVER
;
761 if(!(_edge_detect
& edEVT
)){ untested();
762 }else if(time_by_edge
< _time_by_ambiguous_event
){
763 trace5("setting evt", time_by_edge
, _sim
->_time0
, dt_by_edge
, _time_by_ambiguous_event
, dt_by_edge
/ _sim
->_dtmin
);
764 _time_by_ambiguous_event
= time_by_edge
;
768 _dt_by_edge0
= dt_by_edge
;
771 // limit minimum time step
772 // 2*_sim->_dtmin because _time[1] + _sim->_dtmin might be == _time[0].
773 if (_time_by_ambiguous_event
< _time1
+ 2*_sim
->_dtmin
) {
774 _time_by_ambiguous_event
= _time1
+ 2*_sim
->_dtmin
;
777 // force advance when time too close to previous
778 if (std::abs(_time_by_ambiguous_event
- _sim
->_time0
) < 2*_sim
->_dtmin
) {
779 _time_by_ambiguous_event
= _sim
->_time0
+ 2*_sim
->_dtmin
;
783 if (time_by
._error_estimate
< _time1
+ 2*_sim
->_dtmin
) {
784 _time_by_error_estimate
= _time1
+ 2*_sim
->_dtmin
;
786 _time_by_error_estimate
= time_by
._error_estimate
;
788 if (std::abs(_time_by_error_estimate
- _sim
->_time0
) < 1.1*_sim
->_dtmin
) {
789 _time_by_error_estimate
= _sim
->_time0
+ 1.1*_sim
->_dtmin
;
793 ::status
.review
.stop();
795 return (_time_by_error_estimate
> _sim
->_time0
&& _time_by_ambiguous_event
> _sim
->_time0
);
797 /*--------------------------------------------------------------------------*/
798 void TRANSIENT::accept()
800 ::status
.accept
.start();
801 for (unsigned ii
= _sim
->_lu
.size(); ii
>= 1; --ii
) {
802 _sim
->_nstat
[ii
].set_discont(disNONE
);
805 _dt_by_edge1
= _dt_by_edge0
;
808 while (!_sim
->_eq
.empty() && _sim
->_eq
.top() < _sim
->_time0
+ _sim
->_dtmin
) {itested();
809 trace1("TRANSIENT::accept eq-pop-extra", _sim
->_eq
.top());
814 trace2("TRANSIENT::accept dt0", _sim
->_dt0
, _sim
->_time0
- _time1
);
815 _sim
->_dt0
= _sim
->_time0
- _time1
;
816 if(_sim
->_dt0
<=0) assert (_sim
->_stepno
== 0);
818 if (OPT::traceload
) { // traceload == "use queue"
819 while (!_sim
->_acceptq
.empty()) {
820 trace1("TRANSIENT::accept", _sim
->_acceptq
.back()->long_label());
821 _sim
->_acceptq
.back()->tr_accept();
822 _sim
->_acceptq
.pop_back();
825 _sim
->_acceptq
.clear();
826 CARD_LIST::card_list
.tr_accept();
828 // tmp hack don't know yet how to fix (always_q_for_accept?)
829 ADP_LIST::adp_list
.tr_accept();
832 if( _sim
->analysis_is_tt() || OPT::trage
) {
833 trace0( "TRANSIENT::accept: done stressing cardlist");
836 CARD_LIST::card_list
.do_forall( &CARD::do_tt
);
840 while (!_sim
->_eq
.empty() && _sim
->_eq
.top() <= _sim
->_time0
) {
841 trace1("eq", _sim
->_eq
.top());
845 _sim
->_nstat
[0].set_discont(disNONE
);
846 ::status
.accept
.stop();
848 /*--------------------------------------------------------------------------*/
849 void TRANSIENT::reject()
851 ::status
.accept
.start();
852 _sim
->_acceptq
.clear();
854 ::status
.accept
.stop();
856 /*--------------------------------------------------------------------------*/
857 /*--------------------------------------------------------------------------*/
858 // vim:ts=8:sw=2:noet: