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