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
|