Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <complex>
7 : #include <cstddef>
8 : #include <memory>
9 : #include <vector>
10 :
11 : #include "DataStructures/SpinWeighted.hpp"
12 : #include "Evolution/Systems/Cce/AnalyticSolutions/SphericalMetricData.hpp"
13 : #include "Evolution/Systems/Cce/AnalyticSolutions/WorldtubeData.hpp"
14 : #include "Evolution/Systems/Cce/Tags.hpp"
15 : #include "Options/String.hpp"
16 : #include "Utilities/Gsl.hpp"
17 : #include "Utilities/Literals.hpp"
18 : #include "Utilities/Serialization/CharmPupable.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : /// \cond
22 : class DataVector;
23 : class ComplexDataVector;
24 : /// \endcond
25 :
26 : namespace Cce {
27 : namespace Solutions {
28 :
29 : /*!
30 : * \brief Computes the analytic data for a gauge wave solution described in
31 : * \cite Barkett2019uae.
32 : *
33 : * \details This test computes an analytic solution of a pure-gauge perturbation
34 : * of the Schwarzschild metric. The gauge perturbation is constructed using the
35 : * time-dependent coordinate transformation of the ingoing Eddington-Finklestein
36 : * coordinate \f$\nu \rightarrow \nu + F(t - r) / r\f$, where
37 : *
38 : * \f[
39 : * F(u) = A \sin(\omega u) e^{- (u - u_0)^2 / k^2}.
40 : * \f]
41 : *
42 : * \note In the paper \cite Barkett2019uae, a translation map was
43 : * applied to the solution to make the test more demanding. For simplicity, we
44 : * omit that extra map. The behavior of translation-independence is
45 : * tested by the `Cce::Solutions::BouncingBlackHole` solution.
46 : */
47 1 : struct GaugeWave : public SphericalMetricData {
48 0 : struct ExtractionRadius {
49 0 : using type = double;
50 0 : static constexpr Options::String help{
51 : "The extraction radius of the spherical solution"};
52 0 : static type lower_bound() { return 0.0; }
53 : };
54 0 : struct Mass {
55 0 : using type = double;
56 0 : static constexpr Options::String help{
57 : "The mass of the Schwarzschild solution."};
58 0 : static type lower_bound() { return 0.0; }
59 : };
60 0 : struct Frequency {
61 0 : using type = double;
62 0 : static constexpr Options::String help{
63 : "The frequency of the oscillation of the gauge wave."};
64 0 : static type lower_bound() { return 0.0; }
65 : };
66 0 : struct Amplitude {
67 0 : using type = double;
68 0 : static constexpr Options::String help{
69 : "The amplitude of the gauge wave."};
70 0 : static type lower_bound() { return 0.0; }
71 : };
72 0 : struct PeakTime {
73 0 : using type = double;
74 0 : static constexpr Options::String help{
75 : "The time of the peak of the Gaussian envelope."};
76 0 : static type lower_bound() { return 0.0; }
77 : };
78 0 : struct Duration {
79 0 : using type = double;
80 0 : static constexpr Options::String help{
81 : "The characteristic duration of the Gaussian envelope."};
82 0 : static type lower_bound() { return 0.0; }
83 : };
84 :
85 0 : using options = tmpl::list<ExtractionRadius, Mass, Frequency, Amplitude,
86 : PeakTime, Duration>;
87 :
88 0 : static constexpr Options::String help = {
89 : "Analytic solution representing worldtube data for a pure-gauge "
90 : "perturbation near a Schwarzschild metric in spherical coordinates"};
91 :
92 0 : WRAPPED_PUPable_decl_template(GaugeWave); // NOLINT
93 :
94 0 : explicit GaugeWave(CkMigrateMessage* msg) : SphericalMetricData(msg) {}
95 :
96 : // clang doesn't manage to use = default correctly in this case
97 : // NOLINTNEXTLINE(modernize-use-equals-default)
98 0 : GaugeWave() {}
99 :
100 0 : GaugeWave(double extraction_radius, double mass, double frequency,
101 : double amplitude, double peak_time, double duration);
102 :
103 0 : std::unique_ptr<WorldtubeData> get_clone() const override;
104 :
105 0 : void pup(PUP::er& p) override;
106 :
107 : private:
108 0 : double coordinate_wave_function(double time) const;
109 :
110 0 : double du_coordinate_wave_function(double time) const;
111 :
112 0 : double du_du_coordinate_wave_function(double time) const;
113 :
114 : protected:
115 : /// A no-op as the gauge wave solution does not have substantial
116 : /// shared computation to prepare before the separate component calculations.
117 1 : void prepare_solution(const size_t /*output_l_max*/,
118 : const double /*time*/) const override {}
119 :
120 : /*!
121 : * \brief Compute the spherical coordinate metric from the closed-form gauge
122 : * wave metric.
123 : *
124 : * \details The transformation of the ingoing Eddington-Finkelstein coordinate
125 : * produces metric components in spherical coordinates (identical up to minor
126 : * manipulations of the metric given in Eq. (149) of \cite Barkett2019uae):
127 : *
128 : * \f{align*}{
129 : * g_{tt} &= \frac{-1}{r^3}\left(r - 2 M\right)
130 : * \left[r + \partial_u F(u)\right]^2\\
131 : * g_{rt} &= \frac{1}{r^4} \left[r + \partial_u F(u)\right]
132 : * \left\{2 M r^2 + \left(r - 2 M\right)
133 : * \left[r \partial_u F(u) + F(u)\right]\right\} \\
134 : * g_{rr} &= \frac{1}{r^5} \left[r^2 - r \partial_u F(u) - F(u)\right]
135 : * \left\{r^3 + 2 M r^2 + \left(r - 2 M\right)
136 : * \left[r \partial_u F(u) + F(u)\right]\right\} \\
137 : * g_{\theta \theta} &= r^2 \\
138 : * g_{\phi \phi} &= r^2 \sin^2(\theta),
139 : * \f}
140 : *
141 : * and all other components vanish. Here, \f$F(u)\f$ is defined as
142 : *
143 : * \f{align*}{
144 : * F(u) &= A \sin(\omega u) e^{-(u - u_0)^2 /k^2},\\
145 : * \partial_u F(u) &= A \left[-2 \frac{u - u_0}{k^2} \sin(\omega u)
146 : * + \omega \cos(\omega u)\right] e^{-(u - u_0)^2 / k^2}.
147 : * \f}
148 : *
149 : * \warning The \f$\phi\f$ components are returned in a form for which the
150 : * \f$\sin(\theta)\f$ factors are omitted, assuming that derivatives and
151 : * Jacobians will be applied similarly omitting those factors (and therefore
152 : * improving precision of the tensor expression). If you require the
153 : * \f$\sin(\theta)\f$ factors, be sure to put them in by hand in the calling
154 : * code.
155 : */
156 1 : void spherical_metric(
157 : gsl::not_null<
158 : tnsr::aa<DataVector, 3, ::Frame::Spherical<::Frame::Inertial>>*>
159 : spherical_metric,
160 : size_t l_max, double time) const override;
161 :
162 : /*!
163 : * \brief Compute the radial derivative of the spherical coordinate metric
164 : * from the closed-form gauge wave metric.
165 : *
166 : * \details The transformation of the ingoing Eddington-Finkelstein coordinate
167 : * produces the radial derivative of the metric components in spherical
168 : * coordinates:
169 : *
170 : * \f{align*}{
171 : * \partial_r g_{tt} + \partial_t g_{tt} =& \frac{2}{r^4}
172 : * \left[r + \partial_u F(u)\right]
173 : * \left[- M r + (r - 3 M)\partial_u F(u)\right] \\
174 : * \partial_r g_{rt} + \partial_t g_{rt} =& - \frac{1}{r^5}
175 : * \left\{2 M r^3 + 2 r F(u) (r - 3M) + \partial_u F(u)[r^3 + F(u)(3r - 8 M)]
176 : * + 2 r [\partial_u F(u)]^2 (r - 3M)\right\}\\
177 : * \partial_r g_{rr} + \partial_t g_{rr} =& \frac{2}{r^6}
178 : * \left\{- M r^4 + F(u)^2 (2r - 5M)
179 : * + \partial_u F(u) r^2 \left[4 M r + \partial_u F(u) (r - 3 M)\right]
180 : * + F(u) r \left[6 M r + \partial_u F(u) (3r - 8 M)\right]\right\} \\
181 : * g_{\theta \theta} =& 2 r \\
182 : * g_{\phi \phi} =& 2 r \sin^2(\theta),
183 : * \f}
184 : *
185 : * and all other components vanish (these formulae are obtained simply by
186 : * applying radial derivatives to those given in
187 : * `GaugeWave::spherical_metric()`). Here, \f$F(u)\f$ is defined as
188 : *
189 : * \f{align*}{
190 : * F(u) &= A \sin(\omega u) e^{-(u - u_0)^2 /k^2},\\
191 : * \partial_u F(u) &= A \left[-2 \frac{u - u_0}{k^2} \sin(\omega u)
192 : * + \omega \cos(\omega u)\right] e^{-(u - u_0)^2 / k^2}.
193 : * \f}
194 : *
195 : * \warning The \f$\phi\f$ components are returned in a form for which the
196 : * \f$\sin(\theta)\f$ factors are omitted, assuming that derivatives and
197 : * Jacobians will be applied similarly omitting those factors (and therefore
198 : * improving precision of the tensor expression). If you require the
199 : * \f$\sin(\theta)\f$ factors, be sure to put them in by hand in the calling
200 : * code.
201 : */
202 1 : void dr_spherical_metric(
203 : gsl::not_null<
204 : tnsr::aa<DataVector, 3, ::Frame::Spherical<::Frame::Inertial>>*>
205 : dr_spherical_metric,
206 : size_t l_max, double time) const override;
207 :
208 : /*!
209 : * \brief Compute the spherical coordinate metric from the closed-form gauge
210 : * wave metric.
211 : *
212 : * \details The transformation of the ingoing Eddington-Finkelstein coordinate
213 : * produces metric components in spherical coordinates:
214 : *
215 : * \f{align*}{
216 : * \partial_t g_{tt} =& \frac{-2 \partial_u^2 F(u)}{r^3}
217 : * \left(r - 2 M\right) \left(r + \partial_u F(u)\right) \\
218 : * \partial_t g_{rt} =& \frac{1}{r^4} \Bigg\{\partial_u^2 F(u)
219 : * \left[2 M r^2 + \left(r - 2 M\right)
220 : * (r \partial_u F(u) + F(u))\right] \\
221 : * &+ \left[r + \partial_u F(u)\right]
222 : * \left(r - 2M\right) \left[r \partial_u^2 F(u) + \partial_u F(u)
223 : * \right]\Bigg\} \\
224 : * \partial_t g_{rr} =&
225 : * \frac{1}{r^5}\Bigg\{-\left[r \partial_u^2 F(u) + \partial_u F(u)\right]
226 : * \left[r^3 + 2 M r^2 + \left(r - 2 M\right)
227 : * \left(r \partial_u F(u) + F(u)\right)\right]\\
228 : * &+ \left[r^2 - r \partial_u F(u) - F(u)\right]
229 : * \left(r - 2 M\right)
230 : * \left[r \partial_u^2 F(u) + \partial_u F(u)\right]\Bigg\} \\
231 : * \partial_t g_{\theta \theta} =& 0 \\
232 : * \partial_t g_{\phi \phi} =& 0,
233 : * \f}
234 : *
235 : * and all other components vanish. Here, \f$F(u)\f$ is defined as
236 : *
237 : * \f{align*}{
238 : * F(u) &= A \sin(\omega u) e^{-(u - u_0)^2 /k^2},\\
239 : * \partial_u F(u) &= A \left[-2 \frac{u - u_0}{k^2} \sin(\omega u)
240 : * + \omega \cos(\omega u)\right] e^{-(u - u_0)^2 / k^2},\\
241 : * \partial^2_u F(u) &= \frac{A}{k^4} \left\{-4 k^2 \omega (u - u_0)
242 : * \cos(\omega u) + \left[-2 k^2 + 4 (u - u_0)^2 - k^4 \omega^2\right]
243 : * \sin(\omega u)\right\} e^{-(u - u_0) / k^2}
244 : * \f}
245 : *
246 : * \warning The \f$\phi\f$ components are returned in a form for which the
247 : * \f$\sin(\theta)\f$ factors are omitted, assuming that derivatives and
248 : * Jacobians will be applied similarly omitting those factors (and therefore
249 : * improving precision of the tensor expression). If you require the
250 : * \f$\sin(\theta)\f$ factors, be sure to put them in by hand in the calling
251 : * code.
252 : */
253 1 : void dt_spherical_metric(
254 : gsl::not_null<
255 : tnsr::aa<DataVector, 3, ::Frame::Spherical<::Frame::Inertial>>*>
256 : dt_spherical_metric,
257 : size_t l_max, double time) const override;
258 :
259 0 : using WorldtubeData::variables_impl;
260 :
261 1 : using SphericalMetricData::variables_impl;
262 :
263 : /// The News vanishes, because the wave is pure gauge.
264 1 : void variables_impl(
265 : gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, -2>>*> News,
266 : size_t l_max, double time,
267 : tmpl::type_<Tags::News> /*meta*/) const override;
268 :
269 0 : double mass_ = std::numeric_limits<double>::signaling_NaN();
270 0 : double frequency_ = std::numeric_limits<double>::signaling_NaN();
271 0 : double amplitude_ = std::numeric_limits<double>::signaling_NaN();
272 0 : double peak_time_ = std::numeric_limits<double>::signaling_NaN();
273 0 : double duration_ = std::numeric_limits<double>::signaling_NaN();
274 : };
275 : } // namespace Solutions
276 : } // namespace Cce
|