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  static constexpr T default_value() noexcept { return 0; }
83  };
84 
85  static constexpr Options::String help = "A sequence of evenly spaced times.";
86  using options = tmpl::list<Interval, Offset>;
87 
88  explicit EvenlySpaced(T interval, T offset = 0,
89  const Options::Context& context = {});
90 
91  std::array<std::optional<T>, 3> times_near(T time) const noexcept override;
92 
93  // NOLINTNEXTLINE(google-runtime-references)
94  void pup(PUP::er& p) noexcept override;
95 
96  private:
97  // This is
98  // tmpl::conditional<std::is_integral_v<T>, std::make_signed<T>,
99  // tmpl::identity<T>>::type
100  // except avoiding instantiating std::make_signed<double> because,
101  // depending on the standard version, that is either undefined
102  // behavior or makes the program ill-formed.
103  using SignedT = tmpl::apply<tmpl::apply<
104  tmpl::if_<std::is_integral<tmpl::pin<T>>,
105  tmpl::defer<tmpl::bind<std::make_signed_t, tmpl::pin<T>>>,
106  tmpl::defer<tmpl::always<tmpl::pin<T>>>>>>;
107 
108  SignedT interval_{};
109  SignedT offset_{};
110 };
111 
112 /// An explicitly specified sequence of times.
113 template <typename T>
114 class Specified : public TimeSequence<T> {
115  public:
116  /// \cond
117  Specified() = default;
118  explicit Specified(CkMigrateMessage* /*unused*/) noexcept {}
119  using PUP::able::register_constructor;
120  WRAPPED_PUPable_decl_template(Specified); // NOLINT
121  /// \endcond
122 
123  struct Values {
124  static constexpr Options::String help = "The times in the sequence";
125  using type = std::vector<T>;
126  };
127 
128  static constexpr Options::String help =
129  "An explicitly specified sequence of times.";
130  using options = tmpl::list<Values>;
131 
132  explicit Specified(std::vector<T> values) noexcept;
133 
134  std::array<std::optional<T>, 3> times_near(T time) const noexcept override;
135 
136  // NOLINTNEXTLINE(google-runtime-references)
137  void pup(PUP::er& p) noexcept override;
138 
139  private:
140  std::vector<T> values_;
141 };
142 } // namespace TimeSequences
CharmPupable.hpp
Options.hpp
vector
TimeSequences::EvenlySpaced::Offset
Definition: TimeSequence.hpp:79
Options::Context
Definition: Options.hpp:41
TimeSequences
Definition: TimeSequence.cpp:14
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
db::apply
constexpr auto apply(F &&f, const DataBox< BoxTags > &box, Args &&... args) noexcept
Apply the invokable f with argument Tags TagsList from DataBox box
Definition: DataBox.hpp:1424
TimeSequences::Specified::Values
Definition: TimeSequence.hpp:123
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