SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticSolutions/RelativisticEuler - TovStar.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 18.2 % 33 6
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 <cstddef>
       7              : #include <limits>
       8              : 
       9              : #include "DataStructures/CachedTempBuffer.hpp"
      10              : #include "DataStructures/DataBox/Tag.hpp"
      11              : #include "DataStructures/DataVector.hpp"
      12              : #include "DataStructures/TaggedTuple.hpp"
      13              : #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
      14              : #include "DataStructures/Tensor/Tensor.hpp"
      15              : #include "Options/String.hpp"
      16              : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
      17              : #include "PointwiseFunctions/AnalyticSolutions/RelativisticEuler/Solutions.hpp"
      18              : #include "PointwiseFunctions/AnalyticSolutions/RelativisticEuler/Tov.hpp"
      19              : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
      20              : #include "PointwiseFunctions/Hydro/EquationsOfState/Factory.hpp"
      21              : #include "PointwiseFunctions/Hydro/Tags.hpp"
      22              : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
      23              : #include "Utilities/Gsl.hpp"
      24              : #include "Utilities/MakeWithValue.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 RelativisticEuler::Solutions {
      35              : namespace tov_detail {
      36              : 
      37              : enum class StarRegion { Center, Interior, Exterior };
      38              : 
      39              : namespace Tags {
      40              : template <typename DataType>
      41              : struct MassOverRadius : db::SimpleTag {
      42              :   using type = Scalar<DataType>;
      43              : };
      44              : template <typename DataType>
      45              : struct LogSpecificEnthalpy : db::SimpleTag {
      46              :   using type = Scalar<DataType>;
      47              : };
      48              : template <typename DataType>
      49              : struct ConformalFactor : db::SimpleTag {
      50              :   using type = Scalar<DataType>;
      51              : };
      52              : template <typename DataType>
      53              : struct DrConformalFactor : db::SimpleTag {
      54              :   using type = Scalar<DataType>;
      55              : };
      56              : template <typename DataType>
      57              : struct ArealRadius : db::SimpleTag {
      58              :   using type = Scalar<DataType>;
      59              : };
      60              : template <typename DataType>
      61              : struct DrArealRadius : db::SimpleTag {
      62              :   using type = Scalar<DataType>;
      63              : };
      64              : template <typename DataType>
      65              : struct DrPressure : db::SimpleTag {
      66              :   using type = Scalar<DataType>;
      67              : };
      68              : template <typename DataType>
      69              : struct MetricTimePotential : db::SimpleTag {
      70              :   using type = Scalar<DataType>;
      71              : };
      72              : template <typename DataType>
      73              : struct DrMetricTimePotential : db::SimpleTag {
      74              :   using type = Scalar<DataType>;
      75              : };
      76              : template <typename DataType>
      77              : struct MetricRadialPotential : db::SimpleTag {
      78              :   using type = Scalar<DataType>;
      79              : };
      80              : template <typename DataType>
      81              : struct DrMetricRadialPotential : db::SimpleTag {
      82              :   using type = Scalar<DataType>;
      83              : };
      84              : template <typename DataType>
      85              : struct MetricAngularPotential : db::SimpleTag {
      86              :   using type = Scalar<DataType>;
      87              : };
      88              : template <typename DataType>
      89              : struct DrMetricAngularPotential : db::SimpleTag {
      90              :   using type = Scalar<DataType>;
      91              : };
      92              : }  // namespace Tags
      93              : 
      94              : template <typename DataType>
      95              : using TovVariablesCache = cached_temp_buffer_from_typelist<tmpl::list<
      96              :     Tags::MassOverRadius<DataType>, Tags::LogSpecificEnthalpy<DataType>,
      97              :     Tags::ConformalFactor<DataType>, Tags::DrConformalFactor<DataType>,
      98              :     Tags::ArealRadius<DataType>, Tags::DrArealRadius<DataType>,
      99              :     hydro::Tags::SpecificEnthalpy<DataType>,
     100              :     hydro::Tags::RestMassDensity<DataType>,
     101              :     hydro::Tags::ElectronFraction<DataType>, hydro::Tags::Pressure<DataType>,
     102              :     Tags::DrPressure<DataType>,
     103              :     ::Tags::deriv<hydro::Tags::Pressure<DataType>, tmpl::size_t<3>,
     104              :                   Frame::Inertial>,
     105              :     hydro::Tags::SpecificInternalEnergy<DataType>,
     106              :     hydro::Tags::Temperature<DataType>, Tags::MetricTimePotential<DataType>,
     107              :     Tags::DrMetricTimePotential<DataType>,
     108              :     Tags::MetricRadialPotential<DataType>,
     109              :     Tags::DrMetricRadialPotential<DataType>,
     110              :     Tags::MetricAngularPotential<DataType>,
     111              :     Tags::DrMetricAngularPotential<DataType>,
     112              :     hydro::Tags::LorentzFactor<DataType>,
     113              :     hydro::Tags::SpatialVelocity<DataType, 3>,
     114              :     hydro::Tags::MagneticField<DataType, 3>,
     115              :     hydro::Tags::DivergenceCleaningField<DataType>, gr::Tags::Lapse<DataType>,
     116              :     ::Tags::dt<gr::Tags::Lapse<DataType>>,
     117              :     ::Tags::deriv<gr::Tags::Lapse<DataType>, tmpl::size_t<3>, Frame::Inertial>,
     118              :     gr::Tags::Shift<DataType, 3>, ::Tags::dt<gr::Tags::Shift<DataType, 3>>,
     119              :     ::Tags::deriv<gr::Tags::Shift<DataType, 3>, tmpl::size_t<3>,
     120              :                   Frame::Inertial>,
     121              :     gr::Tags::SpatialMetric<DataType, 3>,
     122              :     ::Tags::dt<gr::Tags::SpatialMetric<DataType, 3>>,
     123              :     ::Tags::deriv<gr::Tags::SpatialMetric<DataType, 3>, tmpl::size_t<3>,
     124              :                   Frame::Inertial>,
     125              :     gr::Tags::SqrtDetSpatialMetric<DataType>,
     126              :     gr::Tags::ExtrinsicCurvature<DataType, 3>,
     127              :     gr::Tags::InverseSpatialMetric<DataType, 3>>>;
     128              : 
     129              : template <typename DataType, StarRegion Region>
     130              : struct TovVariables {
     131              :   static constexpr size_t Dim = 3;
     132              :   using Cache = TovVariablesCache<DataType>;
     133              : 
     134              :   TovVariables(const TovVariables&) = default;
     135              :   TovVariables& operator=(const TovVariables&) = default;
     136              :   TovVariables(TovVariables&&) = default;
     137              :   TovVariables& operator=(TovVariables&&) = default;
     138              :   virtual ~TovVariables() = default;
     139              :   TovVariables(
     140              :       const tnsr::I<DataType, 3>& local_coords, const DataType& local_radius,
     141              :       const RelativisticEuler::Solutions::TovSolution& local_radial_solution,
     142              :       const EquationsOfState::EquationOfState<true, 1>& local_eos)
     143              :       : coords(local_coords),
     144              :         radius(local_radius),
     145              :         radial_solution(local_radial_solution),
     146              :         eos(local_eos) {}
     147              : 
     148              :   const tnsr::I<DataType, 3>& coords;
     149              :   const DataType& radius;
     150              :   const RelativisticEuler::Solutions::TovSolution& radial_solution;
     151              :   const EquationsOfState::EquationOfState<true, 1>& eos;
     152              : 
     153              :   void operator()(gsl::not_null<Scalar<DataType>*> mass_over_radius,
     154              :                   gsl::not_null<Cache*> cache,
     155              :                   Tags::MassOverRadius<DataType> /*meta*/) const;
     156              :   void operator()(gsl::not_null<Scalar<DataType>*> log_specific_enthalpy,
     157              :                   gsl::not_null<Cache*> cache,
     158              :                   Tags::LogSpecificEnthalpy<DataType> /*meta*/) const;
     159              :   void operator()(gsl::not_null<Scalar<DataType>*> conformal_factor,
     160              :                   gsl::not_null<Cache*> cache,
     161              :                   Tags::ConformalFactor<DataType> /*meta*/) const;
     162              :   void operator()(gsl::not_null<Scalar<DataType>*> dr_conformal_factor,
     163              :                   gsl::not_null<Cache*> cache,
     164              :                   Tags::DrConformalFactor<DataType> /*meta*/) const;
     165              :   void operator()(gsl::not_null<Scalar<DataType>*> areal_radius,
     166              :                   gsl::not_null<Cache*> cache,
     167              :                   Tags::ArealRadius<DataType> /*meta*/) const;
     168              :   void operator()(gsl::not_null<Scalar<DataType>*> dr_areal_radius,
     169              :                   gsl::not_null<Cache*> cache,
     170              :                   Tags::DrArealRadius<DataType> /*meta*/) const;
     171              :   void operator()(gsl::not_null<Scalar<DataType>*> specific_enthalpy,
     172              :                   gsl::not_null<Cache*> cache,
     173              :                   hydro::Tags::SpecificEnthalpy<DataType> /*meta*/) const;
     174              :   void operator()(gsl::not_null<Scalar<DataType>*> temperature,
     175              :                   gsl::not_null<Cache*> cache,
     176              :                   hydro::Tags::Temperature<DataType> /*meta*/) const;
     177              :   void operator()(gsl::not_null<Scalar<DataType>*> rest_mass_density,
     178              :                   gsl::not_null<Cache*> cache,
     179              :                   hydro::Tags::RestMassDensity<DataType> /*meta*/) const;
     180              :   void operator()(gsl::not_null<Scalar<DataType>*> electron_fraction,
     181              :                   gsl::not_null<Cache*> cache,
     182              :                   hydro::Tags::ElectronFraction<DataType> /*meta*/) const;
     183              :   void operator()(gsl::not_null<Scalar<DataType>*> pressure,
     184              :                   gsl::not_null<Cache*> cache,
     185              :                   hydro::Tags::Pressure<DataType> /*meta*/) const;
     186              :   void operator()(gsl::not_null<Scalar<DataType>*> dr_pressure,
     187              :                   gsl::not_null<Cache*> cache,
     188              :                   Tags::DrPressure<DataType> /*meta*/) const;
     189              :   void operator()(
     190              :       gsl::not_null<tnsr::i<DataType, 3>*> deriv_pressure,
     191              :       gsl::not_null<Cache*> cache,
     192              :       ::Tags::deriv<hydro::Tags::Pressure<DataType>, tmpl::size_t<3>,
     193              :                     Frame::Inertial> /*meta*/) const;
     194              :   void operator()(gsl::not_null<Scalar<DataType>*> specific_internal_energy,
     195              :                   gsl::not_null<Cache*> cache,
     196              :                   hydro::Tags::SpecificInternalEnergy<DataType> /*meta*/) const;
     197              :   void operator()(gsl::not_null<Scalar<DataType>*> metric_time_potential,
     198              :                   gsl::not_null<Cache*> cache,
     199              :                   Tags::MetricTimePotential<DataType> /*meta*/) const;
     200              :   void operator()(gsl::not_null<Scalar<DataType>*> dr_metric_time_potential,
     201              :                   gsl::not_null<Cache*> cache,
     202              :                   Tags::DrMetricTimePotential<DataType> /*meta*/) const;
     203              :   void operator()(gsl::not_null<Scalar<DataType>*> metric_radial_potential,
     204              :                   gsl::not_null<Cache*> cache,
     205              :                   Tags::MetricRadialPotential<DataType> /*meta*/) const;
     206              :   void operator()(gsl::not_null<Scalar<DataType>*> dr_metric_radial_potential,
     207              :                   gsl::not_null<Cache*> cache,
     208              :                   Tags::DrMetricRadialPotential<DataType> /*meta*/) const;
     209              :   void operator()(gsl::not_null<Scalar<DataType>*> metric_angular_potential,
     210              :                   gsl::not_null<Cache*> cache,
     211              :                   Tags::MetricAngularPotential<DataType> /*meta*/) const;
     212              :   void operator()(gsl::not_null<Scalar<DataType>*> dr_metric_angular_potential,
     213              :                   gsl::not_null<Cache*> cache,
     214              :                   Tags::DrMetricAngularPotential<DataType> /*meta*/) const;
     215              :   void operator()(gsl::not_null<Scalar<DataType>*> lorentz_factor,
     216              :                   gsl::not_null<Cache*> cache,
     217              :                   hydro::Tags::LorentzFactor<DataType> /*meta*/) const;
     218              :   void operator()(gsl::not_null<tnsr::I<DataType, 3>*> spatial_velocity,
     219              :                   gsl::not_null<Cache*> cache,
     220              :                   hydro::Tags::SpatialVelocity<DataType, 3> /*meta*/) const;
     221              :   virtual void operator()(
     222              :       gsl::not_null<tnsr::I<DataType, 3>*> magnetic_field,
     223              :       gsl::not_null<Cache*> cache,
     224              :       hydro::Tags::MagneticField<DataType, 3> /*meta*/) const;
     225              :   void operator()(
     226              :       gsl::not_null<Scalar<DataType>*> div_cleaning_field,
     227              :       gsl::not_null<Cache*> cache,
     228              :       hydro::Tags::DivergenceCleaningField<DataType> /*meta*/) const;
     229              :   void operator()(gsl::not_null<Scalar<DataType>*> lapse,
     230              :                   gsl::not_null<Cache*> cache,
     231              :                   gr::Tags::Lapse<DataType> /*meta*/) const;
     232              :   void operator()(gsl::not_null<Scalar<DataType>*> dt_lapse,
     233              :                   gsl::not_null<Cache*> cache,
     234              :                   ::Tags::dt<gr::Tags::Lapse<DataType>> /*meta*/) const;
     235              :   void operator()(gsl::not_null<tnsr::i<DataType, 3>*> deriv_lapse,
     236              :                   gsl::not_null<Cache*> cache,
     237              :                   ::Tags::deriv<gr::Tags::Lapse<DataType>, tmpl::size_t<3>,
     238              :                                 Frame::Inertial> /*meta*/) const;
     239              :   void operator()(gsl::not_null<tnsr::I<DataType, 3>*> shift,
     240              :                   gsl::not_null<Cache*> cache,
     241              :                   gr::Tags::Shift<DataType, 3> /*meta*/) const;
     242              :   void operator()(gsl::not_null<tnsr::I<DataType, 3>*> dt_shift,
     243              :                   gsl::not_null<Cache*> cache,
     244              :                   ::Tags::dt<gr::Tags::Shift<DataType, 3>> /*meta*/) const;
     245              :   void operator()(gsl::not_null<tnsr::iJ<DataType, 3>*> deriv_shift,
     246              :                   gsl::not_null<Cache*> cache,
     247              :                   ::Tags::deriv<gr::Tags::Shift<DataType, 3>, tmpl::size_t<3>,
     248              :                                 Frame::Inertial> /*meta*/) const;
     249              :   void operator()(gsl::not_null<tnsr::ii<DataType, 3>*> spatial_metric,
     250              :                   gsl::not_null<Cache*> cache,
     251              :                   gr::Tags::SpatialMetric<DataType, 3> /*meta*/) const;
     252              :   void operator()(
     253              :       gsl::not_null<tnsr::ii<DataType, 3>*> dt_spatial_metric,
     254              :       gsl::not_null<Cache*> cache,
     255              :       ::Tags::dt<gr::Tags::SpatialMetric<DataType, 3>> /*meta*/) const;
     256              :   void operator()(
     257              :       gsl::not_null<tnsr::ijj<DataType, 3>*> deriv_spatial_metric,
     258              :       gsl::not_null<Cache*> cache,
     259              :       ::Tags::deriv<gr::Tags::SpatialMetric<DataType, 3>, tmpl::size_t<3>,
     260              :                     Frame::Inertial> /*meta*/) const;
     261              :   void operator()(gsl::not_null<Scalar<DataType>*> sqrt_det_spatial_metric,
     262              :                   gsl::not_null<Cache*> cache,
     263              :                   gr::Tags::SqrtDetSpatialMetric<DataType> /*meta*/) const;
     264              :   void operator()(gsl::not_null<tnsr::ii<DataType, 3>*> extrinsic_curvature,
     265              :                   gsl::not_null<Cache*> cache,
     266              :                   gr::Tags::ExtrinsicCurvature<DataType, 3> /*meta*/) const;
     267              :   void operator()(gsl::not_null<tnsr::II<DataType, 3>*> inv_spatial_metric,
     268              :                   gsl::not_null<Cache*> cache,
     269              :                   gr::Tags::InverseSpatialMetric<DataType, 3> /*meta*/) const;
     270              : };
     271              : }  // namespace tov_detail
     272              : 
     273              : /*!
     274              :  * \brief A static spherically symmetric star
     275              :  *
     276              :  * An analytic solution for a static, spherically-symmetric star found by
     277              :  * solving the Tolman-Oppenheimer-Volkoff (TOV) equations.  The equation of
     278              :  * state is assumed to be that of a polytropic fluid.
     279              :  *
     280              :  * If the spherically symmetric metric is written as
     281              :  *
     282              :  * \f[
     283              :  * ds^2 = - e^{2 \Phi_t} dt^2 + e^{2 \Phi_r} dr^2 + e^{2 \Phi_\Omega} r^2
     284              :  * d\Omega^2
     285              :  * \f]
     286              :  *
     287              :  * where \f$r = \delta_{mn} x^m x^n\f$ is the radial coordinate and
     288              :  * \f$\Phi_t\f$, \f$\Phi_r\f$, and \f$\Phi_\Omega\f$ are the metric potentials,
     289              :  * then the lapse, shift, and spatial metric in Cartesian coordinates are
     290              :  *
     291              :  * \f{align*}
     292              :  * \alpha &= e^{\Phi_t} \\
     293              :  * \beta^i &= 0 \\
     294              :  * \gamma_{ij} &= \delta_{ij} e^{2 \Phi_\Omega} + \delta_{im} \delta_{jn}
     295              :  * \frac{x^m x^n}{r^2} \left( e^{2 \Phi_r} - e^{2 \Phi_\Omega} \right)
     296              :  * \f}
     297              :  *
     298              :  * We solve the TOV equations with the method implemented in
     299              :  * `RelativisticEuler::Solutions::TovSolution`. It provides the areal
     300              :  * mass-over-radius \f$m(r)/r\f$ and the log of the specific enthalpy
     301              :  * \f$\log{h}\f$. In areal (Schwarzschild) coordinates the spatial metric
     302              :  * potentials are
     303              :  *
     304              :  * \f{align}
     305              :  * e^{\Phi_r} &= \left(1 - \frac{2m}{r}\right)^{-1/2} \\
     306              :  * e^{\Phi_\Omega} &= 1
     307              :  * \f}
     308              :  *
     309              :  * In isotropic coordinates the spatial metric potentials are
     310              :  *
     311              :  * \begin{equation}
     312              :  * e^{2\Phi_r} = e^{2\Phi_\Omega} = \psi^4
     313              :  * \text{,}
     314              :  * \end{equation}
     315              :  *
     316              :  * where $\psi = \sqrt{r / \bar{r}}$ is the conformal factor, $r$ is the areal
     317              :  * (Schwarzschild) radius and $\bar{r}$ is the isotropic radius. See
     318              :  * `RelativisticEuler::Solutions::TovSolution` for details.
     319              :  *
     320              :  * \warning Isotropic coordinates should be used because the metric derivatives
     321              :  * are smooth. Otherwise the grid will over-compensate with finite difference
     322              :  * cells.
     323              :  */
     324              : 
     325            1 : class TovStar : public virtual evolution::initial_data::InitialData,
     326              :                 public MarkAsAnalyticSolution,
     327              :                 public AnalyticSolution<3> {
     328              :  public:
     329            0 :   using equation_of_state_type = EquationsOfState::EquationOfState<true, 1>;
     330              : 
     331              :   /// The central density of the star.
     332            1 :   struct CentralDensity {
     333            0 :     using type = double;
     334            0 :     static constexpr Options::String help = {
     335              :         "The central density of the star."};
     336            0 :     static type lower_bound() { return 0.; }
     337              :   };
     338              : 
     339              :   /// Areal (Schwarzschild) or isotropic coordinates
     340            1 :   struct Coordinates {
     341            0 :     using type = RelativisticEuler::Solutions::TovCoordinates;
     342            0 :     static constexpr Options::String help = {
     343              :         "Areal ('Schwarzschild') or 'Isotropic' coordinates."};
     344              :   };
     345              : 
     346            0 :   static constexpr size_t volume_dim = 3_st;
     347              : 
     348            0 :   using options =
     349              :       tmpl::list<CentralDensity,
     350              :                  hydro::OptionTags::InitialDataEquationOfState<true, 1>,
     351              :                  Coordinates>;
     352              : 
     353            0 :   static constexpr Options::String help = {
     354              :       "A static, spherically-symmetric star found by solving the \n"
     355              :       "Tolman-Oppenheimer-Volkoff (TOV) equations, with a given central \n"
     356              :       "density and equation of state."};
     357              : 
     358            0 :   TovStar() = default;
     359            0 :   TovStar(const TovStar& /*rhs*/);
     360            0 :   TovStar& operator=(const TovStar& /*rhs*/);
     361            0 :   TovStar(TovStar&& /*rhs*/) = default;
     362            0 :   TovStar& operator=(TovStar&& /*rhs*/) = default;
     363            0 :   ~TovStar() override = default;
     364            0 :   TovStar(double central_rest_mass_density,
     365              :           std::unique_ptr<EquationsOfState::EquationOfState<true, 1>>
     366              :               equation_of_state,
     367              :           const RelativisticEuler::Solutions::TovCoordinates coordinate_system =
     368              :               RelativisticEuler::Solutions::TovCoordinates::Schwarzschild);
     369              : 
     370            0 :   auto get_clone() const
     371              :       -> std::unique_ptr<evolution::initial_data::InitialData> override;
     372              : 
     373              :   /// \cond
     374              :   explicit TovStar(CkMigrateMessage* msg);
     375              :   using PUP::able::register_constructor;
     376              :   WRAPPED_PUPable_decl_template(TovStar);
     377              :   /// \endcond
     378              : 
     379              :   /// Retrieve a collection of variables at `(x, t)`
     380              :   template <typename DataType, typename... Tags>
     381            1 :   tuples::TaggedTuple<Tags...> variables(const tnsr::I<DataType, 3>& x,
     382              :                                          const double /*t*/,
     383              :                                          tmpl::list<Tags...> /*meta*/) const {
     384              :     return variables_impl<tov_detail::TovVariables>(x, tmpl::list<Tags...>{});
     385              :   }
     386              : 
     387              :   /// NOLINTNEXTLINE(google-runtime-references)
     388            1 :   void pup(PUP::er& /*p*/) override;
     389              : 
     390            0 :   const EquationsOfState::EquationOfState<true, 1>& equation_of_state() const {
     391              :     return *equation_of_state_;
     392              :   }
     393              : 
     394              :   /// The radial profile of the star
     395            1 :   const RelativisticEuler::Solutions::TovSolution& radial_solution() const {
     396              :     return radial_solution_;
     397              :   }
     398              : 
     399              :  protected:
     400              :   template <template <class, tov_detail::StarRegion> class VarsComputer,
     401              :             typename DataType, typename... Tags, typename... VarsComputerArgs>
     402            0 :   tuples::TaggedTuple<Tags...> variables_impl(
     403              :       const tnsr::I<DataType, 3>& x, tmpl::list<Tags...> /*meta*/,
     404              :       VarsComputerArgs&&... vars_computer_args) const {
     405              :     const double outer_radius = radial_solution_.outer_radius();
     406              :     const double center_radius_cutoff = 1.e-30 * outer_radius;
     407              :     const DataType radius = get(magnitude(x));
     408              :     // Dispatch interior and exterior regions of the star.
     409              :     // - Include the equality in the conditions below for the outer radius so
     410              :     //   the `DataVector` variants are preferred over the pointwise `double`
     411              :     //   variant when possible.
     412              :     // - Order the conditions so the cheaper exterior solution is preferred over
     413              :     //   the interior.
     414              :     // - A `DataVector` variant for the center of the star is not needed because
     415              :     //   it's only a single point.
     416              :     if (min(radius) >= outer_radius) {
     417              :       // All points are outside the star. This could be replaced by a
     418              :       // Schwarzschild solution.
     419              :       using ExteriorVarsComputer =
     420              :           VarsComputer<DataType, tov_detail::StarRegion::Exterior>;
     421              :       typename ExteriorVarsComputer::Cache cache{get_size(radius)};
     422              :       ExteriorVarsComputer computer{
     423              :           x, radius, radial_solution_, *equation_of_state_,
     424              :           std::forward<VarsComputerArgs>(vars_computer_args)...};
     425              :       return {cache.get_var(computer, Tags{})...};
     426              :     } else if (max(radius) <= outer_radius and
     427              :                min(radius) > center_radius_cutoff) {
     428              :       // All points are in the star interior, but not at the center
     429              :       using InteriorVarsComputer =
     430              :           VarsComputer<DataType, tov_detail::StarRegion::Interior>;
     431              :       typename InteriorVarsComputer::Cache cache{get_size(radius)};
     432              :       InteriorVarsComputer computer{
     433              :           x, radius, radial_solution_, *equation_of_state_,
     434              :           std::forward<VarsComputerArgs>(vars_computer_args)...};
     435              :       return {cache.get_var(computer, Tags{})...};
     436              :     } else {
     437              :       // Points can be at the center, in the interior, or outside the star, so
     438              :       // check each point individually
     439              :       const size_t num_points = get_size(radius);
     440              :       tuples::TaggedTuple<Tags...> vars{typename Tags::type{num_points}...};
     441              :       const auto get_var = [&vars](const size_t point_index, auto& local_cache,
     442              :                                    const auto& local_computer, auto tag_v) {
     443              :         using tag = std::decay_t<decltype(tag_v)>;
     444              :         if constexpr (std::is_same_v<DataType, DataVector>) {
     445              :           using tags_double = typename VarsComputer<
     446              :               double, tov_detail::StarRegion::Exterior>::Cache::tags_list;
     447              :           using tags_dv = typename VarsComputer<
     448              :               DataVector, tov_detail::StarRegion::Exterior>::Cache::tags_list;
     449              :           using tag_double =
     450              :               tmpl::at<tags_double, tmpl::index_of<tags_dv, tag>>;
     451              :           const auto& tensor =
     452              :               local_cache.get_var(local_computer, tag_double{});
     453              :           for (size_t component = 0; component < tensor.size(); ++component) {
     454              :             get<tag>(vars)[component][point_index] = tensor[component];
     455              :           }
     456              :         } else {
     457              :           (void)point_index;
     458              :           get<tag>(vars) = local_cache.get_var(local_computer, tag{});
     459              :         }
     460              :         return '0';
     461              :       };
     462              :       using CenterVarsComputer =
     463              :           VarsComputer<double, tov_detail::StarRegion::Center>;
     464              :       using InteriorVarsComputer =
     465              :           VarsComputer<double, tov_detail::StarRegion::Interior>;
     466              :       using ExteriorVarsComputer =
     467              :           VarsComputer<double, tov_detail::StarRegion::Exterior>;
     468              :       for (size_t i = 0; i < num_points; ++i) {
     469              :         const tnsr::I<double, 3> x_i{
     470              :             {{get_element(get<0>(x), i), get_element(get<1>(x), i),
     471              :               get_element(get<2>(x), i)}}};
     472              :         if (get_element(radius, i) > outer_radius) {
     473              :           typename ExteriorVarsComputer::Cache cache{1};
     474              :           ExteriorVarsComputer computer{
     475              :               x_i, get_element(radius, i), radial_solution_,
     476              :               *equation_of_state_,
     477              :               std::forward<VarsComputerArgs>(vars_computer_args)...};
     478              :           expand_pack(get_var(i, cache, computer, Tags{})...);
     479              :         } else if (get_element(radius, i) > center_radius_cutoff) {
     480              :           typename InteriorVarsComputer::Cache cache{1};
     481              :           InteriorVarsComputer computer{
     482              :               x_i, get_element(radius, i), radial_solution_,
     483              :               *equation_of_state_,
     484              :               std::forward<VarsComputerArgs>(vars_computer_args)...};
     485              :           expand_pack(get_var(i, cache, computer, Tags{})...);
     486              :         } else {
     487              :           typename CenterVarsComputer::Cache cache{1};
     488              :           CenterVarsComputer computer{
     489              :               x_i, get_element(radius, i), radial_solution_,
     490              :               *equation_of_state_,
     491              :               std::forward<VarsComputerArgs>(vars_computer_args)...};
     492              :           expand_pack(get_var(i, cache, computer, Tags{})...);
     493              :         }
     494              :       }
     495              :       return vars;
     496              :     }
     497              :   }
     498              : 
     499              :  public:
     500              :   template <typename DataType>
     501            0 :   using tags = tmpl::list_difference<
     502              :       typename tov_detail::TovVariablesCache<DataType>::tags_list,
     503              :       tmpl::list<
     504              :           // Remove internal tags, which may not be available in the full domain
     505              :           tov_detail::Tags::MassOverRadius<DataType>,
     506              :           tov_detail::Tags::LogSpecificEnthalpy<DataType>,
     507              :           tov_detail::Tags::ConformalFactor<DataType>,
     508              :           tov_detail::Tags::DrConformalFactor<DataType>,
     509              :           tov_detail::Tags::ArealRadius<DataType>,
     510              :           tov_detail::Tags::DrArealRadius<DataType>,
     511              :           tov_detail::Tags::DrPressure<DataType>,
     512              :           tov_detail::Tags::MetricTimePotential<DataType>,
     513              :           tov_detail::Tags::DrMetricTimePotential<DataType>,
     514              :           tov_detail::Tags::MetricRadialPotential<DataType>,
     515              :           tov_detail::Tags::DrMetricRadialPotential<DataType>,
     516              :           tov_detail::Tags::MetricAngularPotential<DataType>,
     517              :           tov_detail::Tags::DrMetricAngularPotential<DataType>>>;
     518              : 
     519              :  private:
     520            0 :   friend bool operator==(const TovStar& lhs, const TovStar& rhs);
     521              : 
     522            0 :   double central_rest_mass_density_ =
     523              :       std::numeric_limits<double>::signaling_NaN();
     524            0 :   std::unique_ptr<equation_of_state_type> equation_of_state_;
     525            0 :   RelativisticEuler::Solutions::TovCoordinates coordinate_system_{};
     526            0 :   RelativisticEuler::Solutions::TovSolution radial_solution_{};
     527              : };
     528              : 
     529            0 : bool operator!=(const TovStar& lhs, const TovStar& rhs);
     530              : }  // namespace RelativisticEuler::Solutions
        

Generated by: LCOV version 2.0-1