TimeSequence.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <array>
7 #include <optional>
8 #include <pup.h>
9 #include <vector>
10 
11 #include "Options/Options.hpp"
13 #include "Utilities/TMPL.hpp"
14 
15 /// \ingroup TimeSteppersGroup
16 ///
17 /// Holds all the TimeSequences
18 namespace TimeSequences {
19 template <typename T>
21 template <typename T>
22 class Specified;
23 } // namespace TimeSequences
24 
25 /// Represents a sequence of times.
26 ///
27 /// The template parameter \p T can either be `double` for a sequence
28 /// of simulation times or std::uint64_t for a sequence of slab
29 /// numbers.
30 template <typename T>
31 class TimeSequence : public PUP::able {
32  protected:
33  /// \cond HIDDEN_SYMBOLS
34  TimeSequence() = default;
35  TimeSequence(const TimeSequence&) = default;
36  TimeSequence(TimeSequence&&) = default;
37  TimeSequence& operator=(const TimeSequence&) = default;
38  TimeSequence& operator=(TimeSequence&&) = default;
39  /// \endcond
40 
41  public:
42  ~TimeSequence() override = default;
43 
44  WRAPPED_PUPable_abstract(TimeSequence); // NOLINT
45 
46  using creatable_classes =
47  tmpl::list<TimeSequences::EvenlySpaced<T>, TimeSequences::Specified<T>>;
48 
49  /// Returns the time in the sequence nearest to \p time, the time
50  /// before that, and the time after, in numerical order. These
51  /// values allow a consumer to find the times in the sequence
52  /// bracketing the given time and give enough additional information
53  /// so that exact or roundoff matches can be handled however the
54  /// consumer wishes. Any time that does not exist (because the
55  /// sequence terminates) is returned as an empty std::optional. The
56  /// central std::optional will be populated unless the sequence is
57  /// empty.
58  virtual std::array<std::optional<T>, 3> times_near(T time) const noexcept = 0;
59 };
60 
61 namespace TimeSequences {
62 /// A sequence of evenly spaced times.
63 template <typename T>
64 class EvenlySpaced : public TimeSequence<T> {
65  public:
66  /// \cond
67  EvenlySpaced() = default;
68  explicit EvenlySpaced(CkMigrateMessage* /*unused*/) noexcept {}
69  using PUP::able::register_constructor;
70  WRAPPED_PUPable_decl_template(EvenlySpaced); // NOLINT
71  /// \endcond
72 
73  struct Interval {
74  static constexpr Options::String help = "Spacing between times";
75  using type = T;
76  static constexpr T lower_bound() noexcept { return 0; }
77  };
78 
79  struct Offset {
80  static constexpr Options::String help = "Offset of sequence";
81  using type = T;
82  };
83 
84  static constexpr Options::String help = "A sequence of evenly spaced times.";
85  using options = tmpl::list<Interval, Offset>;
86 
87  explicit EvenlySpaced(T interval, T offset = 0,
88  const Options::Context& context = {});
89 
90  std::array<std::optional<T>, 3> times_near(T time) const noexcept override;
91 
92  // NOLINTNEXTLINE(google-runtime-references)
93  void pup(PUP::er& p) noexcept override;
94 
95  private:
96  // This is
97  // tmpl::conditional<std::is_integral_v<T>, std::make_signed<T>,
98  // tmpl::identity<T>>::type
99  // except avoiding instantiating std::make_signed<double> because,
100  // depending on the standard version, that is either undefined
101  // behavior or makes the program ill-formed.
102  using SignedT = tmpl::apply<tmpl::apply<
103  tmpl::if_<std::is_integral<tmpl::pin<T>>,
104  tmpl::defer<tmpl::bind<std::make_signed_t, tmpl::pin<T>>>,
105  tmpl::defer<tmpl::always<tmpl::pin<T>>>>>>;
106 
107  SignedT interval_{};
108  SignedT offset_{};
109 };
110 
111 /// An explicitly specified sequence of times.
112 template <typename T>
113 class Specified : public TimeSequence<T> {
114  public:
115  /// \cond
116  Specified() = default;
117  explicit Specified(CkMigrateMessage* /*unused*/) noexcept {}
118  using PUP::able::register_constructor;
119  WRAPPED_PUPable_decl_template(Specified); // NOLINT
120  /// \endcond
121 
122  struct Values {
123  static constexpr Options::String help = "The times in the sequence";
124  using type = std::vector<T>;
125  };
126 
127  static constexpr Options::String help =
128  "An explicitly specified sequence of times.";
129  using options = tmpl::list<Values>;
130 
131  explicit Specified(std::vector<T> values) noexcept;
132 
133  std::array<std::optional<T>, 3> times_near(T time) const noexcept override;
134 
135  // NOLINTNEXTLINE(google-runtime-references)
136  void pup(PUP::er& p) noexcept override;
137 
138  private:
139  std::vector<T> values_;
140 };
141 } // namespace TimeSequences
CharmPupable.hpp
Options.hpp
vector
TimeSequences::EvenlySpaced::Offset
Definition: TimeSequence.hpp:79
Options::Context
Definition: Options.hpp:41
TimeSequences
Definition: TimeSequence.hpp:18
TimeSequence::times_near
virtual std::array< std::optional< T >, 3 > times_near(T time) const noexcept=0
Returns the time in the sequence nearest to time, the time before that, and the time after,...
TimeSequence
Represents a sequence of times.
Definition: TimeSequence.hpp:31
TimeSequences::Specified::Values
Definition: TimeSequence.hpp:122
WRAPPED_PUPable_decl_template
#define WRAPPED_PUPable_decl_template(className)
Mark derived classes as serializable.
Definition: CharmPupable.hpp:22
TimeSequences::EvenlySpaced::Interval
Definition: TimeSequence.hpp:73
TimeSequences::EvenlySpaced
A sequence of evenly spaced times.
Definition: TimeSequence.hpp:20
array
TimeSequences::Specified
An explicitly specified sequence of times.
Definition: TimeSequence.hpp:22
Options::String
const char *const String
The string used in option structs.
Definition: Options.hpp:32
optional
TMPL.hpp