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