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