SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/Cce - GaugeTransformBoundaryData.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 25.7 % 74 19
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <cstddef>
       7              : 
       8              : #include "DataStructures/ComplexDataVector.hpp"
       9              : #include "DataStructures/DataBox/Prefixes.hpp"
      10              : #include "DataStructures/SpinWeighted.hpp"
      11              : #include "DataStructures/Tags.hpp"
      12              : #include "DataStructures/Tensor/IndexType.hpp"
      13              : #include "DataStructures/Tensor/Tensor.hpp"
      14              : #include "DataStructures/Tensor/TypeAliases.hpp"
      15              : #include "DataStructures/Variables.hpp"
      16              : #include "Evolution/Systems/Cce/Tags.hpp"
      17              : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshCollocation.hpp"
      18              : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshDerivatives.hpp"
      19              : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshInterpolation.hpp"
      20              : #include "Utilities/Gsl.hpp"
      21              : #include "Utilities/TMPL.hpp"
      22              : 
      23              : namespace Cce {
      24              : /// The set of tags that should be calculated before the initial data is
      25              : /// computed on the first hypersurface.
      26            1 : using gauge_adjustments_setup_tags =
      27              :     tmpl::list<Tags::BondiR, Tags::BondiJ, Tags::Dr<Tags::BondiJ>>;
      28              : 
      29              : /*!
      30              :  * \brief Computes the gauge-transformed
      31              :  * `Tags::EvolutionGaugeBoundaryValue<Tag>` for any of the boundary tags needed
      32              :  * in the evolution.
      33              :  *
      34              :  * \details Most of these computations involve first interpolating via a
      35              :  * `Spectral::Swsh::SwshInterpolator` to the new angular grid, followed by
      36              :  * manipulations associated with the tensor transformation of the metric and its
      37              :  * derivatives. Individual template specializations contain detailed
      38              :  * explanations about the respective gauge transformations.
      39              :  */
      40              : template <typename Tag>
      41            1 : struct GaugeAdjustedBoundaryValue;
      42              : 
      43              : /*!
      44              :  * \brief Computes the evolution gauge Bondi \f$\hat R\f$ on the worldtube from
      45              :  * Cauchy gauge quantities
      46              :  *
      47              :  * \details The evolution gauge Bondi \f$\hat R\f$ obeys:
      48              :  *
      49              :  * \f{align*}{
      50              :  * \hat R = \hat \omega R(\hat x^{\hat A}),
      51              :  * \f}
      52              :  *
      53              :  * where the evaluation of \f$R\f$ at \f$\hat x^{\hat A}\f$ requires an
      54              :  * interpolation to the evolution coordinates, and \f$\hat \omega\f$ is the
      55              :  * conformal factor associated with the angular part of the gauge
      56              :  * transformation.
      57              :  */
      58              : template <>
      59            1 : struct GaugeAdjustedBoundaryValue<Tags::BondiR> {
      60            0 :   using return_tags =
      61              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiR>>;
      62            0 :   using argument_tags = tmpl::list<
      63              :       Tags::BoundaryValue<Tags::BondiR>, Tags::PartiallyFlatGaugeOmega,
      64              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>>;
      65              : 
      66            0 :   static void apply(
      67              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
      68              :           evolution_gauge_r,
      69              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& cauchy_gauge_r,
      70              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
      71              :       const Spectral::Swsh::SwshInterpolator& interpolator);
      72              : };
      73              : 
      74              : /*!
      75              :  * \brief Computes the evolution gauge \f$\partial_{\hat u} \hat R / \hat R\f$
      76              :  * on the worldtube.
      77              :  *
      78              :  * \details The evolution gauge quantity \f$ \partial_{\hat u} \hat R / \hat
      79              :  * R\f$ obeys
      80              :  *
      81              :  * \f{align*}{
      82              :  *  \frac{\partial_{\hat u} \hat R}{ \hat R}
      83              :  * = \frac{\partial_u R (\hat x^{\hat A})}{R(\hat x^{\hat A})}
      84              :  * + \frac{\partial_{\hat u} \hat \omega}{\hat \omega}
      85              :  * + \frac{\mathcal U^{(0)} \bar \eth R(\hat x^{\hat A})
      86              :  * + \bar{\mathcal U}^{(0)} \eth R(\hat x^{\hat A}) }{2 R(\hat x^{\hat A})}
      87              :  * \f}
      88              :  *
      89              :  * note that the terms proportional to \f$\eth R\f$ or its conjugate arise from
      90              :  * the conversion between \f$\partial_u\f$ and \f$\partial_{\hat u}f\f$. The
      91              :  * right-hand side quantities with explicit \f$\hat x\f$ require interpolation.
      92              :  * \f$\mathcal U^{(0)}\f$ is the asymptotic quantity determined by
      93              :  * `GaugeUpdateTimeDerivatives`.
      94              :  */
      95              : template <>
      96            1 : struct GaugeAdjustedBoundaryValue<Tags::DuRDividedByR> {
      97            0 :   using return_tags =
      98              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::DuRDividedByR>>;
      99            0 :   using argument_tags = tmpl::list<
     100              :       Tags::BoundaryValue<Tags::DuRDividedByR>, Tags::BondiUAtScri,
     101              :       Tags::EvolutionGaugeBoundaryValue<Tags::BondiR>,
     102              :       Tags::PartiallyFlatGaugeOmega, Tags::Du<Tags::PartiallyFlatGaugeOmega>,
     103              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>,
     104              :       Tags::LMax>;
     105              : 
     106            0 :   static void apply(
     107              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
     108              :           evolution_gauge_du_r_divided_by_r,
     109              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>&
     110              :           cauchy_gauge_du_r_divided_by_r,
     111              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& bondi_u_at_scri,
     112              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
     113              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     114              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& du_omega,
     115              :       const Spectral::Swsh::SwshInterpolator& interpolator, size_t l_max);
     116              : };
     117              : 
     118              : /*!
     119              :  * \brief Computes the evolution gauge quantity \f$\hat J\f$ on the worldtube
     120              :  *
     121              :  * \details The evolution gauge quantity \f$\hat J\f$ obeys
     122              :  *
     123              :  * \f{align*}{
     124              :  * \hat J = \frac{1}{4 \hat{\omega}^2} \left( \bar{\hat d}^2  J(\hat x^{\hat A})
     125              :  * + \hat c^2 \bar J(\hat x^{\hat A})
     126              :  * + 2 \hat c \bar{\hat d} K(\hat x^{\hat A}) \right)
     127              :  * \f}
     128              :  *
     129              :  * Where \f$\hat c\f$ and \f$\hat d\f$ are the spin-weighted angular Jacobian
     130              :  * factors computed by `GaugeUpdateJacobianFromCoords`, and \f$\hat \omega\f$ is
     131              :  * the conformal factor associated with the angular coordinate transformation.
     132              :  * Note that the right-hand sides with explicit \f$\hat x^{\hat A}\f$ dependence
     133              :  * must be interpolated and that \f$K = \sqrt{1 + J \bar J}\f$.
     134              :  */
     135              : template <>
     136            1 : struct GaugeAdjustedBoundaryValue<Tags::BondiJ> {
     137            0 :   using return_tags =
     138              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiJ>>;
     139            0 :   using argument_tags = tmpl::list<
     140              :       Tags::BoundaryValue<Tags::BondiJ>, Tags::PartiallyFlatGaugeC,
     141              :       Tags::PartiallyFlatGaugeD, Tags::PartiallyFlatGaugeOmega,
     142              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>>;
     143              : 
     144            0 :   static void apply(
     145              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 2>>*>
     146              :           evolution_gauge_j,
     147              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& cauchy_gauge_j,
     148              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& gauge_c,
     149              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& gauge_d,
     150              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     151              :       const Spectral::Swsh::SwshInterpolator& interpolator);
     152              : };
     153              : 
     154              : /*!
     155              :  * \brief Computes the evolution gauge quantity \f$\partial_{\hat r} \hat J\f$
     156              :  * on the worldtube
     157              :  *
     158              :  * \details The evolution gauge quantity \f$\partial_{\hat r} \hat J\f$ is
     159              :  * determined from \f$\partial_{\hat r} = \frac{\partial_r}{\hat \omega}\f$ and
     160              :  * the expression for \f$\hat J\f$ given in the documentation for
     161              :  * `GaugeAdjustedBoundaryValue<Tags::BondiJ>`
     162              :  */
     163              : template <>
     164            1 : struct GaugeAdjustedBoundaryValue<Tags::Dr<Tags::BondiJ>> {
     165            0 :   using return_tags =
     166              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::Dr<Tags::BondiJ>>>;
     167            0 :   using argument_tags = tmpl::list<
     168              :       Tags::BoundaryValue<Tags::Dr<Tags::BondiJ>>,
     169              :       Tags::BoundaryValue<Tags::BondiJ>, Tags::PartiallyFlatGaugeC,
     170              :       Tags::PartiallyFlatGaugeD, Tags::PartiallyFlatGaugeOmega,
     171              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>,
     172              :       Tags::LMax>;
     173              : 
     174            0 :   static void apply(
     175              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 2>>*>
     176              :           evolution_gauge_dr_j,
     177              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& cauchy_gauge_dr_j,
     178              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& cauchy_gauge_j,
     179              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& gauge_c,
     180              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& gauge_d,
     181              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     182              :       const Spectral::Swsh::SwshInterpolator& interpolator, size_t l_max);
     183              : };
     184              : 
     185              : /*!
     186              :  * \brief Computes the evolution gauge quantity \f$\hat \beta\f$ on the
     187              :  * worldtube
     188              :  *
     189              :  * \details The evolution gauge quantity \f$\hat \beta\f$ obeys
     190              :  *
     191              :  * \f{align*}{
     192              :  * e^{2 \hat \beta} = e^{2 \beta(\hat x^{\hat A})} / \hat \omega.
     193              :  * \f}
     194              :  *
     195              :  * The explicit evaluation at \f$\hat x^{\hat A}\f$ on the right-hand side
     196              :  * indicates the requirement of an interpolation step, and \f$\hat \omega\f$ is
     197              :  * the conformal factor associated with the angular transformation.
     198              :  */
     199              : template <>
     200            1 : struct GaugeAdjustedBoundaryValue<Tags::BondiBeta> {
     201            0 :   using return_tags =
     202              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiBeta>>;
     203            0 :   using argument_tags = tmpl::list<
     204              :       Tags::BoundaryValue<Tags::BondiBeta>, Tags::PartiallyFlatGaugeOmega,
     205              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>>;
     206              : 
     207            0 :   static void apply(
     208              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
     209              :           evolution_gauge_beta,
     210              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& cauchy_gauge_beta,
     211              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     212              :       const Spectral::Swsh::SwshInterpolator& interpolator);
     213              : };
     214              : 
     215              : /*!
     216              :  * \brief Computes the evolution gauge quantity \f$\hat Q\f$ on the worldtube.
     217              :  *
     218              :  * \details The evolution gauge quantity \f$\hat Q\f$ obeys
     219              :  *
     220              :  * \f{align*}{
     221              :  * \hat Q =& \hat r^2 e^{-2 \hat \beta} (\hat K \partial_{\hat r} \hat U
     222              :  * + \hat J \partial_{\hat r} \hat{\bar U}),\\
     223              :  * \partial_{\hat r} \hat U
     224              :  * =& \frac{1}{2 \hat \omega^3}\left(\hat{\bar d} \partial_r U(\hat x^{\hat A})
     225              :  * - \hat c \partial_r \bar U(\hat x^{\hat A})\right)
     226              :  * + \frac{e^{2\hat \beta}}{\hat r^2 \hat \omega}
     227              :  * \left(\hat J \hat{\bar{\eth}} \hat \omega
     228              :  * - \hat K \hat \eth \hat \omega\right)
     229              :  * \left(-1 + \partial_{\hat y} \hat{\bar{J}} \partial_{\hat y} \hat J
     230              :  * - \left[\frac{\partial_{\hat y}(\hat J \hat{\bar{J}})}
     231              :  * {2 \hat K}\right]^2\right) \notag \\
     232              :  * & + 2 \frac{e^{2 \hat \beta}}{\hat \omega \hat r^2}
     233              :  * \left[ \hat{\bar{\eth}} \hat \omega \partial_{\hat y} \hat J
     234              :  * + \hat{\eth} \hat \omega \left(-\frac{\hat J \partial_{\hat y}
     235              :  * \hat{\bar J}
     236              :  * + \hat{\bar J} \partial_{\hat y} \hat J}{2 \hat K}\right) \right].
     237              :  * \f}
     238              :  *
     239              :  * where the explicit argument \f$\hat x^{\hat A}\f$ on the right-hand side
     240              :  * implies the need for an interpolation operation, and
     241              :  * \f$K = \sqrt{1 + J \bar J}\f$.
     242              :  */
     243              : template <>
     244            1 : struct GaugeAdjustedBoundaryValue<Tags::BondiQ> {
     245            0 :   using return_tags =
     246              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiQ>>;
     247              : 
     248            0 :   using argument_tags = tmpl::list<
     249              :       Tags::BoundaryValue<Tags::Dr<Tags::BondiU>>, Tags::BondiJ,
     250              :       Tags::Dy<Tags::BondiJ>, Tags::EvolutionGaugeBoundaryValue<Tags::BondiR>,
     251              :       Tags::EvolutionGaugeBoundaryValue<Tags::BondiBeta>,
     252              :       Tags::PartiallyFlatGaugeC, Tags::PartiallyFlatGaugeD,
     253              :       Tags::PartiallyFlatGaugeOmega,
     254              :       Spectral::Swsh::Tags::Derivative<Tags::PartiallyFlatGaugeOmega,
     255              :                                        Spectral::Swsh::Tags::Eth>,
     256              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>,
     257              :       Tags::LMax>;
     258              : 
     259            0 :   static void apply(
     260              :       const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*>
     261              :           evolution_gauge_q,
     262              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& cauchy_gauge_dr_u,
     263              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& volume_j,
     264              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& volume_dy_j,
     265              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
     266              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_beta,
     267              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& gauge_c,
     268              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& gauge_d,
     269              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     270              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
     271              :       const Spectral::Swsh::SwshInterpolator& interpolator,
     272              :       const size_t l_max) {
     273              :     apply_impl(make_not_null(&get(*evolution_gauge_q)), get(cauchy_gauge_dr_u),
     274              :                get(volume_j), get(volume_dy_j), get(evolution_gauge_r),
     275              :                get(evolution_gauge_beta), get(gauge_c), get(gauge_d),
     276              :                get(omega), get(eth_omega), interpolator, l_max);
     277              :   }
     278              : 
     279              :  private:
     280            0 :   static void apply_impl(
     281              :       gsl::not_null<SpinWeighted<ComplexDataVector, 1>*> evolution_gauge_q,
     282              :       const SpinWeighted<ComplexDataVector, 1>& cauchy_gauge_dr_u,
     283              :       const SpinWeighted<ComplexDataVector, 2>& volume_j,
     284              :       const SpinWeighted<ComplexDataVector, 2>& volume_dy_j,
     285              :       const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_r,
     286              :       const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_beta,
     287              :       const SpinWeighted<ComplexDataVector, 2>& gauge_c,
     288              :       const SpinWeighted<ComplexDataVector, 0>& gauge_d,
     289              :       const SpinWeighted<ComplexDataVector, 0>& omega,
     290              :       const SpinWeighted<ComplexDataVector, 1>& eth_omega,
     291              :       const Spectral::Swsh::SwshInterpolator& interpolator, size_t l_max);
     292              : };
     293              : 
     294              : /*!
     295              :  * \brief Computes the evolution gauge quantity \f$\mathcal U\f$ on the
     296              :  * worldtube.
     297              :  *
     298              :  * \details Note that the boundary quantity computed by this function is, by
     299              :  * necessity, NOT the evolution gauge bondi \f$\hat U\f$, because there is
     300              :  * insufficient information at the point in the computation this will be
     301              :  * evaluated to completely determine \f$\hat{U}\f$. Instead, this determines
     302              :  * the boundary value of \f$\mathcal U\f$, which satisfies,
     303              :  *
     304              :  * \f{align*}{
     305              :  * \mathcal{U} - \mathcal{U}^{(0)} = \hat U,
     306              :  * \f}
     307              :  *
     308              :  * where the superscript \f$(0)\f$ denotes evaluation at \f$\mathcal I^+\f$. In
     309              :  * particular, the result of this computation may be used with the same
     310              :  * hypersurface equations as the full evolution gauge \f$\hat U\f$, because they
     311              :  * satisfy the same radial differential equation.
     312              :  *
     313              :  * \f$\mathcal U\f$ is computed by,
     314              :  *
     315              :  * \f{align*}{
     316              :  * \mathcal U = \frac{1}{2\hat \omega^2} \left(\hat{\bar d} U(\hat x^{\hat A})
     317              :  * - \hat c \bar U(\hat x^{\hat A}) \right)
     318              :  * - \frac{e^{2 \hat \beta}}{\hat r \hat \omega}
     319              :  * \left(\hat K \hat \eth \hat \omega
     320              :  * -  \hat J\hat{\bar{\eth}} \hat \omega\right),
     321              :  * \f}
     322              :  *
     323              :  * where the explicit argument \f$\hat x^{\hat A}\f$ on the right-hand side
     324              :  * implies the need for an interpolation operation, and
     325              :  * \f$K = \sqrt{1 + J \bar J}\f$.
     326              :  */
     327              : template <>
     328            1 : struct GaugeAdjustedBoundaryValue<Tags::BondiU> {
     329            0 :   using return_tags =
     330              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiU>>;
     331            0 :   using argument_tags = tmpl::list<
     332              :       Tags::BoundaryValue<Tags::BondiU>, Tags::BondiJ,
     333              :       Tags::EvolutionGaugeBoundaryValue<Tags::BondiR>,
     334              :       Tags::EvolutionGaugeBoundaryValue<Tags::BondiBeta>,
     335              :       Tags::PartiallyFlatGaugeC, Tags::PartiallyFlatGaugeD,
     336              :       Tags::PartiallyFlatGaugeOmega,
     337              :       Spectral::Swsh::Tags::Derivative<Tags::PartiallyFlatGaugeOmega,
     338              :                                        Spectral::Swsh::Tags::Eth>,
     339              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>,
     340              :       Tags::LMax>;
     341              : 
     342            0 :   static void apply(
     343              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*>
     344              :           evolution_gauge_u,
     345              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& cauchy_gauge_u,
     346              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& volume_j,
     347              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
     348              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_beta,
     349              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& gauge_c,
     350              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& gauge_d,
     351              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     352              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
     353              :       const Spectral::Swsh::SwshInterpolator& interpolator, size_t l_max);
     354              : };
     355              : 
     356              : /*!
     357              :  * \brief Computes the evolution gauge quantity \f$\hat W\f$ on the worldtube.
     358              :  *
     359              :  * \details The evolution gauge value \f$\hat W\f$ obeys
     360              :  *
     361              :  * \f{align*}{
     362              :  * \hat W =& W(\hat x^{\hat A}) + (\hat \omega - 1) / \hat r
     363              :  * + \frac{e^{2 \hat \beta}}{2 \hat \omega^2 \hat r}
     364              :  * \left(\hat J \left(\hat{\bar \eth} \hat \omega\right)^2
     365              :  * + \hat{\bar{J}} \left(\hat \eth \hat \omega\right) ^2
     366              :  * - 2 K \left( \hat \eth \hat \omega\right) \left(\hat{\bar \eth} \hat
     367              :  * \omega\right) \right)
     368              :  * - \frac{2 \partial_{u} \hat \omega}{\hat \omega}
     369              :  * - \frac{ \hat U \bar \eth \hat \omega + \hat{\bar U} \eth \hat \omega }
     370              :  * {\hat \omega},
     371              :  * \f}
     372              :  *
     373              :  * where the explicit argument \f$\hat x^{\hat A}\f$ on the right-hand side
     374              :  * implies the need for an interpolation operation and
     375              :  * \f$K = \sqrt{1 + J \bar J}\f$.
     376              :  */
     377              : template <>
     378            1 : struct GaugeAdjustedBoundaryValue<Tags::BondiW> {
     379            0 :   using return_tags =
     380              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiW>>;
     381            0 :   using argument_tags = tmpl::list<
     382              :       Tags::BoundaryValue<Tags::BondiW>, Tags::BondiJ,
     383              :       Tags::EvolutionGaugeBoundaryValue<Tags::BondiU>,
     384              :       Tags::EvolutionGaugeBoundaryValue<Tags::BondiBeta>, Tags::BondiUAtScri,
     385              :       Tags::EvolutionGaugeBoundaryValue<Tags::BondiR>,
     386              :       Tags::PartiallyFlatGaugeOmega, Tags::Du<Tags::PartiallyFlatGaugeOmega>,
     387              :       Spectral::Swsh::Tags::Derivative<Tags::PartiallyFlatGaugeOmega,
     388              :                                        Spectral::Swsh::Tags::Eth>,
     389              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>,
     390              :       Tags::LMax>;
     391              : 
     392            0 :   static void apply(
     393              :       const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
     394              :           evolution_gauge_w,
     395              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& cauchy_gauge_w,
     396              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& volume_j,
     397              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& evolution_gauge_u,
     398              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_beta,
     399              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>&
     400              :           evolution_gauge_u_at_scri,
     401              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
     402              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     403              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& du_omega,
     404              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
     405              :       const Spectral::Swsh::SwshInterpolator& interpolator,
     406              :       const size_t l_max) {
     407              :     apply_impl(make_not_null(&get(*evolution_gauge_w)), get(cauchy_gauge_w),
     408              :                get(volume_j), get(evolution_gauge_u), get(evolution_gauge_beta),
     409              :                get(evolution_gauge_u_at_scri), get(evolution_gauge_r),
     410              :                get(omega), get(du_omega), get(eth_omega), interpolator, l_max);
     411              :   }
     412              : 
     413              :  private:
     414            0 :   static void apply_impl(
     415              :       gsl::not_null<SpinWeighted<ComplexDataVector, 0>*> evolution_gauge_w,
     416              :       const SpinWeighted<ComplexDataVector, 0>& cauchy_gauge_w,
     417              :       const SpinWeighted<ComplexDataVector, 2>& volume_j,
     418              :       const SpinWeighted<ComplexDataVector, 1>& evolution_gauge_u,
     419              :       const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_beta,
     420              :       const SpinWeighted<ComplexDataVector, 1>& evolution_gauge_u_at_scri,
     421              :       const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_r,
     422              :       const SpinWeighted<ComplexDataVector, 0>& omega,
     423              :       const SpinWeighted<ComplexDataVector, 0>& du_omega,
     424              :       const SpinWeighted<ComplexDataVector, 1>& eth_omega,
     425              :       const Spectral::Swsh::SwshInterpolator& interpolator, size_t l_max);
     426              : };
     427              : 
     428              : /*!
     429              :  * \brief Computes the evolution gauge quantity \f$\hat H\f$ on the worldtube.
     430              :  *
     431              :  * \details The evolution gauge \f$\hat H\f$ obeys
     432              :  *
     433              :  * \f{align*}{
     434              :  *   \hat H =&
     435              :  * \frac{1}{2} \left(\mathcal{U}^{(0)} \hat{\bar \eth} \hat J
     436              :  * + \bar{\mathcal{U}}^{(0)} \hat{\eth} \hat J\right)
     437              :  * + \frac{\partial_{\hat u} \hat \omega
     438              :  * - \tfrac{1}{2} \left(\mathcal{U}^{(0)} \bar{\hat \eth}\hat \omega
     439              :  * + \bar{\mathcal{U}}^{(0)} \hat \eth \hat \omega \right) }{\hat \omega}
     440              :  * \left(2 \hat J - 2 \partial_{\hat y} \hat J\right)
     441              :  * - \hat J\hat{\bar \eth} \mathcal{U}^{(0)}
     442              :  * + \hat K \hat \eth \bar{\mathcal{U}}^{(0)}  \notag\\
     443              :  * &+ \frac{1}{4 \hat \omega^2} \left(\hat{\bar d}^2 H(\hat x^{\hat A})
     444              :  * + \hat c^2 \bar H(\hat x^{\hat A})
     445              :  * + \hat{\bar d} \hat c \frac{H(\hat x^{\hat A}) \bar J(\hat x^{\hat A})
     446              :  * + J(\hat x^{\hat A}) \bar H(\hat x^{\hat A})}{K}\right)
     447              :  * + 2 \frac{\partial_u R}{R} \partial_{\hat y} J
     448              :  * \f}
     449              :  *
     450              :  * where the superscript \f$(0)\f$ denotes evaluation at \f$\mathcal I^+\f$ and
     451              :  * the explicit \f$\hat x^{\hat A}\f$ arguments on the right-hand side imply
     452              :  * interpolation operations, and \f$K = \sqrt{1 + J \bar J}\f$,
     453              :  * \f$\hat K = \sqrt{1 + \hat J \hat{\bar J}}\f$.
     454              :  *
     455              :  * The interpolated source-gauge angular metric is
     456              :  *
     457              :  * \f{align*}{
     458              :  * J(\hat x^{\hat A}) &=
     459              :  *   \frac{\hat d^2\hat J+\hat c^2\hat{\bar J}
     460              :  *         -2\hat c\hat d\hat K}{4\hat\omega^2}, &
     461              :  * K(\hat x^{\hat A}) &=
     462              :  *   \sqrt{1+J(\hat x^{\hat A})\bar J(\hat x^{\hat A})}.
     463              :  * \f}
     464              :  *
     465              :  * These expressions follow by inverting Eqs. (32) and (33b) of
     466              :  * \cite Moxon2020gha.
     467              :  */
     468              : template <>
     469            1 : struct GaugeAdjustedBoundaryValue<Tags::BondiH> {
     470            0 :   using return_tags =
     471              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiH>>;
     472            0 :   using argument_tags = tmpl::list<
     473              :       Tags::BondiJ, Tags::BoundaryValue<Tags::Du<Tags::BondiJ>>,
     474              :       Tags::Dy<Tags::BondiJ>, Tags::BondiUAtScri,
     475              :       Tags::EvolutionGaugeBoundaryValue<Tags::BondiR>,
     476              :       Tags::PartiallyFlatGaugeC, Tags::PartiallyFlatGaugeD,
     477              :       Tags::PartiallyFlatGaugeOmega, Tags::Du<Tags::PartiallyFlatGaugeOmega>,
     478              :       Spectral::Swsh::Tags::Derivative<Tags::PartiallyFlatGaugeOmega,
     479              :                                        Spectral::Swsh::Tags::Eth>,
     480              :       Tags::EvolutionGaugeBoundaryValue<Tags::DuRDividedByR>,
     481              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>,
     482              :       Tags::LMax>;
     483              : 
     484            0 :   static void apply(
     485              :       const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 2>>*>
     486              :           evolution_gauge_h,
     487              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& volume_j,
     488              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& cauchy_gauge_du_j,
     489              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& volume_dy_j,
     490              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>&
     491              :           evolution_gauge_u_at_scri,
     492              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
     493              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& gauge_c,
     494              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& gauge_d,
     495              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     496              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& du_omega,
     497              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
     498              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>&
     499              :           evolution_gauge_du_r_divided_by_r,
     500              :       const Spectral::Swsh::SwshInterpolator& interpolator,
     501              :       const size_t l_max) {
     502              :     apply_impl(make_not_null(&get(*evolution_gauge_h)), get(volume_j),
     503              :                get(cauchy_gauge_du_j), get(volume_dy_j),
     504              :                get(evolution_gauge_u_at_scri), get(evolution_gauge_r),
     505              :                get(gauge_c), get(gauge_d), get(omega), get(du_omega),
     506              :                get(eth_omega), get(evolution_gauge_du_r_divided_by_r),
     507              :                interpolator, l_max);
     508              :   }
     509              : 
     510              :  private:
     511            0 :   static void apply_impl(
     512              :       gsl::not_null<SpinWeighted<ComplexDataVector, 2>*> evolution_gauge_h,
     513              :       const SpinWeighted<ComplexDataVector, 2>& volume_j,
     514              :       const SpinWeighted<ComplexDataVector, 2>& cauchy_gauge_du_j,
     515              :       const SpinWeighted<ComplexDataVector, 2>& volume_dy_j,
     516              :       const SpinWeighted<ComplexDataVector, 1>& evolution_gauge_u_at_scri,
     517              :       const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_r,
     518              :       const SpinWeighted<ComplexDataVector, 2>& gauge_c,
     519              :       const SpinWeighted<ComplexDataVector, 0>& gauge_d,
     520              :       const SpinWeighted<ComplexDataVector, 0>& omega,
     521              :       const SpinWeighted<ComplexDataVector, 0>& du_omega,
     522              :       const SpinWeighted<ComplexDataVector, 1>& eth_omega,
     523              :       const SpinWeighted<ComplexDataVector, 0>&
     524              :           evolution_gauge_du_r_divided_by_r,
     525              :       const Spectral::Swsh::SwshInterpolator& interpolator, size_t l_max);
     526              : };
     527              : 
     528              : /*!
     529              :  * \brief Computes the evolution gauge quantity \f$\hat \Pi\f$ for the scalar
     530              :  * field on the worldtube.
     531              :  *
     532              :  * \details The evolution gauge \f$\hat \Pi\f$ obeys
     533              :  * \f{align*}{
     534              :  *   \hat \Pi = \partial_{t^\prime} \psi + \Re
     535              :  *   \left(\mathcal{U}^{(0)}\bar{\eth}\psi\right)
     536              :  * \f}
     537              :  *
     538              :  * where \f$\partial_{t^\prime} \psi\f$ comes from the Cauchy evolution.
     539              :  */
     540              : template <>
     541            1 : struct GaugeAdjustedBoundaryValue<Tags::KleinGordonPi> {
     542            0 :   using return_tags =
     543              :       tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::KleinGordonPi>>;
     544            0 :   using argument_tags = tmpl::list<
     545              :       Tags::BoundaryValue<Tags::KleinGordonPi>, Tags::BondiUAtScri,
     546              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::CauchyAngularCoords>,
     547              :       Tags::LMax, Tags::KleinGordonPsi>;
     548              : 
     549            0 :   static void apply(
     550              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
     551              :           evolution_kg_pi,
     552              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& cauchy_kg_pi,
     553              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>&
     554              :           evolution_gauge_u_at_scri,
     555              :       const Spectral::Swsh::SwshInterpolator& interpolator, size_t l_max,
     556              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& volume_psi);
     557              : };
     558              : 
     559              : /*!
     560              :  * \brief Update the Cauchy gauge cartesian coordinate derivative \f$\partial_u
     561              :  * x(\hat x)\f$, as well as remaining gauge quantities \f$\mathcal U^{(0)}\f$,
     562              :  * \f$\hat U \equiv \mathcal U - \mathcal U^{(0)}\f$, and \f$\partial_{\hat u}
     563              :  * \hat \omega\f$ to maintain asymptotically inertial angular coordinates.
     564              :  *
     565              :  * \details The constraint we must satisfy to maintain the asymptotically
     566              :  * inertial angular coordinates is
     567              :  *
     568              :  * \f{align*}{
     569              :  * \partial_{\hat u} x^A =  \mathcal U^{(0) \hat A} \partial_{\hat A} x^{A},
     570              :  * \f}
     571              :  *
     572              :  * which we compute for a representative Cartesian coordinate set on the unit
     573              :  * sphere, to maintain representability and ensure that angular transform and
     574              :  * derivative operations keep the desired precision. The equation we use for the
     575              :  * Cartesian analog is:
     576              :  *
     577              :  * \f{align*}{
     578              :  * \partial_{\hat u} x^i &= \frac{1}{2} (\bar{\mathcal U}^{(0)} \hat \eth x^i +
     579              :  * \mathcal U^{(0)} \hat{\bar \eth} x^i ) \\
     580              :  * &= \text{Re}(\bar{\mathcal U}^{(0)} \hat \eth x^i)
     581              :  * \f}
     582              :  *
     583              :  * This computation completes the unfixed degrees of freedom for the coordinate
     584              :  * transformation at the boundary, so also computes the gauge quantities that
     585              :  * rely on this information \f$\mathcal U^{(0)}\f$,
     586              :  * \f$\hat U\f$, and \f$\partial_{\hat u} \hat \omega\f$.
     587              :  *
     588              :  * The time derivative of \f$\hat \omega\f$ is calculated from the equation
     589              :  * \f{align*}{
     590              :  * \partial_{\hat u} \hat \omega
     591              :  * = \frac{\hat \omega}{4} (\hat{\bar \eth} \mathcal U^{(0)}
     592              :  * + \hat \eth \bar{\mathcal U}^{(0)})
     593              :  * + \frac{1}{2} (\mathcal U^{(0)} \hat{\bar \eth} \hat \omega
     594              :  * + \bar{\mathcal U}^{(0)} \hat \eth \hat \omega)
     595              :  * \f}
     596              :  * \warning Before this update call the quantity stored in the tag
     597              :  * `Cce::Tags::BondiU` represents \f$\mathcal U\f$, and after this update call,
     598              :  * it represents \f$\hat U\f$ (the true evolution gauge quantity).
     599              :  */
     600            1 : struct GaugeUpdateTimeDerivatives {
     601            0 :   using return_tags =
     602              :       tmpl::list<::Tags::dt<Tags::CauchyCartesianCoords>, Tags::BondiUAtScri,
     603              :                  Tags::BondiU, Tags::Du<Tags::PartiallyFlatGaugeOmega>>;
     604            0 :   using argument_tags =
     605              :       tmpl::list<Tags::CauchyCartesianCoords, Tags::PartiallyFlatGaugeOmega,
     606              :                  Spectral::Swsh::Tags::Derivative<Tags::PartiallyFlatGaugeOmega,
     607              :                                                   Spectral::Swsh::Tags::Eth>,
     608              :                  Tags::LMax>;
     609              : 
     610            0 :   static void apply(
     611              :       gsl::not_null<tnsr::i<DataVector, 3>*> cartesian_cauchy_du_x,
     612              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*>
     613              :           evolution_gauge_u_at_scri,
     614              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*> volume_u,
     615              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*> du_omega,
     616              :       const tnsr::i<DataVector, 3>& cartesian_cauchy_coordinates,
     617              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     618              :       const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
     619              :       size_t l_max);
     620              : };
     621              : 
     622              : /*!
     623              :  * \brief Update the inertial gauge cartesian coordinate derivative
     624              :  * \f$\partial_u \hat x(x)\f$.
     625              :  *
     626              :  * \details For the asymptotically inertial angular coordinates
     627              :  * \f$\hat{x}^{\hat{A}}\f$, we have:
     628              :  *
     629              :  * \f{align*}{
     630              :  * \partial_u \hat{x}^{\hat{A}} = -U^{(0)B}\partial_B \hat{x}^{\hat{A}}
     631              :  * \f}
     632              :  *
     633              :  * and the Cartesian version reads
     634              :  *
     635              :  * \f{align*}{
     636              :  * \partial_u \hat{x}^{\hat{i}}= - \text{Re}(\bar{U}^{(0)}
     637              :  * \eth \hat{x}^{\hat{i}})
     638              :  * \f}
     639              :  *
     640              :  * Note that \f$U^{0}\f$ and \f$\mathcal U^{(0)}\f$ are related by
     641              :  *
     642              :  * \f{align*}{
     643              :  * U^{(0)} &= \frac{1}{2\omega^2} \left( \bar{d} \mathcal U^{(0)} -
     644              :  * c \bar{\mathcal U}^{(0)} \right) \\
     645              :  * &= \frac{\hat \omega^2}{2} \left( \bar{d} \mathcal U^{(0)} -
     646              :  * c \bar{\mathcal U}^{(0)} \right)
     647              :  * \f}
     648              :  *
     649              :  * see Eq. (79) of \cite Moxon2020gha.
     650              :  */
     651            1 : struct GaugeUpdateInertialTimeDerivatives {
     652            0 :   using return_tags = tmpl::list<::Tags::dt<Tags::PartiallyFlatCartesianCoords>,
     653              :                                  Tags::BondiUAtScri>;
     654            0 :   using argument_tags = tmpl::list<
     655              :       Tags::PartiallyFlatCartesianCoords, Tags::CauchyGaugeC,
     656              :       Tags::PartiallyFlatGaugeOmega, Tags::CauchyGaugeD, Tags::LMax,
     657              :       Spectral::Swsh::Tags::SwshInterpolator<Tags::PartiallyFlatAngularCoords>>;
     658            0 :   static void apply(
     659              :       gsl::not_null<tnsr::i<DataVector, 3>*> cartesian_inertial_du_x,
     660              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*>
     661              :           evolution_gauge_u_at_scri,
     662              :       const tnsr::i<DataVector, 3>& cartesian_inertial_coordinates,
     663              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& gauge_cauchy_c,
     664              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& omega,
     665              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& gauge_cauchy_d,
     666              :       size_t l_max, const Spectral::Swsh::SwshInterpolator& interpolator);
     667              : };
     668              : 
     669              : /*!
     670              :  * \brief Update the angular coordinates stored in `AngularTag` via
     671              :  * trigonometric operations applied to the Cartesian coordinates stored in
     672              :  * `CartesianTag`.
     673              :  *
     674              :  * \details This function also normalizes the Cartesian coordinates stored in
     675              :  * `CartesianTag`, which is the desired behavior for the CCE boundary
     676              :  * computation.
     677              :  */
     678              : template <typename AngularTag, typename CartesianTag>
     679            1 : struct GaugeUpdateAngularFromCartesian {
     680            0 :   using argument_tags = tmpl::list<>;
     681            0 :   using return_tags = tmpl::list<AngularTag, CartesianTag>;
     682              : 
     683            0 :   static void apply(
     684              :       const gsl::not_null<
     685              :           tnsr::i<DataVector, 2, ::Frame::Spherical<::Frame::Inertial>>*>
     686              :           angular_coordinates,
     687              :       const gsl::not_null<tnsr::i<DataVector, 3>*> cartesian_coordinates) {
     688              :     // normalize the cartesian coordinates
     689              :     const DataVector one_over_cartesian_r =
     690              :         1.0 / sqrt(square(get<0>(*cartesian_coordinates)) +
     691              :                    square(get<1>(*cartesian_coordinates)) +
     692              :                    square(get<2>(*cartesian_coordinates)));
     693              : 
     694              :     get<0>(*cartesian_coordinates) *= one_over_cartesian_r;
     695              :     get<1>(*cartesian_coordinates) *= one_over_cartesian_r;
     696              :     get<2>(*cartesian_coordinates) *= one_over_cartesian_r;
     697              : 
     698              :     const auto& x = get<0>(*cartesian_coordinates);
     699              :     const auto& y = get<1>(*cartesian_coordinates);
     700              :     const auto& z = get<2>(*cartesian_coordinates);
     701              : 
     702              :     get<0>(*angular_coordinates) = atan2(sqrt(square(x) + square(y)), z);
     703              :     get<1>(*angular_coordinates) = atan2(y, x);
     704              :   }
     705              : };
     706              : 
     707              : namespace detail {
     708              : void gauge_update_jacobian_from_coordinates_apply_impl(
     709              :     gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 2>>*>
     710              :         gauge_factor_spin_2,
     711              :     gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
     712              :         gauge_factor_spin_0,
     713              :     const tnsr::i<DataVector, 2, ::Frame::Spherical<::Frame::Inertial>>&
     714              :         angular_source_coordinates,
     715              :     const tnsr::i<DataVector, 3>& cartesian_source_coordinates, size_t l_max);
     716              : }  // namespace detail
     717              : 
     718              : /*!
     719              :  * \brief From the angular coordinates `AngularCoordinateTag` and the Cartesian
     720              :  * coordinates `CartesianCoordinateTag`, determine the spin-weighted Jacobian
     721              :  * factors `GaugeFactorSpin2` and `GaugeFactorSpin0`.
     722              :  *
     723              :  * \details This is most often used in the context of generating the Jacobians
     724              :  * in the evolution-gauge coordinates from the Cauchy collocation points as a
     725              :  * function of the evolution gauge coordinates. In this concrete case, the
     726              :  * `GaugeFactorSpin2` is the gauge factor \f$\hat c\f$ and takes the value
     727              :  *
     728              :  * \f{align*}{
     729              :  * \hat c = \hat q^{\hat A} \partial_{\hat A}(x^A) q_A,
     730              :  * \f}
     731              :  *
     732              :  * and the `GaugeFactorSpin0` is the gauge factor \f$\hat d\f$ and takes the
     733              :  * value
     734              :  *
     735              :  * \f{align*}{
     736              :  * \hat d = \hat{\bar q}^{\hat A} \partial_{\hat A}(x^A) q_A.
     737              :  * \f}
     738              :  *
     739              :  * The more generic template construction is employed so that the spin-weighted
     740              :  * Jacobians can also be computed between two arbitrary gauges, including the
     741              :  * inverse Jacobians associated with moving from the evolution gauge to the
     742              :  * Cauchy gauge.
     743              :  */
     744              : template <typename GaugeFactorSpin2, typename GaugeFactorSpin0,
     745              :           typename AngularCoordinateTag, typename CartesianCoordinateTag>
     746            1 : struct GaugeUpdateJacobianFromCoordinates {
     747            0 :   using return_tags = tmpl::list<GaugeFactorSpin2, GaugeFactorSpin0>;
     748            0 :   using argument_tags =
     749              :       tmpl::list<AngularCoordinateTag, CartesianCoordinateTag, Tags::LMax>;
     750              : 
     751            0 :   static void apply(
     752              :       const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 2>>*>
     753              :           gauge_factor_spin_2,
     754              :       const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
     755              :           gauge_factor_spin_0,
     756              :       const tnsr::i<DataVector, 2, ::Frame::Spherical<::Frame::Inertial>>&
     757              :           angular_source_coordinates,
     758              :       const tnsr::i<DataVector, 3>& cartesian_source_coordinates,
     759              :       const size_t l_max) {
     760              :     detail::gauge_update_jacobian_from_coordinates_apply_impl(
     761              :         gauge_factor_spin_2, gauge_factor_spin_0, angular_source_coordinates,
     762              :         cartesian_source_coordinates, l_max);
     763              :   }
     764              : };
     765              : 
     766              : /*!
     767              :  * \brief Update the interpolator stored in
     768              :  * `Spectral::Swsh::Tags::SwshInterpolator<AngularCoordinates>`.
     769              :  *
     770              :  * \details Note that the `AngularCoordinates` associated with the interpolator
     771              :  * should be the source coordinates. For instance, when interpolating a quantity
     772              :  * defined on the Cauchy gauge collocation points to the evolution gauge
     773              :  * collocation points, the interpolator input should be the Cauchy coordinates
     774              :  * points as a function of the evolution gauge coordinates (at the evolution
     775              :  * gauge collocation points).
     776              :  */
     777              : template <typename AngularCoordinates>
     778            1 : struct GaugeUpdateInterpolator {
     779            0 :   using return_tags =
     780              :       tmpl::list<Spectral::Swsh::Tags::SwshInterpolator<AngularCoordinates>>;
     781            0 :   using argument_tags = tmpl::list<AngularCoordinates, Tags::LMax>;
     782              : 
     783            0 :   static void apply(
     784              :       const gsl::not_null<Spectral::Swsh::SwshInterpolator*> interpolator,
     785              :       const tnsr::i<DataVector, 2, ::Frame::Spherical<::Frame::Inertial>>&
     786              :           angular_coordinates,
     787              :       const size_t l_max) {
     788              :     // throw away the old interpolator and generate a new one for the current
     789              :     // grid points.
     790              :     *interpolator = Spectral::Swsh::SwshInterpolator(
     791              :         get<0>(angular_coordinates), get<1>(angular_coordinates), l_max);
     792              :   }
     793              : };
     794              : 
     795              : /*!
     796              :  * \brief Update the quantity \f$\hat \omega\f$ and \f$\hat \eth \hat \omega\f$
     797              :  * for updated spin-weighted Jacobian quantities \f$\hat c\f$ and \f$\hat d\f$.
     798              :  *
     799              :  * \details The conformal factor \f$\hat \omega\f$ can be determined by the
     800              :  * angular determinant from the spin-weighted Jacobian factors as
     801              :  *
     802              :  * \f{align*}{
     803              :  * \hat \omega = \frac{1}{2} \sqrt{\hat d \hat{\bar d} - \hat c \hat{\bar c}}.
     804              :  * \f}
     805              :  */
     806              : template <typename GaugeC, typename GaugeD, typename GaugeOmega>
     807            1 : struct GaugeUpdateOmega {
     808            0 :   using argument_tags = tmpl::list<GaugeC, GaugeD, Tags::LMax>;
     809            0 :   using return_tags = tmpl::list<
     810              :       GaugeOmega,
     811              :       Spectral::Swsh::Tags::Derivative<GaugeOmega, Spectral::Swsh::Tags::Eth>>;
     812              : 
     813            0 :   static void apply(
     814              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*> omega,
     815              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*> eth_omega,
     816              :       const Scalar<SpinWeighted<ComplexDataVector, 2>>& gauge_c,
     817              :       const Scalar<SpinWeighted<ComplexDataVector, 0>>& gauge_d, size_t l_max);
     818              : };
     819              : 
     820              : /*!
     821              :  * \brief Initialize to default values (identity transform) all of the angular
     822              :  * gauge quantities for the boundary gauge transforms.
     823              :  *
     824              :  * \details The updated quantities are the Cauchy angular and Cartesian
     825              :  * coordinates, as well as the spin-weighted gauge factors and the conformal
     826              :  * factor. All quantities are initialized to the appropriate value for the
     827              :  * identity transform of angular coordinates. Using this initialization function
     828              :  * ensures that the evolution gauge and the Cauchy gauge angular coordinates
     829              :  * agree on the first evaluated time.
     830              :  * - `CauchyAngularCoords` are set to the angular collocation values for the
     831              :  * spin-weighted spherical harmonic library
     832              :  * - `CauchyCartesianCoords` are set to the Cartesian coordinates for the
     833              :  * `CauchyAngularCoords` evaluated on a unit sphere.
     834              :  * - `GaugeC` is set to 0
     835              :  * - `GaugeD` is set to 2
     836              :  * - `GaugeOmega` is set to 1
     837              :  */
     838            1 : struct InitializeGauge {
     839            0 :   using return_tags =
     840              :       tmpl::list<Tags::CauchyAngularCoords, Tags::CauchyCartesianCoords,
     841              :                  Tags::PartiallyFlatGaugeC, Tags::PartiallyFlatGaugeD,
     842              :                  Tags::PartiallyFlatGaugeOmega>;
     843            0 :   using argument_tags = tmpl::list<Tags::LMax>;
     844              : 
     845            0 :   static void apply(
     846              :       gsl::not_null<
     847              :           tnsr::i<DataVector, 2, ::Frame::Spherical<::Frame::Inertial>>*>
     848              :           angular_cauchy_coordinates,
     849              :       gsl::not_null<tnsr::i<DataVector, 3>*> cartesian_cauchy_coordinates,
     850              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 2>>*> gauge_c,
     851              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*> gauge_d,
     852              :       gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*> omega,
     853              :       size_t l_max);
     854              : };
     855              : }  // namespace Cce
        

Generated by: LCOV version 2.0-1