GaugeTransformBoundaryData.hpp
1 // 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"
10 #include "DataStructures/SpinWeighted.hpp"
11 #include "DataStructures/Tags.hpp"
16 #include "Evolution/Systems/Cce/Tags.hpp"
17 #include "NumericalAlgorithms/Spectral/SwshCollocation.hpp"
18 #include "NumericalAlgorithms/Spectral/SwshDerivatives.hpp"
19 #include "NumericalAlgorithms/Spectral/SwshInterpolation.hpp"
20 #include "Utilities/Gsl.hpp"
21 #include "Utilities/TMPL.hpp"
22 
23 namespace Cce {
24 
25 namespace Tags {
26 /// \cond
27 struct LMax;
28 /// \endcond
29 } // namespace Tags
30 
31 /// The set of tags that should be calculated before the initial data is
32 /// computed on the first hypersurface.
34  tmpl::list<Tags::BondiR, Tags::BondiJ, Tags::Dr<Tags::BondiJ>>;
35 
36 /*!
37  * \brief Computes the gauge-transformed
38  * `Tags::EvolutionGaugeBoundaryValue<Tag>` for any of the boundary tags needed
39  * in the evolution.
40  *
41  * \details Most of these computations involve first interpolating via a
42  * `Spectral::Swsh::SwshInterpolator` to the new angular grid, followed by
43  * manipulations associated with the tensor transformation of the metric and its
44  * derivatives. Individual template specializations contain detailed
45  * explanations about the respective gauge transformations.
46  */
47 template <typename Tag>
49 
50 /*!
51  * \brief Computes the evolution gauge Bondi \f$\hat R\f$ on the worldtube from
52  * Cauchy gauge quantities
53  *
54  * \details The evolution gauge Bondi \f$\hat R\f$ obeys:
55  *
56  * \f{align*}{
57  * \hat R = \hat \omega R(\hat x^{\hat A}),
58  * \f}
59  *
60  * where the evaluation of \f$R\f$ at \f$\hat x^{\hat A}\f$ requires an
61  * interpolation to the evolution coordinates, and \f$\hat \omega\f$ is the
62  * conformal factor associated with the angular part of the gauge
63  * transformation.
64  */
65 template <>
66 struct GaugeAdjustedBoundaryValue<Tags::BondiR> {
67  using return_tags =
68  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiR>>;
69  using argument_tags = tmpl::list<
72 
73  static void apply(
75  evolution_gauge_r,
76  const Scalar<SpinWeighted<ComplexDataVector, 0>>& cauchy_gauge_r,
78  const Spectral::Swsh::SwshInterpolator& interpolator) noexcept;
79 };
80 
81 /*!
82  * \brief Computes the evolution gauge \f$\partial_{\hat u} \hat R / \hat R\f$
83  * on the worldtube.
84  *
85  * \details The evolution gauge quantity \f$ \partial_{\hat u} \hat R / \hat
86  * R\f$ obeys
87  *
88  * \f{align*}{
89  * \frac{\partial_{\hat u} \hat R}{ \hat R}
90  * = \frac{\partial_u R (\hat x^{\hat A})}{R(\hat x^{\hat A})}
91  * + \frac{\partial_{\hat u} \hat \omega}{\hat \omega}
92  * + \frac{\mathcal U^{(0)} \bar \eth R(\hat x^{\hat A})
93  * + \bar{\mathcal U}^{(0)} \eth R(\hat x^{\hat A}) }{2 R(\hat x^{\hat A})}
94  * \f}
95  *
96  * note that the terms proportional to \f$\eth R\f$ or its conjugate arise from
97  * the conversion between \f$\partial_u\f$ and \f$\partial_{\hat u}f\f$. The
98  * right-hand side quantities with explicit \f$\hat x\f$ require interpolation.
99  * \f$\mathcal U^{(0)}\f$ is the asymptotic quantity determined by
100  * `GaugeUpdateTimeDerivatives`.
101  */
102 template <>
103 struct GaugeAdjustedBoundaryValue<Tags::DuRDividedByR> {
104  using return_tags =
105  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::DuRDividedByR>>;
106  using argument_tags = tmpl::list<
111  Tags::LMax>;
112 
113  static void apply(
115  evolution_gauge_du_r_divided_by_r,
117  cauchy_gauge_du_r_divided_by_r,
118  const Scalar<SpinWeighted<ComplexDataVector, 1>>& bondi_u_at_scri,
119  const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
122  const Spectral::Swsh::SwshInterpolator& interpolator,
123  size_t l_max) noexcept;
124 };
125 
126 /*!
127  * \brief Computes the evolution gauge quantity \f$\hat J\f$ on the worldtube
128  *
129  * \details The evolution gauge quantity \f$\hat J\f$ obeys
130  *
131  * \f{align*}{
132  * \hat J = \frac{1}{4 \hat{\omega}^2} \left( \bar{\hat d}^2 J(\hat x^{\hat A})
133  * + \hat c^2 \bar J(\hat x^{\hat A})
134  * + 2 \hat c \bar{\hat d} K(\hat x^{\hat A}) \right)
135  * \f}
136  *
137  * Where \f$\hat c\f$ and \f$\hat d\f$ are the spin-weighted angular Jacobian
138  * factors computed by `GaugeUpdateJacobianFromCoords`, and \f$\hat \omega\f$ is
139  * the conformal factor associated with the angular coordinate transformation.
140  * Note that the right-hand sides with explicit \f$\hat x^{\hat A}\f$ dependence
141  * must be interpolated and that \f$K = \sqrt{1 + J \bar J}\f$.
142  */
143 template <>
144 struct GaugeAdjustedBoundaryValue<Tags::BondiJ> {
145  using return_tags =
146  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiJ>>;
147  using argument_tags = tmpl::list<
151 
152  static void apply(
154  evolution_gauge_j,
155  const Scalar<SpinWeighted<ComplexDataVector, 2>>& cauchy_gauge_j,
159  const Spectral::Swsh::SwshInterpolator& interpolator) noexcept;
160 };
161 
162 /*!
163  * \brief Computes the evolution gauge quantity \f$\partial_{\hat r} \hat J\f$
164  * on the worldtube
165  *
166  * \details The evolution gauge quantity \f$\partial_{\hat r} \hat J\f$ is
167  * determined from \f$\partial_{\hat r} = \frac{\partial_r}{\hat \omega}\f$ and
168  * the expression for \f$\hat J\f$ given in the documentation for
169  * `GaugeAdjustedBoundaryValue<Tags::BondiJ>`
170  */
171 template <>
172 struct GaugeAdjustedBoundaryValue<Tags::Dr<Tags::BondiJ>> {
173  using return_tags =
174  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::Dr<Tags::BondiJ>>>;
175  using argument_tags = tmpl::list<
180  Tags::LMax>;
181 
182  static void apply(
184  evolution_gauge_dr_j,
185  const Scalar<SpinWeighted<ComplexDataVector, 2>>& cauchy_gauge_dr_j,
186  const Scalar<SpinWeighted<ComplexDataVector, 2>>& cauchy_gauge_j,
190  const Spectral::Swsh::SwshInterpolator& interpolator,
191  size_t l_max) noexcept;
192 };
193 
194 /*!
195  * \brief Computes the evolution gauge quantity \f$\hat \beta\f$ on the
196  * worldtube
197  *
198  * \details The evolution gauge quantity \f$\hat \beta\f$ obeys
199  *
200  * \f{align*}{
201  * e^{2 \hat \beta} = e^{2 \beta(\hat x^{\hat A})} / \hat \omega.
202  * \f}
203  *
204  * The explicit evaluation at \f$\hat x^{\hat A}\f$ on the right-hand side
205  * indicates the requirement of an interpolation step, and \f$\hat \omega\f$ is
206  * the conformal factor associated with the angular transformation.
207  */
208 template <>
209 struct GaugeAdjustedBoundaryValue<Tags::BondiBeta> {
210  using return_tags =
211  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiBeta>>;
212  using argument_tags = tmpl::list<
215 
216  static void apply(
218  evolution_gauge_beta,
219  const Scalar<SpinWeighted<ComplexDataVector, 0>>& cauchy_gauge_beta,
221  const Spectral::Swsh::SwshInterpolator& interpolator) noexcept;
222 };
223 
224 /*!
225  * \brief Computes the evolution gauge quantity \f$\hat Q\f$ on the worldtube.
226  *
227  * \details The evolution gauge quantity \f$\hat Q\f$ obeys
228  *
229  * \f{align*}{
230  * \hat Q =& \hat r^2 e^{-2 \hat \beta} (\hat K \partial_{\hat r} \hat U
231  * + \hat J \partial_{\hat r} \hat{\bar U}),\\
232  * \partial_{\hat r} \hat U
233  * =& \frac{1}{2 \hat \omega^3}\left(\hat{\bar d} \partial_r U(\hat x^{\hat A})
234  * - \hat c \partial_r \bar U(\hat x^{\hat A})\right)
235  * + \frac{e^{2\hat \beta}}{\hat r^2 \hat \omega}
236  * \left(\hat J \hat{\bar{\eth}} \hat \omega
237  * - \hat K \hat \eth \hat \omega\right)
238  * \left(-1 + \partial_{\hat y} \hat{\bar{J}} \partial_{\hat y} \hat J
239  * - \left[\frac{\partial_{\hat y}(\hat J \hat{\bar{J}})}
240  * {2 \hat K}\right]^2\right) \notag \\
241  * & + 2 \frac{e^{2 \hat \beta}}{\hat \omega \hat r^2}
242  * \left[ \hat{\bar{\eth}} \hat \omega \partial_{\hat y} \hat J
243  * + \hat{\eth} \hat \omega \left(-\frac{\hat J \partial_{\hat y}
244  * \hat{\bar J}
245  * + \hat{\bar J} \partial_{\hat y} \hat J}{2 \hat K}\right) \right].
246  * \f}
247  *
248  * where the explicit argument \f$\hat x^{\hat A}\f$ on the right-hand side
249  * implies the need for an interpolation operation, and
250  * \f$K = \sqrt{1 + J \bar J}\f$.
251  */
252 template <>
253 struct GaugeAdjustedBoundaryValue<Tags::BondiQ> {
254  using return_tags =
255  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiQ>>;
256 
257  using argument_tags = tmpl::list<
265  Tags::LMax>;
266 
267  static void apply(
269  evolution_gauge_q,
270  const Scalar<SpinWeighted<ComplexDataVector, 1>>& cauchy_gauge_dr_u,
272  const Scalar<SpinWeighted<ComplexDataVector, 2>>& volume_dy_j,
273  const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
274  const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_beta,
278  const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
279  const Spectral::Swsh::SwshInterpolator& interpolator,
280  const size_t l_max) noexcept {
281  apply_impl(make_not_null(&get(*evolution_gauge_q)), get(cauchy_gauge_dr_u),
282  get(volume_j), get(volume_dy_j), get(evolution_gauge_r),
283  get(evolution_gauge_beta), get(gauge_c), get(gauge_d),
284  get(omega), get(eth_omega), interpolator, l_max);
285  }
286 
287  private:
288  static void apply_impl(
290  const SpinWeighted<ComplexDataVector, 1>& cauchy_gauge_dr_u,
291  const SpinWeighted<ComplexDataVector, 2>& volume_j,
292  const SpinWeighted<ComplexDataVector, 2>& volume_dy_j,
293  const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_r,
294  const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_beta,
295  const SpinWeighted<ComplexDataVector, 2>& gauge_c,
296  const SpinWeighted<ComplexDataVector, 0>& gauge_d,
298  const SpinWeighted<ComplexDataVector, 1>& eth_omega,
299  const Spectral::Swsh::SwshInterpolator& interpolator,
300  size_t l_max) noexcept;
301 };
302 
303 /*!
304  * \brief Computes the evolution gauge quantity \f$\mathcal U\f$ on the
305  * worldtube.
306  *
307  * \details Note that the boundary quantity computed by this function is, by
308  * necessity, NOT the evolution gauge bondi \f$\hat U\f$, because there is
309  * insufficient information at the point in the computation this will be
310  * evaluated to completely determine \f$\hat{U}\f$. Instead, this determines
311  * the boundary value of \f$\mathcal U\f$, which satisfies,
312  *
313  * \f{align*}{
314  * \mathcal{U} - \mathcal{U}^{(0)} = \hat U,
315  * \f}
316  *
317  * where the superscript \f$(0)\f$ denotes evaluation at \f$\mathcal I^+\f$. In
318  * particular, the result of this computation may be used with the same
319  * hypersurface equations as the full evolution gauge \f$\hat U\f$, because they
320  * satisfy the same radial differential equation.
321  *
322  * \f$\mathcal U\f$ is computed by,
323  *
324  * \f{align*}{
325  * \mathcal U = \frac{1}{2\hat \omega^2} \left(\hat{\bar d} U(\hat x^{\hat A})
326  * - \hat c \bar U(\hat x^{\hat A}) \right)
327  * - \frac{e^{2 \hat \beta}}{\hat r \hat \omega}
328  * \left(\hat K \hat \eth \hat \omega
329  * - \hat J\hat{\bar{\eth}} \hat \omega\right),
330  * \f}
331  *
332  * where the explicit argument \f$\hat x^{\hat A}\f$ on the right-hand side
333  * implies the need for an interpolation operation, and
334  * \f$K = \sqrt{1 + J \bar J}\f$.
335  */
336 template <>
337 struct GaugeAdjustedBoundaryValue<Tags::BondiU> {
338  using return_tags =
339  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiU>>;
340  using argument_tags = tmpl::list<
348  Tags::LMax>;
349 
350  static void apply(
352  evolution_gauge_u,
353  const Scalar<SpinWeighted<ComplexDataVector, 1>>& cauchy_gauge_u,
355  const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
356  const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_beta,
360  const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
361  const Spectral::Swsh::SwshInterpolator& interpolator,
362  size_t l_max) noexcept;
363 };
364 
365 /*!
366  * \brief Computes the evolution gauge quantity \f$\hat W\f$ on the worldtube.
367  *
368  * \details The evolution gauge value \f$\hat W\f$ obeys
369  *
370  * \f{align*}{
371  * \hat W =& W(\hat x^{\hat A}) + (\hat \omega - 1) / \hat r
372  * + \frac{e^{2 \hat \beta}}{2 \hat \omega^2 \hat r}
373  * \left(\hat J \left(\hat{\bar \eth} \hat \omega\right)^2
374  * + \hat{\bar{J}} \left(\hat \eth \hat \omega\right) ^2
375  * - 2 K \left( \hat \eth \hat \omega\right) \left(\hat{\bar \eth} \hat
376  * \omega\right) \right)
377  * - \frac{2 \partial_{u} \hat \omega}{\hat \omega}
378  * - \frac{ \hat U \bar \eth \hat \omega + \hat{\bar U} \eth \hat \omega }
379  * {\hat \omega},
380  * \f}
381  *
382  * where the explicit argument \f$\hat x^{\hat A}\f$ on the right-hand side
383  * implies the need for an interpolation operation and
384  * \f$K = \sqrt{1 + J \bar J}\f$.
385  */
386 template <>
387 struct GaugeAdjustedBoundaryValue<Tags::BondiW> {
388  using return_tags =
389  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiW>>;
390  using argument_tags = tmpl::list<
399  Tags::LMax>;
400 
401  static void apply(
403  evolution_gauge_w,
404  const Scalar<SpinWeighted<ComplexDataVector, 0>>& cauchy_gauge_w,
406  const Scalar<SpinWeighted<ComplexDataVector, 1>>& evolution_gauge_u,
407  const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_beta,
409  evolution_gauge_u_at_scri,
410  const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
413  const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
414  const Spectral::Swsh::SwshInterpolator& interpolator,
415  const size_t l_max) noexcept {
416  apply_impl(make_not_null(&get(*evolution_gauge_w)), get(cauchy_gauge_w),
417  get(volume_j), get(evolution_gauge_u), get(evolution_gauge_beta),
418  get(evolution_gauge_u_at_scri), get(evolution_gauge_r),
419  get(omega), get(du_omega), get(eth_omega), interpolator, l_max);
420  }
421 
422  private:
423  static void apply_impl(
425  const SpinWeighted<ComplexDataVector, 0>& cauchy_gauge_w,
426  const SpinWeighted<ComplexDataVector, 2>& volume_j,
427  const SpinWeighted<ComplexDataVector, 1>& evolution_gauge_u,
428  const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_beta,
429  const SpinWeighted<ComplexDataVector, 1>& evolution_gauge_u_at_scri,
430  const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_r,
432  const SpinWeighted<ComplexDataVector, 0>& du_omega,
433  const SpinWeighted<ComplexDataVector, 1>& eth_omega,
434  const Spectral::Swsh::SwshInterpolator& interpolator,
435  size_t l_max) noexcept;
436 };
437 
438 /*!
439  * \brief Computes the evolution gauge quantity \f$\hat H\f$ on the worldtube.
440  *
441  * \details The evolution gauge \f$\hat H\f$ obeys
442  *
443  * \f{align*}{
444  * \hat H =&
445  * \frac{1}{2} \left(\mathcal{U}^{(0)} \hat{\bar \eth} \hat J
446  * + \bar{\mathcal{U}}^{(0)} \hat{\eth} \hat J\right)
447  * + \frac{\partial_{\hat u} \hat \omega
448  * - \tfrac{1}{2} \left(\mathcal{U}^{(0)} \bar{\hat \eth}\hat \omega
449  * + \bar{\mathcal{U}}^{(0)} \hat \eth \hat \omega \right) }{\hat \omega}
450  * \left(2 \hat J - 2 \partial_{\hat y} \hat J\right)
451  * - \hat J\hat{\bar \eth} \mathcal{U}^{(0)}
452  * + \hat K \hat \eth \bar{\mathcal{U}}^{(0)} \notag\\
453  * &+ \frac{1}{4 \hat \omega^2} \left(\hat{\bar d}^2 H(\hat x^{\hat A})
454  * + \hat c^2 \bar H(\hat x^{\hat A})
455  * + \hat{\bar d} \hat c \frac{H(\hat x^{\hat A}) \bar J(\hat x^{\hat A})
456  * + J(\hat x^{\hat A}) \bar H(\hat x^{\hat A})}{K}\right)
457  * + 2 \frac{\partial_u R}{R} \partial_{\hat y} J
458  * \f}
459  *
460  * where the superscript \f$(0)\f$ denotes evaluation at \f$\mathcal I^+\f$ and
461  * the explicit \f$\hat x^{\hat A}\f$ arguments on the right-hand side imply
462  * interpolation operations, and \f$K = \sqrt{1 + J \bar J}\f$,
463  * \f$\hat K = \sqrt{1 + \hat J \hat{\bar J}}\f$.
464  */
465 template <>
466 struct GaugeAdjustedBoundaryValue<Tags::BondiH> {
467  using return_tags =
468  tmpl::list<Tags::EvolutionGaugeBoundaryValue<Tags::BondiH>>;
469  using argument_tags = tmpl::list<
478  Tags::LMax>;
479 
480  static void apply(
482  evolution_gauge_h,
484  const Scalar<SpinWeighted<ComplexDataVector, 2>>& cauchy_gauge_du_j,
485  const Scalar<SpinWeighted<ComplexDataVector, 2>>& volume_dy_j,
487  evolution_gauge_u_at_scri,
488  const Scalar<SpinWeighted<ComplexDataVector, 0>>& evolution_gauge_r,
493  const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
495  evolution_gauge_du_r_divided_by_r,
496  const Spectral::Swsh::SwshInterpolator& interpolator,
497  const size_t l_max) noexcept {
498  apply_impl(make_not_null(&get(*evolution_gauge_h)), get(volume_j),
499  get(cauchy_gauge_du_j), get(volume_dy_j),
500  get(evolution_gauge_u_at_scri), get(evolution_gauge_r),
501  get(gauge_c), get(gauge_d), get(omega), get(du_omega),
502  get(eth_omega), get(evolution_gauge_du_r_divided_by_r),
503  interpolator, l_max);
504  }
505 
506  private:
507  static void apply_impl(
509  const SpinWeighted<ComplexDataVector, 2>& volume_j,
510  const SpinWeighted<ComplexDataVector, 2>& cauchy_gauge_du_j,
511  const SpinWeighted<ComplexDataVector, 2>& volume_dy_j,
512  const SpinWeighted<ComplexDataVector, 1>& evolution_gauge_u_at_scri,
513  const SpinWeighted<ComplexDataVector, 0>& evolution_gauge_r,
514  const SpinWeighted<ComplexDataVector, 2>& gauge_c,
515  const SpinWeighted<ComplexDataVector, 0>& gauge_d,
517  const SpinWeighted<ComplexDataVector, 0>& du_omega,
518  const SpinWeighted<ComplexDataVector, 1>& eth_omega,
520  evolution_gauge_du_r_divided_by_r,
521  const Spectral::Swsh::SwshInterpolator& interpolator,
522  size_t l_max) noexcept;
523 };
524 
525 /*!
526  * \brief Update the Cauchy gauge cartesian coordinate derivative \f$\partial_u
527  * x(\hat x)\f$, as well as remaining gauge quantities \f$\mathcal U^{(0)}\f$,
528  * \f$\hat U \equiv \mathcal U - \mathcal U^{(0)}\f$, and \f$\partial_{\hat u}
529  * \hat \omega\f$ to maintain asymptotically inertial angular coordinates.
530  *
531  * \details The constraint we must satisfy to maintain the asymptotically
532  * inertial angular coordinates is
533  *
534  * \f{align*}{
535  * \partial_{\hat u} x^A = \mathcal U^{(0) \hat A} \partial_{\hat A} x^{A},
536  * \f}
537  *
538  * which we compute for a representative Cartesian coordinate set on the unit
539  * sphere, to maintain representability and ensure that angular transform and
540  * derivative operations keep the desired precision. The equation we use for the
541  * Cartesian analog is:
542  *
543  * \f{align*}{
544  * \partial_{\hat u} x^i &= \frac{1}{2} (\bar{\mathcal U}^{(0)} \hat \eth x^i +
545  * \mathcal U^{(0)} \hat{\bar \eth} x^i ) \\
546  * &= \text{Re}(\bar{\mathcal U}^{(0)} \hat \eth x^i)
547  * \f}
548  *
549  * This computation completes the unfixed degrees of freedom for the coordinate
550  * transformation at the boundary, so also computes the gauge quantities that
551  * rely on this information \f$\mathcal U^{(0)}\f$,
552  * \f$\hat U\f$, and \f$\partial_{\hat u} \hat \omega\f$.
553  *
554  * The time derivative of \f$\hat \omega\f$ is calculated from the equation
555  * \f{align*}{
556  * \partial_{\hat u} \hat \omega
557  * = \frac{\hat \omega}{4} (\hat{\bar \eth} \mathcal U^{(0)}
558  * + \hat \eth \bar{\mathcal U}^{(0)})
559  * + \frac{1}{2} (\mathcal U^{(0)} \hat{\bar \eth} \hat \omega
560  * + \bar{\mathcal U}^{(0)} \hat \eth \hat \omega)
561  * \f}
562  * \warning Before this update call the quantity stored in the tag
563  * `Cce::Tags::BondiU` represents \f$\mathcal U\f$, and after this update call,
564  * it represents \f$\hat U\f$ (the true evolution gauge quantity).
565  */
567  using return_tags =
568  tmpl::list<::Tags::dt<Tags::CauchyCartesianCoords>, Tags::BondiUAtScri,
570  using argument_tags =
574  Tags::LMax>;
575 
576  static void apply(
577  gsl::not_null<tnsr::i<DataVector, 3>*> cartesian_cauchy_du_x,
579  evolution_gauge_u_at_scri,
582  const tnsr::i<DataVector, 3>& cartesian_cauchy_coordinates,
584  const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_omega,
585  size_t l_max) noexcept;
586 };
587 
588 /*!
589  * \brief Update the angular coordinates stored in `AngularTag` via
590  * trigonometric operations applied to the Cartesian coordinates stored in
591  * `CartesianTag`.
592  *
593  * \details This function also normalizes the Cartesian coordinates stored in
594  * `CartesianTag`, which is the desired behavior for the CCE boundary
595  * computation.
596  */
597 template <typename AngularTag, typename CartesianTag>
599  using argument_tags = tmpl::list<>;
600  using return_tags = tmpl::list<AngularTag, CartesianTag>;
601 
602  static void apply(
603  const gsl::not_null<
605  angular_coordinates,
606  const gsl::not_null<tnsr::i<DataVector, 3>*>
607  cartesian_coordinates) noexcept {
608  // normalize the cartesian coordinates
609  const DataVector one_over_cartesian_r =
610  1.0 / sqrt(square(get<0>(*cartesian_coordinates)) +
611  square(get<1>(*cartesian_coordinates)) +
612  square(get<2>(*cartesian_coordinates)));
613 
614  get<0>(*cartesian_coordinates) *= one_over_cartesian_r;
615  get<1>(*cartesian_coordinates) *= one_over_cartesian_r;
616  get<2>(*cartesian_coordinates) *= one_over_cartesian_r;
617 
618  const auto& x = get<0>(*cartesian_coordinates);
619  const auto& y = get<1>(*cartesian_coordinates);
620  const auto& z = get<2>(*cartesian_coordinates);
621 
622  get<0>(*angular_coordinates) = atan2(sqrt(square(x) + square(y)), z);
623  get<1>(*angular_coordinates) = atan2(y, x);
624  }
625 };
626 
627 namespace detail {
628 void gauge_update_jacobian_from_coordinates_apply_impl(
630  gauge_factor_spin_2,
632  gauge_factor_spin_0,
635  angular_source_coordinates,
636  const tnsr::i<DataVector, 3>& cartesian_source_coordinates,
637  size_t l_max) noexcept;
638 } // namespace detail
639 
640 /*!
641  * \brief From the angular coordinates `AngularCoordinateTag` and the Cartesian
642  * coordinates `CartesianCoordinateTag`, determine the spin-weighted Jacobian
643  * factors `GaugeFactorSpin2` and `GaugeFactorSpin0`.
644  *
645  * \details This is most often used in the context of generating the Jacobians
646  * in the evolution-gauge coordinates from the Cauchy collocation points as a
647  * function of the evolution gauge coordinates. In this concrete case, the
648  * `GaugeFactorSpin2` is the gauge factor \f$\hat c\f$ and takes the value
649  *
650  * \f{align*}{
651  * \hat c = \hat q^{\hat A} \partial_{\hat A}(x^A) q_A,
652  * \f}
653  *
654  * and the `GaugeFactorSpin0` is the gauge factor \f$\hat d\f$ and takes the
655  * value
656  *
657  * \f{align*}{
658  * \hat d = \hat{\bar q}^{\hat A} \partial_{\hat A}(x^A) q_A.
659  * \f}
660  *
661  * The more generic template construction is employed so that the spin-weighted
662  * Jacobians can also be computed between two arbitrary gauges, including the
663  * inverse Jacobians associated with moving from the evolution gauge to the
664  * Cauchy gauge.
665  */
666 template <typename GaugeFactorSpin2, typename GaugeFactorSpin0,
667  typename AngularCoordinateTag, typename CartesianCoordinateTag>
669  using return_tags =
670  tmpl::list<GaugeFactorSpin2, GaugeFactorSpin0, AngularCoordinateTag>;
671  using argument_tags = tmpl::list<CartesianCoordinateTag, Tags::LMax>;
672 
673  static void apply(
675  gauge_factor_spin_2,
677  gauge_factor_spin_0,
678  const gsl::not_null<
680  angular_source_coordinates,
681  const tnsr::i<DataVector, 3>& cartesian_source_coordinates,
682  const size_t l_max) noexcept {
683  detail::gauge_update_jacobian_from_coordinates_apply_impl(
684  gauge_factor_spin_2, gauge_factor_spin_0, angular_source_coordinates,
685  cartesian_source_coordinates, l_max);
686  }
687 };
688 
689 /*!
690  * \brief Update the interpolator stored in
691  * `Spectral::Swsh::Tags::SwshInterpolator<AngularCoordinates>`.
692  *
693  * \details Note that the `AngularCoordinates` associated with the interpolator
694  * should be the source coordinates. For instance, when interpolating a quantity
695  * defined on the Cauchy gauge collocation points to the evolution gauge
696  * collocation points, the interpolator input should be the Cauchy coordinates
697  * points as a function of the evolution gauge coordinates (at the evolution
698  * gauge collocation points).
699  */
700 template <typename AngularCoordinates>
702  using return_tags =
703  tmpl::list<Spectral::Swsh::Tags::SwshInterpolator<AngularCoordinates>>;
704  using argument_tags = tmpl::list<AngularCoordinates, Tags::LMax>;
705 
706  static void apply(
708  const tnsr::i<DataVector, 2, ::Frame::Spherical<::Frame::Inertial>>&
709  angular_coordinates,
710  const size_t l_max) noexcept {
711  // throw away the old interpolator and generate a new one for the current
712  // grid points.
713  *interpolator = Spectral::Swsh::SwshInterpolator(
714  get<0>(angular_coordinates), get<1>(angular_coordinates), l_max);
715  }
716 };
717 
718 /*!
719  * \brief Update the quantity \f$\hat \omega\f$ and \f$\hat \eth \hat \omega\f$
720  * for updated spin-weighted Jacobian quantities \f$\hat c\f$ and \f$\hat d\f$.
721  *
722  * \details The conformal factor \f$\hat \omega\f$ can be determined by the
723  * angular determinant from the spin-weighted Jacobian factors as
724  *
725  * \f{align*}{
726  * \hat \omega = \frac{1}{2} \sqrt{\hat d \hat{\bar d} - \hat c \hat{\bar c}}.
727  * \f}
728  */
730  using argument_tags = tmpl::list<Tags::GaugeC, Tags::GaugeD, Tags::LMax>;
731  using return_tags =
732  tmpl::list<Tags::GaugeOmega,
735 
736  static void apply(
741  size_t l_max) noexcept;
742 };
743 
744 /*!
745  * \brief Initialize to default values (identity transform) all of the angular
746  * gauge quantities for the boundary gauge transforms.
747  *
748  * \details The updated quantities are the Cauchy angular and Cartesian
749  * coordinates, as well as the spin-weighted gauge factors and the conformal
750  * factor. All quantities are initialized to the appropriate value for the
751  * identity transform of angular coordinates. Using this initialization function
752  * ensures that the evolution gauge and the Cauchy gauge angular coordinates
753  * agree on the first evaluated time.
754  * - `CauchyAngularCoords` are set to the angular collocation values for the
755  * spin-weighted spherical harmonic library
756  * - `CauchyCartesianCoords` are set to the Cartesian coordinates for the
757  * `CauchyAngularCoords` evaluated on a unit sphere.
758  * - `GaugeC` is set to 0
759  * - `GaugeD` is set to 2
760  * - `GaugeOmega` is set to 1
761  */
763  using return_tags =
766  using argument_tags = tmpl::list<Tags::LMax>;
767 
768  static void apply(
771  angular_cauchy_coordinates,
772  gsl::not_null<tnsr::i<DataVector, 3>*> cartesian_cauchy_coordinates,
776  size_t l_max) noexcept;
777 };
778 } // namespace Cce
Spectral::Swsh::SwshInterpolator
Performs interpolation for spin-weighted spherical harmonics by taking advantage of the Clenshaw meth...
Definition: SwshInterpolation.hpp:229
get
constexpr Tag::type & get(Variables< TagList > &v) noexcept
Return Tag::type pointing into the contiguous array.
Definition: Variables.hpp:639
IndexType.hpp
Spectral::Swsh::Tags::Eth
Struct for labeling the spin-weighted derivative in tags.
Definition: SwshTags.hpp:30
square
constexpr decltype(auto) square(const T &x)
Compute the square of x
Definition: ConstantExpressions.hpp:55
Cce::Tags::CauchyAngularCoords
Definition: Tags.hpp:157
Cce::GaugeAdjustedBoundaryValue
Computes the gauge-transformed Tags::EvolutionGaugeBoundaryValue<Tag> for any of the boundary tags ne...
Definition: GaugeTransformBoundaryData.hpp:48
Cce::GaugeUpdateTimeDerivatives
Update the Cauchy gauge cartesian coordinate derivative , as well as remaining gauge quantities ,...
Definition: GaugeTransformBoundaryData.hpp:566
Spectral::Swsh::Tags::Derivative
Prefix tag representing the spin-weighted derivative of a spin-weighted scalar.
Definition: SwshTags.hpp:152
SpinWeighted
Make a spin-weighted type T with spin-weight Spin. Mathematical operators are restricted to addition,...
Definition: SpinWeighted.hpp:24
Cce::Tags::BondiUAtScri
The surface quantity of Bondi evaluated at the null spacetime boundary .
Definition: Tags.hpp:97
Cce::Tags::BondiJ
Bondi parameter .
Definition: Tags.hpp:35
Spectral::Swsh::Tags::SwshInterpolator
Tag for a SwshInterpolator associated with a particular set of angular coordinates.
Definition: SwshTags.hpp:227
db::apply
constexpr auto apply(F &&f, const DataBox< BoxTags > &box, Args &&... args) noexcept
Apply the invokable f with argument Tags TagsList from DataBox box
Definition: DataBox.hpp:1424
Cce::GaugeUpdateJacobianFromCoordinates
From the angular coordinates AngularCoordinateTag and the Cartesian coordinates CartesianCoordinateTa...
Definition: GaugeTransformBoundaryData.hpp:668
cstddef
Cce::Tags::Dy
The derivative with respect to the numerical coordinate , where is Bondi radius of the worldtube.
Definition: Tags.hpp:116
Cce::Tags::BoundaryValue
A prefix tag representing the boundary data for a quantity on the extraction surface.
Definition: Tags.hpp:199
Cce::GaugeUpdateAngularFromCartesian
Update the angular coordinates stored in AngularTag via trigonometric operations applied to the Carte...
Definition: GaugeTransformBoundaryData.hpp:598
Cce::GaugeUpdateInterpolator
Update the interpolator stored in Spectral::Swsh::Tags::SwshInterpolator<AngularCoordinates>.
Definition: GaugeTransformBoundaryData.hpp:701
DataVector
Stores a collection of function values.
Definition: DataVector.hpp:42
Cce::Tags::Du
The derivative with respect to Bondi retarded time .
Definition: Tags.hpp:131
Cce::Tags::BondiU
Bondi parameter .
Definition: Tags.hpp:90
Frame::Spherical
Represents a spherical-coordinate frame that is associated with a Cartesian frame,...
Definition: IndexType.hpp:54
Cce::gauge_adjustments_setup_tags
tmpl::list< Tags::BondiR, Tags::BondiJ, Tags::Dr< Tags::BondiJ > > gauge_adjustments_setup_tags
The set of tags that should be calculated before the initial data is computed on the first hypersurfa...
Definition: GaugeTransformBoundaryData.hpp:34
Cce::InitializeGauge
Initialize to default values (identity transform) all of the angular gauge quantities for the boundar...
Definition: GaugeTransformBoundaryData.hpp:762
Variables.hpp
Scalar
Tensor< T, Symmetry<>, index_list<> > Scalar
Definition: TypeAliases.hpp:21
Cce
The set of utilities for performing Cauchy characteristic evolution and Cauchy characteristic matchin...
Definition: BoundaryComputeAndSendToEvolution.hpp:28
Cce::Tags::GaugeD
The spin-weight 0 angular Jacobian factor.
Definition: Tags.hpp:142
Gsl.hpp
TypeAliases.hpp
Tensor.hpp
Cce::Tags::LMax
Definition: OptionTags.hpp:243
make_not_null
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion,...
Definition: Gsl.hpp:880
Cce::Tags::EvolutionGaugeBoundaryValue
A prefix tag representing the gauge-transformed boundary data for a quantity on the extraction surfac...
Definition: Tags.hpp:207
Prefixes.hpp
Cce::Tags::GaugeC
The spin-weight 2 angular Jacobian factor.
Definition: Tags.hpp:137
Cce::GaugeUpdateOmega
Update the quantity and for updated spin-weighted Jacobian quantities and .
Definition: GaugeTransformBoundaryData.hpp:729
TMPL.hpp
Cce::Tags::CauchyCartesianCoords
Definition: Tags.hpp:163
gsl::not_null
Require a pointer to not be a nullptr
Definition: Gsl.hpp:183
Cce::Tags::GaugeOmega
The conformal factor associated with an angular transformation.
Definition: Tags.hpp:147