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 : // Compute the boundary value of `Du<Dr<BondiJ>>` at the requested time by
267 : // numerically time-differentiating the buffered `Dr<BondiJ>` with
268 : // `interpolator_`, holding the angular coordinate fixed (i.e. following the
269 : // worldtube). This is the time derivative at constant numerical coordinate
270 : // y = -1, i.e. d_ubreve d_r J|_Gamma = d/du (d_r J|_Gamma), and is *not* a
271 : // derivative at constant Bondi r.
272 0 : void populate_boundary_du_dr_j(
273 : gsl::not_null<Variables<
274 : Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>>*>
275 : boundary_data_variables,
276 : double time) const;
277 :
278 : std::unique_ptr<
279 : WorldtubeBufferUpdater<Tags::worldtube_boundary_tags_for_writing<
280 : Spectral::Swsh::Tags::SwshTransform>>>
281 0 : buffer_updater_;
282 : // NOLINTNEXTLINE(spectre-mutable)
283 0 : mutable size_t time_span_start_ = 0;
284 : // NOLINTNEXTLINE(spectre-mutable)
285 0 : mutable size_t time_span_end_ = 0;
286 0 : size_t l_max_ = 0;
287 :
288 : // These buffers are just kept around to avoid allocations; they're
289 : // updated every time a time is requested
290 : // NOLINTNEXTLINE(spectre-mutable)
291 : mutable Variables<Tags::worldtube_boundary_tags_for_writing<
292 : Spectral::Swsh::Tags::SwshTransform>>
293 0 : interpolated_coefficients_;
294 :
295 : // note: buffers store data in an 'time-varies-fastest' manner
296 : // NOLINTNEXTLINE(spectre-mutable)
297 : mutable Variables<Tags::worldtube_boundary_tags_for_writing<
298 : Spectral::Swsh::Tags::SwshTransform>>
299 0 : coefficients_buffers_;
300 :
301 0 : size_t buffer_depth_ = 0;
302 :
303 0 : std::unique_ptr<intrp::SpanInterpolator> interpolator_;
304 : };
305 :
306 0 : class KleinGordonWorldtubeDataManager
307 : : public WorldtubeDataManager<Tags::klein_gordon_worldtube_boundary_tags> {
308 : public:
309 : // charm needs an empty constructor.
310 0 : KleinGordonWorldtubeDataManager() = default;
311 :
312 0 : KleinGordonWorldtubeDataManager(
313 : std::unique_ptr<WorldtubeBufferUpdater<klein_gordon_input_tags>>
314 : buffer_updater,
315 : size_t l_max, size_t buffer_depth,
316 : std::unique_ptr<intrp::SpanInterpolator> interpolator);
317 :
318 0 : WRAPPED_PUPable_decl_template(KleinGordonWorldtubeDataManager); // NOLINT
319 :
320 0 : explicit KleinGordonWorldtubeDataManager(CkMigrateMessage* /*unused*/) {}
321 :
322 : /*!
323 : * \brief Update the `boundary_data_box` entries for all tags in
324 : * `Tags::klein_gordon_worldtube_boundary_tags` to the boundary data at
325 : * `time`.
326 : *
327 : * \details First, if the stored buffer requires updating, it will be updated
328 : * via the `buffer_updater_` supplied in the constructor. Then, each of the
329 : * 2 spin-weighted scalars in `Tags::klein_gordon_worldtube_boundary_tags`
330 : * are interpolated across buffer points to the requested time value (via the
331 : * `Interpolator` provided in the constructor).
332 : *
333 : * Returns `true` if the time can be supplied from the `buffer_updater_`, and
334 : * `false` otherwise. No tags are updated if `false` is returned.
335 : */
336 1 : bool populate_hypersurface_boundary_data(
337 : gsl::not_null<Variables<Tags::klein_gordon_worldtube_boundary_tags>*>
338 : boundary_data_variables,
339 : double time, gsl::not_null<Parallel::NodeLock*> hdf5_lock) const override;
340 :
341 0 : std::unique_ptr<WorldtubeDataManager> get_clone() const override;
342 :
343 : /// retrieves the l_max that will be supplied to the \ref DataBoxGroup in
344 : /// `populate_hypersurface_boundary_data()`
345 1 : size_t get_l_max() const override { return l_max_; }
346 :
347 : /// retrieves the current time span associated with the `buffer_updater_` for
348 : /// diagnostics
349 1 : std::pair<size_t, size_t> get_time_span() const override;
350 :
351 : /// Serialization for Charm++.
352 1 : void pup(PUP::er& p) override; // NOLINT
353 :
354 : private:
355 : std::unique_ptr<WorldtubeBufferUpdater<klein_gordon_input_tags>>
356 0 : buffer_updater_;
357 : // NOLINTNEXTLINE(spectre-mutable)
358 0 : mutable size_t time_span_start_ = 0;
359 : // NOLINTNEXTLINE(spectre-mutable)
360 0 : mutable size_t time_span_end_ = 0;
361 0 : size_t l_max_ = 0;
362 :
363 : // These buffers are just kept around to avoid allocations; they're
364 : // updated every time a time is requested
365 : // NOLINTNEXTLINE(spectre-mutable)
366 0 : mutable Variables<klein_gordon_input_tags> interpolated_coefficients_;
367 :
368 : // note: buffers store data in an 'time-varies-fastest' manner
369 : // NOLINTNEXTLINE(spectre-mutable)
370 0 : mutable Variables<klein_gordon_input_tags> coefficients_buffers_;
371 :
372 0 : size_t buffer_depth_ = 0;
373 :
374 0 : std::unique_ptr<intrp::SpanInterpolator> interpolator_;
375 : };
376 : } // namespace Cce
|