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