SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticSolutions/GeneralRelativity - TeukolskyWave.hpp Hit Total Coverage
Commit: c428a3e2e0ca78fe0364ec1b0e0493c627d428d4 Lines: 1 69 1.4 %
Date: 2026-04-26 20:20:36
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 <array>
       7             : #include <cstddef>
       8             : #include <limits>
       9             : #include <string>
      10             : 
      11             : #include "DataStructures/TaggedTuple.hpp"
      12             : #include "DataStructures/Tensor/Tensor.hpp"
      13             : #include "Options/Context.hpp"
      14             : #include "Options/String.hpp"
      15             : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
      16             : #include "PointwiseFunctions/GeneralRelativity/TagsDeclarations.hpp"
      17             : #include "Utilities/TMPL.hpp"
      18             : 
      19             : /// \cond
      20             : namespace PUP {
      21             : class er;
      22             : }  // namespace PUP
      23             : namespace Tags {
      24             : template <typename Tag>
      25             : struct dt;
      26             : }  // namespace Tags
      27             : /// \endcond
      28             : 
      29             : namespace gr::Solutions {
      30             : 
      31             : /*!
      32             :  * \brief A perturbative Teukolsky wave (optionally plus Minkowski).
      33             :  *
      34             :  * \details This class provides a linearized \f$l=2\f$ Teukolsky wave in
      35             :  * Cartesian inertial coordinates. The implementation evaluates the spherical
      36             :  * formulas point-by-point and then transforms to Cartesian coordinates.
      37             :  *
      38             :  * This solution does not provide spatial derivatives of the metric, so it
      39             :  * does not support the full tag list of a typical GR analytic solution.
      40             :  *
      41             :  * See Eqs. (5) -- (10) of \cite Teukolsky1982nz for the equations in
      42             :  * spherical coordinates of the perturbed metric implemented here. Those
      43             :  * equations contain a freely specifiable radial profile; this implementation
      44             :  * chooses a Gaussian in \f$r - R_0 \pm t\f$, where \f$R_0\f$ is the
      45             :  * `Radius` parameter, with `Width` setting the pulse width.
      46             :  *
      47             :  * \note The implementation evaluates spherical-coordinate expressions, so it
      48             :  * must not be used too close to the origin about `Center`, where those
      49             :  * coordinates are singular. Specifically, evaluating the solution at points
      50             :  * with \f$r \le 0.1\f$, where \f$r\f$ is the distance from `Center`,
      51             :  * triggers an error. This cutoff is unrelated to the option `Radius`,
      52             :  * which sets the location of the Gaussian pulse.
      53             :  *
      54             :  * On the \f$z\f$-axis, the spherical coordinate \f$\phi\f$ is not well
      55             :  * defined. The implementation here is based on an implementation in SpEC that
      56             :  * just assumed the solution is never evaluated on the axis. Here, the
      57             :  * z-axis singularity is handled explicitly: on the \f$z\f$-axis
      58             :  * (cylindrical radius \f$\rho = 0\f$), the Cartesian result is obtained by
      59             :  * averaging the smooth limit approached from two orthogonal transverse
      60             :  * directions, so the solution is regular there.
      61             :  *
      62             :  * Optionally, the solution can include a flat Minkowski background as well as
      63             :  * the metric perturbation. Note that the tags for the inverse spatial metric,
      64             :  * square root of the spatial metric determinant, and extrinsic curvature
      65             :  * require the flat background to be included. The background can be excluded
      66             :  * when one wants only the perturbation itself (e.g., to add it on top of a
      67             :  * different background, such as the metric of a Kerr-Schild black hole).
      68             :  */
      69           1 : class TeukolskyWave : public MarkAsAnalyticSolution {
      70             :  public:
      71           0 :   static constexpr size_t volume_dim = 3;
      72             : 
      73           0 :   struct Amplitude {
      74           0 :     using type = double;
      75           0 :     static constexpr Options::String help{"Amplitude of the perturbation"};
      76             :   };
      77             : 
      78           0 :   struct Mode {
      79           0 :     using type = int;
      80           0 :     static constexpr Options::String help{
      81             :         "Azimuthal mode m of the l=2 Teukolsky wave"};
      82           0 :     static type lower_bound() { return -2; }
      83           0 :     static type upper_bound() { return 2; }
      84             :   };
      85             : 
      86           0 :   struct Parity {
      87           0 :     using type = std::string;
      88           0 :     static constexpr Options::String help{
      89             :         "Parity of the perturbation: 'even' or 'odd'"};
      90             :   };
      91             : 
      92           0 :   struct Direction {
      93           0 :     using type = std::string;
      94           0 :     static constexpr Options::String help{
      95             :         "Propagation direction: 'outgoing' or 'ingoing'"};
      96             :   };
      97             : 
      98           0 :   struct Center {
      99           0 :     using type = std::array<double, 3>;
     100           0 :     static constexpr Options::String help{
     101             :         "Center of the Teukolsky wave in inertial coordinates"};
     102             :   };
     103             : 
     104           0 :   struct Radius {
     105           0 :     using type = double;
     106           0 :     static constexpr Options::String help{
     107             :         "Radius of the center of the Gaussian pulse at t=0"};
     108             :   };
     109             : 
     110           0 :   struct Width {
     111           0 :     using type = double;
     112           0 :     static constexpr Options::String help{
     113             :         "Width of the Gaussian pulse profile"};
     114           0 :     static type lower_bound() { return 0.0; }
     115             :   };
     116             : 
     117           0 :   using options =
     118             :       tmpl::list<Amplitude, Mode, Parity, Direction, Center, Radius, Width>;
     119           0 :   static constexpr Options::String help{
     120             :       "A perturbative Teukolsky wave in Cartesian inertial coordinates"};
     121             : 
     122             :   template <typename DataType>
     123           0 :   using tags = tmpl::list<
     124             :       gr::Tags::Lapse<DataType>, ::Tags::dt<gr::Tags::Lapse<DataType>>,
     125             :       gr::Tags::Shift<DataType, volume_dim, Frame::Inertial>,
     126             :       ::Tags::dt<gr::Tags::Shift<DataType, volume_dim, Frame::Inertial>>,
     127             :       gr::Tags::SpatialMetric<DataType, volume_dim, Frame::Inertial>,
     128             :       ::Tags::dt<
     129             :           gr::Tags::SpatialMetric<DataType, volume_dim, Frame::Inertial>>,
     130             :       gr::Tags::SqrtDetSpatialMetric<DataType>,
     131             :       gr::Tags::ExtrinsicCurvature<DataType, volume_dim, Frame::Inertial>,
     132             :       gr::Tags::InverseSpatialMetric<DataType, volume_dim, Frame::Inertial>>;
     133             : 
     134           0 :   TeukolskyWave(double amplitude, int mode, std::string parity,
     135             :                 std::string direction, std::array<double, 3> center,
     136             :                 double radius, double width,
     137             :                 const Options::Context& context = {});
     138             : 
     139           0 :   TeukolskyWave(double amplitude, int mode, std::string parity,
     140             :                 std::string direction, std::array<double, 3> center,
     141             :                 double radius, double width, bool include_minkowski_background,
     142             :                 const Options::Context& context = {});
     143             : 
     144           0 :   TeukolskyWave() = default;
     145           0 :   TeukolskyWave(const TeukolskyWave& /*rhs*/) = default;
     146           0 :   TeukolskyWave& operator=(const TeukolskyWave& /*rhs*/) = default;
     147           0 :   TeukolskyWave(TeukolskyWave&& /*rhs*/) = default;
     148           0 :   TeukolskyWave& operator=(TeukolskyWave&& /*rhs*/) = default;
     149           0 :   ~TeukolskyWave() = default;
     150             : 
     151           0 :   explicit TeukolskyWave(CkMigrateMessage* /*msg*/);
     152             : 
     153             :   template <typename DataType, typename... RequestedTags>
     154           0 :   tuples::TaggedTuple<RequestedTags...> variables(
     155             :       const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
     156             :       tmpl::list<RequestedTags...> /*meta*/) const {
     157             :     static_assert(tmpl2::flat_all_v<
     158             :                       tmpl::list_contains_v<tags<DataType>, RequestedTags>...>,
     159             :                   "At least one of the requested tags is not supported.");
     160             :     return {
     161             :         get<RequestedTags>(variables(x, t, tmpl::list<RequestedTags>{}))...};
     162             :   }
     163             : 
     164             :   template <typename RequestedTag, typename DataType>
     165           0 :   tuples::TaggedTuple<RequestedTag> variable(
     166             :       const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
     167             :       const double t) const {
     168             :     return variables(x, t, tmpl::list<RequestedTag>{});
     169             :   }
     170             : 
     171             :   // NOLINTNEXTLINE(google-runtime-references)
     172           0 :   void pup(PUP::er& p);
     173             : 
     174           0 :   double amplitude() const { return amplitude_; }
     175           0 :   int mode() const { return mode_; }
     176           0 :   const std::string& parity() const { return parity_; }
     177           0 :   const std::string& direction() const { return direction_; }
     178           0 :   const std::array<double, 3>& center() const { return center_; }
     179           0 :   double radius() const { return radius_; }
     180           0 :   double width() const { return width_; }
     181           0 :   bool include_minkowski_background() const {
     182             :     return include_minkowski_background_;
     183             :   }
     184             : 
     185             :  private:
     186             :   template <typename DataType>
     187           0 :   auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
     188             :                  double t, tmpl::list<gr::Tags::Lapse<DataType>> /*meta*/) const
     189             :       -> tuples::TaggedTuple<gr::Tags::Lapse<DataType>>;
     190             : 
     191             :   template <typename DataType>
     192           0 :   auto variables(
     193             :       const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
     194             :       tmpl::list<::Tags::dt<gr::Tags::Lapse<DataType>>> /*meta*/) const
     195             :       -> tuples::TaggedTuple<::Tags::dt<gr::Tags::Lapse<DataType>>>;
     196             : 
     197             :   template <typename DataType>
     198           0 :   auto variables(
     199             :       const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
     200             :       tmpl::list<gr::Tags::Shift<DataType, volume_dim, Frame::Inertial>>
     201             :       /*meta*/) const
     202             :       -> tuples::TaggedTuple<
     203             :           gr::Tags::Shift<DataType, volume_dim, Frame::Inertial>>;
     204             : 
     205             :   template <typename DataType>
     206           0 :   auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
     207             :                  double t,
     208             :                  tmpl::list<::Tags::dt<gr::Tags::Shift<
     209             :                      DataType, volume_dim, Frame::Inertial>>> /*meta*/) const
     210             :       -> tuples::TaggedTuple<
     211             :           ::Tags::dt<gr::Tags::Shift<DataType, volume_dim, Frame::Inertial>>>;
     212             : 
     213             :   template <typename DataType>
     214           0 :   auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
     215             :                  double t,
     216             :                  tmpl::list<gr::Tags::SpatialMetric<
     217             :                      DataType, volume_dim, Frame::Inertial>> /*meta*/) const
     218             :       -> tuples::TaggedTuple<
     219             :           gr::Tags::SpatialMetric<DataType, volume_dim, Frame::Inertial>>;
     220             : 
     221             :   template <typename DataType>
     222           0 :   auto variables(
     223             :       const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
     224             :       tmpl::list<::Tags::dt<
     225             :           gr::Tags::SpatialMetric<DataType, volume_dim, Frame::Inertial>>>
     226             :       /*meta*/) const
     227             :       -> tuples::TaggedTuple<::Tags::dt<
     228             :           gr::Tags::SpatialMetric<DataType, volume_dim, Frame::Inertial>>>;
     229             : 
     230             :   template <typename DataType>
     231           0 :   auto variables(
     232             :       const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
     233             :       tmpl::list<gr::Tags::SqrtDetSpatialMetric<DataType>> /*meta*/) const
     234             :       -> tuples::TaggedTuple<gr::Tags::SqrtDetSpatialMetric<DataType>>;
     235             : 
     236             :   template <typename DataType>
     237           0 :   auto variables(
     238             :       const tnsr::I<DataType, volume_dim, Frame::Inertial>& x, double t,
     239             :       tmpl::list<
     240             :           gr::Tags::ExtrinsicCurvature<DataType, volume_dim, Frame::Inertial>>
     241             :       /*meta*/) const
     242             :       -> tuples::TaggedTuple<
     243             :           gr::Tags::ExtrinsicCurvature<DataType, volume_dim, Frame::Inertial>>;
     244             : 
     245             :   template <typename DataType>
     246           0 :   auto variables(const tnsr::I<DataType, volume_dim, Frame::Inertial>& x,
     247             :                  double t,
     248             :                  tmpl::list<gr::Tags::InverseSpatialMetric<
     249             :                      DataType, volume_dim, Frame::Inertial>> /*meta*/) const
     250             :       -> tuples::TaggedTuple<gr::Tags::InverseSpatialMetric<
     251             :           DataType, volume_dim, Frame::Inertial>>;
     252             : 
     253           0 :   double amplitude_{std::numeric_limits<double>::signaling_NaN()};
     254           0 :   int mode_{0};
     255           0 :   std::string parity_{};
     256           0 :   std::string direction_{};
     257           0 :   std::array<double, 3> center_{};
     258           0 :   double radius_{std::numeric_limits<double>::signaling_NaN()};
     259           0 :   double width_{std::numeric_limits<double>::signaling_NaN()};
     260           0 :   bool include_minkowski_background_{false};
     261             : };
     262             : 
     263           0 : bool operator==(const TeukolskyWave& lhs, const TeukolskyWave& rhs);
     264           0 : bool operator!=(const TeukolskyWave& lhs, const TeukolskyWave& rhs);
     265             : 
     266             : }  // namespace gr::Solutions

Generated by: LCOV version 1.14