Version: SMASH-1.8
clock.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2019
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 
24 static constexpr int LClock = LogArea::Clock::id;
25 
70 class Clock {
71  public:
73  using Representation = std::int64_t;
75  virtual double timestep_duration() const = 0;
77  virtual double current_time() const = 0;
79  virtual double next_time() const = 0;
87  virtual void reset(double start_time, const bool is_output_clock) = 0;
95  virtual void remove_times_in_past(double start_time) = 0;
104  // guard against overflow:
105  if (counter_ >= std::numeric_limits<Representation>::max() - 1) {
106  throw std::overflow_error("Too many timesteps, clock overflow imminent");
107  }
108  ++counter_;
109  return *this;
110  }
111 
120  Clock& operator+=(Representation advance_several_timesteps) {
121  if (counter_ >= std::numeric_limits<Representation>::max() -
122  advance_several_timesteps) {
123  throw std::overflow_error("Too many timesteps, clock overflow imminent");
124  }
125  counter_ += advance_several_timesteps;
126  return *this;
127  }
128 
134  bool operator<(const Clock& rhs) const {
135  return current_time() < rhs.current_time();
136  }
137 
143  bool operator<(double time) const { return current_time() < time; }
144 
150  bool operator>(double time) const { return current_time() > time; }
151 
152  virtual ~Clock() = default;
153 
154  protected:
159 };
160 
172 class UniformClock : public Clock {
185  static constexpr double resolution = 0.000001;
186 
187  public:
189  UniformClock() = default;
196  UniformClock(const double time, const double dt)
198  if (dt < 0.) {
199  throw std::range_error("No negative time increment allowed");
200  }
201  }
203  double current_time() const override {
205  }
213  double next_time() const override {
215  std::numeric_limits<Representation>::max() - timestep_duration_) {
216  throw std::overflow_error("Too many timesteps, clock overflow imminent");
217  }
219  }
221  double timestep_duration() const override {
222  return convert(timestep_duration_);
223  }
229  void set_timestep_duration(const double dt) {
230  if (dt < 0.) {
231  throw std::range_error("No negative time increment allowed");
232  }
234  counter_ = 0;
236  }
237 
244  void reset(const double start_time, const bool is_output_clock) override {
245  double reset_time;
246  if (is_output_clock) {
247  reset_time =
248  std::floor(start_time / timestep_duration()) * timestep_duration();
249  } else {
250  reset_time = start_time;
251  }
252  if (reset_time < current_time()) {
253  logg[LClock].debug("Resetting clock from", current_time(), " fm/c to ",
254  reset_time, " fm/c");
255  }
256  reset_time_ = convert(reset_time);
257  counter_ = 0;
258  }
259 
260  void remove_times_in_past(double) override{};
261 
270  template <typename T>
271  typename std::enable_if<std::is_floating_point<T>::value, Clock&>::type
272  operator+=(T big_timestep) {
273  if (big_timestep < 0.) {
274  throw std::range_error("The clock cannot be turned back.");
275  }
276  reset_time_ += convert(big_timestep);
277  return *this;
278  }
287  Clock& operator+=(Representation advance_several_timesteps) {
288  if (counter_ >= std::numeric_limits<Representation>::max() -
289  advance_several_timesteps) {
290  throw std::overflow_error("Too many timesteps, clock overflow imminent");
291  }
292  counter_ += advance_several_timesteps;
293  return *this;
294  }
295 
296  private:
298  static constexpr double to_double = resolution;
300  static constexpr double from_double = 1. / resolution;
301 
303  static Representation convert(double x) {
304  return std::round(x * from_double);
305  }
307  static double convert(Representation x) { return x * to_double; }
308 
313 };
314 
316 class CustomClock : public Clock {
317  public:
323  CustomClock(std::vector<double> times) : custom_times_(times) {
324  std::sort(custom_times_.begin(), custom_times_.end());
325  counter_ = -1;
326  }
331  double current_time() const override {
332  if (counter_ < 0) {
333  throw std::runtime_error("Trying to access undefined zeroth output time");
334  }
335  return custom_times_[counter_];
336  }
338  double next_time() const override { return custom_times_[counter_ + 1]; }
339  double timestep_duration() const override {
340  return next_time() - current_time();
341  }
342  void reset(double, bool) override { counter_ = -1; }
343 
349  void remove_times_in_past(double start_time) override {
350  std::remove_if(custom_times_.begin(), custom_times_.end(),
351  [start_time](double t) {
352  if (t <= start_time) {
353  logg[LClock].warn("Removing custom output time ", t,
354  " fm since it is earlier than the "
355  "starting time of the simulation");
356  return true;
357  } else {
358  return false;
359  }
360  });
361  }
362 
363  private:
365  std::vector<double> custom_times_;
366 };
367 } // namespace smash
368 
369 #endif // SRC_INCLUDE_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:298
smash::CustomClock::current_time
double current_time() const override
Definition: clock.h:331
smash::UniformClock::resolution
static constexpr double resolution
Defines the resolution of the clock (i.e.
Definition: clock.h:185
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:260
smash::LClock
static constexpr int LClock
Definition: clock.h:24
smash::Clock::operator>
bool operator>(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:150
smash::UniformClock::operator+=
Clock & operator+=(Representation advance_several_timesteps)
advances the clock by an arbitrary number of ticks.
Definition: clock.h:287
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:272
smash::CustomClock::timestep_duration
double timestep_duration() const override
Definition: clock.h:339
smash::UniformClock::UniformClock
UniformClock(const double time, const double dt)
Initialize with base time and time step size.
Definition: clock.h:196
smash::UniformClock::set_timestep_duration
void set_timestep_duration(const double dt)
Sets the time step size (and resets the counter).
Definition: clock.h:229
smash::Clock::counter_
Representation counter_
Internally used to count the number of time steps.
Definition: clock.h:158
smash::Clock::timestep_duration
virtual double timestep_duration() const =0
smash::UniformClock::current_time
double current_time() const override
Definition: clock.h:203
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:349
smash::UniformClock::timestep_duration
double timestep_duration() const override
Definition: clock.h:221
smash::UniformClock::timestep_duration_
Representation timestep_duration_
The time step size in $10^{-3}$ fm.
Definition: clock.h:310
smash::UniformClock::reset_time_
Representation reset_time_
The time of last reset (when counter_ was set to 0).
Definition: clock.h:312
smash::UniformClock::convert
static double convert(Representation x)
Convert an internal int value x into the double representation.
Definition: clock.h:307
smash::CustomClock::CustomClock
CustomClock(std::vector< double > times)
Initialises a custom clock with explicitly given output times.
Definition: clock.h:323
smash::UniformClock::convert
static Representation convert(double x)
Convert a double x into the internal int representation.
Definition: clock.h:303
smash::Clock::operator<
bool operator<(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:143
smash::Clock
Clock tracks the time in the simulation.
Definition: clock.h:70
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:213
smash::CustomClock::reset
void reset(double, bool) override
reset the clock to the starting time of the simulation
Definition: clock.h:342
smash::Clock::operator<
bool operator<(const Clock &rhs) const
Compares the times between two clocks.
Definition: clock.h:134
smash::Clock::operator+=
Clock & operator+=(Representation advance_several_timesteps)
advances the clock by an arbitrary number of ticks.
Definition: clock.h:120
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:365
smash::UniformClock
Clock with uniformly spaced time steps.
Definition: clock.h:172
smash::Clock::current_time
virtual double current_time() const =0
logging.h
smash::CustomClock
Clock with explicitly defined time steps.
Definition: clock.h:316
smash::CustomClock::next_time
double next_time() const override
Definition: clock.h:338
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:244
smash::Clock::Representation
std::int64_t Representation
The type used for counting ticks/time.
Definition: clock.h:73
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:300
smash::Clock::operator++
Clock & operator++()
Advances the clock by one tick.
Definition: clock.h:103