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