MagneticFieldLoop.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 
10 #include "Options/Options.hpp"
11 #include "PointwiseFunctions/AnalyticSolutions/GeneralRelativity/Minkowski.hpp"
12 #include "PointwiseFunctions/Hydro/EquationsOfState/EquationOfState.hpp"
13 #include "PointwiseFunctions/Hydro/EquationsOfState/IdealFluid.hpp" // IWYU pragma: keep
14 #include "PointwiseFunctions/Hydro/Tags.hpp"
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 AnalyticData {
29 
30 /*!
31  * \brief Analytic initial data for an advecting magnetic field loop.
32  *
33  * This test, originally proposed in \cite Gardiner2005hy and presented in a
34  * slightly modified form by \cite Mignone2010br, a region with annular
35  * cross section with the specified `InnerRadius` and `OuterRadius` is given a
36  * non-zero azimuthal magnetic field of constant magnitude `MagFieldStrength`
37  * with zero magnetic field outside the loop. Inside the `InnerRadius` the
38  * magnetic field strength falls to zero quadratically. The loop is embedded in
39  * an ideal fluid with the given `AdiabaticIndex`, `RestMassDensity` and
40  * `Pressure` with a uniform `AdvectionVelocity`. The magnetic field loop
41  * should advect across the grid, maintaining its shape and strength, as long
42  * as the magnetic pressure is negligible compared to the thermal pressure.
43  *
44  * This test diagnoses how well the evolution scheme preserves the no-monopole
45  * condition, as well as the diffusivity of the scheme.
46  *
47  * The standard test setup is done on \f$x \in [-1,1]\f$, \f$y \in [-0.5,
48  * 0.5]\f$, with periodic boundary conditions and with the following values
49  * given for the options:
50  * - InnerRadius: 0.06
51  * - OuterRadius: 0.3
52  * - RestMassDensity: 1.0
53  * - Pressure: 1.0
54  * - AdvectionVelocity: [0.08164965809277261, 0.040824829046386304, 0.0]
55  * - MagFieldStrength: 0.001
56  * - AdiabaticIndex: 1.66666666666666667
57  *
58  */
60  public:
62 
63  /// The pressure throughout the fluid.
64  struct Pressure {
65  using type = double;
66  static constexpr OptionString help = {
67  "The constant pressure throughout the fluid."};
68  static type lower_bound() { return 0.0; }
69  };
70 
71  /// The rest mass density throughout the fluid.
72  struct RestMassDensity {
73  using type = double;
74  static constexpr OptionString help = {
75  "The constant density throughout the fluid."};
76  static type lower_bound() { return 0.0; }
77  };
78 
79  /// The adiabatic index for the ideal fluid.
80  struct AdiabaticIndex {
81  using type = double;
82  static constexpr OptionString help = {
83  "The adiabatic index for the ideal fluid."};
84  static type lower_bound() { return 1.0; }
85  };
86 
87  /// The fluid velocity.
90  static constexpr OptionString help = {"The advection velocity."};
91  static type lower_bound() { return {{-1.0, -1.0, -1.0}}; }
92  static type upper_bound() { return {{1.0, 1.0, 1.0}}; }
93  };
94 
95  /// The strength of the magnetic field.
97  using type = double;
98  static constexpr OptionString help = {
99  "The magnitude of the magnetic field."};
100  static type lower_bound() { return 0.0; }
101  };
102 
103  /// The inner radius of the magnetic loop.
104  struct InnerRadius {
105  using type = double;
106  static constexpr OptionString help = {
107  "The inner radius of the magnetic loop."};
108  static type lower_bound() { return 0.0; }
109  };
110 
111  /// The outer radius of the magnetic loop.
112  struct OuterRadius {
113  using type = double;
114  static constexpr OptionString help = {
115  "The outer radius of the magnetic loop."};
116  static type lower_bound() { return 0.0; }
117  };
118 
119  using options =
122  static constexpr OptionString help = {
123  "Periodic advection of a magnetic field loop in Minkowski."};
124 
125  MagneticFieldLoop() = default;
126  MagneticFieldLoop(const MagneticFieldLoop& /*rhs*/) = delete;
127  MagneticFieldLoop& operator=(const MagneticFieldLoop& /*rhs*/) = delete;
128  MagneticFieldLoop(MagneticFieldLoop&& /*rhs*/) noexcept = default;
129  MagneticFieldLoop& operator=(MagneticFieldLoop&& /*rhs*/) noexcept = default;
130  ~MagneticFieldLoop() = default;
131 
132  MagneticFieldLoop(double pressure, double rest_mass_density,
133  double adiabatic_index,
134  const std::array<double, 3>& advection_velocity,
135  double magnetic_field_magnitude, double inner_radius,
136  double outer_radius, const OptionContext& context = {});
137 
138  explicit MagneticFieldLoop(CkMigrateMessage* /*unused*/) noexcept {}
139 
140  // @{
141  /// Retrieve the GRMHD variables at a given position.
142  template <typename DataType>
143  auto variables(
144  const tnsr::I<DataType, 3>& x,
145  tmpl::list<hydro::Tags::RestMassDensity<DataType>> /*meta*/) const
147 
148  template <typename DataType>
149  auto variables(
150  const tnsr::I<DataType, 3>& x,
151  tmpl::list<hydro::Tags::SpecificInternalEnergy<DataType>> /*meta*/) const
152  noexcept
154 
155  template <typename DataType>
156  auto variables(const tnsr::I<DataType, 3>& x,
157  tmpl::list<hydro::Tags::Pressure<DataType>> /*meta*/) const
159 
160  template <typename DataType>
161  auto variables(const tnsr::I<DataType, 3>& x,
162  tmpl::list<hydro::Tags::SpatialVelocity<
163  DataType, 3, Frame::Inertial>> /*meta*/) const noexcept
166 
167  template <typename DataType>
168  auto variables(const tnsr::I<DataType, 3>& x,
169  tmpl::list<hydro::Tags::MagneticField<
170  DataType, 3, Frame::Inertial>> /*meta*/) const noexcept
173 
174  template <typename DataType>
175  auto variables(
176  const tnsr::I<DataType, 3>& x,
177  tmpl::list<hydro::Tags::DivergenceCleaningField<DataType>> /*meta*/) const
178  noexcept
180 
181  template <typename DataType>
182  auto variables(
183  const tnsr::I<DataType, 3>& x,
184  tmpl::list<hydro::Tags::LorentzFactor<DataType>> /*meta*/) const noexcept
186 
187  template <typename DataType>
188  auto variables(
189  const tnsr::I<DataType, 3>& x,
190  tmpl::list<hydro::Tags::SpecificEnthalpy<DataType>> /*meta*/) const
192  // @}
193 
194  /// Retrieve a collection of hydrodynamic variables at position x
195  template <typename DataType, typename... Tags>
197  const tnsr::I<DataType, 3, Frame::Inertial>& x,
198  tmpl::list<Tags...> /*meta*/) const noexcept {
199  static_assert(sizeof...(Tags) > 1,
200  "The generic template will recurse infinitely if only one "
201  "tag is being retrieved.");
202  return {tuples::get<Tags>(variables(x, tmpl::list<Tags>{}))...};
203  }
204 
205  /// Retrieve the metric variables
206  template <typename DataType, typename Tag>
207  tuples::TaggedTuple<Tag> variables(const tnsr::I<DataType, 3>& x,
208  tmpl::list<Tag> /*meta*/) const noexcept {
209  constexpr double dummy_time = 0.0;
210  return background_spacetime_.variables(x, dummy_time, tmpl::list<Tag>{});
211  }
212 
213  const EquationsOfState::IdealFluid<true>& equation_of_state() const noexcept {
214  return equation_of_state_;
215  }
216 
217  // clang-tidy: no runtime references
218  void pup(PUP::er& /*p*/) noexcept; // NOLINT
219 
220  private:
221  double pressure_ = std::numeric_limits<double>::signaling_NaN();
222  double rest_mass_density_ = std::numeric_limits<double>::signaling_NaN();
223  double adiabatic_index_ = std::numeric_limits<double>::signaling_NaN();
224  std::array<double, 3> advection_velocity_ =
226  double magnetic_field_magnitude_ =
228  double inner_radius_ = std::numeric_limits<double>::signaling_NaN();
229  double outer_radius_ = std::numeric_limits<double>::signaling_NaN();
230 
231  EquationsOfState::IdealFluid<true> equation_of_state_{};
232  gr::Solutions::Minkowski<3> background_spacetime_{};
233 
234  friend bool operator==(const MagneticFieldLoop& lhs,
235  const MagneticFieldLoop& rhs) noexcept;
236 
237  friend bool operator!=(const MagneticFieldLoop& lhs,
238  const MagneticFieldLoop& rhs) noexcept;
239 };
240 
241 } // namespace AnalyticData
242 } // namespace grmhd
tuples::TaggedTuple< Tag > variables(const tnsr::I< DataType, 3 > &x, tmpl::list< Tag >) const noexcept
Retrieve the metric variables.
Definition: MagneticFieldLoop.hpp:207
tuples::TaggedTuple< Tags... > variables(const tnsr::I< DataType, 3, Frame::Inertial > &x, tmpl::list< Tags... >) const noexcept
Retrieve a collection of hydrodynamic variables at position x.
Definition: MagneticFieldLoop.hpp:196
Definition: Strahlkorper.hpp:14
Defines class tuples::TaggedTuple.
The spatial velocity of the fluid, where . Here is the spatial part of the 4-velocity of the fluid...
Definition: Tags.hpp:157
The fluid pressure .
Definition: Tags.hpp:131
The specific internal energy .
Definition: Tags.hpp:190
T signaling_NaN(T... args)
Defines function make_array.
Defines classes and functions for making classes creatable from input files.
Analytic initial data for an advecting magnetic field loop.
Definition: MagneticFieldLoop.hpp:59
The pressure throughout the fluid.
Definition: MagneticFieldLoop.hpp:64
The magnetic field measured by an Eulerian observer, where is the normal to the spatial hypersurfac...
Definition: Tags.hpp:87
The rest mass density throughout the fluid.
Definition: MagneticFieldLoop.hpp:72
The adiabatic index for the ideal fluid.
Definition: MagneticFieldLoop.hpp:80
The divergence-cleaning field .
Definition: Tags.hpp:51
The fluid velocity.
Definition: MagneticFieldLoop.hpp:88
const char *const OptionString
The string used in option structs.
Definition: Options.hpp:29
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:272
The Lorentz factor , where is the spatial velocity of the fluid.
Definition: Tags.hpp:69
Definition: DataBoxTag.hpp:29
The strength of the magnetic field.
Definition: MagneticFieldLoop.hpp:96
Defines a list of useful type aliases for tensors.
auto variables(const tnsr::I< DataType, 3 > &x, tmpl::list< hydro::Tags::RestMassDensity< DataType >>) const noexcept -> tuples::TaggedTuple< hydro::Tags::RestMassDensity< DataType >>
Retrieve the GRMHD variables at a given position.
Information about the nested operations being performed by the parser, for use in printing errors...
Definition: Options.hpp:38
Wraps the template metaprogramming library used (brigand)
The rest-mass density .
Definition: Tags.hpp:138
Definition: IndexType.hpp:44
The specific enthalpy .
Definition: Tags.hpp:183
The inner radius of the magnetic loop.
Definition: MagneticFieldLoop.hpp:104
Items related to general relativistic magnetohydrodynamics (GRMHD)
Definition: Characteristics.hpp:34
The outer radius of the magnetic loop.
Definition: MagneticFieldLoop.hpp:112