ComputeRhsTensorIndexRank2TestHelpers.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 
10 #include "Utilities/GenerateInstantiations.hpp"
11 #include "Utilities/TMPL.hpp"
12 
13 namespace TestHelpers::TensorExpressions {
14 
15 /// \ingroup TestingFrameworkGroup
16 /// \brief Test that the computed tensor multi-index of a rank 2 RHS Tensor is
17 /// equivalent to the given LHS tensor multi-index, according to the order of
18 /// their generic indices
19 ///
20 /// \details `TensorIndexA` and `TensorIndexB` can be any type of TensorIndex
21 /// and are not necessarily `ti_a_t` and `ti_b_t`. The "A" and "B" suffixes just
22 /// denote the ordering of the generic indices of the RHS tensor expression. In
23 /// the RHS tensor expression, it means `TensorIndexA` is the first index used
24 /// and `TensorIndexB` is the second index used.
25 ///
26 /// If we consider the RHS tensor's generic indices to be (a, b), the possible
27 /// orderings of the LHS tensor's generic indices are: (a, b) and (b, a). For
28 /// each of these cases, this test checks that for each LHS component's tensor
29 /// multi-index, the equivalent RHS tensor multi-index is correctly computed.
30 ///
31 /// \tparam DataType the type of data being stored in the Tensors
32 /// \tparam RhsSymmetry the ::Symmetry of the RHS Tensor
33 /// \tparam RhsTensorIndexTypeList the RHS Tensor's typelist of
34 /// \ref SpacetimeIndex "TensorIndexType"s
35 /// \param tensorindex_a the first TensorIndex used on the RHS of the
36 /// TensorExpression, e.g. `ti_a`
37 /// \param tensorindex_b the second TensorIndex used on the RHS of the
38 /// TensorExpression, e.g. `ti_B`
39 template <typename DataType, typename RhsSymmetry,
40  typename RhsTensorIndexTypeList, typename TensorIndexA,
41  typename TensorIndexB>
43  const TensorIndexA& tensorindex_a,
44  const TensorIndexB& tensorindex_b) noexcept {
45  const Tensor<DataType, RhsSymmetry, RhsTensorIndexTypeList> rhs_tensor(5_st);
46  // Get TensorExpression from RHS tensor
47  const auto R_ab = rhs_tensor(tensorindex_a, tensorindex_b);
48 
49  const std::array<size_t, 2> index_order_ab = {TensorIndexA::value,
50  TensorIndexB::value};
51  const std::array<size_t, 2> index_order_ba = {TensorIndexB::value,
52  TensorIndexA::value};
53 
54  const size_t dim_a = tmpl::at_c<RhsTensorIndexTypeList, 0>::dim;
55  const size_t dim_b = tmpl::at_c<RhsTensorIndexTypeList, 1>::dim;
56 
57  for (size_t i = 0; i < dim_a; i++) {
58  for (size_t j = 0; j < dim_b; j++) {
59  const std::array<size_t, 2> ij = {i, j};
60  const std::array<size_t, 2> ji = {j, i};
61 
62  // For L_{ab} = R_{ab}, check that L_{ij} == R_{ij}
63  CHECK(R_ab.compute_rhs_tensor_index(index_order_ab, index_order_ab, ij) ==
64  ij);
65  // For L_{ba} = R_{ab}, check that L_{ij} == R_{ji}
66  CHECK(R_ab.compute_rhs_tensor_index(index_order_ba, index_order_ab, ij) ==
67  ji);
68  }
69  }
70 }
71 
72 /// \ingroup TestingFrameworkGroup
73 /// \brief Iterate testing of computing the RHS tensor multi-index equivalent of
74 /// the LHS tensor multi-index with rank 2 Tensors on multiple Frame types and
75 /// dimension combinations
76 ///
77 /// We test nonsymmetric indices and symmetric indices across two functions to
78 /// ensure that the code works correctly with symmetries. This function tests
79 /// one of the following symmetries:
80 /// - <2, 1> (`test_compute_rhs_tensor_index_rank_2_no_symmetry`)
81 /// - <1, 1> (`test_compute_rhs_tensor_index_rank_2_symmetric`)
82 ///
83 /// \details `TensorIndexA` and `TensorIndexB` can be any type of TensorIndex
84 /// and are not necessarily `ti_a_t` and `ti_b_t`. The "A" and "B" suffixes just
85 /// denote the ordering of the generic indices of the RHS tensor expression. In
86 /// the RHS tensor expression, it means `TensorIndexA` is the first index used
87 /// and `TensorIndexB` is the second index used.
88 ///
89 /// Note: `test_compute_rhs_tensor_index_rank_2_symmetric` has fewer template
90 /// parameters due to the two indices having a shared \ref SpacetimeIndex
91 /// "TensorIndexType" and and valence
92 ///
93 /// \tparam DataType the type of data being stored in the Tensors
94 /// \tparam TensorIndexTypeA the \ref SpacetimeIndex "TensorIndexType" of the
95 /// first index of the RHS Tensor
96 /// \tparam TensorIndexTypeB the \ref SpacetimeIndex "TensorIndexType" of the
97 /// second index of the RHS Tensor
98 /// \tparam ValenceA the valence of the first index used on the RHS of the
99 /// TensorExpression
100 /// \tparam ValenceB the valence of the second index used on the RHS of the
101 /// TensorExpression
102 /// \param tensorindex_a the first TensorIndex used on the RHS of the
103 /// TensorExpression, e.g. `ti_a`
104 /// \param tensorindex_b the second TensorIndex used on the RHS of the
105 /// TensorExpression, e.g. `ti_B`
106 template <
107  typename DataType, template <size_t, UpLo, typename> class TensorIndexTypeA,
108  template <size_t, UpLo, typename> class TensorIndexTypeB, UpLo ValenceA,
109  UpLo ValenceB, typename TensorIndexA, typename TensorIndexB>
111  const TensorIndexA& tensorindex_a,
112  const TensorIndexB& tensorindex_b) noexcept {
113 #define DIM_A(data) BOOST_PP_TUPLE_ELEM(0, data)
114 #define DIM_B(data) BOOST_PP_TUPLE_ELEM(1, data)
115 #define FRAME(data) BOOST_PP_TUPLE_ELEM(2, data)
116 
117 #define CALL_TEST_COMPUTE_RHS_TENSOR_INDEX_RANK_2_IMPL(_, data) \
118  test_compute_rhs_tensor_index_rank_2_impl< \
119  DataType, Symmetry<2, 1>, \
120  index_list<TensorIndexTypeA<DIM_A(data), ValenceA, FRAME(data)>, \
121  TensorIndexTypeB<DIM_B(data), ValenceB, FRAME(data)>>>( \
122  tensorindex_a, tensorindex_b);
123 
124  GENERATE_INSTANTIATIONS(CALL_TEST_COMPUTE_RHS_TENSOR_INDEX_RANK_2_IMPL,
125  (1, 2, 3), (1, 2, 3), (Frame::Grid, Frame::Inertial))
126 
127 #undef CALL_TEST_COMPUTE_RHS_TENSOR_INDEX_RANK_2_IMPL
128 #undef FRAME
129 #undef DIM_B
130 #undef DIM_A
131 }
132 
133 /// \ingroup TestingFrameworkGroup
134 /// \copydoc test_compute_rhs_tensor_index_rank_2_no_symmetry()
135 template <
136  typename DataType, template <size_t, UpLo, typename> class TensorIndexType,
137  UpLo Valence, typename TensorIndexA, typename TensorIndexB>
139  const TensorIndexA& tensorindex_a,
140  const TensorIndexB& tensorindex_b) noexcept {
141 #define DIM(data) BOOST_PP_TUPLE_ELEM(0, data)
142 #define FRAME(data) BOOST_PP_TUPLE_ELEM(1, data)
143 
144 #define CALL_TEST_COMPUTE_RHS_TENSOR_INDEX_RANK_2_IMPL(_, data) \
145  test_compute_rhs_tensor_index_rank_2_impl< \
146  DataType, Symmetry<1, 1>, \
147  index_list<TensorIndexType<DIM(data), Valence, FRAME(data)>, \
148  TensorIndexType<DIM(data), Valence, FRAME(data)>>, \
149  TensorIndexA, TensorIndexB>(tensorindex_a, tensorindex_b);
150 
151  GENERATE_INSTANTIATIONS(CALL_TEST_COMPUTE_RHS_TENSOR_INDEX_RANK_2_IMPL,
152  (1, 2, 3), (Frame::Grid, Frame::Inertial))
153 
154 #undef CALL_TEST_COMPUTE_RHS_TENSOR_INDEX_RANK_2_IMPL
155 #undef FRAME
156 #undef DIM
157 }
158 
159 } // namespace TestHelpers::TensorExpressions
Frame::Inertial
Definition: IndexType.hpp:44
TensorExpression.hpp
UpLo
UpLo
Definition: IndexType.hpp:20
Frame::Grid
Definition: IndexType.hpp:43
cstddef
std::array< size_t, 2 >
TestHelpers::TensorExpressions::test_compute_rhs_tensor_index_rank_2_impl
void test_compute_rhs_tensor_index_rank_2_impl(const TensorIndexA &tensorindex_a, const TensorIndexB &tensorindex_b) noexcept
Test that the computed tensor multi-index of a rank 2 RHS Tensor is equivalent to the given LHS tenso...
Definition: ComputeRhsTensorIndexRank2TestHelpers.hpp:42
Tensor.hpp
TestHelpers::TensorExpressions::test_compute_rhs_tensor_index_rank_2_symmetric
void test_compute_rhs_tensor_index_rank_2_symmetric(const TensorIndexA &tensorindex_a, const TensorIndexB &tensorindex_b) noexcept
Iterate testing of computing the RHS tensor multi-index equivalent of the LHS tensor multi-index with...
Definition: ComputeRhsTensorIndexRank2TestHelpers.hpp:138
GENERATE_INSTANTIATIONS
#define GENERATE_INSTANTIATIONS(INSTANTIATION_MACRO,...)
Macro useful for generating many explicit instantiations of function or class templates.
Definition: GenerateInstantiations.hpp:160
TMPL.hpp
TestHelpers::TensorExpressions::test_compute_rhs_tensor_index_rank_2_no_symmetry
void test_compute_rhs_tensor_index_rank_2_no_symmetry(const TensorIndexA &tensorindex_a, const TensorIndexB &tensorindex_b) noexcept
Iterate testing of computing the RHS tensor multi-index equivalent of the LHS tensor multi-index with...
Definition: ComputeRhsTensorIndexRank2TestHelpers.hpp:110