SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/Cce/AnalyticSolutions - RobinsonTrautman.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 12.7 % 55 7
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            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/ComplexDataVector.hpp"
      12              : #include "DataStructures/SpinWeighted.hpp"
      13              : #include "DataStructures/Tensor/Tensor.hpp"
      14              : #include "Evolution/Systems/Cce/AnalyticSolutions/SphericalMetricData.hpp"
      15              : #include "Evolution/Systems/Cce/AnalyticSolutions/WorldtubeData.hpp"
      16              : #include "NumericalAlgorithms/OdeIntegration/OdeIntegration.hpp"
      17              : #include "Options/Context.hpp"
      18              : #include "Options/String.hpp"
      19              : #include "Utilities/Gsl.hpp"
      20              : #include "Utilities/Literals.hpp"
      21              : #include "Utilities/Serialization/CharmPupable.hpp"
      22              : #include "Utilities/TMPL.hpp"
      23              : 
      24              : namespace Cce {
      25              : namespace Solutions {
      26              : /*!
      27              :  * \brief An analytic solution representing a specialization of the radiative
      28              :  * Robinson-Trautman solution described in \cite Derry1970fk.
      29              :  *
      30              :  * \details This solution is not quite analytic, in the sense that there is a
      31              :  * single scalar field that must be evolved. Ultimately, it is a partial
      32              :  * specialization of the Characteristic equations such that \f$J = 0\f$ and the
      33              :  * evolution equations have been manipulated to give a time evolution equation
      34              :  * for \f$e^{-2 \beta}\f$, which is equivalent to the Robinson-Trautman scalar
      35              :  * \f$\omega_{\text{RT}}\f$ (denoted \f$W\f$ in \cite Derry1970fk -- we deviate
      36              :  * from their notation because the symbol \f$W\f$ is already used elsewhere in
      37              :  * the CCE system).
      38              :  *
      39              :  * \note The value of \f$\omega_{\text{RT}}\f$ should be real and near 1, which
      40              :  * is imposed by the solution itself, any modes specified in the input file are
      41              :  * treated as perturbations to the leading value of 1.0 for the
      42              :  * Robinson-Trautman scalar \f$\omega_{\text{RT}}\f$.
      43              :  *
      44              :  * \note The use of substep time-steppers in conjunction with `RobinsonTrautman`
      45              :  * analytic data is explictly forbidden by checks in
      46              :  * `Cce::Actions::InitializeWorldtubeBoundary`. The reason is that any time the
      47              :  * `RobinsonTrautman` receives a request for data at a time in the past of its
      48              :  * current state, it must re-start its internal time stepper from the beginning
      49              :  * of the evolution. This is a reasonable cost for multistep methods that only
      50              :  * have non-ordered time steps during self-start, but will lead to
      51              :  * \f$\mathcal O(N^2)\f$ internal steps in the `RobinsonTrautman` solution if a
      52              :  * substep method is used, where \f$N\f$ is the number of steps performed by the
      53              :  * substep method. If you find an unavoidable need to use `RobinsonTrautman`
      54              :  * with a substep method, you will either need to only do so for very short
      55              :  * evolutions, or need to write more sophisticated caching of the internal time
      56              :  * step data.
      57              :  */
      58            1 : struct RobinsonTrautman : public SphericalMetricData {
      59            0 :   struct InitialModes {
      60            0 :     using type = std::vector<std::complex<double>>;
      61            0 :     static constexpr Options::String help{
      62              :         "The initial modes of the Robinson-Trautman scalar, denoted W in "
      63              :         "[Derry 1970] and omega_RT in the rendered documentation. "
      64              :         "These are taken in ascending l and m order, m varies fastest. Note "
      65              :         "that the modes are treated as perturbations to the leading-order "
      66              :         "solution of 1.0 for omega_RT and only the real part of the field is "
      67              :         "used."};
      68              :   };
      69            0 :   struct ExtractionRadius {
      70            0 :     using type = double;
      71            0 :     static constexpr Options::String help{
      72              :         "The extraction radius of the spherical solution"};
      73            0 :     static type lower_bound() { return 0.0; }
      74            0 :     static type suggested_value() { return 20.0; }
      75              :   };
      76            0 :   struct LMax {
      77            0 :     using type = size_t;
      78            0 :     static constexpr Options::String help{
      79              :         "The maximum l value for the internal computation of the analytic "
      80              :         "solution"};
      81            0 :     static type lower_bound() { return 4; }
      82              :   };
      83            0 :   struct Tolerance {
      84            0 :     using type = double;
      85            0 :     static constexpr Options::String help{
      86              :         "The tolerance for the time evolution part of the calculation of the "
      87              :         "semi-analytic Robinson-Trautman solution"};
      88            0 :     static type lower_bound() { return 0.0; }
      89            0 :     static type suggested_value() { return 1.0e-11; }
      90              :   };
      91            0 :   struct StartTime {
      92            0 :     using type = double;
      93            0 :     static constexpr Options::String help{
      94              :         "The starting time for the Robinson-Trautman evolution"};
      95            0 :     static type lower_bound() { return 0.0; }
      96            0 :     static type suggested_value() { return 0.0; }
      97              :   };
      98              : 
      99            0 :   using options =
     100              :       tmpl::list<InitialModes, ExtractionRadius, LMax, Tolerance, StartTime>;
     101              : 
     102            0 :   static constexpr Options::String help = {
     103              :       "Analytic solution representing worldtube data for the nonlinear "
     104              :       "semi-analytic Robinson-Trautman metric, which requires a single "
     105              :       "scalar on the boundary to be evolved to determine the metric"};
     106              : 
     107            0 :   WRAPPED_PUPable_decl_template(RobinsonTrautman);  // NOLINT
     108              : 
     109            0 :   explicit RobinsonTrautman(CkMigrateMessage* msg) : SphericalMetricData(msg) {}
     110              : 
     111            0 :   RobinsonTrautman() = default;
     112              : 
     113            0 :   RobinsonTrautman(std::vector<std::complex<double>> initial_modes,
     114              :                    double extraction_radius, size_t l_max, double tolerance,
     115              :                    double start_time, const Options::Context& context);
     116              : 
     117            0 :   std::unique_ptr<WorldtubeData> get_clone() const override;
     118              : 
     119            0 :   void pup(PUP::er& p) override;
     120              : 
     121            0 :   bool use_noninertial_news() const override { return true; }
     122              : 
     123              :  private:
     124            0 :   void du_rt_scalar(
     125              :       gsl::not_null<SpinWeighted<ComplexDataVector, 0>*> local_du_rt_scalar,
     126              :       const SpinWeighted<ComplexDataVector, 0>& rt_scalar) const;
     127              : 
     128            0 :   void du_bondi_w(
     129              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*> du_bondi_w,
     130              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& local_du_rt_scalar,
     131              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& rt_scalar) const;
     132              : 
     133            0 :   void bondi_u(
     134              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*> bondi_u,
     135              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& rt_scalar) const;
     136              : 
     137            0 :   void bondi_w(
     138              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*> bondi_w,
     139              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& rt_scalar) const;
     140              : 
     141            0 :   void dr_bondi_w(
     142              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*> dr_bondi_w,
     143              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& rt_scalar) const;
     144              : 
     145            0 :   void initialize_stepper_from_start() const;
     146              : 
     147              :  protected:
     148              :   /*!
     149              :    * \brief The Robinson-Trautman solution performs the time-stepping to advance
     150              :    * the internal member scalar used to generate the metric solution to the
     151              :    * correct state for `time`.
     152              :    *
     153              :    * \details The generating scalar \f$\omega_{\text{RT}}\f$ is evolved
     154              :    * using equation (2.5) from \cite Derry1970fk (manipulated to a form
     155              :    * convenient for our numerical utilities)
     156              :    *
     157              :    * \f[
     158              :    * \partial_u \omega_{\text{RT}} = -
     159              :    * \left(\omega^4_{\text{RT}} \eth^2 \bar \eth^2 \omega_{\text{RT}}
     160              :    *  - \omega_{\text{RT}}^3 (\eth^2 \omega_{\text{RT}})
     161              :    * (\bar \eth^2  \omega_{\text{RT}}) \right)
     162              :    * \f]
     163              :    *
     164              :    * As the scalar \f$\omega_{\text{RT}}\f$ is evolved, it is filtered by
     165              :    * zeroing the highest two angular modes.
     166              :    */
     167            1 :   void prepare_solution(size_t output_l_max, double time) const override;
     168              : 
     169              :   /*!
     170              :    * \brief Compute the spherical coordinate metric of the Robinson-Trautman
     171              :    * solution generated by the time-evolved scalar \f$\omega_{\text{RT}}\f$.
     172              :    *
     173              :    * \details The spacetime metric of the Robinson-Trautman solution can be
     174              :    * expressed as a specialization of the Bondi-Sachs metric (note the metric
     175              :    * signature change as compared to equation (1.2) from \cite Derry1970fk)
     176              :    *
     177              :    * \f[
     178              :    * ds^2 = -((r W + 1) \omega_{\text{RT}} - r^2 U \bar U) (dt - dr)^2
     179              :    * - 2 \omega_{\text{RT}} (dt - dr) dr
     180              :    * - 2 r^2 U^A q_{AB} dx^B (dt - dr) + r^2 q_{A B} dx^A dx^B,
     181              :    * \f]
     182              :    *
     183              :    * where \f$q_{A B}\f$ represents the angular unit sphere metric, and the
     184              :    * remaining Bondi-Sachs scalars and angular tensors are defined in terms of
     185              :    * the Robinson-Trautman scalar \f$\omega_{\text{RT}}\f$
     186              :    *
     187              :    * \f{align*}{
     188              :    * W &= \frac{1}{r}\left(\omega_{\text{RT}} + \eth \bar \eth
     189              :    * \omega_{\text{RT}} - 1\right) - \frac{2}{r^2 \omega_{\text{RT}}^2}\\
     190              :    * U &\equiv U^A q_A = \frac{\eth \omega_{\text{RT}}}{r}.
     191              :    * \f}
     192              :    * and \f$q_A\f$ is the angular dyad on the unit sphere.
     193              :    *
     194              :    * The angular part of the metric can be expressed in terms of the \f$U\f$
     195              :    * scalar as
     196              :    *
     197              :    * \f{align*}{
     198              :    * g_{u \theta} &= r^2 \Re U\\
     199              :    * g_{u \phi} &= r^2 \Im U
     200              :    * \f}
     201              :    */
     202            1 :   void spherical_metric(
     203              :       gsl::not_null<
     204              :           tnsr::aa<DataVector, 3, ::Frame::Spherical<::Frame::Inertial>>*>
     205              :           spherical_metric,
     206              :       size_t l_max, double time) const override;
     207              : 
     208              :   /*!
     209              :    * \brief Compute radial derivative of the spherical coordinate metric of the
     210              :    * Robinson-Trautman solution generated by the time-evolved scalar
     211              :    * \f$\omega_{\text{RT}}\f$.
     212              :    *
     213              :    * \details The radial derivative (at constant time t) of the
     214              :    * Robinson-Trautman solution is obtained by differentiating the expressions
     215              :    * from the documentation for `RobinsonTrautman::spherical_metric()`:
     216              :    *
     217              :    * \f{align*}{
     218              :    * (\partial_r g_{a b} + \partial_t g_{a b}) dx^a dx^b =
     219              :    * - (\omega_{\text{RT}} (r \partial_r W + W) - 2 r U \bar U
     220              :    * - r^2 (\bar U\partial_r U + U \partial_r \bar U)) (dt - dr)^2
     221              :    * - 2 r U^A q_{A B} dx^B (dt - dr) +  2 r q_{A B} dx^A dx^B
     222              :    * \f}
     223              :    *
     224              :    * where \f$q_{A B}\f$ represents the angular unit sphere metric, and the
     225              :    * remaining Bondi-Sachs scalars and angular tensors are defined in terms of
     226              :    * the Robinson-Trautman scalar \f$\omega_{\text{RT}}\f$
     227              :    *
     228              :    * \f{align*}{
     229              :    * W &= \frac{1}{r}\left(\omega_{\text{RT}}
     230              :    * + \eth \bar \eth \omega_{\text{RT}} - 1\right)
     231              :    * - \frac{2}{r^2 \omega_{\text{RT}}^2}\\
     232              :    * \partial_r W &= -\frac{1}{r^2} \left(\omega_{\text{RT}}
     233              :    * + \eth \bar \eth \omega_{\text{RT}} - 1\right)
     234              :    * + \frac{4}{r^3 \omega_{\text{RT}}^2}\\
     235              :    * U &\equiv U^A q_A = \frac{\eth \omega_{\text{RT}}}{r}.
     236              :    * \f}
     237              :    * and \f$q_A\f$ is the angular dyad on the unit sphere. The Robinson-Trautman
     238              :    * scalar \f$\omega_{\text{RT}}\f$ is independent of the Bondi radius \f$r\f$,
     239              :    * so all radial derivatives of \f$\omega_{\text{RT}}\f$ have been dropped
     240              :    */
     241            1 :   void dr_spherical_metric(
     242              :       gsl::not_null<
     243              :           tnsr::aa<DataVector, 3, ::Frame::Spherical<::Frame::Inertial>>*>
     244              :           dr_spherical_metric,
     245              :       size_t l_max, double time) const override;
     246              : 
     247              :   /*!
     248              :    * \brief Compute time derivative of the spherical coordinate metric of the
     249              :    * Robinson-Trautman solution generated by the time-evolved scalar
     250              :    * \f$\omega_{\text{RT}}\f$.
     251              :    *
     252              :    * \details The time derivative of the Robinson-Trautman solution is obtained
     253              :    * by differentiating the expressions from the documentation for
     254              :    * `RobinsonTrautman::spherical_metric()`:
     255              :    *
     256              :    * \f{align*}{
     257              :    * \partial_t g_{a b} dx^a dx^b =  -( \partial_u \omega_{\text{RT}} (r W + 1)
     258              :    *  + \omega_{\text{RT}} \partial_u W
     259              :    * - r^2 (\bar U \partial_u U + U \partial_u \bar U)) (dt - dr)^2
     260              :    * - 2 \partial_u \omega_{\text{RT}} (dt - dr) dr
     261              :    * - 2 r^2 \partial_u U^A q_{AB} dx^B (dt - dr),
     262              :    * \f}
     263              :    *
     264              :    * where \f$q_{A B}\f$ represents the angular unit sphere metric, and the
     265              :    * remaining Bondi-Sachs scalars and angular tensors are defined in terms of
     266              :    * the Robinson-Trautman scalar \f$\omega_{\text{RT}}\f$
     267              :    *
     268              :    * \f{align*}{
     269              :    * W &= \frac{1}{r}\left(\omega_{\text{RT}}
     270              :    * + \eth \bar \eth \omega_{\text{RT}} - 1\right)
     271              :    * - \frac{2}{r^2 \omega_{\text{RT}}^2}\\
     272              :    * \partial_u W &= \frac{1}{r}\left(\partial_u \omega_{\text{RT}}
     273              :    * + \eth \bar \eth \partial_u \omega_{\text{RT}}\right)
     274              :    * + \frac{4 \partial_u \omega_{\text{RT}}}{r^2 \omega_{\text{RT}}^3} \\
     275              :    * \partial_u U &= q_A \partial_u U^A = \frac{\eth \partial_u
     276              :    * \omega_{\text{RT}}}{r}, \f}
     277              :    *
     278              :    * and \f$q_A\f$ is the angular dyad on the unit sphere; and the time
     279              :    * derivative of the Robinson-Trautman scalar \f$\omega_{\text{RT}}\f$ is
     280              :    *
     281              :    * \f[
     282              :    * \partial_u \omega_{\text{RT}} =
     283              :    * \frac{1}{12} \left(-\omega^4_{\text{RT}} \eth^2 \bar \eth^2
     284              :    * \omega_{\text{RT}} + \omega_{\text{RT}}^3 (\eth^2 \omega_{\text{RT}})
     285              :    * (\bar \eth^2  \omega_{\text{RT}}) \right)
     286              :    * \f]
     287              :    */
     288            1 :   void dt_spherical_metric(
     289              :       gsl::not_null<
     290              :           tnsr::aa<DataVector, 3, ::Frame::Spherical<::Frame::Inertial>>*>
     291              :           dt_spherical_metric,
     292              :       size_t l_max, double time) const override;
     293              : 
     294              :   /*!
     295              :    * \brief Compute the news associated with the Robinson-Trautman solution
     296              :    * generated by the time-evolved scalar \f$\omega_{\text{RT}}\f$.
     297              :    *
     298              :    * \details The Bondi-Sachs news in the Robinson-Trautman solution is
     299              :    *
     300              :    * \f{align*}{
     301              :    * N = \frac{\bar \eth \bar \eth \omega_{\text{RT}}}{\omega_{\text{RT}}}
     302              :    * \f}
     303              :    */
     304            1 :   void variables_impl(
     305              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, -2>>*> News,
     306              :       size_t l_max, double time,
     307              :       tmpl::type_<Tags::News> /*meta*/) const override;
     308              : 
     309            0 :   using WorldtubeData::variables_impl;
     310              : 
     311            1 :   using SphericalMetricData::variables_impl;
     312              :  private:
     313              :   // NOLINTNEXTLINE(spectre-mutable)
     314            0 :   mutable std::pair<double, double> step_range_;
     315              : 
     316              :   // NOLINTNEXTLINE(spectre-mutable)
     317              :   mutable boost::numeric::odeint::dense_output_runge_kutta<
     318              :       boost::numeric::odeint::controlled_runge_kutta<
     319              :           boost::numeric::odeint::runge_kutta_dopri5<ComplexDataVector>>>
     320            0 :       stepper_;
     321              : 
     322              :   // NOLINTNEXTLINE(spectre-mutable)
     323            0 :   mutable Scalar<SpinWeighted<ComplexDataVector, 0>> dense_output_rt_scalar_;
     324              :   // NOLINTNEXTLINE(spectre-mutable)
     325            0 :   mutable Scalar<SpinWeighted<ComplexDataVector, 0>> dense_output_du_rt_scalar_;
     326            0 :   size_t l_max_ = 0;
     327              :   // NOLINTNEXTLINE(spectre-mutable)
     328            0 :   mutable double prepared_time_ = std::numeric_limits<double>::signaling_NaN();
     329            0 :   double tolerance_ = std::numeric_limits<double>::signaling_NaN();
     330            0 :   double start_time_ = std::numeric_limits<double>::signaling_NaN();
     331            0 :   std::vector<std::complex<double>> initial_modes_;
     332              : };
     333              : }  // namespace Solutions
     334              : }  // namespace Cce
        

Generated by: LCOV version 2.0-1