SwshDerivatives.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <complex>
7 #include <cstddef>
8 
9 #include "DataStructures/ComplexDataVector.hpp" // IWYU pragma: keep
10 #include "DataStructures/ComplexDiagonalModalOperator.hpp"
11 #include "DataStructures/ComplexModalVector.hpp" // IWYU pragma: keep
12 #include "DataStructures/DataVector.hpp"
13 #include "DataStructures/SpinWeighted.hpp"
14 #include "DataStructures/TempBuffer.hpp" // IWYU pragma: keep
16 #include "NumericalAlgorithms/Spectral/ComplexDataView.hpp"
17 #include "NumericalAlgorithms/Spectral/SwshCoefficients.hpp"
18 #include "NumericalAlgorithms/Spectral/SwshCollocation.hpp"
19 #include "NumericalAlgorithms/Spectral/SwshSettings.hpp"
20 #include "NumericalAlgorithms/Spectral/SwshTags.hpp"
21 #include "NumericalAlgorithms/Spectral/SwshTransform.hpp"
23 #include "Utilities/Gsl.hpp"
24 #include "Utilities/TMPL.hpp"
25 
26 // IWYU pragma: no_forward_declare ComplexDataVector
27 // IWYU pragma: no_forward_declare SpinWeighted
28 // IWYU pragma: no_forward_declare Variables
29 
30 namespace Spectral {
31 namespace Swsh {
32 namespace detail {
33 
34 // Factors that appear in the modal representation of spin-weighted angular
35 // derivatives, needed for compute_coefficients_of_derivative
36 template <typename DerivativeKind>
37 SPECTRE_ALWAYS_INLINE std::complex<double> derivative_factor(int l,
38  int s) noexcept;
39 
40 template <>
41 SPECTRE_ALWAYS_INLINE std::complex<double> derivative_factor<Tags::Eth>(
42  const int l, const int s) noexcept {
43  return sqrt(static_cast<std::complex<double>>((l - s) * (l + s + 1)));
44 }
45 
46 template <>
47 SPECTRE_ALWAYS_INLINE std::complex<double> derivative_factor<Tags::Ethbar>(
48  const int l, const int s) noexcept {
49  return -sqrt(static_cast<std::complex<double>>((l + s) * (l - s + 1)));
50 }
51 
52 template <>
53 SPECTRE_ALWAYS_INLINE std::complex<double> derivative_factor<Tags::EthEth>(
54  const int l, const int s) noexcept {
55  return sqrt(static_cast<std::complex<double>>((l - s - 1) * (l + s + 2) *
56  (l - s) * (l + s + 1)));
57 }
58 
59 template <>
61 derivative_factor<Tags::EthbarEthbar>(const int l, const int s) noexcept {
62  return sqrt(static_cast<std::complex<double>>((l + s - 1) * (l - s + 2) *
63  (l + s) * (l - s + 1)));
64 }
65 
66 template <>
67 SPECTRE_ALWAYS_INLINE std::complex<double> derivative_factor<Tags::EthbarEth>(
68  const int l, const int s) noexcept {
69  return static_cast<std::complex<double>>(-(l - s) * (l + s + 1));
70 }
71 
72 template <>
73 SPECTRE_ALWAYS_INLINE std::complex<double> derivative_factor<Tags::EthEthbar>(
74  const int l, const int s) noexcept {
75  return static_cast<std::complex<double>>(-(l + s) * (l - s + 1));
76 }
77 
78 template <>
79 SPECTRE_ALWAYS_INLINE std::complex<double> derivative_factor<Tags::InverseEth>(
80  const int l, const int s) noexcept {
81  return (l - s + 1) * (l + s) == 0
82  ? 0.0
83  : 1.0 / sqrt(static_cast<std::complex<double>>((l - s + 1) *
84  (l + s)));
85 }
86 
87 template <>
89 derivative_factor<Tags::InverseEthbar>(const int l, const int s) noexcept {
90  return (l + s + 1) * (l - s) == 0
91  ? 0.0
92  : 1.0 / -sqrt(static_cast<std::complex<double>>((l + s + 1) *
93  (l - s)));
94 }
95 
96 // For a particular derivative represented by `DerivativeKind` and input spin
97 // `Spin`, multiplies the derivative spectral factors with
98 // `pre_derivative_modes`, returning by pointer via parameter `derivative_modes`
99 template <typename DerivativeKind, int Spin>
100 void compute_coefficients_of_derivative(
103  Spin + Tags::derivative_spin_weight<DerivativeKind>>*>
104  derivative_modes,
106  size_t l_max, size_t number_of_radial_points) noexcept;
107 
108 // Helper function for dealing with the parameter packs in the utilities which
109 // evaluate several spin-weighted derivatives at once. The `apply` function of
110 // this struct locates the appropriate mode buffer in the input tuple
111 // `pre_derivative_mode_tuple`, and calls `compute_coefficients_of_derivative`,
112 // deriving the coefficients for `DerivativeTag` and returning by pointer.
113 template <typename DerivativeTag, typename PreDerivativeTagList>
114 struct dispatch_to_compute_coefficients_of_derivative;
115 
116 template <typename DerivativeTag, typename... PreDerivativeTags>
117 struct dispatch_to_compute_coefficients_of_derivative<
118  DerivativeTag, tmpl::list<PreDerivativeTags...>> {
119  template <int Spin, typename... ModalTypes>
121  derivative_modes,
122  const std::tuple<ModalTypes...>& pre_derivative_mode_tuple,
123  const size_t l_max,
124  const size_t number_of_radial_points) noexcept {
125  compute_coefficients_of_derivative<typename DerivativeTag::derivative_kind>(
126  derivative_modes,
127  get<tmpl::position_of_first_v<tmpl::list<PreDerivativeTags...>,
128  typename DerivativeTag::derivative_of>>(
129  pre_derivative_mode_tuple),
130  l_max, number_of_radial_points);
131  }
132 };
133 
134 // Helper function for dealing with the parameter packs in the utilities which
135 // evaluate several spin-weighted derivatives at once. The `apply` function of
136 // this struct locates the like-spin set of paired modes and nodes, and calls
137 // the member function of `SwshTransform` or `InverseSwshTransform` to perform
138 // the spin-weighted transform. This function is a friend of both
139 // `SwshTransform` and `InverseSwshTransform` to gain access to the private
140 // `apply_to_vectors`.
141 // The calling code will pass as tuples a superset of the quantities to be
142 // transformed, in the same order as the tags provided to `TagList`. The
143 // `modal_tuple` must be the storage destinations of the transforms in the
144 // same order as the `nodal_tuple`. The set of nodal tags to be transformed are
145 // the `TransformTags...` determined by the `SwshTransform` or
146 // `InverseSwshTransform`. The reason for using `tuple`s rather than
147 // `TaggedTuple`s or similar is to pass around spin-weighted vectors directly,
148 // rather than `Scalar`s, which allows for more condensed forwarding code.
149 template <typename Transform, typename TagList>
150 struct dispatch_to_transform;
151 
152 template <ComplexRepresentation Representation, typename... TransformTags,
153  typename... Tags>
154 struct dispatch_to_transform<
155  SwshTransform<tmpl::list<TransformTags...>, Representation>,
156  tmpl::list<Tags...>> {
157  template <typename... ModalTypes, typename... NodalTypes>
158  static void apply(const gsl::not_null<std::tuple<ModalTypes...>*> modal_tuple,
159  const std::tuple<NodalTypes...>& nodal_tuple,
160  const size_t l_max,
161  const size_t number_of_radial_points) noexcept {
162  SwshTransform<tmpl::list<TransformTags...>, Representation>::
163  apply_to_vectors(
164  get<tmpl::position_of_first_v<tmpl::list<Tags...>, TransformTags>>(
165  *modal_tuple)...,
166  get<tmpl::position_of_first_v<tmpl::list<Tags...>, TransformTags>>(
167  nodal_tuple)...,
168  l_max, number_of_radial_points);
169  }
170 };
171 
172 template <ComplexRepresentation Representation, typename... TransformTags,
173  typename... Tags>
174 struct dispatch_to_transform<
175  InverseSwshTransform<tmpl::list<TransformTags...>, Representation>,
176  tmpl::list<Tags...>> {
177  template <typename... NodalTypes, typename... ModalTypes>
178  static void apply(const gsl::not_null<std::tuple<NodalTypes...>*> nodal_tuple,
179  const std::tuple<ModalTypes...>& modal_tuple,
180  const size_t l_max,
181  const size_t number_of_radial_points) noexcept {
182  InverseSwshTransform<tmpl::list<TransformTags...>, Representation>::
183  apply_to_vectors(
184  get<tmpl::position_of_first_v<tmpl::list<Tags...>, TransformTags>>(
185  *nodal_tuple)...,
186  *get<tmpl::position_of_first_v<tmpl::list<Tags...>, TransformTags>>(
187  modal_tuple)...,
188  l_max, number_of_radial_points);
189  }
190 };
191 
192 // template 'implementation' for the DataBox mutate-compatible interface to
193 // spin-weighted derivative evaluation. This impl version is needed to have easy
194 // access to the `UniqueDifferentiatedFromTagList` as a parameter pack
195 template <typename DerivativeTagList, typename UniqueDifferentiatedFromTagList,
196  ComplexRepresentation Representation>
197 struct AngularDerivativesImpl;
198 
199 template <typename... DerivativeTags, typename... UniqueDifferentiatedFromTags,
200  ComplexRepresentation Representation>
201 struct AngularDerivativesImpl<tmpl::list<DerivativeTags...>,
202  tmpl::list<UniqueDifferentiatedFromTags...>,
203  Representation> {
204  using return_tags =
205  tmpl::list<DerivativeTags..., Tags::SwshTransform<DerivativeTags>...,
206  Tags::SwshTransform<UniqueDifferentiatedFromTags>...>;
207  using argument_tags =
208  tmpl::list<UniqueDifferentiatedFromTags..., Tags::LMaxBase,
209  Tags::NumberOfRadialPointsBase>;
210 
211  static void apply(
212  const gsl::not_null<db::item_type<DerivativeTags>*>... derivative_scalars,
213  const gsl::not_null<db::item_type<Tags::SwshTransform<
214  DerivativeTags>>*>... transform_of_derivative_scalars,
215  const gsl::not_null<db::item_type<Tags::SwshTransform<
216  UniqueDifferentiatedFromTags>>*>... transform_of_input_scalars,
218  const size_t l_max, const size_t number_of_radial_points) noexcept {
219  apply_to_vectors(make_not_null(&get(*transform_of_derivative_scalars))...,
220  make_not_null(&get(*transform_of_input_scalars))...,
221  make_not_null(&get(*derivative_scalars))...,
222  get(input_scalars)..., l_max, number_of_radial_points);
223  }
224 
225  template <ComplexRepresentation FriendRepresentation,
226  typename... DerivativeKinds, typename... ArgumentTypes,
227  size_t... Is>
228  // NOLINTNEXTLINE(readability-redundant-declaration)
229  friend void angular_derivatives_impl(
230  const std::tuple<ArgumentTypes...>&, size_t, size_t,
231  std::index_sequence<Is...>, tmpl::list<DerivativeKinds...>,
232  std::bool_constant<true>) noexcept;
233 
234  private:
235  // note inputs reordered to accommodate the alternative tag-free functions
236  // which call into this function.
237  static void apply_to_vectors(
238  const gsl::not_null<typename db::item_type<Tags::SwshTransform<
239  DerivativeTags>>::type*>... transform_of_derivatives,
240  const gsl::not_null<typename db::item_type<Tags::SwshTransform<
241  UniqueDifferentiatedFromTags>>::type*>... transform_of_inputs,
242  const gsl::not_null<
243  typename db::const_item_type<DerivativeTags>::type*>... derivatives,
244  const typename db::const_item_type<
245  UniqueDifferentiatedFromTags>::type&... inputs,
246  const size_t l_max, const size_t number_of_radial_points) noexcept {
247  // perform the forward transform on the minimal set of input nodal
248  // quantities to obtain all of the requested derivatives
249  using ForwardTransformList =
251  tmpl::list<DerivativeTags...>>;
252 
253  tmpl::for_each<ForwardTransformList>(
254  [&number_of_radial_points, &l_max, &inputs...,
255  &transform_of_inputs...](auto transform_v) noexcept {
256  using transform = typename decltype(transform_v)::type;
257  auto input_transforms = std::make_tuple(transform_of_inputs...);
258  dispatch_to_transform<transform,
259  tmpl::list<UniqueDifferentiatedFromTags...>>::
260  apply(make_not_null(&input_transforms),
261  std::forward_as_tuple(inputs...), l_max,
262  number_of_radial_points);
263  });
264 
265  // apply the modal derivative factors and place the result in the
266  // `transform_of_derivatives`
268  dispatch_to_compute_coefficients_of_derivative<
269  DerivativeTags, tmpl::list<UniqueDifferentiatedFromTags...>>::
270  apply(transform_of_derivatives,
271  std::make_tuple(transform_of_inputs...), l_max,
272  number_of_radial_points));
273 
274  // perform the inverse transform on the derivative results, placing the
275  // result in the nodal `derivatives` passed by pointer.
276  using InverseTransformList =
277  make_inverse_transform_list<Representation,
278  tmpl::list<DerivativeTags...>>;
279 
280  tmpl::for_each<InverseTransformList>([&number_of_radial_points, &l_max,
281  &derivatives...,
282  &transform_of_derivatives...](
283  auto transform_v) noexcept {
284  using transform = typename decltype(transform_v)::type;
285  auto derivative_tuple = std::make_tuple(derivatives...);
286  dispatch_to_transform<transform, tmpl::list<DerivativeTags...>>::apply(
287  make_not_null(&derivative_tuple),
288  std::make_tuple(transform_of_derivatives...), l_max,
289  number_of_radial_points);
290  });
291  }
292 };
293 
294 // metafunction for determining the tags needed to evaluate the derivative tags
295 // in `DerivativeTagList`, removing all duplicate tags.
296 template <typename DerivativeTagList>
297 struct unique_derived_from_list;
298 
299 template <typename... DerivativeTags>
300 struct unique_derived_from_list<tmpl::list<DerivativeTags...>> {
301  using type = tmpl::remove_duplicates<
302  tmpl::list<typename DerivativeTags::derivative_of...>>;
303 };
304 } // namespace detail
305 
306 /*!
307  * \ingroup SpectralGroup
308  * \brief A \ref DataBoxGroup mutate-compatible computational struct for
309  * computing a set of spin-weighted spherical harmonic derivatives by
310  * grouping and batch-computing spin-weighted spherical harmonic transforms.
311  *
312  * \details A derivative is evaluated for each tag in `DerivativeTagList`. All
313  * entries in `DerivativeTagList` must be the tag
314  * `Spectral::Swsh::Tags::Derivative<Tag, DerivativeKind>` prefixing the `Tag`
315  * to be differentiated, and indicating the spin-weighted derivative
316  * `DerivativeKind` to be taken. A \ref DataBoxGroup on which this struct is
317  * invoked must contain:
318  * - each of the tags in `DerivativeTagList` (the results of the computation)
319  * - each of the tags `Tag` prefixed by `Spectral::Swsh::Tags::Derivative` in
320  * `DerivativeTagList` (the inputs of the computation).
321  * - each of the tags `Spectral::Swsh::Tags::SwshTransform<DerivativeTag>` for
322  * `DerivativeTag`in `DerivativeTagList` (the buffers for the derivative
323  * applied to the modes)
324  * - each of the tags `Spectral::Swsh::Tags::SwshTransform<Tag>` for `Tag`
325  * prefixed by any `DerivativeTag` in `DerivativeTagList` (the buffers for the
326  * transforms of the input data).
327  *
328  * This function optimizes the derivative taking process by clustering like
329  * spins of tags, forward-transforming each spin cluster together, applying the
330  * factor for the derivative to each modal vector, re-clustering according to
331  * the new spin weights (the derivatives alter the spin weights), and finally
332  * inverse-transforming in clusters.
333  */
334 template <typename DerivativeTagList, ComplexRepresentation Representation =
335  ComplexRepresentation::Interleaved>
336 using AngularDerivatives = detail::AngularDerivativesImpl<
337  DerivativeTagList,
338  typename detail::unique_derived_from_list<DerivativeTagList>::type,
339  Representation>;
340 
341 /*!
342  * \ingroup SpectralGroup
343  * \brief Produces a `SpinWeighted<ComplexModalVector, Spin>` of the appropriate
344  * size to be used as a modal buffer for `Spectral::Swsh::AngularDerivatives` or
345  * `Spectral::Swsh::angular_derivatives`.
346  *
347  * \details The `Spectral::Swsh::angular_derivatives` and
348  * `Spectral::Swsh::AngularDerivatives` interfaces require that calling code
349  * provides a buffer for the intermediate transform results, to ensure that
350  * callers are aware of the allocations and can suitably reuse buffers if
351  * possible. This utility eases the creation of those buffers.
352  */
353 template <int Spin>
354 auto swsh_buffer(const size_t l_max,
355  const size_t number_of_radial_points) noexcept {
357  size_of_libsharp_coefficient_vector(l_max) * number_of_radial_points};
358 }
359 
360 namespace detail {
361 // template 'implementation' for the `angular_derivatives` function below which
362 // evaluates an arbitrary number of derivatives, and places them in the set of
363 // nodal containers passed by pointer.
364 template <ComplexRepresentation Representation, typename... DerivativeKinds,
365  typename... ArgumentTypes, size_t... Is>
366 void angular_derivatives_impl(
367  const std::tuple<ArgumentTypes...>& argument_tuple, const size_t l_max,
368  const size_t number_of_radial_points, std::index_sequence<Is...> /*meta*/,
369  tmpl::list<DerivativeKinds...> /*meta*/,
370  std::bool_constant<true> /*buffers_included_in_arguments*/) noexcept {
372  tmpl::list<Tags::Derivative<
376  int, std::decay_t<decltype(get<Is + 3 * sizeof...(Is)>(
377  argument_tuple))>::spin>>,
378  DerivativeKinds>...>,
379  Representation>::apply_to_vectors(get<Is>(argument_tuple)...,
380  get<Is + sizeof...(Is)>(
381  argument_tuple)...,
382  get<Is + 2 * sizeof...(Is)>(
383  argument_tuple)...,
384  get<Is + 3 * sizeof...(Is)>(
385  argument_tuple)...,
386  l_max, number_of_radial_points);
387 }
388 
389 template <ComplexRepresentation Representation, typename... DerivativeKinds,
390  typename... ArgumentTypes, size_t... Is>
391 void angular_derivatives_impl(
392  const std::tuple<ArgumentTypes...>& argument_tuple, const size_t l_max,
393  const size_t number_of_radial_points,
394  std::index_sequence<Is...> index_sequence,
395  tmpl::list<DerivativeKinds...> derivative_kinds,
396  std::bool_constant<false> /*buffers_included_in_arguments*/) noexcept {
397  auto derivative_buffer_tuple = std::make_tuple(
398  swsh_buffer<std::decay_t<decltype(*get<Is>(argument_tuple))>::spin>(
399  l_max, number_of_radial_points)...);
400  auto input_buffer_tuple = std::make_tuple(
401  swsh_buffer<std::decay_t<decltype(get<Is + sizeof...(Is)>(
402  argument_tuple))>::spin>(l_max, number_of_radial_points)...);
403  angular_derivatives_impl<Representation>(
404  std::forward_as_tuple(make_not_null(&get<Is>(derivative_buffer_tuple))...,
405  make_not_null(&get<Is>(input_buffer_tuple))...,
406  get<Is>(argument_tuple)...,
407  get<Is + sizeof...(Is)>(argument_tuple)...),
408  l_max, number_of_radial_points, index_sequence, derivative_kinds,
410 }
411 } // namespace detail
412 
413 /*!
414  * \ingroup SpectralGroup
415  * \brief Evaluate all of the spin-weighted derivatives in `DerivKindList` on
416  * input `SpinWeighted<ComplexDataVector, Spin>` collocation data, returning by
417  * pointer.
418  *
419  * \details This function provides two interfaces, one in which the caller
420  * provides the intermediate coefficient buffers needed during the computation
421  * of the derivatives, and one in which those buffers are temporarily allocated
422  * during the derivative function calls.
423  *
424  * For the interface in which the caller does not provide buffers, the arguments
425  * must take the following structure (enforced by internal function calls):
426  *
427  * - `size_t l_max` : angular resolution for the spherical representation
428  * - `size_t number_of_radial_points` : radial resolution (number of consecutive
429  * blocks to evaluate derivatives, for each input vector )
430  * - for each `DerivKind` in `DerivKindList`, a
431  * `gsl::not_null<SpinWeighted<ComplexDataVector, Spin +
432  * Tags::derivative_spin_weight<DerivKind>>>` : the output of the derivative
433  * evaluation
434  * - for each `DerivKind` in `DerivKindList`, a `const
435  * SpinWeighted<ComplexDataVector, Spin>&` (where the `Spin` for these arguments
436  * matches the corresponding vector from the previous set) : the input to the
437  * derivative evaluation.
438  *
439  * For the interface in which the caller does provide buffers, the arguments
440  * must take the following structure (enforced by internal function calls):
441  *
442  * - `size_t l_max` : angular resolution for the spherical representation
443  * - `size_t number_of_radial_points` : radial resolution (number of consecutive
444  * blocks to evaluate derivatives, for each input vector )
445  * - for each `DerivKind` in `DerivKindList`, a
446  * `gsl::not_null<SpinWeighted<ComplexModalVector, Spin +
447  * Tags::derivative_spin_weight<DerivKind>>>` : the buffer for the spin-weighted
448  * spherical harmonic modes of the derivative quantities.
449  * - for each `DerivKind` in `DerivKindList`, a `const
450  * SpinWeighted<ComplexModalVector, Spin>` (where the `Spin` for these arguments
451  * matches the corresponding vector from the previous set) : the buffer for the
452  * spin-weighted spherical harmonic modes of the input quantities.
453  * - for each `DerivKind` in `DerivKindList`, a
454  * `gsl::not_null<SpinWeighted<ComplexDataVector, Spin +
455  * Tags::derivative_spin_weight<DerivKind>>>` : the output of the derivative
456  * evaluation
457  * - for each `DerivKind` in `DerivKindList`, a `const
458  * SpinWeighted<ComplexDataVector, Spin>` (where the `Spin` for these arguments
459  * matches the corresponding vector from the previous set) : the input to the
460  * derivative evaluation.
461  *
462  * The function `swsh_buffer` assists in generating the modal buffers of
463  * appropriate size.
464  */
465 template <
466  typename DerivativeKindList,
467  ComplexRepresentation Representation = ComplexRepresentation::Interleaved,
468  typename... ArgumentTypes>
469 void angular_derivatives(const size_t l_max, // NOLINT
470  const size_t number_of_radial_points, // NOLINT
471  const ArgumentTypes&... arguments) noexcept {
472  static_assert(
473  tmpl::size<DerivativeKindList>::value * 2 == sizeof...(ArgumentTypes) or
474  tmpl::size<DerivativeKindList>::value * 4 == sizeof...(ArgumentTypes),
475  "When using the tagless `angular_derivatives` interface, you must "
476  "provide either one nodal input and one nodal output per derivative "
477  "or one nodal input, one nodal output, and two appropriate "
478  "intermediate transform buffers per derivative.");
479 
480  detail::angular_derivatives_impl<Representation>(
481  std::forward_as_tuple(arguments...), l_max, number_of_radial_points,
482  std::make_index_sequence<tmpl::size<DerivativeKindList>::value>{},
483  DerivativeKindList{},
484  std::bool_constant<tmpl::size<DerivativeKindList>::value * 4 ==
485  sizeof...(ArgumentTypes)>{});
486 }
487 
488 /*!
489  * \ingroup SpectralGroup
490  * \brief Evaluate the spin-weighted derivative `DerivKind` on the provided
491  * `SpinWeighted<ComplexDataVector, Spin>` collocation data, returning by value.
492  */
493 template <
494  typename DerivKind,
495  ComplexRepresentation Representation = ComplexRepresentation::Interleaved,
496  int Spin>
499  size_t l_max, size_t number_of_radial_points,
500  const SpinWeighted<ComplexDataVector, Spin>& to_differentiate) noexcept;
501 } // namespace Swsh
502 } // namespace Spectral
Spectral::Swsh::AngularDerivatives
detail::AngularDerivativesImpl< DerivativeTagList, typename detail::unique_derived_from_list< DerivativeTagList >::type, Representation > AngularDerivatives
A DataBox mutate-compatible computational struct for computing a set of spin-weighted spherical harmo...
Definition: SwshDerivatives.hpp:339
Spectral::Swsh::angular_derivative
SpinWeighted< ComplexDataVector, Tags::derivative_spin_weight< DerivKind >+Spin > angular_derivative(const size_t l_max, const size_t number_of_radial_points, const SpinWeighted< ComplexDataVector, Spin > &to_differentiate) noexcept
Evaluate the spin-weighted derivative DerivKind on the provided SpinWeighted<ComplexDataVector,...
Definition: SwshDerivatives.cpp:92
std::bool_constant
EXPAND_PACK_LEFT_TO_RIGHT
#define EXPAND_PACK_LEFT_TO_RIGHT(...)
Expand a parameter pack evaluating the terms from left to right.
Definition: TMPL.hpp:563
Spectral::Swsh::ComplexRepresentation
ComplexRepresentation
A set of labels for the possible representations of complex numbers for the ComplexDataView and the c...
Definition: ComplexDataView.hpp:57
get
constexpr Tag::type & get(Variables< TagList > &v) noexcept
Return Tag::type pointing into the contiguous array.
Definition: Variables.hpp:689
std::index_sequence
Spectral::Swsh::swsh_buffer
auto swsh_buffer(const size_t l_max, const size_t number_of_radial_points) noexcept
Produces a SpinWeighted<ComplexModalVector, Spin> of the appropriate size to be used as a modal buffe...
Definition: SwshDerivatives.hpp:354
std::tuple
Spectral::Swsh::size_of_libsharp_coefficient_vector
constexpr size_t size_of_libsharp_coefficient_vector(const size_t l_max) noexcept
Convenience function for determining the number of spin-weighted spherical harmonics coefficients tha...
Definition: SwshCoefficients.hpp:34
Tags::SpinWeighted
Given a Tag with a type of Tensor<VectorType, ...>, acts as a new version of the tag with type of Ten...
Definition: Tags.hpp:59
SpinWeighted
Make a spin-weighted type T with spin-weight Spin. Mathematical operators are restricted to addition,...
Definition: SpinWeighted.hpp:24
std::sqrt
T sqrt(T... args)
Spectral::Swsh::make_transform_list_from_derivative_tags
typename detail::make_transform_list_impl< -2, Representation, tmpl::transform< DerivativeTagList, tmpl::bind< db::remove_tag_prefix, tmpl::_1 > >, decltype(std::make_integer_sequence< int, 5 >{})>::type make_transform_list_from_derivative_tags
Assemble a tmpl::list of SwshTransforms given a list of Spectral::Swsh::Tags::Derivative<Tag,...
Definition: SwshTransform.hpp:784
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:1443
SPECTRE_ALWAYS_INLINE
#define SPECTRE_ALWAYS_INLINE
Definition: ForceInline.hpp:16
cstddef
db::item_type
typename DataBox_detail::item_type_impl< TagList, Tag >::type item_type
Get the type that can be written to the Tag. If it is a base tag then a TagList must be passed as a s...
Definition: DataBoxTag.hpp:246
std::decay_t
ComplexModalVector
A class for storing complex spectral coefficients on a spectral grid.
Definition: ComplexModalVector.hpp:39
Variables.hpp
Tags::TempTensor
Definition: Variables.hpp:937
Gsl.hpp
ForceInline.hpp
Spectral::Swsh::angular_derivatives
void angular_derivatives(const size_t l_max, const size_t number_of_radial_points, const ArgumentTypes &... arguments) noexcept
Evaluate all of the spin-weighted derivatives in DerivKindList on input SpinWeighted<ComplexDataVecto...
Definition: SwshDerivatives.hpp:469
complex
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
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: Gsl.hpp:183
Spectral
Functionality associated with a particular choice of basis functions and quadrature for spectral oper...
Definition: Chebyshev.cpp:19