SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticData/GrMhd/InitialMagneticFields - Poloidal.hpp Hit Total Coverage
Commit: 1afd040526f6585adf96eb1710263813d4f5ac0e Lines: 3 42 7.1 %
Date: 2024-05-23 14:31:37
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 <cstddef>
       7             : #include <limits>
       8             : 
       9             : #include "DataStructures/Tensor/TypeAliases.hpp"
      10             : #include "Options/String.hpp"
      11             : #include "PointwiseFunctions/AnalyticData/GrMhd/InitialMagneticFields/InitialMagneticField.hpp"
      12             : #include "PointwiseFunctions/GeneralRelativity/TagsDeclarations.hpp"
      13             : #include "PointwiseFunctions/Hydro/TagsDeclarations.hpp"
      14             : #include "Utilities/TMPL.hpp"
      15             : #include "Utilities/TaggedTuple.hpp"
      16             : 
      17             : /// \cond
      18             : namespace gsl {
      19             : template <typename T>
      20             : class not_null;
      21             : }  // namespace gsl
      22             : /// \endcond
      23             : 
      24             : namespace grmhd::AnalyticData::InitialMagneticFields {
      25             : 
      26             : /*!
      27             :  * \brief %Poloidal magnetic field for GRMHD initial data.
      28             :  *
      29             :  * The vector potential has the form
      30             :  *
      31             :  * \f{align*}{
      32             :  *  A_{\phi} = A_b \varpi^2 \max(p-p_{\mathrm{cut}}, 0)^{n_s} ,
      33             :  * \f}
      34             :  *
      35             :  * where \f$A_b\f$ controls the amplitude of the magnetic field,
      36             :  * \f$\varpi^2=x^2+y^2=r^2-z^2\f$ is the cylindrical radius,
      37             :  * \f$n_s\f$ controls the degree of differentiability, and
      38             :  * \f$p_{\mathrm{cut}}\f$ controls the pressure cutoff below which the magnetic
      39             :  * field is zero.
      40             :  *
      41             :  * In Cartesian coordinates the vector potential is:
      42             :  *
      43             :  * \f{align*}{
      44             :  *   A_x & = -\frac{y}{\varpi^2}A_\phi
      45             :  *            = -y A_b\max(p-p_{\mathrm{cut}}, 0)^{n_s}, \\
      46             :  *   A_y & = \frac{x}{\varpi^2}A_\phi
      47             :  *            = x A_b\max(p-p_{\mathrm{cut}}, 0)^{n_s}, \\
      48             :  *   A_z & = 0,
      49             :  * \f}
      50             :  *
      51             :  * On the region where the field is non-zero, the magnetic field is given by:
      52             :  *
      53             :  * \f{align*}{
      54             :  *   B^x & = -\frac{A_b n_s}{\sqrt{\gamma}}
      55             :  *        (p-p_{\mathrm{cut}})^{n_s-1} x \partial_z p \\
      56             :  *   B^x & = -\frac{A_b n_s}{\sqrt{\gamma}}
      57             :  *        (p-p_{\mathrm{cut}})^{n_s-1} y \partial_z p \\
      58             :  *   B^z & = \frac{A_b}{\sqrt{\gamma}}\left[
      59             :  *        2(p-p_{\mathrm{cut}})^{n_s}
      60             :  *        + n_s (p-p_{\mathrm{cut}})^{n_s-1} (x \partial_x p + y \partial_y p)
      61             :  *        \right]
      62             :  * \f}
      63             :  *
      64             :  * Taking the small-\f$r\f$ limit gives the magnetic field at the origin:
      65             :  *
      66             :  * \f{align*}{
      67             :  *   B^x&=0, \\
      68             :  *   B^y&=0, \\
      69             :  *   B^z&=\frac{A_b}{\sqrt{\gamma}}
      70             :  *        2(p-p_{\mathrm{cut}})^{n_s}.
      71             :  * \f}
      72             :  *
      73             :  * Note that the coordinates are relative to the `Center` passed in, so the
      74             :  * field can be centered about any arbitrary point. The field is also zero
      75             :  * outside of `MaxDistanceFromCenter`, so that compact support can be imposed if
      76             :  * necessary.
      77             :  *
      78             :  * \warning This assumes the magnetic field is initialized, both in size and
      79             :  * value, before being passed into the `variables` function. This is so that
      80             :  * multiple magnetic fields can be superposed. Each magnetic field
      81             :  * configuration does a `+=` to make this possible.
      82             :  */
      83           1 : class Poloidal : public InitialMagneticField {
      84             :  public:
      85           0 :   struct PressureExponent {
      86           0 :     using type = size_t;
      87           0 :     static constexpr Options::String help = {
      88             :         "The exponent n_s controlling the smoothness of the field"};
      89             :   };
      90             : 
      91           0 :   struct CutoffPressure {
      92           0 :     using type = double;
      93           0 :     static constexpr Options::String help = {
      94             :         "The pressure below which there is no magnetic field."};
      95           0 :     static type lower_bound() { return 0.0; }
      96             :   };
      97             : 
      98           0 :   struct VectorPotentialAmplitude {
      99           0 :     using type = double;
     100           0 :     static constexpr Options::String help = {
     101             :         "The amplitude A_b of the phi-component of the vector potential. This "
     102             :         "controls the magnetic field strength."};
     103           0 :     static type lower_bound() { return 0.0; }
     104             :   };
     105             : 
     106           0 :   struct Center {
     107           0 :     using type = std::array<double, 3>;
     108           0 :     static constexpr Options::String help = {
     109             :         "The center of the magnetic field."};
     110             :   };
     111             : 
     112           0 :   struct MaxDistanceFromCenter {
     113           0 :     using type = double;
     114           0 :     static constexpr Options::String help = {
     115             :         "The maximum distance from the center to compute the magnetic field. "
     116             :         "Everywhere outside the field is set to zero."};
     117           0 :     static type lower_bound() { return 0.0; }
     118             :   };
     119             : 
     120           0 :   using options =
     121             :       tmpl::list<PressureExponent, CutoffPressure, VectorPotentialAmplitude,
     122             :                  Center, MaxDistanceFromCenter>;
     123             : 
     124           0 :   static constexpr Options::String help = {"Poloidal initial magnetic field"};
     125             : 
     126           0 :   Poloidal() = default;
     127           0 :   Poloidal(const Poloidal& /*rhs*/) = default;
     128           0 :   Poloidal& operator=(const Poloidal& /*rhs*/) = default;
     129           0 :   Poloidal(Poloidal&& /*rhs*/) = default;
     130           0 :   Poloidal& operator=(Poloidal&& /*rhs*/) = default;
     131           0 :   ~Poloidal() override = default;
     132             : 
     133           0 :   Poloidal(size_t pressure_exponent, double cutoff_pressure,
     134             :            double vector_potential_amplitude, std::array<double, 3> center,
     135             :            double max_distance_from_center);
     136             : 
     137           0 :   auto get_clone() const -> std::unique_ptr<InitialMagneticField> override;
     138             : 
     139             :   /// \cond
     140             :   explicit Poloidal(CkMigrateMessage* msg);
     141             :   using PUP::able::register_constructor;
     142             :   WRAPPED_PUPable_decl_template(Poloidal);
     143             :   /// \endcond
     144             : 
     145             :   // NOLINTNEXTLINE(google-runtime-references)
     146           0 :   void pup(PUP::er& p) override;
     147             : 
     148             :   /// Retrieve magnetic fields at `(x)`
     149           1 :   void variables(gsl::not_null<tnsr::I<DataVector, 3>*> result,
     150             :                  const tnsr::I<DataVector, 3>& coords,
     151             :                  const Scalar<DataVector>& pressure,
     152             :                  const Scalar<DataVector>& sqrt_det_spatial_metric,
     153             :                  const tnsr::i<DataVector, 3>& deriv_pressure) const override;
     154             : 
     155             :   /// Retrieve magnetic fields at `(x)`
     156           1 :   void variables(gsl::not_null<tnsr::I<double, 3>*> result,
     157             :                  const tnsr::I<double, 3>& coords,
     158             :                  const Scalar<double>& pressure,
     159             :                  const Scalar<double>& sqrt_det_spatial_metric,
     160             :                  const tnsr::i<double, 3>& deriv_pressure) const override;
     161             : 
     162           0 :   bool is_equal(const InitialMagneticField& rhs) const override;
     163             : 
     164             :  private:
     165             :   template <typename DataType>
     166           0 :   void variables_impl(gsl::not_null<tnsr::I<DataType, 3>*> magnetic_field,
     167             :                       const tnsr::I<DataType, 3>& coords,
     168             :                       const Scalar<DataType>& pressure,
     169             :                       const Scalar<DataType>& sqrt_det_spatial_metric,
     170             :                       const tnsr::i<DataType, 3>& deriv_pressure) const;
     171             : 
     172           0 :   size_t pressure_exponent_ = std::numeric_limits<size_t>::max();
     173           0 :   double cutoff_pressure_ = std::numeric_limits<double>::signaling_NaN();
     174           0 :   double vector_potential_amplitude_ =
     175             :       std::numeric_limits<double>::signaling_NaN();
     176           0 :   std::array<double, 3> center_{{std::numeric_limits<double>::signaling_NaN(),
     177             :                                  std::numeric_limits<double>::signaling_NaN(),
     178             :                                  std::numeric_limits<double>::signaling_NaN()}};
     179           0 :   double max_distance_from_center_ =
     180             :       std::numeric_limits<double>::signaling_NaN();
     181             : 
     182           0 :   friend bool operator==(const Poloidal& lhs, const Poloidal& rhs);
     183           0 :   friend bool operator!=(const Poloidal& lhs, const Poloidal& rhs);
     184             : };
     185             : 
     186             : }  // namespace grmhd::AnalyticData::InitialMagneticFields

Generated by: LCOV version 1.14