EquationOfState.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <boost/preprocessor/arithmetic/sub.hpp>
7 #include <boost/preprocessor/list/for_each.hpp>
8 #include <boost/preprocessor/punctuation/comma_if.hpp>
9 #include <boost/preprocessor/repetition/repeat.hpp>
10 #include <boost/preprocessor/tuple/enum.hpp>
11 #include <boost/preprocessor/tuple/to_list.hpp>
12 
15 #include "Utilities/TMPL.hpp"
16 #include "Utilities/TypeTraits.hpp"
17 
18 /// \cond
19 class DataVector;
20 namespace EquationsOfState {
21 template <bool IsRelativistic>
22 class DarkEnergyFluid;
23 template <bool IsRelativistic>
24 class IdealFluid;
25 template <bool IsRelativistic>
26 class PolytropicFluid;
27 } // namespace EquationsOfState
28 /// \endcond
29 
30 /// Contains all equations of state, including base class
31 namespace EquationsOfState {
32 
33 namespace detail {
34 template <bool IsRelativistic, size_t ThermodynamicDim>
35 struct DerivedClasses;
36 
37 template <bool IsRelativistic>
38 struct DerivedClasses<IsRelativistic, 1> {
39  using type = tmpl::list<PolytropicFluid<IsRelativistic>>;
40 };
41 
42 template <>
43 struct DerivedClasses<true, 2> {
44  using type = tmpl::list<DarkEnergyFluid<true>, IdealFluid<true>>;
45 };
46 
47 template <>
48 struct DerivedClasses<false, 2> {
49  using type = tmpl::list<IdealFluid<false>>;
50 };
51 } // namespace detail
52 
53 /*!
54  * \ingroup EquationsOfStateGroup
55  * \brief Base class for equations of state depending on whether or not the
56  * system is relativistic, and the number of independent thermodynamic variables
57  * (`ThermodynamicDim`) needed to determine the pressure.
58  *
59  * The template parameter `IsRelativistic` is `true` for relativistic equations
60  * of state and `false` for non-relativistic equations of state.
61  */
62 template <bool IsRelativistic, size_t ThermodynamicDim>
64 
65 /*!
66  * \ingroup EquationsOfStateGroup
67  * \brief Base class for equations of state which need one thermodynamic
68  * variable in order to determine the pressure.
69  *
70  * The template parameter `IsRelativistic` is `true` for relativistic equations
71  * of state and `false` for non-relativistic equations of state.
72  */
73 template <bool IsRelativistic>
74 class EquationOfState<IsRelativistic, 1>
75  : public PUP::able {
76  public:
77  static constexpr bool is_relativistic = IsRelativistic;
78  static constexpr size_t thermodynamic_dim = 1;
79  using creatable_classes =
80  typename detail::DerivedClasses<IsRelativistic, 1>::type;
81 
82  EquationOfState() = default;
83  EquationOfState(const EquationOfState&) = default;
84  EquationOfState& operator=(const EquationOfState&) = default;
85  EquationOfState(EquationOfState&&) = default;
86  EquationOfState& operator=(EquationOfState&&) = default;
87  ~EquationOfState() override = default;
88 
90 
91  // @{
92  /*!
93  * Computes the pressure \f$p\f$ from the rest mass density \f$\rho\f$.
94  */
95  virtual Scalar<double> pressure_from_density(
96  const Scalar<double>& /*rest_mass_density*/) const noexcept = 0;
97  virtual Scalar<DataVector> pressure_from_density(
98  const Scalar<DataVector>& /*rest_mass_density*/) const noexcept = 0;
99  // @}
100 
101  // @{
102  /*!
103  * Computes the rest mass density \f$\rho\f$ from the specific enthalpy
104  * \f$h\f$.
105  */
106  virtual Scalar<double> rest_mass_density_from_enthalpy(
107  const Scalar<double>& /*specific_enthalpy*/) const noexcept = 0;
108  virtual Scalar<DataVector> rest_mass_density_from_enthalpy(
109  const Scalar<DataVector>& /*specific_enthalpy*/) const noexcept = 0;
110  // @}
111 
112  // @{
113  /*!
114  * Computes the specific enthalpy \f$h\f$ from the rest mass density
115  * \f$\rho\f$.
116  */
117  virtual Scalar<double> specific_enthalpy_from_density(
118  const Scalar<double>& /*rest_mass_density*/) const noexcept = 0;
119  virtual Scalar<DataVector> specific_enthalpy_from_density(
120  const Scalar<DataVector>& /*rest_mass_density*/) const noexcept = 0;
121  // @}
122 
123  // @{
124  /*!
125  * Computes the specific internal energy \f$\epsilon\f$ from the rest mass
126  * density \f$\rho\f$.
127  */
128  virtual Scalar<double> specific_internal_energy_from_density(
129  const Scalar<double>& /*rest_mass_density*/) const noexcept = 0;
130  virtual Scalar<DataVector> specific_internal_energy_from_density(
131  const Scalar<DataVector>& /*rest_mass_density*/) const noexcept = 0;
132  // @}
133 
134  // @{
135  /*!
136  * Computes \f$\chi=\partial p / \partial \rho\f$ from \f$\rho\f$, where
137  * \f$p\f$ is the pressure and \f$\rho\f$ is the rest mass density.
138  */
139  virtual Scalar<double> chi_from_density(
140  const Scalar<double>& /*rest_mass_density*/) const noexcept = 0;
141  virtual Scalar<DataVector> chi_from_density(
142  const Scalar<DataVector>& /*rest_mass_density*/) const noexcept = 0;
143  // @}
144 
145  // @{
146  /*!
147  * Computes \f$\kappa p/\rho^2=(p/\rho^2)\partial p / \partial \epsilon\f$
148  * from \f$\rho\f$, where \f$p\f$ is the pressure, \f$\rho\f$ is the rest mass
149  * density, and \f$\epsilon\f$ is the specific internal energy.
150  *
151  * The reason for not returning just
152  * \f$\kappa=\partial p / \partial \epsilon\f$ is to avoid division by zero
153  * for small values of \f$\rho\f$ when assembling the speed of sound with
154  * some equations of state.
155  */
156  virtual Scalar<double> kappa_times_p_over_rho_squared_from_density(
157  const Scalar<double>& /*rest_mass_density*/) const noexcept = 0;
158  virtual Scalar<DataVector> kappa_times_p_over_rho_squared_from_density(
159  const Scalar<DataVector>& /*rest_mass_density*/) const noexcept = 0;
160 };
161 
162 /*!
163  * \ingroup EquationsOfStateGroup
164  * \brief Base class for equations of state which need two independent
165  * thermodynamic variables in order to determine the pressure.
166  *
167  * The template parameter `IsRelativistic` is `true` for relativistic equations
168  * of state and `false` for non-relativistic equations of state.
169  */
170 template <bool IsRelativistic>
171 class EquationOfState<IsRelativistic, 2>
172  : public PUP::able {
173  public:
174  static constexpr bool is_relativistic = IsRelativistic;
175  static constexpr size_t thermodynamic_dim = 2;
176  using creatable_classes =
177  typename detail::DerivedClasses<IsRelativistic, 2>::type;
178 
179  EquationOfState() = default;
180  EquationOfState(const EquationOfState&) = default;
181  EquationOfState& operator=(const EquationOfState&) = default;
182  EquationOfState(EquationOfState&&) = default;
183  EquationOfState& operator=(EquationOfState&&) = default;
184  ~EquationOfState() override = default;
185 
187 
188  // @{
189  /*!
190  * Computes the pressure \f$p\f$ from the rest mass density \f$\rho\f$ and the
191  * specific internal energy \f$\epsilon\f$.
192  */
193  virtual Scalar<double> pressure_from_density_and_energy(
194  const Scalar<double>& /*rest_mass_density*/,
195  const Scalar<double>& /*specific_internal_energy*/) const noexcept = 0;
196  virtual Scalar<DataVector> pressure_from_density_and_energy(
197  const Scalar<DataVector>& /*rest_mass_density*/,
198  const Scalar<DataVector>& /*specific_internal_energy*/) const
199  noexcept = 0;
200  // @}
201 
202  // @{
203  /*!
204  * Computes the pressure \f$p\f$ from the rest mass density \f$\rho\f$ and the
205  * specific enthalpy \f$h\f$.
206  */
207  virtual Scalar<double> pressure_from_density_and_enthalpy(
208  const Scalar<double>& /*rest_mass_density*/,
209  const Scalar<double>& /*specific_enthalpy*/) const noexcept = 0;
210  virtual Scalar<DataVector> pressure_from_density_and_enthalpy(
211  const Scalar<DataVector>& /*rest_mass_density*/,
212  const Scalar<DataVector>& /*specific_enthalpy*/) const noexcept = 0;
213  // @}
214 
215  // @{
216  /*!
217  * Computes the specific enthalpy \f$h\f$ from the rest mass density
218  * \f$\rho\f$ and the specific internal energy \f$\epsilon\f$.
219  */
220  virtual Scalar<double> specific_enthalpy_from_density_and_energy(
221  const Scalar<double>& /*rest_mass_density*/,
222  const Scalar<double>& /*specific_internal_energy*/) const noexcept = 0;
223  virtual Scalar<DataVector> specific_enthalpy_from_density_and_energy(
224  const Scalar<DataVector>& /*rest_mass_density*/,
225  const Scalar<DataVector>& /*specific_internal_energy*/) const
226  noexcept = 0;
227  // @}
228 
229  // @{
230  /*!
231  * Computes the specific internal energy \f$\epsilon\f$ from the rest mass
232  * density \f$\rho\f$ and the pressure \f$pn\f$.
233  */
234  virtual Scalar<double> specific_internal_energy_from_density_and_pressure(
235  const Scalar<double>& /*rest_mass_density*/,
236  const Scalar<double>& /*pressure*/) const noexcept = 0;
237  virtual Scalar<DataVector> specific_internal_energy_from_density_and_pressure(
238  const Scalar<DataVector>& /*rest_mass_density*/,
239  const Scalar<DataVector>& /*pressure*/) const noexcept = 0;
240  // @}
241 
242  // @{
243  /*!
244  * Computes \f$\chi=\partial p / \partial \rho\f$ from the \f$\rho\f$ and
245  * \f$\epsilon\f$, where \f$p\f$ is the pressure, \f$\rho\f$ is the rest mass
246  * density, and \f$\epsilon\f$ is the specific internal energy.
247  */
248  virtual Scalar<double> chi_from_density_and_energy(
249  const Scalar<double>& /*rest_mass_density*/,
250  const Scalar<double>& /*specific_internal_energy*/) const noexcept = 0;
251  virtual Scalar<DataVector> chi_from_density_and_energy(
252  const Scalar<DataVector>& /*rest_mass_density*/,
253  const Scalar<DataVector>& /*specific_internal_energy*/) const
254  noexcept = 0;
255  // @}
256 
257  // @{
258  /*!
259  * Computes \f$\kappa p/\rho^2=(p/\rho^2)\partial p / \partial \epsilon\f$
260  * from \f$\rho\f$ and \f$\epsilon\f$, where \f$p\f$ is the pressure,
261  * \f$\rho\f$ is the rest mass density, and \f$\epsilon\f$ is the specific
262  * internal energy.
263  *
264  * The reason for not returning just
265  * \f$\kappa=\partial p / \partial \epsilon\f$ is to avoid division by zero
266  * for small values of \f$\rho\f$ when assembling the speed of sound with
267  * some equations of state.
268  */
269  virtual Scalar<double> kappa_times_p_over_rho_squared_from_density_and_energy(
270  const Scalar<double>& /*rest_mass_density*/,
271  const Scalar<double>& /*specific_internal_energy*/) const noexcept = 0;
272  virtual Scalar<DataVector>
273  kappa_times_p_over_rho_squared_from_density_and_energy(
274  const Scalar<DataVector>& /*rest_mass_density*/,
275  const Scalar<DataVector>& /*specific_internal_energy*/) const
276  noexcept = 0;
277  // @}
278 };
279 } // namespace EquationsOfState
280 
281 /// \cond
282 #define EQUATION_OF_STATE_FUNCTIONS_1D \
283  (pressure_from_density, rest_mass_density_from_enthalpy, \
284  specific_enthalpy_from_density, specific_internal_energy_from_density, \
285  chi_from_density, kappa_times_p_over_rho_squared_from_density)
286 
287 #define EQUATION_OF_STATE_FUNCTIONS_2D \
288  (pressure_from_density_and_energy, pressure_from_density_and_enthalpy, \
289  specific_enthalpy_from_density_and_energy, \
290  specific_internal_energy_from_density_and_pressure, \
291  chi_from_density_and_energy, \
292  kappa_times_p_over_rho_squared_from_density_and_energy)
293 
294 #define EQUATION_OF_STATE_ARGUMENTS_EXPAND(z, n, type) \
295  BOOST_PP_COMMA_IF(n) const Scalar<type>&
296 
297 #define EQUATION_OF_STATE_FORWARD_DECLARE_MEMBERS_HELPER(r, DIM, \
298  FUNCTION_NAME) \
299  Scalar<double> FUNCTION_NAME( \
300  BOOST_PP_REPEAT(DIM, EQUATION_OF_STATE_ARGUMENTS_EXPAND, double)) \
301  const noexcept override; \
302  Scalar<DataVector> FUNCTION_NAME( \
303  BOOST_PP_REPEAT(DIM, EQUATION_OF_STATE_ARGUMENTS_EXPAND, DataVector)) \
304  const noexcept override;
305 
306 /// \endcond
307 
308 /*!
309  * \ingroup EquationsOfStateGroup
310  * \brief Macro used to generate forward declarations of member functions in
311  * derived classes
312  */
313 #define EQUATION_OF_STATE_FORWARD_DECLARE_MEMBERS(DERIVED, DIM) \
314  BOOST_PP_LIST_FOR_EACH( \
315  EQUATION_OF_STATE_FORWARD_DECLARE_MEMBERS_HELPER, DIM, \
316  BOOST_PP_TUPLE_TO_LIST(BOOST_PP_TUPLE_ELEM( \
317  BOOST_PP_SUB(DIM, 1), \
318  (EQUATION_OF_STATE_FUNCTIONS_1D, EQUATION_OF_STATE_FUNCTIONS_2D)))) \
319  \
320  /* clang-tidy: do not use non-const references */ \
321  void pup(PUP::er& p) noexcept override; /* NOLINT */ \
322  \
323  explicit DERIVED(CkMigrateMessage* /*unused*/) noexcept;
324 
325 /// \cond
326 #define EQUATION_OF_STATE_FORWARD_ARGUMENTS(z, n, unused) \
327  BOOST_PP_COMMA_IF(n) arg##n
328 
329 #define EQUATION_OF_STATE_ARGUMENTS_EXPAND_NAMED(z, n, type) \
330  BOOST_PP_COMMA_IF(n) const Scalar<type>& arg##n
331 
332 #define EQUATION_OF_STATE_MEMBER_DEFINITIONS_HELPER( \
333  TEMPLATE, DERIVED, DATA_TYPE, DIM, FUNCTION_NAME) \
334  TEMPLATE \
335  Scalar<DATA_TYPE> DERIVED::FUNCTION_NAME(BOOST_PP_REPEAT( \
336  DIM, EQUATION_OF_STATE_ARGUMENTS_EXPAND_NAMED, DATA_TYPE)) \
337  const noexcept { \
338  return FUNCTION_NAME##_impl( \
339  BOOST_PP_REPEAT(DIM, EQUATION_OF_STATE_FORWARD_ARGUMENTS, UNUSED)); \
340  }
341 
342 #define EQUATION_OF_STATE_MEMBER_DEFINITIONS_HELPER_2(r, ARGS, FUNCTION_NAME) \
343  EQUATION_OF_STATE_MEMBER_DEFINITIONS_HELPER( \
344  BOOST_PP_TUPLE_ELEM(0, ARGS), BOOST_PP_TUPLE_ELEM(1, ARGS), \
345  BOOST_PP_TUPLE_ELEM(2, ARGS), BOOST_PP_TUPLE_ELEM(3, ARGS), \
346  FUNCTION_NAME)
347 /// \endcond
348 
349 #define EQUATION_OF_STATE_MEMBER_DEFINITIONS(TEMPLATE, DERIVED, DATA_TYPE, \
350  DIM) \
351  BOOST_PP_LIST_FOR_EACH( \
352  EQUATION_OF_STATE_MEMBER_DEFINITIONS_HELPER_2, \
353  (TEMPLATE, DERIVED, DATA_TYPE, DIM), \
354  BOOST_PP_TUPLE_TO_LIST(BOOST_PP_TUPLE_ELEM( \
355  BOOST_PP_SUB(DIM, 1), \
356  (EQUATION_OF_STATE_FUNCTIONS_1D, EQUATION_OF_STATE_FUNCTIONS_2D))))
357 
358 /// \cond
359 #define EQUATION_OF_STATE_FORWARD_DECLARE_MEMBER_IMPLS_HELPER(r, DIM, \
360  FUNCTION_NAME) \
361  template <class DataType> \
362  Scalar<DataType> FUNCTION_NAME##_impl(BOOST_PP_REPEAT( \
363  DIM, EQUATION_OF_STATE_ARGUMENTS_EXPAND, DataType)) const noexcept;
364 /// \endcond
365 
366 #define EQUATION_OF_STATE_FORWARD_DECLARE_MEMBER_IMPLS(DIM) \
367  BOOST_PP_LIST_FOR_EACH( \
368  EQUATION_OF_STATE_FORWARD_DECLARE_MEMBER_IMPLS_HELPER, DIM, \
369  BOOST_PP_TUPLE_TO_LIST(BOOST_PP_TUPLE_ELEM( \
370  BOOST_PP_SUB(DIM, 1), \
371  (EQUATION_OF_STATE_FUNCTIONS_1D, EQUATION_OF_STATE_FUNCTIONS_2D))))
372 
373 #include "PointwiseFunctions/Hydro/EquationsOfState/DarkEnergyFluid.hpp"
374 #include "PointwiseFunctions/Hydro/EquationsOfState/IdealFluid.hpp"
375 #include "PointwiseFunctions/Hydro/EquationsOfState/PolytropicFluid.hpp"
Base class for equations of state depending on whether or not the system is relativistic, and the number of independent thermodynamic variables (ThermodynamicDim) needed to determine the pressure.
Definition: EquationOfState.hpp:63
Contains all equations of state, including base class.
Definition: DarkEnergyFluid.hpp:26
Defines macros to allow serialization of abstract template base classes.
Definition: Determinant.hpp:11
Defines a list of useful type aliases for tensors.
#define WRAPPED_PUPable_abstract(className)
Wraps the Charm++ macro, see the Charm++ documentation.
Definition: CharmPupable.hpp:39
Stores a collection of function values.
Definition: DataVector.hpp:46
Wraps the template metaprogramming library used (brigand)
Defines type traits, some of which are future STL type_traits header.
Tensor< T, Symmetry<>, index_list<> > Scalar
Scalar type.
Definition: TypeAliases.hpp:21