SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/GrMhd/ValenciaDivClean - Characteristics.hpp Coverage Total Hit
Commit: a37d7b3c1803b88b537d2aef1c27ca5e6b499398 Lines: 48.0 % 25 12
Test Date: 2026-11-12 04:47:19
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 <cstddef>
       8              : 
       9              : #include "DataStructures/DataBox/Tag.hpp"
      10              : #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
      11              : #include "DataStructures/Tensor/TypeAliases.hpp"
      12              : #include "Domain/FaceNormal.hpp"
      13              : #include "Evolution/Systems/GrMhd/ValenciaDivClean/Tags.hpp"
      14              : #include "PointwiseFunctions/GeneralRelativity/TagsDeclarations.hpp"
      15              : #include "PointwiseFunctions/Hydro/EquationsOfState/EquationOfState.hpp"
      16              : #include "PointwiseFunctions/Hydro/TagsDeclarations.hpp"
      17              : #include "Utilities/Gsl.hpp"
      18              : #include "Utilities/TMPL.hpp"
      19              : 
      20              : /// \cond
      21              : class DataVector;
      22              : namespace Tags {
      23              : template <typename Tag>
      24              : struct Normalized;
      25              : }  // namespace Tags
      26              : /// \endcond
      27              : 
      28              : namespace grmhd {
      29              : namespace ValenciaDivClean {
      30              : /// @{
      31              : /*!
      32              :  * \brief Compute the characteristic speeds for the Valencia formulation of
      33              :  * GRMHD with divergence cleaning.
      34              :  *
      35              :  * Obtaining the exact form of the characteristic speeds involves the solution
      36              :  * of a nontrivial quartic equation for the fast and slow modes. Here we make
      37              :  * use of a common approximation in the literature (e.g. \cite Gammie2003)
      38              :  * where the resulting characteristic speeds are analogous to those of the
      39              :  * Valencia formulation of the 3-D relativistic Euler system
      40              :  * (see RelativisticEuler::Valencia::characteristic_speeds),
      41              :  *
      42              :  * \f{align*}
      43              :  * \lambda_2 &= \alpha \Lambda^- - \beta_n,\\
      44              :  * \lambda_{3, 4, 5, 6, 7} &= \alpha v_n - \beta_n,\\
      45              :  * \lambda_{8} &= \alpha \Lambda^+ - \beta_n,
      46              :  * \f}
      47              :  *
      48              :  * with the substitution
      49              :  *
      50              :  * \f{align*}
      51              :  * c_s^2 \longrightarrow c_s^2 + v_A^2(1 - c_s^2)
      52              :  * \f}
      53              :  *
      54              :  * in the definition of \f$\Lambda^\pm\f$. Here \f$v_A\f$ is the Alfvén
      55              :  * speed. In addition, two more speeds corresponding to the divergence cleaning
      56              :  * mode and the longitudinal magnetic field are added,
      57              :  *
      58              :  * \f{align*}
      59              :  * \lambda_1 = -\alpha - \beta_n,\\
      60              :  * \lambda_9 = \alpha - \beta_n.
      61              :  * \f}
      62              :  *
      63              :  * \note The ordering assumed here is such that, in the Newtonian limit,
      64              :  * the exact expressions for \f$\lambda_{2, 8}\f$, \f$\lambda_{3, 7}\f$,
      65              :  * and \f$\lambda_{4, 6}\f$ should reduce to the
      66              :  * corresponding fast modes, Alfvén modes, and slow modes, respectively.
      67              :  * See \cite Dedner2002 for a detailed description of the hyperbolic
      68              :  * characterization of Newtonian MHD.  In terms of the primitive variables:
      69              :  *
      70              :  * \f{align*}
      71              :  * v^2 &= \gamma_{mn} v^m v^n \\
      72              :  * c_s^2 &= \frac{1}{h} \left[ \left( \frac{\partial p}{\partial \rho}
      73              :  * \right)_\epsilon +
      74              :  * \frac{p}{\rho^2} \left(\frac{\partial p}{\partial \epsilon}
      75              :  * \right)_\rho \right] \\
      76              :  * v_A^2 &= \frac{b^2}{b^2 + \rho h} \\
      77              :  * b^2 &= \frac{1}{W^2} \gamma_{mn} B^m B^n + \left( \gamma_{mn} B^m v^n
      78              :  * \right)^2
      79              :  * \f}
      80              :  *
      81              :  * where \f$\gamma_{mn}\f$ is the spatial metric, \f$\rho\f$ is the rest
      82              :  * mass density, \f$W = 1/\sqrt{1-v_i v^i}\f$ is the Lorentz factor, \f$h = 1 +
      83              :  * \epsilon + \frac{p}{\rho}\f$ is the specific enthalpy, \f$v^i\f$ is the
      84              :  * spatial velocity, \f$\epsilon\f$ is the specific internal energy, \f$p\f$ is
      85              :  * the pressure, and \f$B^i\f$ is the spatial magnetic field measured by an
      86              :  * Eulerian observer.
      87              :  */
      88              : 
      89              : template <size_t ThermodynamicDim>
      90            1 : std::array<DataVector, 9> characteristic_speeds_approximate_mhd(
      91              :     const Scalar<DataVector>& rest_mass_density,
      92              :     const Scalar<DataVector>& electron_fraction,
      93              :     const Scalar<DataVector>& specific_internal_energy,
      94              :     const Scalar<DataVector>& specific_enthalpy,
      95              :     const tnsr::I<DataVector, 3, Frame::Inertial>& spatial_velocity,
      96              :     const Scalar<DataVector>& lorentz_factor,
      97              :     const tnsr::I<DataVector, 3, Frame::Inertial>& magnetic_field,
      98              :     const Scalar<DataVector>& lapse, const tnsr::I<DataVector, 3>& shift,
      99              :     const tnsr::ii<DataVector, 3, Frame::Inertial>& spatial_metric,
     100              :     const tnsr::i<DataVector, 3>& unit_normal,
     101              :     const EquationsOfState::EquationOfState<true, ThermodynamicDim>&
     102              :         equation_of_state);
     103              : 
     104              : template <size_t ThermodynamicDim>
     105            1 : void characteristic_speeds_approximate_mhd(
     106              :     gsl::not_null<std::array<DataVector, 9>*> char_speeds,
     107              :     const Scalar<DataVector>& rest_mass_density,
     108              :     const Scalar<DataVector>& electron_fraction,
     109              :     const Scalar<DataVector>& specific_internal_energy,
     110              :     const Scalar<DataVector>& specific_enthalpy,
     111              :     const tnsr::I<DataVector, 3, Frame::Inertial>& spatial_velocity,
     112              :     const Scalar<DataVector>& lorentz_factor,
     113              :     const tnsr::I<DataVector, 3, Frame::Inertial>& magnetic_field,
     114              :     const Scalar<DataVector>& lapse, const tnsr::I<DataVector, 3>& shift,
     115              :     const tnsr::ii<DataVector, 3, Frame::Inertial>& spatial_metric,
     116              :     const tnsr::i<DataVector, 3>& unit_normal,
     117              :     const EquationsOfState::EquationOfState<true, ThermodynamicDim>&
     118              :         equation_of_state);
     119              : /// @}
     120              : 
     121              : /*!
     122              :  * \brief Labels for the characteristic speeds of the relativistic hydrodynamics
     123              :  * system.
     124              :  *
     125              :  * \see `grmhd::ValenciaDivClean::characteristic_speeds_hydro`
     126              :  */
     127            1 : namespace HydroSpeed {
     128              : /// The smallest speed, $\lambda_-$
     129            1 : constexpr size_t LambdaMinus = 0;
     130              : /// The normal velocity, $v_n = n_i v^i$
     131            1 : constexpr size_t NormalDotVelocity = 1;
     132              : /// The largest speed, $\lambda_+$
     133            1 : constexpr size_t LambdaPlus = 2;
     134              : }  // namespace HydroSpeed
     135              : 
     136              : /// @{
     137              : /*!
     138              :  * \brief Compute the characteristic speeds for the relativistic hydrodynamics
     139              :  * system in the Eulerian frame.
     140              :  *
     141              :  * These are the eigenvalues of the flux Jacobian projected along a spatial
     142              :  * direction with unit normal \f$ s_i\f$, measured by an Eulerian observer.
     143              :  * They consist of four degenerate modes and two non-degenerate modes:
     144              :  *
     145              :  * \f{align*}
     146              :  * \lambda_\mathrm{deg} &= v_n ,\\
     147              :  * \lambda_{\pm} &=
     148              :  *   \frac{ (1 - c_s^2)\,v_n \pm c_s\,d / W^2 }
     149              :  *        { 1 - v^2 c_s^2 }.
     150              :  * \f}
     151              :  *
     152              :  * where
     153              :  *
     154              :  * \f{align*}
     155              :  * d &\equiv
     156              :  *   W\,\sqrt{ 1 - v^2 c_s^2 - v_n^2(1 - c_s^2) } .
     157              :  * \f}
     158              :  *
     159              :  * The variables are defined as:
     160              :  *
     161              :  * \f{align*}
     162              :  * v^2 &= \gamma_{mn} v^m v^n ,\\
     163              :  * v_n &= v^a s_a ,\\
     164              :  * W &= \frac{1}{\sqrt{1 - v^a v_a}} ,\\
     165              :  * h &= 1 + \epsilon + \frac{p}{\rho} ,\\
     166              :  * c_s^2 &= \frac{1}{h}\left(\chi + \kappa \frac{p}{\rho^2}\right) ,
     167              :  * \f}
     168              :  *
     169              :  * The returned tensor has index 0..2, in increasing order (see `HydroSpeed`):
     170              :  * - `characteristic_speeds.get(0)`: acoustic speed \f$\lambda_-\f$
     171              :  * - `characteristic_speeds.get(1)`: degenerate speed \f$v_n\f$
     172              :  * - `characteristic_speeds.get(2)`: acoustic speed \f$\lambda_+\f$
     173              :  *
     174              :  * \see `grmhd::ValenciaDivClean::numerical_characteristics` for how these
     175              :  * speeds are paired with characteristic modes and characteristic projectors.
     176              :  */
     177              : 
     178              : template <size_t ThermodynamicDim>
     179            1 : void characteristic_speeds_hydro(
     180              :     gsl::not_null<tnsr::i<DataVector, 3>*> characteristic_speeds,
     181              : 
     182              :     /* primitive variables */
     183              :     const tnsr::I<DataVector, 3, Frame::Inertial>& spatial_velocity,
     184              :     const Scalar<DataVector>& rest_mass_density,
     185              :     const Scalar<DataVector>& specific_internal_energy,
     186              :     const Scalar<DataVector>& electron_fraction,
     187              : 
     188              :     /* other helpful quantities */
     189              :     const Scalar<DataVector>& lorentz_factor,
     190              :     const Scalar<DataVector>& specific_enthalpy,
     191              :     const tnsr::ii<DataVector, 3, Frame::Inertial>& spatial_metric,
     192              :     const tnsr::i<DataVector, 3>& unit_normal,
     193              :     const EquationsOfState::EquationOfState<true, ThermodynamicDim>&
     194              :         equation_of_state);
     195              : 
     196              : template <size_t ThermodynamicDim>
     197            1 : tnsr::i<DataVector, 3> characteristic_speeds_hydro(
     198              :     const tnsr::I<DataVector, 3, Frame::Inertial>& spatial_velocity,
     199              :     const Scalar<DataVector>& rest_mass_density,
     200              :     const Scalar<DataVector>& specific_internal_energy,
     201              :     const Scalar<DataVector>& electron_fraction,
     202              :     const Scalar<DataVector>& lorentz_factor,
     203              :     const Scalar<DataVector>& specific_enthalpy,
     204              :     const tnsr::ii<DataVector, 3, Frame::Inertial>& spatial_metric,
     205              :     const tnsr::i<DataVector, 3>& unit_normal,
     206              :     const EquationsOfState::EquationOfState<true, ThermodynamicDim>&
     207              :         equation_of_state);
     208              : /// @}
     209              : 
     210              : /**
     211              :  * \brief Compute the characteristic matrix (flux Jacobian) for relativistic
     212              :  * hydrodynamics + composition ($Y_e$), in a given direction.
     213              :  *
     214              :  * The characteristic matrix is the Jacobian of the flux along the unit normal
     215              :  * $n_i$ with respect to the conserved variables $U_n$,
     216              :  * \begin{equation}
     217              :  *   A_{m}{}^{n} = \frac{\partial (n_i F^i_m)}{\partial U_n},
     218              :  * \end{equation}
     219              :  * evaluated with unit lapse and zero shift. With lapse $\alpha$ and shift
     220              :  * $\beta^i$, the physical characteristic speeds are $\alpha \lambda - \beta_n$,
     221              :  * where $\lambda$ are the eigenvalues of this matrix and
     222              :  * $\beta_n = n_i \beta^i$.
     223              :  *
     224              :  * The index $m$ labels the rows of the matrix (the flux components), and the
     225              :  * index $n$ labels its columns (the conserved variables). Both follow the order
     226              :  * $(D, S_i, \tau, D Y_e)$, which differs from the order of the system's
     227              :  * `variables_tag`.
     228              :  *
     229              :  * \note The normal must be unit with respect to the spatial metric.
     230              :  *
     231              :  * \note With a 2D equation of state, the pressure must be positive, since
     232              :  * $\kappa = \partial p / \partial \epsilon |_\rho$ is recovered from
     233              :  * $\kappa p / \rho^2$, the only form the 2D interface provides.
     234              :  *
     235              :  * \note The specific enthalpy must be consistent with the equation of state,
     236              :  * $h = 1 + \epsilon + p / \rho$. The matrix uses both $h$ and
     237              :  * $h - 1 = \epsilon + p / \rho$, which is computed from the equation of state
     238              :  * to avoid cancellation when $h \approx 1$.
     239              :  *
     240              :  * \see `grmhd::ValenciaDivClean::numerical_characteristics` for the
     241              :  * conventions relating this matrix to characteristic speeds, modes, and
     242              :  * projectors.
     243              :  *
     244              :  * \see `find_real_eigensystem` for the index conventions of the matrix.
     245              :  */
     246              : template <size_t ThermodynamicDim>
     247            1 : void flux_jacobian_hydro(
     248              :     gsl::not_null<tnsr::iJ<DataVector, 6>*> characteristic_matrix,
     249              : 
     250              :     /* primitive variables */
     251              :     const tnsr::I<DataVector, 3, Frame::Inertial>& spatial_velocity,
     252              :     const Scalar<DataVector>& rest_mass_density,
     253              :     const Scalar<DataVector>& specific_internal_energy,
     254              :     const Scalar<DataVector>& electron_fraction,
     255              : 
     256              :     /* other helpful quantities */
     257              :     const Scalar<DataVector>& lorentz_factor,
     258              :     const Scalar<DataVector>& specific_enthalpy,
     259              :     const tnsr::ii<DataVector, 3, Frame::Inertial>& spatial_metric,
     260              :     const tnsr::II<DataVector, 3, Frame::Inertial>& inv_spatial_metric,
     261              :     const tnsr::i<DataVector, 3>& unit_normal,
     262              :     const EquationsOfState::EquationOfState<true, ThermodynamicDim>&
     263              :         equation_of_state);
     264              : 
     265              : /**
     266              :  * \brief Compute numerical characteristic speeds (eigenvalues), characteristic
     267              :  * projectors (left eigenvectors), and characteristic modes (right eigenvectors)
     268              :  * in a given direction, from the primitive variables.
     269              :  *
     270              :  * \note Currently, this function only supports building the eigensystem for
     271              :  * relativistic hydrodynamics (no magnetic field) with composition dependence
     272              :  * ($Y_e$).
     273              :  *
     274              :  * The characteristic speeds $\lambda_{(i)}$ are the eigenvalues of the
     275              :  * characteristic matrix in a given direction, $A_{m}{}^{n}$. The characteristic
     276              :  * projectors $L^{im}$ and modes $R_{im}$ are its left and right eigenvectors,
     277              :  * with the index conventions of `find_real_eigensystem`. We provide the
     278              :  * characteristics in the following types:
     279              :  * - Eigenvalues $\lambda_{(i)}$: `tnsr::i<DataVector, 6> characteristic_speeds`
     280              :  * - Right eigenvectors $R_{in}$: `tnsr::ij<DataVector, 6> characteristic_modes`
     281              :  * - Left eigenvectors $L^{im}$: `tnsr::IJ<DataVector, 6>
     282              :  *   characteristic_projectors`
     283              :  *
     284              :  * We refer to the left eigenvectors as "projectors" because they are used to
     285              :  * project a state into the characteristic basis. Similarly, we refer to the
     286              :  * right eigenvectors as "modes" because they are used to reconstruct the state.
     287              :  * For example, consider a state vector $U_{m}$ that can be represented in the
     288              :  * characteristic basis as
     289              :  * \begin{equation}
     290              :  *   U_{m} = \sum_i w^{i} R_{im}.
     291              :  * \end{equation}
     292              :  * Then, the characteristic fields $w^{i}$ can be obtained by projecting the
     293              :  * state vector $U_{m}$ into the characteristic basis using the left
     294              :  * eigenvectors:
     295              :  * \begin{equation}
     296              :  *   w^{i} = \sum_m L^{im} U_{m}.
     297              :  * \end{equation}
     298              :  *
     299              :  * The eigenvalues are in increasing order. The eigenvectors are normalized so
     300              :  * that $\sum_m L^{im} R_{jm} = \delta^{i}_{j}$. The right eigenvectors are not
     301              :  * unit vectors.
     302              :  *
     303              :  * \see `find_real_eigensystem` for the index conventions and for how this
     304              :  * eigensystem is computed at each grid point.
     305              :  */
     306              : template <size_t ThermodynamicDim>
     307            1 : void numerical_characteristics(
     308              :     gsl::not_null<tnsr::i<DataVector, 6>*> characteristic_speeds,
     309              :     gsl::not_null<tnsr::ij<DataVector, 6>*> characteristic_modes,
     310              :     gsl::not_null<tnsr::IJ<DataVector, 6>*> characteristic_projectors,
     311              : 
     312              :     /* primitive variables */
     313              :     const tnsr::I<DataVector, 3, Frame::Inertial>& spatial_velocity,
     314              :     const Scalar<DataVector>& rest_mass_density,
     315              :     const Scalar<DataVector>& specific_internal_energy,
     316              :     const Scalar<DataVector>& electron_fraction,
     317              : 
     318              :     /* other helpful quantities */
     319              :     const Scalar<DataVector>& lorentz_factor,
     320              :     const Scalar<DataVector>& specific_enthalpy,
     321              :     const tnsr::ii<DataVector, 3, Frame::Inertial>& spatial_metric,
     322              :     const tnsr::II<DataVector, 3, Frame::Inertial>& inv_spatial_metric,
     323              :     const tnsr::i<DataVector, 3>& unit_normal,
     324              :     const EquationsOfState::EquationOfState<true, ThermodynamicDim>&
     325              :         equation_of_state);
     326              : 
     327            1 : namespace Tags {
     328              : /// \brief Compute the characteristic speeds for the Valencia formulation of
     329              : /// GRMHD with divergence cleaning.
     330              : ///
     331              : /// \details see grmhd::ValenciaDivClean::characteristic_speeds
     332            1 : struct CharacteristicSpeedsCompute : Tags::CharacteristicSpeeds,
     333              :                                      db::ComputeTag {
     334            0 :   using base = Tags::CharacteristicSpeeds;
     335            0 :   using argument_tags =
     336              :       tmpl::list<hydro::Tags::RestMassDensity<DataVector>,
     337              :                  hydro::Tags::ElectronFraction<DataVector>,
     338              :                  hydro::Tags::SpecificInternalEnergy<DataVector>,
     339              :                  hydro::Tags::SpecificEnthalpy<DataVector>,
     340              :                  hydro::Tags::SpatialVelocity<DataVector, 3>,
     341              :                  hydro::Tags::LorentzFactor<DataVector>,
     342              :                  hydro::Tags::MagneticField<DataVector, 3>,
     343              :                  gr::Tags::Lapse<DataVector>, gr::Tags::Shift<DataVector, 3>,
     344              :                  gr::Tags::SpatialMetric<DataVector, 3>,
     345              :                  ::Tags::Normalized<domain::Tags::UnnormalizedFaceNormal<3>>,
     346              :                  hydro::Tags::GrmhdEquationOfState>;
     347              : 
     348            0 :   using volume_tags = tmpl::list<hydro::Tags::GrmhdEquationOfState>;
     349              : 
     350            0 :   using return_type = std::array<DataVector, 9>;
     351              : 
     352              :   template <size_t ThermodynamicDim>
     353            0 :   void function(gsl::not_null<return_type*> result,
     354              :                 const Scalar<DataVector>& rest_mass_density,
     355              :                 const Scalar<DataVector>& /* electron_fraction */,
     356              :                 const Scalar<DataVector>& specific_internal_energy,
     357              :                 const Scalar<DataVector>& specific_enthalpy,
     358              :                 const tnsr::I<DataVector, 3, Frame::Inertial>& spatial_velocity,
     359              :                 const Scalar<DataVector>& lorentz_factor,
     360              :                 const tnsr::I<DataVector, 3, Frame::Inertial>& magnetic_field,
     361              :                 const Scalar<DataVector>& lapse,
     362              :                 const tnsr::I<DataVector, 3>& shift,
     363              :                 const tnsr::ii<DataVector, 3, Frame::Inertial>& spatial_metric,
     364              :                 const tnsr::i<DataVector, 3>& unit_normal,
     365              :                 const EquationsOfState::EquationOfState<true, ThermodynamicDim>&
     366              :                     equation_of_state);
     367              : };
     368              : 
     369            0 : struct LargestCharacteristicSpeed : db::SimpleTag {
     370            0 :   using type = double;
     371              : };
     372              : 
     373            0 : struct ComputeLargestCharacteristicSpeed : db::ComputeTag,
     374              :                                            LargestCharacteristicSpeed {
     375            0 :   using argument_tags =
     376              :       tmpl::list<gr::Tags::Lapse<DataVector>, gr::Tags::Shift<DataVector, 3>,
     377              :                  gr::Tags::SpatialMetric<DataVector, 3>>;
     378            0 :   using return_type = double;
     379            0 :   using base = LargestCharacteristicSpeed;
     380            0 :   static void function(gsl::not_null<double*> speed,
     381              :                        const Scalar<DataVector>& lapse,
     382              :                        const tnsr::I<DataVector, 3>& shift,
     383              :                        const tnsr::ii<DataVector, 3>& spatial_metric) {
     384              :     const auto shift_magnitude = magnitude(shift, spatial_metric);
     385              :     *speed = max(get(shift_magnitude) + get(lapse));
     386              :   }
     387              : };
     388              : }  // namespace Tags
     389              : }  // namespace ValenciaDivClean
     390              : }  // namespace grmhd
        

Generated by: LCOV version 2.0-1