IndexType.hpp
Go to the documentation of this file.
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 /// \file
5 /// Defines classes representing tensor indices
6 
7 #pragma once
8 
9 #include <cstddef>
10 #include <ostream>
11 #include <string>
12 #include <type_traits>
13 
14 #include "Utilities/Literals.hpp" // IWYU pragma: keep
15 #include "Utilities/TMPL.hpp"
16 
17 /// \ingroup TensorGroup
18 /// Whether a \ref SpacetimeIndex "TensorIndexType" is covariant or
19 /// contravariant
20 enum class UpLo {
21  /// Contravariant, or Upper index
22  Up,
23  /// Covariant, or Lower index
24  Lo
25 };
26 
27 /// \cond HIDDEN_SYMBOLS
28 inline std::ostream& operator<<(std::ostream& os, const UpLo& ul) {
29  return os << (ul == UpLo::Up ? "Up"s : "Lo"s);
30 }
31 /// \endcond
32 
33 /// \ingroup TensorGroup
34 /// Indicates the ::Frame that a \ref SpacetimeIndex "TensorIndexType"
35 /// is in.
36 namespace Frame {
37 /// \ingroup TensorGroup
38 /// Marks a Frame as being "physical" in the sense that it is meaningful to
39 /// evaluate an analytic solution in that frame.
40 struct FrameIsPhysical {};
41 
42 struct Logical {};
43 struct Grid {};
45 struct Distorted {};
46 /// Represents an index that is not in a known frame, e.g. some internal
47 /// intermediate frame that is irrelevant to the interface.
48 struct NoFrame {};
49 
50 /// Represents a spherical-coordinate frame that is associated with a
51 /// Cartesian frame, e.g. \f$(r,\theta,\phi)\f$ associated with the Inertial
52 /// frame, as used on an apparent horizon or a wave-extraction surface.
53 template <typename CartesianFrame>
54 struct Spherical {};
55 
56 /// \ingroup TensorGroup
57 /// Returns std::true_type if the frame is "physical" in the sense that it is
58 /// meaningful to evaluate an analytic solution in that frame.
59 /// \example
60 /// \snippet Test_Tensor.cpp is_frame_physical
61 template <typename CheckFrame>
62 using is_frame_physical =
65 
66 /// \ingroup TensorGroup
67 /// Returns true if the frame is "physical" in the sense that it is
68 /// meaningful to evaluate an analytic solution in that frame.
69 /// \example
70 /// \snippet Test_Tensor.cpp is_frame_physical
71 template <typename CheckFrame>
73 
74 /// \cond HIDDEN_SYMBOLS
75 inline std::ostream& operator<<(std::ostream& os,
76  const Frame::Logical& /*meta*/) {
77  return os << "Logical";
78 }
79 inline std::ostream& operator<<(std::ostream& os, const Frame::Grid& /*meta*/) {
80  return os << "Grid";
81 }
82 inline std::ostream& operator<<(std::ostream& os,
83  const Frame::Inertial& /*meta*/) {
84  return os << "Inertial";
85 }
86 inline std::ostream& operator<<(std::ostream& os,
87  const Frame::Distorted& /*meta*/) {
88  return os << "Distorted";
89 }
90 inline std::ostream& operator<<(std::ostream& os,
91  const Frame::NoFrame& /*meta*/) {
92  return os << "NoFrame";
93 }
94 /// \endcond
95 
96 /// \ingroup TensorGroup
97 /// The frame-dependent prefix used when constructing the string returned by the
98 /// name function of a tag.
99 ///
100 /// For Frame::Inertial it is the empty string, otherwise, it is the name of
101 /// the Frame followed by an underscore (as the name will be used in I/O).
102 /// \example
103 /// \snippet Hydro/Test_Tags.cpp prefix_example
104 template <typename Fr>
105 inline std::string prefix() noexcept;
106 
107 /// \cond HIDDEN_SYMBOLS
108 template <>
109 inline std::string prefix<Frame::Logical>() noexcept {
110  return "Logical_";
111 }
112 
113 template <>
114 inline std::string prefix<Frame::Grid>() noexcept {
115  return "Grid_";
116 }
117 
118 template <>
119 inline std::string prefix<Frame::Inertial>() noexcept {
120  return "";
121 }
122 
123 template <>
124 inline std::string prefix<Frame::Distorted>() noexcept {
125  return "Distorted_";
126 }
127 /// \endcond
128 } // namespace Frame
129 
130 /// \ingroup TensorGroup
131 /// Indicates whether the \ref SpacetimeIndex "TensorIndexType" is
132 /// Spatial or Spacetime
133 enum class IndexType : char {
134  /// The \ref SpatialIndex "TensorIndexType" is purely spatial
135  Spatial,
136  /// The \ref SpacetimeIndex "TensorIndexType" is a spacetime index
137  Spacetime
138 };
139 
140 /// \cond HIDDEN_SYMBOLS
141 inline std::ostream& operator<<(std::ostream& os, const IndexType& index_type) {
142  return os << (index_type == IndexType::Spatial ? "Spatial" : "Spacetime");
143 }
144 /// \endcond
145 
146 namespace Tensor_detail {
147 /// \ingroup TensorGroup
148 /// A ::TensorIndexType holds information about what type of index an index of a
149 /// Tensor is. It holds the information about the number of spatial dimensions,
150 /// whether the index is covariant or contravariant (::UpLo), the ::Frame the
151 /// index is in, and whether the Index is Spatial or Spacetime.
152 /// \tparam SpatialDim the spatial dimensionality of the TensorIndex
153 /// \tparam Ul either UpLo::Up or UpLo::Lo for contra or covariant
154 /// \tparam Fr the Frame the TensorIndex is in
155 /// \tparam Index either IndexType::Spatial or IndexType::Spacetime
156 template <size_t SpatialDim, UpLo Ul, typename Fr, IndexType Index>
157 struct TensorIndexType {
158  static_assert(SpatialDim > 0,
159  "Cannot have a spatial dimensionality less than 1 (one) in a "
160  "TensorIndexType");
161  using value_type = decltype(SpatialDim);
162  static constexpr value_type dim =
163  Index == IndexType::Spatial ? SpatialDim
164  : SpatialDim + static_cast<value_type>(1);
165  // value is here just so that some generic metafunctions can retrieve the dim
166  // easily
167  static constexpr value_type value = dim;
168  static constexpr UpLo ul = Ul;
169  using Frame = Fr;
170  static constexpr IndexType index_type = Index;
171 };
172 } // namespace Tensor_detail
173 
174 /// \ingroup TensorGroup
175 /// A SpatialIndex holds information about the number of spatial
176 /// dimensions, whether the index is covariant or contravariant (::UpLo), and
177 /// the ::Frame the index is in.
178 /// \tparam SpatialDim the spatial dimensionality of the \ref
179 /// SpatialIndex "TensorIndexType"
180 /// \tparam Ul either UpLo::Up or UpLo::Lo for contra or covariant
181 /// \tparam Fr the ::Frame the \ref SpatialIndex "TensorIndexType"
182 /// is in
183 template <size_t SpatialDim, UpLo Ul, typename Fr>
184 using SpatialIndex =
185  Tensor_detail::TensorIndexType<SpatialDim, Ul, Fr, IndexType::Spatial>;
186 
187 /// \ingroup TensorGroup
188 /// A SpacetimeIndex holds information about the number of spatial
189 /// dimensions, whether the index is covariant or contravariant (::UpLo), and
190 /// the ::Frame the index is in.
191 ///
192 /// \tparam SpatialDim the spatial dimensionality of the \ref
193 /// SpacetimeIndex "TensorIndexType"
194 /// \tparam Ul either UpLo::Up or UpLo::Lo for contra or covariant
195 /// \tparam Fr the ::Frame the \ref SpacetimeIndex "TensorIndexType"
196 /// is in
197 template <size_t SpatialDim, UpLo Ul, typename Fr>
198 using SpacetimeIndex =
199  Tensor_detail::TensorIndexType<SpatialDim, Ul, Fr, IndexType::Spacetime>;
200 
201 namespace tt {
202 // @{
203 /// \ingroup TensorGroup TypeTraits
204 /// Inherits from std::true_type if T is a \ref SpacetimeIndex
205 /// "TensorIndexType"
206 /// \tparam T the type to check
207 template <typename T>
209 /// \cond HIDDEN_SYMBOLS
210 template <size_t SpatialDim, UpLo Ul, typename Fr, IndexType Index>
211 struct is_tensor_index_type<
212  Tensor_detail::TensorIndexType<SpatialDim, Ul, Fr, Index>>
213  : std::true_type {};
214 /// \endcond
215 /// \see is_tensor_index_type
216 template <typename T>
218 // @}
219 } // namespace tt
220 
221 /// \ingroup TensorGroup
222 /// Change the \ref SpacetimeIndex "TensorIndexType" to be covariant
223 /// if it's contravariant and vice-versa
224 ///
225 /// Here is an example of how to use ::change_index_up_lo
226 /// \snippet Test_Tensor.cpp change_up_lo
227 ///
228 /// \tparam Index the \ref SpacetimeIndex "TensorIndexType" to change
229 template <typename Index>
230 using change_index_up_lo = Tensor_detail::TensorIndexType<
231  Index::index_type == IndexType::Spatial ? Index::value : Index::value - 1,
232  Index::ul == UpLo::Up ? UpLo::Lo : UpLo::Up, typename Index::Frame,
233  Index::index_type>;
234 
235 template <typename... Ts>
236 using index_list = tmpl::list<Ts...>;
Definition: IndexType.hpp:43
The TensorIndexType is purely spatial.
Covariant, or Lower index.
The TensorIndexType is a spacetime index.
Contravariant, or Upper index.
Definition: IndexType.hpp:146
typename is_tensor_index_type< T >::type is_tensor_index_type_t
Definition: IndexType.hpp:217
Definition: IndexType.hpp:45
Inherits from std::true_type if T is a TensorIndexType.
Definition: IndexType.hpp:208
A collection of useful type traits.
Definition: TensorExpression.hpp:115
std::string prefix() noexcept
The frame-dependent prefix used when constructing the string returned by the name function of a tag...
Tensor_detail::TensorIndexType< SpatialDim, Ul, Fr, IndexType::Spacetime > SpacetimeIndex
A SpacetimeIndex holds information about the number of spatial dimensions, whether the index is covar...
Definition: IndexType.hpp:199
Tensor_detail::TensorIndexType< SpatialDim, Ul, Fr, IndexType::Spatial > SpatialIndex
A SpatialIndex holds information about the number of spatial dimensions, whether the index is covaria...
Definition: IndexType.hpp:185
constexpr bool is_frame_physical_v
Returns true if the frame is "physical" in the sense that it is meaningful to evaluate an analytic so...
Definition: IndexType.hpp:72
Defines useful literals.
Marks a Frame as being "physical" in the sense that it is meaningful to evaluate an analytic solution...
Definition: IndexType.hpp:40
Indicates the Frame that a TensorIndexType is in.
Definition: IndexType.hpp:36
Definition: IndexType.hpp:42
Tensor_detail::TensorIndexType< Index::index_type==IndexType::Spatial ? Index::value :Index::value - 1, Index::ul==UpLo::Up ? UpLo::Lo :UpLo::Up, typename Index::Frame, Index::index_type > change_index_up_lo
Change the TensorIndexType to be covariant if it&#39;s contravariant and vice-versa.
Definition: IndexType.hpp:233
Represents an index that is not in a known frame, e.g. some internal intermediate frame that is irrel...
Definition: IndexType.hpp:48
Represents a spherical-coordinate frame that is associated with a Cartesian frame, e.g. associated with the Inertial frame, as used on an apparent horizon or a wave-extraction surface.
Definition: IndexType.hpp:54
Wraps the template metaprogramming library used (brigand)
An integer multi-index.
Definition: Index.hpp:28
IndexType
Indicates whether the TensorIndexType is Spatial or Spacetime.
Definition: IndexType.hpp:133
Definition: IndexType.hpp:44
UpLo
Whether a TensorIndexType is covariant or contravariant.
Definition: IndexType.hpp:20