2 #ifndef SYDEVS_SYSTEMS_SIMULATION_H_
3 #define SYDEVS_SYSTEMS_SIMULATION_H_
72 template<
typename Node>
136 void process_initialization_event();
137 void process_planned_event();
138 void process_finalization_event();
157 template<
typename Node>
161 , can_end_early_(can_end_early)
162 , external_context_(start_t, seed, stream)
169 , top(
"top", external_context_)
175 template<
typename Node>
178 , end_t_(total_dt.finite() ?
time_point() + total_dt :
180 , can_end_early_(!total_dt.finite())
181 , external_context_(start_t_, seed, stream)
188 , top(
"top", external_context_)
194 template<
typename Node>
201 template<
typename Node>
208 template<
typename Node>
211 return can_end_early_;
215 template<
typename Node>
222 template<
typename Node>
229 template<
typename Node>
236 template<
typename Node>
239 return const_cast<node_context&
>(external_context_).event_time();
243 template<
typename Node>
246 return t_queue_.imminent_duration();
250 template<
typename Node>
256 process_initialization_event();
259 process_planned_event();
264 process_finalization_event();
270 template<
typename Node>
273 int64 event_count = 0;
274 auto t = event_time().t();
275 while (!finished_ && event_time().t() == t) {
276 process_next_event();
283 template<
typename Node>
286 int64 event_count = 0;
287 while (!finished_ && event_time().t() < t) {
288 process_next_event();
295 template<
typename Node>
298 int64 event_count = 0;
300 process_next_event();
307 template<
typename Node>
314 template<
typename Node>
321 template<
typename Node>
322 inline discrete_event_time& simulation<Node>::event_time()
324 return external_context_.event_time();
328 template<
typename Node>
329 inline void simulation<Node>::validate()
331 static_assert(std::is_base_of<system_node, Node>::value,
"Node must inherit from system_node");
333 if (top_IO().flow_input_port_count() != 0 ||
334 top_IO().message_input_port_count() != 0 ||
335 top_IO().message_output_port_count() != 0 ||
336 top_IO().flow_output_port_count() != 0) {
337 throw std::invalid_argument(
"Node to be simulated must have no ports");
342 template<
typename Node>
343 inline void simulation<Node>::process_initialization_event()
346 top_IO().print_event(
"initialization");
348 event_timer_.start();
349 auto planned_dt = top.process_initialization_event();
351 top_IO().deactivate();
352 if (planned_dt.finite()) {
353 t_queue_.plan_event(0, planned_dt);
355 if (top.time_precision() !=
no_scale) {
356 t_cache_.retain_event(0, top.time_precision());
361 template<
typename Node>
362 inline void simulation<Node>::process_planned_event()
364 top_IO().print_event(
"planned");
366 if (top.time_precision() !=
no_scale) {
367 elapsed_dt = t_cache_.duration_since(0).fixed_at(top.time_precision());
370 event_timer_.start();
371 auto planned_dt = top.process_planned_event(elapsed_dt);
373 top_IO().deactivate();
374 if (planned_dt.finite()) {
375 t_queue_.plan_event(0, planned_dt);
378 t_queue_.pop_imminent_event(0);
380 if (top.time_precision() !=
no_scale) {
381 t_cache_.retain_event(0, top.time_precision());
386 template<
typename Node>
387 inline void simulation<Node>::process_finalization_event()
389 top_IO().print_event(
"finalization");
391 if (top.time_precision() !=
no_scale) {
392 elapsed_dt = t_cache_.duration_since(0).fixed_at(top.time_precision());
395 event_timer_.start();
396 top.process_finalization_event(elapsed_dt);
398 top_IO().deactivate();
403 template<
typename Node>
404 inline void simulation<Node>::advance_time()
407 auto planned_dt = t_queue_.imminent_duration();
408 if (planned_dt.finite() || !can_end_early_) {
410 event_time().advance(planned_dt, end_t_);
411 if (planned_dt > 0
_s) {
413 external_context_.time_printed() =
false;
414 t_queue_.advance_time(event_time().t());
415 t_cache_.advance_time(event_time().t());
417 if (event_time().t() >= end_t_) {
const auto output
Equivalent to data_goal::output.
Definition: data_goal.h:22
const auto input
Equivalent to data_goal::input.
Definition: data_goal.h:21
bool can_end_early() const
Returns true if the simulation can end before the specified end time.
Definition: simulation.h:209
A data structure which represents progress through a simulation, encapsulating both simulated time an...
Definition: discrete_event_time.h:36
virtual ~simulation()=default
Destructor.
Node top
The topmost system node.
Definition: simulation.h:153
const time_point & end_time() const
Returns the end time of the simulation.
Definition: simulation.h:202
constexpr scale no_scale
Definition: scale.h:153
bool finishing() const
Returns true if all events are finished except finalization.
Definition: simulation.h:223
A class for measuring and accumulating intervals of wallclock time.
Definition: timer.h:24
constexpr auto _s
Definition: units.h:128
int64 process_next_events()
Runs all events until simulated time advances; returns the number of processed events.
Definition: simulation.h:271
A data structure which provides durations elapsed since past events.
Definition: time_cache.h:27
int64 process_remaining_events()
Runs simulation until completion; returns the number of processed events.
Definition: simulation.h:296
int64 process_events_until(const time_point &t)
Runs all events until simulated time advances at least to t; returns the number of processed events...
Definition: simulation.h:284
A data type which represents the general concept of scale as a dimensionless power of 1000...
Definition: scale.h:70
const time_point & start_time() const
Returns the start time of the simulation.
Definition: simulation.h:195
bool finished() const
Returns true if the simulation has finished.
Definition: simulation.h:230
const discrete_event_time & time() const
Returns the current point in discrete event time.
Definition: simulation.h:237
A data structure which represents a point in time as an arbitrary-precision multiple of its shortest ...
Definition: time_point.h:84
const timer & event_timer() const
Returns the object that accumulated wallclock event durations.
Definition: simulation.h:308
duration imminent_duration() const
Returns the duration until the imminent event.
Definition: simulation.h:244
A data structure which supports the scheduling of future events.
Definition: time_queue.h:34
A class template for running simulations.
Definition: simulation.h:73
Definition: node_context.h:16
Definition: node_interface.h:16
bool started() const
Returns true if the simulation has started.
Definition: simulation.h:216
const auto flow
Equivalent to data_mode::flow.
Definition: data_mode.h:22
quantity< seconds > duration
Definition: quantity.h:1006
const auto message
Equivalent to data_mode::message.
Definition: data_mode.h:23
void process_next_event()
Runs the next event of the topmost system node.
Definition: simulation.h:251
simulation & operator=(const simulation &)=delete
No copy assignment.
simulation(const time_point &start_t, const time_point &end_t, bool can_end_early, int64 seed, std::ostream &stream)
Constructs a simulation with the full set of configuration options.
Definition: simulation.h:158