Version: SMASH-1.7
clock.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2018
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_CLOCK_H_
11 #define SRC_INCLUDE_CLOCK_H_
12 
13 #include <algorithm>
14 #include <cmath>
15 #include <cstdint>
16 #include <cstdio>
17 #include <limits>
18 #include <stdexcept>
19 
20 #include "logging.h"
21 
22 namespace smash {
23 
68 class Clock {
69  public:
71  using Representation = std::int64_t;
73  virtual double timestep_duration() const = 0;
75  virtual double current_time() const = 0;
77  virtual double next_time() const = 0;
85  virtual void reset(double start_time, const bool is_output_clock) = 0;
93  virtual void remove_times_in_past(double start_time) = 0;
102  // guard against overflow:
103  if (counter_ >= std::numeric_limits<Representation>::max() - 1) {
104  throw std::overflow_error("Too many timesteps, clock overflow imminent");
105  }
106  ++counter_;
107  return *this;
108  }
109 
118  Clock& operator+=(Representation advance_several_timesteps) {
119  if (counter_ >= std::numeric_limits<Representation>::max() -
120  advance_several_timesteps) {
121  throw std::overflow_error("Too many timesteps, clock overflow imminent");
122  }
123  counter_ += advance_several_timesteps;
124  return *this;
125  }
126 
132  bool operator<(const Clock& rhs) const {
133  return current_time() < rhs.current_time();
134  }
135 
141  bool operator<(double time) const { return current_time() < time; }
142 
148  bool operator>(double time) const { return current_time() > time; }
149 
150  virtual ~Clock() = default;
151 
152  protected:
157 };
158 
170 class UniformClock : public Clock {
183  static constexpr double resolution = 0.000001;
184 
185  public:
187  UniformClock() = default;
194  UniformClock(const double time, const double dt)
195  : timestep_duration_(convert(dt)), reset_time_(convert(time)) {
196  if (dt < 0.) {
197  throw std::range_error("No negative time increment allowed");
198  }
199  }
201  double current_time() const override {
202  return convert(reset_time_ + timestep_duration_ * counter_);
203  }
211  double next_time() const override {
212  if (counter_ * timestep_duration_ >=
213  std::numeric_limits<Representation>::max() - timestep_duration_) {
214  throw std::overflow_error("Too many timesteps, clock overflow imminent");
215  }
216  return convert(reset_time_ + timestep_duration_ * (counter_ + 1));
217  }
219  double timestep_duration() const override {
220  return convert(timestep_duration_);
221  }
227  void set_timestep_duration(const double dt) {
228  if (dt < 0.) {
229  throw std::range_error("No negative time increment allowed");
230  }
231  reset_time_ += timestep_duration_ * counter_;
232  counter_ = 0;
233  timestep_duration_ = convert(dt);
234  }
235 
242  void reset(const double start_time, const bool is_output_clock) override {
243  double reset_time;
244  if (is_output_clock) {
245  reset_time =
246  std::floor(start_time / timestep_duration()) * timestep_duration();
247  } else {
248  reset_time = start_time;
249  }
250  if (reset_time < current_time()) {
251  logger<LogArea::Clock>().debug("Resetting clock from", current_time(),
252  " fm/c to ", reset_time, " fm/c");
253  }
254  reset_time_ = convert(reset_time);
255  counter_ = 0;
256  }
257 
258  void remove_times_in_past(double) override{};
259 
268  template <typename T>
269  typename std::enable_if<std::is_floating_point<T>::value, Clock&>::type
270  operator+=(T big_timestep) {
271  if (big_timestep < 0.) {
272  throw std::range_error("The clock cannot be turned back.");
273  }
274  reset_time_ += convert(big_timestep);
275  return *this;
276  }
285  Clock& operator+=(Representation advance_several_timesteps) {
286  if (counter_ >= std::numeric_limits<Representation>::max() -
287  advance_several_timesteps) {
288  throw std::overflow_error("Too many timesteps, clock overflow imminent");
289  }
290  counter_ += advance_several_timesteps;
291  return *this;
292  }
293 
294  private:
296  static constexpr double to_double = resolution;
298  static constexpr double from_double = 1. / resolution;
299 
301  static Representation convert(double x) {
302  return std::round(x * from_double);
303  }
305  static double convert(Representation x) { return x * to_double; }
306 
308  Representation timestep_duration_ = 0u;
310  Representation reset_time_ = 0;
311 };
312 
314 class CustomClock : public Clock {
315  public:
321  CustomClock(std::vector<double> times) : custom_times_(times) {
322  std::sort(custom_times_.begin(), custom_times_.end());
323  counter_ = -1;
324  }
329  double current_time() const override {
330  if (counter_ < 0) {
331  throw std::runtime_error("Trying to access undefined zeroth output time");
332  }
333  return custom_times_[counter_];
334  }
336  double next_time() const override { return custom_times_[counter_ + 1]; }
337  double timestep_duration() const override {
338  return next_time() - current_time();
339  }
340  void reset(double, bool) override { counter_ = -1; }
341 
347  void remove_times_in_past(double start_time) override {
348  std::remove_if(
349  custom_times_.begin(), custom_times_.end(), [start_time](double t) {
350  if (t <= start_time) {
351  logger<LogArea::Clock>().warn("Removing custom output time ", t,
352  " fm since it is earlier than the "
353  "starting time of the simulation");
354  return true;
355  } else {
356  return false;
357  }
358  });
359  }
360 
361  private:
363  std::vector<double> custom_times_;
364 };
365 } // namespace smash
366 
367 #endif // SRC_INCLUDE_CLOCK_H_
std::vector< double > custom_times_
Vector of times where output is generated.
Definition: clock.h:363
bool operator<(const Clock &rhs) const
Compares the times between two clocks.
Definition: clock.h:132
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:242
double current_time() const override
Definition: clock.h:201
Clock & operator+=(Representation advance_several_timesteps)
advances the clock by an arbitrary number of ticks.
Definition: clock.h:118
virtual double next_time() const =0
Representation counter_
Internally used to count the number of time steps.
Definition: clock.h:156
double timestep_duration() const override
Definition: clock.h:219
Clock with explicitly defined time steps.
Definition: clock.h:314
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:258
virtual double current_time() const =0
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:270
Clock & operator+=(Representation advance_several_timesteps)
advances the clock by an arbitrary number of ticks.
Definition: clock.h:285
static Representation convert(double x)
Convert a double x into the internal int representation.
Definition: clock.h:301
virtual ~Clock()=default
double timestep_duration() const override
Definition: clock.h:337
CustomClock(std::vector< double > times)
Initialises a custom clock with explicitly given output times.
Definition: clock.h:321
static double convert(Representation x)
Convert an internal int value x into the double representation.
Definition: clock.h:305
Clock & operator++()
Advances the clock by one tick.
Definition: clock.h:101
std::int64_t Representation
The type used for counting ticks/time.
Definition: clock.h:71
Clock tracks the time in the simulation.
Definition: clock.h:68
double next_time() const override
Definition: clock.h:336
double current_time() const override
Definition: clock.h:329
virtual void reset(double start_time, const bool is_output_clock)=0
reset the clock to the starting time of the simulation
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...
void set_timestep_duration(const double dt)
Sets the time step size (and resets the counter).
Definition: clock.h:227
Clock with uniformly spaced time steps.
Definition: clock.h:170
void remove_times_in_past(double start_time) override
Remove all custom times before start_time.
Definition: clock.h:347
double next_time() const override
Definition: clock.h:211
void reset(double, bool) override
reset the clock to the starting time of the simulation
Definition: clock.h:340
bool operator>(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:148
Definition: action.h:24
virtual double timestep_duration() const =0
bool operator<(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:141
UniformClock(const double time, const double dt)
Initialize with base time and time step size.
Definition: clock.h:194