Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <algorithm>
7 : #include <cstddef>
8 : #include <memory>
9 : #include <utility>
10 :
11 : #include "DataStructures/DataBox/Tag.hpp"
12 : #include "Evolution/Systems/Cce/BoundaryData.hpp"
13 : #include "Evolution/Systems/Cce/Tags.hpp"
14 : #include "Evolution/Systems/Cce/WorldtubeBufferUpdater.hpp"
15 : #include "NumericalAlgorithms/Interpolation/SpanInterpolator.hpp"
16 : #include "Parallel/NodeLock.hpp"
17 : #include "Utilities/Gsl.hpp"
18 : #include "Utilities/Serialization/CharmPupable.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : namespace Cce {
22 :
23 : namespace detail {
24 :
25 : template <typename InputTags>
26 : void set_non_pupped_members(
27 : gsl::not_null<size_t*> time_span_start,
28 : gsl::not_null<size_t*> time_span_end,
29 : gsl::not_null<Variables<InputTags>*> coefficients_buffers,
30 : gsl::not_null<Variables<InputTags>*> interpolated_coefficients,
31 : size_t buffer_depth, size_t interpolator_length, size_t l_max);
32 :
33 : template <typename InputTags>
34 : void initialize_buffers(
35 : gsl::not_null<size_t*> buffer_depth,
36 : gsl::not_null<Variables<InputTags>*> coefficients_buffers,
37 : size_t buffer_size, size_t interpolator_length, size_t l_max);
38 :
39 : template <typename InputTags, typename OutputTags>
40 : void populate_hypersurface_boundary_data(
41 : gsl::not_null<Variables<OutputTags>*> boundary_data_variables,
42 : gsl::not_null<Variables<InputTags>*> interpolated_coefficients,
43 : gsl::not_null<Variables<InputTags>*> coefficients_buffers,
44 : gsl::not_null<size_t*> time_span_start,
45 : gsl::not_null<size_t*> time_span_end,
46 : gsl::not_null<Parallel::NodeLock*> hdf5_lock, double time,
47 : const std::unique_ptr<intrp::SpanInterpolator>& interpolator,
48 : const std::unique_ptr<WorldtubeBufferUpdater<InputTags>>& buffer_updater,
49 : size_t l_max, size_t buffer_depth);
50 : } // namespace detail
51 :
52 : /// \cond
53 : class MetricWorldtubeDataManager;
54 : class BondiWorldtubeDataManager;
55 : class KleinGordonWorldtubeDataManager;
56 : /// \endcond
57 :
58 : /*!
59 : * \brief Abstract base class for managers of CCE worldtube data that is
60 : * provided in large time-series chunks, especially the type provided by input
61 : * h5 files. `BoundaryTags` is a `tmpl::list` of tags on the worldtube boundary.
62 : *
63 : * \details The methods that are required to be overridden in the derived
64 : * classes are:
65 : *
66 : * - `WorldtubeDataManager::populate_hypersurface_boundary_data()`:
67 : * updates the Variables passed by pointer to contain correct boundary data
68 : * for the time value passed in. This function should update all of the tags
69 : * in `Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>`.
70 : * - `WorldtubeDataManager::get_clone()`: clone function to obtain a
71 : * `std::unique_ptr` of the base `WorldtubeDataManager`, needed to pass around
72 : * the factory-created object.
73 : * - `WorldtubeDataManager::get_l_max()`: The override should return the
74 : * `l_max` that it computes for the collocation data calculated during
75 : * `WorldtubeDataManager::populate_hypersurface_boundary_data()`.
76 : * - `WorldtubeBufferUpdater::get_time_span()`: The override should return the
77 : * `std::pair` of indices that represent the start and end point of the
78 : * underlying data source. This is primarily used for monitoring the frequency
79 : * and size of the buffer updates.
80 : */
81 : template <typename BoundaryTags>
82 1 : class WorldtubeDataManager : public PUP::able {
83 : public:
84 0 : using creatable_classes =
85 : tmpl::list<MetricWorldtubeDataManager, BondiWorldtubeDataManager,
86 : KleinGordonWorldtubeDataManager>;
87 :
88 0 : WRAPPED_PUPable_abstract(WorldtubeDataManager); // NOLINT
89 :
90 0 : virtual bool populate_hypersurface_boundary_data(
91 : gsl::not_null<Variables<BoundaryTags>*> boundary_data_variables,
92 : double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const = 0;
93 :
94 0 : virtual std::unique_ptr<WorldtubeDataManager> get_clone() const = 0;
95 :
96 0 : virtual size_t get_l_max() const = 0;
97 :
98 0 : virtual std::pair<size_t, size_t> get_time_span() const = 0;
99 : };
100 :
101 : /*!
102 : * \brief Manages the cached buffer data associated with a CCE worldtube and
103 : * interpolates to requested time points to provide worldtube boundary data to
104 : * the main evolution routines.
105 : *
106 : * \details The maintained buffer will be maintained at a length that is set by
107 : * the `Interpolator` and the `buffer_depth` also passed to the constructor. A
108 : * longer depth will ensure that the buffer updater is called less frequently,
109 : * which is useful for slow updaters (e.g. those that perform file access).
110 : * The main functionality is provided by the
111 : * `WorldtubeDataManager::populate_hypersurface_boundary_data()` member
112 : * function that handles buffer updating and boundary computation.
113 : */
114 1 : class MetricWorldtubeDataManager
115 : : public WorldtubeDataManager<
116 : Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>> {
117 : public:
118 : // charm needs an empty constructor.
119 0 : MetricWorldtubeDataManager() = default;
120 :
121 0 : MetricWorldtubeDataManager(
122 : std::unique_ptr<WorldtubeBufferUpdater<cce_metric_input_tags>>
123 : buffer_updater,
124 : size_t l_max, size_t buffer_depth,
125 : std::unique_ptr<intrp::SpanInterpolator> interpolator,
126 : bool fix_spec_normalization);
127 :
128 0 : WRAPPED_PUPable_decl_template(MetricWorldtubeDataManager); // NOLINT
129 :
130 0 : explicit MetricWorldtubeDataManager(CkMigrateMessage* /*unused*/) {}
131 :
132 : /*!
133 : * \brief Update the `boundary_data_box` entries for all tags in
134 : * `Tags::characteristic_worldtube_boundary_tags` to the boundary data at
135 : * `time`.
136 : *
137 : * \details First, if the stored buffer requires updating, it will be updated
138 : * via the `buffer_updater_` supplied in the constructor. Then, each of the
139 : * spatial metric, shift, lapse, and each of their radial and time derivatives
140 : * are interpolated across buffer points to the requested time value (via the
141 : * `Interpolator` provided in the constructor). Finally, that data is supplied
142 : * to the `create_bondi_boundary_data()`, which updates the
143 : * `boundary_data_box` with the Bondi spin-weighted scalars determined from
144 : * the interpolated Cartesian data.
145 : *
146 : * Returns `true` if the time can be supplied from the `buffer_updater_`, and
147 : * `false` otherwise. No tags are updated if `false` is returned.
148 : */
149 1 : bool populate_hypersurface_boundary_data(
150 : gsl::not_null<Variables<
151 : Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>>*>
152 : boundary_data_variables,
153 : double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const override;
154 :
155 0 : std::unique_ptr<WorldtubeDataManager> get_clone() const override;
156 :
157 : /// retrieves the l_max that will be supplied to the \ref DataBoxGroup in
158 : /// `populate_hypersurface_boundary_data()`
159 1 : size_t get_l_max() const override { return l_max_; }
160 :
161 : /// retrieves the current time span associated with the `buffer_updater_` for
162 : /// diagnostics
163 1 : std::pair<size_t, size_t> get_time_span() const override;
164 :
165 : /// Serialization for Charm++.
166 1 : void pup(PUP::er& p) override; // NOLINT
167 :
168 : private:
169 : std::unique_ptr<WorldtubeBufferUpdater<cce_metric_input_tags>>
170 0 : buffer_updater_;
171 : // NOLINTNEXTLINE(spectre-mutable)
172 0 : mutable size_t time_span_start_ = 0;
173 : // NOLINTNEXTLINE(spectre-mutable)
174 0 : mutable size_t time_span_end_ = 0;
175 0 : size_t l_max_ = 0;
176 0 : bool fix_spec_normalization_ = false;
177 :
178 : // These buffers are just kept around to avoid allocations; they're
179 : // updated every time a time is requested
180 : // NOLINTNEXTLINE(spectre-mutable)
181 0 : mutable Variables<cce_metric_input_tags> interpolated_coefficients_;
182 :
183 : // note: buffers store data in a 'time-varies-fastest' manner
184 : // NOLINTNEXTLINE(spectre-mutable)
185 0 : mutable Variables<cce_metric_input_tags> coefficients_buffers_;
186 :
187 0 : size_t buffer_depth_ = 0;
188 :
189 0 : std::unique_ptr<intrp::SpanInterpolator> interpolator_;
190 : };
191 :
192 : /*!
193 : * \brief Manages the 'reduced' cached buffer dataset associated with a CCE
194 : * worldtube and interpolates to requested time points to provide worldtube
195 : * boundary data to the main evolution routines.
196 : *
197 : * \details The maintained buffer will be kept at a length that is set by
198 : * the `Interpolator` and the `buffer_depth` also passed to the constructor. A
199 : * longer depth will ensure that the buffer updater is called less frequently,
200 : * which is useful for slow updaters (e.g. those that perform file access).
201 : * The main functionality is provided by the
202 : * `WorldtubeDataManager::populate_hypersurface_boundary_data()` member
203 : * function that handles buffer updating and boundary computation. This version
204 : * of the data manager handles the 9 scalars of
205 : * `cce_bondi_input_tags`, rather than direct metric components
206 : * handled by `WorldtubeDataManager`. The set of 9 scalars is a far leaner
207 : * (factor of ~4) data storage format.
208 : */
209 1 : class BondiWorldtubeDataManager
210 : : public WorldtubeDataManager<
211 : Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>> {
212 : public:
213 : // charm needs an empty constructor.
214 0 : BondiWorldtubeDataManager() = default;
215 :
216 0 : BondiWorldtubeDataManager(
217 : std::unique_ptr<WorldtubeBufferUpdater<cce_bondi_input_tags>>
218 : buffer_updater,
219 : size_t l_max, size_t buffer_depth,
220 : std::unique_ptr<intrp::SpanInterpolator> interpolator);
221 :
222 0 : WRAPPED_PUPable_decl_template(BondiWorldtubeDataManager); // NOLINT
223 :
224 0 : explicit BondiWorldtubeDataManager(CkMigrateMessage* /*unused*/) {}
225 :
226 : /*!
227 : * \brief Update the `boundary_data_box` entries for all tags in
228 : * `Tags::characteristic_worldtube_boundary_tags` to the boundary data at
229 : * `time`.
230 : *
231 : * \details First, if the stored buffer requires updating, it will be updated
232 : * via the `buffer_updater_` supplied in the constructor. Then, each of the
233 : * 9 spin-weighted scalars in `cce_bondi_input_tags`
234 : * are interpolated across buffer points to the requested time value (via the
235 : * `Interpolator` provided in the constructor). Finally, the remaining two
236 : * scalars not directly supplied in the input file are calculated in-line and
237 : * put in the \ref DataBoxGroup.
238 : *
239 : * Returns `true` if the time can be supplied from the `buffer_updater_`, and
240 : * `false` otherwise. No tags are updated if `false` is returned.
241 : */
242 1 : bool populate_hypersurface_boundary_data(
243 : gsl::not_null<Variables<
244 : Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>>*>
245 : boundary_data_variables,
246 : double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const override;
247 :
248 0 : std::unique_ptr<WorldtubeDataManager> get_clone() const override;
249 :
250 : /// retrieves the l_max that will be supplied to the \ref DataBoxGroup in
251 : /// `populate_hypersurface_boundary_data()`
252 1 : size_t get_l_max() const override { return l_max_; }
253 :
254 : /// retrieves the current time span associated with the `buffer_updater_` for
255 : /// diagnostics
256 1 : std::pair<size_t, size_t> get_time_span() const override;
257 :
258 : /// Serialization for Charm++.
259 1 : void pup(PUP::er& p) override; // NOLINT
260 :
261 : private:
262 0 : std::unique_ptr<WorldtubeBufferUpdater<cce_bondi_input_tags>> buffer_updater_;
263 : // NOLINTNEXTLINE(spectre-mutable)
264 0 : mutable size_t time_span_start_ = 0;
265 : // NOLINTNEXTLINE(spectre-mutable)
266 0 : mutable size_t time_span_end_ = 0;
267 0 : size_t l_max_ = 0;
268 :
269 : // These buffers are just kept around to avoid allocations; they're
270 : // updated every time a time is requested
271 : // NOLINTNEXTLINE(spectre-mutable)
272 0 : mutable Variables<cce_bondi_input_tags> interpolated_coefficients_;
273 :
274 : // note: buffers store data in an 'time-varies-fastest' manner
275 : // NOLINTNEXTLINE(spectre-mutable)
276 0 : mutable Variables<cce_bondi_input_tags> coefficients_buffers_;
277 :
278 0 : size_t buffer_depth_ = 0;
279 :
280 0 : std::unique_ptr<intrp::SpanInterpolator> interpolator_;
281 : };
282 :
283 0 : class KleinGordonWorldtubeDataManager
284 : : public WorldtubeDataManager<Tags::klein_gordon_worldtube_boundary_tags> {
285 : public:
286 : // charm needs an empty constructor.
287 0 : KleinGordonWorldtubeDataManager() = default;
288 :
289 0 : KleinGordonWorldtubeDataManager(
290 : std::unique_ptr<WorldtubeBufferUpdater<klein_gordon_input_tags>>
291 : buffer_updater,
292 : size_t l_max, size_t buffer_depth,
293 : std::unique_ptr<intrp::SpanInterpolator> interpolator);
294 :
295 0 : WRAPPED_PUPable_decl_template(KleinGordonWorldtubeDataManager); // NOLINT
296 :
297 0 : explicit KleinGordonWorldtubeDataManager(CkMigrateMessage* /*unused*/) {}
298 :
299 : /*!
300 : * \brief Update the `boundary_data_box` entries for all tags in
301 : * `Tags::klein_gordon_worldtube_boundary_tags` to the boundary data at
302 : * `time`.
303 : *
304 : * \details First, if the stored buffer requires updating, it will be updated
305 : * via the `buffer_updater_` supplied in the constructor. Then, each of the
306 : * 2 spin-weighted scalars in `Tags::klein_gordon_worldtube_boundary_tags`
307 : * are interpolated across buffer points to the requested time value (via the
308 : * `Interpolator` provided in the constructor).
309 : *
310 : * Returns `true` if the time can be supplied from the `buffer_updater_`, and
311 : * `false` otherwise. No tags are updated if `false` is returned.
312 : */
313 1 : bool populate_hypersurface_boundary_data(
314 : gsl::not_null<Variables<Tags::klein_gordon_worldtube_boundary_tags>*>
315 : boundary_data_variables,
316 : double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const override;
317 :
318 0 : std::unique_ptr<WorldtubeDataManager> get_clone() const override;
319 :
320 : /// retrieves the l_max that will be supplied to the \ref DataBoxGroup in
321 : /// `populate_hypersurface_boundary_data()`
322 1 : size_t get_l_max() const override { return l_max_; }
323 :
324 : /// retrieves the current time span associated with the `buffer_updater_` for
325 : /// diagnostics
326 1 : std::pair<size_t, size_t> get_time_span() const override;
327 :
328 : /// Serialization for Charm++.
329 1 : void pup(PUP::er& p) override; // NOLINT
330 :
331 : private:
332 : std::unique_ptr<WorldtubeBufferUpdater<klein_gordon_input_tags>>
333 0 : buffer_updater_;
334 : // NOLINTNEXTLINE(spectre-mutable)
335 0 : mutable size_t time_span_start_ = 0;
336 : // NOLINTNEXTLINE(spectre-mutable)
337 0 : mutable size_t time_span_end_ = 0;
338 0 : size_t l_max_ = 0;
339 :
340 : // These buffers are just kept around to avoid allocations; they're
341 : // updated every time a time is requested
342 : // NOLINTNEXTLINE(spectre-mutable)
343 0 : mutable Variables<klein_gordon_input_tags> interpolated_coefficients_;
344 :
345 : // note: buffers store data in an 'time-varies-fastest' manner
346 : // NOLINTNEXTLINE(spectre-mutable)
347 0 : mutable Variables<klein_gordon_input_tags> coefficients_buffers_;
348 :
349 0 : size_t buffer_depth_ = 0;
350 :
351 0 : std::unique_ptr<intrp::SpanInterpolator> interpolator_;
352 : };
353 : } // namespace Cce
|