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