EvaluateRank4TestHelpers.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <iterator>
8 #include <numeric>
9 
13 #include "Utilities/TMPL.hpp"
14 
15 namespace TestHelpers::TensorExpressions {
16 
17 /// \ingroup TestingFrameworkGroup
18 /// \brief Test that evaluating a right hand side tensor expression containing a
19 /// single rank 4 tensor correctly assigns the data to the evaluated left hand
20 /// side tensor
21 ///
22 /// \details `TensorIndexA`, `TensorIndexB`, `TensorIndexC`, and `TensorIndexD`
23 /// can be any type of TensorIndex and are not necessarily `ti_a`, `ti_b`,
24 /// `ti_c`, and `ti_d`. The "A", "B", "C", and "D" suffixes just denote the
25 /// ordering of the generic indices of the RHS tensor expression. In the RHS
26 /// tensor expression, it means `TensorIndexA` is the first index used,
27 /// `TensorIndexB` is the second index used, `TensorIndexC` is the third index
28 /// used, and `TensorIndexD` is the fourth index used.
29 ///
30 /// If we consider the RHS tensor's generic indices to be (a, b, c, d), then
31 /// this test checks that the data in the evaluated LHS tensor is correct
32 /// according to the index orders of the LHS and RHS. The possible cases that
33 /// are checked are when the LHS tensor is evaluated with index orders of all 24
34 /// permutations of (a, b, c, d), e.g. (a, b, d, c), (a, c, b, d), ...
35 ///
36 /// \tparam DataType the type of data being stored in the Tensors
37 /// \tparam RhsSymmetry the ::Symmetry of the RHS Tensor
38 /// \tparam RhsTensorIndexTypeList the RHS Tensor's typelist of
39 /// \ref SpacetimeIndex "TensorIndexType"s
40 /// \tparam TensorIndexA the first TensorIndex used on the RHS of the
41 /// TensorExpression, e.g. `ti_a`
42 /// \tparam TensorIndexB the second TensorIndex used on the RHS of the
43 /// TensorExpression, e.g. `ti_B`
44 /// \tparam TensorIndexC the third TensorIndex used on the RHS of the
45 /// TensorExpression, e.g. `ti_c`
46 /// \tparam TensorIndexD the fourth TensorIndex used on the RHS of the
47 /// TensorExpression, e.g. `ti_D`
48 template <typename DataType, typename RhsSymmetry,
49  typename RhsTensorIndexTypeList, auto& TensorIndexA,
50  auto& TensorIndexB, auto& TensorIndexC, auto& TensorIndexD>
51 void test_evaluate_rank_4() noexcept {
52  Tensor<DataType, RhsSymmetry, RhsTensorIndexTypeList> R_abcd(5_st);
53  std::iota(R_abcd.begin(), R_abcd.end(), 0.0);
54 
55  // Used for enforcing the ordering of the symmetry and TensorIndexTypes of the
56  // LHS Tensor returned by `evaluate`
57  const std::int32_t rhs_symmetry_element_a = tmpl::at_c<RhsSymmetry, 0>::value;
58  const std::int32_t rhs_symmetry_element_b = tmpl::at_c<RhsSymmetry, 1>::value;
59  const std::int32_t rhs_symmetry_element_c = tmpl::at_c<RhsSymmetry, 2>::value;
60  const std::int32_t rhs_symmetry_element_d = tmpl::at_c<RhsSymmetry, 3>::value;
61  using rhs_tensorindextype_a = tmpl::at_c<RhsTensorIndexTypeList, 0>;
62  using rhs_tensorindextype_b = tmpl::at_c<RhsTensorIndexTypeList, 1>;
63  using rhs_tensorindextype_c = tmpl::at_c<RhsTensorIndexTypeList, 2>;
64  using rhs_tensorindextype_d = tmpl::at_c<RhsTensorIndexTypeList, 3>;
65 
66  // L_{abcd} = R_{abcd}
67  // Use explicit type (vs auto) so the compiler checks the return type of
68  // `evaluate`
69  const Tensor<DataType, RhsSymmetry, RhsTensorIndexTypeList> L_abcd =
70  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexB, TensorIndexC,
71  TensorIndexD>(
72  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
73 
74  // L_{abdc} = R_{abcd}
75  using L_abdc_symmetry =
76  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_b,
77  rhs_symmetry_element_d, rhs_symmetry_element_c>;
78  using L_abdc_tensorindextype_list =
79  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_b,
80  rhs_tensorindextype_d, rhs_tensorindextype_c>;
81  const Tensor<DataType, L_abdc_symmetry, L_abdc_tensorindextype_list> L_abdc =
82  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexB, TensorIndexD,
83  TensorIndexC>(
84  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
85 
86  // L_{acbd} = R_{abcd}
87  using L_acbd_symmetry =
88  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_c,
89  rhs_symmetry_element_b, rhs_symmetry_element_d>;
90  using L_acbd_tensorindextype_list =
91  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_c,
92  rhs_tensorindextype_b, rhs_tensorindextype_d>;
93  const Tensor<DataType, L_acbd_symmetry, L_acbd_tensorindextype_list> L_acbd =
94  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexC, TensorIndexB,
95  TensorIndexD>(
96  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
97 
98  // L_{acdb} = R_{abcd}
99  using L_acdb_symmetry =
100  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_c,
101  rhs_symmetry_element_d, rhs_symmetry_element_b>;
102  using L_acdb_tensorindextype_list =
103  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_c,
104  rhs_tensorindextype_d, rhs_tensorindextype_b>;
105  const Tensor<DataType, L_acdb_symmetry, L_acdb_tensorindextype_list> L_acdb =
106  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexC, TensorIndexD,
107  TensorIndexB>(
108  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
109 
110  // L_{adbc} = R_{abcd}
111  using L_adbc_symmetry =
112  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_d,
113  rhs_symmetry_element_b, rhs_symmetry_element_c>;
114  using L_adbc_tensorindextype_list =
115  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_d,
116  rhs_tensorindextype_b, rhs_tensorindextype_c>;
117  const Tensor<DataType, L_adbc_symmetry, L_adbc_tensorindextype_list> L_adbc =
118  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexD, TensorIndexB,
119  TensorIndexC>(
120  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
121 
122  // L_{adcb} = R_{abcd}
123  using L_adcb_symmetry =
124  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_d,
125  rhs_symmetry_element_c, rhs_symmetry_element_b>;
126  using L_adcb_tensorindextype_list =
127  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_d,
128  rhs_tensorindextype_c, rhs_tensorindextype_b>;
129  const Tensor<DataType, L_adcb_symmetry, L_adcb_tensorindextype_list> L_adcb =
130  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexD, TensorIndexC,
131  TensorIndexB>(
132  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
133 
134  // L_{bacd} = R_{abcd}
135  using L_bacd_symmetry =
136  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_a,
137  rhs_symmetry_element_c, rhs_symmetry_element_d>;
138  using L_bacd_tensorindextype_list =
139  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_a,
140  rhs_tensorindextype_c, rhs_tensorindextype_d>;
141  const Tensor<DataType, L_bacd_symmetry, L_bacd_tensorindextype_list> L_bacd =
142  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexA, TensorIndexC,
143  TensorIndexD>(
144  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
145 
146  // L_{badc} = R_{abcd}
147  using L_badc_symmetry =
148  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_a,
149  rhs_symmetry_element_d, rhs_symmetry_element_c>;
150  using L_badc_tensorindextype_list =
151  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_a,
152  rhs_tensorindextype_d, rhs_tensorindextype_c>;
153  const Tensor<DataType, L_badc_symmetry, L_badc_tensorindextype_list> L_badc =
154  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexA, TensorIndexD,
155  TensorIndexC>(
156  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
157 
158  // L_{bcad} = R_{abcd}
159  using L_bcad_symmetry =
160  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_c,
161  rhs_symmetry_element_a, rhs_symmetry_element_d>;
162  using L_bcad_tensorindextype_list =
163  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_c,
164  rhs_tensorindextype_a, rhs_tensorindextype_d>;
165  const Tensor<DataType, L_bcad_symmetry, L_bcad_tensorindextype_list> L_bcad =
166  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexC, TensorIndexA,
167  TensorIndexD>(
168  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
169 
170  // L_{bcda} = R_{abcd}
171  using L_bcda_symmetry =
172  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_c,
173  rhs_symmetry_element_d, rhs_symmetry_element_a>;
174  using L_bcda_tensorindextype_list =
175  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_c,
176  rhs_tensorindextype_d, rhs_tensorindextype_a>;
177  const Tensor<DataType, L_bcda_symmetry, L_bcda_tensorindextype_list> L_bcda =
178  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexC, TensorIndexD,
179  TensorIndexA>(
180  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
181 
182  // L_{bdac} = R_{abcd}
183  using L_bdac_symmetry =
184  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_d,
185  rhs_symmetry_element_a, rhs_symmetry_element_c>;
186  using L_bdac_tensorindextype_list =
187  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_d,
188  rhs_tensorindextype_a, rhs_tensorindextype_c>;
189  const Tensor<DataType, L_bdac_symmetry, L_bdac_tensorindextype_list> L_bdac =
190  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexD, TensorIndexA,
191  TensorIndexC>(
192  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
193 
194  // L_{bdca} = R_{abcd}
195  using L_bdca_symmetry =
196  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_d,
197  rhs_symmetry_element_c, rhs_symmetry_element_a>;
198  using L_bdca_tensorindextype_list =
199  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_d,
200  rhs_tensorindextype_c, rhs_tensorindextype_a>;
201  const Tensor<DataType, L_bdca_symmetry, L_bdca_tensorindextype_list> L_bdca =
202  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexD, TensorIndexC,
203  TensorIndexA>(
204  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
205 
206  // L_{cabd} = R_{abcd}
207  using L_cabd_symmetry =
208  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_a,
209  rhs_symmetry_element_b, rhs_symmetry_element_d>;
210  using L_cabd_tensorindextype_list =
211  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_a,
212  rhs_tensorindextype_b, rhs_tensorindextype_d>;
213  const Tensor<DataType, L_cabd_symmetry, L_cabd_tensorindextype_list> L_cabd =
214  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexA, TensorIndexB,
215  TensorIndexD>(
216  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
217 
218  // L_{cadb} = R_{abcd}
219  using L_cadb_symmetry =
220  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_a,
221  rhs_symmetry_element_d, rhs_symmetry_element_b>;
222  using L_cadb_tensorindextype_list =
223  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_a,
224  rhs_tensorindextype_d, rhs_tensorindextype_b>;
225  const Tensor<DataType, L_cadb_symmetry, L_cadb_tensorindextype_list> L_cadb =
226  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexA, TensorIndexD,
227  TensorIndexB>(
228  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
229 
230  // L_{cbad} = R_{abcd}
231  using L_cbad_symmetry =
232  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_b,
233  rhs_symmetry_element_a, rhs_symmetry_element_d>;
234  using L_cbad_tensorindextype_list =
235  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_b,
236  rhs_tensorindextype_a, rhs_tensorindextype_d>;
237  const Tensor<DataType, L_cbad_symmetry, L_cbad_tensorindextype_list> L_cbad =
238  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexB, TensorIndexA,
239  TensorIndexD>(
240  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
241 
242  // L_{cbda} = R_{abcd}
243  using L_cbda_symmetry =
244  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_b,
245  rhs_symmetry_element_d, rhs_symmetry_element_a>;
246  using L_cbda_tensorindextype_list =
247  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_b,
248  rhs_tensorindextype_d, rhs_tensorindextype_a>;
249  const Tensor<DataType, L_cbda_symmetry, L_cbda_tensorindextype_list> L_cbda =
250  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexB, TensorIndexD,
251  TensorIndexA>(
252  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
253 
254  // L_{cdab} = R_{abcd}
255  using L_cdab_symmetry =
256  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_d,
257  rhs_symmetry_element_a, rhs_symmetry_element_b>;
258  using L_cdab_tensorindextype_list =
259  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_d,
260  rhs_tensorindextype_a, rhs_tensorindextype_b>;
261  const Tensor<DataType, L_cdab_symmetry, L_cdab_tensorindextype_list> L_cdab =
262  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexD, TensorIndexA,
263  TensorIndexB>(
264  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
265 
266  // L_{cdba} = R_{abcd}
267  using L_cdba_symmetry =
268  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_d,
269  rhs_symmetry_element_b, rhs_symmetry_element_a>;
270  using L_cdba_tensorindextype_list =
271  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_d,
272  rhs_tensorindextype_b, rhs_tensorindextype_a>;
273  const Tensor<DataType, L_cdba_symmetry, L_cdba_tensorindextype_list> L_cdba =
274  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexD, TensorIndexB,
275  TensorIndexA>(
276  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
277 
278  // L_{dabc} = R_{abcd}
279  using L_dabc_symmetry =
280  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_a,
281  rhs_symmetry_element_b, rhs_symmetry_element_c>;
282  using L_dabc_tensorindextype_list =
283  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_a,
284  rhs_tensorindextype_b, rhs_tensorindextype_c>;
285  const Tensor<DataType, L_dabc_symmetry, L_dabc_tensorindextype_list> L_dabc =
286  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexA, TensorIndexB,
287  TensorIndexC>(
288  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
289 
290  // L_{dacb} = R_{abcd}
291  using L_dacb_symmetry =
292  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_a,
293  rhs_symmetry_element_c, rhs_symmetry_element_b>;
294  using L_dacb_tensorindextype_list =
295  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_a,
296  rhs_tensorindextype_c, rhs_tensorindextype_b>;
297  const Tensor<DataType, L_dacb_symmetry, L_dacb_tensorindextype_list> L_dacb =
298  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexA, TensorIndexC,
299  TensorIndexB>(
300  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
301 
302  // L_{dbac} = R_{abcd}
303  using L_dbac_symmetry =
304  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_b,
305  rhs_symmetry_element_a, rhs_symmetry_element_c>;
306  using L_dbac_tensorindextype_list =
307  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_b,
308  rhs_tensorindextype_a, rhs_tensorindextype_c>;
309  const Tensor<DataType, L_dbac_symmetry, L_dbac_tensorindextype_list> L_dbac =
310  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexB, TensorIndexA,
311  TensorIndexC>(
312  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
313 
314  // L_{dbca} = R_{abcd}
315  using L_dbca_symmetry =
316  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_b,
317  rhs_symmetry_element_c, rhs_symmetry_element_a>;
318  using L_dbca_tensorindextype_list =
319  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_b,
320  rhs_tensorindextype_c, rhs_tensorindextype_a>;
321  const Tensor<DataType, L_dbca_symmetry, L_dbca_tensorindextype_list> L_dbca =
322  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexB, TensorIndexC,
323  TensorIndexA>(
324  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
325 
326  // L_{dcab} = R_{abcd}
327  using L_dcab_symmetry =
328  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_c,
329  rhs_symmetry_element_a, rhs_symmetry_element_b>;
330  using L_dcab_tensorindextype_list =
331  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_c,
332  rhs_tensorindextype_a, rhs_tensorindextype_b>;
333  const Tensor<DataType, L_dcab_symmetry, L_dcab_tensorindextype_list> L_dcab =
334  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexC, TensorIndexA,
335  TensorIndexB>(
336  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
337 
338  // L_{dcba} = R_{abcd}
339  using L_dcba_symmetry =
340  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_c,
341  rhs_symmetry_element_b, rhs_symmetry_element_a>;
342  using L_dcba_tensorindextype_list =
343  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_c,
344  rhs_tensorindextype_b, rhs_tensorindextype_a>;
345  const Tensor<DataType, L_dcba_symmetry, L_dcba_tensorindextype_list> L_dcba =
346  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexC, TensorIndexB,
347  TensorIndexA>(
348  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
349 
350  const size_t dim_a = tmpl::at_c<RhsTensorIndexTypeList, 0>::dim;
351  const size_t dim_b = tmpl::at_c<RhsTensorIndexTypeList, 1>::dim;
352  const size_t dim_c = tmpl::at_c<RhsTensorIndexTypeList, 2>::dim;
353  const size_t dim_d = tmpl::at_c<RhsTensorIndexTypeList, 3>::dim;
354 
355  for (size_t i = 0; i < dim_a; ++i) {
356  for (size_t j = 0; j < dim_b; ++j) {
357  for (size_t k = 0; k < dim_c; ++k) {
358  for (size_t l = 0; l < dim_d; ++l) {
359  // For L_{abcd} = R_{abcd}, check that L_{ijkl} == R_{ijkl}
360  CHECK(L_abcd.get(i, j, k, l) == R_abcd.get(i, j, k, l));
361  // For L_{abdc} = R_{abcd}, check that L_{ijlk} == R_{ijkl}
362  CHECK(L_abdc.get(i, j, l, k) == R_abcd.get(i, j, k, l));
363  // For L_{acbd} = R_{abcd}, check that L_{ikjl} == R_{ijkl}
364  CHECK(L_acbd.get(i, k, j, l) == R_abcd.get(i, j, k, l));
365  // For L_{acdb} = R_{abcd}, check that L_{iklj} == R_{ijkl}
366  CHECK(L_acdb.get(i, k, l, j) == R_abcd.get(i, j, k, l));
367  // For L_{adbc} = R_{abcd}, check that L_{iljk} == R_{ijkl}
368  CHECK(L_adbc.get(i, l, j, k) == R_abcd.get(i, j, k, l));
369  // For L_{adcb} = R_{abcd}, check that L_{ilkj} == R_{ijkl}
370  CHECK(L_adcb.get(i, l, k, j) == R_abcd.get(i, j, k, l));
371  // For L_{bacd} = R_{abcd}, check that L_{jikl} == R_{ijkl}
372  CHECK(L_bacd.get(j, i, k, l) == R_abcd.get(i, j, k, l));
373  // For L_{badc} = R_{abcd}, check that L_{jilk} == R_{ijkl}
374  CHECK(L_badc.get(j, i, l, k) == R_abcd.get(i, j, k, l));
375  // For L_{bcad} = R_{abcd}, check that L_{jkil} == R_{ijkl}
376  CHECK(L_bcad.get(j, k, i, l) == R_abcd.get(i, j, k, l));
377  // For L_{bcda} = R_{abcd}, check that L_{jkli} == R_{ijkl}
378  CHECK(L_bcda.get(j, k, l, i) == R_abcd.get(i, j, k, l));
379  // For L_{bdac} = R_{abcd}, check that L_{jlik} == R_{ijkl}
380  CHECK(L_bdac.get(j, l, i, k) == R_abcd.get(i, j, k, l));
381  // For L_{bdca} = R_{abcd}, check that L_{jlki} == R_{ijkl}
382  CHECK(L_bdca.get(j, l, k, i) == R_abcd.get(i, j, k, l));
383  // For L_{cabd} = R_{abcd}, check that L_{kijl} == R_{ijkl}
384  CHECK(L_cabd.get(k, i, j, l) == R_abcd.get(i, j, k, l));
385  // For L_{cadb} = R_{abcd}, check that L_{kilj} == R_{ijkl}
386  CHECK(L_cadb.get(k, i, l, j) == R_abcd.get(i, j, k, l));
387  // For L_{cbad} = R_{abcd}, check that L_{kjil} == R_{ijkl}
388  CHECK(L_cbad.get(k, j, i, l) == R_abcd.get(i, j, k, l));
389  // For L_{cbda} = R_{abcd}, check that L_{kjli} == R_{ijkl}
390  CHECK(L_cbda.get(k, j, l, i) == R_abcd.get(i, j, k, l));
391  // For L_{cdab} = R_{abcd}, check that L_{klij} == R_{ijkl}
392  CHECK(L_cdab.get(k, l, i, j) == R_abcd.get(i, j, k, l));
393  // For L_{cdba} = R_{abcd}, check that L_{klji} == R_{ijkl}
394  CHECK(L_cdba.get(k, l, j, i) == R_abcd.get(i, j, k, l));
395  // For L_{dabc} = R_{abcd}, check that L_{lijk} == R_{ijkl}
396  CHECK(L_dabc.get(l, i, j, k) == R_abcd.get(i, j, k, l));
397  // For L_{dacb} = R_{abcd}, check that L_{likj} == R_{ijkl}
398  CHECK(L_dacb.get(l, i, k, j) == R_abcd.get(i, j, k, l));
399  // For L_{dbac} = R_{abcd}, check that L_{ljik} == R_{ijkl}
400  CHECK(L_dbac.get(l, j, i, k) == R_abcd.get(i, j, k, l));
401  // For L_{dbca} = R_{abcd}, check that L_{ljki} == R_{ijkl}
402  CHECK(L_dbca.get(l, j, k, i) == R_abcd.get(i, j, k, l));
403  // For L_{dcab} = R_{abcd}, check that L_{lkij} == R_{ijkl}
404  CHECK(L_dcab.get(l, k, i, j) == R_abcd.get(i, j, k, l));
405  // For L_{dcba} = R_{abcd}, check that L_{lkji} == R_{ijkl}
406  CHECK(L_dcba.get(l, k, j, i) == R_abcd.get(i, j, k, l));
407  }
408  }
409  }
410  }
411 }
412 
413 } // namespace TestHelpers::TensorExpressions
TensorExpression.hpp
TensorExpressions::evaluate
auto evaluate(const T &rhs_te)
Evaluate a RHS tensor expression to a tensor with the LHS index order set in the template parameters.
Definition: Evaluate.hpp:49
iterator
TestHelpers::TensorExpressions::test_evaluate_rank_4
void test_evaluate_rank_4() noexcept
Test that evaluating a right hand side tensor expression containing a single rank 4 tensor correctly ...
Definition: EvaluateRank4TestHelpers.hpp:51
cstddef
std::int32_t
Symmetry
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
Tensor.hpp
numeric
TMPL.hpp
Evaluate.hpp
cpp2b::iota
constexpr void iota(ForwardIterator first, ForwardIterator last, T value)
Definition: Numeric.hpp:20