Version: SMASH-3.0
clock.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2020,2022
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 
73 class Clock {
74  public:
76  using Representation = std::int64_t;
78  virtual double timestep_duration() const = 0;
80  virtual double current_time() const = 0;
82  virtual double next_time() const = 0;
90  virtual void reset(double start_time, const bool is_output_clock) = 0;
98  virtual void remove_times_in_past(double start_time) = 0;
107  // guard against overflow:
108  if (counter_ >= std::numeric_limits<Representation>::max() - 1) {
109  throw std::overflow_error("Too many timesteps, clock overflow imminent");
110  }
111  ++counter_;
112  return *this;
113  }
114 
123  Clock& operator+=(Representation advance_several_timesteps) {
124  if (counter_ >= std::numeric_limits<Representation>::max() -
125  advance_several_timesteps) {
126  throw std::overflow_error("Too many timesteps, clock overflow imminent");
127  }
128  counter_ += advance_several_timesteps;
129  return *this;
130  }
131 
137  bool operator<(const Clock& rhs) const {
138  return current_time() < rhs.current_time();
139  }
140 
146  bool operator<(double time) const { return current_time() < time; }
147 
153  bool operator>(double time) const { return current_time() > time; }
154 
155  virtual ~Clock() = default;
156 
157  protected:
162 };
163 
175 class UniformClock : public Clock {
188  static constexpr double resolution = 0.000001;
189 
190  public:
192  UniformClock() = default;
200  UniformClock(const double time, const double dt, const double time_end)
202  reset_time_(convert(time)),
203  time_end_(convert(time_end)) {
204  if (dt < 0.) {
205  throw std::range_error("No negative time increment allowed");
206  }
207  }
209  double current_time() const override {
211  return convert(time_end_);
212  } else {
214  }
215  }
223  double next_time() const override {
225  std::numeric_limits<Representation>::max() - timestep_duration_) {
226  throw std::overflow_error("Too many timesteps, clock overflow imminent");
227  }
228  if ((reset_time_ + timestep_duration_ * (counter_ + 1)) > time_end_) {
229  return convert(time_end_);
230  } else {
232  }
233  }
235  double timestep_duration() const override {
236  if ((reset_time_ + timestep_duration_ * (counter_ + 1)) > time_end_) {
237  Representation last_timestep =
239  return convert(last_timestep);
240  } else {
241  return convert(timestep_duration_);
242  }
243  }
249  void set_timestep_duration(const double dt) {
250  if (dt < 0.) {
251  throw std::range_error("No negative time increment allowed");
252  }
254  counter_ = 0;
256  }
257 
264  void reset(const double start_time, const bool is_output_clock) override {
265  double reset_time;
266  if (is_output_clock) {
267  reset_time =
268  std::floor(start_time / timestep_duration()) * timestep_duration();
269  } else {
270  reset_time = start_time;
271  }
272  if (reset_time < current_time()) {
273  logg[LClock].debug("Resetting clock from", current_time(), " fm to ",
274  reset_time, " fm");
275  }
276  reset_time_ = convert(reset_time);
277  counter_ = 0;
278  }
279 
280  void remove_times_in_past(double) override{};
281 
290  template <typename T>
291  typename std::enable_if<std::is_floating_point<T>::value, Clock&>::type
292  operator+=(T big_timestep) {
293  if (big_timestep < 0.) {
294  throw std::range_error("The clock cannot be turned back.");
295  }
296  reset_time_ += convert(big_timestep);
297  return *this;
298  }
307  Clock& operator+=(Representation advance_several_timesteps) {
308  if (counter_ >= std::numeric_limits<Representation>::max() -
309  advance_several_timesteps) {
310  throw std::overflow_error("Too many timesteps, clock overflow imminent");
311  }
312  counter_ += advance_several_timesteps;
313  return *this;
314  }
315 
316  private:
318  static constexpr double to_double = resolution;
320  static constexpr double from_double = 1. / resolution;
321 
323  static Representation convert(double x) {
324  return std::round(x * from_double);
325  }
327  static double convert(Representation x) { return x * to_double; }
328 
335 };
336 
338 class CustomClock : public Clock {
339  public:
345  explicit CustomClock(std::vector<double> times) : custom_times_(times) {
346  std::sort(custom_times_.begin(), custom_times_.end());
347  counter_ = -1;
348  }
353  double current_time() const override {
354  if (counter_ == -1) {
355  // current time before the first output should be the starting time
356  return start_time_;
357  } else if (counter_ < -1) {
358  throw std::runtime_error("Trying to access undefined zeroth output time");
359  } else {
360  return custom_times_[counter_];
361  }
362  }
364  double next_time() const override { return custom_times_[counter_ + 1]; }
365  double timestep_duration() const override {
366  return next_time() - current_time();
367  }
368  void reset(double start_time, bool) override {
369  counter_ = -1;
370  start_time_ = start_time;
371  }
372 
378  void remove_times_in_past(double start_time) override {
379  std::remove_if(custom_times_.begin(), custom_times_.end(),
380  [start_time](double t) {
381  if (t <= start_time) {
382  logg[LClock].warn("Removing custom output time ", t,
383  " fm since it is earlier than the "
384  "starting time of the simulation");
385  return true;
386  } else {
387  return false;
388  }
389  });
390  }
391 
392  private:
394  std::vector<double> custom_times_;
396  double start_time_ = 0.;
397 };
398 } // namespace smash
399 
400 #endif // SRC_INCLUDE_SMASH_CLOCK_H_
Clock tracks the time in the simulation.
Definition: clock.h:73
bool operator<(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:146
virtual ~Clock()=default
bool operator<(const Clock &rhs) const
Compares the times between two clocks.
Definition: clock.h:137
std::int64_t Representation
The type used for counting ticks/time.
Definition: clock.h:76
virtual double current_time() const =0
virtual double timestep_duration() const =0
Representation counter_
Internally used to count the number of time steps.
Definition: clock.h:161
bool operator>(double time) const
Compares the time of the clock against a fixed time.
Definition: clock.h:153
Clock & operator++()
Advances the clock by one tick.
Definition: clock.h:106
virtual void reset(double start_time, const bool is_output_clock)=0
reset the clock to the starting time of the simulation
virtual double next_time() const =0
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.
Clock & operator+=(Representation advance_several_timesteps)
Advances the clock by an arbitrary number of ticks.
Definition: clock.h:123
Clock with explicitly defined time steps.
Definition: clock.h:338
double next_time() const override
Definition: clock.h:364
CustomClock(std::vector< double > times)
Initialises a custom clock with explicitly given output times.
Definition: clock.h:345
double start_time_
Starting time of the simulation.
Definition: clock.h:396
void remove_times_in_past(double start_time) override
Remove all custom times before start_time.
Definition: clock.h:378
std::vector< double > custom_times_
Vector of times where output is generated.
Definition: clock.h:394
void reset(double start_time, bool) override
reset the clock to the starting time of the simulation
Definition: clock.h:368
double timestep_duration() const override
Definition: clock.h:365
double current_time() const override
Definition: clock.h:353
Clock with uniformly spaced time steps.
Definition: clock.h:175
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:264
static constexpr double from_double
A multiplier transfering the real time to the internal integer.
Definition: clock.h:320
static constexpr double to_double
A multiplier transfering the internal integer to the real time.
Definition: clock.h:318
Representation timestep_duration_
The time step size in .
Definition: clock.h:330
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:280
double next_time() const override
Definition: clock.h:223
static constexpr double resolution
Defines the resolution of the clock (i.e.
Definition: clock.h:188
Representation time_end_
The end time of the particle propagation.
Definition: clock.h:334
static Representation convert(double x)
Convert a double x into the internal int representation.
Definition: clock.h:323
Representation reset_time_
The time of last reset (when counter_ was set to 0).
Definition: clock.h:332
void set_timestep_duration(const double dt)
Sets the time step size (and resets the counter).
Definition: clock.h:249
UniformClock()=default
default initializer: Timestep size is set to 0!
double timestep_duration() const override
Definition: clock.h:235
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).
Definition: clock.h:292
UniformClock(const double time, const double dt, const double time_end)
Initialize with base time and time step size.
Definition: clock.h:200
Clock & operator+=(Representation advance_several_timesteps)
advances the clock by an arbitrary number of ticks.
Definition: clock.h:307
static double convert(Representation x)
Convert an internal int value x into the double representation.
Definition: clock.h:327
double current_time() const override
Definition: clock.h:209
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
Definition: action.h:24
static constexpr int LClock
Definition: clock.h:25