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/DataBox.hpp"
10 : #include "DataStructures/SpinWeighted.hpp"
11 : #include "DataStructures/Tensor/Tensor.hpp"
12 : #include "DataStructures/Tensor/TypeAliases.hpp"
13 : #include "Evolution/Systems/Cce/IntegrandInputSteps.hpp"
14 : #include "Evolution/Systems/Cce/LinearOperators.hpp"
15 : #include "Evolution/Systems/Cce/OptionTags.hpp"
16 : #include "Evolution/Systems/Cce/Tags.hpp"
17 : #include "NumericalAlgorithms/Spectral/Basis.hpp"
18 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
19 : #include "NumericalAlgorithms/Spectral/Quadrature.hpp"
20 : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshCollocation.hpp"
21 : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshDerivatives.hpp"
22 : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshTags.hpp"
23 : #include "Utilities/Gsl.hpp"
24 : #include "Utilities/TMPL.hpp"
25 :
26 : namespace Cce {
27 :
28 : /*!
29 : * \brief A set of procedures for computing the set of inputs to the CCE
30 : * integrand computations that are to be performed prior to the spin-weighted
31 : * spherical harmonic differentiation (and for the first step in the series of
32 : * integrations, after the `PrecomputeCceDependencies`)
33 : *
34 : * \details For the storage model in which a set of `Variables` are stored in a
35 : * `DataBox`, there are type aliases provided in each of the specializations:
36 : * - output/input : `pre_swsh_derivatives` type alias. A \ref DataBoxGroup with
37 : * tags `all_pre_swsh_derivative_tags` is compatible with all specializations.
38 : * - input : `swsh_derivative_tags` type alias. A \ref DataBoxGroup with tags
39 : * `all_swsh_derivative_tags` is compatible with all specializations.
40 : * - input : `integrand_tags` type alias. A \ref DataBoxGroup with tags
41 : * `Tags::BondiU` and `Tags::BondiBeta` is compatible with all specializations.
42 : */
43 : template <typename Tag>
44 1 : struct PreSwshDerivatives;
45 :
46 : /*!
47 : * \brief Compute \f$\bar{J}\f$.
48 : *
49 : * \note Computing \f$\bar{J}\f$ should be unnecessary in most execution
50 : * procedures, as all quantities should be derived from \f$J\f$ and its
51 : * derivatives followed by explicit conjugation operations, which are expected
52 : * to be sufficiently cheap to avoid the storage cost of recording the
53 : * conjugates. The exception is caching for certain spin-weighted derivatives of
54 : * products
55 : */
56 : template <>
57 1 : struct PreSwshDerivatives<Tags::BondiJbar> {
58 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::BondiJ>;
59 0 : using swsh_derivative_tags = tmpl::list<>;
60 0 : using integrand_tags = tmpl::list<>;
61 :
62 0 : using return_tags = tmpl::list<Tags::BondiJbar>;
63 0 : using argument_tags = pre_swsh_derivative_tags;
64 0 : static void apply(
65 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, -2>>*> jbar,
66 : const Scalar<SpinWeighted<ComplexDataVector, 2>>& j) {
67 : get(*jbar) = conj(get(j));
68 : }
69 : };
70 :
71 : /*!
72 : * \brief Compute \f$\bar{U}\f$.
73 : *
74 : * \note Computing \f$\bar{U}\f$ should be unnecessary in most execution
75 : * procedures, as all quantities should be derived from \f$U\f$ and its
76 : * derivatives followed by explicit conjugation operations, which are expected
77 : * to be sufficiently cheap to avoid the storage cost of recording the
78 : * conjugates.
79 : */
80 : template <>
81 1 : struct PreSwshDerivatives<Tags::BondiUbar> {
82 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::BondiU>;
83 0 : using swsh_derivative_tags = tmpl::list<>;
84 0 : using integrand_tags = tmpl::list<>;
85 :
86 0 : using return_tags = tmpl::list<Tags::BondiUbar>;
87 0 : using argument_tags = pre_swsh_derivative_tags;
88 0 : static void apply(
89 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, -1>>*> ubar,
90 : const Scalar<SpinWeighted<ComplexDataVector, 1>>& u) {
91 : get(*ubar) = conj(get(u));
92 : }
93 : };
94 :
95 : /*!
96 : * Compute \f$\bar{Q}\f$.
97 : *
98 : * \note Computing \f$\bar{Q}\f$ should be unnecessary in most execution
99 : * procedures, as all quantities should be derived from \f$Q\f$ and its
100 : * derivatives followed by explicit conjugation operations, which are expected
101 : * to be sufficiently cheap to avoid the storage cost of recording the
102 : * conjugates
103 : */
104 : template <>
105 1 : struct PreSwshDerivatives<Tags::BondiQbar> {
106 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::BondiQ>;
107 0 : using swsh_derivative_tags = tmpl::list<>;
108 0 : using integrand_tags = tmpl::list<>;
109 :
110 0 : using return_tags = tmpl::list<Tags::BondiQbar>;
111 0 : using argument_tags = pre_swsh_derivative_tags;
112 0 : static void apply(
113 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, -1>>*> qbar,
114 : const Scalar<SpinWeighted<ComplexDataVector, 1>>& q) {
115 : get(*qbar) = conj(get(q));
116 : }
117 : };
118 :
119 : /// Compute the product of `Lhs` and `Rhs`.
120 : template <typename Lhs, typename Rhs>
121 1 : struct PreSwshDerivatives<::Tags::Multiplies<Lhs, Rhs>> {
122 0 : using pre_swsh_derivative_tags = tmpl::list<Lhs, Rhs>;
123 0 : using swsh_derivative_tags = tmpl::list<>;
124 0 : using integrand_tags = tmpl::list<>;
125 :
126 0 : using return_tags = tmpl::list<::Tags::Multiplies<Lhs, Rhs>>;
127 0 : using argument_tags = pre_swsh_derivative_tags;
128 0 : static void apply(
129 : const gsl::not_null<Scalar<SpinWeighted<
130 : ComplexDataVector, ::Tags::Multiplies<Lhs, Rhs>::type::type::spin>>*>
131 : result,
132 : const Scalar<SpinWeighted<ComplexDataVector, Lhs::type::type::spin>>& lhs,
133 : const Scalar<SpinWeighted<ComplexDataVector, Rhs::type::type::spin>>&
134 : rhs) {
135 : get(*result) = get(lhs) * get(rhs);
136 : }
137 : };
138 :
139 : /*!
140 : * \brief Compute the product of \f$\bar{J}\f$ and the quantity represented by
141 : * `Rhs`.
142 : *
143 : * \details In this function, \f$\bar{J}\f$ is obtained via conjugation of
144 : * `Tags::BondiJ` inline, rather than accessing `Tags::BondiJbar` in storage.
145 : */
146 : template <typename Rhs>
147 1 : struct PreSwshDerivatives<::Tags::Multiplies<Tags::BondiJbar, Rhs>> {
148 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::BondiJ, Rhs>;
149 0 : using swsh_derivative_tags = tmpl::list<>;
150 0 : using integrand_tags = tmpl::list<>;
151 :
152 0 : using return_tags = tmpl::list<::Tags::Multiplies<Tags::BondiJbar, Rhs>>;
153 0 : using argument_tags = pre_swsh_derivative_tags;
154 0 : static void apply(
155 : const gsl::not_null<Scalar<SpinWeighted<
156 : ComplexDataVector,
157 : ::Tags::Multiplies<Tags::BondiJbar, Rhs>::type::type::spin>>*>
158 : result,
159 : const Scalar<SpinWeighted<ComplexDataVector, 2>>& j,
160 : const Scalar<SpinWeighted<ComplexDataVector, Rhs::type::type::spin>>&
161 : rhs) {
162 : get(*result) = conj(get(j)) * get(rhs);
163 : }
164 : };
165 :
166 : /*!
167 : * \brief Compute the product of \f$\bar{J}\f$ and the quantity represented by
168 : * `Rhs`.
169 : *
170 : * \details In this function, \f$\bar{J}\f$ is obtained via conjugation of
171 : * `Tags::BondiJ` inline, rather than accessing `Tags::BondiJbar` in storage.
172 : */
173 : template <typename Lhs>
174 1 : struct PreSwshDerivatives<::Tags::Multiplies<Lhs, Tags::BondiJbar>> {
175 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::BondiJ, Lhs>;
176 0 : using swsh_derivative_tags = tmpl::list<>;
177 0 : using integrand_tags = tmpl::list<>;
178 :
179 0 : using return_tags = tmpl::list<::Tags::Multiplies<Lhs, Tags::BondiJbar>>;
180 0 : using argument_tags = pre_swsh_derivative_tags;
181 0 : static void apply(
182 : const gsl::not_null<Scalar<SpinWeighted<
183 : ComplexDataVector,
184 : ::Tags::Multiplies<Lhs, Tags::BondiJbar>::type::type::spin>>*>
185 : result,
186 : const Scalar<SpinWeighted<ComplexDataVector, 2>>& j,
187 : const Scalar<SpinWeighted<ComplexDataVector, Lhs::type::type::spin>>&
188 : lhs) {
189 : get(*result) = get(lhs) * conj(get(j));
190 : }
191 : };
192 :
193 : /*!
194 : * \brief Compute the product of \f$\bar{U}\f$ and the quantity represented by
195 : * `Rhs`.
196 : *
197 : * \details In this function, \f$\bar{U}\f$ is obtained via conjugation of
198 : * `Tags::BondiU` inline, rather than accessing `Tags::BondiUbar` in storage.
199 : */
200 : template <typename Rhs>
201 1 : struct PreSwshDerivatives<::Tags::Multiplies<Tags::BondiUbar, Rhs>> {
202 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::BondiU, Rhs>;
203 0 : using swsh_derivative_tags = tmpl::list<>;
204 0 : using integrand_tags = tmpl::list<>;
205 :
206 0 : using return_tags = tmpl::list<::Tags::Multiplies<Tags::BondiUbar, Rhs>>;
207 0 : using argument_tags = pre_swsh_derivative_tags;
208 0 : static void apply(
209 : const gsl::not_null<Scalar<SpinWeighted<
210 : ComplexDataVector,
211 : ::Tags::Multiplies<Tags::BondiUbar, Rhs>::type::type::spin>>*>
212 : result,
213 : const Scalar<SpinWeighted<ComplexDataVector, 1>>& u,
214 : const Scalar<SpinWeighted<ComplexDataVector, Rhs::type::type::spin>>&
215 : rhs) {
216 : get(*result) = conj(get(u)) * get(rhs);
217 : }
218 : };
219 :
220 : /*!
221 : * \brief Compute \f$\bar{J} * (Q - 2 \eth \beta)\f$.
222 : *
223 : * \note the conjugates for this are accessed by their non-conjugate
224 : * counterparts (`Tags::BondiJ` and `Tags::BondiQ`) then conjugated inline
225 : */
226 : template <>
227 1 : struct PreSwshDerivatives<Tags::JbarQMinus2EthBeta> {
228 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::BondiJ, Tags::BondiQ>;
229 0 : using swsh_derivative_tags =
230 : tmpl::list<Spectral::Swsh::Tags::Derivative<Tags::BondiBeta,
231 : Spectral::Swsh::Tags::Eth>>;
232 0 : using integrand_tags = tmpl::list<>;
233 :
234 0 : using return_tags = tmpl::list<Tags::JbarQMinus2EthBeta>;
235 0 : using argument_tags =
236 : tmpl::append<pre_swsh_derivative_tags, swsh_derivative_tags>;
237 0 : static void apply(
238 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, -1>>*>
239 : jbar_q_minus_2_eth_beta,
240 : const Scalar<SpinWeighted<ComplexDataVector, 2>>& j,
241 : const Scalar<SpinWeighted<ComplexDataVector, 1>>& q,
242 : const Scalar<SpinWeighted<ComplexDataVector, 1>>& eth_beta) {
243 : get(*jbar_q_minus_2_eth_beta) =
244 : conj(get(j)) * (get(q) - 2.0 * get(eth_beta));
245 : }
246 : };
247 :
248 : /// Compute \f$\exp(2 \beta)\f$
249 : template <>
250 1 : struct PreSwshDerivatives<Tags::Exp2Beta> {
251 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::BondiBeta>;
252 0 : using swsh_derivative_tags = tmpl::list<>;
253 0 : using integrand_tags = tmpl::list<>;
254 :
255 0 : using return_tags = tmpl::list<Tags::Exp2Beta>;
256 0 : using argument_tags = pre_swsh_derivative_tags;
257 0 : static void apply(
258 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
259 : exp_2_beta,
260 : const Scalar<SpinWeighted<ComplexDataVector, 0>>& beta) {
261 : get(*exp_2_beta).data() = exp(2.0 * get(beta).data());
262 : }
263 : };
264 :
265 : /// Copies the values of the inertial retarded time into a spin-weighted
266 : /// container so that spin-weighted derivatives can be taken
267 : template <>
268 1 : struct PreSwshDerivatives<Tags::ComplexInertialRetardedTime> {
269 0 : using pre_swsh_derivative_tags = tmpl::list<>;
270 0 : using swsh_derivative_tags = tmpl::list<>;
271 0 : using integrand_tags = tmpl::list<>;
272 :
273 0 : using return_tags = tmpl::list<Tags::ComplexInertialRetardedTime>;
274 0 : using argument_tags = tmpl::list<Tags::InertialRetardedTime>;
275 0 : static void apply(
276 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
277 : complex_inertial_retarded_time,
278 : const Scalar<DataVector>& inertial_retarded_time) {
279 : get(*complex_inertial_retarded_time).data() =
280 : std::complex<double>(1.0, 0.0) * get(inertial_retarded_time);
281 : }
282 : };
283 :
284 : /// Compute the derivative of the quantity represented by `Tag` with respect to
285 : /// the numerical radial coordinate \f$y\f$.
286 : template <typename Tag>
287 1 : struct PreSwshDerivatives<Tags::Dy<Tag>> {
288 0 : using pre_swsh_derivative_tags = tmpl::list<Tag>;
289 0 : using swsh_derivative_tags = tmpl::list<>;
290 0 : using integrand_tags = tmpl::list<>;
291 :
292 0 : using return_tags = tmpl::list<Tags::Dy<Tag>>;
293 0 : using argument_tags =
294 : tmpl::append<pre_swsh_derivative_tags, tmpl::list<Tags::LMax>>;
295 :
296 0 : static void apply(
297 : const gsl::not_null<
298 : Scalar<SpinWeighted<ComplexDataVector, Tag::type::type::spin>>*>
299 : dy_val,
300 : const Scalar<SpinWeighted<ComplexDataVector, Tag::type::type::spin>>& val,
301 : const size_t l_max) {
302 : logical_partial_directional_derivative_of_complex(
303 : make_not_null(&get(*dy_val).data()), get(val).data(),
304 : Mesh<3>{
305 : {{Spectral::Swsh::number_of_swsh_theta_collocation_points(l_max),
306 : Spectral::Swsh::number_of_swsh_phi_collocation_points(l_max),
307 : get(val).size() /
308 : Spectral::Swsh::number_of_swsh_collocation_points(l_max)}},
309 : Spectral::Basis::Legendre,
310 : Spectral::Quadrature::GaussLobatto},
311 : // 2 for differentiating in y; coordinate ordering is:
312 : // {\phi, \theta, y}.
313 : 2);
314 : }
315 : };
316 :
317 : /*!
318 : * \brief Computes the first derivative with respect to \f$y\f$ of
319 : * `Tags::BondiBeta`.
320 : *
321 : * \details In a CCE evolution, the values of the first derivatives of
322 : * `Tags::BondiBeta` can just be copied from its integrand.
323 : */
324 : template <>
325 1 : struct PreSwshDerivatives<Tags::Dy<Tags::BondiBeta>> {
326 0 : using pre_swsh_derivative_tags = tmpl::list<>;
327 0 : using swsh_derivative_tags = tmpl::list<>;
328 0 : using integrand_tags = tmpl::list<Tags::Integrand<Tags::BondiBeta>>;
329 :
330 0 : using return_tags = tmpl::list<Tags::Dy<Tags::BondiBeta>>;
331 0 : using argument_tags = integrand_tags;
332 0 : static void apply(
333 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*> dy_beta,
334 : const Scalar<SpinWeighted<ComplexDataVector, 0>>& integrand_beta) {
335 : *dy_beta = integrand_beta;
336 : }
337 : };
338 :
339 : /*!
340 : * \brief Computes the first derivative with respect to \f$y\f$ of
341 : * `Tags::BondiU`.
342 : *
343 : * \details In a CCE evolution, the values of the first derivatives of
344 : * `Tags::BondiU` can just be copied from its integrand.
345 : */
346 : template <>
347 1 : struct PreSwshDerivatives<Tags::Dy<Tags::BondiU>> {
348 0 : using pre_swsh_derivative_tags = tmpl::list<>;
349 0 : using swsh_derivative_tags = tmpl::list<>;
350 0 : using integrand_tags = tmpl::list<Tags::Integrand<Tags::BondiU>>;
351 :
352 0 : using return_tags = tmpl::list<Tags::Dy<Tags::BondiU>>;
353 0 : using argument_tags = integrand_tags;
354 0 : static void apply(
355 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*> dy_u,
356 : const Scalar<SpinWeighted<ComplexDataVector, 1>>& integrand_u) {
357 : *dy_u = integrand_u;
358 : }
359 : };
360 :
361 : /// \brief Compute \f$\partial_u J\f$ from \f$H\f$ and the Jacobian factors.
362 : template <>
363 1 : struct PreSwshDerivatives<Tags::Du<Tags::BondiJ>> {
364 0 : using pre_swsh_derivative_tags = tmpl::list<Tags::Dy<Tags::BondiJ>>;
365 0 : using swsh_derivative_tags = tmpl::list<>;
366 0 : using integrand_tags = tmpl::list<Tags::BondiH>;
367 0 : using integration_independent_tags =
368 : tmpl::list<Tags::DuRDividedByR, Tags::OneMinusY>;
369 :
370 0 : using return_tags = tmpl::list<Tags::Du<Tags::BondiJ>>;
371 0 : using argument_tags = tmpl::append<pre_swsh_derivative_tags, integrand_tags,
372 : integration_independent_tags>;
373 0 : static void apply(
374 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 2>>*> du_j,
375 : const Scalar<SpinWeighted<ComplexDataVector, 2>>& dy_bondi_j,
376 : const Scalar<SpinWeighted<ComplexDataVector, 2>>& bondi_h,
377 : const Scalar<SpinWeighted<ComplexDataVector, 0>>& du_r_divided_by_r,
378 : const Scalar<SpinWeighted<ComplexDataVector, 0>>& one_minus_y) {
379 : get(*du_j) = get(bondi_h) -
380 : get(du_r_divided_by_r) * get(one_minus_y) * get(dy_bondi_j);
381 : }
382 : };
383 :
384 : /*!
385 : * \brief Compute the derivative with respect to the numerical radial coordinate
386 : * \f$y\f$ of a quantity which is a spin-weighted spherical harmonic
387 : * derivative.
388 : *
389 : * \details This is separate from the generic case of a derivative with
390 : * respect to \f$y\f$ because the included type aliases arrange the input tags
391 : * in different categories.
392 : */
393 : template <typename Tag, typename DerivKind>
394 1 : struct PreSwshDerivatives<
395 : Tags::Dy<Spectral::Swsh::Tags::Derivative<Tag, DerivKind>>> {
396 0 : using pre_swsh_derivative_tags = tmpl::list<>;
397 0 : using swsh_derivative_tags =
398 : tmpl::list<Spectral::Swsh::Tags::Derivative<Tag, DerivKind>>;
399 0 : using integrand_tags = tmpl::list<>;
400 :
401 0 : using return_tags =
402 : tmpl::list<Tags::Dy<Spectral::Swsh::Tags::Derivative<Tag, DerivKind>>>;
403 0 : using argument_tags =
404 : tmpl::append<swsh_derivative_tags, tmpl::list<Tags::LMax>>;
405 :
406 0 : static constexpr int spin =
407 : Spectral::Swsh::Tags::Derivative<Tag, DerivKind>::spin;
408 0 : static void apply(
409 : const gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, spin>>*>
410 : dy_val,
411 : const Scalar<SpinWeighted<ComplexDataVector, spin>>& val,
412 : const size_t l_max) {
413 : logical_partial_directional_derivative_of_complex(
414 : make_not_null(&get(*dy_val).data()), get(val).data(),
415 : Mesh<3>{
416 : {{Spectral::Swsh::number_of_swsh_theta_collocation_points(l_max),
417 : Spectral::Swsh::number_of_swsh_phi_collocation_points(l_max),
418 : get(val).size() /
419 : Spectral::Swsh::number_of_swsh_collocation_points(l_max)}},
420 : Spectral::Basis::Legendre,
421 : Spectral::Quadrature::GaussLobatto},
422 : // 2 for differentiating in y; coordinate ordering is:
423 : // {\phi, \theta, y}.
424 : 2);
425 : }
426 : };
427 :
428 : /*!
429 : * \brief Evaluates the set of inputs to the CCE integrand for
430 : * `BondiValueTag` that do not involve spin-weighted angular differentiation.
431 : *
432 : * \details This function is to be called on the `DataBox` holding the relevant
433 : * CCE data on each hypersurface integration step, prior to evaluating the
434 : * spin-weighted derivatives needed for the same CCE integrand. Provided a
435 : * `DataBox` with the appropriate tags (including
436 : * `all_pre_swsh_derivative_tags`, `all_swsh_derivative_tags` and
437 : * `Tags::LMax`), this function will apply all of the necessary
438 : * mutations to update `all_pre_swsh_derivatives_for_tag<BondiValueTag>` to
439 : * their correct values for the current values for the remaining (input) tags.
440 : */
441 : template <typename BondiValueTag, typename DataBoxType>
442 1 : void mutate_all_pre_swsh_derivatives_for_tag(
443 : const gsl::not_null<DataBoxType*> box) {
444 : tmpl::for_each<pre_swsh_derivative_tags_to_compute_for_t<BondiValueTag>>(
445 : [&box](auto pre_swsh_derivative_tag_v) {
446 : using pre_swsh_derivative_tag =
447 : typename decltype(pre_swsh_derivative_tag_v)::type;
448 : using mutation = PreSwshDerivatives<pre_swsh_derivative_tag>;
449 : db::mutate_apply<mutation>(box);
450 : });
451 : }
452 : } // namespace Cce
|