Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <memory>
9 :
10 : #include "DataStructures/Tensor/TypeAliases.hpp"
11 : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
12 : #include "Options/String.hpp"
13 : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
14 : #include "PointwiseFunctions/AnalyticSolutions/GeneralRelativity/Solutions.hpp"
15 : #include "PointwiseFunctions/GeneralRelativity/TagsDeclarations.hpp"
16 : #include "PointwiseFunctions/MathFunctions/MathFunction.hpp"
17 : #include "Utilities/TMPL.hpp"
18 : #include "Utilities/TaggedTuple.hpp"
19 :
20 : /// \cond
21 : namespace PUP {
22 : class er;
23 : } // namespace PUP
24 : namespace Tags {
25 : template <typename Tag>
26 : struct dt;
27 : } // namespace Tags
28 : /// \endcond
29 :
30 1 : namespace gr::Solutions {
31 :
32 : /*!
33 : * \brief Gauge plane wave in flat spacetime
34 : *
35 : * \details
36 : * The spacetime metric is in Kerr-Schild form:
37 : * \f{equation}{
38 : * g_{\mu\nu} = \eta_{\mu\nu} + H l_\mu l_\nu
39 : * \f}
40 : * where \f$H\f$ is a scalar function of the coordinates, \f$\eta_{\mu\nu}\f$
41 : * is the Minkowski metric, and \f$l^\mu\f$ is a null vector. Note that the
42 : * form of the metric along with the nullness of \f$l^\mu\f$ allows one to
43 : * raise and lower indices of \f$l^\mu\f$ using \f$\eta_{\mu\nu}\f$, and
44 : * that \f$l^t l^t = l_t l_t = l^i l_i\f$.
45 : * Note also that
46 : * \f{equation}{
47 : * g^{\mu\nu} \equiv \eta^{\mu\nu} - H l^\mu l^\nu,
48 : * \f}
49 : * and that \f$\sqrt{-g}=1\f$.
50 : * Also, \f$l_\mu\f$ is a geodesic with respect to both the physical metric
51 : * and the Minkowski metric:
52 : * \f{equation}{
53 : * l^\mu \partial_\mu l_\nu = l^\mu\nabla_\mu l_\nu = 0.
54 : * \f}
55 : *
56 : * For this solution we choose the profile \f$H\f$ of the plane wave to be an
57 : * arbitrary one-dimensional function of \f$u = \vec{k} \cdot \vec{x} - \omega
58 : * t\f$ with a constant Euclidean wave vector \f$\vec{k}\f$ and frequency
59 : * \f$\omega = ||\vec{k}||\f$. The null covector is chosen to be \f$l_a =
60 : * (-\omega, k_i)\f$. Thus, if \f$H = H[u]\f$, then \f$\partial_\mu H = H'[u]
61 : * l_\mu\f$. Therefore the derivatives of the spacetime metric are:
62 : * \f{equation}{
63 : * \partial_\rho g_{\mu\nu} = H' l_\rho l_\mu l_\nu,
64 : * \f}
65 : *
66 : * The 3+1 quantities are
67 : * \f{align}{
68 : * \alpha & = \left( 1 + H \omega^2 \right)^{-1/2},\\
69 : * \beta^i & = \frac{-H \omega k^i}{1 + H \omega^2},\\
70 : * \gamma_{ij} & = \delta_{ij} + H k_i k_j,\\
71 : * \gamma & = 1 + H \omega^2,\\
72 : * \gamma^{ij} & = \delta^{ij} - \frac{H k^i k^j}{1 + H \omega^2},\\
73 : * \partial_t \alpha & = \frac{\omega^3 H'}{2 \left(1 + H \omega^2
74 : * \right)^{3/2}},\\
75 : * \partial_i \alpha & = - \frac{\omega^2 H' k_i}{2 \left(1 + H
76 : * \omega^2 \right)^{3/2}},\\
77 : * \partial_t \beta^i & = \frac{\omega^2 H' k^i}{\left(1 + H \omega^2
78 : * \right)^2},\\
79 : * \partial_j \beta^i & = - \frac{\omega H' k_j k^i}{\left(1 + H
80 : * \omega^2 \right)^2},\\
81 : * \partial_t \gamma_{ij} & = - \omega H' k_i k_j,\\
82 : * \partial_k \gamma_{ij} & = H' k_k k_i k_j,\\
83 : * K_{ij} & = - \frac{\omega H' k_i k_j}{2 \left(1 + H
84 : * \omega^2 \right)^{1/2}}.
85 : * \f}
86 : *
87 : * Note that this solution is a gauge wave as \f$\Gamma^a{}_{bc} = \frac{1}{2}
88 : * H' l^a l_b l_c\f$ and thus \f$R^a{}_{bcd} = 0\f$.
89 : *
90 : * \tparam Dim the spatial dimension of the solution
91 : */
92 : template <size_t Dim>
93 1 : class GaugePlaneWave : public AnalyticSolution<Dim>,
94 : public MarkAsAnalyticSolution {
95 : template <typename DataType>
96 : struct IntermediateVars;
97 :
98 : public:
99 0 : static constexpr size_t volume_dim = Dim;
100 0 : struct WaveVector {
101 0 : using type = std::array<double, Dim>;
102 0 : static constexpr Options::String help = {
103 : "The direction of propagation of the wave."};
104 : };
105 :
106 0 : struct Profile {
107 0 : using type = std::unique_ptr<MathFunction<1, Frame::Inertial>>;
108 0 : static constexpr Options::String help = {"The profile of the wave."};
109 : };
110 :
111 0 : using options = tmpl::list<WaveVector, Profile>;
112 0 : static constexpr Options::String help{"Gauge plane wave in flat spacetime"};
113 :
114 0 : GaugePlaneWave() = default;
115 0 : GaugePlaneWave(std::array<double, Dim> wave_vector,
116 : std::unique_ptr<MathFunction<1, Frame::Inertial>> profile);
117 0 : GaugePlaneWave(const GaugePlaneWave&);
118 0 : GaugePlaneWave& operator=(const GaugePlaneWave&);
119 0 : GaugePlaneWave(GaugePlaneWave&&) = default;
120 0 : GaugePlaneWave& operator=(GaugePlaneWave&&) = default;
121 0 : ~GaugePlaneWave() = default;
122 :
123 0 : explicit GaugePlaneWave(CkMigrateMessage* /*msg*/);
124 :
125 : template <typename DataType>
126 0 : using DerivLapse = ::Tags::deriv<gr::Tags::Lapse<DataType>,
127 : tmpl::size_t<volume_dim>, Frame::Inertial>;
128 : template <typename DataType>
129 0 : using DerivShift = ::Tags::deriv<gr::Tags::Shift<DataType, volume_dim>,
130 : tmpl::size_t<volume_dim>, Frame::Inertial>;
131 : template <typename DataType>
132 0 : using DerivSpatialMetric =
133 : ::Tags::deriv<gr::Tags::SpatialMetric<DataType, volume_dim>,
134 : tmpl::size_t<volume_dim>, Frame::Inertial>;
135 :
136 : template <typename DataType, typename... Tags>
137 0 : tuples::TaggedTuple<Tags...> variables(
138 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
139 : tmpl::list<Tags...> /*meta*/) const {
140 : const auto& vars =
141 : IntermediateVars<DataType>{wave_vector_, profile_, omega_, x, t};
142 : return {get<Tags>(variables(x, t, vars, tmpl::list<Tags>{}))...};
143 : }
144 :
145 : template <typename DataType, typename... Tags>
146 0 : tuples::TaggedTuple<Tags...> variables(
147 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
148 : const IntermediateVars<DataType>& vars,
149 : tmpl::list<Tags...> /*meta*/) const {
150 : static_assert(sizeof...(Tags) > 1,
151 : "Unrecognized tag requested. See the function parameters "
152 : "for the tag.");
153 : return {get<Tags>(variables(x, t, vars, tmpl::list<Tags>{}))...};
154 : }
155 :
156 : // NOLINTNEXTLINE(google-runtime-references)
157 0 : void pup(PUP::er& p);
158 :
159 : private:
160 : template <typename DataType>
161 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
162 : double t, const IntermediateVars<DataType>& vars,
163 : tmpl::list<gr::Tags::Lapse<DataType>> /*meta*/) const
164 : -> tuples::TaggedTuple<gr::Tags::Lapse<DataType>>;
165 :
166 : template <typename DataType>
167 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
168 : double t, const IntermediateVars<DataType>& vars,
169 : tmpl::list<::Tags::dt<gr::Tags::Lapse<DataType>>> /*meta*/)
170 : const -> tuples::TaggedTuple<::Tags::dt<gr::Tags::Lapse<DataType>>>;
171 :
172 : template <typename DataType>
173 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
174 : double t, const IntermediateVars<DataType>& vars,
175 : tmpl::list<DerivLapse<DataType>> /*meta*/) const
176 : -> tuples::TaggedTuple<DerivLapse<DataType>>;
177 :
178 : template <typename DataType>
179 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
180 : double t, const IntermediateVars<DataType>& vars,
181 : tmpl::list<gr::Tags::Shift<DataType, volume_dim>> /*meta*/)
182 : const -> tuples::TaggedTuple<gr::Tags::Shift<DataType, volume_dim>>;
183 :
184 : template <typename DataType>
185 0 : auto variables(
186 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
187 : const IntermediateVars<DataType>& vars,
188 : tmpl::list<::Tags::dt<gr::Tags::Shift<DataType, volume_dim>>> /*meta*/)
189 : const
190 : -> tuples::TaggedTuple<::Tags::dt<gr::Tags::Shift<DataType, volume_dim>>>;
191 :
192 : template <typename DataType>
193 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
194 : double t, const IntermediateVars<DataType>& vars,
195 : tmpl::list<DerivShift<DataType>> /*meta*/) const
196 : -> tuples::TaggedTuple<DerivShift<DataType>>;
197 :
198 : template <typename DataType>
199 0 : auto variables(
200 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
201 : const IntermediateVars<DataType>& vars,
202 : tmpl::list<gr::Tags::SpatialMetric<DataType, volume_dim>> /*meta*/) const
203 : -> tuples::TaggedTuple<gr::Tags::SpatialMetric<DataType, volume_dim>>;
204 :
205 : template <typename DataType>
206 0 : auto variables(
207 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
208 : const IntermediateVars<DataType>& vars,
209 : tmpl::list<
210 : ::Tags::dt<gr::Tags::SpatialMetric<DataType, volume_dim>>> /*meta*/)
211 : const -> tuples::TaggedTuple<
212 : ::Tags::dt<gr::Tags::SpatialMetric<DataType, volume_dim>>>;
213 :
214 : template <typename DataType>
215 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& /*x*/,
216 : double /*t*/, const IntermediateVars<DataType>& vars,
217 : tmpl::list<DerivSpatialMetric<DataType>> /*meta*/) const
218 : -> tuples::TaggedTuple<DerivSpatialMetric<DataType>>;
219 :
220 : template <typename DataType>
221 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& /*x*/,
222 : double /*t*/, const IntermediateVars<DataType>& vars,
223 : tmpl::list<gr::Tags::SqrtDetSpatialMetric<DataType>> /*meta*/)
224 : const -> tuples::TaggedTuple<gr::Tags::SqrtDetSpatialMetric<DataType>>;
225 :
226 : template <typename DataType>
227 0 : auto variables(
228 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
229 : const IntermediateVars<DataType>& vars,
230 : tmpl::list<gr::Tags::ExtrinsicCurvature<DataType, volume_dim>> /*meta*/)
231 : const -> tuples::TaggedTuple<
232 : gr::Tags::ExtrinsicCurvature<DataType, volume_dim>>;
233 :
234 : template <typename DataType>
235 0 : auto variables(
236 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
237 : const IntermediateVars<DataType>& vars,
238 : tmpl::list<gr::Tags::InverseSpatialMetric<DataType, volume_dim>> /*meta*/)
239 : const -> tuples::TaggedTuple<
240 : gr::Tags::InverseSpatialMetric<DataType, volume_dim>>;
241 :
242 : template <typename DataType>
243 0 : struct IntermediateVars {
244 0 : IntermediateVars(
245 : const std::array<double, Dim>& wave_vector,
246 : const std::unique_ptr<MathFunction<1, Frame::Inertial>>& profile,
247 : double omega, const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
248 : double t);
249 0 : DataType h{};
250 0 : DataType du_h{};
251 0 : DataType det_gamma{};
252 0 : DataType lapse{};
253 : };
254 :
255 : template <size_t LocalDim>
256 : // NOLINTNEXTLINE(readability-redundant-declaration)
257 0 : friend bool operator==(const GaugePlaneWave<LocalDim>& lhs,
258 : const GaugePlaneWave<LocalDim>& rhs);
259 : template <size_t LocalDim>
260 : // NOLINTNEXTLINE(readability-redundant-declaration)
261 0 : friend bool operator!=(const GaugePlaneWave<LocalDim>& lhs,
262 : const GaugePlaneWave<LocalDim>& rhs);
263 :
264 0 : std::array<double, Dim> wave_vector_{};
265 0 : std::unique_ptr<MathFunction<1, Frame::Inertial>> profile_;
266 0 : double omega_{};
267 : };
268 : } // namespace gr::Solutions
|