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