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 <memory> 8 : #include <string> 9 : #include <type_traits> 10 : #include <utility> 11 : 12 : #include "DataStructures/TaggedTuple.hpp" 13 : #include "DataStructures/Tensor/TypeAliases.hpp" 14 : #include "Options/String.hpp" 15 : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp" 16 : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp" 17 : #include "Utilities/PrettyType.hpp" 18 : #include "Utilities/Serialization/CharmPupable.hpp" 19 : #include "Utilities/TMPL.hpp" 20 : 21 : /// \cond 22 : class DataVector; 23 : namespace SecondOrderScalarWave::Tags { 24 : struct Psi; 25 : struct Pi; 26 : template <size_t Dim> 27 : struct Phi; 28 : } // namespace SecondOrderScalarWave::Tags 29 : namespace Tags { 30 : template <typename Tag> 31 : struct dt; 32 : } // namespace Tags 33 : namespace PUP { 34 : class er; 35 : } // namespace PUP 36 : /// \endcond 37 : 38 : namespace SecondOrderScalarWave::Solutions { 39 : /*! 40 : * \brief Adapts a `ScalarWave` analytic solution to an analytic solution of 41 : * the `SecondOrderScalarWave` system. 42 : * 43 : * The wrapped `SolutionType` supplies the mathematics of the solution together 44 : * with its variables and their time derivatives in the `ScalarWave` tag 45 : * namespace. This adapter re-exposes those quantities through the 46 : * `SecondOrderScalarWave` tags, adding the three `variables` interfaces the 47 : * second-order-in-space system requires: the evolved and auxiliary variables 48 : * \f$\{\Psi, \Pi, \Phi_i\}\f$, the evolved variables \f$\{\Psi, \Pi\}\f$, and 49 : * the time derivatives of the evolved variables 50 : * \f$\{\partial_t\Psi, \partial_t\Pi\}\f$. In the second-order-in-space system 51 : * only \f$\Psi\f$ and \f$\Pi\f$ are evolved; \f$\Phi_i\f$ is auxiliary and is 52 : * not evolved, so \f$\partial_t\Phi_i\f$ from the wrapped solution is 53 : * discarded. 54 : * 55 : * The wrapped solution is held by composition, so only the second-order 56 : * interface below is public; the `ScalarWave` interface of `SolutionType` is 57 : * not exposed. 58 : * 59 : * \tparam SolutionType a `ScalarWave` analytic solution to adapt 60 : */ 61 : template <typename SolutionType> 62 1 : class SecondOrderWrapper : public evolution::initial_data::InitialData, 63 : public MarkAsAnalyticSolution { 64 : private: 65 : // Lifetime-safe backing storage for `help`, built on first use so it is 66 : // constructed before `help` reads it. 67 0 : static const std::string& help_storage() { 68 : static const std::string storage = 69 : "Adapts a ScalarWave analytic solution for SecondOrderScalarWave.\n" + 70 : std::string{SolutionType::help}; 71 : return storage; 72 : } 73 : 74 : public: 75 0 : SecondOrderWrapper() = default; 76 0 : SecondOrderWrapper(const SecondOrderWrapper& /*rhs*/) = default; 77 0 : SecondOrderWrapper& operator=(const SecondOrderWrapper& /*rhs*/) = default; 78 0 : SecondOrderWrapper(SecondOrderWrapper&& /*rhs*/) = default; 79 0 : SecondOrderWrapper& operator=(SecondOrderWrapper&& /*rhs*/) = default; 80 0 : ~SecondOrderWrapper() override = default; 81 : 82 0 : explicit SecondOrderWrapper(SolutionType solution) 83 : : wrapped_solution_(std::move(solution)) {} 84 : 85 : template <typename... Args> 86 : requires std::is_constructible_v<SolutionType, Args&&...> 87 0 : explicit SecondOrderWrapper(Args&&... args) 88 : : wrapped_solution_(std::forward<Args>(args)...) {} 89 : 90 0 : auto get_clone() const 91 : -> std::unique_ptr<evolution::initial_data::InitialData> override; 92 : 93 : /// \cond 94 : explicit SecondOrderWrapper(CkMigrateMessage* msg); 95 : using PUP::able::register_constructor; 96 : WRAPPED_PUPable_decl_template(SecondOrderWrapper); 97 : /// \endcond 98 : 99 0 : static constexpr size_t volume_dim = SolutionType::volume_dim; 100 0 : using options = typename SolutionType::options; 101 0 : inline static Options::String help = help_storage().c_str(); 102 0 : static std::string name() { 103 : return "SecondOrder" + pretty_type::name<SolutionType>(); 104 : } 105 : 106 0 : using tags = tmpl::list<SecondOrderScalarWave::Tags::Psi, 107 : SecondOrderScalarWave::Tags::Pi, 108 : SecondOrderScalarWave::Tags::Phi<volume_dim>, 109 : ::Tags::dt<SecondOrderScalarWave::Tags::Psi>, 110 : ::Tags::dt<SecondOrderScalarWave::Tags::Pi>>; 111 : 112 : /// Retrieve the evolved and auxiliary variables (Psi, Pi, Phi) at time `t` 113 : /// and spatial coordinates `x` 114 : tuples::TaggedTuple<SecondOrderScalarWave::Tags::Psi, 115 : SecondOrderScalarWave::Tags::Pi, 116 : SecondOrderScalarWave::Tags::Phi<volume_dim>> 117 1 : variables(const tnsr::I<DataVector, volume_dim>& x, double t, 118 : tmpl::list<SecondOrderScalarWave::Tags::Psi, 119 : SecondOrderScalarWave::Tags::Pi, 120 : SecondOrderScalarWave::Tags::Phi<volume_dim>> 121 : /*meta*/) const; 122 : 123 : /// Retrieve the evolved variables (Psi, Pi) 124 : tuples::TaggedTuple<SecondOrderScalarWave::Tags::Psi, 125 : SecondOrderScalarWave::Tags::Pi> 126 1 : variables(const tnsr::I<DataVector, volume_dim>& x, double t, 127 : tmpl::list<SecondOrderScalarWave::Tags::Psi, 128 : SecondOrderScalarWave::Tags::Pi> /*meta*/) const; 129 : 130 : /// Retrieve the time derivatives of the evolved variables (dt(Psi), dt(Pi)) 131 : /// at time `t` and spatial coordinates `x` 132 : tuples::TaggedTuple<::Tags::dt<SecondOrderScalarWave::Tags::Psi>, 133 : ::Tags::dt<SecondOrderScalarWave::Tags::Pi>> 134 1 : variables(const tnsr::I<DataVector, volume_dim>& x, double t, 135 : tmpl::list<::Tags::dt<SecondOrderScalarWave::Tags::Psi>, 136 : ::Tags::dt<SecondOrderScalarWave::Tags::Pi>> 137 : /*meta*/) const; 138 : 139 : // NOLINTNEXTLINE(google-runtime-references) 140 0 : void pup(PUP::er& p) override; 141 : 142 : private: 143 0 : friend bool operator==(const SecondOrderWrapper& lhs, 144 : const SecondOrderWrapper& rhs) { 145 : return lhs.wrapped_solution_ == rhs.wrapped_solution_; 146 : } 147 0 : friend bool operator!=(const SecondOrderWrapper& lhs, 148 : const SecondOrderWrapper& rhs) { 149 : return not(lhs == rhs); 150 : } 151 : 152 0 : SolutionType wrapped_solution_{}; 153 : }; 154 : } // namespace SecondOrderScalarWave::Solutions