SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/Hydro/EquationsOfState - Enthalpy.hpp Hit Total Coverage
Commit: 3c072f0ce967e2e56649d3fa12aa2a0e4fe2a42e Lines: 7 97 7.2 %
Date: 2024-04-23 20:50:18
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 <boost/preprocessor/arithmetic/dec.hpp>
       7             : #include <boost/preprocessor/arithmetic/inc.hpp>
       8             : #include <boost/preprocessor/control/expr_iif.hpp>
       9             : #include <boost/preprocessor/list/adt.hpp>
      10             : #include <boost/preprocessor/repetition/for.hpp>
      11             : #include <boost/preprocessor/repetition/repeat.hpp>
      12             : #include <boost/preprocessor/tuple/to_list.hpp>
      13             : #include <limits>
      14             : #include <pup.h>
      15             : #include <vector>
      16             : 
      17             : #include "DataStructures/Tensor/TypeAliases.hpp"
      18             : #include "Options/String.hpp"
      19             : #include "PointwiseFunctions/Hydro/EquationsOfState/EquationOfState.hpp"  // IWYU pragma: keep
      20             : #include "PointwiseFunctions/Hydro/Units.hpp"
      21             : #include "Utilities/Math.hpp"
      22             : #include "Utilities/Serialization/CharmPupable.hpp"
      23             : #include "Utilities/TMPL.hpp"
      24             : 
      25             : /// \cond
      26             : class DataVector;
      27             : 
      28             : /// \endcond
      29             : 
      30             : // IWYU pragma: no_forward_declare Tensor
      31             : 
      32             : namespace EquationsOfState {
      33             : 
      34             : /*!
      35             :  * \ingroup EquationsOfStateGroup
      36             :  * \brief An equation of state given by parametrized enthalpy
      37             :  *
      38             :  * This equation of state is determined as a function of \f$x =
      39             :  * \ln(\rho/\rho_0)\f$ where \f$\rho\f$ is the rest mass density and
      40             :  * \f$\rho_0\f$ is the provided reference density.
      41             :  * The pseudo-enthalpy \f$h \equiv (p + rho  + u)/rho\f$
      42             :  * is expanded as
      43             :  *
      44             :  * \f{equation}
      45             :  * h(x) = \sum_i a_i x^i + \sum_j b_j \sin(jkx) + c_j \cos(jkx)
      46             :  * \f}
      47             :  *
      48             :  * This form allows for convenient calculation of thermodynamic
      49             :  * quantities for a cold equation of state. For example
      50             :  *
      51             :  * \f{equation}
      52             :  * h(x) = \frac{d e} {d \rho} |_{x = \log(\rho/\rho_0)}
      53             :  * \f}
      54             :  *
      55             :  * where \f$e\f$ is the total energy density.  At the same time \f$ dx =
      56             :  * d\rho/\rho \f$ so \f$ \rho_0 e^x dx = d \rho \f$ Therefore,
      57             :  *
      58             :  * \f{equation}
      59             :  * e(x) - e(x_0) = \int_{x_0}^x h(x') e^{x'} dx '
      60             :  * \f}
      61             :  *
      62             :  * This can be computed analytically because
      63             :  *
      64             :  * \f{equation}
      65             :  *  \int a_i \frac{x^i}{i!} e^{x} dx = \sum_{j \leq i} a_i (-1)^{i-j}
      66             :  * \frac{(x)^{j}}{j!}
      67             :  * + C \f}
      68             :  *
      69             :  * and
      70             :  *
      71             :  * \f{equation}
      72             :  * \int b_j \sin(j k x) e^x dx = b_j e^x \frac{\sin(jkx) - j k \cos(jkx)}{j^2
      73             :  * k^2 + 1} \f}
      74             :  *
      75             :  * \f{equation}
      76             :  * \int c_j \cos(j k x) e^x dx = b_j e^x \frac{\cos(jkx) + j k \sin(jkx)}{j^2
      77             :  * k^2 + 1} \f}
      78             :  *
      79             :  * From this most other thermodynamic quantities can be computed
      80             :  * analytically
      81             :  *
      82             :  * The internal energy density
      83             :  * \f{equation}
      84             :  * \epsilon(x)\rho(x) = e(x)  - \rho(x)
      85             :  * \f}
      86             :  *
      87             :  * The pressure
      88             :  * \f{equation}
      89             :  * p(x) = \rho(x) h(x) - e(x)
      90             :  * \f}
      91             :  *
      92             :  * The derivative of the pressure with respect to the rest mass density
      93             :  * \f{equation}
      94             :  * \chi(x) = \frac{dp}{d\rho} |_{x = x(\rho)} = \frac{dh}{dx}
      95             :  * \f}
      96             :  *
      97             :  * Below the minimum density, a spectral parameterization
      98             :  * is used.
      99             :  *
     100             :  *
     101             :  *
     102             :  */
     103             : template <typename LowDensityEoS>
     104           1 : class Enthalpy : public EquationOfState<true, 1> {
     105             :  private:
     106           0 :   struct Coefficients {
     107           0 :     std::vector<double> polynomial_coefficients;
     108           0 :     std::vector<double> sin_coefficients;
     109           0 :     std::vector<double> cos_coefficients;
     110           0 :     double trig_scale;
     111           0 :     double reference_density;
     112           0 :     bool has_exponential_prefactor;
     113           0 :     double exponential_external_constant;
     114           0 :     Coefficients() = default;
     115           0 :     ~Coefficients() = default;
     116           0 :     Coefficients(const Coefficients& coefficients) = default;
     117           0 :     Coefficients(std::vector<double> in_polynomial_coefficients,
     118             :                  std::vector<double> in_sin_coefficients,
     119             :                  std::vector<double> in_cos_coefficients, double in_trig_scale,
     120             :                  double in_reference_density,
     121             :                  double in_exponential_constant =
     122             :                      std::numeric_limits<double>::quiet_NaN());
     123           0 :     bool operator==(const Coefficients& rhs) const;
     124             : 
     125           0 :     Enthalpy<LowDensityEoS>::Coefficients compute_exponential_integral(
     126             :         const std::pair<double, double>& initial_condition,
     127             :         const double minimum_density);
     128           0 :     Enthalpy<LowDensityEoS>::Coefficients compute_derivative();
     129           0 :     void pup(PUP::er& p);
     130             :   };
     131             : 
     132             :  public:
     133           0 :   static constexpr size_t thermodynamic_dim = 1;
     134           0 :   static constexpr bool is_relativistic = true;
     135             : 
     136           0 :   static std::string name() {
     137             :     return "Enthalpy(" + pretty_type::name<LowDensityEoS>() + ")";
     138             :   }
     139             : 
     140           0 :   struct ReferenceDensity {
     141           0 :     using type = double;
     142           0 :     static constexpr Options::String help = {"Reference density rho_0"};
     143           0 :     static double lower_bound() { return 0.0; }
     144             :   };
     145             : 
     146           0 :   struct MinimumDensity {
     147           0 :     using type = double;
     148           0 :     static constexpr Options::String help = {
     149             :         "Minimum valid density rho_min,"
     150             :         " for this parametrization"};
     151           0 :     static double lower_bound() { return 0.0; }
     152             :   };
     153           0 :   struct MaximumDensity {
     154           0 :     using type = double;
     155           0 :     static constexpr Options::String help = {"Maximum density for this EoS"};
     156           0 :     static double lower_bound() { return 0.0; }
     157             :   };
     158             : 
     159           0 :   struct PolynomialCoefficients {
     160           0 :     using type = std::vector<double>;
     161           0 :     static constexpr Options::String help = {"Polynomial coefficients a_i"};
     162             :   };
     163             : 
     164           0 :   struct TrigScaling {
     165           0 :     using type = double;
     166           0 :     static constexpr Options::String help = {
     167             :         "Fundamental wavenumber of trig "
     168             :         "functions, k"};
     169           0 :     static double lower_bound() { return 0.0; }
     170             :   };
     171             : 
     172           0 :   struct SinCoefficients {
     173           0 :     using type = std::vector<double>;
     174           0 :     static constexpr Options::String help = {"Sine coefficients b_j"};
     175             :   };
     176           0 :   struct CosCoefficients {
     177           0 :     using type = std::vector<double>;
     178           0 :     static constexpr Options::String help = {"Cosine coefficients c_j"};
     179             :   };
     180           0 :   struct StitchedLowDensityEoS {
     181           0 :     using type = LowDensityEoS;
     182           0 :     static std::string name() {
     183             :       return pretty_type::short_name<LowDensityEoS>();
     184             :     }
     185           0 :     static constexpr Options::String help = {
     186             :         "Low density EoS stitched at the MinimumDensity"};
     187             :   };
     188             : 
     189           0 :   struct TransitionDeltaEpsilon {
     190           0 :     using type = double;
     191           0 :     static constexpr Options::String help = {
     192             :         "the change in internal energy across the low-"
     193             :         "to-high-density transition, generically 0.0"};
     194           0 :     static double lower_bound() { return 0.0; }
     195             :   };
     196             : 
     197           0 :   static constexpr Options::String help = {
     198             :       "An EoS with a parametrized value h(log(rho/rho_0)) with h the specific "
     199             :       "enthalpy and rho the baryon rest mass density.  The enthalpy is "
     200             :       "expanded as a sum of polynomial terms and trigonometric corrections. "
     201             :       "let x = log(rho/rho_0) in"
     202             :       "h(x) = \\sum_i a_ix^i + \\sum_j b_jsin(k * j * x) + c_jcos(k * j * x) "
     203             :       "Note that rho(x)(1+epsilon(x)) = int_0^x e^x' h((x') dx' can be "
     204             :       "computed "
     205             :       "analytically, and therefore so can "
     206             :       "P(x) = rho(x) * (h(x) - (1 + epsilon(x))) "};
     207             : 
     208           0 :   using options =
     209             :       tmpl::list<ReferenceDensity, MaximumDensity, MinimumDensity, TrigScaling,
     210             :                  PolynomialCoefficients, SinCoefficients, CosCoefficients,
     211             :                  StitchedLowDensityEoS, TransitionDeltaEpsilon>;
     212             : 
     213           0 :   Enthalpy() = default;
     214           0 :   Enthalpy(const Enthalpy&) = default;
     215           0 :   Enthalpy& operator=(const Enthalpy&) = default;
     216           0 :   Enthalpy(Enthalpy&&) = default;
     217           0 :   Enthalpy& operator=(Enthalpy&&) = default;
     218           0 :   ~Enthalpy() override = default;
     219             : 
     220           0 :   Enthalpy(double reference_density, double max_density, double min_density,
     221             :            double trig_scale,
     222             :            const std::vector<double>& polynomial_coefficients,
     223             :            const std::vector<double>& sin_coefficients,
     224             :            const std::vector<double>& cos_coefficients,
     225             :            const LowDensityEoS& low_density_eos,
     226             :            const double transition_delta_epsilon);
     227             : 
     228           0 :   std::unique_ptr<EquationOfState<true, 1>> get_clone() const override;
     229             : 
     230           0 :   std::unique_ptr<EquationOfState<true, 3>> promote_to_3d_eos() const override;
     231             : 
     232           0 :   std::unique_ptr<EquationOfState<true, 2>> promote_to_2d_eos() const override;
     233             : 
     234           0 :   bool is_equal(const EquationOfState<true, 1>& rhs) const override;
     235             : 
     236           0 :   bool operator==(const Enthalpy<LowDensityEoS>& rhs) const;
     237             : 
     238           0 :   bool operator!=(const Enthalpy<LowDensityEoS>& rhs) const;
     239             : 
     240             :   EQUATION_OF_STATE_FORWARD_DECLARE_MEMBERS(Enthalpy, 1)
     241             : 
     242           0 :   WRAPPED_PUPable_decl_base_template(  // NOLINT
     243             :       SINGLE_ARG(EquationOfState<true, 1>), Enthalpy);
     244             : 
     245             :   /// The lower bound of the rest mass density that is valid for this EOS
     246           1 :   double rest_mass_density_lower_bound() const override { return 0.0; }
     247             : 
     248             :   /// The upper bound of the rest mass density that is valid for this EOS
     249           1 :   double rest_mass_density_upper_bound() const override {
     250             :     return std::numeric_limits<double>::max();
     251             :   }
     252             : 
     253             :   /// The lower bound of the specific internal energy that is valid for this EOS
     254             :   /// at the given rest mass density \f$\rho\f$
     255           1 :   double specific_internal_energy_lower_bound(
     256             :       const double /* rest_mass_density */) const override {
     257             :     return 0.0;
     258             :   }
     259             : 
     260             :   /// The upper bound of the specific internal energy that is valid for this EOS
     261             :   /// at the given rest mass density \f$\rho\f$
     262           1 :   double specific_internal_energy_upper_bound(
     263             :       const double /* rest_mass_density */) const override {
     264             :     return std::numeric_limits<double>::max();
     265             :   }
     266             : 
     267             :   /// The lower bound of the specific enthalpy that is valid for this EOS
     268           1 :   double specific_enthalpy_lower_bound() const override { return 1.0; }
     269             : 
     270             :   /// The vacuum baryon mass for this EoS
     271           1 :   double baryon_mass() const override { return low_density_eos_.baryon_mass(); }
     272             : 
     273             :  private:
     274             :   EQUATION_OF_STATE_FORWARD_DECLARE_MEMBER_IMPLS(1)
     275             : 
     276             :   SPECTRE_ALWAYS_INLINE
     277           0 :   bool in_low_density_domain(const double rest_mass_density) const {
     278             :     return rest_mass_density < minimum_density_;
     279             :   }
     280             : 
     281           0 :   double x_from_density(const double rest_mass_density) const;
     282           0 :   double density_from_x(const double x) const;
     283           0 :   double energy_density_from_log_density(const double x,
     284             :                                          const double rest_mass_density) const;
     285           0 :   static double evaluate_coefficients(
     286             :       const Enthalpy::Coefficients& coefficients, const double x,
     287             :       const double exponential_prefactor =
     288             :           std::numeric_limits<double>::signaling_NaN());
     289           0 :   static Enthalpy::Coefficients compute_pressure_coefficients(
     290             :       const typename Enthalpy::Coefficients& enthalpy,
     291             :       const typename Enthalpy::Coefficients& energy_density);
     292             : 
     293           0 :   double chi_from_density(const double rest_mass_density) const;
     294           0 :   double specific_internal_energy_from_density(
     295             :       const double rest_mass_density) const;
     296           0 :   double specific_enthalpy_from_density(const double rest_mass_density) const;
     297           0 :   double pressure_from_density(const double rest_mass_density) const;
     298           0 :   double pressure_from_log_density(const double x,
     299             :                                    const double rest_mass_density) const;
     300           0 :   double rest_mass_density_from_enthalpy(const double specific_enthalpy) const;
     301             : 
     302           0 :   double reference_density_ = std::numeric_limits<double>::signaling_NaN();
     303           0 :   double minimum_density_ = std::numeric_limits<double>::signaling_NaN();
     304           0 :   double maximum_density_ = std::numeric_limits<double>::signaling_NaN();
     305           0 :   double minimum_enthalpy_ = std::numeric_limits<double>::signaling_NaN();
     306             : 
     307           0 :   LowDensityEoS low_density_eos_;
     308           0 :   Coefficients coefficients_;
     309           0 :   Coefficients exponential_integral_coefficients_;
     310           0 :   Coefficients derivative_coefficients_;
     311           0 :   Coefficients pressure_coefficients_;
     312             : };
     313             : 
     314             : }  // namespace EquationsOfState

Generated by: LCOV version 1.14