WorldtubeBufferUpdater.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <memory>
8 #include <optional>
9 #include <string>
10 #include <utility>
11 
12 #include "DataStructures/ComplexModalVector.hpp"
13 #include "DataStructures/DataBox/PrefixHelpers.hpp"
15 #include "DataStructures/DataBox/Tag.hpp"
16 #include "DataStructures/DataBox/TagName.hpp"
17 #include "DataStructures/DataVector.hpp"
19 #include "Evolution/Systems/Cce/Tags.hpp"
20 #include "IO/H5/Dat.hpp"
21 #include "IO/H5/File.hpp"
22 #include "IO/H5/Version.hpp"
23 #include "NumericalAlgorithms/Spectral/SwshTags.hpp"
25 #include "Parallel/PupStlCpp17.hpp"
26 #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
28 #include "Utilities/Gsl.hpp"
29 #include "Utilities/TMPL.hpp"
30 #include "Utilities/TaggedTuple.hpp"
31 
32 namespace Cce {
33 namespace Tags {
34 namespace detail {
35 // tags for use in the buffers for the modal input worldtube data management
36 // classes
37 using SpatialMetric =
41 
42 // radial derivative prefix tag to be used with the modal input worldtube data
43 template <typename Tag>
44 struct Dr : db::SimpleTag, db::PrefixTag {
45  using type = typename Tag::type;
46  using tag = Tag;
47 };
48 
49 // tag for the string for accessing the quantity associated with `Tag` in
50 // worldtube h5 file
51 template <typename Tag>
52 struct InputDataSet : db::SimpleTag, db::PrefixTag {
53  using type = std::string;
54  using tag = Tag;
55 };
56 } // namespace detail
57 } // namespace Tags
58 
59 namespace detail {
60 // generates the component dataset name in the worldtube file based on the
61 // tensor indices requested. For instance, if called with arguments ("/g", 0,1),
62 // it returns the dataset name "/gxy".
63 template <typename... T>
64 std::string dataset_name_for_component(std::string base_name,
65  const T... indices) noexcept { // NOLINT
66  const auto add_index = [&base_name](size_t index) noexcept {
67  ASSERT(index < 3, "The character-arithmetic index must be less than 3.");
68  base_name += static_cast<char>('x' + index);
69  };
70  EXPAND_PACK_LEFT_TO_RIGHT(add_index(indices));
71  // void cast so that compilers can tell it's used.
72  (void)add_index;
73  return base_name;
74 }
75 
76 // creates a pair of indices such that the difference is `2 *
77 // interpolator_length + pad`, centered around `time`, and bounded by
78 // `lower_bound` and `upper_bound`. If it cannot be centered, it gives a span
79 // that is appropriately sized and bounded by the supplied bounds. If the bounds
80 // are too constraining for the necessary size, it gives a span that is the
81 // correct size starting at `lower bound`, but not constrained by `upper_bound`
82 std::pair<size_t, size_t> create_span_for_time_value(
83  double time, size_t pad, size_t interpolator_length, size_t lower_bound,
84  size_t upper_bound, const DataVector& time_buffer) noexcept;
85 } // namespace detail
86 
87 /// the full set of tensors to be extracted from the worldtube h5 file
88 using cce_metric_input_tags = tmpl::list<
89  Tags::detail::SpatialMetric, Tags::detail::Dr<Tags::detail::SpatialMetric>,
90  ::Tags::dt<Tags::detail::SpatialMetric>, Tags::detail::Shift,
91  Tags::detail::Dr<Tags::detail::Shift>, ::Tags::dt<Tags::detail::Shift>,
92  Tags::detail::Lapse, Tags::detail::Dr<Tags::detail::Lapse>,
94 
95 /// the full set of tensors to be extracted from the reduced form of the
96 /// worldtube h5 file
98  tmpl::list<Spectral::Swsh::Tags::SwshTransform<Tags::BondiBeta>,
107 
108 /// \cond
111 /// \endcond
112 
113 /*!
114  * \brief Abstract base class for utilities that are able to perform the buffer
115  * updating procedure needed by the `WorldtubeDataManager`.
116  *
117  * \details The methods that are required to be overridden in the derived
118  * classes are:
119  * - `WorldtubeBufferUpdater::update_buffers_for_time()`:
120  * updates the buffers passed by pointer and the `time_span_start` and
121  * `time_span_end` to be appropriate for the requested `time`,
122  * `interpolator_length`, and `buffer_depth`.
123  * - `WorldtubeBufferUpdater::get_clone()`
124  * clone function to obtain a `std::unique_ptr` of the base
125  * `WorldtubeBufferUpdater`, needed to pass around the factory-created
126  * object.
127  * - `WorldtubeBufferUpdater::time_is_outside_range()`
128  * the override should return `true` if the `time` could be used in a
129  * `update_buffers_for_time` call given the data available to the derived
130  * class, and `false` otherwise
131  * - `WorldtubeBufferUpdater::get_l_max()`
132  * The override should return the `l_max` it uses in the
133  * Goldberg modal data placed in the buffers.
134  * - `WorldtubeBufferUpdater::get_extraction_radius()`
135  * The override should return the coordinate radius associated with the modal
136  * worldtube data that it supplies in the buffer update function. This is
137  * currently assumed to be a single double, but may be generalized in future
138  * to be time-dependent.
139  * - `WorldtubeBufferUpdater::get_time_buffer`
140  * The override should return the vector of times that it can produce modal
141  * data at. For instance, if associated with a file input, this will be the
142  * times at each of the rows of the time-series data.
143  */
144 template <typename BufferTags>
145 class WorldtubeBufferUpdater : public PUP::able {
146  public:
147  using creatable_classes =
148  tmpl::list<MetricWorldtubeH5BufferUpdater, BondiWorldtubeH5BufferUpdater>;
149 
150  WRAPPED_PUPable_abstract(WorldtubeBufferUpdater); // NOLINT
151 
152  virtual double update_buffers_for_time(
153  gsl::not_null<Variables<BufferTags>*> buffers,
154  gsl::not_null<size_t*> time_span_start,
155  gsl::not_null<size_t*> time_span_end, double time,
156  size_t computation_l_max, size_t interpolator_length,
157  size_t buffer_depth) const noexcept = 0;
158 
159  virtual std::unique_ptr<WorldtubeBufferUpdater> get_clone()
160  const noexcept = 0;
161 
162  virtual bool time_is_outside_range(double time) const noexcept = 0;
163 
164  virtual size_t get_l_max() const noexcept = 0;
165 
166  virtual double get_extraction_radius() const noexcept = 0;
167 
168  virtual bool has_version_history() const noexcept = 0;
169 
170  virtual DataVector& get_time_buffer() noexcept = 0;
171 };
172 
173 /// A `WorldtubeBufferUpdater` specialized to the CCE input worldtube H5 file
174 /// produced by SpEC.
176  : public WorldtubeBufferUpdater<cce_metric_input_tags> {
177  public:
178  // charm needs the empty constructor
179  MetricWorldtubeH5BufferUpdater() = default;
180 
181  /// The constructor takes the filename of the SpEC h5 file that will be used
182  /// for boundary data. The extraction radius can either be passed in directly,
183  /// or if it takes the value `std::nullopt`, then the extraction radius is
184  /// retrieved as an integer in the filename.
186  const std::string& cce_data_filename,
187  std::optional<double> extraction_radius = std::nullopt) noexcept;
188 
189  WRAPPED_PUPable_decl_template(MetricWorldtubeH5BufferUpdater); // NOLINT
190 
192  CkMigrateMessage* /*unused*/) noexcept {}
193 
194  /// update the `buffers`, `time_span_start`, and `time_span_end` with
195  /// time-varies-fastest, Goldberg modal data and the start and end index in
196  /// the member `time_buffer_` covered by the newly updated `buffers`. The
197  /// function returns the next time at which a full update will occur. If
198  /// called again at times earlier than the next full update time, it will
199  /// leave the `buffers` unchanged and again return the next needed time.
201  gsl::not_null<Variables<cce_metric_input_tags>*> buffers,
202  gsl::not_null<size_t*> time_span_start,
203  gsl::not_null<size_t*> time_span_end, double time,
204  size_t computation_l_max, size_t interpolator_length,
205  size_t buffer_depth) const noexcept override;
206 
208  const noexcept override;
209 
210  /// The time can only be supported in the buffer update if it is between the
211  /// first and last time of the input file.
212  bool time_is_outside_range(double time) const noexcept override;
213 
214  /// retrieves the l_max of the input file
215  size_t get_l_max() const noexcept override { return l_max_; }
216 
217  /// retrieves the extraction radius
218  double get_extraction_radius() const noexcept override {
219  return extraction_radius_;
220  }
221 
222  /// The time buffer is supplied by non-const reference to allow views to
223  /// easily point into the buffer.
224  ///
225  /// \warning Altering this buffer outside of the constructor of this class
226  /// results in undefined behavior! This should be supplied by const reference
227  /// once there is a convenient method of producing a const view of a vector
228  /// type.
229  DataVector& get_time_buffer() noexcept override { return time_buffer_; }
230 
231  bool has_version_history() const noexcept override {
232  return has_version_history_;
233  }
234 
235  /// Serialization for Charm++.
236  void pup(PUP::er& p) noexcept override;
237 
238  private:
239  void update_buffer(gsl::not_null<ComplexModalVector*> buffer_to_update,
240  const h5::Dat& read_data, size_t computation_l_max,
241  size_t time_span_start,
242  size_t time_span_end) const noexcept;
243 
244  bool has_version_history_ = true;
245  double extraction_radius_ = std::numeric_limits<double>::signaling_NaN();
246  size_t l_max_ = 0;
247 
249  std::string filename_;
250 
251  tuples::tagged_tuple_from_typelist<
253  dataset_names_;
254 
255  // stores all the times in the input file
256  DataVector time_buffer_;
257 };
258 
259 /// A `WorldtubeBufferUpdater` specialized to the CCE input worldtube H5 file
260 /// produced by the reduced SpEC format.
262  : public WorldtubeBufferUpdater<cce_bondi_input_tags> {
263  public:
264  // charm needs the empty constructor
265  BondiWorldtubeH5BufferUpdater() = default;
266 
267  /// The constructor takes the filename of the SpEC h5 file that will be used
268  /// for boundary data. The extraction radius can either be passed in directly,
269  /// or if it takes the value `std::nullopt`, then the extraction radius is
270  /// retrieved as an integer in the filename.
272  const std::string& cce_data_filename,
273  std::optional<double> extraction_radius = std::nullopt) noexcept;
274 
275  WRAPPED_PUPable_decl_template(BondiWorldtubeH5BufferUpdater); // NOLINT
276 
278  CkMigrateMessage* /*unused*/) noexcept {}
279 
280  /// update the `buffers`, `time_span_start`, and `time_span_end` with
281  /// time-varies-fastest, Goldberg modal data and the start and end index in
282  /// the member `time_buffer_` covered by the newly updated `buffers`.
284  gsl::not_null<Variables<cce_bondi_input_tags>*> buffers,
285  gsl::not_null<size_t*> time_span_start,
286  gsl::not_null<size_t*> time_span_end, double time,
287  size_t computation_l_max, size_t interpolator_length,
288  size_t buffer_depth) const noexcept override;
289 
291  const noexcept override {
292  return std::make_unique<BondiWorldtubeH5BufferUpdater>(filename_);
293  }
294 
295  /// The time can only be supported in the buffer update if it is between the
296  /// first and last time of the input file.
297  bool time_is_outside_range(const double time) const noexcept override {
298  return time < time_buffer_[0] or
299  time > time_buffer_[time_buffer_.size() - 1];
300  }
301 
302  /// retrieves the l_max of the input file
303  size_t get_l_max() const noexcept override { return l_max_; }
304 
305  /// retrieves the extraction radius. In most normal circumstances, this will
306  /// not be needed for Bondi data.
307  double get_extraction_radius() const noexcept override {
308  if (not static_cast<bool>(extraction_radius_)) {
309  ERROR(
310  "Extraction radius has not been set, and was not successfully parsed "
311  "from the filename. The extraction radius has been used, so must be "
312  "set either by the input file or via the filename.");
313  }
314  return *extraction_radius_;
315  }
316 
317  /// The time buffer is supplied by non-const reference to allow views to
318  /// easily point into the buffer.
319  ///
320  /// \warning Altering this buffer outside of the constructor of this class
321  /// results in undefined behavior! This should be supplied by const reference
322  /// once there is a convenient method of producing a const view of a vector
323  /// type.
324  DataVector& get_time_buffer() noexcept override { return time_buffer_; }
325 
326  bool has_version_history() const noexcept override {
327  return true;
328  }
329 
330  /// Serialization for Charm++.
331  void pup(PUP::er& p) noexcept override;
332 
333  private:
334  void update_buffer(gsl::not_null<ComplexModalVector*> buffer_to_update,
335  const h5::Dat& read_data, size_t computation_l_max,
336  size_t time_span_start, size_t time_span_end,
337  bool is_real) const noexcept;
338 
339  std::optional<double> extraction_radius_ = std::nullopt;
340  size_t l_max_ = 0;
341 
343  std::string filename_;
344 
345  tuples::tagged_tuple_from_typelist<
347  dataset_names_;
348 
349  // stores all the times in the input file
350  DataVector time_buffer_;
351 };
352 } // namespace Cce
h5::read_data
T read_data(const hid_t group_id, const std::string &dataset_name) noexcept
Read an array of rank 0-3 into an object.
Definition: Helpers.cpp:458
Cce::MetricWorldtubeH5BufferUpdater
A WorldtubeBufferUpdater specialized to the CCE input worldtube H5 file produced by SpEC.
Definition: WorldtubeBufferUpdater.hpp:175
std::string
CharmPupable.hpp
EXPAND_PACK_LEFT_TO_RIGHT
#define EXPAND_PACK_LEFT_TO_RIGHT(...)
Expand a parameter pack evaluating the terms from left to right.
Definition: TMPL.hpp:563
utility
Cce::BondiWorldtubeH5BufferUpdater::get_time_buffer
DataVector & get_time_buffer() noexcept override
The time buffer is supplied by non-const reference to allow views to easily point into the buffer.
Definition: WorldtubeBufferUpdater.hpp:324
gr::Tags::SpatialMetric
Definition: Tags.hpp:26
db::PrefixTag
Mark a struct as a prefix tag by inheriting from this.
Definition: Tag.hpp:103
std::pair
h5::Dat
Represents a multicolumn dat file inside an HDF5 file.
Definition: Dat.hpp:42
Cce::BondiWorldtubeH5BufferUpdater::get_extraction_radius
double get_extraction_radius() const noexcept override
retrieves the extraction radius. In most normal circumstances, this will not be needed for Bondi data...
Definition: WorldtubeBufferUpdater.hpp:307
Cce::MetricWorldtubeH5BufferUpdater::time_is_outside_range
bool time_is_outside_range(double time) const noexcept override
The time can only be supported in the buffer update if it is between the first and last time of the i...
Definition: WorldtubeBufferUpdater.cpp:213
db::SimpleTag
Mark a struct as a simple tag by inheriting from this.
Definition: Tag.hpp:36
Cce::BondiWorldtubeH5BufferUpdater
A WorldtubeBufferUpdater specialized to the CCE input worldtube H5 file produced by the reduced SpEC ...
Definition: WorldtubeBufferUpdater.hpp:261
File.hpp
ERROR
#define ERROR(m)
prints an error message to the standard error stream and aborts the program.
Definition: Error.hpp:36
h5::H5File< h5::AccessType::ReadOnly >
Version.hpp
Spectral::Swsh::Tags::SwshTransform
Prefix tag representing the spin-weighted spherical harmonic transform of a spin-weighted scalar.
Definition: SwshTags.hpp:183
cstddef
Assert.hpp
Cce::MetricWorldtubeH5BufferUpdater::get_l_max
size_t get_l_max() const noexcept override
retrieves the l_max of the input file
Definition: WorldtubeBufferUpdater.hpp:215
Cce::MetricWorldtubeH5BufferUpdater::get_time_buffer
DataVector & get_time_buffer() noexcept override
The time buffer is supplied by non-const reference to allow views to easily point into the buffer.
Definition: WorldtubeBufferUpdater.hpp:229
DataVector
Stores a collection of function values.
Definition: DataVector.hpp:46
Cce::BondiWorldtubeH5BufferUpdater::update_buffers_for_time
double update_buffers_for_time(gsl::not_null< Variables< cce_bondi_input_tags > * > buffers, gsl::not_null< size_t * > time_span_start, gsl::not_null< size_t * > time_span_end, double time, size_t computation_l_max, size_t interpolator_length, size_t buffer_depth) const noexcept override
update the buffers, time_span_start, and time_span_end with time-varies-fastest, Goldberg modal data ...
Definition: WorldtubeBufferUpdater.cpp:324
std::numeric_limits::signaling_NaN
T signaling_NaN(T... args)
Cce::MetricWorldtubeH5BufferUpdater::get_extraction_radius
double get_extraction_radius() const noexcept override
retrieves the extraction radius
Definition: WorldtubeBufferUpdater.hpp:218
memory
Cce::MetricWorldtubeH5BufferUpdater::update_buffers_for_time
double update_buffers_for_time(gsl::not_null< Variables< cce_metric_input_tags > * > buffers, gsl::not_null< size_t * > time_span_start, gsl::not_null< size_t * > time_span_end, double time, size_t computation_l_max, size_t interpolator_length, size_t buffer_depth) const noexcept override
update the buffers, time_span_start, and time_span_end with time-varies-fastest, Goldberg modal data ...
Definition: WorldtubeBufferUpdater.cpp:134
gr::Tags::Shift
Definition: Tags.hpp:48
Cce::cce_metric_input_tags
tmpl::list< Tags::detail::SpatialMetric, Tags::detail::Dr< Tags::detail::SpatialMetric >, ::Tags::dt< Tags::detail::SpatialMetric >, Tags::detail::Shift, Tags::detail::Dr< Tags::detail::Shift >, ::Tags::dt< Tags::detail::Shift >, Tags::detail::Lapse, Tags::detail::Dr< Tags::detail::Lapse >, ::Tags::dt< Tags::detail::Lapse > > cce_metric_input_tags
the full set of tensors to be extracted from the worldtube h5 file
Definition: WorldtubeBufferUpdater.hpp:93
ASSERT
#define ASSERT(a, m)
Assert that an expression should be true.
Definition: Assert.hpp:49
Tags::dt
Prefix indicating a time derivative.
Definition: Prefixes.hpp:29
Cce
The set of utilities for performing Cauchy characteristic evolution and Cauchy characteristic matchin...
Definition: CharacteristicExtractFwd.hpp:6
Gsl.hpp
Dat.hpp
Cce::MetricWorldtubeH5BufferUpdater::pup
void pup(PUP::er &p) noexcept override
Serialization for Charm++.
Definition: WorldtubeBufferUpdater.cpp:218
db::wrap_tags_in
tmpl::transform< TagList, tmpl::bind< Wrapper, tmpl::_1, tmpl::pin< Args >... > > wrap_tags_in
Create a new tmpl::list of tags by wrapping each tag in TagList in Wrapper<_, Args....
Definition: PrefixHelpers.hpp:30
optional
Matrix.hpp
Cce::BondiWorldtubeH5BufferUpdater::get_l_max
size_t get_l_max() const noexcept override
retrieves the l_max of the input file
Definition: WorldtubeBufferUpdater.hpp:303
Cce::WorldtubeBufferUpdater
Abstract base class for utilities that are able to perform the buffer updating procedure needed by th...
Definition: WorldtubeBufferUpdater.hpp:145
Cce::BondiWorldtubeH5BufferUpdater::pup
void pup(PUP::er &p) noexcept override
Serialization for Charm++.
Definition: WorldtubeBufferUpdater.cpp:438
std::unique_ptr
Prefixes.hpp
gr::Tags::Lapse
Definition: Tags.hpp:52
TMPL.hpp
Cce::cce_bondi_input_tags
tmpl::list< Spectral::Swsh::Tags::SwshTransform< Tags::BondiBeta >, Spectral::Swsh::Tags::SwshTransform< Tags::BondiU >, Spectral::Swsh::Tags::SwshTransform< Tags::BondiQ >, Spectral::Swsh::Tags::SwshTransform< Tags::BondiW >, Spectral::Swsh::Tags::SwshTransform< Tags::BondiJ >, Spectral::Swsh::Tags::SwshTransform< Tags::Dr< Tags::BondiJ > >, Spectral::Swsh::Tags::SwshTransform< Tags::Du< Tags::BondiJ > >, Spectral::Swsh::Tags::SwshTransform< Tags::BondiR >, Spectral::Swsh::Tags::SwshTransform< Tags::Du< Tags::BondiR > >> cce_bondi_input_tags
the full set of tensors to be extracted from the reduced form of the worldtube h5 file
Definition: WorldtubeBufferUpdater.hpp:106
Cce::BondiWorldtubeH5BufferUpdater::time_is_outside_range
bool time_is_outside_range(const double time) const noexcept override
The time can only be supported in the buffer update if it is between the first and last time of the i...
Definition: WorldtubeBufferUpdater.hpp:297
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecThirdOrderPiecewisePolynomial.hpp:13
string