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 : // implementation for get_tags_with_spin 255 : template <typename Tag, typename S> 256 : struct has_spin : std::bool_constant<Tag::type::type::spin == S::value> {}; 257 : 258 : template <typename PrefixTag, typename S> 259 : struct wrapped_has_spin : has_spin<typename PrefixTag::tag, S> {}; 260 : 261 : } // namespace detail 262 : 263 : /// \ingroup SwshGroup 264 : /// \brief A metafunction for determining the coefficient buffers needed by 265 : /// `angular_derivatives()` to avoid repeatedly allocating space for modal 266 : /// data each time a derivative is taken. 267 : /// \note Using these buffers is required to use the batch 268 : /// `angular_derivatives()` rather than the individual `angular_derivative()`. 269 : template <typename DerivativeTag> 270 1 : using coefficient_buffer_tags_for_derivative_tag = tmpl::list< 271 : Spectral::Swsh::Tags::SwshTransform<typename DerivativeTag::derivative_of>, 272 : Spectral::Swsh::Tags::SwshTransform<DerivativeTag>>; 273 : 274 : /// \ingroup SwshGroup 275 : /// \brief Extract from `TagList` the subset of those tags that have a static 276 : /// int member `spin` equal to the template parameter `Spin`. 277 : /// 278 : /// \snippet Test_SwshTags.cpp get_tags_with_spin 279 : template <int Spin, typename TagList> 280 1 : using get_tags_with_spin = tmpl::remove_duplicates<tmpl::filter< 281 : TagList, detail::has_spin<tmpl::_1, std::integral_constant<int, Spin>>>>; 282 : 283 : /// \ingroup SwshGroup 284 : /// \brief Extract from `TagList` the subset of those tags that wrap a tag 285 : /// that has a static int member `spin` equal to the template parameter `Spin`. 286 : /// 287 : /// \snippet Test_SwshTags.cpp get_prefix_tags_that_wrap_tags_with_spin 288 : template <int Spin, typename TagList> 289 1 : using get_prefix_tags_that_wrap_tags_with_spin = 290 : tmpl::filter<TagList, tmpl::bind<detail::wrapped_has_spin, tmpl::_1, 291 : std::integral_constant<int, Spin>>>; 292 : 293 : } // namespace Swsh 294 : } // namespace Spectral