Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <string>
8 :
9 : #include "DataStructures/DataBox/Tag.hpp"
10 : #include "DataStructures/Tensor/IndexType.hpp"
11 : #include "DataStructures/Tensor/TypeAliases.hpp"
12 : #include "Evolution/TypeTraits.hpp"
13 : #include "Options/Auto.hpp"
14 : #include "Options/String.hpp"
15 : #include "PointwiseFunctions/Hydro/EquationsOfState/EquationOfState.hpp"
16 : #include "PointwiseFunctions/Hydro/EquationsOfState/Factory.hpp"
17 : #include "PointwiseFunctions/Hydro/EquationsOfState/PolytropicFluid.hpp"
18 : #include "PointwiseFunctions/Hydro/TagsDeclarations.hpp"
19 : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
20 : #include "PointwiseFunctions/InitialDataUtilities/Tags/InitialData.hpp"
21 : #include "Utilities/ErrorHandling/Error.hpp"
22 : /// \ingroup EvolutionSystemsGroup
23 : /// \brief Items related to hydrodynamic systems.
24 : namespace hydro {
25 :
26 : /// %Tags for options of hydrodynamic systems.
27 1 : namespace OptionTags {
28 : /// The equation of state of the fluid.
29 : template <bool IsRelativistic, size_t ThermoDim>
30 1 : struct InitialDataEquationOfState {
31 0 : using type = std::unique_ptr<
32 : EquationsOfState::EquationOfState<IsRelativistic, ThermoDim>>;
33 0 : static std::string name() { return "EquationOfState"; }
34 0 : static constexpr Options::String help = {
35 : "Options for the equation of state used for the initial data."};
36 : };
37 :
38 : /// The equation of state of the fluid.
39 : template <bool IsRelativistic, size_t ThermoDim>
40 1 : struct EquationOfState {
41 0 : struct FromInitialData {};
42 0 : using type = Options::Auto<std::unique_ptr<EquationsOfState::EquationOfState<
43 : IsRelativistic, ThermoDim>>,
44 : FromInitialData>;
45 :
46 0 : static constexpr Options::String help = {
47 : "The equation of state to use during the evolution."};
48 : };
49 :
50 0 : struct GrmhdEquationOfState {
51 0 : struct FromInitialData {};
52 0 : using type =
53 : Options::Auto<std::unique_ptr<EquationsOfState::EquationOfState<true, 3>>,
54 : FromInitialData>;
55 0 : static std::string name() { return "EquationOfState"; }
56 0 : static constexpr Options::String help = {
57 : "Options for the equation of state used for relativistic"
58 : "hydro simulations using GRMHD executables."};
59 : };
60 : } // namespace OptionTags
61 :
62 : /// %Tags for hydrodynamic systems.
63 : namespace Tags {
64 :
65 : /// The Alfvén speed squared \f$v_A^2\f$.
66 : template <typename DataType>
67 1 : struct AlfvenSpeedSquared : db::SimpleTag {
68 0 : using type = Scalar<DataType>;
69 : };
70 :
71 : /// The magnetic field \f$b^\mu = u_\nu {}^\star\!F^{\mu \nu}\f$
72 : /// measured by an observer comoving with the fluid with 4-velocity
73 : /// \f$u_\nu\f$ where \f${}^\star\!F^{\mu \nu}\f$
74 : /// is the dual of the Faraday tensor. Note that \f$b^\mu\f$ has a
75 : /// time component (that is, \f$b^\mu n_\mu \neq 0\f$, where \f$n_\mu\f$ is
76 : /// the normal to the spacelike hypersurface).
77 : template <typename DataType, size_t Dim, typename Fr>
78 1 : struct ComovingMagneticField : db::SimpleTag {
79 0 : using type = tnsr::A<DataType, Dim, Fr>;
80 0 : static std::string name() {
81 : return Frame::prefix<Fr>() + "ComovingMagneticField";
82 : }
83 : };
84 :
85 : /// The square of the comoving magnetic field, \f$b^\mu b_\mu\f$
86 : template <typename DataType>
87 1 : struct ComovingMagneticFieldSquared : db::SimpleTag {
88 0 : using type = Scalar<DataType>;
89 : };
90 :
91 : /// The magnitude of the comoving magnetic field, \f$\sqrt{b^\mu b_\mu}\f$
92 : template <typename DataType>
93 1 : struct ComovingMagneticFieldMagnitude : db::SimpleTag {
94 0 : using type = Scalar<DataType>;
95 : };
96 :
97 : /// The divergence-cleaning field \f$\Phi\f$.
98 : template <typename DataType>
99 1 : struct DivergenceCleaningField : db::SimpleTag {
100 0 : using type = Scalar<DataType>;
101 : };
102 :
103 : /// The electron fraction \f$Y_e\f$.
104 : template <typename DataType>
105 1 : struct ElectronFraction : db::SimpleTag {
106 0 : using type = Scalar<DataType>;
107 : };
108 :
109 : /// The equation of state retrieved from the analytic solution / data in the
110 : /// input file
111 : template <bool IsRelativistic, size_t ThermodynamicDim>
112 1 : struct EquationOfState : db::SimpleTag {
113 0 : using type = std::unique_ptr<
114 : EquationsOfState::EquationOfState<IsRelativistic, ThermodynamicDim>>;
115 :
116 : template <typename Metavariables>
117 0 : using option_tags =
118 : tmpl::list<OptionTags::EquationOfState<IsRelativistic, ThermodynamicDim>,
119 : ::evolution::initial_data::OptionTags::InitialData>;
120 0 : static constexpr bool pass_metavariables = true;
121 :
122 : template <typename Metavariables>
123 0 : static type create_from_options(
124 : const std::optional<type>& eos,
125 : const std::unique_ptr<::evolution::initial_data::InitialData>&
126 : initial_data) {
127 : if (eos.has_value()) {
128 : return eos.value()->get_clone();
129 : } else {
130 : return call_with_dynamic_type<
131 : type,
132 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
133 : ::evolution::initial_data::InitialData>>(
134 : initial_data.get(), [](const auto* const derived_initial_data) {
135 : if constexpr (::evolution::is_numeric_initial_data_v<
136 : std::decay_t<decltype(*derived_initial_data)>>) {
137 : ERROR(
138 : "Equation of State cannot currently be parsed from numeric"
139 : "initial data, please explicitly specify the equation of "
140 : "state for the evolution in the input file.");
141 : if constexpr (ThermodynamicDim == 1) {
142 : return std::make_unique<
143 : EquationsOfState::PolytropicFluid<IsRelativistic>>(100.0,
144 : 2.0);
145 : } else if constexpr (ThermodynamicDim == 2) {
146 : return std::make_unique<
147 : EquationsOfState::IdealFluid<IsRelativistic>>(2.0);
148 : } else if constexpr (ThermodynamicDim == 3) {
149 : return std::make_unique<EquationsOfState::Barotropic3D<
150 : EquationsOfState::PolytropicFluid<IsRelativistic>>>(
151 : EquationsOfState::PolytropicFluid<IsRelativistic>(100.0,
152 : 2.0));
153 : }
154 : } else {
155 : if constexpr (ThermodynamicDim == 3) {
156 : return derived_initial_data->equation_of_state()
157 : .promote_to_3d_eos();
158 : } else if constexpr (ThermodynamicDim == 2) {
159 : return derived_initial_data->equation_of_state()
160 : .promote_to_2d_eos();
161 : } else {
162 : return derived_initial_data->equation_of_state().get_clone();
163 : }
164 : }
165 : });
166 : }
167 : }
168 : };
169 :
170 : /// The inverse plasma beta \f$\beta^{-1} = b^2 / (2 p)\f$, where
171 : ///// \f$b^2\f$ is the square of the comoving magnetic field amplitude
172 : ///// and \f$p\f$ is the fluid pressure.
173 : template <typename DataType>
174 1 : struct InversePlasmaBeta : db::SimpleTag {
175 0 : using type = Scalar<DataType>;
176 : };
177 :
178 : /// The Lorentz factor \f$W = (1-v^iv_i)^{-1/2}\f$, where \f$v^i\f$ is
179 : /// the spatial velocity of the fluid.
180 : template <typename DataType>
181 1 : struct LorentzFactor : db::SimpleTag {
182 0 : using type = Scalar<DataType>;
183 : };
184 :
185 : /// The square of the Lorentz factor \f$W^2\f$.
186 : template <typename DataType>
187 1 : struct LorentzFactorSquared : db::SimpleTag {
188 0 : using type = Scalar<DataType>;
189 : };
190 :
191 : /// The magnetic field \f$B^i = n_\mu {}^\star\!F^{i \mu}\f$ measured by an
192 : /// Eulerian observer, where \f$n_\mu\f$ is the normal to the spatial
193 : /// hypersurface and \f${}^\star\!F^{\mu \nu}\f$ is the dual of the
194 : /// Faraday tensor. Note that \f$B^i\f$ is purely spatial, and it
195 : /// can be lowered using the spatial metric.
196 : template <typename DataType, size_t Dim, typename Fr>
197 1 : struct MagneticField : db::SimpleTag {
198 0 : using type = tnsr::I<DataType, Dim, Fr>;
199 0 : static std::string name() { return Frame::prefix<Fr>() + "MagneticField"; }
200 : };
201 :
202 : /// The magnetic field dotted into the spatial velocity, \f$B^iv_i\f$ where
203 : /// \f$v_i\f$ is the spatial velocity one-form.
204 : template <typename DataType>
205 1 : struct MagneticFieldDotSpatialVelocity : db::SimpleTag {
206 0 : using type = Scalar<DataType>;
207 : };
208 :
209 : /// The one-form of the magnetic field. Note that \f$B^i\f$ is raised
210 : /// and lowered with the spatial metric.
211 : /// \see hydro::Tags::MagneticField
212 : template <typename DataType, size_t Dim, typename Fr>
213 1 : struct MagneticFieldOneForm : db::SimpleTag {
214 0 : using type = tnsr::i<DataType, Dim, Fr>;
215 0 : static std::string name() {
216 : return Frame::prefix<Fr>() + "MagneticFieldOneForm";
217 : }
218 : };
219 :
220 : /// The square of the magnetic field, \f$B^iB_i\f$
221 : template <typename DataType>
222 1 : struct MagneticFieldSquared : db::SimpleTag {
223 0 : using type = Scalar<DataType>;
224 : };
225 :
226 : /// The magnetic pressure \f$p_m\f$.
227 : template <typename DataType>
228 1 : struct MagneticPressure : db::SimpleTag {
229 0 : using type = Scalar<DataType>;
230 : };
231 :
232 : /// The fluid pressure \f$p\f$.
233 : template <typename DataType>
234 1 : struct Pressure : db::SimpleTag {
235 0 : using type = Scalar<DataType>;
236 : };
237 :
238 : /// The rest-mass density \f$\rho\f$.
239 : template <typename DataType>
240 1 : struct RestMassDensity : db::SimpleTag {
241 0 : using type = Scalar<DataType>;
242 : };
243 :
244 : /// The sound speed squared \f$c_s^2\f$.
245 : template <typename DataType>
246 1 : struct SoundSpeedSquared : db::SimpleTag {
247 0 : using type = Scalar<DataType>;
248 : };
249 :
250 : /// The spatial velocity \f$v^i\f$ of the fluid,
251 : /// where \f$v^i=u^i/W + \beta^i/\alpha\f$.
252 : /// Here \f$u^i\f$ is the spatial part of the 4-velocity of the fluid,
253 : /// \f$W\f$ is the Lorentz factor, \f$\beta^i\f$ is the shift vector,
254 : /// and \f$\alpha\f$ is the lapse function. Note that \f$v^i\f$ is raised
255 : /// and lowered with the spatial metric.
256 : template <typename DataType, size_t Dim, typename Fr>
257 1 : struct SpatialVelocity : db::SimpleTag {
258 0 : using type = tnsr::I<DataType, Dim, Fr>;
259 0 : static std::string name() { return Frame::prefix<Fr>() + "SpatialVelocity"; }
260 : };
261 :
262 : /// The spatial velocity one-form \f$v_i\f$, where \f$v_i\f$ is raised
263 : /// and lowered with the spatial metric.
264 : template <typename DataType, size_t Dim, typename Fr>
265 1 : struct SpatialVelocityOneForm : db::SimpleTag {
266 0 : using type = tnsr::i<DataType, Dim, Fr>;
267 0 : static std::string name() {
268 : return Frame::prefix<Fr>() + "SpatialVelocityOneForm";
269 : }
270 : };
271 :
272 : /// The spatial velocity squared \f$v^2 = v_i v^i\f$.
273 : template <typename DataType>
274 1 : struct SpatialVelocitySquared : db::SimpleTag {
275 0 : using type = Scalar<DataType>;
276 : };
277 :
278 : /// The relativistic specific enthalpy \f$h\f$.
279 : template <typename DataType>
280 1 : struct SpecificEnthalpy : db::SimpleTag {
281 0 : using type = Scalar<DataType>;
282 : };
283 :
284 : /// The specific internal energy \f$\epsilon\f$.
285 : template <typename DataType>
286 1 : struct SpecificInternalEnergy : db::SimpleTag {
287 0 : using type = Scalar<DataType>;
288 : };
289 :
290 : /// The temperature \f$T\f$ of the fluid.
291 : template <typename DataType>
292 1 : struct Temperature : db::SimpleTag {
293 0 : using type = Scalar<DataType>;
294 : };
295 :
296 : /// \brief Tag containing the transport velocity.
297 : ///
298 : /// The transport velocity is defined as \f$v_t^i=\alpha v^i-\beta^i\f$,
299 : /// with $v^i$ being the spatial velocity, $\alpha$ the lapse, and
300 : /// $\beta^i$ the shift.
301 : template <typename DataType, size_t Dim, typename Fr = Frame::Inertial>
302 1 : struct TransportVelocity : db::SimpleTag {
303 0 : using type = tnsr::I<DataType, Dim, Fr>;
304 : };
305 :
306 : /// The spatial components of the four-velocity one-form \f$u_i\f$.
307 : template <typename DataType, size_t Dim, typename Fr>
308 1 : struct LowerSpatialFourVelocity : db::SimpleTag {
309 0 : using type = tnsr::i<DataType, Dim, Fr>;
310 : };
311 :
312 : /// The Lorentz factor \f$W\f$ times the spatial velocity \f$v^i\f$.
313 : template <typename DataType, size_t Dim, typename Fr>
314 1 : struct LorentzFactorTimesSpatialVelocity : db::SimpleTag {
315 0 : using type = tnsr::I<DataType, Dim, Fr>;
316 : };
317 :
318 : /// The vector \f$J^i\f$ in \f$\dot{M} = -\int J^i s_i d^2S\f$,
319 : /// representing the mass flux through a surface with normal \f$s_i\f$.
320 : ///
321 : /// Note that the integral is understood
322 : /// as a flat-space integral: all metric factors are included in \f$J^i\f$.
323 : /// In particular, if the integral is done over a Strahlkorper, the
324 : /// `gr::surfaces::euclidean_area_element` of the Strahlkorper should be used,
325 : /// and \f$s_i\f$ is
326 : /// the normal one-form to the Strahlkorper normalized with the flat metric,
327 : /// \f$s_is_j\delta^{ij}=1\f$.
328 : ///
329 : /// The formula is
330 : /// \f$ J^i = \rho W \sqrt{\gamma}(\alpha v^i-\beta^i)\f$,
331 : /// where \f$\rho\f$ is the mass density, \f$W\f$ is the Lorentz factor,
332 : /// \f$v^i\f$ is the spatial velocity of the fluid,
333 : /// \f$\gamma\f$ is the determinant of the 3-metric \f$\gamma_{ij}\f$,
334 : /// \f$\alpha\f$ is the lapse, and \f$\beta^i\f$ is the shift.
335 : template <typename DataType, size_t Dim, typename Fr>
336 1 : struct MassFlux : db::SimpleTag {
337 0 : using type = tnsr::I<DataType, Dim, Fr>;
338 0 : static std::string name() { return Frame::prefix<Fr>() + "MassFlux"; }
339 : };
340 :
341 : /// The equation of state retrieved from the analytic solution / data in the
342 : /// input file
343 1 : struct GrmhdEquationOfState : db::SimpleTag {
344 0 : using type = std::unique_ptr<EquationsOfState::EquationOfState<true, 3>>;
345 :
346 : template <typename Metavariables>
347 0 : using option_tags =
348 : tmpl::list<OptionTags::GrmhdEquationOfState,
349 : ::evolution::initial_data::OptionTags::InitialData>;
350 0 : static constexpr bool pass_metavariables = true;
351 :
352 : template <typename Metavariables>
353 0 : static type create_from_options(
354 : const std::optional<type>& eos,
355 : const std::unique_ptr<::evolution::initial_data::InitialData>&
356 : initial_data) {
357 : if (eos.has_value()) {
358 : return eos.value()->get_clone();
359 : } else {
360 : return call_with_dynamic_type<
361 : type,
362 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
363 : ::evolution::initial_data::InitialData>>(
364 : initial_data.get(), [](const auto* const derived_initial_data) {
365 : if constexpr (::evolution::is_numeric_initial_data_v<
366 : std::decay_t<decltype(*derived_initial_data)>>) {
367 : ERROR(
368 : "Equation of State cannot currently be parsed from numeric"
369 : "initial data, please explicitly specify the equation of "
370 : "state for the evolution in the input file.");
371 : return std::make_unique<EquationsOfState::Barotropic3D<
372 : EquationsOfState::PolytropicFluid<true>>>(
373 : EquationsOfState::PolytropicFluid<true>(100.0, 2.0));
374 : } else {
375 : return (derived_initial_data->equation_of_state()
376 : .promote_to_3d_eos());
377 : }
378 : });
379 : }
380 : }
381 : };
382 : } // namespace Tags
383 :
384 : } // namespace hydro
|