SIMLIB/C++  3.07
run.cc
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 //! \file run.cc Simulation control algorithm
3 //
4 // Copyright (c) 1991-2008 Petr Peringer
5 //
6 // This library is licensed under GNU Library GPL. See the file COPYING.
7 //
8 
9 //
10 // description: control of simulation
11 //
12 
13 
14 ////////////////////////////////////////////////////////////////////////////
15 // interface
16 ////////////////////////////////////////////////////////////////////////////
17 
18 #include "simlib.h"
19 #include "internal.h"
20 #include <cstdlib> // exit()
21 
22 
23 ////////////////////////////////////////////////////////////////////////////
24 // implementation
25 ////////////////////////////////////////////////////////////////////////////
26 
27 namespace simlib3 {
28 
30 
31 ////////////////////////////////////////////////////////////////////////////
32 // SIMLIB global variables ### move to extra module!!!
33 //
34 // SIMLIB_* --- internal variables
35 // [A-Z]* --- user-level variables
36 //
37 
38 
39 // time-related variables
40 double SIMLIB_StartTime; // time of simulation start
41 double SIMLIB_Time; // simulation time
42 double SIMLIB_NextTime; // next-event time
43 double SIMLIB_EndTime; // time of simulation end
44 
45 // read-only references to time variables
46 // ASSERTION: StartTime <= Time <= NextTime <= EndTime
47 const double & StartTime = SIMLIB_StartTime; // time of simulation start
48 const double & Time = SIMLIB_Time; // simulation time
49 const double & NextTime = SIMLIB_NextTime; // next-event time
50 const double & EndTime = SIMLIB_EndTime; // time of simulation end
51 
52 // current entity pointer
54 Entity *const &Current = SIMLIB_Current; // read-only reference
55 
56 // phase of simulation experiment
58 const SIMLIB_Phase_t & Phase = SIMLIB_Phase; // read-only reference
59 
60 // experiment counter
61 unsigned long SIMLIB_experiment_no = 0;
62 
63 ////////////////////////////////////////////////////////////////////////////
64 /// internal statistical information
66  Init();
67 }
69  StepCount = 0;
70  MinStep = -1;
71  MaxStep = -1;
72  EventCount = 0;
73  StartTime = -1;
74  EndTime = -1;
75 }
76 
79 
80 ////////////////////////////////////////////////////////////////////////////
81 // private module variables
82 
83 static bool StopFlag = false; // if set, stop simulation run
84 
85 ////////////////////////////////////////////////////////////////////////////
86 // support for Delay blocks (internal)
87 //
88 DEFINE_HOOK(Delay); // called in Run() and SampleDelays()
89 DEFINE_HOOK(DelayInit); // called in Init()
90 
91 // for explicit sampling
92 void SampleDelays() { // used at step-wise changes !!!###
94 }
95 
96 // ZDelays:
97 DEFINE_HOOK(ZDelayTimerInit); // called in Run()
98 
99 ////////////////////////////////////////////////////////////////////////////
100 // support for simulation interrupt (user-level)
101 //
102 DEFINE_HOOK(Break); // called in Run()
103 
104 void InstallBreak(void (*f)()) { // for user interface (in simlib.h)
105  INSTALL_HOOK( Break, f );
106 }
107 
108 ////////////////////////////////////////////////////////////////////////////
109 // support for Samplers (internal)
110 //
111 DEFINE_HOOK(SamplerAct); // called in Run()
112 DEFINE_HOOK(SamplerInit); // called in Init()
113 
114 
115 ////////////////////////////////////////////////////////////////////////////
116 // WUclear hook --- if non-empty WUlist, call init function
117 //
118 DEFINE_HOOK(WUclear); // should be in run.cc
119 
120 ////////////////////////////////////////////////////////////////////////////
121 // SIMLIB_WUClear --- remove all items in WaitUntil list
122 //
123 void SIMLIB_WUClear() // should be removed -- ise CALL_HOOK instead
124 {
125  CALL_HOOK(WUclear);
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////
129 // special WaitUntil processing
130 DEFINE_HOOK(WUget_next);
131 ////////////////////////////////////////////////////////////////////////////
132 // SIMLIB_DoActions --- central calling of interruptable procedures
133 // WARNING: SIMLIB_Current->_Run() should be called from this place only!
134 //
136 {
137  do {
138  SIMLIB_Current->_Run(); // perform event-dispatch
139  SIMLIB_Current = 0;
140  CALL_HOOK(WUget_next); // check and activate next in WUlist
141  }while( SIMLIB_Current != 0 );
142 }
143 
144 ////////////////////////////////////////////////////////////////////////////
145 // Stop --- break the simulation run, can continue with another run
146 //
147 void Stop()
148 {
149  Dprintf(("\n ********************* STOP *********************\n"));
150  if( SIMLIB_Phase != SIMULATION ) // if runs a simulation experiment
152  StopFlag = true;
153 }
154 
155 
156 ////////////////////////////////////////////////////////////////////////////
157 // Abort --- end of simulation program
158 //
159 void Abort()
160 {
161  Dprintf(("\n ********************* ABORT *********************\n"));
162  SIMLIB_Phase = ERROREXIT;
163  std::exit(1); // end of program, errorcode 1
164 }
165 
166 
167 ////////////////////////////////////////////////////////////////////////////
168 // SIMLIB_Init --- initialization of simulation system and some parts of
169 // model; some checks
170 // initialize:
171 // - Time, StartTime, EndTime
172 // - calendar (SQS)
173 // - WaitUntilList
174 // - existing continuous blocks, ...
175 // - Delay blocks
176 //
177 void SIMLIB_Init(double T0, double T1, unsigned version)
178 {
180  Dprintf(("\n\t ************************* Init(%g,%g) #%lu \n",
181  T0, T1, SIMLIB_experiment_no));
182  // first some checks
183  if(version != SIMLIB_version) { // check versions
184  Dprintf(("\n SIMLIB library version %x.%02x ",
185  SIMLIB_version >> 8, SIMLIB_version & 0xFF));
186  Dprintf((" SIMLIB header version %x.%02x \n",
187  version >> 8, version & 0xFF));
188  SIMLIB_error(InconsistentHeader); // exit program
189  }
190  if( SIMLIB_Phase == INITIALIZATION ) SIMLIB_error(TwiceInitError);
191  if( SIMLIB_Phase == SIMULATION ) SIMLIB_error(InitInRunError);
192  SIMLIB_Phase = INITIALIZATION;
193  /////////////////////////////////////////////////////////////////
196  if( T0 >= T1 ) SIMLIB_error(InitError);
197  /////////////////////////////////////////////////////////////////
198  // set simulation parameters
199  _SetTime(StartTime,T0);
200  _SetTime(Time,T0);
201  _SetTime(EndTime,T1);
202 
203 // set reasonable defaults for Step limits ???
204 // if not set by user first ### add flag to SetStep
205 // MaxStep = tend/100;
206 // MinStep = MaxStep/1000;
207 
208  // TODO: add SIMLIB_RunNumber++
209  // TODO: add real-time stderr/cerr output message for long computations?
210  // on-demand print of "RunNumber:Time ETArun:minutes" each minute?
211 
212  // ADD list of functions to call: (dynamically!, priority)
213  // something like atexit(): atInit, atRunStart, atRunEnd
214 
215  SQS::Clear(); // initialize calendar
216  SIMLIB_WUClear(); // initialize WaitUntilList
217  SIMLIB_ContinueInit(); // initialize status variables 1 ###
218 
219  CALL_HOOK(SamplerInit); // initialize all Samplers
220  CALL_HOOK(DelayInit); // initialize all Delays
221 
222 }
223 
224 
225 ////////////////////////////////////////////////////////////////////////////
226 // Run --- main simulation control
227 //
228 void Run() {
229  Dprintf(("\n\t ********** Run() --- START \n"));
230 
231  // first some checks
232  if( SIMLIB_Phase != INITIALIZATION )
233  SIMLIB_error(RunUseError); // bad use of Run()
234  if( NextTime < StartTime )
235  SIMLIB_internal_error(); // never reached
236 
237  // welcome to the SIMLIB simulation control algorithm :-)
238 
239  // initialize variables
240  SIMLIB_Phase = SIMULATION;
241  StopFlag = false; // flag for stop simulation
242 
243  SIMLIB_run_statistics.Init(); // initialize internal statistics
244  SIMLIB_run_statistics.StartTime = Time;
245 
246  // call init functions
247  SIMLIB_ContinueInit(); // initialize status variables 2 ###
248 
249  CALL_HOOK(ZDelayTimerInit); // activate all ZDelayTimers
250  CALL_HOOK(SamplerAct); // activate all Samplers
251  CALL_HOOK(Break); // user can stop simulation by any key?
252 
253 // TODO: try using special lowest priority end-event to stop simulation
254 // It should be simpler
255 
256  // main loop
257  while( Time < EndTime && !StopFlag ) {
258  int endFlag = NextTime > EndTime; // if no event at end time
259  if( endFlag )
260  _SetTime( NextTime, EndTime ); // limit NextTime to EndTime
261 
262  if( Time < NextTime ) { // no event at current Time
264  // there are integrators or status variables, so we enter
265  // -------------- CONTINUOUS SIMULATION ---------------
266  SIMLIB_ResetStatus = true; // don't use previous step buffers
267  // TODO: is it really needed always?
268  CALL_HOOK(Delay); // DELAY: sample input
269  while( Time < NextTime ) { // do continuous steps
270  // until scheduled event or end ...
271  IntegrationMethod::StepSim(); // *** continuous step ***
272 
273  SIMLIB_run_statistics.StepCount++; // some runtime statistics
274  if(SIMLIB_run_statistics.MinStep<0) {
275  SIMLIB_run_statistics.MinStep = StepSize;
276  SIMLIB_run_statistics.MaxStep = StepSize;
277  } else if(SIMLIB_run_statistics.MinStep>StepSize)
278  SIMLIB_run_statistics.MinStep = StepSize;
279  else if(SIMLIB_run_statistics.MaxStep<StepSize)
280  SIMLIB_run_statistics.MaxStep = StepSize;
281 
282  SIMLIB_DoConditions(); // perform state events
283  CALL_HOOK(Delay); // DELAY: sample input at each step
284  CALL_HOOK(Break); // user can stop simulation by any key?
285  // TODO: use signal handler, ^C=SIGINT
286  if(StopFlag)
287  break; // end of simulation run was required
288  // by a state-event
289  } // while continuous steps
290  // _SetTime( Time, NextTime ); // set next event activation time
291  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ should be in StepSim()
292  } else { // no integrators, status blocks, ...
293  _SetTime( Time, NextTime ); // set next event activation time
294  }
295  } // if (NextTime>Time)
296 
297  // assert(is event in Time OR end of simulation)
298  if( endFlag ) break; // end of simulation if no event at endtime
299  ///////////// (TODO: ###BUG? state-conditions can schedule!)
300 
301  while( Time >= NextTime && !StopFlag && !SQS::Empty() ) {
302  // there are events scheduled at current Time
303  // >= because of rounding errors
304  SIMLIB_Current = SQS::GetFirst(); // get first record from calendar
305  SIMLIB_DoActions(); // perform actions (see waitunti.cc)
306  SIMLIB_run_statistics.EventCount++; // internal statistics
307  // assert: SIMLIB_Current is NULL
308  CALL_HOOK(Break); // Callback: user can stop simulation by key or GUI
309  }
310  } // main loop
311  IntegrationMethod::IntegrationDone(); // terminate integration run
312  SQS::Clear(); // terminate all scheduled events/processes
313  SIMLIB_Phase = TERMINATION;
314  SIMLIB_run_statistics.EndTime = Time;
315  Dprintf(("\n\t ********** Run() --- END \n"));
316 }
317 
318 } // namespace
319 
const double SIMLIB_MAXTIME
maximum time (1e30 works for float, too)
Definition: simlib.h:148
void SIMLIB_error(const enum _ErrEnum N)
print error message and abort program
Definition: error.cc:38
double SIMLIB_NextTime
Definition: run.cc:42
const double & StepSize
actual integration step
Definition: intg.cc:48
void Stop()
stop current simulation run
Definition: run.cc:147
virtual void _Run() noexcept=0
run the Behavior() function
double SIMLIB_StartTime
Definition: run.cc:40
void SampleDelays()
Definition: run.cc:92
void Run()
run simulation experiment
Definition: run.cc:228
static void IntegrationDone(void)
Definition: simlib.h:1121
bool SIMLIB_ResetStatus
flag set if there is a need for integration method restart
Definition: intg.cc:86
void SIMLIB_DoConditions()
Definition: cond.cc:139
void Init()
initialize - used at the start of each Run()
Definition: run.cc:68
Implementation of class CalendarList interface is static - using global functions in SQS namespace...
Definition: algloop.cc:32
static bool isAny(void)
Definition: simlib.h:994
SIMLIB_statistics_t()
constructor runs SIMLIB_statistics_t::Init()
Definition: run.cc:65
void SIMLIB_DoActions()
Definition: run.cc:135
abstract base class for active entities (Process, Event) instances of derived classes provide Behavio...
Definition: simlib.h:375
DEFINE_HOOK(Delay)
Entity *const & Current
pointer to active (now running) entity
Definition: run.cc:54
static bool isAny(void)
Definition: simlib.h:1029
const double & Time
model time (is NOT the block)
Definition: run.cc:48
void SIMLIB_Init(double T0, double T1, unsigned version)
Definition: run.cc:177
static bool StopFlag
Definition: run.cc:83
const double & EndTime
time of simulation end
Definition: run.cc:50
static SIMLIB_statistics_t SIMLIB_run_statistics
Definition: run.cc:77
double SIMLIB_EndTime
Definition: run.cc:43
const SIMLIB_Phase_t & Phase
This variable contains the current phase of experiment (used for internal checking) ...
Definition: run.cc:58
Entity * GetFirst()
remove entity with minimum activation time
Definition: calendar.cc:1327
#define SIMLIB_internal_error()
Definition: internal.h:167
void InstallBreak(void(*f)())
InstallBreak — set function for checking if user breaks simulation.
Definition: run.cc:104
Internal header file for SIMLIB/C++.
void SIMLIB_ContinueInit()
Definition: intg.cc:125
const double & NextTime
next-event time
Definition: run.cc:49
double SIMLIB_Time
Definition: internal.h:209
static void StepSim(void)
step of numerical integration method
Definition: numint.cc:52
Main SIMLIB/C++ interface.
#define INSTALL_HOOK(name, function)
Definition: internal.h:255
SIMLIB_IMPLEMENTATION
Definition: algloop.cc:34
bool Empty()
empty calendar predicate
Definition: calendar.cc:1280
Entity * SIMLIB_Current
Definition: run.cc:53
#define _SetTime(t, x)
macro for simple assignement to internal time variables
Definition: internal.h:228
SIMLIB_Phase_t
values indicate current phase of experiment
Definition: internal.h:76
unsigned long SIMLIB_experiment_no
Definition: run.cc:61
SIMLIB_Phase_t SIMLIB_Phase
Definition: run.cc:57
#define CALL_HOOK(name)
Definition: internal.h:278
continuous signal delay block
Definition: delay.h:26
#define Dprintf(f)
Definition: internal.h:100
const double SIMLIB_MINTIME
minimal time value
Definition: simlib.h:147
void SIMLIB_WUClear()
Definition: run.cc:123
const SIMLIB_statistics_t & SIMLIB_statistics
interface to internal run-time statistics structure
Definition: run.cc:78
void Abort()
end simulation program
Definition: run.cc:159
internal statistics structure contains basic statistics of simulator execution
Definition: simlib.h:1801
const double & StartTime
time of simulation start
Definition: run.cc:47
const unsigned SIMLIB_version
library version
Definition: version.cc:9
void Clear()
remove all scheduled entities
Definition: calendar.cc:1346