History.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <deque>
7 #include <iterator>
8 #include <pup.h>
9 #include <tuple>
10 #include <utility>
11 
12 #include "Parallel/PupStlCpp11.hpp"
13 #include "Time/Time.hpp"
14 
15 namespace TimeSteppers {
16 
17 template <typename Vars, typename DerivVars>
19 
20 /// \ingroup TimeSteppersGroup
21 /// History data used by a TimeStepper.
22 /// \tparam Vars type of variables being integrated
23 /// \tparam DerivVars type of derivative variables
24 template <typename Vars, typename DerivVars>
25 class History {
26  public:
27  using value_type = Time;
28  using const_reference = const value_type&;
30  using difference_type =
32  using size_type = size_t;
33 
34  History() = default;
35  History(const History&) = delete;
36  History(History&&) = default;
37  History& operator=(const History&) = delete;
38  History& operator=(History&&) = default;
39  ~History() = default;
40 
41  /// Add a new set of values to the end of the history. `deriv` is
42  /// either left unchanged or set to a previously inserted `deriv`
43  /// value. The different argument types for `value` and `deriv`
44  /// reflect the common use of this class, which wants `value` to
45  /// remain unchanged but does not care about `deriv`.
46  void insert(Time time, const Vars& value, DerivVars&& deriv) noexcept;
47 
48  /// Add a new set of values to the front of the history. This is
49  /// often convenient for setting initial data.
50  void insert_initial(Time time, Vars value, DerivVars deriv) noexcept;
51 
52  /// Mark all data before the passed point in history as unneeded so
53  /// it can be removed. Calling this directly should not often be
54  /// necessary, as it is handled internally by the time steppers.
55  void mark_unneeded(const const_iterator& first_needed) noexcept;
56 
57  /// These iterators directly return the Time of the past values.
58  /// The other data can be accessed through the iterators using
59  /// HistoryIterator::value() and HistoryIterator::derivative().
60  //@{
61  const_iterator begin() const noexcept {
62  return data_.begin() +
63  static_cast<typename decltype(data_.begin())::difference_type>(
64  first_needed_entry_);
65  }
66  const_iterator end() const noexcept { return data_.end(); }
67  const_iterator cbegin() const noexcept { return begin(); }
68  const_iterator cend() const noexcept { return end(); }
69  //@}
70 
71  size_type size() const noexcept { return capacity() - first_needed_entry_; }
72  size_type capacity() const noexcept { return data_.size(); }
73  void shrink_to_fit() noexcept;
74 
75  /// These return the past times. The other data can be accessed
76  /// through HistoryIterator methods.
77  //@{
78  const_reference operator[](size_type n) const noexcept {
79  return *(begin() + static_cast<difference_type>(n));
80  }
81 
82  const_reference front() const noexcept { return *begin(); }
83  const_reference back() const noexcept { return std::get<0>(data_.back()); }
84  //@}
85 
86  // clang-tidy: google-runtime-references
87  void pup(PUP::er& p) noexcept { // NOLINT
88  // Don't send cached allocations. This object is probably going
89  // to be thrown away after serialization, so we take the easy
90  // route of just throwing them away.
91  shrink_to_fit();
92  p | data_;
93  }
94 
95  private:
97  size_t first_needed_entry_{0};
98 };
99 
100 /// \ingroup TimeSteppersGroup
101 /// Iterator over history data used by a TimeStepper. See History for
102 /// details.
103 template <typename Vars, typename DerivVars>
104 class HistoryIterator {
105  using Base =
107 
108  public:
109  using iterator_category =
111  using value_type = Time;
112  using difference_type = typename std::iterator_traits<Base>::difference_type;
113  using pointer = const value_type*;
114  using reference = const value_type&;
115 
116  HistoryIterator() = default;
117 
118  reference operator*() const noexcept { return std::get<0>(*base_); }
119  pointer operator->() const noexcept { return &std::get<0>(*base_); }
120  reference operator[](difference_type n) const noexcept {
121  return std::get<0>(base_[n]);
122  }
123  HistoryIterator& operator++() noexcept { ++base_; return *this; }
124  // clang-tidy: return const... Really? What?
125  HistoryIterator operator++(int) noexcept { return base_++; } // NOLINT
126  HistoryIterator& operator--() noexcept { --base_; return *this; }
127  // clang-tidy: return const... Really? What?
128  HistoryIterator operator--(int) noexcept { return base_--; } // NOLINT
129  HistoryIterator& operator+=(difference_type n) noexcept {
130  base_ += n;
131  return *this;
132  }
133  HistoryIterator& operator-=(difference_type n) noexcept {
134  base_ -= n;
135  return *this;
136  }
137 
138  const Vars& value() const noexcept { return std::get<1>(*base_); }
139  const DerivVars& derivative() const noexcept { return std::get<2>(*base_); }
140 
141  private:
142  friend class History<Vars, DerivVars>;
143 
144  friend difference_type operator-(const HistoryIterator& a,
145  const HistoryIterator& b) noexcept {
146  return a.base_ - b.base_;
147  }
148 
149 #define FORWARD_HISTORY_ITERATOR_OP(op) \
150  friend bool operator op(const HistoryIterator& a, \
151  const HistoryIterator& b) noexcept { \
152  return a.base_ op b.base_; \
153  }
154  FORWARD_HISTORY_ITERATOR_OP(==)
155  FORWARD_HISTORY_ITERATOR_OP(!=)
156  FORWARD_HISTORY_ITERATOR_OP(<)
157  FORWARD_HISTORY_ITERATOR_OP(>)
158  FORWARD_HISTORY_ITERATOR_OP(<=)
159  FORWARD_HISTORY_ITERATOR_OP(>=)
160 #undef FORWARD_HISTORY_ITERATOR_OP
161 
162  // clang-tidy: google-explicit-constructor - private
163  HistoryIterator(Base base) noexcept : base_(std::move(base)) {} // NOLINT
164 
165  Base base_{};
166 };
167 
168 // ================================================================
169 
170 template <typename Vars, typename DerivVars>
171 void History<Vars, DerivVars>::insert(Time time, const Vars& value,
172  DerivVars&& deriv) noexcept {
173  if (first_needed_entry_ == 0) {
174  // clang-tidy: move of trivially-copyable type
175  data_.emplace_back(std::move(time), value, deriv); // NOLINT
176  } else {
177  // Move an unneeded entry into the arguments so the caller can
178  // reuse any resources the entry contained.
179  using std::swap;
180  auto& old_entry = data_.front();
181  // clang-tidy: move of trivially-copyable type
182  std::get<0>(old_entry) = std::move(time); // NOLINT
183  std::get<1>(old_entry) = value;
184  swap(std::get<2>(old_entry), deriv);
185  data_.push_back(std::move(old_entry));
186  data_.pop_front();
187  --first_needed_entry_;
188  }
189 }
190 
191 template <typename Vars, typename DerivVars>
192 inline void History<Vars, DerivVars>::insert_initial(Time time, Vars value,
193  DerivVars deriv) noexcept {
194  // clang-tidy: move of trivially-copyable type
195  data_.emplace_front(std::move(time), // NOLINT
196  std::move(value), std::move(deriv));
197 }
198 
199 template <typename Vars, typename DerivVars>
201  const const_iterator& first_needed) noexcept {
202  first_needed_entry_ = static_cast<size_t>(first_needed.base_ - data_.begin());
203 }
204 
205 template <typename Vars, typename DerivVars>
206 inline void History<Vars, DerivVars>::shrink_to_fit() noexcept {
207  data_.erase(
208  data_.begin(),
209  data_.begin() +
210  static_cast<typename decltype(data_.begin())::difference_type>(
211  first_needed_entry_));
212  first_needed_entry_ = 0;
213 }
214 
215 template <typename Vars, typename DerivVars>
216 inline HistoryIterator<Vars, DerivVars> operator+(
218  typename HistoryIterator<Vars, DerivVars>::difference_type n) noexcept {
219  it += n;
220  return it;
221 }
222 
223 template <typename Vars, typename DerivVars>
224 inline HistoryIterator<Vars, DerivVars> operator+(
225  typename HistoryIterator<Vars, DerivVars>::difference_type n,
226  HistoryIterator<Vars, DerivVars> it) noexcept {
227  return std::move(it) + n;
228 }
229 
230 template <typename Vars, typename DerivVars>
231 inline HistoryIterator<Vars, DerivVars> operator-(
233  typename HistoryIterator<Vars, DerivVars>::difference_type n) noexcept {
234  return std::move(it) + (-n);
235 }
236 } // namespace TimeSteppers
Iterator over history data used by a TimeStepper. See History for details.
Definition: History.hpp:18
The time in a simulation. Times can be safely compared for exact equality as long as they do not belo...
Definition: Time.hpp:31
auto operator*(const TensorExpression< T1, X, Symm1, IndexList1, Args1 > &t1, const TensorExpression< T2, X, Symm2, IndexList2, Args2 > &t2)
Definition: Product.hpp:89
const_reference back() const noexcept
These return the past times. The other data can be accessed through HistoryIterator methods...
Definition: History.hpp:83
History data used by a TimeStepper.
Definition: History.hpp:25
Defines Time and TimeDelta.
const_iterator cend() const noexcept
These iterators directly return the Time of the past values. The other data can be accessed through t...
Definition: History.hpp:68
void insert_initial(Time time, Vars value, DerivVars deriv) noexcept
Add a new set of values to the front of the history. This is often convenient for setting initial dat...
Definition: History.hpp:192
const_iterator begin() const noexcept
These iterators directly return the Time of the past values. The other data can be accessed through t...
Definition: History.hpp:61
Prefix indicating spatial derivatives.
Definition: PartialDerivatives.hpp:45
const_reference operator[](size_type n) const noexcept
These return the past times. The other data can be accessed through HistoryIterator methods...
Definition: History.hpp:78
const_iterator cbegin() const noexcept
These iterators directly return the Time of the past values. The other data can be accessed through t...
Definition: History.hpp:67
PUP routines for new C+11 STL containers and other standard library objects Charm does not provide im...
constexpr void swap(T &a, T &b) noexcept
Definition: Algorithm.hpp:19
const_iterator end() const noexcept
These iterators directly return the Time of the past values. The other data can be accessed through t...
Definition: History.hpp:66
Holds classes that take time steps.
Definition: BoundaryHistory.hpp:23
void mark_unneeded(const const_iterator &first_needed) noexcept
Mark all data before the passed point in history as unneeded so it can be removed. Calling this directly should not often be necessary, as it is handled internally by the time steppers.
Definition: History.hpp:200
const_reference front() const noexcept
These return the past times. The other data can be accessed through HistoryIterator methods...
Definition: History.hpp:82
void insert(Time time, const Vars &value, DerivVars &&deriv) noexcept
Add a new set of values to the end of the history. deriv is either left unchanged or set to a previou...
Definition: History.hpp:171