Version: SMASH-1.5
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 <cmath>
14 #include <cstdint>
15 #include <cstdio>
16 #include <limits>
17 #include <stdexcept>
18 
19 #include "logging.h"
20 
21 namespace smash {
22 
75 class Clock {
88  static constexpr double resolution = 0.000001;
89 
90  public:
92  using Representation = std::int64_t;
93 
94  public:
96  Clock() = default;
103  Clock(const double time, const double dt)
105  if (dt < 0.) {
106  throw std::range_error("No negative time increment allowed");
107  }
108  }
110  double current_time() const {
112  }
120  double next_time() const {
122  std::numeric_limits<Representation>::max() - timestep_duration_) {
123  throw std::overflow_error("Too many timesteps, clock overflow imminent");
124  }
126  }
128  double timestep_duration() const { return convert(timestep_duration_); }
134  void set_timestep_duration(const double dt) {
135  if (dt < 0.) {
136  throw std::range_error("No negative time increment allowed");
137  }
139  counter_ = 0;
141  }
158  bool multiple_is_in_next_tick(const double interval) const {
159  if (interval < 0.) {
160  throw std::range_error("Negative interval makes no sense for clock");
161  }
162  const Representation int_interval = convert(interval);
163  // if the interval is less than or equal to the time step size, one
164  // multiple will surely be within the next tick!
165  if (int_interval <= timestep_duration_) {
166  return true;
167  }
168  const auto next = reset_time_ + timestep_duration_ * counter_;
169  if (unlikely(next < 0)) {
170  return -next % int_interval < timestep_duration_;
171  }
172  return (timestep_duration_ - 1 + next) % int_interval < timestep_duration_;
173  }
182  double next_multiple(const double interval) const {
183  const Representation int_interval = convert(interval);
184  const auto current = reset_time_ + timestep_duration_ * counter_;
185  if (unlikely(current < 0)) {
186  return convert(current / int_interval * int_interval);
187  }
188  return convert((current / int_interval + 1) * int_interval);
189  }
195  void end_tick_on_multiple(const double interval) {
196  const Representation int_interval = convert(interval);
197  const auto current = reset_time_ + timestep_duration_ * counter_;
198  reset_time_ = current;
199  counter_ = 0;
200  if (unlikely(current < 0)) {
201  timestep_duration_ = current / int_interval * int_interval - current;
202  } else {
204  (current / int_interval + 1) * int_interval - current;
205  }
206  }
216  void reset(const double reset_time) {
217  if (reset_time < current_time()) {
218  logger<LogArea::Clock>().debug("Resetting clock from", current_time(),
219  " fm/c to ", reset_time, " fm/c");
220  }
221  reset_time_ = convert(reset_time);
222  counter_ = 0;
223  }
232  // guard against overflow:
233  if (counter_ >= std::numeric_limits<Representation>::max() - 1) {
234  throw std::overflow_error("Too many timesteps, clock overflow imminent");
235  }
236  ++counter_;
237  return *this;
238  }
247  template <typename T>
248  typename std::enable_if<std::is_floating_point<T>::value, Clock&>::type
249  operator+=(T big_timestep) {
250  if (big_timestep < 0.) {
251  throw std::range_error("The clock cannot be turned back.");
252  }
253  reset_time_ += convert(big_timestep);
254  return *this;
255  }
264  Clock& operator+=(Representation advance_several_timesteps) {
265  if (counter_ >= std::numeric_limits<Representation>::max() -
266  advance_several_timesteps) {
267  throw std::overflow_error("Too many timesteps, clock overflow imminent");
268  }
269  counter_ += advance_several_timesteps;
270  return *this;
271  }
277  bool operator<(const Clock& rhs) const {
279  (rhs.reset_time_ + rhs.timestep_duration_ * rhs.counter_);
280  }
286  bool operator<(double time) const { return current_time() < time; }
292  bool operator>(double time) const { return current_time() > time; }
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 
316 };
317 
318 } // namespace smash
319 
320 #endif // SRC_INCLUDE_CLOCK_H_
void reset(const double reset_time)
Resets the time to a pre-defined value reset_time.
Definition: clock.h:216
bool operator<(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:286
Clock & operator+=(Representation advance_several_timesteps)
advances the clock by an arbitrary number of ticks.
Definition: clock.h:264
double timestep_duration() const
Definition: clock.h:128
Representation counter_
Clock tick.
Definition: clock.h:311
Representation timestep_duration_
The time step size in $10^{-3}$ fm.
Definition: clock.h:313
static double convert(Representation x)
Convert an internal int value x into the double representation.
Definition: clock.h:305
bool operator<(const Clock &rhs) const
Compares the times between two clocks.
Definition: clock.h:277
Clock(const double time, const double dt)
Initialize with base time and time step size.
Definition: clock.h:103
static Representation convert(double x)
Convert a double x into the internal int representation.
Definition: clock.h:301
Representation reset_time_
The time of last reset (when counter_ was set to 0).
Definition: clock.h:315
bool operator>(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:292
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:249
static constexpr double resolution
Defines the resolution of the clock (i.e.
Definition: clock.h:88
Clock & operator++()
Advances the clock by one tick ( ).
Definition: clock.h:231
static constexpr double to_double
A multiplier transfering the internal integer to the real time.
Definition: clock.h:296
std::int64_t Representation
The type used for counting ticks/time.
Definition: clock.h:92
Clock tracks the time in the simulation.
Definition: clock.h:75
double next_multiple(const double interval) const
Returns the next multiple of a given interval.
Definition: clock.h:182
Clock()=default
default initializer: Timestep size is set to 0!
double next_time() const
Definition: clock.h:120
#define unlikely(x)
Tell the branch predictor that this expression is likely false.
Definition: macros.h:16
void end_tick_on_multiple(const double interval)
Set the time step such that it ends on the next multiple of the interval.
Definition: clock.h:195
double current_time() const
Definition: clock.h:110
bool multiple_is_in_next_tick(const double interval) const
Checks if a multiple of a given interval is reached within the next tick.
Definition: clock.h:158
void set_timestep_duration(const double dt)
Sets the time step size (and resets the counter).
Definition: clock.h:134
Definition: action.h:24
static constexpr double from_double
A multiplier transfering the real time to the internal integer.
Definition: clock.h:298