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 : /// Base tag for the equation of state
110 1 : struct EquationOfStateBase : db::BaseTag {};
111 :
112 : /// The equation of state retrieved from the analytic solution / data in the
113 : /// input file
114 : template <bool IsRelativistic, size_t ThermodynamicDim>
115 1 : struct EquationOfState : EquationOfStateBase, db::SimpleTag {
116 0 : using type = std::unique_ptr<
117 : EquationsOfState::EquationOfState<IsRelativistic, ThermodynamicDim>>;
118 :
119 : template <typename Metavariables>
120 0 : using option_tags =
121 : tmpl::list<OptionTags::EquationOfState<IsRelativistic, ThermodynamicDim>,
122 : ::evolution::initial_data::OptionTags::InitialData>;
123 0 : static constexpr bool pass_metavariables = true;
124 :
125 : template <typename Metavariables>
126 0 : static type create_from_options(
127 : const std::optional<type>& eos,
128 : const std::unique_ptr<::evolution::initial_data::InitialData>&
129 : initial_data) {
130 : if (eos.has_value()) {
131 : return eos.value()->get_clone();
132 : } else {
133 : return call_with_dynamic_type<
134 : type,
135 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
136 : ::evolution::initial_data::InitialData>>(
137 : initial_data.get(), [](const auto* const derived_initial_data) {
138 : if constexpr (::evolution::is_numeric_initial_data_v<
139 : std::decay_t<decltype(*derived_initial_data)>>) {
140 : ERROR(
141 : "Equation of State cannot currently be parsed from numeric"
142 : "initial data, please explicitly specify the equation of "
143 : "state for the evolution in the input file.");
144 : if constexpr (ThermodynamicDim == 1) {
145 : return std::make_unique<
146 : EquationsOfState::PolytropicFluid<IsRelativistic>>(100.0,
147 : 2.0);
148 : } else if constexpr (ThermodynamicDim == 2) {
149 : return std::make_unique<
150 : EquationsOfState::IdealFluid<IsRelativistic>>(2.0);
151 : } else if constexpr (ThermodynamicDim == 3) {
152 : return std::make_unique<EquationsOfState::Barotropic3D<
153 : EquationsOfState::PolytropicFluid<IsRelativistic>>>(
154 : EquationsOfState::PolytropicFluid<IsRelativistic>(100.0,
155 : 2.0));
156 : }
157 : } else {
158 : if constexpr (ThermodynamicDim == 3) {
159 : return derived_initial_data->equation_of_state()
160 : .promote_to_3d_eos();
161 : } else if constexpr (ThermodynamicDim == 2) {
162 : return derived_initial_data->equation_of_state()
163 : .promote_to_2d_eos();
164 : } else {
165 : return derived_initial_data->equation_of_state().get_clone();
166 : }
167 : }
168 : });
169 : }
170 : }
171 : };
172 :
173 : /// The inverse plasma beta \f$\beta^{-1} = b^2 / (2 p)\f$, where
174 : ///// \f$b^2\f$ is the square of the comoving magnetic field amplitude
175 : ///// and \f$p\f$ is the fluid pressure.
176 : template <typename DataType>
177 1 : struct InversePlasmaBeta : db::SimpleTag {
178 0 : using type = Scalar<DataType>;
179 : };
180 :
181 : /// The equation of state constructed from options in the input file
182 : template <bool IsRelativistic, size_t ThermodynamicDim>
183 1 : struct EquationOfStateFromOptions : EquationOfStateBase, db::SimpleTag {
184 0 : static std::string name() { return "EquationOfState"; }
185 0 : using type = std::unique_ptr<
186 : EquationsOfState::EquationOfState<IsRelativistic, ThermodynamicDim>>;
187 :
188 0 : static constexpr bool pass_metavariables = false;
189 0 : using option_tags =
190 : tmpl::list<OptionTags::EquationOfState<IsRelativistic, ThermodynamicDim>>;
191 :
192 0 : static type create_from_options(const type& eos) { return eos->get_clone(); }
193 : };
194 :
195 : /// The Lorentz factor \f$W = (1-v^iv_i)^{-1/2}\f$, where \f$v^i\f$ is
196 : /// the spatial velocity of the fluid.
197 : template <typename DataType>
198 1 : struct LorentzFactor : db::SimpleTag {
199 0 : using type = Scalar<DataType>;
200 : };
201 :
202 : /// The square of the Lorentz factor \f$W^2\f$.
203 : template <typename DataType>
204 1 : struct LorentzFactorSquared : db::SimpleTag {
205 0 : using type = Scalar<DataType>;
206 : };
207 :
208 : /// The magnetic field \f$B^i = n_\mu {}^\star\!F^{i \mu}\f$ measured by an
209 : /// Eulerian observer, where \f$n_\mu\f$ is the normal to the spatial
210 : /// hypersurface and \f${}^\star\!F^{\mu \nu}\f$ is the dual of the
211 : /// Faraday tensor. Note that \f$B^i\f$ is purely spatial, and it
212 : /// can be lowered using the spatial metric.
213 : template <typename DataType, size_t Dim, typename Fr>
214 1 : struct MagneticField : db::SimpleTag {
215 0 : using type = tnsr::I<DataType, Dim, Fr>;
216 0 : static std::string name() { return Frame::prefix<Fr>() + "MagneticField"; }
217 : };
218 :
219 : /// The magnetic field dotted into the spatial velocity, \f$B^iv_i\f$ where
220 : /// \f$v_i\f$ is the spatial velocity one-form.
221 : template <typename DataType>
222 1 : struct MagneticFieldDotSpatialVelocity : db::SimpleTag {
223 0 : using type = Scalar<DataType>;
224 : };
225 :
226 : /// The one-form of the magnetic field. Note that \f$B^i\f$ is raised
227 : /// and lowered with the spatial metric.
228 : /// \see hydro::Tags::MagneticField
229 : template <typename DataType, size_t Dim, typename Fr>
230 1 : struct MagneticFieldOneForm : db::SimpleTag {
231 0 : using type = tnsr::i<DataType, Dim, Fr>;
232 0 : static std::string name() {
233 : return Frame::prefix<Fr>() + "MagneticFieldOneForm";
234 : }
235 : };
236 :
237 : /// The square of the magnetic field, \f$B^iB_i\f$
238 : template <typename DataType>
239 1 : struct MagneticFieldSquared : db::SimpleTag {
240 0 : using type = Scalar<DataType>;
241 : };
242 :
243 : /// The magnetic pressure \f$p_m\f$.
244 : template <typename DataType>
245 1 : struct MagneticPressure : db::SimpleTag {
246 0 : using type = Scalar<DataType>;
247 : };
248 :
249 : /// The fluid pressure \f$p\f$.
250 : template <typename DataType>
251 1 : struct Pressure : db::SimpleTag {
252 0 : using type = Scalar<DataType>;
253 : };
254 :
255 : /// The rest-mass density \f$\rho\f$.
256 : template <typename DataType>
257 1 : struct RestMassDensity : db::SimpleTag {
258 0 : using type = Scalar<DataType>;
259 : };
260 :
261 : /// The sound speed squared \f$c_s^2\f$.
262 : template <typename DataType>
263 1 : struct SoundSpeedSquared : db::SimpleTag {
264 0 : using type = Scalar<DataType>;
265 : };
266 :
267 : /// The spatial velocity \f$v^i\f$ of the fluid,
268 : /// where \f$v^i=u^i/W + \beta^i/\alpha\f$.
269 : /// Here \f$u^i\f$ is the spatial part of the 4-velocity of the fluid,
270 : /// \f$W\f$ is the Lorentz factor, \f$\beta^i\f$ is the shift vector,
271 : /// and \f$\alpha\f$ is the lapse function. Note that \f$v^i\f$ is raised
272 : /// and lowered with the spatial metric.
273 : template <typename DataType, size_t Dim, typename Fr>
274 1 : struct SpatialVelocity : db::SimpleTag {
275 0 : using type = tnsr::I<DataType, Dim, Fr>;
276 0 : static std::string name() { return Frame::prefix<Fr>() + "SpatialVelocity"; }
277 : };
278 :
279 : /// The spatial velocity one-form \f$v_i\f$, where \f$v_i\f$ is raised
280 : /// and lowered with the spatial metric.
281 : template <typename DataType, size_t Dim, typename Fr>
282 1 : struct SpatialVelocityOneForm : db::SimpleTag {
283 0 : using type = tnsr::i<DataType, Dim, Fr>;
284 0 : static std::string name() {
285 : return Frame::prefix<Fr>() + "SpatialVelocityOneForm";
286 : }
287 : };
288 :
289 : /// The spatial velocity squared \f$v^2 = v_i v^i\f$.
290 : template <typename DataType>
291 1 : struct SpatialVelocitySquared : db::SimpleTag {
292 0 : using type = Scalar<DataType>;
293 : };
294 :
295 : /// The relativistic specific enthalpy \f$h\f$.
296 : template <typename DataType>
297 1 : struct SpecificEnthalpy : db::SimpleTag {
298 0 : using type = Scalar<DataType>;
299 : };
300 :
301 : /// The specific internal energy \f$\epsilon\f$.
302 : template <typename DataType>
303 1 : struct SpecificInternalEnergy : db::SimpleTag {
304 0 : using type = Scalar<DataType>;
305 : };
306 :
307 : /// The temperature \f$T\f$ of the fluid.
308 : template <typename DataType>
309 1 : struct Temperature : db::SimpleTag {
310 0 : using type = Scalar<DataType>;
311 : };
312 :
313 : /// \brief Tag containing the transport velocity.
314 : ///
315 : /// The transport velocity is defined as \f$v_t^i=\alpha v^i-\beta^i\f$,
316 : /// with $v^i$ being the spatial velocity, $\alpha$ the lapse, and
317 : /// $\beta^i$ the shift.
318 : template <typename DataType, size_t Dim, typename Fr = Frame::Inertial>
319 1 : struct TransportVelocity : db::SimpleTag {
320 0 : using type = tnsr::I<DataType, Dim, Fr>;
321 : };
322 :
323 : /// The spatial components of the four-velocity one-form \f$u_i\f$.
324 : template <typename DataType, size_t Dim, typename Fr>
325 1 : struct LowerSpatialFourVelocity : db::SimpleTag {
326 0 : using type = tnsr::i<DataType, Dim, Fr>;
327 : };
328 :
329 : /// The Lorentz factor \f$W\f$ times the spatial velocity \f$v^i\f$.
330 : template <typename DataType, size_t Dim, typename Fr>
331 1 : struct LorentzFactorTimesSpatialVelocity : db::SimpleTag {
332 0 : using type = tnsr::I<DataType, Dim, Fr>;
333 : };
334 :
335 : /// The vector \f$J^i\f$ in \f$\dot{M} = -\int J^i s_i d^2S\f$,
336 : /// representing the mass flux through a surface with normal \f$s_i\f$.
337 : ///
338 : /// Note that the integral is understood
339 : /// as a flat-space integral: all metric factors are included in \f$J^i\f$.
340 : /// In particular, if the integral is done over a Strahlkorper, the
341 : /// `gr::surfaces::euclidean_area_element` of the Strahlkorper should be used,
342 : /// and \f$s_i\f$ is
343 : /// the normal one-form to the Strahlkorper normalized with the flat metric,
344 : /// \f$s_is_j\delta^{ij}=1\f$.
345 : ///
346 : /// The formula is
347 : /// \f$ J^i = \rho W \sqrt{\gamma}(\alpha v^i-\beta^i)\f$,
348 : /// where \f$\rho\f$ is the mass density, \f$W\f$ is the Lorentz factor,
349 : /// \f$v^i\f$ is the spatial velocity of the fluid,
350 : /// \f$\gamma\f$ is the determinant of the 3-metric \f$\gamma_{ij}\f$,
351 : /// \f$\alpha\f$ is the lapse, and \f$\beta^i\f$ is the shift.
352 : template <typename DataType, size_t Dim, typename Fr>
353 1 : struct MassFlux : db::SimpleTag {
354 0 : using type = tnsr::I<DataType, Dim, Fr>;
355 0 : static std::string name() { return Frame::prefix<Fr>() + "MassFlux"; }
356 : };
357 :
358 : /// The equation of state retrieved from the analytic solution / data in the
359 : /// input file
360 1 : struct GrmhdEquationOfState : ::hydro::Tags::EquationOfStateBase,
361 : db::SimpleTag {
362 0 : using type = std::unique_ptr<EquationsOfState::EquationOfState<true, 3>>;
363 :
364 : template <typename Metavariables>
365 0 : using option_tags =
366 : tmpl::list<OptionTags::GrmhdEquationOfState,
367 : ::evolution::initial_data::OptionTags::InitialData>;
368 0 : static constexpr bool pass_metavariables = true;
369 :
370 : template <typename Metavariables>
371 0 : static type create_from_options(
372 : const std::optional<type>& eos,
373 : const std::unique_ptr<::evolution::initial_data::InitialData>&
374 : initial_data) {
375 : if (eos.has_value()) {
376 : return eos.value()->get_clone();
377 : } else {
378 : return call_with_dynamic_type<
379 : type,
380 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
381 : ::evolution::initial_data::InitialData>>(
382 : initial_data.get(), [](const auto* const derived_initial_data) {
383 : if constexpr (::evolution::is_numeric_initial_data_v<
384 : std::decay_t<decltype(*derived_initial_data)>>) {
385 : ERROR(
386 : "Equation of State cannot currently be parsed from numeric"
387 : "initial data, please explicitly specify the equation of "
388 : "state for the evolution in the input file.");
389 : return std::make_unique<EquationsOfState::Barotropic3D<
390 : EquationsOfState::PolytropicFluid<true>>>(
391 : EquationsOfState::PolytropicFluid<true>(100.0, 2.0));
392 : } else {
393 : return (derived_initial_data->equation_of_state()
394 : .promote_to_3d_eos());
395 : }
396 : });
397 : }
398 : }
399 : };
400 : } // namespace Tags
401 :
402 : } // namespace hydro
|