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 <memory>
9 : #include <string>
10 : #include <tuple>
11 : #include <vector>
12 :
13 : #include "Evolution/Systems/Cce/AnalyticSolutions/WorldtubeData.hpp"
14 : #include "Evolution/Systems/Cce/BoundaryData.hpp"
15 : #include "Evolution/Systems/Cce/Tags.hpp"
16 : #include "Evolution/Systems/Cce/WorldtubeDataManager.hpp"
17 : #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
18 : #include "IO/Observer/ObserverComponent.hpp"
19 : #include "IO/Observer/ReductionActions.hpp"
20 : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshCoefficients.hpp"
21 : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshTransform.hpp"
22 : #include "Parallel/GlobalCache.hpp"
23 : #include "Parallel/Invoke.hpp"
24 : #include "Parallel/Local.hpp"
25 : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
26 : #include "Utilities/MakeString.hpp"
27 : #include "Utilities/Serialization/CharmPupable.hpp"
28 : #include "Utilities/System/ParallelInfo.hpp"
29 :
30 : namespace Cce {
31 1 : namespace Tags {
32 : /// \cond
33 : struct ObservationLMax;
34 : /// \endcond
35 : } // namespace Tags
36 :
37 : /// A boundary data manager that constructs the desired boundary data into
38 : /// the `Variables` from the data provided by the analytic solution.
39 1 : class AnalyticBoundaryDataManager {
40 : public:
41 : // charm needs an empty constructor.
42 0 : AnalyticBoundaryDataManager() = default;
43 :
44 0 : AnalyticBoundaryDataManager(
45 : size_t l_max, double extraction_radius,
46 : std::unique_ptr<Solutions::WorldtubeData> generator);
47 :
48 : /*!
49 : * \brief Update the `boundary_data_variables` entries for all tags in
50 : * `Tags::characteristic_worldtube_boundary_tags` to the boundary data from
51 : * the analytic solution at `time`.
52 : *
53 : * \details This class retrieves metric boundary data from the
54 : * `Cce::Solutions::WorldtubeData` derived class that represents an analytic
55 : * solution, then dispatches to `Cce::create_bondi_boundary_data()` to
56 : * construct the Bondi values into the provided `Variables`
57 : */
58 1 : bool populate_hypersurface_boundary_data(
59 : gsl::not_null<Variables<
60 : Tags::characteristic_worldtube_boundary_tags<Tags::BoundaryValue>>*>
61 : boundary_data_variables,
62 : double time) const;
63 :
64 : /// Use `observers::ThreadedActions::WriteSimpleData` to output the expected
65 : /// news at `time` from the analytic data to dataset `/expected_news.dat`.
66 : template <typename ParallelComponent, typename Metavariables>
67 1 : void write_news(Parallel::GlobalCache<Metavariables>& cache,
68 : double time) const;
69 :
70 0 : size_t get_l_max() const { return l_max_; }
71 :
72 0 : const Solutions::WorldtubeData& get_generator() const { return *generator_; }
73 :
74 : /// Serialization for Charm++.
75 : // NOLINTNEXTLINE(google-runtime-references)
76 1 : void pup(PUP::er& p);
77 :
78 : private:
79 0 : size_t l_max_ = 0;
80 0 : std::unique_ptr<Solutions::WorldtubeData> generator_;
81 0 : double extraction_radius_ = std::numeric_limits<double>::signaling_NaN();
82 : };
83 :
84 : template <typename ParallelComponent, typename Metavariables>
85 : void AnalyticBoundaryDataManager::write_news(
86 : Parallel::GlobalCache<Metavariables>& cache, const double time) const {
87 : const auto news = get<Tags::News>(
88 : generator_->variables(l_max_, time, tmpl::list<Tags::News>{}));
89 : const size_t observation_l_max = Parallel::get<Tags::ObservationLMax>(cache);
90 : std::vector<double> data_to_write(2 * square(observation_l_max + 1) + 1);
91 : std::vector<std::string> file_legend;
92 : file_legend.reserve(2 * square(observation_l_max + 1) + 1);
93 : file_legend.emplace_back("time");
94 : for (int i = 0; i <= static_cast<int>(observation_l_max); ++i) {
95 : for (int j = -i; j <= i; ++j) {
96 : file_legend.push_back(MakeString{} << "Real Y_" << i << "," << j);
97 : file_legend.push_back(MakeString{} << "Imag Y_" << i << "," << j);
98 : }
99 : }
100 : const ComplexModalVector goldberg_modes =
101 : Spectral::Swsh::libsharp_to_goldberg_modes(
102 : Spectral::Swsh::swsh_transform(l_max_, 1, get(news)), l_max_)
103 : .data();
104 : data_to_write[0] = time;
105 : for (size_t i = 0; i < square(observation_l_max + 1); ++i) {
106 : data_to_write[2 * i + 1] = real(goldberg_modes[i]);
107 : data_to_write[2 * i + 2] = imag(goldberg_modes[i]);
108 : }
109 : auto observer_proxy = Parallel::get_parallel_component<
110 : observers::ObserverWriter<Metavariables>>(cache)[0];
111 : const std::string prefix =
112 : generator_->use_noninertial_news() ? "Noninertial_" : "";
113 : Parallel::threaded_action<observers::ThreadedActions::WriteReductionDataRow>(
114 : observer_proxy, "/Cce/News_" + prefix + "expected"s, file_legend,
115 : std::make_tuple(data_to_write));
116 : }
117 : } // namespace Cce
|