Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <limits>
8 : #include <optional>
9 : #include <stdexcept>
10 :
11 : #include "DataStructures/ComplexDataVector.hpp"
12 : #include "DataStructures/ComplexModalVector.hpp"
13 : #include "DataStructures/DataBox/Tag.hpp"
14 : #include "Evolution/Systems/Cce/AnalyticBoundaryDataManager.hpp"
15 : #include "Evolution/Systems/Cce/AnalyticSolutions/WorldtubeData.hpp"
16 : #include "Evolution/Systems/Cce/ExtractionRadius.hpp"
17 : #include "Evolution/Systems/Cce/Initialize/InitializeJ.hpp"
18 : #include "Evolution/Systems/Cce/InterfaceManagers/GhInterfaceManager.hpp"
19 : #include "Evolution/Systems/Cce/InterfaceManagers/GhLocalTimeStepping.hpp"
20 : #include "Evolution/Systems/Cce/InterfaceManagers/GhLockstep.hpp"
21 : #include "Evolution/Systems/Cce/WorldtubeDataManager.hpp"
22 : #include "NumericalAlgorithms/Interpolation/SpanInterpolator.hpp"
23 : #include "Options/Auto.hpp"
24 : #include "Options/String.hpp"
25 : #include "Parallel/Printf/Printf.hpp"
26 : #include "Utilities/PrettyType.hpp"
27 :
28 : namespace Cce {
29 : /// \brief %Option tags for CCE
30 1 : namespace OptionTags {
31 :
32 : /// %Option group
33 1 : struct Cce {
34 0 : static constexpr Options::String help = {
35 : "Options for the Cce evolution system"};
36 : };
37 :
38 : /// %Option group
39 1 : struct Filtering {
40 0 : static constexpr Options::String help = {"Options for the filtering in Cce"};
41 0 : using group = Cce;
42 : };
43 :
44 : /// %Option group for evolution-related quantities in the CCE system
45 1 : struct Evolution {
46 0 : static constexpr Options::String help = {"Options for the CCE evolution"};
47 0 : using group = Cce;
48 : };
49 :
50 : /// A prefix for common tags (e.g. from Time/Tags.hpp) that are specific to CCE,
51 : /// so should be in the Cce::Evolution group.
52 : template <typename OptionTag>
53 1 : struct CceEvolutionPrefix {
54 0 : using type = typename OptionTag::type;
55 0 : static std::string name() { return pretty_type::name<OptionTag>(); }
56 0 : static constexpr Options::String help = OptionTag::help;
57 0 : using group = Evolution;
58 : };
59 :
60 0 : struct BondiSachsOutputFilePrefix {
61 0 : using type = std::string;
62 0 : static constexpr Options::String help{
63 : "Filename prefix for dumping Bondi-Sachs data on worltube radii. Files "
64 : "will have this prefix prepended to 'CceRXXXX.h5' where XXXX will be the "
65 : "zero-padded extraction radius to the nearest integer."};
66 0 : using group = Cce;
67 : };
68 :
69 0 : struct FilterLMax {
70 0 : using type = size_t;
71 0 : static constexpr Options::String help{"l mode cutoff for angular filtering"};
72 0 : using group = Filtering;
73 : };
74 :
75 0 : struct RadialFilterAlpha {
76 0 : using type = double;
77 0 : static constexpr Options::String help{
78 : "alpha parameter in exponential radial filter"};
79 0 : using group = Filtering;
80 : };
81 :
82 0 : struct RadialFilterHalfPower {
83 0 : using type = size_t;
84 0 : static constexpr Options::String help{
85 : "Half-power of the exponential radial filter argument"};
86 0 : using group = Filtering;
87 : };
88 :
89 0 : struct ObservationLMax {
90 0 : using type = size_t;
91 0 : static constexpr Options::String help{"Maximum l value for swsh output"};
92 0 : using group = Cce;
93 : };
94 :
95 0 : struct ExtractionRadius {
96 0 : using type = double;
97 0 : static constexpr Options::String help{"Extraction radius of the CCE system."};
98 0 : using group = Cce;
99 : };
100 :
101 0 : struct StandaloneExtractionRadius {
102 0 : static std::string name() { return "ExtractionRadius"; }
103 0 : using type = Options::Auto<double>;
104 :
105 0 : static constexpr Options::String help{
106 : "Extraction radius of the CCE system for a standalone run. This may be "
107 : "set to \"Auto\" to infer the radius from the filename (often used for "
108 : "SpEC worldtube data)."};
109 0 : using group = Cce;
110 : };
111 :
112 0 : struct EndTime {
113 0 : using type = Options::Auto<double>;
114 0 : static constexpr Options::String help{"End time for the Cce Evolution."};
115 0 : static type suggested_value() { return {}; }
116 0 : using group = Cce;
117 : };
118 :
119 0 : struct StartTime {
120 0 : using type = Options::Auto<double>;
121 0 : static constexpr Options::String help{
122 : "Cce Start time (default to earliest possible time)."};
123 0 : static type suggested_value() { return {}; }
124 0 : using group = Cce;
125 : };
126 :
127 0 : struct BoundaryDataFilename {
128 0 : using type = std::string;
129 0 : static constexpr Options::String help{
130 : "H5 file to read the wordltube data from."};
131 0 : using group = Cce;
132 : };
133 :
134 0 : struct KleinGordonBoundaryDataFilename {
135 0 : using type = std::string;
136 0 : static constexpr Options::String help{
137 : "H5 file to read the Klein-Gordon wordltube data from. It could be the "
138 : "same as/different from `BoundaryDataFilename`."};
139 0 : using group = Cce;
140 : };
141 :
142 0 : struct H5LookaheadTimes {
143 0 : using type = size_t;
144 0 : static constexpr Options::String help{
145 : "Number of times steps from the h5 to cache each read."};
146 0 : static size_t suggested_value() { return 200; }
147 0 : using group = Cce;
148 : };
149 :
150 0 : struct H5Interpolator {
151 0 : using type = std::unique_ptr<intrp::SpanInterpolator>;
152 0 : static constexpr Options::String help{
153 : "The interpolator for imported h5 worldtube data."};
154 0 : using group = Cce;
155 : };
156 :
157 0 : struct AnalyticSolution {
158 0 : using type = std::unique_ptr<Solutions::WorldtubeData>;
159 0 : static constexpr Options::String help{
160 : "Analytic worldtube data for tests of CCE."};
161 0 : using group = Cce;
162 : };
163 :
164 0 : struct GhInterfaceManager {
165 0 : using type = InterfaceManagers::GhLocalTimeStepping;
166 0 : static constexpr Options::String help{
167 : "Class to manage worldtube data from a GH system."};
168 0 : using group = Cce;
169 : };
170 :
171 0 : struct ScriInterpolationOrder {
172 0 : static std::string name() { return "ScriInterpOrder"; }
173 0 : using type = size_t;
174 0 : static constexpr Options::String help{
175 : "Order of time interpolation at scri+."};
176 0 : static size_t suggested_value() { return 5; }
177 0 : using group = Cce;
178 : };
179 :
180 0 : struct ScriOutputDensity {
181 0 : using type = size_t;
182 0 : static constexpr Options::String help{
183 : "Number of scri output points per timestep."};
184 0 : static size_t suggested_value() { return 1; }
185 0 : using group = Cce;
186 : };
187 :
188 : template <bool evolve_ccm>
189 0 : struct InitializeJ {
190 0 : using type = std::unique_ptr<::Cce::InitializeJ::InitializeJ<evolve_ccm>>;
191 0 : static constexpr Options::String help{
192 : "The initialization for the first hypersurface for J"};
193 0 : using group = Cce;
194 : };
195 : } // namespace OptionTags
196 :
197 : /// \brief Initialization tags for CCE
198 1 : namespace InitializationTags {
199 0 : struct ScriInterpolationOrder : db::SimpleTag {
200 0 : using type = size_t;
201 0 : using option_tags = tmpl::list<OptionTags::ScriInterpolationOrder>;
202 :
203 0 : static constexpr bool pass_metavariables = false;
204 0 : static size_t create_from_options(
205 : const size_t scri_plus_interpolation_order) {
206 : return scri_plus_interpolation_order;
207 : }
208 : };
209 :
210 0 : struct ScriOutputDensity : db::SimpleTag {
211 0 : using type = size_t;
212 0 : using option_tags = tmpl::list<OptionTags::ScriOutputDensity>;
213 :
214 0 : static constexpr bool pass_metavariables = false;
215 0 : static size_t create_from_options(const size_t scri_output_density) {
216 : return scri_output_density;
217 : }
218 : };
219 : } // namespace InitializationTags
220 :
221 : namespace Tags {
222 0 : struct ExtractionRadius : db::SimpleTag {
223 0 : using type = double;
224 : };
225 :
226 0 : struct ExtractionRadiusSimple : ExtractionRadius {
227 0 : using base = ExtractionRadius;
228 0 : using option_tags = tmpl::list<OptionTags::ExtractionRadius>;
229 :
230 0 : static constexpr bool pass_metavariables = false;
231 0 : static double create_from_options(const double extraction_radius) {
232 : return extraction_radius;
233 : }
234 : };
235 :
236 0 : struct ExtractionRadiusFromH5 : ExtractionRadius {
237 0 : using base = ExtractionRadius;
238 0 : using option_tags = tmpl::list<OptionTags::BoundaryDataFilename,
239 : OptionTags::StandaloneExtractionRadius>;
240 :
241 0 : static constexpr bool pass_metavariables = false;
242 0 : static double create_from_options(
243 : const std::string& filename,
244 : const std::optional<double>& extraction_radius) {
245 : const std::optional<double> radius =
246 : Cce::get_extraction_radius(filename, extraction_radius);
247 : return radius.value();
248 : }
249 : };
250 :
251 0 : struct FilePrefix : db::SimpleTag {
252 0 : using type = std::string;
253 0 : using option_tags = tmpl::list<OptionTags::BondiSachsOutputFilePrefix>;
254 0 : static constexpr bool pass_metavariables = false;
255 0 : static type create_from_options(const type& option) { return option; }
256 : };
257 :
258 : /// Tag for duplicating functionality of another tag, but allows creation from
259 : /// options in the Cce::Evolution option group.
260 : template <typename Tag>
261 1 : struct CceEvolutionPrefix : Tag {
262 0 : using base = Tag;
263 0 : using type = typename Tag::type;
264 0 : using option_tags = db::wrap_tags_in<OptionTags::CceEvolutionPrefix,
265 : typename Tag::option_tags>;
266 0 : static std::string name() { return pretty_type::name<Tag>(); }
267 :
268 0 : static constexpr bool pass_metavariables = Tag::pass_metavariables;
269 : template <typename Metavariables, typename... Args>
270 0 : static type create_from_options(const Args&... args) {
271 : return Tag::template create_from_options<Metavariables>(args...);
272 : }
273 :
274 : template <typename... Args>
275 0 : static type create_from_options(const Args&... args) {
276 : return Tag::create_from_options(args...);
277 : }
278 : };
279 :
280 : /// A tag that constructs a `MetricWorldtubeDataManager` or
281 : /// `BondiWorldtubeDataManager` from options
282 1 : struct H5WorldtubeBoundaryDataManager : db::SimpleTag {
283 0 : using type = std::unique_ptr<WorldtubeDataManager<
284 : Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>>>;
285 0 : using option_tags =
286 : tmpl::list<Spectral::Swsh::OptionTags::LMax,
287 : OptionTags::BoundaryDataFilename, OptionTags::H5LookaheadTimes,
288 : OptionTags::H5Interpolator,
289 : OptionTags::StandaloneExtractionRadius>;
290 :
291 0 : static constexpr bool pass_metavariables = false;
292 0 : static type create_from_options(
293 : const size_t l_max, const std::string& filename,
294 : const size_t number_of_lookahead_times,
295 : const std::unique_ptr<intrp::SpanInterpolator>& interpolator,
296 : const std::optional<double> extraction_radius) {
297 : const std::string text_radius_str = Cce::get_text_radius(filename);
298 : try {
299 : // If this doesn't throw an exception, then an extraction radius was
300 : // supplied in the filename. We don't actually need the value.
301 : const double text_radius = std::stod(text_radius_str);
302 : (void)text_radius;
303 : if (extraction_radius.has_value()) {
304 : Parallel::printf(
305 : "Warning: Option ExtractionRadius is set to a specific value and "
306 : "there is an extraction radius in the H5 filename. The value in "
307 : "the file name will be ignored.It is recommended to set "
308 : "`ExtractionRadius` to `\"Auto\"` if the H5 filename has the "
309 : "extraction radius in it to make the input file clearer.\n");
310 : }
311 : } catch (const std::invalid_argument&) {
312 : }
313 :
314 : return std::make_unique<BondiWorldtubeDataManager>(
315 : std::make_unique<BondiWorldtubeH5BufferUpdater<ComplexModalVector>>(
316 : filename, extraction_radius),
317 : l_max, number_of_lookahead_times, interpolator->get_clone());
318 : }
319 : };
320 :
321 : /// A tag that constructs a `KleinGordonWorldtubeDataManager` from options
322 1 : struct KleinGordonH5WorldtubeBoundaryDataManager : db::SimpleTag {
323 0 : using type = std::unique_ptr<
324 : WorldtubeDataManager<Tags::klein_gordon_worldtube_boundary_tags>>;
325 0 : using option_tags =
326 : tmpl::list<Spectral::Swsh::OptionTags::LMax,
327 : OptionTags::KleinGordonBoundaryDataFilename,
328 : OptionTags::H5LookaheadTimes, OptionTags::H5Interpolator,
329 : OptionTags::StandaloneExtractionRadius>;
330 :
331 0 : static constexpr bool pass_metavariables = false;
332 0 : static type create_from_options(
333 : const size_t l_max, const std::string& filename,
334 : const size_t number_of_lookahead_times,
335 : const std::unique_ptr<intrp::SpanInterpolator>& interpolator,
336 : const std::optional<double> extraction_radius) {
337 : return std::make_unique<KleinGordonWorldtubeDataManager>(
338 : std::make_unique<KleinGordonWorldtubeH5BufferUpdater>(
339 : filename, extraction_radius),
340 : l_max, number_of_lookahead_times, interpolator->get_clone());
341 : }
342 : };
343 :
344 0 : struct ObservationLMax : db::SimpleTag {
345 0 : using type = size_t;
346 0 : using option_tags = tmpl::list<OptionTags::ObservationLMax>;
347 :
348 0 : static constexpr bool pass_metavariables = false;
349 0 : static size_t create_from_options(const size_t observation_l_max) {
350 : return observation_l_max;
351 : }
352 : };
353 :
354 0 : struct FilterLMax : db::SimpleTag {
355 0 : using type = size_t;
356 0 : using option_tags = tmpl::list<OptionTags::FilterLMax>;
357 :
358 0 : static constexpr bool pass_metavariables = false;
359 0 : static size_t create_from_options(const size_t filter_l_max) {
360 : return filter_l_max;
361 : }
362 : };
363 :
364 0 : struct RadialFilterAlpha : db::SimpleTag {
365 0 : using type = double;
366 0 : using option_tags = tmpl::list<OptionTags::RadialFilterAlpha>;
367 :
368 0 : static constexpr bool pass_metavariables = false;
369 0 : static double create_from_options(const double radial_filter_alpha) {
370 : return radial_filter_alpha;
371 : }
372 : };
373 :
374 0 : struct RadialFilterHalfPower : db::SimpleTag {
375 0 : using type = size_t;
376 0 : using option_tags = tmpl::list<OptionTags::RadialFilterHalfPower>;
377 :
378 0 : static constexpr bool pass_metavariables = false;
379 0 : static size_t create_from_options(const size_t radial_filter_half_power) {
380 : return radial_filter_half_power;
381 : }
382 : };
383 :
384 : /// \brief Represents the start time of a bounded CCE evolution, determined
385 : /// either from option specification or from the file
386 : ///
387 : /// \details If no start time is specified in the input file (so the option
388 : /// `OptionTags::StartTime` is set to "Auto"), this will find the start time
389 : /// from the provided H5 file. If `OptionTags::StartTime` takes any other value,
390 : /// it will be used directly as the start time for the CCE evolution instead.
391 1 : struct StartTimeFromFile : Tags::StartTime {
392 0 : using base = Tags::StartTime;
393 0 : using option_tags =
394 : tmpl::list<OptionTags::StartTime, OptionTags::BoundaryDataFilename,
395 : OptionTags::StandaloneExtractionRadius>;
396 :
397 0 : static constexpr bool pass_metavariables = false;
398 0 : static double create_from_options(
399 : const std::optional<double> start_time, const std::string& filename,
400 : const std::optional<double>& extraction_radius) {
401 : if (start_time.has_value()) {
402 : return *start_time;
403 : }
404 :
405 : BondiWorldtubeH5BufferUpdater<ComplexModalVector> h5_boundary_updater{
406 : filename, extraction_radius};
407 : const auto& time_buffer = h5_boundary_updater.get_time_buffer();
408 : return time_buffer[0];
409 : }
410 : };
411 :
412 : /// \brief Represents the start time of a bounded CCE evolution that must be
413 : /// supplied in the input file (for e.g. analytic tests).
414 1 : struct SpecifiedStartTime : Tags::StartTime {
415 0 : using base = Tags::StartTime;
416 0 : using option_tags = tmpl::list<OptionTags::StartTime>;
417 :
418 0 : static constexpr bool pass_metavariables = false;
419 0 : static double create_from_options(const std::optional<double> start_time) {
420 : if (not start_time.has_value()) {
421 : ERROR(
422 : "The start time must be explicitly specified for the tag "
423 : "`SpecifiedStartTime`");
424 : }
425 : return *start_time;
426 : }
427 : };
428 :
429 : /// \brief Represents the final time of a bounded CCE evolution, determined
430 : /// either from option specification or from the file
431 : ///
432 : /// \details If no end time is specified in the input file (so the option
433 : /// `OptionTags::EndTime` is set to "Auto"), this will find the end time
434 : /// from the provided H5 file. If `OptionTags::EndTime` takes any other value,
435 : /// it will be used directly as the final time for the CCE evolution instead.
436 1 : struct EndTimeFromFile : Tags::EndTime {
437 0 : using base = Tags::EndTime;
438 0 : using option_tags =
439 : tmpl::list<OptionTags::EndTime, OptionTags::BoundaryDataFilename,
440 : OptionTags::StandaloneExtractionRadius>;
441 :
442 0 : static constexpr bool pass_metavariables = false;
443 0 : static double create_from_options(
444 : const std::optional<double> end_time, const std::string& filename,
445 : const std::optional<double>& extraction_radius) {
446 : if (end_time) {
447 : return *end_time;
448 : }
449 : BondiWorldtubeH5BufferUpdater<ComplexModalVector> h5_boundary_updater{
450 : filename, extraction_radius};
451 : const auto& time_buffer = h5_boundary_updater.get_time_buffer();
452 : return time_buffer[time_buffer.size() - 1];
453 : }
454 : };
455 :
456 : /// \brief Represents the final time of a CCE evolution that should just proceed
457 : /// until it receives no more boundary data and becomes quiescent.
458 1 : struct NoEndTime : Tags::EndTime {
459 0 : using base = Tags::EndTime;
460 0 : using option_tags = tmpl::list<>;
461 :
462 0 : static constexpr bool pass_metavariables = false;
463 0 : static double create_from_options() {
464 : return std::numeric_limits<double>::infinity();
465 : }
466 : };
467 :
468 : /// \brief Represents the final time of a bounded CCE evolution that must be
469 : /// supplied in the input file (for e.g. analytic tests).
470 1 : struct SpecifiedEndTime : Tags::EndTime {
471 0 : using base = Tags::EndTime;
472 0 : using option_tags = tmpl::list<OptionTags::EndTime>;
473 :
474 0 : static constexpr bool pass_metavariables = false;
475 0 : static double create_from_options(const std::optional<double> end_time) {
476 : if (not end_time.has_value()) {
477 : ERROR(
478 : "The end time must be explicitly specified for the tag "
479 : "`SpecifiedEndTime`");
480 : }
481 : return *end_time;
482 : }
483 : };
484 :
485 0 : struct GhInterfaceManager : db::SimpleTag {
486 0 : using type = InterfaceManagers::GhLocalTimeStepping;
487 0 : using option_tags = tmpl::list<OptionTags::GhInterfaceManager>;
488 :
489 0 : static constexpr bool pass_metavariables = false;
490 0 : static InterfaceManagers::GhLocalTimeStepping create_from_options(
491 : const InterfaceManagers::GhLocalTimeStepping& interface_manager) {
492 : return interface_manager;
493 : }
494 : };
495 :
496 : /// Tag for first-hypersurface initialization procedure specified by input
497 : /// options.
498 : template <bool evolve_ccm>
499 1 : struct InitializeJ : db::SimpleTag {
500 0 : using type = std::unique_ptr<::Cce::InitializeJ::InitializeJ<evolve_ccm>>;
501 0 : using option_tags = tmpl::list<OptionTags::InitializeJ<evolve_ccm>>;
502 :
503 0 : static constexpr bool pass_metavariables = false;
504 : static std::unique_ptr<::Cce::InitializeJ::InitializeJ<evolve_ccm>>
505 0 : create_from_options(
506 : const std::unique_ptr<::Cce::InitializeJ::InitializeJ<evolve_ccm>>&
507 : initialize_j) {
508 : return initialize_j->get_clone();
509 : }
510 : };
511 :
512 : // Tags that generates an `Cce::InitializeJ::InitializeJ` derived class from an
513 : // analytic solution.
514 0 : struct AnalyticInitializeJ : InitializeJ<false> {
515 0 : using base = InitializeJ<false>;
516 0 : using option_tags =
517 : tmpl::list<OptionTags::AnalyticSolution, OptionTags::StartTime>;
518 0 : static constexpr bool pass_metavariables = false;
519 : static std::unique_ptr<::Cce::InitializeJ::InitializeJ<false>>
520 0 : create_from_options(
521 : const std::unique_ptr<Cce::Solutions::WorldtubeData>& worldtube_data,
522 : const std::optional<double> start_time) {
523 : return worldtube_data->get_initialize_j(*start_time);
524 : }
525 : };
526 :
527 : /// A tag that constructs a `AnalyticBoundaryDataManager` from options
528 1 : struct AnalyticBoundaryDataManager : db::SimpleTag {
529 0 : using type = ::Cce::AnalyticBoundaryDataManager;
530 0 : using option_tags =
531 : tmpl::list<OptionTags::ExtractionRadius, Spectral::Swsh::OptionTags::LMax,
532 : OptionTags::AnalyticSolution>;
533 :
534 0 : static constexpr bool pass_metavariables = false;
535 0 : static Cce::AnalyticBoundaryDataManager create_from_options(
536 : const double extraction_radius, const size_t l_max,
537 : const std::unique_ptr<Cce::Solutions::WorldtubeData>& worldtube_data) {
538 : return ::Cce::AnalyticBoundaryDataManager(l_max, extraction_radius,
539 : worldtube_data->get_clone());
540 : }
541 : };
542 :
543 : /// Represents whether the news should be provided at noninertial times.
544 : ///
545 : /// \details Currently, this is only useful for analytic solutions for which the
546 : /// inertial-time news is difficult to compute.
547 1 : struct OutputNoninertialNews : db::SimpleTag {
548 0 : using type = bool;
549 0 : using option_tags = tmpl::list<OptionTags::AnalyticSolution>;
550 0 : static constexpr bool pass_metavariables = false;
551 0 : static bool create_from_options(
552 : const std::unique_ptr<Cce::Solutions::WorldtubeData>& worldtube_data) {
553 : return worldtube_data->use_noninertial_news();
554 : }
555 : };
556 : } // namespace Tags
557 : } // namespace Cce
|