SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/GeneralizedHarmonic - Constraints.hpp Hit Total Coverage
Commit: 3c072f0ce967e2e56649d3fa12aa2a0e4fe2a42e Lines: 23 47 48.9 %
Date: 2024-04-23 20:50:18
Legend: Lines: hit not hit

          Line data    Source code
       1           1 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : ///\file
       5             : /// Defines functions to calculate the generalized harmonic constraints
       6             : 
       7             : #pragma once
       8             : 
       9             : #include <cstddef>
      10             : 
      11             : #include "DataStructures/DataBox/Prefixes.hpp"
      12             : #include "DataStructures/DataBox/Tag.hpp"
      13             : #include "DataStructures/DataVector.hpp"
      14             : #include "DataStructures/Tensor/TypeAliases.hpp"
      15             : #include "Evolution/Systems/GeneralizedHarmonic/ConstraintDamping/Tags.hpp"
      16             : #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
      17             : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
      18             : #include "Utilities/SetNumberOfGridPoints.hpp"
      19             : #include "Utilities/TMPL.hpp"
      20             : 
      21             : /// \cond
      22             : namespace gsl {
      23             : template <typename T>
      24             : class not_null;
      25             : }  // namespace gsl
      26             : /// \endcond
      27             : 
      28             : namespace gh {
      29             : /// @{
      30             : /*!
      31             :  * \brief Computes the generalized-harmonic 3-index constraint.
      32             :  *
      33             :  * \details Computes the generalized-harmonic 3-index constraint,
      34             :  * \f$C_{iab} = \partial_i\psi_{ab} - \Phi_{iab},\f$ which is
      35             :  * given by Eq. (26) of \cite Lindblom2005qh
      36             :  */
      37             : template <typename DataType, size_t SpatialDim, typename Frame>
      38           1 : tnsr::iaa<DataType, SpatialDim, Frame> three_index_constraint(
      39             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
      40             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi);
      41             : 
      42             : template <typename DataType, size_t SpatialDim, typename Frame>
      43           1 : void three_index_constraint(
      44             :     gsl::not_null<tnsr::iaa<DataType, SpatialDim, Frame>*> constraint,
      45             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
      46             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi);
      47             : /// @}
      48             : 
      49             : /// @{
      50             : /*!
      51             :  * \brief Computes the generalized-harmonic gauge constraint.
      52             :  *
      53             :  * \details Computes the generalized-harmonic gauge constraint
      54             :  * [Eq. (40) of \cite Lindblom2005qh],
      55             :  * \f[
      56             :  * C_a = H_a + g^{ij} \Phi_{ija} + t^b \Pi_{ba}
      57             :  * - \frac{1}{2} g^i_a \psi^{bc} \Phi_{ibc}
      58             :  * - \frac{1}{2} t_a \psi^{bc} \Pi_{bc},
      59             :  * \f]
      60             :  * where \f$H_a\f$ is the gauge function,
      61             :  * \f$\psi_{ab}\f$ is the spacetime metric,
      62             :  * \f$\Pi_{ab}=-t^c\partial_c \psi_{ab}\f$, and
      63             :  * \f$\Phi_{iab} = \partial_i\psi_{ab}\f$; \f$t^a\f$ is the timelike unit
      64             :  * normal vector to the spatial slice, \f$g^{ij}\f$ is the inverse spatial
      65             :  * metric, and \f$g^b_c = \delta^b_c + t^b t_c\f$.
      66             :  */
      67             : template <typename DataType, size_t SpatialDim, typename Frame>
      68           1 : tnsr::a<DataType, SpatialDim, Frame> gauge_constraint(
      69             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
      70             :     const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
      71             :     const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
      72             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
      73             :     const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
      74             :     const tnsr::aa<DataType, SpatialDim, Frame>& pi,
      75             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi);
      76             : 
      77             : template <typename DataType, size_t SpatialDim, typename Frame>
      78           1 : void gauge_constraint(
      79             :     gsl::not_null<tnsr::a<DataType, SpatialDim, Frame>*> constraint,
      80             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
      81             :     const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
      82             :     const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
      83             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
      84             :     const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
      85             :     const tnsr::aa<DataType, SpatialDim, Frame>& pi,
      86             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi);
      87             : /// @}
      88             : 
      89             : /// @{
      90             : /*!
      91             :  * \brief Computes the generalized-harmonic 2-index constraint.
      92             :  *
      93             :  * \details Computes the generalized-harmonic 2-index constraint
      94             :  * [Eq. (44) of \cite Lindblom2005qh],
      95             :  * \f{eqnarray}{
      96             :  * C_{ia} &\equiv& g^{jk}\partial_j \Phi_{ika}
      97             :  * - \frac{1}{2} g_a^j\psi^{cd}\partial_j \Phi_{icd}
      98             :  * + t^b \partial_i \Pi_{ba}
      99             :  * - \frac{1}{2} t_a \psi^{cd}\partial_i\Pi_{cd}
     100             :  * \nonumber\\&&
     101             :  * + \partial_i H_a
     102             :  * + \frac{1}{2} g_a^j \Phi_{jcd} \Phi_{ief}
     103             :  * \psi^{ce}\psi^{df}
     104             :  * + \frac{1}{2} g^{jk} \Phi_{jcd} \Phi_{ike}
     105             :  * \psi^{cd}t^e t_a
     106             :  * \nonumber\\&&
     107             :  * - g^{jk}g^{mn}\Phi_{jma}\Phi_{ikn}
     108             :  * + \frac{1}{2} \Phi_{icd} \Pi_{be} t_a
     109             :  *                             \left(\psi^{cb}\psi^{de}
     110             :  *                       +\frac{1}{2}\psi^{be} t^c t^d\right)
     111             :  * \nonumber\\&&
     112             :  * - \Phi_{icd} \Pi_{ba} t^c \left(\psi^{bd}
     113             :  *                             +\frac{1}{2} t^b t^d\right)
     114             :  * + \frac{1}{2} \gamma_2 \left(t_a \psi^{cd}
     115             :  * - 2 \delta^c_a t^d\right) C_{icd}.
     116             :  * \f}
     117             :  * where \f$H_a\f$ is the gauge function,
     118             :  * \f$\psi_{ab}\f$ is the spacetime metric,
     119             :  * \f$\Pi_{ab}=-t^c\partial_c \psi_{ab}\f$, and
     120             :  * \f$\Phi_{iab} = \partial_i\psi_{ab}\f$; \f$t^a\f$ is the timelike unit
     121             :  * normal vector to the spatial slice, \f$g^{ij}\f$ is the inverse spatial
     122             :  * metric, and \f$g^b_c = \delta^b_c + t^b t_c\f$.
     123             :  */
     124             : template <typename DataType, size_t SpatialDim, typename Frame>
     125           1 : tnsr::ia<DataType, SpatialDim, Frame> two_index_constraint(
     126             :     const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
     127             :     const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
     128             :     const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
     129             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     130             :     const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
     131             :     const tnsr::aa<DataType, SpatialDim, Frame>& pi,
     132             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
     133             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     134             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     135             :     const Scalar<DataType>& gamma2,
     136             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint);
     137             : 
     138             : template <typename DataType, size_t SpatialDim, typename Frame>
     139           1 : void two_index_constraint(
     140             :     gsl::not_null<tnsr::ia<DataType, SpatialDim, Frame>*> constraint,
     141             :     const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
     142             :     const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
     143             :     const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
     144             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     145             :     const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
     146             :     const tnsr::aa<DataType, SpatialDim, Frame>& pi,
     147             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
     148             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     149             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     150             :     const Scalar<DataType>& gamma2,
     151             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint);
     152             : /// @}
     153             : 
     154             : /// @{
     155             : /*!
     156             :  * \brief Computes the generalized-harmonic 4-index constraint.
     157             :  *
     158             :  * \details Computes the independent components of the generalized-harmonic
     159             :  * 4-index constraint. The constraint itself is given by Eq. (45) of
     160             :  * \cite Lindblom2005qh,
     161             :  * \f{eqnarray}{
     162             :  * C_{ijab} = 2 \partial_{[i}\Phi_{j]ab},
     163             :  * \f}
     164             :  * where \f$\Phi_{iab} = \partial_i\psi_{ab}\f$. Because the constraint is
     165             :  * antisymmetric on the two spatial indices, here we compute and store
     166             :  * only the independent components of \f$C_{ijab}\f$. Specifically, we
     167             :  * compute
     168             :  * \f{eqnarray}{
     169             :  * D_{iab} \equiv \frac{1}{2} \epsilon_{i}{}^{jk} C_{jkab}
     170             :  * = \epsilon_{i}{}^{jk} \partial_j \Phi_{kab},
     171             :  * \f}
     172             :  * where \f$\epsilon_{ijk}\f$ is the flat-space Levi-Civita symbol,
     173             :  * which is raised and lowered with the Kronecker delta.
     174             :  * In terms
     175             :  * of \f$D_{iab}\f$, the full 4-index constraint is
     176             :  * \f{eqnarray}{
     177             :  * C_{jkab} = \epsilon^{i}{}_{jk} D_{iab}.
     178             :  * \f}
     179             :  */
     180             : template <typename DataType, size_t SpatialDim, typename Frame>
     181           1 : tnsr::iaa<DataType, SpatialDim, Frame> four_index_constraint(
     182             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi);
     183             : 
     184             : template <typename DataType, size_t SpatialDim, typename Frame>
     185           1 : void four_index_constraint(
     186             :     gsl::not_null<tnsr::iaa<DataType, SpatialDim, Frame>*> constraint,
     187             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi);
     188             : /// @}
     189             : 
     190             : /// @{
     191             : /*!
     192             :  * \brief Computes the generalized-harmonic F constraint.
     193             :  *
     194             :  * \details Computes the generalized-harmonic F constraint
     195             :  * [Eq. (43) of \cite Lindblom2005qh],
     196             :  * \f{eqnarray}{
     197             :  * {\cal F}_a &\equiv&
     198             :  * \frac{1}{2} g_a^i \psi^{bc}\partial_i \Pi_{bc}
     199             :  * - g^{ij} \partial_i \Pi_{ja}
     200             :  * - g^{ij} t^b \partial_i \Phi_{jba}
     201             :  * + \frac{1}{2} t_a \psi^{bc} g^{ij} \partial_i \Phi_{jbc}
     202             :  * \nonumber \\ &&
     203             :  * + t_a g^{ij} \partial_i H_j
     204             :  * + g_a^i \Phi_{ijb} g^{jk}\Phi_{kcd} \psi^{bd} t^c
     205             :  * - \frac{1}{2} g_a^i \Phi_{ijb} g^{jk}
     206             :  *   \Phi_{kcd} \psi^{cd} t^b
     207             :  * \nonumber \\ &&
     208             :  * - g_a^i t^b \partial_i H_b
     209             :  * + g^{ij} \Phi_{icd} \Phi_{jba} \psi^{bc} t^d
     210             :  * - \frac{1}{2} t_a g^{ij} g^{mn} \Phi_{imc} \Phi_{njd}\psi^{cd}
     211             :  * \nonumber \\ &&
     212             :  * - \frac{1}{4}  t_a g^{ij}\Phi_{icd}\Phi_{jbe}
     213             :  *    \psi^{cb}\psi^{de}
     214             :  * + \frac{1}{4}  t_a \Pi_{cd} \Pi_{be}
     215             :  *    \psi^{cb}\psi^{de}
     216             :  * - g^{ij} H_i \Pi_{ja}
     217             :  * \nonumber \\ &&
     218             :  * - t^b g^{ij} \Pi_{b i} \Pi_{ja}
     219             :  * - \frac{1}{4}  g_a^i \Phi_{icd} t^c t^d \Pi_{be}
     220             :  *   \psi^{be}
     221             :  * + \frac{1}{2} t_a \Pi_{cd} \Pi_{be}\psi^{ce}
     222             :  *   t^d t^b
     223             :  * \nonumber \\ &&
     224             :  * + g_a^i \Phi_{icd} \Pi_{be} t^c t^b \psi^{de}
     225             :  * - g^{ij}\Phi_{iba} t^b \Pi_{je} t^e
     226             :  * - \frac{1}{2} g^{ij}\Phi_{icd} t^c t^d \Pi_{ja}
     227             :  * \nonumber \\ &&
     228             :  * - g^{ij} H_i \Phi_{jba} t^b
     229             :  * + g_{a}^i \Phi_{icd} H_b \psi^{bc} t^d
     230             :  * +\gamma_2\bigl(g^{id}{\cal C}_{ida}
     231             :  * -\frac{1}{2}  g_a^i\psi^{cd}{\cal C}_{icd}\bigr)
     232             :  * \nonumber \\ &&
     233             :  * + \frac{1}{2} t_a \Pi_{cd}\psi^{cd} H_b t^b
     234             :  * - t_a g^{ij} \Phi_{ijc} H_d \psi^{cd}
     235             :  * +\frac{1}{2}  t_a g^{ij} H_i \Phi_{jcd}\psi^{cd}
     236             :  * \nonumber \\ &&
     237             :  * - 16 \pi t^a T_{a b}
     238             :  * \f}
     239             :  * where \f$H_a\f$ is the gauge function,
     240             :  * \f$\psi_{ab}\f$ is the spacetime metric,
     241             :  * \f$\Pi_{ab}=-t^c\partial_c \psi_{ab}\f$, and
     242             :  * \f$\Phi_{iab} = \partial_i\psi_{ab}\f$; \f$t^a\f$ is the timelike unit
     243             :  * normal vector to the spatial slice, \f$g^{ij}\f$ is the inverse spatial
     244             :  * metric, \f$g^b_c = \delta^b_c + t^b t_c\f$, and \f$T_{a b}\f$ is the
     245             :  * stress-energy tensor if nonzero (if using the overload with no stress-energy
     246             :  * tensor provided, the stress energy term is omitted).
     247             :  *
     248             :  * To justify the stress-energy contribution to the F constraint, note that
     249             :  * the stress-energy tensor appears in the dynamics of the Generalized
     250             :  * Harmonic system only through \f$\partial_t \Pi_{a b}\f$.
     251             :  * That dependence arises from (using \f$\dots\f$ to indicate collections of
     252             :  * terms that are known to be independent of the stress-energy tensor):
     253             :  *
     254             :  * \f[
     255             :  * {\cal F}_a = \dots \alpha^{-1}(\partial_t {\cal C}_a),
     256             :  * \f]
     257             :  *
     258             :  * where
     259             :  *
     260             :  * \f[
     261             :  * {\cal C}_a = H_a + g^{i j} \Phi_{ij a} + t^b \Pi_{ba}
     262             :  * - \frac{1}{2} g_a{}^i \psi^{bc} \Phi_{i b c}
     263             :  * - \frac{1}{2} t_a \psi^{bc} \Pi_{b c}.
     264             :  * \f].
     265             :  *
     266             :  * Therefore, the Stress-energy contribution can be calculated from the
     267             :  * trace-reversed contribution appearing in
     268             :  * `grmhd::GhValenciaDivClean::add_stress_energy_term_to_dt_pi` -- the
     269             :  * trace reversal in that function and the trace-reversal that appears
     270             :  * explicitly in \f${\cal C}_a\f$ cancel.
     271             :  */
     272             : template <typename DataType, size_t SpatialDim, typename Frame>
     273           1 : tnsr::a<DataType, SpatialDim, Frame> f_constraint(
     274             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
     275             :     const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
     276             :     const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
     277             :     const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
     278             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     279             :     const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
     280             :     const tnsr::aa<DataType, SpatialDim, Frame>& pi,
     281             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
     282             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     283             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     284             :     const Scalar<DataType>& gamma2,
     285             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint);
     286             : 
     287             : template <typename DataType, size_t SpatialDim, typename Frame>
     288           1 : void f_constraint(
     289             :     gsl::not_null<tnsr::a<DataType, SpatialDim, Frame>*> constraint,
     290             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
     291             :     const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
     292             :     const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
     293             :     const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
     294             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     295             :     const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
     296             :     const tnsr::aa<DataType, SpatialDim, Frame>& pi,
     297             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
     298             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     299             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     300             :     const Scalar<DataType>& gamma2,
     301             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint);
     302             : 
     303             : template <typename DataType, size_t SpatialDim, typename Frame>
     304           1 : tnsr::a<DataType, SpatialDim, Frame> f_constraint(
     305             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
     306             :     const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
     307             :     const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
     308             :     const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
     309             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     310             :     const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
     311             :     const tnsr::aa<DataType, SpatialDim, Frame>& pi,
     312             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
     313             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     314             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     315             :     const Scalar<DataType>& gamma2,
     316             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
     317             :     const tnsr::aa<DataType, SpatialDim, Frame>& trace_reversed_stress_energy);
     318             : 
     319             : template <typename DataType, size_t SpatialDim, typename Frame>
     320           1 : void f_constraint(
     321             :     gsl::not_null<tnsr::a<DataType, SpatialDim, Frame>*> constraint,
     322             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
     323             :     const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
     324             :     const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
     325             :     const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
     326             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     327             :     const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
     328             :     const tnsr::aa<DataType, SpatialDim, Frame>& pi,
     329             :     const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
     330             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     331             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     332             :     const Scalar<DataType>& gamma2,
     333             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
     334             :     const tnsr::aa<DataType, SpatialDim, Frame>& trace_reversed_stress_energy);
     335             : /// @}
     336             : 
     337             : /// @{
     338             : /*!
     339             :  * \brief Computes the generalized-harmonic (unnormalized) constraint energy.
     340             :  *
     341             :  * \details Computes the generalized-harmonic unnormalized constraint energy
     342             :  * [Eq. (53) of \cite Lindblom2005qh with \f$m^{ab}=\delta^{ab}\f$ and with each
     343             :  * term in the sum scaled by an arbitrary coefficient],
     344             :  * \f{eqnarray}{
     345             :  * E & = & K_1 C_a C_a + K_2\left(F_a F_a
     346             :      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     347             :      & + & K_3 C_{iab} C_{jab} g^{ij} + K_4 C_{ikab} C_{jlab}g^{ij} g^{kl}.
     348             :  * \f}
     349             :  * Here \f$C_a\f$ is the gauge constraint, \f$F_a\f$ is the f constraint,
     350             :  * \f$C_{ia}\f$ is the two-index constraint, \f$C_{iab}\f$ is the
     351             :  * three-index constraint, \f$C_{ikab}\f$ is the four-index constraint,
     352             :  * \f$g^{ij}\f$ is the inverse spatial metric, and
     353             :  * \f$K_1\f$, \f$K_2\f$, \f$K_3\f$, and \f$K_4\f$ are constant multipliers
     354             :  * for each term that each default to a value of 1.0. Note that in this
     355             :  * equation, spacetime indices \f$a,b\f$ are raised and lowered with
     356             :  * the Kronecker delta.
     357             :  *
     358             :  * Also note that the argument `four_index_constraint` is a rank-3 tensor.
     359             :  * This is because `gh::four_index_constraint()` takes
     360             :  * advantage of the antisymmetry of the four-index constraint's first two
     361             :  * indices to only compute and return the independent
     362             :  * components of \f$C_{ijab}\f$, which can be written as
     363             :  * \f{eqnarray}{
     364             :  * D_{iab} \equiv \frac{1}{2} \epsilon_{i}{}^{jk} C_{jkab},
     365             :  * \f} where \f$\epsilon_{ijk}\f$ is the flat-space Levi-Civita tensor,
     366             :  * whose inidces are raised and lowered with the Kronecker delta.
     367             :  * The result is
     368             :  * \f{eqnarray}{
     369             :  * E & = & K_1 C_a C_a + K_2\left(F_a F_a
     370             :  *       + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     371             :  *   & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     372             :      & + & 2 K_4 g D_{iab} D_{jab} g^{ij},
     373             :  * \f} where \f$g\f$ is the determinant of the spatial metric.
     374             :  *
     375             :  * To derive this expression for the constraint energy implemented here,
     376             :  * Eq.~(53) of \cite Lindblom2005qh is
     377             :  * \f{eqnarray}{
     378             :  * S_{AB} dc^A dc^B &=&
     379             :  *      m^{ab}\Bigl[d F_ad F_b
     380             :  *      +g^{ij}\bigl(d C_{ia}d C_{jb}
     381             :  *      +g^{kl}m^{cd}d C_{ikac}d C_{jlbd}\bigr)
     382             :  * \nonumber\\
     383             :  *      & + & \Lambda^2\bigl(d C_ad C_b
     384             :  *      +g^{ij}m^{cd}d C_{iac}d C_{jbd}\bigr)
     385             :  * \Bigr].
     386             :  * \f} Replace \f$dc^A\rightarrow c^A\f$ to get
     387             :  * \f{eqnarray}{
     388             :  * E&=&
     389             :  *      m^{ab}\Bigl[ F_a F_b
     390             :  *      +g^{ij}\bigl( C_{ia} C_{jb}
     391             :  *      +g^{kl}m^{cd} C_{ikac} C_{jlbd}\bigr)
     392             :  * \nonumber\\
     393             :  *      & + & \Lambda^2\bigl( C_a C_b
     394             :  *      +g^{ij}m^{cd} C_{iac} C_{jbd}\bigr)
     395             :  * \Bigr]\nonumber\\
     396             :  * &=&
     397             :  *      m^{ab} F_a F_b
     398             :  *      +m^{ab}g^{ij} C_{ia} C_{jb}
     399             :  *      +m^{ab}g^{ij} g^{kl}m^{cd} C_{ikac} C_{jlbd}
     400             :  * \nonumber\\
     401             :  *      & + & m^{ab}\Lambda^2 C_a C_b
     402             :  *      +m^{ab}\Lambda^2 g^{ij}m^{cd} C_{iac} C_{jbd}.
     403             :  * \f} Here \f$m^{ab}\f$ is an arbitrary positive-definite matrix, and
     404             :  * \f$\Lambda\f$ is an arbitrary real scalar.
     405             :  * Choose \f$m^{ab} = \delta^{ab}\f$ but allow an arbitrary coefficient to be
     406             :  * placed in front of each term. Then, absorb \f$\Lambda^2\f$ into one of
     407             :  * these coefficients, to get
     408             :  * \f{eqnarray}{ E &=& K_
     409             :  * F\delta^{ab} F_a F_b +K_2\delta^{ab}g^{ij} C_{ia} C_{jb}
     410             :  +K_4\delta^{ab}g^{ij}
     411             :  * g^{kl}\delta^{cd} C_{ikac} C_{jlbd}
     412             :  * \nonumber\\
     413             :  *      & + & K_1\delta^{ab} C_a C_b
     414             :  *      +K_3\delta^{ab} g^{ij}\delta^{cd} C_{iac} C_{jbd}.
     415             :  * \f}
     416             :  * Adopting a Euclidean norm for the constraint space (i.e., choosing to raise
     417             :  and
     418             :  * lower spacetime indices with Kronecker deltas) gives
     419             :  * \f{eqnarray}{ E &=& K_ F
     420             :  * F_a F_a +K_2g^{ij} C_{ia} C_{ja} +K_4 g^{ij} g^{kl} C_{ikac} C_{jlac}
     421             :  * \nonumber\\
     422             :  *      & + & K_1 C_a C_a
     423             :  *      +K_3g^{ij} C_{iac} C_{jac}.
     424             :  * \f} The two-index constraint and f constraint can be viewed as the
     425             :  * time and space components of a combined spacetime constraint. So next
     426             :  * choose
     427             :  * \f$K_ F=K_2\f$, giving \f{eqnarray}{ E&=& K_1 C_a C_a + K_2\left(F_a F_a
     428             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     429             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}
     430             :  *      + K_4 C_{ikab} C_{jlab}g^{ij} g^{kl}.
     431             :  * \f}
     432             :  *
     433             :  * Note that \f$C_{ikab}\f$ is antisymmetric on the first two indices. Next,
     434             :  * replace the four-index constraint \f$C_{ijab}\f$ with \f$D_{iab}\f$, which
     435             :  * contains the independent components of \f$C_{ijab}\f$. Specifically,
     436             :  * \f{eqnarray}{
     437             :  * D_{iab} \equiv \frac{1}{2} \epsilon_{i}{}^{jk} C_{jkab}.
     438             :  * \f} The inverse relationship is
     439             :  * \f{eqnarray}{
     440             :  * C_{jkab} = \epsilon^{i}{}_{jk} D_{iab},
     441             :  * \f} where \f$\epsilon_{ijk}\f$ is the flat-space Levi-Civita tensor, whose
     442             :  * indices are raised and lowered with the Kronecker delta. Inserting this
     443             :  relation
     444             :  * to replace \f$C_{jkab}\f$ with \f$D_{iab}\f$ gives \f{eqnarray}{ E &=& K_1
     445             :  C_a
     446             :  * C_a + K_2\left(F_a F_a
     447             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     448             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     449             :  *      & + & K_4 D_{mab} D_{nab} \epsilon^{m}{}_{ik}
     450             :  *      \epsilon^{n}{}_{jl} g^{ij} g^{kl}. \f}
     451             :  *
     452             :  * There's a subtle point here: \f$g^{ij}\f$ is the inverse spatial metric,
     453             :  which
     454             :  * is not necessarily flat. But \f$\epsilon^{i}{}_{jk}\f$ is the flat space
     455             :  * Levi-Civita tensor. In order to raise and lower indices of the Levi-Civita
     456             :  * tensor with the inverse spatial metrics, put in the appropriate factors of
     457             :  * \f$\sqrt{g}\f$, where \f$g\f$ is the metric determinant, to make the
     458             :  * curved-space Levi-Civita tensor compatible with \f$g^{ij}\f$. Let
     459             :  * \f$\varepsilon^{ijk}\f$ represent the curved space Levi-Civita tensor
     460             :  compatible
     461             :  * with \f$g^{ij}\f$: \f{eqnarray}{
     462             :  * \varepsilon^{mik} = g^{-1/2} \epsilon^{mik}\\
     463             :  * \varepsilon_{mik} = g^{1/2} \epsilon_{mik}.
     464             :  * \f} Then we can write the constraint energy as
     465             :  * \f{eqnarray}{
     466             :  * E &=& K_1 C_a C_a + K_2\left(F_a F_a
     467             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     468             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     469             :  *      & + & K_4 D_{mab} D_{nab} g g^{-1/2}\epsilon^{m}{}_{ik}
     470             :  * g^{-1/2}\epsilon^{n}{}_{jl} g^{ij} g^{kl}. \f} The factors of
     471             :  * \f$g^{-1/2}\f$ make the Levi-Civita tensor compatible with \f$g^{ij}\f$.
     472             :  * Swapping which summed indices are raised and which are lowered gives
     473             :  * \f{eqnarray}{ E &=& K_1 C_a
     474             :  C_a +
     475             :  * K_2\left(F_a F_a
     476             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     477             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     478             :  *      & + & K_4 D_{mab} D_{nab} g g^{-1/2}\epsilon^{mik}
     479             :  g^{-1/2}\epsilon^{njl}
     480             :  * g_{ij} g_{kl}, \f} or \f{eqnarray}{ E &=& K_1 C_a C_a + K_2\left(F_a F_a
     481             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     482             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     483             :  *      & + & K_4 D_{mab} D_{nab} g \varepsilon^{mik} \varepsilon^{njl} g_{ij}
     484             :  * g_{kl}, \f} or, reversing up and down repeated indices again,
     485             :  * \f{eqnarray}{ E
     486             :  * &=& K_1 C_a C_a + K_2\left(F_a F_a
     487             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     488             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     489             :  *      & + & K_4 D_{mab} D_{nab} g \varepsilon^{m}{}_{ik}
     490             :  \varepsilon^{n}{}_{jl}
     491             :  * g^{ij} g^{kl}. \f}
     492             :  *
     493             :  * The metric raises and lowers the indices of \f$\varepsilon^{ijk}\f$,
     494             :  * so this can
     495             :  * be written as \f{eqnarray}{ E &=& K_1 C_a C_a + K_2\left(F_a F_a
     496             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     497             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     498             :  *      & + & K_4 g D_{mab} D^{n}{}_{ab} \varepsilon^{mjl} \varepsilon_{njl}.
     499             :  * \f}
     500             :  *
     501             :  * Now, in flat space (Eq. (1.23) of \cite ThorneBlandford2017),
     502             :  * \f{eqnarray}{
     503             :  * \epsilon^{mjl} \epsilon_{njl} = \delta^{mj}_{nj} = \delta^m_n \delta^j_j -
     504             :  * \delta^m_j \delta^j_n = 2 \delta^m_n. \f} But this holds for curved space
     505             :  * as well: multiply the left hand side by \f$1 = g^{1/2} g^{-1/2}\f$ to get
     506             :  * \f{eqnarray}{
     507             :  * g^{-1/2}\epsilon^{mjl} g^{1/2}\epsilon_{njl} = \varepsilon^{mjl}
     508             :  * \varepsilon_{njl} = \delta^{mj}_{nj} = \delta^m_n \delta^j_j - \delta^m_j
     509             :  * \delta^j_n = 2 \delta^m_n. \f} So the constraint energy is \f{eqnarray}{ E
     510             :  &=&
     511             :  * K_1 C_a C_a + K_2\left(F_a F_a
     512             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     513             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     514             :  *      & + & 2 K_4 D_{mab} D^{n}{}_{ab} \delta^m_n.
     515             :  * \f}
     516             :  * Simplifying gives the formula implemented here:
     517             :  * \f{eqnarray}{
     518             :  * E &=& K_1 C_a C_a + K_2\left(F_a F_a
     519             :  *      + C_{ia} C_{ja} g^{ij}\right)\nonumber\\
     520             :  *      & + & K_3 C_{iab} C_{jab} g^{ij}\nonumber\\
     521             :  *      & + & 2 K_4 g D_{iab} D_{jab} g^{ij}.
     522             :  * \f}
     523             :  */
     524             : template <typename DataType, size_t SpatialDim, typename Frame>
     525           1 : Scalar<DataType> constraint_energy(
     526             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_constraint,
     527             :     const tnsr::a<DataType, SpatialDim, Frame>& f_constraint,
     528             :     const tnsr::ia<DataType, SpatialDim, Frame>& two_index_constraint,
     529             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
     530             :     const tnsr::iaa<DataType, SpatialDim, Frame>& four_index_constraint,
     531             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     532             :     const Scalar<DataType>& spatial_metric_determinant,
     533             :     double gauge_constraint_multiplier = 1.0,
     534             :     double two_index_constraint_multiplier = 1.0,
     535             :     double three_index_constraint_multiplier = 1.0,
     536             :     double four_index_constraint_multiplier = 1.0);
     537             : 
     538             : template <typename DataType, size_t SpatialDim, typename Frame>
     539           1 : void constraint_energy(
     540             :     gsl::not_null<Scalar<DataType>*> energy,
     541             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_constraint,
     542             :     const tnsr::a<DataType, SpatialDim, Frame>& f_constraint,
     543             :     const tnsr::ia<DataType, SpatialDim, Frame>& two_index_constraint,
     544             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
     545             :     const tnsr::iaa<DataType, SpatialDim, Frame>& four_index_constraint,
     546             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     547             :     const Scalar<DataType>& spatial_metric_determinant,
     548             :     double gauge_constraint_multiplier = 1.0,
     549             :     double two_index_constraint_multiplier = 1.0,
     550             :     double three_index_constraint_multiplier = 1.0,
     551             :     double four_index_constraint_multiplier = 1.0);
     552             : /// @}
     553             : 
     554             : /// @{
     555             : /*!
     556             :  * \brief Computes the generalized-harmonic normalized constraint energy.
     557             :  *
     558             :  * \details Computes the generalized-harmonic normalized constraint energy
     559             :  * integrand [Eq. (70) of \cite Lindblom2005qh with \f$m^{ab}=\delta^{ab}\f$],
     560             :  * \f{eqnarray}{
     561             :  * ||E||=\gamma^{ij}\delta^{ab}\delta^{cd}
     562             :  * (\Lambda^{2}\partial_{i}g_{ac}\partial_{j}g_{bd}
     563             :  * + \partial_{i}\Pi_{ac}\partial_{j}\Pi_{bd} +
     564             :  * \gamma^{kl}\partial_{i}\Phi_{kac}\partial_{j}\Phi_{lbd})\gamma^{1/2}
     565             :  * \f}
     566             :  *
     567             :  * Here \f$\gamma^{ij}\f$ is the inverse spatial metric, and \f$\Lambda^{2}\f$
     568             :  * is the squared dimensional constant. Note
     569             :  * that in this equation, spacetime indices \f$a,b\f$ are raised and lowered
     570             :  * with the Kronecker delta.
     571             :  */
     572             : template <typename DataType, size_t SpatialDim, typename Frame>
     573           1 : Scalar<DataType> constraint_energy_normalization(
     574             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
     575             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     576             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     577             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     578             :     const Scalar<DataType>& sqrt_spatial_metric_determinant,
     579             :     double dimensional_constant);
     580             : 
     581             : template <typename DataType, size_t SpatialDim, typename Frame>
     582           1 : void constraint_energy_normalization(
     583             :     gsl::not_null<Scalar<DataType>*> energy_norm,
     584             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
     585             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     586             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     587             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     588             :     const Scalar<DataType>& sqrt_spatial_metric_determinant,
     589             :     double dimensional_constant);
     590             : /// @}
     591             : 
     592             : namespace Tags {
     593             : /*!
     594             :  * \brief Compute item to get the gauge constraint for the
     595             :  * generalized harmonic evolution system.
     596             :  *
     597             :  * \details See `gauge_constraint()`. Can be retrieved using
     598             :  * `gh::Tags::GaugeConstraint`.
     599             :  */
     600             : template <size_t SpatialDim, typename Frame>
     601           1 : struct GaugeConstraintCompute : GaugeConstraint<DataVector, SpatialDim, Frame>,
     602             :                                 db::ComputeTag {
     603           0 :   using argument_tags = tmpl::list<
     604             :       GaugeH<DataVector, SpatialDim, Frame>,
     605             :       gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
     606             :       gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
     607             :       gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
     608             :       gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
     609             :       Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>>;
     610             : 
     611           0 :   using return_type = tnsr::a<DataVector, SpatialDim, Frame>;
     612             : 
     613           0 :   static constexpr auto function = static_cast<void (*)(
     614             :       gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*>,
     615             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     616             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     617             :       const tnsr::A<DataVector, SpatialDim, Frame>&,
     618             :       const tnsr::II<DataVector, SpatialDim, Frame>&,
     619             :       const tnsr::AA<DataVector, SpatialDim, Frame>&,
     620             :       const tnsr::aa<DataVector, SpatialDim, Frame>&,
     621             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
     622             :       &gauge_constraint<DataVector, SpatialDim, Frame>);
     623             : 
     624           0 :   using base = GaugeConstraint<DataVector, SpatialDim, Frame>;
     625             : };
     626             : 
     627             : /*!
     628             :  * \brief Compute item to get the F-constraint for the
     629             :  * generalized harmonic evolution system.
     630             :  *
     631             :  * \details See `f_constraint()`. Can be retrieved using
     632             :  * `gh::Tags::FConstraint`.
     633             :  *
     634             :  * \note If the system contains matter, you will need to use a system-specific
     635             :  * version of this compute tag that passes the appropriate stress-energy tensor
     636             :  * to the F-constraint calculation.
     637             :  */
     638             : template <size_t SpatialDim, typename Frame>
     639           1 : struct FConstraintCompute : FConstraint<DataVector, SpatialDim, Frame>,
     640             :                             db::ComputeTag {
     641           0 :   using argument_tags = tmpl::list<
     642             :       GaugeH<DataVector, SpatialDim, Frame>,
     643             :       SpacetimeDerivGaugeH<DataVector, SpatialDim, Frame>,
     644             :       gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
     645             :       gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
     646             :       gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
     647             :       gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
     648             :       Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>,
     649             :       ::Tags::deriv<Pi<DataVector, SpatialDim, Frame>, tmpl::size_t<SpatialDim>,
     650             :                     Frame>,
     651             :       ::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
     652             :                     tmpl::size_t<SpatialDim>, Frame>,
     653             :       ::gh::ConstraintDamping::Tags::ConstraintGamma2,
     654             :       ThreeIndexConstraint<DataVector, SpatialDim, Frame>>;
     655             : 
     656           0 :   using return_type = tnsr::a<DataVector, SpatialDim, Frame>;
     657             : 
     658           0 :   static constexpr auto function = static_cast<void (*)(
     659             :       gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*>,
     660             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     661             :       const tnsr::ab<DataVector, SpatialDim, Frame>&,
     662             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     663             :       const tnsr::A<DataVector, SpatialDim, Frame>&,
     664             :       const tnsr::II<DataVector, SpatialDim, Frame>&,
     665             :       const tnsr::AA<DataVector, SpatialDim, Frame>&,
     666             :       const tnsr::aa<DataVector, SpatialDim, Frame>&,
     667             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     668             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     669             :       const tnsr::ijaa<DataVector, SpatialDim, Frame>&,
     670             :       const Scalar<DataVector>&,
     671             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
     672             :       &f_constraint<DataVector, SpatialDim, Frame>);
     673             : 
     674           0 :   using base = FConstraint<DataVector, SpatialDim, Frame>;
     675             : };
     676             : 
     677             : /*!
     678             :  * \brief Compute item to get the two-index constraint for the
     679             :  * generalized harmonic evolution system.
     680             :  *
     681             :  * \details See `two_index_constraint()`. Can be retrieved using
     682             :  * `gh::Tags::TwoIndexConstraint`.
     683             :  */
     684             : template <size_t SpatialDim, typename Frame>
     685           1 : struct TwoIndexConstraintCompute
     686             :     : TwoIndexConstraint<DataVector, SpatialDim, Frame>,
     687             :       db::ComputeTag {
     688           0 :   using argument_tags = tmpl::list<
     689             :       SpacetimeDerivGaugeH<DataVector, SpatialDim, Frame>,
     690             :       gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
     691             :       gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
     692             :       gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
     693             :       gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
     694             :       Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>,
     695             :       ::Tags::deriv<Pi<DataVector, SpatialDim, Frame>, tmpl::size_t<SpatialDim>,
     696             :                     Frame>,
     697             :       ::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
     698             :                     tmpl::size_t<SpatialDim>, Frame>,
     699             :       ::gh::ConstraintDamping::Tags::ConstraintGamma2,
     700             :       ThreeIndexConstraint<DataVector, SpatialDim, Frame>>;
     701             : 
     702           0 :   using return_type = tnsr::ia<DataVector, SpatialDim, Frame>;
     703             : 
     704           0 :   static constexpr auto function = static_cast<void (*)(
     705             :       gsl::not_null<tnsr::ia<DataVector, SpatialDim, Frame>*>,
     706             :       const tnsr::ab<DataVector, SpatialDim, Frame>&,
     707             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     708             :       const tnsr::A<DataVector, SpatialDim, Frame>&,
     709             :       const tnsr::II<DataVector, SpatialDim, Frame>&,
     710             :       const tnsr::AA<DataVector, SpatialDim, Frame>&,
     711             :       const tnsr::aa<DataVector, SpatialDim, Frame>&,
     712             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     713             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     714             :       const tnsr::ijaa<DataVector, SpatialDim, Frame>&,
     715             :       const Scalar<DataVector>&,
     716             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
     717             :       &two_index_constraint<DataVector, SpatialDim, Frame>);
     718             : 
     719           0 :   using base = TwoIndexConstraint<DataVector, SpatialDim, Frame>;
     720             : };
     721             : 
     722             : /*!
     723             :  * \brief Compute item to get the three-index constraint for the
     724             :  * generalized harmonic evolution system.
     725             :  *
     726             :  * \details See `three_index_constraint()`. Can be retrieved using
     727             :  * `gh::Tags::ThreeIndexConstraint`.
     728             :  */
     729             : template <size_t SpatialDim, typename Frame>
     730           1 : struct ThreeIndexConstraintCompute
     731             :     : ThreeIndexConstraint<DataVector, SpatialDim, Frame>,
     732             :       db::ComputeTag {
     733           0 :   using argument_tags = tmpl::list<
     734             :       ::Tags::deriv<gr::Tags::SpacetimeMetric<DataVector, SpatialDim, Frame>,
     735             :                     tmpl::size_t<SpatialDim>, Frame>,
     736             :       Phi<DataVector, SpatialDim, Frame>>;
     737             : 
     738           0 :   using return_type = tnsr::iaa<DataVector, SpatialDim, Frame>;
     739             : 
     740           0 :   static constexpr auto function = static_cast<void (*)(
     741             :       gsl::not_null<tnsr::iaa<DataVector, SpatialDim, Frame>*>,
     742             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     743             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
     744             :       &three_index_constraint<DataVector, SpatialDim, Frame>);
     745             : 
     746           0 :   using base = ThreeIndexConstraint<DataVector, SpatialDim, Frame>;
     747             : };
     748             : 
     749             : /*!
     750             :  * \brief Compute item to get the four-index constraint for the
     751             :  * generalized harmonic evolution system.
     752             :  *
     753             :  * \details See `four_index_constraint()`. Can be retrieved using
     754             :  * `gh::Tags::FourIndexConstraint`.
     755             :  */
     756             : template <size_t SpatialDim, typename Frame>
     757           1 : struct FourIndexConstraintCompute
     758             :     : FourIndexConstraint<DataVector, SpatialDim, Frame>,
     759             :       db::ComputeTag {
     760           0 :   using argument_tags =
     761             :       tmpl::list<::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
     762             :                                tmpl::size_t<SpatialDim>, Frame>>;
     763             : 
     764           0 :   using return_type = tnsr::iaa<DataVector, SpatialDim, Frame>;
     765             : 
     766           0 :   static constexpr auto function = static_cast<void (*)(
     767             :       gsl::not_null<tnsr::iaa<DataVector, SpatialDim, Frame>*>,
     768             :       const tnsr::ijaa<DataVector, SpatialDim, Frame>&)>(
     769             :       &four_index_constraint<DataVector, SpatialDim, Frame>);
     770             : 
     771           0 :   using base = FourIndexConstraint<DataVector, SpatialDim, Frame>;
     772             : };
     773             : 
     774             : /*!
     775             :  * \brief Compute item to get combined energy in all constraints for the
     776             :  * generalized harmonic evolution system.
     777             :  *
     778             :  * \details See `constraint_energy()`. Can be retrieved using
     779             :  * `gh::Tags::ConstraintEnergy`.
     780             :  */
     781             : template <size_t SpatialDim, typename Frame>
     782           1 : struct ConstraintEnergyCompute
     783             :     : ConstraintEnergy<DataVector, SpatialDim, Frame>,
     784             :       db::ComputeTag {
     785           0 :   using argument_tags =
     786             :       tmpl::list<GaugeConstraint<DataVector, SpatialDim, Frame>,
     787             :                  FConstraint<DataVector, SpatialDim, Frame>,
     788             :                  TwoIndexConstraint<DataVector, SpatialDim, Frame>,
     789             :                  ThreeIndexConstraint<DataVector, SpatialDim, Frame>,
     790             :                  FourIndexConstraint<DataVector, SpatialDim, Frame>,
     791             :                  gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
     792             :                  gr::Tags::DetSpatialMetric<DataVector>>;
     793             : 
     794           0 :   using return_type = Scalar<DataVector>;
     795             : 
     796           0 :   static constexpr auto function(
     797             :       const gsl::not_null<Scalar<DataVector>*> energy,
     798             :       const tnsr::a<DataVector, SpatialDim, Frame>& gauge_constraint,
     799             :       const tnsr::a<DataVector, SpatialDim, Frame>& f_constraint,
     800             :       const tnsr::ia<DataVector, SpatialDim, Frame>& two_index_constraint,
     801             :       const tnsr::iaa<DataVector, SpatialDim, Frame>& three_index_constraint,
     802             :       const tnsr::iaa<DataVector, SpatialDim, Frame>& four_index_constraint,
     803             :       const tnsr::II<DataVector, SpatialDim, Frame>& inverse_spatial_metric,
     804             :       const Scalar<DataVector>& spatial_metric_determinant) {
     805             :     set_number_of_grid_points(energy, spatial_metric_determinant);
     806             :     constraint_energy<DataVector, SpatialDim, Frame>(
     807             :         energy, gauge_constraint, f_constraint, two_index_constraint,
     808             :         three_index_constraint, four_index_constraint, inverse_spatial_metric,
     809             :         spatial_metric_determinant);
     810             :   }
     811             : 
     812           0 :   using base = ConstraintEnergy<DataVector, SpatialDim, Frame>;
     813             : };
     814             : }  // namespace Tags
     815             : }  // namespace gh

Generated by: LCOV version 1.14