Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines Time and TimeDelta
6 :
7 : #pragma once
8 :
9 : #include <cstddef>
10 : #include <functional>
11 : #include <iosfwd>
12 : #include <limits>
13 :
14 : #include "Time/Slab.hpp"
15 : #include "Utilities/Rational.hpp"
16 :
17 : /// \cond
18 : namespace PUP {
19 : class er;
20 : } // namespace PUP
21 : class TimeDelta;
22 : /// \endcond
23 :
24 : /// \ingroup TimeGroup
25 : ///
26 : /// The time in a simulation. Times can be safely compared for exact
27 : /// equality as long as they do not belong to overlapping unequal
28 : /// slabs.
29 1 : class Time {
30 : public:
31 0 : using rational_t = Rational;
32 :
33 : /// Default constructor gives an invalid Time.
34 1 : Time() = default;
35 :
36 : /// A time a given fraction of the way through the given slab.
37 1 : Time(Slab slab, rational_t fraction);
38 :
39 : /// Move the time to a different slab. The time must be at an end
40 : /// of the current slab and the new slab must share that endpoint.
41 1 : Time with_slab(const Slab& new_slab) const;
42 :
43 : /// Approximate numerical value of the Time.
44 1 : double value() const { return value_; }
45 0 : const Slab& slab() const { return slab_; }
46 0 : const rational_t& fraction() const { return fraction_; }
47 :
48 0 : Time& operator+=(const TimeDelta& delta);
49 0 : Time& operator-=(const TimeDelta& delta);
50 :
51 0 : bool is_at_slab_start() const;
52 0 : bool is_at_slab_end() const;
53 0 : bool is_at_slab_boundary() const;
54 :
55 : // NOLINTNEXTLINE(google-runtime-references)
56 0 : void pup(PUP::er& p);
57 :
58 : /// A comparison operator that compares Times structurally, i.e.,
59 : /// just looking at the class members. This is only intended for
60 : /// use as the comparator in a map. The returned ordering does not
61 : /// match the time ordering and opposite sides of slab boundaries do
62 : /// not compare equal. It is, however, much faster to compute than
63 : /// the temporal ordering, so it is useful when an ordering is
64 : /// required, but the ordering does not have to be physically
65 : /// meaningful.
66 1 : struct StructuralCompare {
67 0 : bool operator()(const Time& a, const Time& b) const;
68 : };
69 :
70 : private:
71 0 : Slab slab_;
72 0 : rational_t fraction_;
73 0 : double value_ = std::numeric_limits<double>::signaling_NaN();
74 :
75 : // The value is precomputed so that we can avoid doing the rational
76 : // math repeatedly. The value of a Time should almost always be
77 : // needed at some point.
78 0 : void compute_value();
79 :
80 0 : void range_check() const;
81 :
82 0 : friend class TimeDelta;
83 : };
84 :
85 : /// \ingroup TimeGroup
86 : ///
87 : /// Represents an interval of time within a single slab.
88 1 : class TimeDelta {
89 : public:
90 0 : using rational_t = Time::rational_t;
91 :
92 : /// Default constructor gives an invalid TimeDelta.
93 1 : TimeDelta() = default;
94 :
95 : /// An interval covering a given fraction of the slab.
96 1 : TimeDelta(Slab slab, rational_t fraction);
97 :
98 : /// Move the interval to a different slab. The resulting interval
99 : /// will in general not be the same length, but will take up the
100 : /// same fraction of its slab.
101 1 : TimeDelta with_slab(const Slab& new_slab) const;
102 :
103 0 : Slab slab() const { return slab_; }
104 0 : rational_t fraction() const { return fraction_; }
105 :
106 : /// Approximate numerical length of the interval.
107 1 : double value() const;
108 :
109 : /// Test if the interval is oriented towards larger time.
110 1 : bool is_positive() const;
111 :
112 0 : TimeDelta& operator+=(const TimeDelta& other);
113 0 : TimeDelta& operator-=(const TimeDelta& other);
114 0 : TimeDelta operator+() const;
115 0 : TimeDelta operator-() const;
116 0 : TimeDelta& operator*=(const rational_t& mult);
117 0 : TimeDelta& operator/=(const rational_t& div);
118 :
119 : // NOLINTNEXTLINE(google-runtime-references)
120 0 : void pup(PUP::er& p);
121 :
122 : private:
123 0 : Slab slab_;
124 0 : rational_t fraction_;
125 :
126 0 : friend class Time;
127 : };
128 :
129 : // Time <cmp> Time
130 : // clang-tidy: clang-tidy wants this removed in favor of friend
131 : // declaration in different header.
132 0 : bool operator==(const Time& a, const Time& b); // NOLINT
133 0 : bool operator!=(const Time& a, const Time& b);
134 0 : bool operator<(const Time& a, const Time& b);
135 0 : bool operator>(const Time& a, const Time& b);
136 0 : bool operator<=(const Time& a, const Time& b);
137 0 : bool operator>=(const Time& a, const Time& b);
138 :
139 : // TimeDelta <cmp> TimeDelta
140 0 : bool operator==(const TimeDelta& a, const TimeDelta& b);
141 0 : bool operator!=(const TimeDelta& a, const TimeDelta& b);
142 0 : bool operator<(const TimeDelta& a, const TimeDelta& b);
143 0 : bool operator>(const TimeDelta& a, const TimeDelta& b);
144 0 : bool operator<=(const TimeDelta& a, const TimeDelta& b);
145 0 : bool operator>=(const TimeDelta& a, const TimeDelta& b);
146 :
147 : // Time <op> Time
148 0 : TimeDelta operator-(const Time& a, const Time& b);
149 :
150 : // Time <op> TimeDelta, TimeDelta <op> Time
151 0 : Time operator+(Time a, const TimeDelta& b);
152 0 : Time operator+(const TimeDelta& a, Time b);
153 0 : Time operator-(Time a, const TimeDelta& b);
154 :
155 : // TimeDelta <op> TimeDelta
156 0 : TimeDelta operator+(TimeDelta a, const TimeDelta& b);
157 0 : TimeDelta operator-(TimeDelta a, const TimeDelta& b);
158 :
159 : // This returns a double rather than a rational so we can compare dt
160 : // in different slabs.
161 0 : double operator/(const TimeDelta& a, const TimeDelta& b);
162 :
163 : // rational <op> TimeDelta, TimeDelta <op> rational
164 0 : TimeDelta operator*(TimeDelta a, const TimeDelta::rational_t& b);
165 0 : TimeDelta operator*(const TimeDelta::rational_t& a, TimeDelta b);
166 0 : TimeDelta operator/(TimeDelta a, const TimeDelta::rational_t& b);
167 :
168 : // Miscellaneous other functions for Time
169 :
170 0 : std::ostream& operator<<(std::ostream& os, const Time& t);
171 :
172 0 : size_t hash_value(const Time& t);
173 :
174 : namespace std {
175 : template <>
176 : struct hash<Time> {
177 : size_t operator()(const Time& t) const;
178 : };
179 : } // namespace std
180 :
181 : // Miscellaneous other functions for TimeDelta
182 :
183 0 : TimeDelta abs(TimeDelta t);
184 :
185 0 : std::ostream& operator<<(std::ostream& os, const TimeDelta& dt);
186 :
187 0 : size_t hash_value(const TimeDelta& dt);
188 :
189 : namespace std {
190 : template <>
191 : struct hash<TimeDelta> {
192 : size_t operator()(const TimeDelta& dt) const;
193 : };
194 : } // namespace std
|