SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticSolutions/GeneralRelativity - TeukolskyWave.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 1.4 % 69 1
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 <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 2.0-1