SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticData/GrMhd - MagnetizedFmDisk.hpp Hit Total Coverage
Commit: aabde07399ba7837e5db64eedfd0a21f31f96922 Lines: 6 44 13.6 %
Date: 2024-04-26 02:38:13
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/AnalyticData.hpp"
      12             : #include "PointwiseFunctions/AnalyticData/GrMhd/AnalyticData.hpp"
      13             : #include "PointwiseFunctions/AnalyticSolutions/RelativisticEuler/FishboneMoncriefDisk.hpp"
      14             : #include "PointwiseFunctions/GeneralRelativity/KerrSchildCoords.hpp"
      15             : #include "PointwiseFunctions/Hydro/EquationsOfState/PolytropicFluid.hpp"  // IWYU pragma: keep
      16             : #include "PointwiseFunctions/Hydro/TagsDeclarations.hpp"
      17             : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
      18             : #include "Utilities/Serialization/CharmPupable.hpp"
      19             : #include "Utilities/TMPL.hpp"
      20             : #include "Utilities/TaggedTuple.hpp"
      21             : 
      22             : // IWYU pragma:  no_include <pup.h>
      23             : 
      24             : /// \cond
      25             : namespace PUP {
      26             : class er;  // IWYU pragma: keep
      27             : }  // namespace PUP
      28             : /// \endcond
      29             : 
      30             : namespace grmhd::AnalyticData {
      31             : 
      32             : /*!
      33             :  * \brief Magnetized fluid disk orbiting a Kerr black hole.
      34             :  *
      35             :  * In the context of simulating accretion disks, this class implements a widely
      36             :  * used (e.g. \cite Gammie2003, \cite Porth2016rfi, \cite White2015omx)
      37             :  * initial setup for the GRMHD variables, consisting of a Fishbone-Moncrief disk
      38             :  * \cite Fishbone1976apj (see also
      39             :  * RelativisticEuler::Solutions::FishboneMoncriefDisk),
      40             :  * threaded by a weak poloidal magnetic field. The magnetic field is constructed
      41             :  * from an axially symmetric toroidal magnetic potential which, in Kerr
      42             :  * ("spherical Kerr-Schild") coordinates, has the form
      43             :  *
      44             :  * \f{align*}
      45             :  * A_\phi(r,\theta) \propto \text{max}(\rho(r,\theta) - \rho_\text{thresh}, 0),
      46             :  * \f}
      47             :  *
      48             :  * where \f$\rho_\text{thresh}\f$ is a user-specified threshold density that
      49             :  * confines the magnetic flux to exist inside of the fluid disk only. A commonly
      50             :  * used value for this parameter is
      51             :  * \f$\rho_\text{thresh} = 0.2\rho_\text{max}\f$, where \f$\rho_\text{max}\f$
      52             :  * is the maximum value of
      53             :  * the rest mass density in the disk. Using this potential, the Eulerian
      54             :  * magnetic field takes the form
      55             :  *
      56             :  * \f{align*}
      57             :  * B^r = \frac{F_{\theta\phi}}{\sqrt{\gamma}},\quad
      58             :  * B^\theta = \frac{F_{\phi r}}{\sqrt{\gamma}},\quad B^\phi = 0,
      59             :  * \f}
      60             :  *
      61             :  * where \f$F_{ij} = \partial_i A_j - \partial_j A_i\f$ are the spatial
      62             :  * components of the Faraday tensor, and \f$\gamma\f$ is the determinant of the
      63             :  * spatial metric. The magnetic field is then normalized so that the
      64             :  * plasma-\f$\beta\f$ parameter, \f$\beta = 2p/b^2\f$, equals some value
      65             :  * specified by the user. Here, \f$p\f$ is the fluid pressure, and
      66             :  *
      67             :  * \f{align*}
      68             :  * b^2 = b^\mu b_\mu = \frac{B_iB^i}{W^2} + (B^iv_i)^2
      69             :  * \f}
      70             :  *
      71             :  * is the norm of the magnetic field in the fluid frame, with \f$v_i\f$ being
      72             :  * the spatial velocity, and \f$W\f$ the Lorentz factor.
      73             :  *
      74             :  * \note When using Kerr-Schild coordinates, the horizon that is at
      75             :  * constant \f$r\f$ is not spherical, but instead spheroidal. This could make
      76             :  * application of boundary condition and computing various fluxes
      77             :  * across the horizon more complicated than they need to be.
      78             :  * Thus, similar to RelativisticEuler::Solutions::FishboneMoncriefDisk
      79             :  * we use Spherical Kerr-Schild coordinates,
      80             :  * see gr::Solutions::SphericalKerrSchild, in which constant \f$r\f$
      81             :  * is spherical. Because we compute variables in Kerr-Schild coordinates,
      82             :  * there is a necessary extra step of transforming them back to
      83             :  * Spherical Kerr-Schild coordinates.
      84             :  *
      85             :  * \warning Spherical Kerr-Schild coordinates and "spherical Kerr-Schild"
      86             :  * coordinates are not same.
      87             :  *
      88             :  */
      89           1 : class MagnetizedFmDisk : public virtual evolution::initial_data::InitialData,
      90             :                          public MarkAsAnalyticData {
      91             :  private:
      92           0 :   using FmDisk = RelativisticEuler::Solutions::FishboneMoncriefDisk;
      93             : 
      94             :  public:
      95             :   /// The rest mass density (in units of the maximum rest mass density in the
      96             :   /// disk) below which the matter in the disk is initially unmagetized.
      97           1 :   struct ThresholdDensity {
      98           0 :     using type = double;
      99           0 :     static constexpr Options::String help = {
     100             :         "Frac. rest mass density below which B-field vanishes."};
     101           0 :     static type lower_bound() { return 0.0; }
     102           0 :     static type upper_bound() { return 1.0; }
     103             :   };
     104             :   /// The maximum-magnetic-pressure-to-maximum-fluid-pressure ratio.
     105           1 :   struct InversePlasmaBeta {
     106           0 :     using type = double;
     107           0 :     static constexpr Options::String help = {
     108             :         "Ratio of max magnetic pressure to max fluid pressure."};
     109           0 :     static type lower_bound() { return 0.0; }
     110             :   };
     111             :   /// Grid resolution used in magnetic field normalization.
     112           1 :   struct BFieldNormGridRes {
     113           0 :     using type = size_t;
     114           0 :     static constexpr Options::String help = {
     115             :         "Grid Resolution for b-field normalization."};
     116           0 :     static type suggested_value() { return 255; }
     117           0 :     static type lower_bound() { return 4; }
     118             :   };
     119             : 
     120             :   // Unlike the other analytic data classes, we cannot get these from the
     121             :   // `AnalyticDataBase` because this case causes clang-tidy to believe that
     122             :   // there is an ambiguous inheritance problem
     123           0 :   static constexpr size_t volume_dim = 3_st;
     124             : 
     125             :   template <typename DataType>
     126           0 :   using tags =
     127             :       tmpl::push_back<typename gr::AnalyticSolution<3>::template tags<DataType>,
     128             :                       hydro::Tags::RestMassDensity<DataType>,
     129             :                       hydro::Tags::SpecificInternalEnergy<DataType>,
     130             :                       hydro::Tags::Temperature<DataType>,
     131             :                       hydro::Tags::Pressure<DataType>,
     132             :                       hydro::Tags::SpatialVelocity<DataType, 3>,
     133             :                       hydro::Tags::MagneticField<DataType, 3>,
     134             :                       hydro::Tags::DivergenceCleaningField<DataType>,
     135             :                       hydro::Tags::LorentzFactor<DataType>,
     136             :                       hydro::Tags::SpecificEnthalpy<DataType>>;
     137             : 
     138           0 :   using options = tmpl::push_back<FmDisk::options, ThresholdDensity,
     139             :                                   InversePlasmaBeta, BFieldNormGridRes>;
     140             : 
     141           0 :   static constexpr Options::String help = {
     142             :       "Magnetized Fishbone-Moncrief disk."};
     143             : 
     144           0 :   MagnetizedFmDisk() = default;
     145           0 :   MagnetizedFmDisk(const MagnetizedFmDisk& /*rhs*/) = default;
     146           0 :   MagnetizedFmDisk& operator=(const MagnetizedFmDisk& /*rhs*/) = default;
     147           0 :   MagnetizedFmDisk(MagnetizedFmDisk&& /*rhs*/) = default;
     148           0 :   MagnetizedFmDisk& operator=(MagnetizedFmDisk&& /*rhs*/) = default;
     149           0 :   ~MagnetizedFmDisk() override = default;
     150             : 
     151           0 :   MagnetizedFmDisk(
     152             :       double bh_mass, double bh_dimless_spin, double inner_edge_radius,
     153             :       double max_pressure_radius, double polytropic_constant,
     154             :       double polytropic_exponent, double threshold_density,
     155             :       double inverse_plasma_beta,
     156             :       size_t normalization_grid_res = BFieldNormGridRes::suggested_value());
     157             : 
     158           0 :   auto get_clone() const
     159             :       -> std::unique_ptr<evolution::initial_data::InitialData> override;
     160             : 
     161             :   /// \cond
     162             :   explicit MagnetizedFmDisk(CkMigrateMessage* msg);
     163             :   using PUP::able::register_constructor;
     164             :   WRAPPED_PUPable_decl_template(MagnetizedFmDisk);
     165             :   /// \endcond
     166             : 
     167             :   // Overload the variables function from the base class.
     168           0 :   using equation_of_state_type = typename FmDisk::equation_of_state_type;
     169             : 
     170             :   /// @{
     171             :   /// The variables in Cartesian Kerr-Schild coordinates at `(x, t)`.
     172             :   template <typename DataType, typename... Tags>
     173           1 :   tuples::TaggedTuple<Tags...> variables(const tnsr::I<DataType, 3>& x,
     174             :                                          tmpl::list<Tags...> /*meta*/) const {
     175             :     // Can't store IntermediateVariables as member variable because we
     176             :     // need to be threadsafe.
     177             :     typename FmDisk::IntermediateVariables<DataType> vars(x);
     178             :     return {std::move(get<Tags>([this, &x, &vars]() {
     179             :       if constexpr (std::is_same_v<hydro::Tags::MagneticField<DataType, 3>,
     180             :                                    Tags>) {
     181             :         return variables(x, tmpl::list<Tags>{}, make_not_null(&vars));
     182             :       } else {
     183             :         return fm_disk_.variables(x, tmpl::list<Tags>{}, make_not_null(&vars));
     184             :       }
     185             :     }()))...};
     186             :   }
     187             : 
     188             :   template <typename DataType, typename Tag>
     189           1 :   tuples::TaggedTuple<Tag> variables(const tnsr::I<DataType, 3>& x,
     190             :                                      tmpl::list<Tag> /*meta*/) const {
     191             :     // Can't store IntermediateVariables as member variable because we need to
     192             :     // be threadsafe.
     193             :     typename FmDisk::IntermediateVariables<DataType> vars(x);
     194             :     if constexpr (std::is_same_v<hydro::Tags::MagneticField<DataType, 3>,
     195             :                                  Tag>) {
     196             :       return variables(x, tmpl::list<Tag>{}, make_not_null(&vars));
     197             :     } else {
     198             :       return fm_disk_.variables(x, tmpl::list<Tag>{}, make_not_null(&vars));
     199             :     }
     200             :   }
     201             :   /// @}
     202             : 
     203             :   // NOLINTNEXTLINE(google-runtime-references)
     204           0 :   void pup(PUP::er& /*p*/) override;
     205             : 
     206           0 :   const equation_of_state_type& equation_of_state() const {
     207             :     return fm_disk_.equation_of_state();
     208             :   }
     209             : 
     210             :  private:
     211             :   template <typename DataType>
     212           0 :   auto variables(const tnsr::I<DataType, 3>& x,
     213             :                  tmpl::list<hydro::Tags::MagneticField<DataType, 3>> /*meta*/,
     214             :                  gsl::not_null<FmDisk::IntermediateVariables<DataType>*> vars)
     215             :       const -> tuples::TaggedTuple<hydro::Tags::MagneticField<DataType, 3>>;
     216             : 
     217             :   template <typename DataType>
     218           0 :   tnsr::I<DataType, 3> unnormalized_magnetic_field(
     219             :       const tnsr::I<DataType, 3>& x) const;
     220             : 
     221           0 :   friend bool operator==(const MagnetizedFmDisk& lhs,
     222             :                          const MagnetizedFmDisk& rhs);
     223             : 
     224           0 :   RelativisticEuler::Solutions::FishboneMoncriefDisk fm_disk_{};
     225           0 :   double threshold_density_ = std::numeric_limits<double>::signaling_NaN();
     226           0 :   double inverse_plasma_beta_ = std::numeric_limits<double>::signaling_NaN();
     227           0 :   double b_field_normalization_ = std::numeric_limits<double>::signaling_NaN();
     228           0 :   size_t normalization_grid_res_ = 255;
     229           0 :   gr::KerrSchildCoords kerr_schild_coords_{};
     230             : };
     231             : 
     232           0 : bool operator!=(const MagnetizedFmDisk& lhs, const MagnetizedFmDisk& rhs);
     233             : 
     234             : }  // namespace grmhd::AnalyticData

Generated by: LCOV version 1.14