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 <cstddef> 14 : #include <limits> 15 : #include <pup.h> 16 : #include <vector> 17 : 18 : #include "DataStructures/Tensor/TypeAliases.hpp" 19 : #include "Options/String.hpp" 20 : #include "PointwiseFunctions/Hydro/EquationsOfState/EquationOfState.hpp" 21 : #include "PointwiseFunctions/Hydro/Units.hpp" 22 : #include "Utilities/Math.hpp" 23 : #include "Utilities/Serialization/CharmPupable.hpp" 24 : #include "Utilities/TMPL.hpp" 25 : 26 : /// \cond 27 : class DataVector; 28 : /// \endcond 29 : 30 : namespace EquationsOfState { 31 : /*! 32 : * \ingroup EquationsOfStateGroup 33 : * \brief A spectral equation of state 34 : * 35 : * This equation of state is determined as a function of \f$x = 36 : * \ln(\rho/\rho_0)\f$ where \f$\rho\f$ is the rest mass density and 37 : * \f$\rho_0\f$ is the provided reference density. The adiabatic 38 : * index \f$\Gamma(x)\f$ is defined such that 39 : * \f{equation}{ 40 : * \frac{d \ln p}{dx} = \Gamma(x) = \sum_{n=0}^N 41 : * \gamma_n x^n 42 : * \f} 43 : * 44 : * for the set of spectral coefficinets \f$\gamma_n\f$ when 45 : * \f$0 < x < x_u = \ln(\rho_u/\rho_0)\f$, where \f$\rho_u\f$ is the provided 46 : * upper density. 47 : * 48 : * For \f$ x < 0 \f$, \f$ \Gamma(x) = \gamma_0 \f$. 49 : * 50 : * For \f$ x > x_u \f$, \f$ \Gamma(x) = \Gamma(x_u) \f$ 51 : * 52 : * 53 : */ 54 1 : class Spectral : public EquationOfState<true, 1> { 55 : public: 56 0 : static constexpr size_t thermodynamic_dim = 1; 57 0 : static constexpr bool is_relativistic = true; 58 : 59 0 : struct ReferenceDensity { 60 0 : using type = double; 61 0 : static constexpr Options::String help = {"Reference density rho_0"}; 62 0 : static double lower_bound() { return 0.0; } 63 : }; 64 : 65 0 : struct ReferencePressure { 66 0 : using type = double; 67 0 : static constexpr Options::String help = {"Reference pressure p_0"}; 68 0 : static double lower_bound() { return 0.0; } 69 : }; 70 : 71 0 : struct Coefficients { 72 0 : using type = std::vector<double>; 73 0 : static constexpr Options::String help = {"Spectral coefficients gamma_i"}; 74 : }; 75 : 76 0 : struct UpperDensity { 77 0 : using type = double; 78 0 : static constexpr Options::String help = {"Upper density rho_u"}; 79 0 : static double lower_bound() { return 0.0; } 80 : }; 81 : 82 0 : static constexpr Options::String help = { 83 : "A spectral equation of state. Defining x = log(rho/rho_0), Gamma(x) = " 84 : "Sum_i gamma_i x^i, then the pressure is determined from d(log P)/dx = " 85 : "Gamma(x) for x > 0. For x < 0 the EOS is a polytrope with " 86 : "Gamma(x)=Gamma(0). For x > x_u = log(rho_u/rho_0), Gamma(x) = " 87 : "Gamma(x_u).\n" 88 : "To get smooth equations of state, it is recommended that the second " 89 : "and third supplied coefficient should be 0. It is up to the user to " 90 : "choose coefficients that are physically reasonable, e.g. that " 91 : "satisfy causality."}; 92 : 93 0 : using options = tmpl::list<ReferenceDensity, ReferencePressure, Coefficients, 94 : UpperDensity>; 95 : 96 0 : Spectral() = default; 97 0 : Spectral(const Spectral&) = default; 98 0 : Spectral& operator=(const Spectral&) = default; 99 0 : Spectral(Spectral&&) = default; 100 0 : Spectral& operator=(Spectral&&) = default; 101 0 : ~Spectral() override = default; 102 : 103 0 : Spectral(double reference_density, double reference_pressure, 104 : std::vector<double> coefficients, double upper_density); 105 : 106 : EQUATION_OF_STATE_FORWARD_DECLARE_MEMBERS(Spectral, 1) 107 : 108 0 : std::unique_ptr<EquationOfState<true, 1>> get_clone() const override; 109 : 110 0 : std::unique_ptr<EquationOfState<true, 3>> promote_to_3d_eos() const override; 111 : 112 0 : std::unique_ptr<EquationOfState<true, 2>> promote_to_2d_eos() const override; 113 : 114 0 : bool operator==(const Spectral& rhs) const; 115 : 116 0 : bool operator!=(const Spectral& rhs) const; 117 : 118 0 : bool is_equal(const EquationOfState<true, 1>& rhs) const override; 119 : 120 0 : WRAPPED_PUPable_decl_base_template( // NOLINT 121 : SINGLE_ARG(EquationOfState<true, 1>), Spectral); 122 : 123 : /// The lower bound of the rest mass density that is valid for this EOS 124 1 : double rest_mass_density_lower_bound() const override { return 0.0; } 125 : 126 : /// The upper bound of the rest mass density that is valid for this EOS 127 1 : double rest_mass_density_upper_bound() const override { 128 : return std::numeric_limits<double>::max(); 129 : } 130 : 131 : /// The lower bound of the specific enthalpy that is valid for this EOS 132 1 : double specific_enthalpy_lower_bound() const override { return 1.0; } 133 : 134 : /// The lower bound of the specific internal energy that is valid for this EOS 135 1 : double specific_internal_energy_lower_bound() const override { return 0.0; } 136 : 137 : /// The upper bound of the specific internal energy that is valid for this EOS 138 1 : double specific_internal_energy_upper_bound() const override { 139 : return std::numeric_limits<double>::max(); 140 : } 141 : 142 : /// The vacuum baryon mass for this EoS 143 1 : double baryon_mass() const override { 144 : return hydro::units::geometric::default_baryon_mass; 145 : } 146 : 147 : private: 148 : EQUATION_OF_STATE_FORWARD_DECLARE_MEMBER_IMPLS(1) 149 : 150 0 : double gamma(const double x) const; 151 0 : double integral_of_gamma(const double x) const; 152 0 : double chi_from_density(const double density) const; 153 0 : double specific_internal_energy_from_density(const double density) const; 154 0 : double specific_enthalpy_from_density(const double density) const; 155 0 : double pressure_from_density(const double density) const; 156 0 : double pressure_from_log_density(const double x) const; 157 0 : double rest_mass_density_from_enthalpy(const double specific_enthalpy) const; 158 : 159 0 : double reference_density_ = std::numeric_limits<double>::signaling_NaN(); 160 0 : double reference_pressure_ = std::numeric_limits<double>::signaling_NaN(); 161 0 : std::vector<double> integral_coefficients_{}; 162 0 : std::vector<double> gamma_coefficients_{}; 163 0 : double x_max_ = std::numeric_limits<double>::signaling_NaN(); 164 0 : double gamma_of_x_max_ = std::numeric_limits<double>::signaling_NaN(); 165 0 : double integral_of_gamma_of_x_max_ = 166 : std::numeric_limits<double>::signaling_NaN(); 167 0 : std::vector<double> table_of_specific_energies_{}; 168 : // Information for Gaussian quadrature 169 0 : size_t number_of_quadrature_coefs_ = 170 : std::numeric_limits<size_t>::signaling_NaN(); 171 0 : std::vector<double> quadrature_weights_{}; 172 0 : std::vector<double> quadrature_points_{}; 173 : }; 174 : 175 : } // namespace EquationsOfState