Version: SMASH-2.0
clock.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2020
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_CLOCK_H_
11 #define SRC_INCLUDE_SMASH_CLOCK_H_
12 
13 #include <algorithm>
14 #include <cmath>
15 #include <cstdint>
16 #include <cstdio>
17 #include <limits>
18 #include <stdexcept>
19 #include <vector>
20 
21 #include "logging.h"
22 
23 namespace smash {
24 
25 static constexpr int LClock = LogArea::Clock::id;
26 
71 class Clock {
72  public:
74  using Representation = std::int64_t;
76  virtual double timestep_duration() const = 0;
78  virtual double current_time() const = 0;
80  virtual double next_time() const = 0;
88  virtual void reset(double start_time, const bool is_output_clock) = 0;
96  virtual void remove_times_in_past(double start_time) = 0;
105  // guard against overflow:
106  if (counter_ >= std::numeric_limits<Representation>::max() - 1) {
107  throw std::overflow_error("Too many timesteps, clock overflow imminent");
108  }
109  ++counter_;
110  return *this;
111  }
112 
121  Clock& operator+=(Representation advance_several_timesteps) {
122  if (counter_ >= std::numeric_limits<Representation>::max() -
123  advance_several_timesteps) {
124  throw std::overflow_error("Too many timesteps, clock overflow imminent");
125  }
126  counter_ += advance_several_timesteps;
127  return *this;
128  }
129 
135  bool operator<(const Clock& rhs) const {
136  return current_time() < rhs.current_time();
137  }
138 
144  bool operator<(double time) const { return current_time() < time; }
145 
151  bool operator>(double time) const { return current_time() > time; }
152 
153  virtual ~Clock() = default;
154 
155  protected:
160 };
161 
173 class UniformClock : public Clock {
186  static constexpr double resolution = 0.000001;
187 
188  public:
190  UniformClock() = default;
197  UniformClock(const double time, const double dt)
199  if (dt < 0.) {
200  throw std::range_error("No negative time increment allowed");
201  }
202  }
204  double current_time() const override {
206  }
214  double next_time() const override {
216  std::numeric_limits<Representation>::max() - timestep_duration_) {
217  throw std::overflow_error("Too many timesteps, clock overflow imminent");
218  }
220  }
222  double timestep_duration() const override {
223  return convert(timestep_duration_);
224  }
230  void set_timestep_duration(const double dt) {
231  if (dt < 0.) {
232  throw std::range_error("No negative time increment allowed");
233  }
235  counter_ = 0;
237  }
238 
245  void reset(const double start_time, const bool is_output_clock) override {
246  double reset_time;
247  if (is_output_clock) {
248  reset_time =
249  std::floor(start_time / timestep_duration()) * timestep_duration();
250  } else {
251  reset_time = start_time;
252  }
253  if (reset_time < current_time()) {
254  logg[LClock].debug("Resetting clock from", current_time(), " fm/c to ",
255  reset_time, " fm/c");
256  }
257  reset_time_ = convert(reset_time);
258  counter_ = 0;
259  }
260 
261  void remove_times_in_past(double) override{};
262 
271  template <typename T>
272  typename std::enable_if<std::is_floating_point<T>::value, Clock&>::type
273  operator+=(T big_timestep) {
274  if (big_timestep < 0.) {
275  throw std::range_error("The clock cannot be turned back.");
276  }
277  reset_time_ += convert(big_timestep);
278  return *this;
279  }
288  Clock& operator+=(Representation advance_several_timesteps) {
289  if (counter_ >= std::numeric_limits<Representation>::max() -
290  advance_several_timesteps) {
291  throw std::overflow_error("Too many timesteps, clock overflow imminent");
292  }
293  counter_ += advance_several_timesteps;
294  return *this;
295  }
296 
297  private:
299  static constexpr double to_double = resolution;
301  static constexpr double from_double = 1. / resolution;
302 
304  static Representation convert(double x) {
305  return std::round(x * from_double);
306  }
308  static double convert(Representation x) { return x * to_double; }
309 
314 };
315 
317 class CustomClock : public Clock {
318  public:
324  explicit CustomClock(std::vector<double> times) : custom_times_(times) {
325  std::sort(custom_times_.begin(), custom_times_.end());
326  counter_ = -1;
327  }
332  double current_time() const override {
333  if (counter_ == -1) {
334  // current time before the first output should be the starting time
335  return start_time_;
336  } else if (counter_ < -1) {
337  throw std::runtime_error("Trying to access undefined zeroth output time");
338  } else {
339  return custom_times_[counter_];
340  }
341  }
343  double next_time() const override { return custom_times_[counter_ + 1]; }
344  double timestep_duration() const override {
345  return next_time() - current_time();
346  }
347  void reset(double start_time, bool) override {
348  counter_ = -1;
349  start_time_ = start_time;
350  }
351 
357  void remove_times_in_past(double start_time) override {
358  std::remove_if(custom_times_.begin(), custom_times_.end(),
359  [start_time](double t) {
360  if (t <= start_time) {
361  logg[LClock].warn("Removing custom output time ", t,
362  " fm since it is earlier than the "
363  "starting time of the simulation");
364  return true;
365  } else {
366  return false;
367  }
368  });
369  }
370 
371  private:
373  std::vector<double> custom_times_;
375  double start_time_ = 0.;
376 };
377 } // namespace smash
378 
379 #endif // SRC_INCLUDE_SMASH_CLOCK_H_
smash
Definition: action.h:24
smash::UniformClock::to_double
static constexpr double to_double
A multiplier transfering the internal integer to the real time.
Definition: clock.h:299
smash::CustomClock::current_time
double current_time() const override
Definition: clock.h:332
smash::UniformClock::resolution
static constexpr double resolution
Defines the resolution of the clock (i.e.
Definition: clock.h:186
smash::UniformClock::remove_times_in_past
void remove_times_in_past(double) override
Remove output times before the starting time of the simulation if this is a custom clock.
Definition: clock.h:261
smash::LClock
static constexpr int LClock
Definition: clock.h:25
smash::Clock::operator>
bool operator>(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:151
smash::UniformClock::operator+=
Clock & operator+=(Representation advance_several_timesteps)
advances the clock by an arbitrary number of ticks.
Definition: clock.h:288
smash::UniformClock::operator+=
std::enable_if< std::is_floating_point< T >::value, Clock & >::type operator+=(T big_timestep)
Advances the clock by an arbitrary timestep (multiple of 0.000001 fm/c).
Definition: clock.h:273
smash::CustomClock::timestep_duration
double timestep_duration() const override
Definition: clock.h:344
smash::UniformClock::UniformClock
UniformClock(const double time, const double dt)
Initialize with base time and time step size.
Definition: clock.h:197
smash::CustomClock::reset
void reset(double start_time, bool) override
reset the clock to the starting time of the simulation
Definition: clock.h:347
smash::UniformClock::set_timestep_duration
void set_timestep_duration(const double dt)
Sets the time step size (and resets the counter).
Definition: clock.h:230
smash::Clock::counter_
Representation counter_
Internally used to count the number of time steps.
Definition: clock.h:159
smash::Clock::timestep_duration
virtual double timestep_duration() const =0
smash::UniformClock::current_time
double current_time() const override
Definition: clock.h:204
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::Clock::remove_times_in_past
virtual void remove_times_in_past(double start_time)=0
Remove output times before the starting time of the simulation if this is a custom clock.
smash::CustomClock::remove_times_in_past
void remove_times_in_past(double start_time) override
Remove all custom times before start_time.
Definition: clock.h:357
smash::UniformClock::timestep_duration
double timestep_duration() const override
Definition: clock.h:222
smash::UniformClock::timestep_duration_
Representation timestep_duration_
The time step size in $10^{-3}$ fm.
Definition: clock.h:311
smash::UniformClock::reset_time_
Representation reset_time_
The time of last reset (when counter_ was set to 0).
Definition: clock.h:313
smash::UniformClock::convert
static double convert(Representation x)
Convert an internal int value x into the double representation.
Definition: clock.h:308
smash::CustomClock::CustomClock
CustomClock(std::vector< double > times)
Initialises a custom clock with explicitly given output times.
Definition: clock.h:324
smash::UniformClock::convert
static Representation convert(double x)
Convert a double x into the internal int representation.
Definition: clock.h:304
smash::Clock::operator<
bool operator<(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:144
smash::Clock
Clock tracks the time in the simulation.
Definition: clock.h:71
smash::Clock::reset
virtual void reset(double start_time, const bool is_output_clock)=0
reset the clock to the starting time of the simulation
smash::Clock::~Clock
virtual ~Clock()=default
smash::UniformClock::next_time
double next_time() const override
Definition: clock.h:214
smash::CustomClock::start_time_
double start_time_
Starting time of the simulation.
Definition: clock.h:375
smash::Clock::operator<
bool operator<(const Clock &rhs) const
Compares the times between two clocks.
Definition: clock.h:135
smash::Clock::operator+=
Clock & operator+=(Representation advance_several_timesteps)
advances the clock by an arbitrary number of ticks.
Definition: clock.h:121
smash::Clock::next_time
virtual double next_time() const =0
smash::CustomClock::custom_times_
std::vector< double > custom_times_
Vector of times where output is generated.
Definition: clock.h:373
smash::UniformClock
Clock with uniformly spaced time steps.
Definition: clock.h:173
smash::Clock::current_time
virtual double current_time() const =0
logging.h
smash::CustomClock
Clock with explicitly defined time steps.
Definition: clock.h:317
smash::CustomClock::next_time
double next_time() const override
Definition: clock.h:343
smash::UniformClock::reset
void reset(const double start_time, const bool is_output_clock) override
Resets the time to the starting time of an event.
Definition: clock.h:245
smash::Clock::Representation
std::int64_t Representation
The type used for counting ticks/time.
Definition: clock.h:74
smash::UniformClock::UniformClock
UniformClock()=default
default initializer: Timestep size is set to 0!
smash::UniformClock::from_double
static constexpr double from_double
A multiplier transfering the real time to the internal integer.
Definition: clock.h:301
smash::Clock::operator++
Clock & operator++()
Advances the clock by one tick.
Definition: clock.h:104