IndexManipulation.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
7 #include "Utilities/Gsl.hpp"
9 #include "Utilities/TMPL.hpp"
10 
11 // IWYU pragma: no_forward_declare Tensor
12 
13 // @{
14 /*!
15  * \ingroup GeneralRelativityGroup
16  * \brief Raises or lowers the first index of a rank 3 tensor which is symmetric
17  * in the last two indices.
18  *
19  * \details If \f$T_{abc}\f$ is a tensor with \f$T_{abc} = T_{acb}\f$ and the
20  * indices \f$a,b,c,...\f$ can represent either spatial or spacetime indices,
21  * then the tensor \f$ T^a_{bc} = g^{ad} T_{abc} \f$ is computed, where \f$
22  * g^{ab}\f$ is the inverse metric, which is either a spatial or spacetime
23  * metric. If a tensor \f$ S^a_{bc} \f$ is passed as an argument than the
24  * corresponding tensor \f$ S_{abc} \f$ is calculated with respect to the metric
25  * \f$g_{ab}\f$. You may have to add a new instantiation of this template if
26  * you need a new use case.
27  */
28 template <typename DataType, typename Index0, typename Index1>
31  Tensor<DataType, Symmetry<2, 1, 1>,
32  index_list<change_index_up_lo<Index0>, Index1, Index1>>*>
33  result,
34  const Tensor<DataType, Symmetry<2, 1, 1>,
35  index_list<Index0, Index1, Index1>>& tensor,
36  const Tensor<DataType, Symmetry<1, 1>,
37  index_list<change_index_up_lo<Index0>,
38  change_index_up_lo<Index0>>>& metric) noexcept;
39 
40 template <typename DataType, typename Index0, typename Index1>
41 Tensor<DataType, Symmetry<2, 1, 1>,
42  index_list<change_index_up_lo<Index0>, Index1, Index1>>
44  const Tensor<DataType, Symmetry<2, 1, 1>,
45  index_list<Index0, Index1, Index1>>& tensor,
46  const Tensor<DataType, Symmetry<1, 1>,
47  index_list<change_index_up_lo<Index0>,
48  change_index_up_lo<Index0>>>& metric) noexcept {
49  auto result = make_with_value<
50  Tensor<DataType, Symmetry<2, 1, 1>,
51  index_list<change_index_up_lo<Index0>, Index1, Index1>>>(metric,
52  0.);
53  raise_or_lower_first_index(make_not_null(&result), tensor, metric);
54  return result;
55 }
56 // @}
57 
58 // @{
59 /*!
60  * \ingroup GeneralRelativityGroup
61  * \brief Raises or lowers the index of a rank 1 tensor.
62  *
63  * \details If \f$T_{a}\f$ is a tensor and the
64  * index \f$a\f$ can represent either a spatial or spacetime index,
65  * then the tensor \f$ T^a = g^{ad} T_{d} \f$ is computed, where \f$
66  * g^{ab}\f$ is the inverse metric, which is either a spatial or spacetime
67  * metric. If a tensor \f$ S^a \f$ is passed as an argument than the
68  * corresponding tensor \f$ S_{a} \f$ is calculated with respect to the metric
69  * \f$g_{ab}\f$.
70  */
71 template <typename DataType, typename Index0>
74  Tensor<DataType, Symmetry<1>, index_list<change_index_up_lo<Index0>>>*>
75  result,
76  const Tensor<DataType, Symmetry<1>, index_list<Index0>>& tensor,
77  const Tensor<DataType, Symmetry<1, 1>,
78  index_list<change_index_up_lo<Index0>,
79  change_index_up_lo<Index0>>>& metric) noexcept;
80 
81 template <typename DataType, typename Index0>
82 Tensor<DataType, Symmetry<1>, index_list<change_index_up_lo<Index0>>>
84  const Tensor<DataType, Symmetry<1>, index_list<Index0>>& tensor,
85  const Tensor<DataType, Symmetry<1, 1>,
86  index_list<change_index_up_lo<Index0>,
87  change_index_up_lo<Index0>>>& metric) noexcept {
88  auto result = make_with_value<
89  Tensor<DataType, Symmetry<1>, index_list<change_index_up_lo<Index0>>>>(
90  metric, 0.);
91  raise_or_lower_index(make_not_null(&result), tensor, metric);
92  return result;
93 }
94 // @}
95 
96 // @{
97 /*!
98  * \ingroup GeneralRelativityGroup
99  * \brief Computes trace of a rank 3 tensor, which is symmetric in its last two
100  * indices, tracing the symmetric indices.
101  *
102  * \details For example, if \f$ T_{abc} \f$ is a tensor such that \f$T_{abc} =
103  * T_{acb} \f$ then \f$ T_a = g^{bc}T_{abc} \f$ is computed, where \f$ g^{bc}
104  * \f$ is the inverse metric. Note that indices \f$a,b,c,...\f$ can represent
105  * either spatial or spacetime indices, and can have either valence. You may
106  * have to add a new instantiation of this template if you need a new use case.
107  */
108 template <typename DataType, typename Index0, typename Index1>
109 void trace_last_indices(
110  gsl::not_null<Tensor<DataType, Symmetry<1>, index_list<Index0>>*>
111  trace_of_tensor,
112  const Tensor<DataType, Symmetry<2, 1, 1>,
113  index_list<Index0, Index1, Index1>>& tensor,
114  const Tensor<DataType, Symmetry<1, 1>,
115  index_list<change_index_up_lo<Index1>,
116  change_index_up_lo<Index1>>>& metric) noexcept;
117 
118 template <typename DataType, typename Index0, typename Index1>
119 Tensor<DataType, Symmetry<1>, index_list<Index0>> trace_last_indices(
120  const Tensor<DataType, Symmetry<2, 1, 1>,
121  index_list<Index0, Index1, Index1>>& tensor,
122  const Tensor<DataType, Symmetry<1, 1>,
123  index_list<change_index_up_lo<Index1>,
124  change_index_up_lo<Index1>>>& metric) noexcept {
125  auto trace_of_tensor =
126  make_with_value<Tensor<DataType, Symmetry<1>, index_list<Index0>>>(metric,
127  0.);
128  trace_last_indices(make_not_null(&trace_of_tensor), tensor, metric);
129  return trace_of_tensor;
130 }
131 // @}
132 
133 // @{
134 /*!
135  * \ingroup GeneralRelativityGroup
136  * \brief Computes trace of a rank-2 symmetric tensor.
137  * \details Computes \f$g^{ab}T_{ab}\f$ or \f$g_{ab}T^{ab}\f$ where \f$(a,b)\f$
138  * can be spatial or spacetime indices.
139  */
140 template <typename DataType, typename Index0>
141 void trace(
143  const Tensor<DataType, Symmetry<1, 1>, index_list<Index0, Index0>>& tensor,
144  const Tensor<DataType, Symmetry<1, 1>,
145  index_list<change_index_up_lo<Index0>,
146  change_index_up_lo<Index0>>>& metric) noexcept;
147 
148 template <typename DataType, typename Index0>
150  const Tensor<DataType, Symmetry<1, 1>, index_list<Index0, Index0>>& tensor,
151  const Tensor<DataType, Symmetry<1, 1>,
152  index_list<change_index_up_lo<Index0>,
153  change_index_up_lo<Index0>>>& metric) noexcept {
155  ::trace(make_not_null(&trace), tensor, metric);
156  return trace;
157 }
158 // @}
void trace(gsl::not_null< Scalar< DataType > *> trace, const Tensor< DataType, Symmetry< 1, 1 >, index_list< Index0, Index0 >> &tensor, const Tensor< DataType, Symmetry< 1, 1 >, index_list< change_index_up_lo< Index0 >, change_index_up_lo< Index0 >>> &metric) noexcept
Computes trace of a rank-2 symmetric tensor.
void trace_last_indices(gsl::not_null< Tensor< DataType, Symmetry< 1 >, index_list< Index0 >> *> trace_of_tensor, const Tensor< DataType, Symmetry< 2, 1, 1 >, index_list< Index0, Index1, Index1 >> &tensor, const Tensor< DataType, Symmetry< 1, 1 >, index_list< change_index_up_lo< Index1 >, change_index_up_lo< Index1 >>> &metric) noexcept
Computes trace of a rank 3 tensor, which is symmetric in its last two indices, tracing the symmetric ...
void raise_or_lower_index(gsl::not_null< Tensor< DataType, Symmetry< 1 >, index_list< change_index_up_lo< Index0 >>> *> result, const Tensor< DataType, Symmetry< 1 >, index_list< Index0 >> &tensor, const Tensor< DataType, Symmetry< 1, 1 >, index_list< change_index_up_lo< Index0 >, change_index_up_lo< Index0 >>> &metric) noexcept
Raises or lowers the index of a rank 1 tensor.
typename detail::SymmetryImpl< std::make_index_sequence< sizeof...(T)>, tmpl::integral_list< std::int32_t, T... > >::type Symmetry
Computes the canonical symmetry from the integers T
Definition: Symmetry.hpp:81
std::remove_const_t< R > make_with_value(const T &input, const ValueType &value) noexcept
Given an object of type T, create an object of type R whose elements are initialized to value...
Definition: MakeWithValue.hpp:42
Defines classes for Tensor.
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
void raise_or_lower_first_index(gsl::not_null< Tensor< DataType, Symmetry< 2, 1, 1 >, index_list< change_index_up_lo< Index0 >, Index1, Index1 >> *> result, const Tensor< DataType, Symmetry< 2, 1, 1 >, index_list< Index0, Index1, Index1 >> &tensor, const Tensor< DataType, Symmetry< 1, 1 >, index_list< change_index_up_lo< Index0 >, change_index_up_lo< Index0 >>> &metric) noexcept
Raises or lowers the first index of a rank 3 tensor which is symmetric in the last two indices...
Wraps the template metaprogramming library used (brigand)
Defines functions and classes from the GSL.
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, but it may be necessary to perform the conversion explicitly when type deduction is desired.
Definition: Gsl.hpp:863
Tensor< T, Symmetry<>, index_list<> > Scalar
Scalar type.
Definition: TypeAliases.hpp:21
Require a pointer to not be a nullptr
Definition: ConservativeFromPrimitive.hpp:12
Defines make_with_value.