Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <string>
7 :
8 : #include "DataStructures/ComplexDataVector.hpp"
9 : #include "DataStructures/ComplexModalVector.hpp"
10 : #include "DataStructures/DataBox/Tag.hpp"
11 : #include "DataStructures/DataBox/TagName.hpp"
12 : #include "DataStructures/SpinWeighted.hpp"
13 : #include "DataStructures/Tensor/Tensor.hpp"
14 : #include "DataStructures/Tensor/TypeAliases.hpp"
15 : #include "Options/String.hpp"
16 : #include "Utilities/TMPL.hpp"
17 : #include "Utilities/TypeTraits.hpp"
18 :
19 : /// \cond
20 : namespace Cce::OptionTags {
21 : struct Cce;
22 : } // namespace Cce::OptionTags
23 : /// \endcond
24 :
25 : namespace Spectral {
26 : namespace Swsh {
27 : /// \cond
28 : class SwshInterpolator;
29 : /// \endcond
30 :
31 0 : namespace OptionTags {
32 0 : struct LMax {
33 0 : using type = size_t;
34 0 : static constexpr Options::String help{
35 : "Maximum l value for spin-weighted spherical harmonics"};
36 0 : using group = Cce::OptionTags::Cce;
37 : };
38 0 : struct NumberOfRadialPoints {
39 0 : using type = size_t;
40 0 : static constexpr Options::String help{
41 : "Number of radial grid points in the spherical domain"};
42 0 : using group = Cce::OptionTags::Cce;
43 : };
44 : } // namespace OptionTags
45 :
46 0 : namespace Tags {
47 :
48 : /// \ingroup SwshGroup
49 : /// \brief Struct for labeling the \f$\eth\f$ spin-weighted derivative in tags
50 1 : struct Eth {};
51 : /// \ingroup SwshGroup
52 : /// \brief Struct for labeling the \f$\bar{\eth}\f$ spin-weighted derivative in
53 : /// tags
54 1 : struct Ethbar {};
55 : /// \ingroup SwshGroup
56 : /// \brief Struct for labeling the \f$\eth^2\f$ spin-weighted derivative in tags
57 1 : struct EthEth {};
58 : /// \ingroup SwshGroup
59 : /// \brief Struct for labeling the \f$\bar{\eth} \eth\f$ spin-weighted
60 : /// derivative in tags
61 1 : struct EthbarEth {};
62 : /// \ingroup SwshGroup
63 : /// \brief Struct for labeling the \f$\eth \bar{\eth}\f$ spin-weighted
64 : /// derivative in tags
65 1 : struct EthEthbar {};
66 : /// \ingroup SwshGroup
67 : /// \brief Struct for labeling the \f$\bar{\eth}^2\f$ spin-weighted derivative
68 : /// in tags
69 1 : struct EthbarEthbar {};
70 :
71 : /// \ingroup SwshGroup
72 : /// \brief Struct for labeling the inverse \f$\eth^{-1}\f$ spin-weighted
73 : /// derivative in tags
74 1 : struct InverseEth {};
75 : /// \ingroup SwshGroup
76 : /// \brief Struct for labeling the inverse\f$\bar{\eth}^{-1}\f$ spin-weighted
77 : /// derivative in tags
78 1 : struct InverseEthbar {};
79 :
80 : /// \brief Struct which acts as a placeholder for a spin-weighted derivative
81 : /// label in the spin-weighted derivative utilities, but represents a 'no-op':
82 : /// no derivative is taken.
83 1 : struct NoDerivative {};
84 :
85 : namespace detail {
86 : template <typename DerivativeKind>
87 : inline constexpr int derivative_spin_weight_impl() {
88 : if (std::is_same_v<DerivativeKind, Eth> or
89 : std::is_same_v<DerivativeKind, InverseEthbar>) {
90 : return 1;
91 : } else if (std::is_same_v<DerivativeKind, Ethbar> or
92 : std::is_same_v<DerivativeKind, InverseEth>) {
93 : return -1;
94 : } else if (std::is_same_v<DerivativeKind, EthEth>) {
95 : return 2;
96 : } else if (std::is_same_v<DerivativeKind, EthbarEthbar>) {
97 : return -2;
98 : }
99 : return 0;
100 : }
101 : } // namespace detail
102 :
103 : // utility function for determining the change of spin after a spin-weighted
104 : // derivative has been applied.
105 : template <typename DerivativeKind>
106 0 : constexpr int derivative_spin_weight =
107 : detail::derivative_spin_weight_impl<DerivativeKind>();
108 :
109 : namespace detail {
110 : // The below tags are used to find the new type represented by the spin-weighted
111 : // derivative of a spin-weighted quantity. The derivatives alter the spin
112 : // weights, and so the utility `adjust_spin_weight_t<Tag, DerivativeKind>` is a
113 : // metafunction that determines the correct spin-weighted type for the
114 : // spin-weighted derivative `DerivativeKind` of `Tag`.
115 : //
116 : // if there is no `Tag::type::spin`, but the internal type is a compatible
117 : // complex vector type, the spin associated with `Tag` is assumed to be 0.
118 : template <typename DataType, typename DerivativeKind>
119 : struct adjust_spin_weight {
120 : using type =
121 : Scalar<SpinWeighted<DataType, derivative_spin_weight<DerivativeKind>>>;
122 : };
123 :
124 : // case for if there is a `Tag::type::spin`
125 : template <typename DataType, int Spin, typename DerivativeKind>
126 : struct adjust_spin_weight<SpinWeighted<DataType, Spin>, DerivativeKind> {
127 : using type = Scalar<
128 : SpinWeighted<DataType, Spin + derivative_spin_weight<DerivativeKind>>>;
129 : };
130 :
131 : template <typename Tag, typename DerivativeKind>
132 : using adjust_spin_weight_t =
133 : typename adjust_spin_weight<typename Tag::type::type, DerivativeKind>::type;
134 :
135 : // Helper function for creating an appropriate prefix tag name from one of the
136 : // spin-weighted derivative types and an existing tag name
137 : template <typename DerivativeKind>
138 : std::string compose_spin_weighted_derivative_name(const std::string& suffix);
139 :
140 : } // namespace detail
141 :
142 : /// Convenience metafunction for accessing the tag from which a `Derivative` was
143 : /// derived.
144 : template <typename Tag>
145 1 : using derived_from = typename Tag::derived_from;
146 :
147 : /// \ingroup SwshGroup
148 : /// \brief Prefix tag representing the spin-weighted derivative of a
149 : /// spin-weighted scalar.
150 : ///
151 : /// Template Parameters:
152 : /// - `Tag`: The tag to prefix
153 : /// - `DerivativeKind`: The type of spin-weighted derivative. This may be any of
154 : /// the labeling structs: `Eth`, `Ethbar`, `EthEth`, `EthbarEth`, `EthEthbar`,
155 : /// `EthbarEthbar`, or `NoDerivative`.
156 : ///
157 : /// Type Aliases and static values:
158 : /// - `type`: Always a `SpinWeighted<Scalar<ComplexDataVector>, Spin>`, where
159 : /// `Spin` is the spin weight after the derivative `DerivativeKind` has been
160 : /// applied.
161 : /// - `tag`: An alias to the wrapped tag `Tag`. Provided for applicability to
162 : /// general `db::PrefixTag` functionality.
163 : /// - `derivative_of`: Another alias to the wrapped tag `Tag`. Provided so that
164 : /// utilities that use this prefix for taking derivatives can have a more
165 : /// expressive code style.
166 : /// - `derivative_kind`: Type alias to `DerivativeKind`, represents the kind of
167 : /// spin-weighted derivative applied to `Tag`
168 : /// - `spin`: The spin weight of the scalar after the derivative has been
169 : /// applied.
170 : template <typename Tag, typename DerivativeKind>
171 1 : struct Derivative : db::PrefixTag, db::SimpleTag {
172 0 : using type = detail::adjust_spin_weight_t<Tag, DerivativeKind>;
173 0 : using tag = Tag;
174 : // derivative_of is provided as a second alias so that utilities that assume a
175 : // derivative prefix tag fail earlier during compilation
176 0 : using derivative_of = Tag;
177 0 : using derivative_kind = DerivativeKind;
178 0 : const static int spin = type::type::spin;
179 0 : static std::string name() {
180 : return detail::compose_spin_weighted_derivative_name<DerivativeKind>(
181 : db::tag_name<Tag>());
182 : }
183 : };
184 :
185 : /// \ingroup SwshGroup
186 : /// \brief Prefix tag representing the spin-weighted spherical harmonic
187 : /// transform of a spin-weighted scalar.
188 : ///
189 : /// Template Parameters:
190 : /// - `Tag`: The tag to prefix.
191 : ///
192 : /// Type aliases and static values:
193 : /// - `type`: Always a `SpinWeighted<Scalar<ComplexModalVector>, Spin>`, where
194 : /// `Spin` is the same spin weight of the pre-transformed `Tag`, and 0 if
195 : /// provided a `Tag` with a `Type` that is not `SpinWeighted`
196 : /// - `tag`: An alias to the wrapped tag `Tag`. Provided for applicability to
197 : /// general `db::PrefixTag` functionality
198 : /// - `transform_of`: Another alias to the wrapped tag `Tag`. Provided so that
199 : /// utilities that use this prefix for taking transforms can have a more
200 : /// expressive code style.
201 : template <typename Tag>
202 1 : struct SwshTransform : db::PrefixTag, db::SimpleTag {
203 0 : using type = Scalar<SpinWeighted<
204 : ComplexModalVector,
205 : detail::adjust_spin_weight_t<Tag, NoDerivative>::type::spin>>;
206 0 : using tag = Tag;
207 : // transform_of is provided as a second alias so that utilities that assume a
208 : // derivative prefix tag fail earlier during compilation
209 0 : using transform_of = Tag;
210 0 : const static int spin = type::type::spin;
211 : };
212 :
213 : /// \ingroup SwshGroup
214 : /// \brief Tag for the maximum spin-weighted spherical harmonic l; sets angular
215 : /// resolution.
216 1 : struct LMax : db::SimpleTag {
217 0 : using type = size_t;
218 0 : using option_tags = tmpl::list<OptionTags::LMax>;
219 :
220 0 : static constexpr bool pass_metavariables = false;
221 0 : static size_t create_from_options(const size_t l_max) { return l_max; }
222 : };
223 :
224 : /// \ingroup SwshGroup
225 : /// \brief Tag for the number of radial grid points in the three-dimensional
226 : /// representation of radially concentric spherical shells
227 1 : struct NumberOfRadialPoints : db::SimpleTag {
228 0 : using type = size_t;
229 0 : using option_tags = tmpl::list<OptionTags::NumberOfRadialPoints>;
230 :
231 0 : static constexpr bool pass_metavariables = false;
232 0 : static size_t create_from_options(const size_t number_of_radial_points) {
233 : return number_of_radial_points;
234 : }
235 : };
236 :
237 : /// \ingroup SwshGroup
238 : /// \brief Tag for a SwshInterpolator associated with a particular set
239 : /// of angular coordinates.
240 : ///
241 : /// \details It is recommended to use this to store a `SwshInterpolator` in the
242 : /// \ref DataBoxGroup of a parallel component, as interpolations can be
243 : /// significantly faster if they don't have to re-construct the
244 : /// `SwhsInterpolator` as frequently.
245 : template <typename Tag>
246 1 : struct SwshInterpolator : db::SimpleTag, db::PrefixTag {
247 0 : using tag = Tag;
248 0 : using type = ::Spectral::Swsh::SwshInterpolator;
249 : };
250 :
251 : } // namespace Tags
252 :
253 : namespace detail {
254 : template <typename Tag, typename S>
255 : struct has_spin : std::bool_constant<Tag::type::type::spin == S::value> {};
256 :
257 : template <typename TagList>
258 : struct spins_in_tag_list;
259 :
260 : template <typename... Tags>
261 : struct spins_in_tag_list<tmpl::list<Tags...>> {
262 : using type = tmpl::sort<tmpl::remove_duplicates<
263 : tmpl::list<std::integral_constant<int, Tags::type::type::spin>...>>>;
264 : };
265 : } // namespace detail
266 :
267 : /// \ingroup SwshGroup
268 : /// \brief A metafunction for determining the coefficient buffers needed by
269 : /// `angular_derivatives()` to avoid repeatedly allocating space for modal
270 : /// data each time a derivative is taken.
271 : /// \note Using these buffers is required to use the batch
272 : /// `angular_derivatives()` rather than the individual `angular_derivative()`.
273 : template <typename DerivativeTag>
274 1 : using coefficient_buffer_tags_for_derivative_tag = tmpl::list<
275 : Spectral::Swsh::Tags::SwshTransform<typename DerivativeTag::derivative_of>,
276 : Spectral::Swsh::Tags::SwshTransform<DerivativeTag>>;
277 :
278 : /// \ingroup SwshGroup
279 : /// \brief Get a list of distinct spins appearing in `TagList`.
280 : ///
281 : /// \snippet Test_SwshTags.cpp spins_in_tag_list
282 : template <typename TagList>
283 1 : using spins_in_tag_list = typename detail::spins_in_tag_list<TagList>::type;
284 :
285 : /// \ingroup SwshGroup
286 : /// \brief Partition `TagList` into lists with the same spin.
287 : ///
288 : /// \snippet Test_SwshTags.cpp partition_tags_by_spin
289 : template <typename TagList>
290 1 : using partition_tags_by_spin = tmpl::transform<
291 : spins_in_tag_list<TagList>,
292 : tmpl::lazy::filter<
293 : tmpl::pin<TagList>,
294 : tmpl::defer<detail::has_spin<tmpl::_1, tmpl::parent<tmpl::_1>>>>>;
295 : } // namespace Swsh
296 : } // namespace Spectral
|