AlfvenWave.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <array>
7 #include <limits>
8 #include <string>
9 
11 #include "Options/Options.hpp"
12 #include "PointwiseFunctions/AnalyticSolutions/GeneralRelativity/Minkowski.hpp"
13 #include "PointwiseFunctions/Hydro/EquationsOfState/EquationOfState.hpp"
14 #include "PointwiseFunctions/Hydro/Tags.hpp" // IWYU pragma: keep
15 #include "Utilities/MakeArray.hpp" // IWYU pragma: keep
16 #include "Utilities/TMPL.hpp"
18 
19 // IWYU pragma: no_include <pup.h>
20 
21 /// \cond
22 namespace PUP {
23 class er; // IWYU pragma: keep
24 } // namespace PUP
25 /// \endcond
26 
27 namespace grmhd {
28 namespace Solutions {
29 
30 /*!
31  * \brief Circularly polarized Alfv&eacute;n wave solution in Minkowski
32  * spacetime travelling along a background magnetic field.
33  *
34  * An analytic solution to the 3-D GRMHD system. The user specifies the
35  * wavenumber \f$k\f$ of the Alfv&eacute;n wave, the constant pressure
36  * throughout the fluid \f$P\f$, the constant rest mass density throughout the
37  * fluid \f$\rho_0\f$, the adiabatic index for the ideal fluid equation of
38  * state \f$\gamma\f$, the magnetic field parallel to the wavevector
39  * \f$\vec{B}_0\f$, and the transverse magnetic field vector \f$\vec{B}_1\f$ at
40  * \f$x=y=z=t=0\f$.
41  *
42  * We define the auxiliary velocities:
43  * \f[v^2_{B0} = \frac{B_0^2}{\rho_0 h + B_0^2 + B_1^2}\f]
44  * \f[v^2_{B1} = \frac{B_1^2}{\rho_0 h + B_0^2 + B_1^2}\f]
45  *
46  * The Alfv&eacute;n wave phase speed that solves the GRMHD equations, even for
47  * finite amplitudes \cite DelZanna2007pk, is given by:
48  *
49  * \f[v_A^2 = \frac{2v^2_{B0}}{1 + \sqrt{1 - 4 v^2_{B0}v^2_{B1}}}\f]
50  *
51  * The amplitude of the fluid velocity is given by:
52  *
53  * \f[v_f^2 = \frac{2v^2_{B1}}{1 + \sqrt{1 - 4 v^2_{B0}v^2_{B1}}}\f]
54  *
55  * The electromagnetic field vectors define a set of basis vectors:
56  *
57  * \f{align*}{
58  * \hat{b}_0 &= \vec{B_0}/B_0 \\
59  * \hat{b}_1 &= \vec{B_1}/B_1 \\
60  * \hat{e} &= \hat{b}_1 \times \hat{b}_0
61  * \f}
62  *
63  * We also define the auxiliary variable for the phase \f$\phi\f$:
64  * \f[\phi = k(\vec{x}\cdot\hat{b}_0 - v_A t)\f]
65  * In Cartesian coordinates \f$(x, y, z)\f$, and using
66  * dimensionless units, the primitive quantities at a given time \f$t\f$ are
67  * then
68  *
69  * \f{align*}
70  * \rho(\vec{x},t) &= \rho_0 \\
71  * \vec{v}(\vec{x},t) &= v_f(-\hat{b}_1\cos\phi
72  * +\hat{e}\sin\phi)\\
73  * P(\vec{x},t) &= P, \\
74  * \epsilon(\vec{x}, t) &= \frac{P}{(\gamma - 1)\rho_0}\\
75  * \vec{B}(\vec{x},t) &= B_1(\hat{b}_1\cos\phi
76  * -\hat{e}\sin\phi) + \vec{B_0}
77  * \f}
78  *
79  * Note that the phase speed is not the characteristic Alfv&eacute;n speed
80  * \f$c_A\f$, which is the speed in the limiting case where the total magnetic
81  * field is parallel to the direction of propagation \cite DelZanna2007pk :
82  *
83  * \f[c_A^2 = \frac{b^2}{\rho_0 h + b^2}\f]
84  *
85  * Where \f$b^2\f$ is the invariant quantity \f$B^2 - E^2\f$, given by:
86  *
87  * \f[b^2 = B_0^2 + B_1^2 - B_0^2 v_f^2\f]
88  */
89 class AlfvenWave {
90  public:
93 
94  /// The wave number of the profile.
95  struct WaveNumber {
96  using type = double;
97  static constexpr OptionString help = {"The wave number of the profile."};
98  };
99 
100  /// The constant pressure throughout the fluid.
101  struct Pressure {
102  using type = double;
103  static constexpr OptionString help = {
104  "The constant pressure throughout the fluid."};
105  static type lower_bound() noexcept { return 0.0; }
106  };
107 
108  /// The constant rest mass density throughout the fluid.
110  using type = double;
111  static constexpr OptionString help = {
112  "The constant rest mass density throughout the fluid."};
113  static type lower_bound() noexcept { return 0.0; }
114  };
115 
116  /// The adiabatic index for the ideal fluid.
117  struct AdiabaticIndex {
118  using type = double;
119  static constexpr OptionString help = {
120  "The adiabatic index for the ideal fluid."};
121  static type lower_bound() noexcept { return 1.0; }
122  };
123 
124  /// The background static magnetic field vector.
126  using type = std::array<double, 3>;
127  static std::string name() noexcept { return "BkgdMagneticField"; }
128  static constexpr OptionString help = {
129  "The background magnetic field [B0^x, B0^y, B0^z]."};
130  };
131 
132  /// The sinusoidal magnetic field vector associated with
133  /// the Alfv&eacute;n wave, perpendicular to the background
134  /// magnetic field vector.
136  using type = std::array<double, 3>;
137  static constexpr OptionString help = {
138  "The wave magnetic field [B1^x, B1^y, B1^z]."};
139  };
140 
141  using options =
144  static constexpr OptionString help = {
145  "Circularly polarized Alfven wave in Minkowski spacetime."};
146 
147  AlfvenWave() = default;
148  AlfvenWave(const AlfvenWave& /*rhs*/) = delete;
149  AlfvenWave& operator=(const AlfvenWave& /*rhs*/) = delete;
150  AlfvenWave(AlfvenWave&& /*rhs*/) noexcept = default;
151  AlfvenWave& operator=(AlfvenWave&& /*rhs*/) noexcept = default;
152  ~AlfvenWave() = default;
153 
154  AlfvenWave(WaveNumber::type wavenumber, Pressure::type pressure,
155  RestMassDensity::type rest_mass_density,
156  AdiabaticIndex::type adiabatic_index,
157  BackgroundMagneticField::type background_magnetic_field,
158  WaveMagneticField::type wave_magnetic_field) noexcept;
159 
160  // @{
161  /// Retrieve hydro variable at `(x, t)`
162  template <typename DataType>
163  auto variables(
164  const tnsr::I<DataType, 3>& x, double t,
165  tmpl::list<hydro::Tags::RestMassDensity<DataType>> /*meta*/) const
167 
168  template <typename DataType>
169  auto variables(
170  const tnsr::I<DataType, 3>& x, double t,
171  tmpl::list<hydro::Tags::SpecificInternalEnergy<DataType>> /*meta*/) const
172  noexcept
174 
175  template <typename DataType>
176  auto variables(const tnsr::I<DataType, 3>& x, double /*t*/,
177  tmpl::list<hydro::Tags::Pressure<DataType>> /*meta*/) const
179 
180  template <typename DataType>
181  auto variables(const tnsr::I<DataType, 3>& x, double /*t*/,
182  tmpl::list<hydro::Tags::SpatialVelocity<
183  DataType, 3, Frame::Inertial>> /*meta*/) const noexcept
186 
187  template <typename DataType>
188  auto variables(const tnsr::I<DataType, 3>& x, double /*t*/,
189  tmpl::list<hydro::Tags::MagneticField<
190  DataType, 3, Frame::Inertial>> /*meta*/) const noexcept
193 
194  template <typename DataType>
195  auto variables(
196  const tnsr::I<DataType, 3>& x, double /*t*/,
197  tmpl::list<hydro::Tags::DivergenceCleaningField<DataType>> /*meta*/) const
198  noexcept
200 
201  template <typename DataType>
202  auto variables(
203  const tnsr::I<DataType, 3>& x, double /*t*/,
204  tmpl::list<hydro::Tags::LorentzFactor<DataType>> /*meta*/) const noexcept
206 
207  template <typename DataType>
208  auto variables(
209  const tnsr::I<DataType, 3>& x, double t,
210  tmpl::list<hydro::Tags::SpecificEnthalpy<DataType>> /*meta*/) const
212  // @}
213 
214  /// Retrieve a collection of hydro variables at `(x, t)`
215  template <typename DataType, typename... Tags>
216  tuples::TaggedTuple<Tags...> variables(const tnsr::I<DataType, 3>& x,
217  double t,
218  tmpl::list<Tags...> /*meta*/) const
219  noexcept {
220  static_assert(sizeof...(Tags) > 1,
221  "The generic template will recurse infinitely if only one "
222  "tag is being retrieved.");
223  return {get<Tags>(variables(x, t, tmpl::list<Tags>{}))...};
224  }
225 
226  /// Retrieve the metric variables
227  template <typename DataType, typename Tag>
228  tuples::TaggedTuple<Tag> variables(const tnsr::I<DataType, 3>& x, double t,
229  tmpl::list<Tag> /*meta*/) const noexcept {
230  return background_spacetime_.variables(x, t, tmpl::list<Tag>{});
231  }
232 
233  // clang-tidy: no runtime references
234  void pup(PUP::er& /*p*/) noexcept; // NOLINT
235 
236  const EquationsOfState::IdealFluid<true>& equation_of_state() const noexcept {
237  return equation_of_state_;
238  }
239 
240  private:
241  friend bool operator==(const AlfvenWave& lhs, const AlfvenWave& rhs) noexcept;
242 
243  // Computes the phase.
244  template <typename DataType>
245  DataType k_dot_x_minus_vt(const tnsr::I<DataType, 3>& x, double t) const
246  noexcept;
247  WaveNumber::type wavenumber_ = std::numeric_limits<double>::signaling_NaN();
248  Pressure::type pressure_ = std::numeric_limits<double>::signaling_NaN();
249  RestMassDensity::type rest_mass_density_ =
251  AdiabaticIndex::type adiabatic_index_ =
253  BackgroundMagneticField::type background_magnetic_field_{
255  WaveMagneticField::type wave_magnetic_field_{
257  EquationsOfState::IdealFluid<true> equation_of_state_{};
258  tnsr::I<double, 3, Frame::Inertial>
259  initial_unit_vector_along_background_magnetic_field_{};
260  tnsr::I<double, 3, Frame::Inertial>
261  initial_unit_vector_along_wave_magnetic_field_{};
262  tnsr::I<double, 3, Frame::Inertial>
263  initial_unit_vector_along_wave_electric_field_{};
264  double magnitude_B0_ = std::numeric_limits<double>::signaling_NaN();
265  double magnitude_B1_ = std::numeric_limits<double>::signaling_NaN();
266  double magnitude_E_ = std::numeric_limits<double>::signaling_NaN();
267  double alfven_speed_ = std::numeric_limits<double>::signaling_NaN();
268  double fluid_speed_ = std::numeric_limits<double>::signaling_NaN();
269  gr::Solutions::Minkowski<3> background_spacetime_{};
270 };
271 
272 bool operator!=(const AlfvenWave& lhs, const AlfvenWave& rhs) noexcept;
273 
274 } // namespace Solutions
275 } // namespace grmhd
Definition: Strahlkorper.hpp:14
Defines class tuples::TaggedTuple.
The spatial velocity .
Definition: Tags.hpp:144
The constant pressure throughout the fluid.
Definition: AlfvenWave.hpp:101
The fluid pressure .
Definition: Tags.hpp:123
The specific internal energy .
Definition: Tags.hpp:176
T signaling_NaN(T... args)
Defines function make_array.
Circularly polarized Alfvén wave solution in Minkowski spacetime travelling along a background magnet...
Definition: AlfvenWave.hpp:89
Defines classes and functions for making classes creatable from input files.
The adiabatic index for the ideal fluid.
Definition: AlfvenWave.hpp:117
auto variables(const tnsr::I< DataType, 3 > &x, double t, tmpl::list< hydro::Tags::RestMassDensity< DataType >>) const noexcept -> tuples::TaggedTuple< hydro::Tags::RestMassDensity< DataType >>
Retrieve hydro variable at (x, t)
The magnetic field measured by an Eulerian observer, where is the normal to the spatial hypersurfac...
Definition: Tags.hpp:80
The divergence-cleaning field .
Definition: Tags.hpp:47
The background static magnetic field vector.
Definition: AlfvenWave.hpp:125
const char *const OptionString
The string used in option structs.
Definition: Options.hpp:26
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:272
The sinusoidal magnetic field vector associated with the Alfvén wave, perpendicular to the background...
Definition: AlfvenWave.hpp:135
The wave number of the profile.
Definition: AlfvenWave.hpp:95
The constant rest mass density throughout the fluid.
Definition: AlfvenWave.hpp:109
The Lorentz factor .
Definition: Tags.hpp:64
Definition: DataBoxTag.hpp:29
Defines a list of useful type aliases for tensors.
Wraps the template metaprogramming library used (brigand)
tuples::TaggedTuple< Tags... > variables(const tnsr::I< DataType, 3 > &x, double t, tmpl::list< Tags... >) const noexcept
Retrieve a collection of hydro variables at (x, t)
Definition: AlfvenWave.hpp:216
The rest-mass density .
Definition: Tags.hpp:130
Definition: IndexType.hpp:44
The specific enthalpy .
Definition: Tags.hpp:169
Items related to general relativistic magnetohydrodynamics (GRMHD)
Definition: Characteristics.hpp:34
tuples::TaggedTuple< Tag > variables(const tnsr::I< DataType, 3 > &x, double t, tmpl::list< Tag >) const noexcept
Retrieve the metric variables.
Definition: AlfvenWave.hpp:228