SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/GeneralizedHarmonic - Constraints.hpp Hit Total Coverage
Commit: 1e29a35ad8559408f21493dc5db8a49a237bb2f0 Lines: 23 47 48.9 %
Date: 2026-03-31 22:27:51
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/Tags.hpp"
      16             : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
      17             : #include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/ConstraintDampingTags.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 g_{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 + \gamma^{ij} \Phi_{ija} + n^b \Pi_{ba}
      57             :  * - \frac{1}{2} \gamma^i_a g^{bc} \Phi_{ibc}
      58             :  * - \frac{1}{2} n_a g^{bc} \Pi_{bc},
      59             :  * \f]
      60             :  * where \f$H_a\f$ is the gauge function,
      61             :  * \f$g_{ab}\f$ is the spacetime metric,
      62             :  * \f$\Pi_{ab}=-n^c\partial_c g_{ab}\f$, and
      63             :  * \f$\Phi_{iab} = \partial_i g_{ab}\f$; \f$n^a\f$ is the timelike unit
      64             :  * normal vector to the spatial slice, \f$\gamma^{ij}\f$ is the inverse spatial
      65             :  * metric, and \f$\gamma^b_c = \delta^b_c + n^b n_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& \gamma^{jk}\partial_j \Phi_{ika}
      97             :  * - \frac{1}{2} \gamma_a^j g^{cd}\partial_j \Phi_{icd}
      98             :  * + n^b \partial_i \Pi_{ba}
      99             :  * - \frac{1}{2} n_a g^{cd}\partial_i\Pi_{cd}
     100             :  * \nonumber\\&&
     101             :  * + \partial_i H_a
     102             :  * + \frac{1}{2} \gamma_a^j \Phi_{jcd} \Phi_{ief}
     103             :  * g^{ce}g^{df}
     104             :  * + \frac{1}{2} \gamma^{jk} \Phi_{jcd} \Phi_{ike}
     105             :  * g^{cd}n^e n_a
     106             :  * \nonumber\\&&
     107             :  * - \gamma^{jk}\gamma^{mn}\Phi_{jma}\Phi_{ikn}
     108             :  * + \frac{1}{2} \Phi_{icd} \Pi_{be} n_a
     109             :  *                             \left(g^{cb}g^{de}
     110             :  *                       +\frac{1}{2}g^{be} n^c n^d\right)
     111             :  * \nonumber\\&&
     112             :  * - \Phi_{icd} \Pi_{ba} n^c \left(g^{bd}
     113             :  *                             +\frac{1}{2} n^b n^d\right)
     114             :  * + \frac{1}{2} \gamma_2 \left(n_a g^{cd}
     115             :  * - 2 \delta^c_a n^d\right) C_{icd}.
     116             :  * \f}
     117             :  * where \f$H_a\f$ is the gauge function,
     118             :  * \f$g_{ab}\f$ is the spacetime metric,
     119             :  * \f$\Pi_{ab}=-n^c\partial_c g_{ab}\f$, and
     120             :  * \f$\Phi_{iab} = \partial_i g_{ab}\f$; \f$n^a\f$ is the timelike unit
     121             :  * normal vector to the spatial slice, \f$\gamma^{ij}\f$ is the inverse spatial
     122             :  * metric, and \f$\gamma^b_c = \delta^b_c + n^b n_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 g_{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} \gamma_a^i g^{bc}\partial_i \Pi_{bc}
     199             :  * - \gamma^{ij} \partial_i \Pi_{ja}
     200             :  * - \gamma^{ij} n^b \partial_i \Phi_{jba}
     201             :  * + \frac{1}{2} n_a g^{bc} \gamma^{ij} \partial_i \Phi_{jbc}
     202             :  * \nonumber \\ &&
     203             :  * + n_a \gamma^{ij} \partial_i H_j
     204             :  * + \gamma_a^i \Phi_{ijb} \gamma^{jk}\Phi_{kcd} g^{bd} n^c
     205             :  * - \frac{1}{2} \gamma_a^i \Phi_{ijb} \gamma^{jk}
     206             :  *   \Phi_{kcd} g^{cd} n^b
     207             :  * \nonumber \\ &&
     208             :  * - \gamma_a^i n^b \partial_i H_b
     209             :  * + \gamma^{ij} \Phi_{icd} \Phi_{jba} g^{bc} n^d
     210             :  * - \frac{1}{2} n_a \gamma^{ij} \gamma^{mn} \Phi_{imc} \Phi_{njd}g^{cd}
     211             :  * \nonumber \\ &&
     212             :  * - \frac{1}{4}  n_a \gamma^{ij}\Phi_{icd}\Phi_{jbe}
     213             :  *    g^{cb}g^{de}
     214             :  * + \frac{1}{4}  n_a \Pi_{cd} \Pi_{be}
     215             :  *    g^{cb}g^{de}
     216             :  * - \gamma^{ij} H_i \Pi_{ja}
     217             :  * \nonumber \\ &&
     218             :  * - n^b \gamma^{ij} \Pi_{b i} \Pi_{ja}
     219             :  * - \frac{1}{4}  \gamma_a^i \Phi_{icd} n^c n^d \Pi_{be}
     220             :  *   g^{be}
     221             :  * + \frac{1}{2} n_a \Pi_{cd} \Pi_{be}g^{ce}
     222             :  *   n^d n^b
     223             :  * \nonumber \\ &&
     224             :  * + \gamma_a^i \Phi_{icd} \Pi_{be} n^c n^b g^{de}
     225             :  * - \gamma^{ij}\Phi_{iba} n^b \Pi_{je} n^e
     226             :  * - \frac{1}{2} \gamma^{ij}\Phi_{icd} n^c n^d \Pi_{ja}
     227             :  * \nonumber \\ &&
     228             :  * - \gamma^{ij} H_i \Phi_{jba} n^b
     229             :  * + \gamma_{a}^i \Phi_{icd} H_b g^{bc} n^d
     230             :  * +\gamma_2\bigl(\gamma^{id}{\cal C}_{ida}
     231             :  * -\frac{1}{2}  \gamma_a^i g^{cd}{\cal C}_{icd}\bigr)
     232             :  * \nonumber \\ &&
     233             :  * + \frac{1}{2} n_a \Pi_{cd}g^{cd} H_b n^b
     234             :  * - n_a \gamma^{ij} \Phi_{ijc} H_d g^{cd}
     235             :  * +\frac{1}{2}  n_a \gamma^{ij} H_i \Phi_{jcd}g^{cd}
     236             :  * \nonumber \\ &&
     237             :  * - 16 \pi n^a T_{a b}
     238             :  * \f}
     239             :  * where \f$H_a\f$ is the gauge function,
     240             :  * \f$g_{ab}\f$ is the spacetime metric,
     241             :  * \f$\Pi_{ab}=-n^c\partial_c g_{ab}\f$, and
     242             :  * \f$\Phi_{iab} = \partial_i g_{ab}\f$; \f$n^a\f$ is the timelike unit
     243             :  * normal vector to the spatial slice, \f$\gamma^{ij}\f$ is the inverse spatial
     244             :  * metric, \f$\gamma^b_c = \delta^b_c + n^b n_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 + \gamma^{i j} \Phi_{ij a} + n^b \Pi_{ba}
     262             :  * - \frac{1}{2} \gamma_a{}^i g^{bc} \Phi_{i b c}
     263             :  * - \frac{1}{2} n_a g^{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} \gamma^{ij}\right)\nonumber\\
     347             :      & + & K_3 C_{iab} C_{jab} \gamma^{ij} + K_4 C_{ikab} C_{jlab}\gamma^{ij}
     348             :  \gamma^{kl}.
     349             :  * \f}
     350             :  * Here \f$C_a\f$ is the gauge constraint, \f$F_a\f$ is the f constraint,
     351             :  * \f$C_{ia}\f$ is the two-index constraint, \f$C_{iab}\f$ is the
     352             :  * three-index constraint, \f$C_{ikab}\f$ is the four-index constraint,
     353             :  * \f$\gamma^{ij}\f$ is the inverse spatial metric, and
     354             :  * \f$K_1\f$, \f$K_2\f$, \f$K_3\f$, and \f$K_4\f$ are constant multipliers
     355             :  * for each term that each default to a value of 1.0. Note that in this
     356             :  * equation, spacetime indices \f$a,b\f$ are raised and lowered with
     357             :  * the Kronecker delta.
     358             :  *
     359             :  * Also note that the argument `four_index_constraint` is a rank-3 tensor.
     360             :  * This is because `gh::four_index_constraint()` takes
     361             :  * advantage of the antisymmetry of the four-index constraint's first two
     362             :  * indices to only compute and return the independent
     363             :  * components of \f$C_{ijab}\f$, which can be written as
     364             :  * \f{eqnarray}{
     365             :  * D_{iab} \equiv \frac{1}{2} \epsilon_{i}{}^{jk} C_{jkab},
     366             :  * \f} where \f$\epsilon_{ijk}\f$ is the flat-space Levi-Civita tensor,
     367             :  * whose inidces are raised and lowered with the Kronecker delta.
     368             :  * The result is
     369             :  * \f{eqnarray}{
     370             :  * E & = & K_1 C_a C_a + K_2\left(F_a F_a
     371             :  *       + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     372             :  *   & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     373             :      & + & 2 K_4 \gamma D_{iab} D_{jab} \gamma^{ij},
     374             :  * \f} where \f$\gamma\f$ is the determinant of the spatial metric.
     375             :  *
     376             :  * To derive this expression for the constraint energy implemented here,
     377             :  * Eq.~(53) of \cite Lindblom2005qh is
     378             :  * \f{eqnarray}{
     379             :  * S_{AB} dc^A dc^B &=&
     380             :  *      m^{ab}\Bigl[d F_ad F_b
     381             :  *      +\gamma^{ij}\bigl(d C_{ia}d C_{jb}
     382             :  *      +\gamma^{kl}m^{cd}d C_{ikac}d C_{jlbd}\bigr)
     383             :  * \nonumber\\
     384             :  *      & + & \Lambda^2\bigl(d C_ad C_b
     385             :  *      +\gamma^{ij}m^{cd}d C_{iac}d C_{jbd}\bigr)
     386             :  * \Bigr].
     387             :  * \f} Replace \f$dc^A\rightarrow c^A\f$ to get
     388             :  * \f{eqnarray}{
     389             :  * E&=&
     390             :  *      m^{ab}\Bigl[ F_a F_b
     391             :  *      +\gamma^{ij}\bigl( C_{ia} C_{jb}
     392             :  *      +\gamma^{kl}m^{cd} C_{ikac} C_{jlbd}\bigr)
     393             :  * \nonumber\\
     394             :  *      & + & \Lambda^2\bigl( C_a C_b
     395             :  *      +\gamma^{ij}m^{cd} C_{iac} C_{jbd}\bigr)
     396             :  * \Bigr]\nonumber\\
     397             :  * &=&
     398             :  *      m^{ab} F_a F_b
     399             :  *      +m^{ab}\gamma^{ij} C_{ia} C_{jb}
     400             :  *      +m^{ab}\gamma^{ij} \gamma^{kl}m^{cd} C_{ikac} C_{jlbd}
     401             :  * \nonumber\\
     402             :  *      & + & m^{ab}\Lambda^2 C_a C_b
     403             :  *      +m^{ab}\Lambda^2 \gamma^{ij}m^{cd} C_{iac} C_{jbd}.
     404             :  * \f} Here \f$m^{ab}\f$ is an arbitrary positive-definite matrix, and
     405             :  * \f$\Lambda\f$ is an arbitrary real scalar.
     406             :  * Choose \f$m^{ab} = \delta^{ab}\f$ but allow an arbitrary coefficient to be
     407             :  * placed in front of each term. Then, absorb \f$\Lambda^2\f$ into one of
     408             :  * these coefficients, to get
     409             :  * \f{eqnarray}{ E &=& K_
     410             :  * F\delta^{ab} F_a F_b +K_2\delta^{ab}\gamma^{ij} C_{ia} C_{jb}
     411             :  +K_4\delta^{ab}\gamma^{ij}
     412             :  * \gamma^{kl}\delta^{cd} C_{ikac} C_{jlbd}
     413             :  * \nonumber\\
     414             :  *      & + & K_1\delta^{ab} C_a C_b
     415             :  *      +K_3\delta^{ab} \gamma^{ij}\delta^{cd} C_{iac} C_{jbd}.
     416             :  * \f}
     417             :  * Adopting a Euclidean norm for the constraint space (i.e., choosing to raise
     418             :  and
     419             :  * lower spacetime indices with Kronecker deltas) gives
     420             :  * \f{eqnarray}{ E &=& K_ F
     421             :  * F_a F_a +K_2\gamma^{ij} C_{ia} C_{ja} +K_4 \gamma^{ij} \gamma^{kl} C_{ikac}
     422             :  C_{jlac}
     423             :  * \nonumber\\
     424             :  *      & + & K_1 C_a C_a
     425             :  *      +K_3\gamma^{ij} C_{iac} C_{jac}.
     426             :  * \f} The two-index constraint and f constraint can be viewed as the
     427             :  * time and space components of a combined spacetime constraint. So next
     428             :  * choose
     429             :  * \f$K_ F=K_2\f$, giving \f{eqnarray}{ E&=& K_1 C_a C_a + K_2\left(F_a F_a
     430             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     431             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}
     432             :  *      + K_4 C_{ikab} C_{jlab}\gamma^{ij} \gamma^{kl}.
     433             :  * \f}
     434             :  *
     435             :  * Note that \f$C_{ikab}\f$ is antisymmetric on the first two indices. Next,
     436             :  * replace the four-index constraint \f$C_{ijab}\f$ with \f$D_{iab}\f$, which
     437             :  * contains the independent components of \f$C_{ijab}\f$. Specifically,
     438             :  * \f{eqnarray}{
     439             :  * D_{iab} \equiv \frac{1}{2} \epsilon_{i}{}^{jk} C_{jkab}.
     440             :  * \f} The inverse relationship is
     441             :  * \f{eqnarray}{
     442             :  * C_{jkab} = \epsilon^{i}{}_{jk} D_{iab},
     443             :  * \f} where \f$\epsilon_{ijk}\f$ is the flat-space Levi-Civita tensor, whose
     444             :  * indices are raised and lowered with the Kronecker delta. Inserting this
     445             :  relation
     446             :  * to replace \f$C_{jkab}\f$ with \f$D_{iab}\f$ gives \f{eqnarray}{ E &=& K_1
     447             :  C_a
     448             :  * C_a + K_2\left(F_a F_a
     449             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     450             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     451             :  *      & + & K_4 D_{mab} D_{nab} \epsilon^{m}{}_{ik}
     452             :  *      \epsilon^{n}{}_{jl} \gamma^{ij} \gamma^{kl}. \f}
     453             :  *
     454             :  * There's a subtle point here: \f$\gamma^{ij}\f$ is the inverse spatial metric,
     455             :  which
     456             :  * is not necessarily flat. But \f$\epsilon^{i}{}_{jk}\f$ is the flat space
     457             :  * Levi-Civita tensor. In order to raise and lower indices of the Levi-Civita
     458             :  * tensor with the inverse spatial metrics, put in the appropriate factors of
     459             :  * \f$\sqrt{\gamma}\f$, where \f$\gamma\f$ is the metric determinant, to make
     460             :  the
     461             :  * curved-space Levi-Civita tensor compatible with \f$\gamma^{ij}\f$. Let
     462             :  * \f$\varepsilon^{ijk}\f$ represent the curved space Levi-Civita tensor
     463             :  compatible
     464             :  * with \f$\gamma^{ij}\f$: \f{eqnarray}{
     465             :  * \varepsilon^{mik} = \gamma^{-1/2} \epsilon^{mik}\\
     466             :  * \varepsilon_{mik} = \gamma^{1/2} \epsilon_{mik}.
     467             :  * \f} Then we can write the constraint energy as
     468             :  * \f{eqnarray}{
     469             :  * E &=& K_1 C_a C_a + K_2\left(F_a F_a
     470             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     471             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     472             :  *      & + & K_4 D_{mab} D_{nab} \gamma \gamma^{-1/2}\epsilon^{m}{}_{ik}
     473             :  * \gamma^{-1/2}\epsilon^{n}{}_{jl} \gamma^{ij} \gamma^{kl}. \f} The factors of
     474             :  * \f$\gamma^{-1/2}\f$ make the Levi-Civita tensor compatible with
     475             :  \f$\gamma^{ij}\f$.
     476             :  * Swapping which summed indices are raised and which are lowered gives
     477             :  * \f{eqnarray}{ E &=& K_1 C_a
     478             :  C_a +
     479             :  * K_2\left(F_a F_a
     480             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     481             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     482             :  *      & + & K_4 D_{mab} D_{nab} \gamma \gamma^{-1/2}\epsilon^{mik}
     483             :  \gamma^{-1/2}\epsilon^{njl}
     484             :  * \gamma_{ij} \gamma_{kl}, \f} or \f{eqnarray}{ E &=& K_1 C_a C_a +
     485             :  K_2\left(F_a F_a
     486             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     487             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     488             :  *      & + & K_4 D_{mab} D_{nab} \gamma \varepsilon^{mik} \varepsilon^{njl}
     489             :  \gamma_{ij}
     490             :  * \gamma_{kl}, \f} or, reversing up and down repeated indices again,
     491             :  * \f{eqnarray}{ E
     492             :  * &=& K_1 C_a C_a + K_2\left(F_a F_a
     493             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     494             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     495             :  *      & + & K_4 D_{mab} D_{nab} \gamma \varepsilon^{m}{}_{ik}
     496             :  \varepsilon^{n}{}_{jl}
     497             :  * \gamma^{ij} \gamma^{kl}. \f}
     498             :  *
     499             :  * The metric raises and lowers the indices of \f$\varepsilon^{ijk}\f$,
     500             :  * so this can
     501             :  * be written as \f{eqnarray}{ E &=& K_1 C_a C_a + K_2\left(F_a F_a
     502             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     503             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     504             :  *      & + & K_4 \gamma D_{mab} D^{n}{}_{ab} \varepsilon^{mjl}
     505             :  \varepsilon_{njl}.
     506             :  * \f}
     507             :  *
     508             :  * Now, in flat space (Eq. (1.23) of \cite ThorneBlandford2017),
     509             :  * \f{eqnarray}{
     510             :  * \epsilon^{mjl} \epsilon_{njl} = \delta^{mj}_{nj} = \delta^m_n \delta^j_j -
     511             :  * \delta^m_j \delta^j_n = 2 \delta^m_n. \f} But this holds for curved space
     512             :  * as well: multiply the left hand side by \f$1 = \gamma^{1/2} \gamma^{-1/2}\f$
     513             :  to get
     514             :  * \f{eqnarray}{
     515             :  * \gamma^{-1/2}\epsilon^{mjl} \gamma^{1/2}\epsilon_{njl} = \varepsilon^{mjl}
     516             :  * \varepsilon_{njl} = \delta^{mj}_{nj} = \delta^m_n \delta^j_j - \delta^m_j
     517             :  * \delta^j_n = 2 \delta^m_n. \f} So the constraint energy is \f{eqnarray}{ E
     518             :  &=&
     519             :  * K_1 C_a C_a + K_2\left(F_a F_a
     520             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     521             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     522             :  *      & + & 2 K_4 D_{mab} D^{n}{}_{ab} \delta^m_n.
     523             :  * \f}
     524             :  * Simplifying gives the formula implemented here:
     525             :  * \f{eqnarray}{
     526             :  * E &=& K_1 C_a C_a + K_2\left(F_a F_a
     527             :  *      + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
     528             :  *      & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
     529             :  *      & + & 2 K_4 \gamma D_{iab} D_{jab} \gamma^{ij}.
     530             :  * \f}
     531             :  */
     532             : template <typename DataType, size_t SpatialDim, typename Frame>
     533           1 : Scalar<DataType> constraint_energy(
     534             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_constraint,
     535             :     const tnsr::a<DataType, SpatialDim, Frame>& f_constraint,
     536             :     const tnsr::ia<DataType, SpatialDim, Frame>& two_index_constraint,
     537             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
     538             :     const tnsr::iaa<DataType, SpatialDim, Frame>& four_index_constraint,
     539             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     540             :     const Scalar<DataType>& spatial_metric_determinant,
     541             :     double gauge_constraint_multiplier = 1.0,
     542             :     double two_index_constraint_multiplier = 1.0,
     543             :     double three_index_constraint_multiplier = 1.0,
     544             :     double four_index_constraint_multiplier = 1.0);
     545             : 
     546             : template <typename DataType, size_t SpatialDim, typename Frame>
     547           1 : void constraint_energy(
     548             :     gsl::not_null<Scalar<DataType>*> energy,
     549             :     const tnsr::a<DataType, SpatialDim, Frame>& gauge_constraint,
     550             :     const tnsr::a<DataType, SpatialDim, Frame>& f_constraint,
     551             :     const tnsr::ia<DataType, SpatialDim, Frame>& two_index_constraint,
     552             :     const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
     553             :     const tnsr::iaa<DataType, SpatialDim, Frame>& four_index_constraint,
     554             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     555             :     const Scalar<DataType>& spatial_metric_determinant,
     556             :     double gauge_constraint_multiplier = 1.0,
     557             :     double two_index_constraint_multiplier = 1.0,
     558             :     double three_index_constraint_multiplier = 1.0,
     559             :     double four_index_constraint_multiplier = 1.0);
     560             : /// @}
     561             : 
     562             : /// @{
     563             : /*!
     564             :  * \brief Computes the generalized-harmonic normalized constraint energy.
     565             :  *
     566             :  * \details Computes the generalized-harmonic normalized constraint energy
     567             :  * integrand [Eq. (70) of \cite Lindblom2005qh with \f$m^{ab}=\delta^{ab}\f$],
     568             :  * \f{eqnarray}{
     569             :  * ||E||=\gamma^{ij}\delta^{ab}\delta^{cd}
     570             :  * (\Lambda^{2}\partial_{i}g_{ac}\partial_{j}g_{bd}
     571             :  * + \partial_{i}\Pi_{ac}\partial_{j}\Pi_{bd} +
     572             :  * \gamma^{kl}\partial_{i}\Phi_{kac}\partial_{j}\Phi_{lbd})\gamma^{1/2}
     573             :  * \f}
     574             :  *
     575             :  * Here \f$\gamma^{ij}\f$ is the inverse spatial metric, and \f$\Lambda^{2}\f$
     576             :  * is the squared dimensional constant. Note
     577             :  * that in this equation, spacetime indices \f$a,b\f$ are raised and lowered
     578             :  * with the Kronecker delta.
     579             :  */
     580             : template <typename DataType, size_t SpatialDim, typename Frame>
     581           1 : Scalar<DataType> constraint_energy_normalization(
     582             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
     583             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     584             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     585             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     586             :     const Scalar<DataType>& sqrt_spatial_metric_determinant,
     587             :     double dimensional_constant);
     588             : 
     589             : template <typename DataType, size_t SpatialDim, typename Frame>
     590           1 : void constraint_energy_normalization(
     591             :     gsl::not_null<Scalar<DataType>*> energy_norm,
     592             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
     593             :     const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
     594             :     const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
     595             :     const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
     596             :     const Scalar<DataType>& sqrt_spatial_metric_determinant,
     597             :     double dimensional_constant);
     598             : /// @}
     599             : 
     600             : namespace Tags {
     601             : /*!
     602             :  * \brief Compute item to get the gauge constraint for the
     603             :  * generalized harmonic evolution system.
     604             :  *
     605             :  * \details See `gauge_constraint()`. Can be retrieved using
     606             :  * `gh::Tags::GaugeConstraint`.
     607             :  */
     608             : template <size_t SpatialDim, typename Frame>
     609           1 : struct GaugeConstraintCompute : GaugeConstraint<DataVector, SpatialDim, Frame>,
     610             :                                 db::ComputeTag {
     611           0 :   using argument_tags = tmpl::list<
     612             :       GaugeH<DataVector, SpatialDim, Frame>,
     613             :       gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
     614             :       gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
     615             :       gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
     616             :       gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
     617             :       Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>>;
     618             : 
     619           0 :   using return_type = tnsr::a<DataVector, SpatialDim, Frame>;
     620             : 
     621           0 :   static constexpr auto function = static_cast<void (*)(
     622             :       gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*>,
     623             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     624             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     625             :       const tnsr::A<DataVector, SpatialDim, Frame>&,
     626             :       const tnsr::II<DataVector, SpatialDim, Frame>&,
     627             :       const tnsr::AA<DataVector, SpatialDim, Frame>&,
     628             :       const tnsr::aa<DataVector, SpatialDim, Frame>&,
     629             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
     630             :       &gauge_constraint<DataVector, SpatialDim, Frame>);
     631             : 
     632           0 :   using base = GaugeConstraint<DataVector, SpatialDim, Frame>;
     633             : };
     634             : 
     635             : /*!
     636             :  * \brief Compute item to get the F-constraint for the
     637             :  * generalized harmonic evolution system.
     638             :  *
     639             :  * \details See `f_constraint()`. Can be retrieved using
     640             :  * `gh::Tags::FConstraint`.
     641             :  *
     642             :  * \note If the system contains matter, you will need to use a system-specific
     643             :  * version of this compute tag that passes the appropriate stress-energy tensor
     644             :  * to the F-constraint calculation.
     645             :  */
     646             : template <size_t SpatialDim, typename Frame>
     647           1 : struct FConstraintCompute : FConstraint<DataVector, SpatialDim, Frame>,
     648             :                             db::ComputeTag {
     649           0 :   using argument_tags = tmpl::list<
     650             :       GaugeH<DataVector, SpatialDim, Frame>,
     651             :       SpacetimeDerivGaugeH<DataVector, SpatialDim, Frame>,
     652             :       gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
     653             :       gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
     654             :       gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
     655             :       gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
     656             :       Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>,
     657             :       ::Tags::deriv<Pi<DataVector, SpatialDim, Frame>, tmpl::size_t<SpatialDim>,
     658             :                     Frame>,
     659             :       ::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
     660             :                     tmpl::size_t<SpatialDim>, Frame>,
     661             :       ::gh::Tags::ConstraintGamma2,
     662             :       ThreeIndexConstraint<DataVector, SpatialDim, Frame>>;
     663             : 
     664           0 :   using return_type = tnsr::a<DataVector, SpatialDim, Frame>;
     665             : 
     666           0 :   static constexpr auto function = static_cast<void (*)(
     667             :       gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*>,
     668             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     669             :       const tnsr::ab<DataVector, SpatialDim, Frame>&,
     670             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     671             :       const tnsr::A<DataVector, SpatialDim, Frame>&,
     672             :       const tnsr::II<DataVector, SpatialDim, Frame>&,
     673             :       const tnsr::AA<DataVector, SpatialDim, Frame>&,
     674             :       const tnsr::aa<DataVector, SpatialDim, Frame>&,
     675             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     676             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     677             :       const tnsr::ijaa<DataVector, SpatialDim, Frame>&,
     678             :       const Scalar<DataVector>&,
     679             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
     680             :       &f_constraint<DataVector, SpatialDim, Frame>);
     681             : 
     682           0 :   using base = FConstraint<DataVector, SpatialDim, Frame>;
     683             : };
     684             : 
     685             : /*!
     686             :  * \brief Compute item to get the two-index constraint for the
     687             :  * generalized harmonic evolution system.
     688             :  *
     689             :  * \details See `two_index_constraint()`. Can be retrieved using
     690             :  * `gh::Tags::TwoIndexConstraint`.
     691             :  */
     692             : template <size_t SpatialDim, typename Frame>
     693           1 : struct TwoIndexConstraintCompute
     694             :     : TwoIndexConstraint<DataVector, SpatialDim, Frame>,
     695             :       db::ComputeTag {
     696           0 :   using argument_tags = tmpl::list<
     697             :       SpacetimeDerivGaugeH<DataVector, SpatialDim, Frame>,
     698             :       gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
     699             :       gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
     700             :       gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
     701             :       gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
     702             :       Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>,
     703             :       ::Tags::deriv<Pi<DataVector, SpatialDim, Frame>, tmpl::size_t<SpatialDim>,
     704             :                     Frame>,
     705             :       ::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
     706             :                     tmpl::size_t<SpatialDim>, Frame>,
     707             :       ::gh::Tags::ConstraintGamma2,
     708             :       ThreeIndexConstraint<DataVector, SpatialDim, Frame>>;
     709             : 
     710           0 :   using return_type = tnsr::ia<DataVector, SpatialDim, Frame>;
     711             : 
     712           0 :   static constexpr auto function = static_cast<void (*)(
     713             :       gsl::not_null<tnsr::ia<DataVector, SpatialDim, Frame>*>,
     714             :       const tnsr::ab<DataVector, SpatialDim, Frame>&,
     715             :       const tnsr::a<DataVector, SpatialDim, Frame>&,
     716             :       const tnsr::A<DataVector, SpatialDim, Frame>&,
     717             :       const tnsr::II<DataVector, SpatialDim, Frame>&,
     718             :       const tnsr::AA<DataVector, SpatialDim, Frame>&,
     719             :       const tnsr::aa<DataVector, SpatialDim, Frame>&,
     720             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     721             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     722             :       const tnsr::ijaa<DataVector, SpatialDim, Frame>&,
     723             :       const Scalar<DataVector>&,
     724             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
     725             :       &two_index_constraint<DataVector, SpatialDim, Frame>);
     726             : 
     727           0 :   using base = TwoIndexConstraint<DataVector, SpatialDim, Frame>;
     728             : };
     729             : 
     730             : /*!
     731             :  * \brief Compute item to get the three-index constraint for the
     732             :  * generalized harmonic evolution system.
     733             :  *
     734             :  * \details See `three_index_constraint()`. Can be retrieved using
     735             :  * `gh::Tags::ThreeIndexConstraint`.
     736             :  */
     737             : template <size_t SpatialDim, typename Frame>
     738           1 : struct ThreeIndexConstraintCompute
     739             :     : ThreeIndexConstraint<DataVector, SpatialDim, Frame>,
     740             :       db::ComputeTag {
     741           0 :   using argument_tags = tmpl::list<
     742             :       ::Tags::deriv<gr::Tags::SpacetimeMetric<DataVector, SpatialDim, Frame>,
     743             :                     tmpl::size_t<SpatialDim>, Frame>,
     744             :       Phi<DataVector, SpatialDim, Frame>>;
     745             : 
     746           0 :   using return_type = tnsr::iaa<DataVector, SpatialDim, Frame>;
     747             : 
     748           0 :   static constexpr auto function = static_cast<void (*)(
     749             :       gsl::not_null<tnsr::iaa<DataVector, SpatialDim, Frame>*>,
     750             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&,
     751             :       const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
     752             :       &three_index_constraint<DataVector, SpatialDim, Frame>);
     753             : 
     754           0 :   using base = ThreeIndexConstraint<DataVector, SpatialDim, Frame>;
     755             : };
     756             : 
     757             : /*!
     758             :  * \brief Compute item to get the four-index constraint for the
     759             :  * generalized harmonic evolution system.
     760             :  *
     761             :  * \details See `four_index_constraint()`. Can be retrieved using
     762             :  * `gh::Tags::FourIndexConstraint`.
     763             :  */
     764             : template <size_t SpatialDim, typename Frame>
     765           1 : struct FourIndexConstraintCompute
     766             :     : FourIndexConstraint<DataVector, SpatialDim, Frame>,
     767             :       db::ComputeTag {
     768           0 :   using argument_tags =
     769             :       tmpl::list<::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
     770             :                                tmpl::size_t<SpatialDim>, Frame>>;
     771             : 
     772           0 :   using return_type = tnsr::iaa<DataVector, SpatialDim, Frame>;
     773             : 
     774           0 :   static constexpr auto function = static_cast<void (*)(
     775             :       gsl::not_null<tnsr::iaa<DataVector, SpatialDim, Frame>*>,
     776             :       const tnsr::ijaa<DataVector, SpatialDim, Frame>&)>(
     777             :       &four_index_constraint<DataVector, SpatialDim, Frame>);
     778             : 
     779           0 :   using base = FourIndexConstraint<DataVector, SpatialDim, Frame>;
     780             : };
     781             : 
     782             : /*!
     783             :  * \brief Compute item to get combined energy in all constraints for the
     784             :  * generalized harmonic evolution system.
     785             :  *
     786             :  * \details See `constraint_energy()`. Can be retrieved using
     787             :  * `gh::Tags::ConstraintEnergy`.
     788             :  */
     789             : template <size_t SpatialDim, typename Frame>
     790           1 : struct ConstraintEnergyCompute
     791             :     : ConstraintEnergy<DataVector, SpatialDim, Frame>,
     792             :       db::ComputeTag {
     793           0 :   using argument_tags =
     794             :       tmpl::list<GaugeConstraint<DataVector, SpatialDim, Frame>,
     795             :                  FConstraint<DataVector, SpatialDim, Frame>,
     796             :                  TwoIndexConstraint<DataVector, SpatialDim, Frame>,
     797             :                  ThreeIndexConstraint<DataVector, SpatialDim, Frame>,
     798             :                  FourIndexConstraint<DataVector, SpatialDim, Frame>,
     799             :                  gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
     800             :                  gr::Tags::DetSpatialMetric<DataVector>>;
     801             : 
     802           0 :   using return_type = Scalar<DataVector>;
     803             : 
     804           0 :   static constexpr auto function(
     805             :       const gsl::not_null<Scalar<DataVector>*> energy,
     806             :       const tnsr::a<DataVector, SpatialDim, Frame>& gauge_constraint,
     807             :       const tnsr::a<DataVector, SpatialDim, Frame>& f_constraint,
     808             :       const tnsr::ia<DataVector, SpatialDim, Frame>& two_index_constraint,
     809             :       const tnsr::iaa<DataVector, SpatialDim, Frame>& three_index_constraint,
     810             :       const tnsr::iaa<DataVector, SpatialDim, Frame>& four_index_constraint,
     811             :       const tnsr::II<DataVector, SpatialDim, Frame>& inverse_spatial_metric,
     812             :       const Scalar<DataVector>& spatial_metric_determinant) {
     813             :     set_number_of_grid_points(energy, spatial_metric_determinant);
     814             :     constraint_energy<DataVector, SpatialDim, Frame>(
     815             :         energy, gauge_constraint, f_constraint, two_index_constraint,
     816             :         three_index_constraint, four_index_constraint, inverse_spatial_metric,
     817             :         spatial_metric_determinant);
     818             :   }
     819             : 
     820           0 :   using base = ConstraintEnergy<DataVector, SpatialDim, Frame>;
     821             : };
     822             : }  // namespace Tags
     823             : }  // namespace gh

Generated by: LCOV version 1.14