Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines metafunctions used by Tensor
6 :
7 : #pragma once
8 :
9 : #include <cstddef>
10 : #include <cstdint>
11 : #include <type_traits>
12 :
13 : #include "DataStructures/Tensor/IndexType.hpp"
14 : #include "Utilities/TMPL.hpp"
15 :
16 : /// \cond
17 : template <typename X, typename Symm, typename IndexList>
18 : class Tensor;
19 : /// \endcond
20 :
21 : /// \ingroup TensorGroup
22 : /// Contains all metafunctions related to Tensor manipulations
23 1 : namespace TensorMetafunctions {
24 : namespace detail {
25 : template <unsigned>
26 : struct check_index_symmetry_impl;
27 : // empty typelist or only had a vector to start with
28 : template <>
29 : struct check_index_symmetry_impl<0> {
30 : template <typename...>
31 : using f = std::true_type;
32 : };
33 :
34 : // found incorrect symmetric index
35 : template <>
36 : struct check_index_symmetry_impl<1> {
37 : template <typename...>
38 : using f = std::false_type;
39 : };
40 :
41 : // recurse the list
42 : template <>
43 : struct check_index_symmetry_impl<2> {
44 : template <typename Symm, typename IndexSymm, typename Index0,
45 : typename... IndexPack>
46 : using f = typename check_index_symmetry_impl<
47 : tmpl::has_key<IndexSymm, tmpl::front<Symm>>::value and
48 : not std::is_same<Index0,
49 : tmpl::at<IndexSymm, tmpl::front<Symm>>>::value
50 : ? 1
51 : : tmpl::size<Symm>::value == 1 ? 0 : 2>::
52 : template f<tmpl::pop_front<Symm>,
53 : tmpl::insert<IndexSymm, tmpl::pair<tmpl::front<Symm>, Index0>>,
54 : IndexPack...>;
55 : };
56 :
57 : // helper function for prepending indices
58 : template <typename TheTensor>
59 : using new_sym_index =
60 : tmpl::int32_t<1 +
61 : tmpl::fold<typename TheTensor::symmetry, tmpl::int32_t<0>,
62 : tmpl::max<tmpl::_state, tmpl::_element>>::value>;
63 : } // namespace detail
64 :
65 : /*!
66 : * \ingroup TensorGroup
67 : * \brief Check that each of symmetric indices is in the same frame and have the
68 : * same dimensionality.
69 : */
70 : template <typename Symm, typename... IndexPack>
71 1 : using check_index_symmetry = typename detail::check_index_symmetry_impl<
72 : tmpl::size<Symm>::value == 0 or tmpl::size<Symm>::value == 1 ? 0 : 2>::
73 : template f<Symm, tmpl::map<>, IndexPack...>;
74 : template <typename Symm, typename... IndexPack>
75 0 : constexpr bool check_index_symmetry_v =
76 : check_index_symmetry<Symm, IndexPack...>::value;
77 :
78 : /*!
79 : * \ingroup TensorGroup
80 : * \brief Add a spatial index to the front of a Tensor
81 : *
82 : * \tparam TheTensor the tensor type to which the new index is prepended
83 : * \tparam VolumeDim the volume dimension of the tensor index to prepend
84 : * \tparam Fr the ::Frame of the tensor index to prepend
85 : */
86 : template <typename TheTensor, std::size_t VolumeDim, UpLo Ul, typename Fr>
87 1 : using prepend_spatial_index =
88 : ::Tensor<typename TheTensor::type,
89 : tmpl::push_front<typename TheTensor::symmetry,
90 : detail::new_sym_index<TheTensor>>,
91 : tmpl::push_front<typename TheTensor::index_list,
92 : SpatialIndex<VolumeDim, Ul, Fr>>>;
93 :
94 : /*!
95 : * \ingroup TensorGroup
96 : * \brief Add two symmetric spatial indices to the front of a Tensor (e.g. when
97 : * doing second derivatives)
98 : *
99 : * \tparam TheTensor the tensor type to which the new indices is prepended
100 : * \tparam VolumeDim the volume dimension of the tensor indices to prepend
101 : * \tparam Fr the ::Frame of the tensor indices to prepend
102 : */
103 : template <typename TheTensor, std::size_t VolumeDim, UpLo Ul, typename Fr>
104 1 : using prepend_two_symmetric_spatial_indices = ::Tensor<
105 : typename TheTensor::type,
106 : tmpl::push_front<tmpl::push_front<typename TheTensor::symmetry,
107 : detail::new_sym_index<TheTensor>>,
108 : detail::new_sym_index<TheTensor>>,
109 : tmpl::push_front<tmpl::push_front<typename TheTensor::index_list,
110 : SpatialIndex<VolumeDim, Ul, Fr>>,
111 : SpatialIndex<VolumeDim, Ul, Fr>>>;
112 :
113 : /*!
114 : * \ingroup TensorGroup
115 : * \brief Add a spacetime index to the front of a Tensor
116 : *
117 : * \tparam TheTensor the tensor type to which the new index is prepended
118 : * \tparam VolumeDim the volume dimension of the tensor index to prepend
119 : * \tparam Fr the ::Frame of the tensor index to prepend
120 : */
121 : template <typename TheTensor, std::size_t VolumeDim, UpLo Ul, typename Fr>
122 1 : using prepend_spacetime_index =
123 : ::Tensor<typename TheTensor::type,
124 : tmpl::push_front<typename TheTensor::symmetry,
125 : detail::new_sym_index<TheTensor>>,
126 : tmpl::push_front<typename TheTensor::index_list,
127 : SpacetimeIndex<VolumeDim, Ul, Fr>>>;
128 :
129 : /// \ingroup TensorGroup
130 : /// \brief remove the first index of a tensor
131 : /// \tparam TheTensor the tensor type whose first index is removed
132 : template <typename TheTensor>
133 1 : using remove_first_index =
134 : ::Tensor<typename TheTensor::type,
135 : tmpl::pop_front<typename TheTensor::symmetry>,
136 : tmpl::pop_front<typename TheTensor::index_list>>;
137 :
138 : /// \ingroup TensorGroup
139 : /// \brief Swap the valences of all indices on a Tensor
140 : template <typename TheTensor>
141 1 : using change_all_valences =
142 : ::Tensor<typename TheTensor::type, typename TheTensor::symmetry,
143 : tmpl::transform<typename TheTensor::index_list,
144 : tmpl::bind<change_index_up_lo, tmpl::_1>>>;
145 :
146 : /// \ingroup TensorGroup
147 : /// \brief Swap the data type of a tensor for a new type
148 : /// \tparam NewType the new data type
149 : /// \tparam TheTensor the tensor from which to keep symmetry and index
150 : /// information
151 : template <typename NewType, typename TheTensor>
152 1 : using swap_type = ::Tensor<NewType, typename TheTensor::symmetry,
153 : typename TheTensor::index_list>;
154 :
155 : namespace detail {
156 : template <typename T, typename Frame>
157 : using frame_is_the_same = std::is_same<typename T::Frame, Frame>;
158 : } // namespace detail
159 :
160 : /// \ingroup TensorGroup
161 : /// \brief Return tmpl::true_type if any indices of the Tensor are in the
162 : /// frame Frame.
163 : template <typename TheTensor, typename Frame>
164 1 : using any_index_in_frame =
165 : tmpl::any<typename TheTensor::index_list,
166 : tmpl::bind<detail::frame_is_the_same, tmpl::_1, Frame>>;
167 :
168 : /// \ingroup TensorGroup
169 : /// \brief Return true if any indices of the Tensor are in the
170 : /// frame Frame.
171 : template <typename TheTensor, typename Frame>
172 1 : constexpr bool any_index_in_frame_v =
173 : any_index_in_frame<TheTensor, Frame>::value;
174 :
175 : } // namespace TensorMetafunctions
|