Theseus
Compressible flow solver
Loading...
Searching...
No Matches
EOS.hpp
Go to the documentation of this file.
1// Copyright (c) 2025-2026 Board of Trustees of the University of Illinois
2//
3// This file is part of Theseus.
4//
5// SPDX-License-Identifier: BSD-3-Clause
6#pragma once
7
8#include <cmath>
9#include "Physics.hpp"
10#include "GasState.hpp"
11
12namespace Theseus
13{
14
15 // ============================================================================
16 // EOS: Ideal single-species gas using PhysicsConstants
17 // ============================================================================
19 {
20 // ---- helpers on conservative state --------------------------------------
21 template<typename StateView>
22 MFEM_HOST_DEVICE
23 inline mfem::real_t R_gas(const PhysicsConstants &phys, const StateLayout &L,
24 const StateView &S) const
25 {
26 return phys.R_gas;
27 }
28
29 template<typename StateView>
30 MFEM_HOST_DEVICE
31 inline mfem::real_t density(const PhysicsConstants &phys, const StateLayout &L,
32 const StateView &S) const
33 {
34 return S.mass(L); // this is "rho" (mass density)
35 }
36
37 template<typename StateView>
38 MFEM_HOST_DEVICE
39 inline mfem::real_t rhoE(const PhysicsConstants &phys, const StateLayout &L,
40 const StateView &S) const
41 {
42 return S.energy(L);
43 }
44
45 template<typename StateView>
46 MFEM_HOST_DEVICE
47 inline mfem::real_t momentum_sq(const PhysicsConstants &phys, const StateLayout &L,
48 const StateView &S) const
49 {
50 const int dim = L.dim; // uses state layout
51 mfem::real_t m2 = 0;
52 for (int d = 0; d < dim; ++d)
53 {
54 const mfem::real_t m = S.momentum(L,d);
55 m2 += m * m;
56 }
57 return m2;
58 }
59
60 template<typename StateView>
61 MFEM_HOST_DEVICE
62 inline mfem::real_t kinetic_energy_density(const PhysicsConstants &phys, const StateLayout &L,
63 const StateView &S) const
64 {
65 // 0.5 * rho * |u|^2 = 0.5 * |rho*u|^2 / rho
66 const mfem::real_t rho = density(phys, L, S);
67 const mfem::real_t m2 = momentum_sq(phys, L, S);
68 return 0.5 * m2 / rho;
69 }
70
71 template<typename StateView>
72 MFEM_HOST_DEVICE
73 inline mfem::real_t internal_energy_density(const PhysicsConstants &phys, const StateLayout &L,
74 const StateView &S) const
75 {
76 // rho*e = rho*E - 0.5*rho*|u|^2
77 return rhoE(phys, L, S) - kinetic_energy_density(phys, L, S);
78 }
79
80 template<typename StateView>
81 MFEM_HOST_DEVICE
82 inline mfem::real_t internal_energy_from_pressure(const PhysicsConstants &phys, const StateLayout &L,
83 const StateView &S, mfem::real_t pressure) const
84 {
85 // rho*e = rho*E - 0.5*rho*|u|^2
86 return pressure / (phys.gamma - 1.0);
87 }
88
89 template<typename StateView>
90 MFEM_HOST_DEVICE
91 inline mfem::real_t specific_internal_energy(const PhysicsConstants &phys, const StateLayout &L,
92 const StateView &S) const
93 {
94 // e = (rho*e) / rho
95 const mfem::real_t rho = density(phys, L, S);
96 const mfem::real_t rhoe = internal_energy_density(phys, L, S);
97 return rhoe / rho;
98 }
99
100 // ---- primary EOS interface ----------------------------------------------
101
102 template<typename StateView>
103 MFEM_HOST_DEVICE
104 inline mfem::real_t pressure(const PhysicsConstants &phys, const StateLayout &L,
105 const StateView &S) const
106 {
107 // p = (gamma - 1) * (rho*E - 0.5*|rho*u|^2 / rho)
108 const mfem::real_t rhoe = internal_energy_density(phys, L, S);
109 return phys.gammaM1 * rhoe;
110 }
111
112 template<typename StateView>
113 MFEM_HOST_DEVICE
114 inline mfem::real_t gamma(const PhysicsConstants &phys, const StateLayout &L,
115 const StateView &S) const
116 {
117 return phys.gamma;
118 }
119
120 template<typename StateView>
121 MFEM_HOST_DEVICE
122 inline mfem::real_t temperature(const PhysicsConstants &phys, const StateLayout &L,
123 const StateView &S) const
124 {
125 // p = rho*R*T => T = p / (rho*R)
126 const mfem::real_t rho = density(phys, L, S);
127 const mfem::real_t p = pressure(phys, L, S);
128 return p / (rho * phys.R_gas);
129 }
130
131 template<typename StateView>
132 MFEM_HOST_DEVICE
133 inline void grad_temperature(const PhysicsConstants &phys, const StateLayout &L,
134 const StateView &S, const mfem::real_t *grad_rho,
135 const mfem::real_t *grad_p, mfem::real_t *grad_t) const
136 {
137 const int dim = L.dim;
138 const mfem::real_t rho = density(phys, L, S);
139 const mfem::real_t pressor = pressure(phys, L, S)/rho;
140 const mfem::real_t cv = cp(phys, L, S)/phys.gamma;
141 const mfem::real_t fac = phys.gammaM1Inverse/(cv*rho);
142 for(int i = 0; i < dim; i++){
143 grad_t[i] = fac*(grad_p[i] - pressor*grad_rho[i]);
144 }
145 }
146
147 template<typename StateView>
148 MFEM_HOST_DEVICE
149 inline mfem::real_t sound_speed(const PhysicsConstants &phys, const StateLayout &L,
150 const StateView &S) const
151 {
152 // a^2 = gamma * p / rho
153 const mfem::real_t rho = density(phys, L, S);
154 const mfem::real_t p = pressure(phys, L, S);
155 return std::sqrt(phys.gamma * p / rho);
156 }
157
158 // cp is constant for ideal gas
159 template<typename StateView>
160 MFEM_HOST_DEVICE
161 inline mfem::real_t cp(const PhysicsConstants &phys, const StateLayout &L,
162 const StateView & /*S*/) const
163 {
164 return phys.cp;
165 }
166
167 template<typename StateView>
168 MFEM_HOST_DEVICE
169 inline mfem::real_t entropy(const PhysicsConstants &phys, const StateLayout &L,
170 const StateView &S) const
171 {
172 const mfem::real_t p = pressure(phys, L, S);
173 const mfem::real_t gamma = phys.gamma;
174 // TODO: Augment for correct treatment of passive scalars
175 return std::log(p) - gamma * std::log(S.mass(L));
176 }
177
178 template<typename InStateView, typename OutStateView>
179 MFEM_HOST_DEVICE
180 inline void entropy_state(const PhysicsConstants &phys, const StateLayout &L,
181 const InStateView &S, OutStateView &E) const
182 {
183 const mfem::real_t p = pressure(phys, L, S);
184 const mfem::real_t gamma = phys.gamma;
185 const mfem::real_t rho = S.mass(L);
186 const mfem::real_t s = std::log(p) - gamma*std::log(rho);
187 const mfem::real_t beta = rho / p;
188 const mfem::real_t v2o2 = kinetic_energy_density(phys, L, S) / rho;
189 const mfem::real_t s_rho = (gamma - s)/(gamma - 1) - beta*v2o2;
190
191 E.set_mass(L, s_rho);
192 int dim = L.dim;
193 int num_scalars = L.num_scalars;
194 for(int idim = 0;idim < dim;idim++){
195 E.set_momentum(L, idim, beta * S.velocity(L, idim));
196 }
197 E.set_energy(L, -beta);
198 // TODO: Update for correct treatment of passive scalars (depends on ES approach)
199 // - Here we should probably set the entropy state to scalar_state / density
200 // - If we do that, we need to modify the mass component of the entropy state
201 // - Making this fix will make the sensor function sensitive to the scalars
202 // - If we need to recover CV from this, lax scalar treatment is a nogo
203 for(int iscalar = 0;iscalar < num_scalars;iscalar++){
204 E.set_scalar(L, iscalar, 0.0);
205 }
206 }
207
208 template<typename InStateView, typename OutStateView>
209 MFEM_HOST_DEVICE
210 inline void grad_entropy_to_grad_prim(const PhysicsConstants &phys, const StateLayout &L,
211 const InStateView &S, const InStateView &dE,
212 OutStateView &dPrim) const
213 {
214
215 const mfem::real_t ke = kinetic_energy_density(phys, L, S);
216 const mfem::real_t p = pressure(phys, L, S);
217 const mfem::real_t rho = S.mass(L);
218 const mfem::real_t rhoE = S.energy(L);
219 const mfem::real_t ie = internal_energy_density(phys, L, S);
220
221 int dim = L.dim;
222 int num_scalars = L.num_scalars;
223
224 mfem::real_t drho = 0.0;
225 for(int idim = 0; idim < dim; idim++){
226 dPrim.set_momentum(L, idim, p/rho * (dE.momentum(L, idim) + S.velocity(L, idim)*dE.energy(L)));
227 drho += S.momentum(L, idim)*dPrim.momentum(L, idim);
228 }
229 drho = rho*dE.mass(L) - dE.energy(L)*(ke - ie) + rho*drho/p;
230 dPrim.set_mass(L, drho);
231 dPrim.set_energy(L, p/rho * (dPrim.mass(L) + p*dE.energy(L)));
232 for(int isp = 0; isp < num_scalars; isp++){
233 dPrim.set_scalar(L, isp, 0.0); // just a placeholder for now
234 }
235 }
236
237 template<typename InStateView, typename OutStateView>
238 MFEM_HOST_DEVICE
239 inline void entropy_to_conserved(const PhysicsConstants &phys, const StateLayout &L,
240 const InStateView &Se, OutStateView &Sc) const
241 {
242 int dim = L.dim;
243 const mfem::real_t beta = -Se.energy(L);
244 mfem::real_t k = 0.0;
245 mfem::real_t vel[3];
246 for(int idim = 0;idim < dim;idim++){
247 vel[idim] = Se.momentum(L, idim)/beta;
248 k += vel[idim]*vel[idim];
249 }
250 const mfem::real_t gamma = phys.gamma;
251 const mfem::real_t s = gamma - (Se.mass(L) + 0.5*k*beta)*(gamma - 1.);
252 const mfem::real_t rho = std::pow(std::exp(-s)/beta, 1.0/(gamma - 1));
253 Sc.set_mass(L, rho);
254 Sc.set_energy(L, rho*(1.0/(beta*(gamma-1.)) + 0.5*k));
255 for(int idim = 0;idim < dim;idim++){
256 Sc.set_momentum(L, idim, rho*vel[idim]);
257 }
258 }
259
260 template<typename InStateView, typename OutStateView>
261 inline void primitive_to_conserved(const PhysicsConstants &phys, const StateLayout &L,
262 const InStateView &prim, OutStateView &cons) const
263 {
264 const mfem::real_t rho = prim.mass(L);
265 const int dim = L.dim;
266 mfem::real_t v2 = 0.0;
267
268 cons.set_mass(L, rho);
269 for(int d = 0; d < dim; d++)
270 {
271 cons.set_momentum(L, d, rho*prim.velocity(L, d));
272 v2 += prim.velocity(L,d)*prim.velocity(L,d);
273 }
274 mfem::real_t rhoe = prim.pressure(L) / (phys.gamma-1.);
275 cons.set_energy(L, rhoe + 0.5 * rho * v2);
276 }
277
278 // TODO: Consider whether this is needed/convenient
279 // It *can be* nice to have here, but kind of out-of-place
280 template<typename StateView>
281 MFEM_HOST_DEVICE
282 inline void velocity(const PhysicsConstants &phys, const StateLayout &L,
283 const StateView &S, mfem::real_t u[3]) const
284 {
285 const int dim = L.dim;
286 for (int d = 0; d < dim; ++d)
287 {
288 u[d] = S.velocity(L, d);
289 }
290 for (int d = dim; d < 3; ++d)
291 {
292 u[d] = mfem::real_t(0);
293 }
294 }
295 };
296}
Definition AxisymmetricGeometry.hpp:15
Definition EOS.hpp:19
MFEM_HOST_DEVICE void entropy_to_conserved(const PhysicsConstants &phys, const StateLayout &L, const InStateView &Se, OutStateView &Sc) const
Definition EOS.hpp:239
MFEM_HOST_DEVICE mfem::real_t internal_energy_density(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:73
MFEM_HOST_DEVICE void grad_entropy_to_grad_prim(const PhysicsConstants &phys, const StateLayout &L, const InStateView &S, const InStateView &dE, OutStateView &dPrim) const
Definition EOS.hpp:210
MFEM_HOST_DEVICE mfem::real_t kinetic_energy_density(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:62
MFEM_HOST_DEVICE void entropy_state(const PhysicsConstants &phys, const StateLayout &L, const InStateView &S, OutStateView &E) const
Definition EOS.hpp:180
MFEM_HOST_DEVICE mfem::real_t gamma(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:114
MFEM_HOST_DEVICE void velocity(const PhysicsConstants &phys, const StateLayout &L, const StateView &S, mfem::real_t u[3]) const
Definition EOS.hpp:282
MFEM_HOST_DEVICE mfem::real_t specific_internal_energy(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:91
MFEM_HOST_DEVICE mfem::real_t temperature(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:122
MFEM_HOST_DEVICE mfem::real_t density(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:31
MFEM_HOST_DEVICE mfem::real_t sound_speed(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:149
void primitive_to_conserved(const PhysicsConstants &phys, const StateLayout &L, const InStateView &prim, OutStateView &cons) const
Definition EOS.hpp:261
MFEM_HOST_DEVICE mfem::real_t pressure(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:104
MFEM_HOST_DEVICE mfem::real_t internal_energy_from_pressure(const PhysicsConstants &phys, const StateLayout &L, const StateView &S, mfem::real_t pressure) const
Definition EOS.hpp:82
MFEM_HOST_DEVICE mfem::real_t cp(const PhysicsConstants &phys, const StateLayout &L, const StateView &) const
Definition EOS.hpp:161
MFEM_HOST_DEVICE mfem::real_t entropy(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:169
MFEM_HOST_DEVICE mfem::real_t R_gas(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:23
MFEM_HOST_DEVICE mfem::real_t rhoE(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:39
MFEM_HOST_DEVICE void grad_temperature(const PhysicsConstants &phys, const StateLayout &L, const StateView &S, const mfem::real_t *grad_rho, const mfem::real_t *grad_p, mfem::real_t *grad_t) const
Definition EOS.hpp:133
MFEM_HOST_DEVICE mfem::real_t momentum_sq(const PhysicsConstants &phys, const StateLayout &L, const StateView &S) const
Definition EOS.hpp:47
Definition Physics.hpp:14
mfem::real_t gammaM1
Definition Physics.hpp:18
mfem::real_t R_gas
Definition Physics.hpp:26
mfem::real_t cp
Definition Physics.hpp:27
mfem::real_t gammaM1Inverse
Definition Physics.hpp:20
mfem::real_t gamma
Definition Physics.hpp:15
Definition GasState.hpp:37
int num_scalars
Definition GasState.hpp:49
int dim
Definition GasState.hpp:38