SPH
Eos.cpp
Go to the documentation of this file.
1 #include "physics/Eos.h"
2 #include "math/Functional.h"
3 #include "physics/Constants.h"
4 #include "system/Settings.h"
5 
7 
8 //-----------------------------------------------------------------------------------------------------------
9 // IdealGasEos implementation
10 //-----------------------------------------------------------------------------------------------------------
11 
13  : gamma(gamma) {}
14 
15 Pair<Float> IdealGasEos::evaluate(const Float rho, const Float u) const {
16  const Float p = (gamma - 1._f) * u * rho;
17  return { p, sqrt(gamma * p / rho) };
18 }
19 
20 Float IdealGasEos::getInternalEnergy(const Float rho, const Float p) const {
21  return p / ((gamma - 1._f) * rho);
22 }
23 
24 Float IdealGasEos::getDensity(const Float p, const Float u) const {
25  return p / ((gamma - 1._f) * u);
26 }
27 
29  return u / Constants::gasConstant;
30 }
31 
32 Float IdealGasEos::getSpecificEntropy(const Float rho, const Float p) const {
33  return p / pow(rho, gamma);
34 }
35 
36 //-----------------------------------------------------------------------------------------------------------
37 // TaitEos implementation
38 //-----------------------------------------------------------------------------------------------------------
39 
40 TaitEos::TaitEos(const BodySettings& settings) {
42  rho0 = settings.get<Float>(BodySettingsId::DENSITY);
43  gamma = settings.get<Float>(BodySettingsId::TAIT_GAMMA);
44 }
45 
46 Pair<Float> TaitEos::evaluate(const Float rho, const Float UNUSED(u)) const {
47  const Float p = sqr(c0) * rho0 / gamma * (pow(rho / rho0, gamma) - 1._f);
48  return { p, c0 };
49 }
50 
51 //-----------------------------------------------------------------------------------------------------------
52 // MieGruneisenEos implementation
53 //-----------------------------------------------------------------------------------------------------------
54 
57  rho0 = settings.get<Float>(BodySettingsId::DENSITY);
58  Gamma = settings.get<Float>(BodySettingsId::GRUNEISEN_GAMMA);
60 }
61 
62 Pair<Float> MieGruneisenEos::evaluate(const Float rho, const Float u) const {
63  const Float chi = 1._f - rho0 / rho;
64  SPH_ASSERT(isReal(chi));
65  const Float num = rho0 * sqr(c0) * chi * (1._f - 0.5_f * Gamma * chi);
66  const Float denom = sqr(1._f - s * chi);
67  SPH_ASSERT(denom != 0._f);
68  return { num / denom + Gamma * u * rho, c0 };
69 }
70 
71 //-----------------------------------------------------------------------------------------------------------
72 // TillotsonEos implementation
73 //-----------------------------------------------------------------------------------------------------------
74 
76  : u0(settings.get<Float>(BodySettingsId::TILLOTSON_SUBLIMATION))
77  , uiv(settings.get<Float>(BodySettingsId::TILLOTSON_ENERGY_IV))
78  , ucv(settings.get<Float>(BodySettingsId::TILLOTSON_ENERGY_CV))
79  , a(settings.get<Float>(BodySettingsId::TILLOTSON_SMALL_A))
80  , b(settings.get<Float>(BodySettingsId::TILLOTSON_SMALL_B))
81  , rho0(settings.get<Float>(BodySettingsId::DENSITY))
82  , A(settings.get<Float>(BodySettingsId::BULK_MODULUS))
83  , B(settings.get<Float>(BodySettingsId::TILLOTSON_NONLINEAR_B))
84  , alpha(settings.get<Float>(BodySettingsId::TILLOTSON_ALPHA))
85  , beta(settings.get<Float>(BodySettingsId::TILLOTSON_BETA)) {}
86 
87 Pair<Float> TillotsonEos::evaluate(const Float rho, const Float u) const {
88  const Float eta = rho / rho0;
89  const Float mu = eta - 1._f;
90  const Float denom = u / (u0 * eta * eta) + 1._f;
91  SPH_ASSERT(isReal(denom));
92  SPH_ASSERT(isReal(eta));
93  // compressed phase
94  const Float pc = (a + b / denom) * rho * u + A * mu + B * mu * mu;
95  Float dpdu = a * rho + b * rho / sqr(denom);
96  Float dpdrho = a * u + b * u * (3._f * denom - 2._f) / sqr(denom) + A / rho0 + 2._f * B * mu / rho0;
97  const Float csc = dpdrho + dpdu * pc / (rho * rho);
98  SPH_ASSERT(isReal(csc));
99 
100  // expanded phase
101  const Float rhoExp = rho0 / rho - 1._f;
102  const Float betaExp = exp(-min(beta * rhoExp, 70._f));
103  const Float alphaExp = exp(-min(alpha * sqr(rhoExp), 70._f));
104  const Float pe = a * rho * u + (b * rho * u / denom + A * mu * betaExp) * alphaExp;
105  dpdu = a * rho + alphaExp * b * rho / sqr(denom);
106  dpdrho = a * u + alphaExp * (b * u * (3._f * denom - 2._f) / sqr(denom)) +
107  alphaExp * (b * u * rho / denom) * rho0 * (2._f * alpha * rhoExp) / sqr(rho) +
108  alphaExp * A * betaExp * (1._f / rho0 + rho0 * mu / sqr(rho) * (2._f * alpha * rhoExp + beta));
109  Float cse = dpdrho + dpdu * pe / (rho * rho);
110  SPH_ASSERT(isReal(cse));
111  cse = max(cse, 0._f);
112 
113  // select phase based on internal energy
114  Float p = pc, cs = csc;
115  if (rho <= rho0 && u > ucv) {
116  p = pe;
117  cs = cse;
118  } else if (rho <= rho0 && u > uiv && u <= ucv) {
119  p = ((u - uiv) * pe + (ucv - u) * pc) / (ucv - uiv);
121  cs = ((u - uiv) * cse + (ucv - u) * csc) / (ucv - uiv);
122  }
123  // clamp sound speed to prevent negative values
124  cs = max(cs, 0.25_f * A / rho0);
125 
126  SPH_ASSERT(isReal(p) && isReal(cs) && cs > 0._f);
127  return { p, sqrt(cs) };
128 }
129 
131  // try compressed phase first
132  const Float eta = rho / rho0;
133  const Float mu = eta - 1._f;
134  const Float x = (p - A * mu - B * sqr(mu)) / rho;
135  const Float l = a;
136  const Float m = u0 * sqr(eta) * (a + b) - x;
137  const Float n = -x * u0 * sqr(eta);
138  const Float u = (-m + sqrt(sqr(m) - 4._f * l * n)) / (2._f * l);
139  SPH_ASSERT(isReal(u));
140 
141  if (rho <= rho0 && u > uiv) {
142  // this is actually in expanded regime, find root
143  auto func = [this, rho, p0 = p](const Float u) {
144  Float p, cs;
145  tie(p, cs) = this->evaluate(rho, u);
146  return p0 - p;
147  };
149  Optional<Float> root = getRoot(Interval(0._f, u0), EPS, func);
150  SPH_ASSERT(root);
151  // if no root exists, return the compressed u to avoid crashing
152  return root.valueOr(u);
153  } else {
154  return u;
155  }
156 }
157 
158 Float TillotsonEos::getDensity(const Float p, const Float u) const {
159  // both phases are highly non-linear in density, no chance of getting an analytic solution ...
160  // so let's find the root
161  auto func = [this, u, p0 = p](const Float rho) {
162  Float p, cs;
163  tie(p, cs) = this->evaluate(rho, u);
164  return p0 - p;
165  };
166  Optional<Float> root = getRoot(Interval(0.95_f * rho0, 1.05 * rho0), EPS, func);
167  SPH_ASSERT(root);
168  return root.value();
169 }
170 
171 //-----------------------------------------------------------------------------------------------------------
172 // SimplifiedTillotsonEos implementation
173 //-----------------------------------------------------------------------------------------------------------
174 
176  const Float a = settings.get<Float>(BodySettingsId::TILLOTSON_SMALL_A);
177  const Float b = settings.get<Float>(BodySettingsId::TILLOTSON_SMALL_B);
178  c = a + b;
179  rho0 = settings.get<Float>(BodySettingsId::DENSITY);
180  A = settings.get<Float>(BodySettingsId::BULK_MODULUS);
181 }
182 
184  const Float mu = rho / rho0 - 1._f;
185  const Float p = c * rho * u + A * mu;
186  const Float cs = sqrt(A / rho0);
187  return { p, cs };
188 }
189 
190 //-----------------------------------------------------------------------------------------------------------
191 // MurnaghanEos implementation
192 //-----------------------------------------------------------------------------------------------------------
193 
195  : rho0(settings.get<Float>(BodySettingsId::DENSITY))
196  , A(settings.get<Float>(BodySettingsId::BULK_MODULUS)) {}
197 
199  const Float cs = sqrt(A / rho0);
200  const Float p = sqr(cs) * (rho - rho0);
201  return { p, cs };
202 }
203 
204 //-----------------------------------------------------------------------------------------------------------
205 // Aneos implementation
206 //-----------------------------------------------------------------------------------------------------------
207 
208 Aneos::Aneos(const BodySettings& settings) {
209  (void)settings;
210 }
211 
212 Pair<Float> Aneos::evaluate(const Float rho, const Float u) const {
214  return { rho, u };
215 }
216 
INLINE bool isReal(const AntisymmetricTensor &t)
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
Definition: Assert.h:100
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Definitions of physical constaints (in SI units).
Equations of state.
INLINE Optional< Float > getRoot(const Interval &range, const Float eps, const TFunctor &functor)
Returns a root of a R->R function on given range.
Definition: Functional.h:91
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
NAMESPACE_SPH_BEGIN constexpr INLINE T min(const T &f1, const T &f2)
Minimum & Maximum value.
Definition: MathBasic.h:15
INLINE Float root(const Float f)
constexpr Float EPS
Definition: MathUtils.h:30
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
Definition: MathUtils.h:67
INLINE T sqrt(const T f)
Return a squared root of a value.
Definition: MathUtils.h:78
constexpr INLINE Float pow(const Float v)
Power for floats.
INLINE T exp(const T f)
Definition: MathUtils.h:269
#define UNUSED(x)
Definition: Object.h:37
#define NAMESPACE_SPH_END
Definition: Object.h:12
@ DENSITY
Density, always a scalar quantity.
StaticArray< T0 &, sizeof...(TArgs)+1 > tie(T0 &t0, TArgs &... rest)
Creates a static array from a list of l-value references.
Definition: StaticArray.h:281
Aneos(const BodySettings &settings)
Definition: Eos.cpp:208
virtual Pair< Float > evaluate(const Float rho, const Float u) const override
Computes pressure and local sound speed from given density rho and specific internal energy u.
Definition: Eos.cpp:212
Float getTemperature(const Float u) const
Definition: Eos.cpp:28
virtual Float getDensity(const Float p, const Float u) const override
Inverted function; computes density from pressure p and internal energy u.
Definition: Eos.cpp:24
Float getSpecificEntropy(const Float rho, const Float p) const
Definition: Eos.cpp:32
virtual Pair< Float > evaluate(const Float rho, const Float u) const override
Computes pressure and local sound speed from given density rho and specific internal energy u.
Definition: Eos.cpp:15
IdealGasEos(const Float gamma)
Definition: Eos.cpp:12
virtual Float getInternalEnergy(const Float rho, const Float p) const override
Inverted function; computes specific internal energy u from given density rho and pressure p.
Definition: Eos.cpp:20
Object representing a 1D interval of real numbers.
Definition: Interval.h:17
virtual Pair< Float > evaluate(const Float rho, const Float u) const override
Computes pressure and local sound speed from given density rho and specific internal energy u.
Definition: Eos.cpp:62
MieGruneisenEos(const BodySettings &settings)
Definition: Eos.cpp:55
virtual Pair< Float > evaluate(const Float rho, const Float u) const override
Computes pressure and local sound speed from given density rho and specific internal energy u.
Definition: Eos.cpp:198
MurnaghanEos(const BodySettings &settings)
Definition: Eos.cpp:194
TValue get(const TEnum idx, std::enable_if_t<!std::is_enum< std::decay_t< TValue >>::value, int >=0) const
Returns a value of given type from the settings.
Definition: Settings.h:326
virtual Pair< Float > evaluate(const Float rho, const Float u) const override
Computes pressure and local sound speed from given density rho and specific internal energy u.
Definition: Eos.cpp:183
SimplifiedTillotsonEos(const BodySettings &settings)
Definition: Eos.cpp:175
Array with fixed number of allocated elements.
Definition: StaticArray.h:19
virtual Pair< Float > evaluate(const Float rho, const Float u) const override
Computes pressure and local sound speed from given density rho and specific internal energy u.
Definition: Eos.cpp:46
TaitEos(const BodySettings &settings)
Definition: Eos.cpp:40
virtual Float getInternalEnergy(const Float rho, const Float p) const override
Inverted function; computes specific internal energy u from given density rho and pressure p.
Definition: Eos.cpp:130
virtual Float getDensity(const Float p, const Float u) const override
Definition: Eos.cpp:158
virtual Pair< Float > evaluate(const Float rho, const Float u) const override
Computes pressure and local sound speed from given density rho and specific internal energy u.
Definition: Eos.cpp:87
TillotsonEos(const BodySettings &settings)
Definition: Eos.cpp:75
Generic storage and input/output routines of settings.
BodySettingsId
Settings of a single body / gas phase / ...
Definition: Settings.h:1394
@ TILLOTSON_NONLINEAR_B
Coefficient B of the nonlinear compressive term in Tillotson equation.
@ TILLOTSON_ALPHA
Alpha coefficient in expanded phase of Tillotson equation.
@ TILLOTSON_ENERGY_CV
Specific energy of complete vaporization.
@ TILLOTSON_SMALL_B
"Small b" coefficient in Tillotson equation
@ BULK_SOUND_SPEED
Used in Mie-Gruneisen equations of state.
@ TAIT_GAMMA
Exponent of density, representing a compressibility of a fluid. Used in Tait equation of state.
@ TILLOTSON_BETA
Beta coefficient in expanded phase of Tillotson equation.
@ TAIT_SOUND_SPEED
Sound speed used in Tait equation of state.
@ BULK_MODULUS
Bulk modulus of the material.
@ DENSITY
Density at zero pressure.
@ TILLOTSON_ENERGY_IV
Specific energy of incipient vaporization.
@ GRUNEISEN_GAMMA
Gruneisen's gamma paraemter used in Mie-Gruneisen equation of state.
@ TILLOTSON_SMALL_A
"Small a" coefficient in Tillotson equation
@ HUGONIOT_SLOPE
Linear Hugoniot slope coefficient used in Mie-Gruneisen equation of state.
@ TILLOTSON_SUBLIMATION
Specific sublimation energy.
constexpr Float pc
Parsec.
Definition: Constants.h:41
constexpr Float gasConstant
Definition: Constants.h:14