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 : public:
96 0 : static constexpr size_t volume_dim = Dim;
97 0 : struct WaveVector {
98 0 : using type = std::array<double, Dim>;
99 0 : static constexpr Options::String help = {
100 : "The direction of propagation of the wave."};
101 : };
102 :
103 0 : struct Profile {
104 0 : using type = std::unique_ptr<MathFunction<1, Frame::Inertial>>;
105 0 : static constexpr Options::String help = {"The profile of the wave."};
106 : };
107 :
108 0 : using options = tmpl::list<WaveVector, Profile>;
109 0 : static constexpr Options::String help{"Gauge plane wave in flat spacetime"};
110 :
111 0 : GaugePlaneWave() = default;
112 0 : GaugePlaneWave(const std::array<double, Dim>& wave_vector,
113 : std::unique_ptr<MathFunction<1, Frame::Inertial>> profile);
114 0 : GaugePlaneWave(const GaugePlaneWave&);
115 0 : GaugePlaneWave& operator=(const GaugePlaneWave&);
116 0 : GaugePlaneWave(GaugePlaneWave&&) = default;
117 0 : GaugePlaneWave& operator=(GaugePlaneWave&&) = default;
118 0 : ~GaugePlaneWave() = default;
119 :
120 0 : explicit GaugePlaneWave(CkMigrateMessage* /*msg*/);
121 :
122 : template <typename DataType>
123 0 : using DerivLapse = ::Tags::deriv<gr::Tags::Lapse<DataType>,
124 : tmpl::size_t<volume_dim>, Frame::Inertial>;
125 : template <typename DataType>
126 0 : using DerivShift = ::Tags::deriv<gr::Tags::Shift<DataType, volume_dim>,
127 : tmpl::size_t<volume_dim>, Frame::Inertial>;
128 : template <typename DataType>
129 0 : using DerivSpatialMetric =
130 : ::Tags::deriv<gr::Tags::SpatialMetric<DataType, volume_dim>,
131 : tmpl::size_t<volume_dim>, Frame::Inertial>;
132 :
133 : template <typename DataType>
134 0 : struct IntermediateVars {
135 0 : IntermediateVars(
136 : const std::array<double, Dim>& wave_vector,
137 : const std::unique_ptr<MathFunction<1, Frame::Inertial>>& profile,
138 : double omega, const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
139 : double t);
140 0 : DataType h{};
141 0 : DataType du_h{};
142 0 : DataType du_du_h{};
143 0 : DataType det_gamma{};
144 0 : DataType lapse{};
145 : };
146 :
147 : template <typename DataType, typename... Tags>
148 0 : tuples::TaggedTuple<Tags...> variables(
149 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
150 : tmpl::list<Tags...> /*meta*/) const {
151 : const auto& vars =
152 : IntermediateVars<DataType>{wave_vector_, profile_, omega_, x, t};
153 : return {get<Tags>(variables(x, t, vars, tmpl::list<Tags>{}))...};
154 : }
155 :
156 : template <typename DataType, typename... Tags>
157 0 : tuples::TaggedTuple<Tags...> variables(
158 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
159 : const IntermediateVars<DataType>& vars,
160 : tmpl::list<Tags...> /*meta*/) const {
161 : static_assert(sizeof...(Tags) > 1,
162 : "Unrecognized tag requested. See the function parameters "
163 : "for the tag.");
164 : return {get<Tags>(variables(x, t, vars, tmpl::list<Tags>{}))...};
165 : }
166 :
167 0 : std::array<double, Dim> get_wave_vector() const { return wave_vector_; }
168 :
169 : // NOLINTNEXTLINE(google-runtime-references)
170 0 : void pup(PUP::er& p);
171 :
172 : private:
173 : template <typename DataType>
174 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
175 : double t, const IntermediateVars<DataType>& vars,
176 : tmpl::list<gr::Tags::Lapse<DataType>> /*meta*/) const
177 : -> tuples::TaggedTuple<gr::Tags::Lapse<DataType>>;
178 :
179 : template <typename DataType>
180 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
181 : double t, const IntermediateVars<DataType>& vars,
182 : tmpl::list<::Tags::dt<gr::Tags::Lapse<DataType>>> /*meta*/)
183 : const -> tuples::TaggedTuple<::Tags::dt<gr::Tags::Lapse<DataType>>>;
184 :
185 : template <typename DataType>
186 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
187 : double t, const IntermediateVars<DataType>& vars,
188 : tmpl::list<DerivLapse<DataType>> /*meta*/) const
189 : -> tuples::TaggedTuple<DerivLapse<DataType>>;
190 :
191 : template <typename DataType>
192 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
193 : double t, const IntermediateVars<DataType>& vars,
194 : tmpl::list<gr::Tags::Shift<DataType, volume_dim>> /*meta*/)
195 : const -> tuples::TaggedTuple<gr::Tags::Shift<DataType, volume_dim>>;
196 :
197 : template <typename DataType>
198 0 : auto variables(
199 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
200 : const IntermediateVars<DataType>& vars,
201 : tmpl::list<::Tags::dt<gr::Tags::Shift<DataType, volume_dim>>> /*meta*/)
202 : const
203 : -> tuples::TaggedTuple<::Tags::dt<gr::Tags::Shift<DataType, volume_dim>>>;
204 :
205 : template <typename DataType>
206 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
207 : double t, const IntermediateVars<DataType>& vars,
208 : tmpl::list<DerivShift<DataType>> /*meta*/) const
209 : -> tuples::TaggedTuple<DerivShift<DataType>>;
210 :
211 : template <typename DataType>
212 0 : auto variables(
213 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
214 : const IntermediateVars<DataType>& vars,
215 : tmpl::list<gr::Tags::SpatialMetric<DataType, volume_dim>> /*meta*/) const
216 : -> tuples::TaggedTuple<gr::Tags::SpatialMetric<DataType, volume_dim>>;
217 :
218 : template <typename DataType>
219 0 : auto variables(
220 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
221 : const IntermediateVars<DataType>& vars,
222 : tmpl::list<
223 : ::Tags::dt<gr::Tags::SpatialMetric<DataType, volume_dim>>> /*meta*/)
224 : const -> tuples::TaggedTuple<
225 : ::Tags::dt<gr::Tags::SpatialMetric<DataType, volume_dim>>>;
226 :
227 : template <typename DataType>
228 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& /*x*/,
229 : double /*t*/, const IntermediateVars<DataType>& vars,
230 : tmpl::list<DerivSpatialMetric<DataType>> /*meta*/) const
231 : -> tuples::TaggedTuple<DerivSpatialMetric<DataType>>;
232 :
233 : template <typename DataType>
234 0 : auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& /*x*/,
235 : double /*t*/, const IntermediateVars<DataType>& vars,
236 : tmpl::list<gr::Tags::SqrtDetSpatialMetric<DataType>> /*meta*/)
237 : const -> tuples::TaggedTuple<gr::Tags::SqrtDetSpatialMetric<DataType>>;
238 :
239 : template <typename DataType>
240 0 : auto variables(
241 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
242 : const IntermediateVars<DataType>& vars,
243 : tmpl::list<gr::Tags::ExtrinsicCurvature<DataType, volume_dim>> /*meta*/)
244 : const -> tuples::TaggedTuple<
245 : gr::Tags::ExtrinsicCurvature<DataType, volume_dim>>;
246 :
247 : template <typename DataType>
248 0 : auto variables(
249 : const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
250 : const IntermediateVars<DataType>& vars,
251 : tmpl::list<gr::Tags::InverseSpatialMetric<DataType, volume_dim>> /*meta*/)
252 : const -> tuples::TaggedTuple<
253 : gr::Tags::InverseSpatialMetric<DataType, volume_dim>>;
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
|