SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticSolutions/Xcts - Schwarzschild.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 11.8 % 17 2
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 <limits>
       7              : #include <memory>
       8              : #include <ostream>
       9              : 
      10              : #include "DataStructures/CachedTempBuffer.hpp"
      11              : #include "DataStructures/DataBox/Prefixes.hpp"
      12              : #include "DataStructures/DataVector.hpp"
      13              : #include "DataStructures/TaggedTuple.hpp"
      14              : #include "DataStructures/Tensor/Tensor.hpp"
      15              : #include "Elliptic/Systems/Xcts/Tags.hpp"
      16              : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
      17              : #include "Options/String.hpp"
      18              : #include "PointwiseFunctions/AnalyticSolutions/Xcts/CommonVariables.hpp"
      19              : #include "PointwiseFunctions/AnalyticSolutions/Xcts/Flatness.hpp"
      20              : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
      21              : #include "PointwiseFunctions/GeneralRelativity/Tags/Conformal.hpp"
      22              : #include "PointwiseFunctions/InitialDataUtilities/AnalyticSolution.hpp"
      23              : #include "Utilities/ContainerHelpers.hpp"
      24              : #include "Utilities/Gsl.hpp"
      25              : #include "Utilities/Serialization/CharmPupable.hpp"
      26              : #include "Utilities/TMPL.hpp"
      27              : 
      28              : /// \cond
      29              : namespace PUP {
      30              : class er;
      31              : }  // namespace PUP
      32              : /// \endcond
      33              : 
      34              : namespace Xcts::Solutions {
      35              : 
      36              : /// Various coordinate systems in which to express the Schwarzschild solution
      37            1 : enum class SchwarzschildCoordinates {
      38              :   /*!
      39              :    * \brief Isotropic Schwarzschild coordinates
      40              :    *
      41              :    * These arise from the canonical Schwarzschild coordinates by the radial
      42              :    * transformation
      43              :    *
      44              :    * \f{equation}
      45              :    * r = \bar{r}\left(1+\frac{M}{2\bar{r}}\right)^2
      46              :    * \f}
      47              :    *
      48              :    * (Eq. (1.61) in \cite BaumgarteShapiro) where \f$r\f$ is the canonical
      49              :    * Schwarzschild radius, also referred to as "areal" radius because it is
      50              :    * defined such that spheres with constant \f$r\f$ have the area \f$4\pi
      51              :    * r^2\f$, and \f$\bar{r}\f$ is the "isotropic" radius. In the isotropic
      52              :    * radius the Schwarzschild spatial metric is conformally flat:
      53              :    *
      54              :    * \f{equation}
      55              :    * \gamma_{ij}=\psi^4\eta_{ij} \quad \text{with conformal factor} \quad
      56              :    * \psi=1+\frac{M}{2\bar{r}}
      57              :    * \f}
      58              :    *
      59              :    * (Table 2.1 in \cite BaumgarteShapiro). The lapse in the conformal radius is
      60              :    *
      61              :    * \f{equation}
      62              :    * \alpha=\frac{1-M/(2\bar{r})}{1+M/(2\bar{r})}
      63              :    * \f}
      64              :    *
      65              :    * and the shift vanishes (\f$\beta^i=0\f$) as it does in areal Schwarzschild
      66              :    * coordinates. The solution also remains maximally sliced, i.e. \f$K=0\f$.
      67              :    *
      68              :    * The Schwarzschild horizon in these coordinates is at
      69              :    * \f$\bar{r}=\frac{M}{2}\f$ due to the radial transformation from \f$r=2M\f$.
      70              :    */
      71              :   Isotropic,
      72              :   /*!
      73              :    * \brief Painlevé-Gullstrand coordinates
      74              :    *
      75              :    * In these coordinates the spatial metric is flat and the lapse is trivial,
      76              :    * but contrary to (isotropic) Schwarzschild coordinates the shift is
      77              :    * nontrivial,
      78              :    *
      79              :    * \begin{align}
      80              :    *   \gamma_{ij} &= \eta_{ij} \\
      81              :    *   \alpha &= 1 \\
      82              :    *   \beta^i &= \sqrt{\frac{2M}{r}} \frac{x^i}{r} \\
      83              :    *   K &= \frac{3}{2}\sqrt{\frac{2M}{r^3}}
      84              :    * \end{align}
      85              :    *
      86              :    * (Table 2.1 in \cite BaumgarteShapiro).
      87              :    */
      88              :   PainleveGullstrand,
      89              :   /*!
      90              :    * \brief Isotropic Kerr-Schild coordinates
      91              :    *
      92              :    * Kerr-Schild coordinates with a radial transformation such that the spatial
      93              :    * metric is conformally flat.
      94              :    *
      95              :    * The Schwarzschild spacetime in canonical (areal) Kerr-Schild coordinates is
      96              :    *
      97              :    * \begin{align}
      98              :    *   \gamma_{ij} &= \eta_{ij} + \frac{2M}{r}\frac{x^i x^j}{r^2} \\
      99              :    *   \alpha &= \sqrt{1 + \frac{2M}{r}}^{-1} \\
     100              :    *   \beta^i &= \frac{2M\alpha^2}{r} \frac{x^i}{r} \\
     101              :    *   K &= \frac{2M\alpha^3}{r^2} \left(1 + \frac{3M}{r}\right)
     102              :    *   \text{.}
     103              :    * \end{align}
     104              :    *
     105              :    * (Table 2.1 in \cite BaumgarteShapiro). Since the Schwarzschild spacetime is
     106              :    * spherically symmetric we can transform to a radial coordinate $\bar{r}$ in
     107              :    * which it is conformally flat (see, e.g., Sec. 7.4.1 in \cite Pfeiffer2005zm
     108              :    * for details):
     109              :    *
     110              :    * \begin{equation}
     111              :    *   {}^{(3)}\mathrm{d}s^2
     112              :    *     = \left(1 + \frac{2M}{r}\right)\mathrm{d}r^2 + r^2 \mathrm{d}\Omega^2
     113              :    *     = \psi^4 \left(\mathrm{d}\bar{r}^2 +
     114              :    *       \bar{r}^2 \mathrm{d}\Omega^2\right)
     115              :    * \end{equation}
     116              :    *
     117              :    * Therefore, the conformal factor is $\psi^2 = r / \bar{r}$ and
     118              :    *
     119              :    * \begin{equation}
     120              :    *   \frac{\mathrm{d}\bar{r}}{\mathrm{d}r}
     121              :    *     = \frac{\bar{r}}{r} \sqrt{1 + \frac{2M}{r}}
     122              :    *     = \frac{\bar{r}}{r} \frac{1}{\alpha}
     123              :    *   \text{,}
     124              :    * \end{equation}
     125              :    *
     126              :    * which has the solution
     127              :    *
     128              :    * \begin{equation}
     129              :    *   \bar{r} = \frac{r}{4} \left(1 + \sqrt{1 + \frac{2M}{r}}\right)^2
     130              :    *     e^{2 - 2\sqrt{1 + 2M / r}}
     131              :    * \end{equation}
     132              :    *
     133              :    * when we impose $\bar{r} \rightarrow r$ as $r \rightarrow \infty$. We can
     134              :    * invert this transformation law with a numerical root find to obtain the
     135              :    * areal radius $r$ for any isotropic radius $\bar{r}$.
     136              :    *
     137              :    * In the isotropic radial coordinate $\bar{r}$ the solution is then:
     138              :    *
     139              :    * \begin{align}
     140              :    *   \gamma_{ij} &= \psi^4 \eta_{ij} \\
     141              :    *   \psi &= \sqrt{\frac{r}{\bar{r}}}
     142              :    *     = \frac{2e^{\sqrt{1 + 2M / r} - 1}}{1 + \sqrt{1 + 2M / r}} \\
     143              :    *   \alpha &= \sqrt{1 + \frac{2M}{r}}^{-1} \\
     144              :    *   \beta^i
     145              :    *     &= \frac{\mathrm{d}\bar{r}}{\mathrm{d}r} \beta^r \frac{x^i}{\bar{r}}
     146              :    *      = \frac{2M\alpha}{r^2} x^i \\
     147              :    *   K &= \frac{2M\alpha^3}{r^2} \left(1 + \frac{3M}{r}\right)
     148              :    * \end{align}
     149              :    *
     150              :    * Here, $x^i$ are the (isotropic) Cartesian coordinates from which we compute
     151              :    * the isotropic radius $\bar{r}$, $r$ is the areal radius we can obtain from
     152              :    * the isotropic radius by a root find, and $\beta^r$ is the magnitude of the
     153              :    * shift in areal coordinates, as given above.
     154              :    *
     155              :    * The horizon in these coordinates is at (Eq. (7.37) in
     156              :    * \cite Pfeiffer2005zm):
     157              :    *
     158              :    * \begin{equation}
     159              :    * \bar{r}_\mathrm{AH} / M \approx 1.2727410334221052
     160              :    * \end{equation}
     161              :    */
     162              :   KerrSchildIsotropic,
     163              :   /*!
     164              :    * \brief Maximal Isotropic (Horizon Penetrating) Schwarzschild coordinates
     165              :    *
     166              :    * Schwarzschild coordinates with a radial transformation such that the radius
     167              :    * is isotropic and the coordinates are horizon penetrating.
     168              :    *
     169              :    * These arise from first choosing a family of time-independent, maximal
     170              :    * slicings of the Schwarzschild spacetime and a slicing condition that give a
     171              :    * unique solution with a limiting surface at \f$R=3M/2\f$ and horizon at
     172              :    * \f$R=2M\f$ \cite Estabrook1973ue. The latter is then changed by the radial
     173              :    * transformation \cite Baumgarte2007ht
     174              :    *
     175              :    * \f{equation}
     176              :    *  r = \frac{\left[2R + M + \sqrt{4R^2 + 4MR + 3M^2}\right]}{4}
     177              :    *  \times \left[
     178              :    *  \frac{(4 + 3\sqrt{2})(2R - 3M)}{8R + 6M + 3\sqrt{8R^2 + 8MR + 6M^2}}
     179              :    *  \right]^{1/\sqrt{2}}
     180              :    * \f}
     181              :    *
     182              :    * where \f$R\f$ is the canonical
     183              :    * Schwarzschild radius, also referred to as "areal" radius because it is
     184              :    * defined such that spheres with constant \f$R\f$ have the area \f$4\pi
     185              :    * R^2\f$, and \f$r\f$ is the "isotropic" radius. In the isotropic
     186              :    * radius the Schwarzschild spatial metric is conformally flat:
     187              :    *
     188              :    * \f{equation}
     189              :    * \gamma_{ij}=\psi^4\eta_{ij} \quad \text{with conformal factor} \quad
     190              :    * \psi=\sqrt{\frac{R}{r}}.
     191              :    * \f}
     192              :    *
     193              :    * The lapse in the conformal radius is
     194              :    *
     195              :    * \f{equation}
     196              :    * \alpha = \left(1 - \frac{2M}{R} + \frac{27M^4}{16R^4} \right)^{1/2}
     197              :    * \f}
     198              :    *
     199              :    * and the shift is given by
     200              :    *
     201              :    * \f{equation}
     202              :    * \beta^r = \frac{3 \sqrt{3} M^2}{4} \frac{r}{R^3}
     203              :    * \f}
     204              :    *
     205              :    * The solution remains maximally sliced, i.e. \f$K=0\f$. And the horizon in
     206              :    * these coordinates is at \f$r\approx 0.7793271080557972 M\f$ due to the
     207              :    * radial transformation from \f$R=2M\f$.
     208              :    *
     209              :    */
     210              :   MaximalIsotropic,
     211              : };
     212              : 
     213            0 : std::ostream& operator<<(std::ostream& os, SchwarzschildCoordinates coords);
     214              : 
     215              : }  // namespace Xcts::Solutions
     216              : 
     217              : template <>
     218            0 : struct Options::create_from_yaml<Xcts::Solutions::SchwarzschildCoordinates> {
     219              :   template <typename Metavariables>
     220            0 :   static Xcts::Solutions::SchwarzschildCoordinates create(
     221              :       const Options::Option& options) {
     222              :     return create<void>(options);
     223              :   }
     224              : };
     225              : 
     226              : template <>
     227            0 : Xcts::Solutions::SchwarzschildCoordinates
     228              : Options::create_from_yaml<Xcts::Solutions::SchwarzschildCoordinates>::create<
     229              :     void>(const Options::Option& options);
     230              : 
     231              : namespace Xcts::Solutions {
     232              : 
     233              : namespace detail {
     234              : 
     235              : struct SchwarzschildImpl {
     236              :   struct Mass {
     237              :     using type = double;
     238              :     static constexpr Options::String help = "Mass parameter M";
     239              :   };
     240              : 
     241              :   struct CoordinateSystem {
     242              :     static std::string name() { return "Coordinates"; }
     243              :     using type = SchwarzschildCoordinates;
     244              :     static constexpr Options::String help =
     245              :         "The coordinate system used to describe the solution";
     246              :   };
     247              : 
     248              :   using options = tmpl::list<Mass, CoordinateSystem>;
     249              :   static constexpr Options::String help{
     250              :       "Schwarzschild spacetime in general relativity"};
     251              : 
     252              :   SchwarzschildImpl() = default;
     253              :   SchwarzschildImpl(const SchwarzschildImpl&) = default;
     254              :   SchwarzschildImpl& operator=(const SchwarzschildImpl&) = default;
     255              :   SchwarzschildImpl(SchwarzschildImpl&&) = default;
     256              :   SchwarzschildImpl& operator=(SchwarzschildImpl&&) = default;
     257              :   ~SchwarzschildImpl() = default;
     258              : 
     259              :   explicit SchwarzschildImpl(double mass,
     260              :                              SchwarzschildCoordinates coordinate_system);
     261              : 
     262              :   /// The mass parameter \f$M\f$.
     263              :   double mass() const;
     264              : 
     265              :   SchwarzschildCoordinates coordinate_system() const;
     266              : 
     267              :   /// The radius of the Schwarzschild horizon in the given coordinates.
     268              :   double radius_at_horizon() const;
     269              : 
     270              :   // NOLINTNEXTLINE(google-runtime-references)
     271              :   void pup(PUP::er& p);
     272              : 
     273              :  protected:
     274              :   double mass_{std::numeric_limits<double>::signaling_NaN()};
     275              :   SchwarzschildCoordinates coordinate_system_{};
     276              : };
     277              : 
     278              : bool operator==(const SchwarzschildImpl& lhs, const SchwarzschildImpl& rhs);
     279              : 
     280              : bool operator!=(const SchwarzschildImpl& lhs, const SchwarzschildImpl& rhs);
     281              : 
     282              : namespace Tags {
     283              : template <typename DataType>
     284              : struct Radius : db::SimpleTag {
     285              :   using type = Scalar<DataType>;
     286              : };
     287              : template <typename DataType>
     288              : struct ArealRadius : db::SimpleTag {
     289              :   using type = Scalar<DataType>;
     290              : };
     291              : }  // namespace Tags
     292              : 
     293              : template <typename DataType>
     294              : using SchwarzschildVariablesCache =
     295              :     cached_temp_buffer_from_typelist<tmpl::push_front<
     296              :         common_tags<DataType>, detail::Tags::Radius<DataType>,
     297              :         detail::Tags::ArealRadius<DataType>,
     298              :         ::Tags::deriv<gr::Tags::Lapse<DataType>, tmpl::size_t<3>,
     299              :                       Frame::Inertial>,
     300              :         gr::Tags::Conformal<gr::Tags::EnergyDensity<DataType>, 0>,
     301              :         gr::Tags::Conformal<gr::Tags::StressTrace<DataType>, 0>,
     302              :         gr::Tags::Conformal<gr::Tags::MomentumDensity<DataType, 3>, 0>>>;
     303              : 
     304              : template <typename DataType>
     305              : struct SchwarzschildVariables
     306              :     : CommonVariables<DataType, SchwarzschildVariablesCache<DataType>> {
     307              :   static constexpr size_t Dim = 3;
     308              :   static constexpr int ConformalMatterScale = 0;
     309              :   using Cache = SchwarzschildVariablesCache<DataType>;
     310              :   using Base = CommonVariables<DataType, SchwarzschildVariablesCache<DataType>>;
     311              :   using Base::operator();
     312              : 
     313              :   SchwarzschildVariables(
     314              :       std::optional<std::reference_wrapper<const Mesh<Dim>>> local_mesh,
     315              :       std::optional<std::reference_wrapper<const InverseJacobian<
     316              :           DataType, Dim, Frame::ElementLogical, Frame::Inertial>>>
     317              :           local_inv_jacobian,
     318              :       const tnsr::I<DataType, 3>& local_x, const double local_mass,
     319              :       const SchwarzschildCoordinates local_coordinate_system)
     320              :       : Base(std::move(local_mesh), std::move(local_inv_jacobian)),
     321              :         x(local_x),
     322              :         mass(local_mass),
     323              :         coordinate_system(local_coordinate_system) {}
     324              : 
     325              :   const tnsr::I<DataType, 3>& x;
     326              :   double mass;
     327              :   SchwarzschildCoordinates coordinate_system;
     328              : 
     329              :   void operator()(gsl::not_null<Scalar<DataType>*> radius,
     330              :                   gsl::not_null<Cache*> cache,
     331              :                   detail::Tags::Radius<DataType> /*meta*/) const;
     332              :   void operator()(gsl::not_null<Scalar<DataType>*> areal_radius,
     333              :                   gsl::not_null<Cache*> cache,
     334              :                   detail::Tags::ArealRadius<DataType> /*meta*/) const;
     335              :   void operator()(
     336              :       gsl::not_null<tnsr::ii<DataType, 3>*> conformal_metric,
     337              :       gsl::not_null<Cache*> cache,
     338              :       Xcts::Tags::ConformalMetric<DataType, 3, Frame::Inertial> /*meta*/)
     339              :       const override;
     340              :   void operator()(
     341              :       gsl::not_null<tnsr::II<DataType, 3>*> inv_conformal_metric,
     342              :       gsl::not_null<Cache*> cache,
     343              :       Xcts::Tags::InverseConformalMetric<DataType, 3, Frame::Inertial> /*meta*/)
     344              :       const override;
     345              :   void operator()(
     346              :       gsl::not_null<tnsr::ijj<DataType, 3>*> deriv_conformal_metric,
     347              :       gsl::not_null<Cache*> cache,
     348              :       ::Tags::deriv<Xcts::Tags::ConformalMetric<DataType, 3, Frame::Inertial>,
     349              :                     tmpl::size_t<3>, Frame::Inertial> /*meta*/) const override;
     350              :   void operator()(
     351              :       gsl::not_null<Scalar<DataType>*> trace_extrinsic_curvature,
     352              :       gsl::not_null<Cache*> cache,
     353              :       gr::Tags::TraceExtrinsicCurvature<DataType> /*meta*/) const override;
     354              :   void operator()(
     355              :       gsl::not_null<tnsr::i<DataType, 3>*> trace_extrinsic_curvature_gradient,
     356              :       gsl::not_null<Cache*> cache,
     357              :       ::Tags::deriv<gr::Tags::TraceExtrinsicCurvature<DataType>,
     358              :                     tmpl::size_t<3>, Frame::Inertial> /*meta*/) const override;
     359              :   void operator()(
     360              :       gsl::not_null<Scalar<DataType>*> dt_trace_extrinsic_curvature,
     361              :       gsl::not_null<Cache*> cache,
     362              :       ::Tags::dt<gr::Tags::TraceExtrinsicCurvature<DataType>> /*meta*/)
     363              :       const override;
     364              :   void operator()(
     365              :       gsl::not_null<Scalar<DataType>*> conformal_factor_minus_one,
     366              :       gsl::not_null<Cache*> cache,
     367              :       Xcts::Tags::ConformalFactorMinusOne<DataType> /*meta*/) const override;
     368              :   void operator()(
     369              :       gsl::not_null<Scalar<DataType>*> conformal_factor,
     370              :       gsl::not_null<Cache*> cache,
     371              :       Xcts::Tags::ConformalFactor<DataType> /*meta*/) const override;
     372              :   void operator()(
     373              :       gsl::not_null<tnsr::i<DataType, 3>*> conformal_factor_gradient,
     374              :       gsl::not_null<Cache*> cache,
     375              :       ::Tags::deriv<Xcts::Tags::ConformalFactorMinusOne<DataType>,
     376              :                     tmpl::size_t<3>, Frame::Inertial> /*meta*/) const override;
     377              :   void operator()(gsl::not_null<Scalar<DataType>*> lapse,
     378              :                   gsl::not_null<Cache*> cache,
     379              :                   gr::Tags::Lapse<DataType> /*meta*/) const override;
     380              :   void operator()(gsl::not_null<tnsr::i<DataType, 3>*> deriv_lapse,
     381              :                   gsl::not_null<Cache*> cache,
     382              :                   ::Tags::deriv<gr::Tags::Lapse<DataType>, tmpl::size_t<3>,
     383              :                                 Frame::Inertial> /*meta*/) const;
     384              :   void operator()(
     385              :       gsl::not_null<Scalar<DataType>*> lapse_times_conformal_factor_minus_one,
     386              :       gsl::not_null<Cache*> cache,
     387              :       Xcts::Tags::LapseTimesConformalFactorMinusOne<DataType> /*meta*/)
     388              :       const override;
     389              :   void operator()(
     390              :       gsl::not_null<Scalar<DataType>*> lapse_times_conformal_factor,
     391              :       gsl::not_null<Cache*> cache,
     392              :       Xcts::Tags::LapseTimesConformalFactor<DataType> /*meta*/) const override;
     393              :   void operator()(
     394              :       gsl::not_null<tnsr::i<DataType, 3>*>
     395              :           lapse_times_conformal_factor_gradient,
     396              :       gsl::not_null<Cache*> cache,
     397              :       ::Tags::deriv<Xcts::Tags::LapseTimesConformalFactorMinusOne<DataType>,
     398              :                     tmpl::size_t<3>, Frame::Inertial> /*meta*/) const override;
     399              :   void operator()(
     400              :       gsl::not_null<tnsr::I<DataType, 3>*> shift_background,
     401              :       gsl::not_null<Cache*> cache,
     402              :       Xcts::Tags::ShiftBackground<DataType, 3, Frame::Inertial> /*meta*/)
     403              :       const override;
     404              :   void operator()(
     405              :       gsl::not_null<tnsr::iJ<DataType, 3, Frame::Inertial>*>
     406              :           deriv_shift_background,
     407              :       gsl::not_null<Cache*> cache,
     408              :       ::Tags::deriv<Xcts::Tags::ShiftBackground<DataType, 3, Frame::Inertial>,
     409              :                     tmpl::size_t<3>, Frame::Inertial> /*meta*/) const override;
     410              :   void operator()(gsl::not_null<tnsr::II<DataType, 3, Frame::Inertial>*>
     411              :                       longitudinal_shift_background_minus_dt_conformal_metric,
     412              :                   gsl::not_null<Cache*> cache,
     413              :                   Xcts::Tags::LongitudinalShiftBackgroundMinusDtConformalMetric<
     414              :                       DataType, 3, Frame::Inertial> /*meta*/) const override;
     415              :   void operator()(
     416              :       gsl::not_null<tnsr::I<DataType, 3>*> shift_excess,
     417              :       gsl::not_null<Cache*> cache,
     418              :       Xcts::Tags::ShiftExcess<DataType, 3, Frame::Inertial> /*meta*/)
     419              :       const override;
     420              :   void operator()(
     421              :       gsl::not_null<tnsr::iJ<DataType, 3>*> deriv_shift_excess,
     422              :       gsl::not_null<Cache*> cache,
     423              :       ::Tags::deriv<Xcts::Tags::ShiftExcess<DataType, 3, Frame::Inertial>,
     424              :                     tmpl::size_t<3>, Frame::Inertial> /*meta*/) const override;
     425              :   void operator()(
     426              :       gsl::not_null<tnsr::ii<DataType, 3>*> extrinsic_curvature,
     427              :       gsl::not_null<Cache*> cache,
     428              :       gr::Tags::ExtrinsicCurvature<DataType, 3> /*meta*/) const override;
     429              :   void operator()(gsl::not_null<Scalar<DataType>*> energy_density,
     430              :                   gsl::not_null<Cache*> cache,
     431              :                   gr::Tags::Conformal<gr::Tags::EnergyDensity<DataType>,
     432              :                                       ConformalMatterScale> /*meta*/) const;
     433              :   void operator()(gsl::not_null<Scalar<DataType>*> stress_trace,
     434              :                   gsl::not_null<Cache*> cache,
     435              :                   gr::Tags::Conformal<gr::Tags::StressTrace<DataType>,
     436              :                                       ConformalMatterScale> /*meta*/) const;
     437              :   void operator()(gsl::not_null<tnsr::I<DataType, 3>*> momentum_density,
     438              :                   gsl::not_null<Cache*> cache,
     439              :                   gr::Tags::Conformal<gr::Tags::MomentumDensity<DataType, 3>,
     440              :                                       ConformalMatterScale> /*meta*/) const;
     441              : };
     442              : 
     443              : }  // namespace detail
     444              : 
     445              : /*!
     446              :  * \brief Schwarzschild spacetime in general relativity
     447              :  *
     448              :  * This class implements the Schwarzschild solution with mass parameter
     449              :  * \f$M\f$ in various coordinate systems. See the entries of the
     450              :  * `Xcts::Solutions::SchwarzschildCoordinates` enum for the available coordinate
     451              :  * systems and for the solution variables in the respective coordinates.
     452              :  */
     453            1 : class Schwarzschild : public elliptic::analytic_data::AnalyticSolution,
     454              :                       public detail::SchwarzschildImpl {
     455              :  public:
     456            0 :   Schwarzschild() = default;
     457            0 :   Schwarzschild(const Schwarzschild&) = default;
     458            0 :   Schwarzschild& operator=(const Schwarzschild&) = default;
     459            0 :   Schwarzschild(Schwarzschild&&) = default;
     460            0 :   Schwarzschild& operator=(Schwarzschild&&) = default;
     461            0 :   ~Schwarzschild() = default;
     462              : 
     463              :   using SchwarzschildImpl::SchwarzschildImpl;
     464              : 
     465              :   /// \cond
     466              :   explicit Schwarzschild(CkMigrateMessage* m)
     467              :       : elliptic::analytic_data::AnalyticSolution(m) {}
     468              :   using PUP::able::register_constructor;
     469              :   WRAPPED_PUPable_decl_template(Schwarzschild);
     470              :   std::unique_ptr<elliptic::analytic_data::AnalyticSolution> get_clone()
     471              :       const override {
     472              :     return std::make_unique<Schwarzschild>(*this);
     473              :   }
     474              :   /// \endcond
     475              : 
     476              :   template <typename DataType, typename... RequestedTags>
     477            0 :   tuples::TaggedTuple<RequestedTags...> variables(
     478              :       const tnsr::I<DataType, 3, Frame::Inertial>& x,
     479              :       tmpl::list<RequestedTags...> /*meta*/) const {
     480              :     return variables_impl<DataType>(x, std::nullopt, std::nullopt,
     481              :                                     tmpl::list<RequestedTags...>{});
     482              :   }
     483              : 
     484              :   template <typename... RequestedTags>
     485            0 :   tuples::TaggedTuple<RequestedTags...> variables(
     486              :       const tnsr::I<DataVector, 3, Frame::Inertial>& x, const Mesh<3>& mesh,
     487              :       const InverseJacobian<DataVector, 3, Frame::ElementLogical,
     488              :                             Frame::Inertial>& inv_jacobian,
     489              :       tmpl::list<RequestedTags...> /*meta*/) const {
     490              :     return variables_impl<DataVector>(x, mesh, inv_jacobian,
     491              :                                       tmpl::list<RequestedTags...>{});
     492              :   }
     493              : 
     494            0 :   void pup(PUP::er& p) override {
     495              :     elliptic::analytic_data::AnalyticSolution::pup(p);
     496              :     detail::SchwarzschildImpl::pup(p);
     497              :   }
     498              : 
     499              :  private:
     500              :   template <typename DataType, typename... RequestedTags>
     501            0 :   tuples::TaggedTuple<RequestedTags...> variables_impl(
     502              :       const tnsr::I<DataType, 3, Frame::Inertial>& x,
     503              :       std::optional<std::reference_wrapper<const Mesh<3>>> mesh,
     504              :       std::optional<std::reference_wrapper<const InverseJacobian<
     505              :           DataType, 3, Frame::ElementLogical, Frame::Inertial>>>
     506              :           inv_jacobian,
     507              :       tmpl::list<RequestedTags...> /*meta*/) const {
     508              :     using VarsComputer = detail::SchwarzschildVariables<DataType>;
     509              :     typename VarsComputer::Cache cache{get_size(*x.begin())};
     510              :     const VarsComputer computer{std::move(mesh), std::move(inv_jacobian), x,
     511              :                                 mass_, coordinate_system_};
     512              :     const auto get_var = [&cache, &computer, &x](auto tag_v) {
     513              :       using tag = std::decay_t<decltype(tag_v)>;
     514              :       if constexpr (tmpl::list_contains_v<hydro_tags<DataType>, tag>) {
     515              :         (void)cache;
     516              :         (void)computer;
     517              :         return get<tag>(Flatness{}.variables(x, tmpl::list<tag>{}));
     518              :       } else {
     519              :         (void)x;
     520              :         return cache.get_var(computer, tag{});
     521              :       }
     522              :     };
     523              :     return {get_var(RequestedTags{})...};
     524              :   }
     525              : };
     526              : 
     527              : }  // namespace Xcts::Solutions
        

Generated by: LCOV version 2.0-1