SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticSolutions/GrMhd - AlfvenWave.hpp Hit Total Coverage
Commit: a8efe75339f4781ca06d43fed14c40144d5e8a08 Lines: 21 75 28.0 %
Date: 2024-10-17 21:19:21
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : // 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             : 
      10             : #include "DataStructures/Tensor/TypeAliases.hpp"
      11             : #include "Options/String.hpp"
      12             : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
      13             : #include "PointwiseFunctions/AnalyticSolutions/GeneralRelativity/Minkowski.hpp"
      14             : #include "PointwiseFunctions/AnalyticSolutions/GrMhd/Solutions.hpp"
      15             : #include "PointwiseFunctions/Hydro/EquationsOfState/IdealFluid.hpp"
      16             : #include "PointwiseFunctions/Hydro/TagsDeclarations.hpp"
      17             : #include "PointwiseFunctions/Hydro/Temperature.hpp"
      18             : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
      19             : #include "Utilities/Serialization/CharmPupable.hpp"
      20             : #include "Utilities/TMPL.hpp"
      21             : #include "Utilities/TaggedTuple.hpp"
      22             : 
      23             : /// \cond
      24             : namespace PUP {
      25             : class er;
      26             : }  // namespace PUP
      27             : /// \endcond
      28             : 
      29           1 : namespace grmhd::Solutions {
      30             : 
      31             : /*!
      32             :  * \brief Circularly polarized Alfv&eacute;n wave solution in Minkowski
      33             :  * spacetime travelling along a background magnetic field.
      34             :  *
      35             :  * An analytic solution to the 3-D GRMHD system. The user specifies the
      36             :  * wavenumber \f$k\f$ of the Alfv&eacute;n wave, the constant pressure
      37             :  * throughout the fluid \f$P\f$, the constant rest mass density throughout the
      38             :  * fluid \f$\rho_0\f$, the adiabatic index for the ideal fluid equation of
      39             :  * state \f$\gamma\f$, the magnetic field parallel to the wavevector
      40             :  * \f$\vec{B}_0\f$, and the transverse magnetic field vector \f$\vec{B}_1\f$ at
      41             :  * \f$x=y=z=t=0\f$.
      42             :  *
      43             :  * We define the auxiliary velocities:
      44             :  * \f[v^2_{B0} = \frac{B_0^2}{\rho_0 h + B_0^2 + B_1^2}\f]
      45             :  * \f[v^2_{B1} = \frac{B_1^2}{\rho_0 h + B_0^2 + B_1^2}\f]
      46             :  *
      47             :  * The Alfv&eacute;n wave phase speed that solves the GRMHD equations, even for
      48             :  * finite amplitudes \cite DelZanna2007pk, is given by:
      49             :  *
      50             :  * \f[v_A^2 = \frac{2v^2_{B0}}{1 + \sqrt{1 - 4 v^2_{B0}v^2_{B1}}}\f]
      51             :  *
      52             :  * The amplitude of the fluid velocity is given by:
      53             :  *
      54             :  * \f[v_f^2 = \frac{2v^2_{B1}}{1 + \sqrt{1 - 4 v^2_{B0}v^2_{B1}}}\f]
      55             :  *
      56             :  * The electromagnetic field vectors define a set of basis vectors:
      57             :  *
      58             :  * \f{align*}{
      59             :  * \hat{b}_0 &= \vec{B_0}/B_0 \\
      60             :  * \hat{b}_1 &= \vec{B_1}/B_1 \\
      61             :  * \hat{e} &= \hat{b}_1 \times \hat{b}_0
      62             :  * \f}
      63             :  *
      64             :  * We also define the auxiliary variable for the phase \f$\phi\f$:
      65             :  * \f[\phi = k(\vec{x}\cdot\hat{b}_0 - v_A t)\f]
      66             :  * In Cartesian coordinates \f$(x, y, z)\f$, and using
      67             :  * dimensionless units, the primitive quantities at a given time \f$t\f$ are
      68             :  * then
      69             :  *
      70             :  * \f{align*}
      71             :  * \rho(\vec{x},t) &= \rho_0 \\
      72             :  * \vec{v}(\vec{x},t) &= v_f(-\hat{b}_1\cos\phi
      73             :  *  +\hat{e}\sin\phi)\\
      74             :  * P(\vec{x},t) &= P, \\
      75             :  * \epsilon(\vec{x}, t) &= \frac{P}{(\gamma - 1)\rho_0}\\
      76             :  * \vec{B}(\vec{x},t) &= B_1(\hat{b}_1\cos\phi
      77             :  *  -\hat{e}\sin\phi) + \vec{B_0}
      78             :  * \f}
      79             :  *
      80             :  * Note that the phase speed is not the characteristic Alfv&eacute;n speed
      81             :  * \f$c_A\f$, which is the speed in the limiting case where the total magnetic
      82             :  * field is parallel to the direction of propagation \cite DelZanna2007pk :
      83             :  *
      84             :  * \f[c_A^2 = \frac{b^2}{\rho_0 h + b^2}\f]
      85             :  *
      86             :  * Where \f$b^2\f$ is the invariant quantity \f$B^2 - E^2\f$, given by:
      87             :  *
      88             :  * \f[b^2 = B_0^2 + B_1^2 - B_0^2 v_f^2\f]
      89             :  */
      90           1 : class AlfvenWave : public evolution::initial_data::InitialData,
      91             :                    public AnalyticSolution,
      92             :                    public hydro::TemperatureInitialization<AlfvenWave>,
      93             :                    public MarkAsAnalyticSolution {
      94             :  public:
      95           0 :   using equation_of_state_type = EquationsOfState::IdealFluid<true>;
      96             : 
      97             :   /// The wave number of the profile.
      98           1 :   struct WaveNumber {
      99           0 :     using type = double;
     100           0 :     static constexpr Options::String help = {"The wave number of the profile."};
     101             :   };
     102             : 
     103             :   /// The constant pressure throughout the fluid.
     104           1 :   struct Pressure {
     105           0 :     using type = double;
     106           0 :     static constexpr Options::String help = {
     107             :         "The constant pressure throughout the fluid."};
     108           0 :     static type lower_bound() { return 0.0; }
     109             :   };
     110             : 
     111             :   /// The constant rest mass density throughout the fluid.
     112           1 :   struct RestMassDensity {
     113           0 :     using type = double;
     114           0 :     static constexpr Options::String help = {
     115             :         "The constant rest mass density throughout the fluid."};
     116           0 :     static type lower_bound() { return 0.0; }
     117             :   };
     118             : 
     119             :   /// The constant electron fraction throughout the fluid.
     120           1 :   struct ElectronFraction {
     121           0 :     using type = double;
     122           0 :     static constexpr Options::String help = {
     123             :         "The constant electron fraction throughout the fluid."};
     124           0 :     static type lower_bound() { return 0.0; }
     125           0 :     static type upper_bound() { return 1.0; }
     126             :   };
     127             : 
     128             :   /// The adiabatic index for the ideal fluid.
     129           1 :   struct AdiabaticIndex {
     130           0 :     using type = double;
     131           0 :     static constexpr Options::String help = {
     132             :         "The adiabatic index for the ideal fluid."};
     133           0 :     static type lower_bound() { return 1.0; }
     134             :   };
     135             : 
     136             :   /// The background static magnetic field vector.
     137           1 :   struct BackgroundMagneticField {
     138           0 :     using type = std::array<double, 3>;
     139           0 :     static std::string name() { return "BkgdMagneticField"; }
     140           0 :     static constexpr Options::String help = {
     141             :         "The background magnetic field [B0^x, B0^y, B0^z]."};
     142             :   };
     143             : 
     144             :   /// The sinusoidal magnetic field vector associated with
     145             :   /// the Alfv&eacute;n wave, perpendicular to the background
     146             :   /// magnetic field vector.
     147           1 :   struct WaveMagneticField {
     148           0 :     using type = std::array<double, 3>;
     149           0 :     static constexpr Options::String help = {
     150             :         "The wave magnetic field [B1^x, B1^y, B1^z]."};
     151             :   };
     152             : 
     153           0 :   using options =
     154             :       tmpl::list<WaveNumber, Pressure, RestMassDensity, ElectronFraction,
     155             :                  AdiabaticIndex, BackgroundMagneticField, WaveMagneticField>;
     156           0 :   static constexpr Options::String help = {
     157             :       "Circularly polarized Alfven wave in Minkowski spacetime."};
     158             : 
     159           0 :   AlfvenWave() = default;
     160           0 :   AlfvenWave(const AlfvenWave& /*rhs*/) = default;
     161           0 :   AlfvenWave& operator=(const AlfvenWave& /*rhs*/) = default;
     162           0 :   AlfvenWave(AlfvenWave&& /*rhs*/) = default;
     163           0 :   AlfvenWave& operator=(AlfvenWave&& /*rhs*/) = default;
     164           0 :   ~AlfvenWave() override = default;
     165             : 
     166           0 :   AlfvenWave(double wavenumber, double pressure, double rest_mass_density,
     167             :              double electron_fraction, double adiabatic_index,
     168             :              const std::array<double, 3>& background_magnetic_field,
     169             :              const std::array<double, 3>& wave_magnetic_field);
     170             : 
     171           0 :   auto get_clone() const
     172             :       -> std::unique_ptr<evolution::initial_data::InitialData> override;
     173             : 
     174             :   /// \cond
     175             :   explicit AlfvenWave(CkMigrateMessage* msg);
     176             :   using PUP::able::register_constructor;
     177             :   WRAPPED_PUPable_decl_template(AlfvenWave);
     178             :   /// \endcond
     179             : 
     180             :   /// @{
     181             :   /// Retrieve hydro variable at `(x, t)`
     182             :   template <typename DataType>
     183           1 :   auto variables(const tnsr::I<DataType, 3>& x, double t,
     184             :                  tmpl::list<hydro::Tags::RestMassDensity<DataType>> /*meta*/)
     185             :       const -> tuples::TaggedTuple<hydro::Tags::RestMassDensity<DataType>>;
     186             : 
     187             :   template <typename DataType>
     188           1 :   auto variables(const tnsr::I<DataType, 3>& x, double t,
     189             :                  tmpl::list<hydro::Tags::ElectronFraction<DataType>> /*meta*/)
     190             :       const -> tuples::TaggedTuple<hydro::Tags::ElectronFraction<DataType>>;
     191             : 
     192             :   template <typename DataType>
     193           1 :   auto variables(
     194             :       const tnsr::I<DataType, 3>& x, double t,
     195             :       tmpl::list<hydro::Tags::SpecificInternalEnergy<DataType>> /*meta*/) const
     196             :       -> tuples::TaggedTuple<hydro::Tags::SpecificInternalEnergy<DataType>>;
     197             : 
     198             :   template <typename DataType>
     199           1 :   auto variables(const tnsr::I<DataType, 3>& x, double /*t*/,
     200             :                  tmpl::list<hydro::Tags::Pressure<DataType>> /*meta*/) const
     201             :       -> tuples::TaggedTuple<hydro::Tags::Pressure<DataType>>;
     202             : 
     203             :   template <typename DataType>
     204           1 :   auto variables(const tnsr::I<DataType, 3>& x, double /*t*/,
     205             :                  tmpl::list<hydro::Tags::SpatialVelocity<DataType, 3>> /*meta*/)
     206             :       const -> tuples::TaggedTuple<hydro::Tags::SpatialVelocity<DataType, 3>>;
     207             : 
     208             :   template <typename DataType>
     209           1 :   auto variables(const tnsr::I<DataType, 3>& x, double /*t*/,
     210             :                  tmpl::list<hydro::Tags::MagneticField<DataType, 3>> /*meta*/)
     211             :       const -> tuples::TaggedTuple<hydro::Tags::MagneticField<DataType, 3>>;
     212             : 
     213             :   template <typename DataType>
     214           1 :   auto variables(
     215             :       const tnsr::I<DataType, 3>& x, double /*t*/,
     216             :       tmpl::list<hydro::Tags::DivergenceCleaningField<DataType>> /*meta*/) const
     217             :       -> tuples::TaggedTuple<hydro::Tags::DivergenceCleaningField<DataType>>;
     218             : 
     219             :   template <typename DataType>
     220           1 :   auto variables(const tnsr::I<DataType, 3>& x, double /*t*/,
     221             :                  tmpl::list<hydro::Tags::LorentzFactor<DataType>> /*meta*/)
     222             :       const -> tuples::TaggedTuple<hydro::Tags::LorentzFactor<DataType>>;
     223             : 
     224             :   template <typename DataType>
     225           1 :   auto variables(const tnsr::I<DataType, 3>& x, double t,
     226             :                  tmpl::list<hydro::Tags::SpecificEnthalpy<DataType>> /*meta*/)
     227             :       const -> tuples::TaggedTuple<hydro::Tags::SpecificEnthalpy<DataType>>;
     228             : 
     229             :   template <typename DataType>
     230           1 :   auto variables(const tnsr::I<DataType, 3>& x, double t,
     231             :                  tmpl::list<hydro::Tags::Temperature<DataType>> /*meta*/) const
     232             :       -> tuples::TaggedTuple<hydro::Tags::Temperature<DataType>> {
     233             :     return TemperatureInitialization::variables(
     234             :         x, t, tmpl::list<hydro::Tags::Temperature<DataType>>{});
     235             :   }
     236             :   /// @}
     237             : 
     238             :   /// Retrieve a collection of hydro variables at `(x, t)`
     239             :   template <typename DataType, typename Tag1, typename Tag2, typename... Tags>
     240           1 :   tuples::TaggedTuple<Tag1, Tag2, Tags...> variables(
     241             :       const tnsr::I<DataType, 3>& x, double t,
     242             :       tmpl::list<Tag1, Tag2, Tags...> /*meta*/) const {
     243             :     return {tuples::get<Tag1>(variables(x, t, tmpl::list<Tag1>{})),
     244             :             tuples::get<Tag2>(variables(x, t, tmpl::list<Tag2>{})),
     245             :             tuples::get<Tags>(variables(x, t, tmpl::list<Tags>{}))...};
     246             :   }
     247             : 
     248             :   /// Retrieve the metric variables
     249             :   template <typename DataType, typename Tag,
     250             :             Requires<tmpl::list_contains_v<
     251             :                 gr::analytic_solution_tags<3, DataType>, Tag>> = nullptr>
     252           1 :   tuples::TaggedTuple<Tag> variables(const tnsr::I<DataType, 3>& x, double t,
     253             :                                      tmpl::list<Tag> /*meta*/) const {
     254             :     return background_spacetime_.variables(x, t, tmpl::list<Tag>{});
     255             :   }
     256             : 
     257             :   // NOLINTNEXTLINE(google-runtime-references)
     258           0 :   void pup(PUP::er& /*p*/) override;
     259             : 
     260           0 :   const EquationsOfState::IdealFluid<true>& equation_of_state() const {
     261             :     return equation_of_state_;
     262             :   }
     263             : 
     264             :  protected:
     265           0 :   friend bool operator==(const AlfvenWave& lhs, const AlfvenWave& rhs);
     266             : 
     267             :   // Computes the phase.
     268             :   template <typename DataType>
     269           0 :   DataType k_dot_x_minus_vt(const tnsr::I<DataType, 3>& x, double t) const;
     270           0 :   double wavenumber_ = std::numeric_limits<double>::signaling_NaN();
     271           0 :   double pressure_ = std::numeric_limits<double>::signaling_NaN();
     272           0 :   double rest_mass_density_ = std::numeric_limits<double>::signaling_NaN();
     273           0 :   double electron_fraction_ = std::numeric_limits<double>::signaling_NaN();
     274           0 :   double adiabatic_index_ = std::numeric_limits<double>::signaling_NaN();
     275           0 :   std::array<double, 3> background_magnetic_field_{
     276             :       {std::numeric_limits<double>::signaling_NaN(),
     277             :        std::numeric_limits<double>::signaling_NaN(),
     278             :        std::numeric_limits<double>::signaling_NaN()}};
     279           0 :   std::array<double, 3> wave_magnetic_field_{
     280             :       {std::numeric_limits<double>::signaling_NaN(),
     281             :        std::numeric_limits<double>::signaling_NaN(),
     282             :        std::numeric_limits<double>::signaling_NaN()}};
     283           0 :   EquationsOfState::IdealFluid<true> equation_of_state_{};
     284           0 :   tnsr::I<double, 3> initial_unit_vector_along_background_magnetic_field_{};
     285           0 :   tnsr::I<double, 3> initial_unit_vector_along_wave_magnetic_field_{};
     286           0 :   tnsr::I<double, 3> initial_unit_vector_along_wave_electric_field_{};
     287           0 :   double magnitude_B0_ = std::numeric_limits<double>::signaling_NaN();
     288           0 :   double magnitude_B1_ = std::numeric_limits<double>::signaling_NaN();
     289           0 :   double magnitude_E_ = std::numeric_limits<double>::signaling_NaN();
     290           0 :   double alfven_speed_ = std::numeric_limits<double>::signaling_NaN();
     291           0 :   double fluid_speed_ = std::numeric_limits<double>::signaling_NaN();
     292           0 :   gr::Solutions::Minkowski<3> background_spacetime_{};
     293             : };
     294             : 
     295           0 : bool operator!=(const AlfvenWave& lhs, const AlfvenWave& rhs);
     296             : 
     297             : }  // namespace grmhd::Solutions

Generated by: LCOV version 1.14