EvaluateRank4TestHelpers.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <cstdint>
8 #include <iterator>
9 #include <numeric>
10 #include <type_traits>
11 
12 #include "DataStructures/Tags/TempTensor.hpp"
16 #include "Utilities/Gsl.hpp"
17 #include "Utilities/TMPL.hpp"
18 
19 namespace TestHelpers::TensorExpressions {
20 
21 /// \ingroup TestingFrameworkGroup
22 /// \brief Test that evaluating a right hand side tensor expression containing a
23 /// single rank 4 tensor correctly assigns the data to the evaluated left hand
24 /// side tensor
25 ///
26 /// \details `TensorIndexA`, `TensorIndexB`, `TensorIndexC`, and `TensorIndexD`
27 /// can be any type of TensorIndex and are not necessarily `ti_a`, `ti_b`,
28 /// `ti_c`, and `ti_d`. The "A", "B", "C", and "D" suffixes just denote the
29 /// ordering of the generic indices of the RHS tensor expression. In the RHS
30 /// tensor expression, it means `TensorIndexA` is the first index used,
31 /// `TensorIndexB` is the second index used, `TensorIndexC` is the third index
32 /// used, and `TensorIndexD` is the fourth index used.
33 ///
34 /// If we consider the RHS tensor's generic indices to be (a, b, c, d), then
35 /// this test checks that the data in the evaluated LHS tensor is correct
36 /// according to the index orders of the LHS and RHS. The possible cases that
37 /// are checked are when the LHS tensor is evaluated with index orders of all 24
38 /// permutations of (a, b, c, d), e.g. (a, b, d, c), (a, c, b, d), ...
39 ///
40 /// \tparam DataType the type of data being stored in the Tensors
41 /// \tparam RhsSymmetry the ::Symmetry of the RHS Tensor
42 /// \tparam RhsTensorIndexTypeList the RHS Tensor's typelist of
43 /// \ref SpacetimeIndex "TensorIndexType"s
44 /// \tparam TensorIndexA the first TensorIndex used on the RHS of the
45 /// TensorExpression, e.g. `ti_a`
46 /// \tparam TensorIndexB the second TensorIndex used on the RHS of the
47 /// TensorExpression, e.g. `ti_B`
48 /// \tparam TensorIndexC the third TensorIndex used on the RHS of the
49 /// TensorExpression, e.g. `ti_c`
50 /// \tparam TensorIndexD the fourth TensorIndex used on the RHS of the
51 /// TensorExpression, e.g. `ti_D`
52 template <typename DataType, typename RhsSymmetry,
53  typename RhsTensorIndexTypeList, auto& TensorIndexA,
54  auto& TensorIndexB, auto& TensorIndexC, auto& TensorIndexD>
55 void test_evaluate_rank_4() noexcept {
56  const size_t used_for_size = 5;
57  Tensor<DataType, RhsSymmetry, RhsTensorIndexTypeList> R_abcd(used_for_size);
58  std::iota(R_abcd.begin(), R_abcd.end(), 0.0);
59 
60  // Used for enforcing the ordering of the symmetry and TensorIndexTypes of the
61  // LHS Tensor returned by `evaluate`
62  const std::int32_t rhs_symmetry_element_a = tmpl::at_c<RhsSymmetry, 0>::value;
63  const std::int32_t rhs_symmetry_element_b = tmpl::at_c<RhsSymmetry, 1>::value;
64  const std::int32_t rhs_symmetry_element_c = tmpl::at_c<RhsSymmetry, 2>::value;
65  const std::int32_t rhs_symmetry_element_d = tmpl::at_c<RhsSymmetry, 3>::value;
66  using rhs_tensorindextype_a = tmpl::at_c<RhsTensorIndexTypeList, 0>;
67  using rhs_tensorindextype_b = tmpl::at_c<RhsTensorIndexTypeList, 1>;
68  using rhs_tensorindextype_c = tmpl::at_c<RhsTensorIndexTypeList, 2>;
69  using rhs_tensorindextype_d = tmpl::at_c<RhsTensorIndexTypeList, 3>;
70 
71  // L_{abcd} = R_{abcd}
72  // Use explicit type (vs auto) so the compiler checks the return type of
73  // `evaluate`
74  using L_abcd_type = Tensor<DataType, RhsSymmetry, RhsTensorIndexTypeList>;
75  const L_abcd_type L_abcd_returned =
76  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexB, TensorIndexC,
77  TensorIndexD>(
78  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
79  L_abcd_type L_abcd_filled{};
80  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexB, TensorIndexC,
81  TensorIndexD>(
82  make_not_null(&L_abcd_filled),
83  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
84 
85  // L_{abdc} = R_{abcd}
86  using L_abdc_symmetry =
87  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_b,
88  rhs_symmetry_element_d, rhs_symmetry_element_c>;
89  using L_abdc_tensorindextype_list =
90  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_b,
91  rhs_tensorindextype_d, rhs_tensorindextype_c>;
92  using L_abdc_type =
93  Tensor<DataType, L_abdc_symmetry, L_abdc_tensorindextype_list>;
94  const L_abdc_type L_abdc_returned =
95  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexB, TensorIndexD,
96  TensorIndexC>(
97  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
98  L_abdc_type L_abdc_filled{};
99  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexB, TensorIndexD,
100  TensorIndexC>(
101  make_not_null(&L_abdc_filled),
102  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
103 
104  // L_{acbd} = R_{abcd}
105  using L_acbd_symmetry =
106  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_c,
107  rhs_symmetry_element_b, rhs_symmetry_element_d>;
108  using L_acbd_tensorindextype_list =
109  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_c,
110  rhs_tensorindextype_b, rhs_tensorindextype_d>;
111  using L_acbd_type =
112  Tensor<DataType, L_acbd_symmetry, L_acbd_tensorindextype_list>;
113  const L_acbd_type L_acbd_returned =
114  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexC, TensorIndexB,
115  TensorIndexD>(
116  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
117  L_acbd_type L_acbd_filled{};
118  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexC, TensorIndexB,
119  TensorIndexD>(
120  make_not_null(&L_acbd_filled),
121  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
122 
123  // L_{acdb} = R_{abcd}
124  using L_acdb_symmetry =
125  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_c,
126  rhs_symmetry_element_d, rhs_symmetry_element_b>;
127  using L_acdb_tensorindextype_list =
128  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_c,
129  rhs_tensorindextype_d, rhs_tensorindextype_b>;
130  using L_acdb_type =
131  Tensor<DataType, L_acdb_symmetry, L_acdb_tensorindextype_list>;
132  const L_acdb_type L_acdb_returned =
133  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexC, TensorIndexD,
134  TensorIndexB>(
135  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
136  L_acdb_type L_acdb_filled{};
137  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexC, TensorIndexD,
138  TensorIndexB>(
139  make_not_null(&L_acdb_filled),
140  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
141 
142  // L_{adbc} = R_{abcd}
143  using L_adbc_symmetry =
144  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_d,
145  rhs_symmetry_element_b, rhs_symmetry_element_c>;
146  using L_adbc_tensorindextype_list =
147  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_d,
148  rhs_tensorindextype_b, rhs_tensorindextype_c>;
149  using L_adbc_type =
150  Tensor<DataType, L_adbc_symmetry, L_adbc_tensorindextype_list>;
151  const L_adbc_type L_adbc_returned =
152  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexD, TensorIndexB,
153  TensorIndexC>(
154  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
155  L_adbc_type L_adbc_filled{};
156  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexD, TensorIndexB,
157  TensorIndexC>(
158  make_not_null(&L_adbc_filled),
159  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
160 
161  // L_{adcb} = R_{abcd}
162  using L_adcb_symmetry =
163  Symmetry<rhs_symmetry_element_a, rhs_symmetry_element_d,
164  rhs_symmetry_element_c, rhs_symmetry_element_b>;
165  using L_adcb_tensorindextype_list =
166  tmpl::list<rhs_tensorindextype_a, rhs_tensorindextype_d,
167  rhs_tensorindextype_c, rhs_tensorindextype_b>;
168  using L_adcb_type =
169  Tensor<DataType, L_adcb_symmetry, L_adcb_tensorindextype_list>;
170  const L_adcb_type L_adcb_returned =
171  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexD, TensorIndexC,
172  TensorIndexB>(
173  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
174  L_adcb_type L_adcb_filled{};
175  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexD, TensorIndexC,
176  TensorIndexB>(
177  make_not_null(&L_adcb_filled),
178  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
179 
180  // L_{bacd} = R_{abcd}
181  using L_bacd_symmetry =
182  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_a,
183  rhs_symmetry_element_c, rhs_symmetry_element_d>;
184  using L_bacd_tensorindextype_list =
185  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_a,
186  rhs_tensorindextype_c, rhs_tensorindextype_d>;
187  using L_bacd_type =
188  Tensor<DataType, L_bacd_symmetry, L_bacd_tensorindextype_list>;
189  const L_bacd_type L_bacd_returned =
190  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexA, TensorIndexC,
191  TensorIndexD>(
192  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
193  L_bacd_type L_bacd_filled{};
194  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexA, TensorIndexC,
195  TensorIndexD>(
196  make_not_null(&L_bacd_filled),
197  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
198 
199  // L_{badc} = R_{abcd}
200  using L_badc_symmetry =
201  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_a,
202  rhs_symmetry_element_d, rhs_symmetry_element_c>;
203  using L_badc_tensorindextype_list =
204  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_a,
205  rhs_tensorindextype_d, rhs_tensorindextype_c>;
206  using L_badc_type =
207  Tensor<DataType, L_badc_symmetry, L_badc_tensorindextype_list>;
208  const L_badc_type L_badc_returned =
209  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexA, TensorIndexD,
210  TensorIndexC>(
211  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
212  L_badc_type L_badc_filled{};
213  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexA, TensorIndexD,
214  TensorIndexC>(
215  make_not_null(&L_badc_filled),
216  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
217 
218  // L_{bcad} = R_{abcd}
219  using L_bcad_symmetry =
220  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_c,
221  rhs_symmetry_element_a, rhs_symmetry_element_d>;
222  using L_bcad_tensorindextype_list =
223  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_c,
224  rhs_tensorindextype_a, rhs_tensorindextype_d>;
225  using L_bcad_type =
226  Tensor<DataType, L_bcad_symmetry, L_bcad_tensorindextype_list>;
227  const L_bcad_type L_bcad_returned =
228  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexC, TensorIndexA,
229  TensorIndexD>(
230  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
231  L_bcad_type L_bcad_filled{};
232  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexC, TensorIndexA,
233  TensorIndexD>(
234  make_not_null(&L_bcad_filled),
235  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
236 
237  // L_{bcda} = R_{abcd}
238  using L_bcda_symmetry =
239  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_c,
240  rhs_symmetry_element_d, rhs_symmetry_element_a>;
241  using L_bcda_tensorindextype_list =
242  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_c,
243  rhs_tensorindextype_d, rhs_tensorindextype_a>;
244  using L_bcda_type =
245  Tensor<DataType, L_bcda_symmetry, L_bcda_tensorindextype_list>;
246  const L_bcda_type L_bcda_returned =
247  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexC, TensorIndexD,
248  TensorIndexA>(
249  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
250  L_bcda_type L_bcda_filled{};
251  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexC, TensorIndexD,
252  TensorIndexA>(
253  make_not_null(&L_bcda_filled),
254  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
255 
256  // L_{bdac} = R_{abcd}
257  using L_bdac_symmetry =
258  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_d,
259  rhs_symmetry_element_a, rhs_symmetry_element_c>;
260  using L_bdac_tensorindextype_list =
261  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_d,
262  rhs_tensorindextype_a, rhs_tensorindextype_c>;
263  using L_bdac_type =
264  Tensor<DataType, L_bdac_symmetry, L_bdac_tensorindextype_list>;
265  const L_bdac_type L_bdac_returned =
266  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexD, TensorIndexA,
267  TensorIndexC>(
268  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
269  L_bdac_type L_bdac_filled{};
270  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexD, TensorIndexA,
271  TensorIndexC>(
272  make_not_null(&L_bdac_filled),
273  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
274 
275  // L_{bdca} = R_{abcd}
276  using L_bdca_symmetry =
277  Symmetry<rhs_symmetry_element_b, rhs_symmetry_element_d,
278  rhs_symmetry_element_c, rhs_symmetry_element_a>;
279  using L_bdca_tensorindextype_list =
280  tmpl::list<rhs_tensorindextype_b, rhs_tensorindextype_d,
281  rhs_tensorindextype_c, rhs_tensorindextype_a>;
282  using L_bdca_type =
283  Tensor<DataType, L_bdca_symmetry, L_bdca_tensorindextype_list>;
284  const L_bdca_type L_bdca_returned =
285  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexD, TensorIndexC,
286  TensorIndexA>(
287  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
288  L_bdca_type L_bdca_filled{};
289  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexD, TensorIndexC,
290  TensorIndexA>(
291  make_not_null(&L_bdca_filled),
292  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
293 
294  // L_{cabd} = R_{abcd}
295  using L_cabd_symmetry =
296  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_a,
297  rhs_symmetry_element_b, rhs_symmetry_element_d>;
298  using L_cabd_tensorindextype_list =
299  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_a,
300  rhs_tensorindextype_b, rhs_tensorindextype_d>;
301  using L_cabd_type =
302  Tensor<DataType, L_cabd_symmetry, L_cabd_tensorindextype_list>;
303  const L_cabd_type L_cabd_returned =
304  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexA, TensorIndexB,
305  TensorIndexD>(
306  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
307  L_cabd_type L_cabd_filled{};
308  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexA, TensorIndexB,
309  TensorIndexD>(
310  make_not_null(&L_cabd_filled),
311  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
312 
313  // L_{cadb} = R_{abcd}
314  using L_cadb_symmetry =
315  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_a,
316  rhs_symmetry_element_d, rhs_symmetry_element_b>;
317  using L_cadb_tensorindextype_list =
318  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_a,
319  rhs_tensorindextype_d, rhs_tensorindextype_b>;
320  using L_cadb_type =
321  Tensor<DataType, L_cadb_symmetry, L_cadb_tensorindextype_list>;
322  const L_cadb_type L_cadb_returned =
323  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexA, TensorIndexD,
324  TensorIndexB>(
325  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
326  L_cadb_type L_cadb_filled{};
327  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexA, TensorIndexD,
328  TensorIndexB>(
329  make_not_null(&L_cadb_filled),
330  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
331 
332  // L_{cbad} = R_{abcd}
333  using L_cbad_symmetry =
334  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_b,
335  rhs_symmetry_element_a, rhs_symmetry_element_d>;
336  using L_cbad_tensorindextype_list =
337  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_b,
338  rhs_tensorindextype_a, rhs_tensorindextype_d>;
339  using L_cbad_type =
340  Tensor<DataType, L_cbad_symmetry, L_cbad_tensorindextype_list>;
341  const L_cbad_type L_cbad_returned =
342  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexB, TensorIndexA,
343  TensorIndexD>(
344  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
345  L_cbad_type L_cbad_filled{};
346  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexB, TensorIndexA,
347  TensorIndexD>(
348  make_not_null(&L_cbad_filled),
349  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
350 
351  // L_{cbda} = R_{abcd}
352  using L_cbda_symmetry =
353  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_b,
354  rhs_symmetry_element_d, rhs_symmetry_element_a>;
355  using L_cbda_tensorindextype_list =
356  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_b,
357  rhs_tensorindextype_d, rhs_tensorindextype_a>;
358  using L_cbda_type =
359  Tensor<DataType, L_cbda_symmetry, L_cbda_tensorindextype_list>;
360  const L_cbda_type L_cbda_returned =
361  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexB, TensorIndexD,
362  TensorIndexA>(
363  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
364  L_cbda_type L_cbda_filled{};
365  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexB, TensorIndexD,
366  TensorIndexA>(
367  make_not_null(&L_cbda_filled),
368  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
369 
370  // L_{cdab} = R_{abcd}
371  using L_cdab_symmetry =
372  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_d,
373  rhs_symmetry_element_a, rhs_symmetry_element_b>;
374  using L_cdab_tensorindextype_list =
375  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_d,
376  rhs_tensorindextype_a, rhs_tensorindextype_b>;
377  using L_cdab_type =
378  Tensor<DataType, L_cdab_symmetry, L_cdab_tensorindextype_list>;
379  const L_cdab_type L_cdab_returned =
380  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexD, TensorIndexA,
381  TensorIndexB>(
382  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
383  L_cdab_type L_cdab_filled{};
384  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexD, TensorIndexA,
385  TensorIndexB>(
386  make_not_null(&L_cdab_filled),
387  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
388 
389  // L_{cdba} = R_{abcd}
390  using L_cdba_symmetry =
391  Symmetry<rhs_symmetry_element_c, rhs_symmetry_element_d,
392  rhs_symmetry_element_b, rhs_symmetry_element_a>;
393  using L_cdba_tensorindextype_list =
394  tmpl::list<rhs_tensorindextype_c, rhs_tensorindextype_d,
395  rhs_tensorindextype_b, rhs_tensorindextype_a>;
396  using L_cdba_type =
397  Tensor<DataType, L_cdba_symmetry, L_cdba_tensorindextype_list>;
398  const L_cdba_type L_cdba_returned =
399  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexD, TensorIndexB,
400  TensorIndexA>(
401  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
402  L_cdba_type L_cdba_filled{};
403  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexD, TensorIndexB,
404  TensorIndexA>(
405  make_not_null(&L_cdba_filled),
406  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
407 
408  // L_{dabc} = R_{abcd}
409  using L_dabc_symmetry =
410  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_a,
411  rhs_symmetry_element_b, rhs_symmetry_element_c>;
412  using L_dabc_tensorindextype_list =
413  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_a,
414  rhs_tensorindextype_b, rhs_tensorindextype_c>;
415  using L_dabc_type =
416  Tensor<DataType, L_dabc_symmetry, L_dabc_tensorindextype_list>;
417  const L_dabc_type L_dabc_returned =
418  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexA, TensorIndexB,
419  TensorIndexC>(
420  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
421  L_dabc_type L_dabc_filled{};
422  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexA, TensorIndexB,
423  TensorIndexC>(
424  make_not_null(&L_dabc_filled),
425  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
426 
427  // L_{dacb} = R_{abcd}
428  using L_dacb_symmetry =
429  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_a,
430  rhs_symmetry_element_c, rhs_symmetry_element_b>;
431  using L_dacb_tensorindextype_list =
432  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_a,
433  rhs_tensorindextype_c, rhs_tensorindextype_b>;
434  using L_dacb_type =
435  Tensor<DataType, L_dacb_symmetry, L_dacb_tensorindextype_list>;
436  const L_dacb_type L_dacb_returned =
437  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexA, TensorIndexC,
438  TensorIndexB>(
439  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
440  L_dacb_type L_dacb_filled{};
441  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexA, TensorIndexC,
442  TensorIndexB>(
443  make_not_null(&L_dacb_filled),
444  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
445 
446  // L_{dbac} = R_{abcd}
447  using L_dbac_symmetry =
448  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_b,
449  rhs_symmetry_element_a, rhs_symmetry_element_c>;
450  using L_dbac_tensorindextype_list =
451  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_b,
452  rhs_tensorindextype_a, rhs_tensorindextype_c>;
453  using L_dbac_type =
454  Tensor<DataType, L_dbac_symmetry, L_dbac_tensorindextype_list>;
455  const L_dbac_type L_dbac_returned =
456  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexB, TensorIndexA,
457  TensorIndexC>(
458  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
459  L_dbac_type L_dbac_filled{};
460  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexB, TensorIndexA,
461  TensorIndexC>(
462  make_not_null(&L_dbac_filled),
463  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
464 
465  // L_{dbca} = R_{abcd}
466  using L_dbca_symmetry =
467  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_b,
468  rhs_symmetry_element_c, rhs_symmetry_element_a>;
469  using L_dbca_tensorindextype_list =
470  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_b,
471  rhs_tensorindextype_c, rhs_tensorindextype_a>;
472  using L_dbca_type =
473  Tensor<DataType, L_dbca_symmetry, L_dbca_tensorindextype_list>;
474  const L_dbca_type L_dbca_returned =
475  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexB, TensorIndexC,
476  TensorIndexA>(
477  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
478  L_dbca_type L_dbca_filled{};
479  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexB, TensorIndexC,
480  TensorIndexA>(
481  make_not_null(&L_dbca_filled),
482  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
483 
484  // L_{dcab} = R_{abcd}
485  using L_dcab_symmetry =
486  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_c,
487  rhs_symmetry_element_a, rhs_symmetry_element_b>;
488  using L_dcab_tensorindextype_list =
489  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_c,
490  rhs_tensorindextype_a, rhs_tensorindextype_b>;
491  using L_dcab_type =
492  Tensor<DataType, L_dcab_symmetry, L_dcab_tensorindextype_list>;
493  const L_dcab_type L_dcab_returned =
494  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexC, TensorIndexA,
495  TensorIndexB>(
496  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
497  L_dcab_type L_dcab_filled{};
498  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexC, TensorIndexA,
499  TensorIndexB>(
500  make_not_null(&L_dcab_filled),
501  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
502 
503  // L_{dcba} = R_{abcd}
504  using L_dcba_symmetry =
505  Symmetry<rhs_symmetry_element_d, rhs_symmetry_element_c,
506  rhs_symmetry_element_b, rhs_symmetry_element_a>;
507  using L_dcba_tensorindextype_list =
508  tmpl::list<rhs_tensorindextype_d, rhs_tensorindextype_c,
509  rhs_tensorindextype_b, rhs_tensorindextype_a>;
510  using L_dcba_type =
511  Tensor<DataType, L_dcba_symmetry, L_dcba_tensorindextype_list>;
512  const L_dcba_type L_dcba_returned =
513  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexC, TensorIndexB,
514  TensorIndexA>(
515  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
516  L_dcba_type L_dcba_filled{};
517  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexC, TensorIndexB,
518  TensorIndexA>(
519  make_not_null(&L_dcba_filled),
520  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
521 
522  const size_t dim_a = tmpl::at_c<RhsTensorIndexTypeList, 0>::dim;
523  const size_t dim_b = tmpl::at_c<RhsTensorIndexTypeList, 1>::dim;
524  const size_t dim_c = tmpl::at_c<RhsTensorIndexTypeList, 2>::dim;
525  const size_t dim_d = tmpl::at_c<RhsTensorIndexTypeList, 3>::dim;
526 
527  for (size_t i = 0; i < dim_a; ++i) {
528  for (size_t j = 0; j < dim_b; ++j) {
529  for (size_t k = 0; k < dim_c; ++k) {
530  for (size_t l = 0; l < dim_d; ++l) {
531  // For L_{abcd} = R_{abcd}, check that L_{ijkl} == R_{ijkl}
532  CHECK(L_abcd_returned.get(i, j, k, l) == R_abcd.get(i, j, k, l));
533  CHECK(L_abcd_filled.get(i, j, k, l) == R_abcd.get(i, j, k, l));
534  // For L_{abdc} = R_{abcd}, check that L_{ijlk} == R_{ijkl}
535  CHECK(L_abdc_returned.get(i, j, l, k) == R_abcd.get(i, j, k, l));
536  CHECK(L_abdc_filled.get(i, j, l, k) == R_abcd.get(i, j, k, l));
537  // For L_{acbd} = R_{abcd}, check that L_{ikjl} == R_{ijkl}
538  CHECK(L_acbd_returned.get(i, k, j, l) == R_abcd.get(i, j, k, l));
539  CHECK(L_acbd_filled.get(i, k, j, l) == R_abcd.get(i, j, k, l));
540  // For L_{acdb} = R_{abcd}, check that L_{iklj} == R_{ijkl}
541  CHECK(L_acdb_returned.get(i, k, l, j) == R_abcd.get(i, j, k, l));
542  CHECK(L_acdb_filled.get(i, k, l, j) == R_abcd.get(i, j, k, l));
543  // For L_{adbc} = R_{abcd}, check that L_{iljk} == R_{ijkl}
544  CHECK(L_adbc_returned.get(i, l, j, k) == R_abcd.get(i, j, k, l));
545  CHECK(L_adbc_filled.get(i, l, j, k) == R_abcd.get(i, j, k, l));
546  // For L_{adcb} = R_{abcd}, check that L_{ilkj} == R_{ijkl}
547  CHECK(L_adcb_returned.get(i, l, k, j) == R_abcd.get(i, j, k, l));
548  CHECK(L_adcb_filled.get(i, l, k, j) == R_abcd.get(i, j, k, l));
549  // For L_{bacd} = R_{abcd}, check that L_{jikl} == R_{ijkl}
550  CHECK(L_bacd_returned.get(j, i, k, l) == R_abcd.get(i, j, k, l));
551  CHECK(L_bacd_filled.get(j, i, k, l) == R_abcd.get(i, j, k, l));
552  // For L_{badc} = R_{abcd}, check that L_{jilk} == R_{ijkl}
553  CHECK(L_badc_returned.get(j, i, l, k) == R_abcd.get(i, j, k, l));
554  CHECK(L_badc_filled.get(j, i, l, k) == R_abcd.get(i, j, k, l));
555  // For L_{bcad} = R_{abcd}, check that L_{jkil} == R_{ijkl}
556  CHECK(L_bcad_returned.get(j, k, i, l) == R_abcd.get(i, j, k, l));
557  CHECK(L_bcad_filled.get(j, k, i, l) == R_abcd.get(i, j, k, l));
558  // For L_{bcda} = R_{abcd}, check that L_{jkli} == R_{ijkl}
559  CHECK(L_bcda_returned.get(j, k, l, i) == R_abcd.get(i, j, k, l));
560  CHECK(L_bcda_filled.get(j, k, l, i) == R_abcd.get(i, j, k, l));
561  // For L_{bdac} = R_{abcd}, check that L_{jlik} == R_{ijkl}
562  CHECK(L_bdac_returned.get(j, l, i, k) == R_abcd.get(i, j, k, l));
563  CHECK(L_bdac_filled.get(j, l, i, k) == R_abcd.get(i, j, k, l));
564  // For L_{bdca} = R_{abcd}, check that L_{jlki} == R_{ijkl}
565  CHECK(L_bdca_returned.get(j, l, k, i) == R_abcd.get(i, j, k, l));
566  CHECK(L_bdca_filled.get(j, l, k, i) == R_abcd.get(i, j, k, l));
567  // For L_{cabd} = R_{abcd}, check that L_{kijl} == R_{ijkl}
568  CHECK(L_cabd_returned.get(k, i, j, l) == R_abcd.get(i, j, k, l));
569  CHECK(L_cabd_filled.get(k, i, j, l) == R_abcd.get(i, j, k, l));
570  // For L_{cadb} = R_{abcd}, check that L_{kilj} == R_{ijkl}
571  CHECK(L_cadb_returned.get(k, i, l, j) == R_abcd.get(i, j, k, l));
572  CHECK(L_cadb_filled.get(k, i, l, j) == R_abcd.get(i, j, k, l));
573  // For L_{cbad} = R_{abcd}, check that L_{kjil} == R_{ijkl}
574  CHECK(L_cbad_returned.get(k, j, i, l) == R_abcd.get(i, j, k, l));
575  CHECK(L_cbad_filled.get(k, j, i, l) == R_abcd.get(i, j, k, l));
576  // For L_{cbda} = R_{abcd}, check that L_{kjli} == R_{ijkl}
577  CHECK(L_cbda_returned.get(k, j, l, i) == R_abcd.get(i, j, k, l));
578  CHECK(L_cbda_filled.get(k, j, l, i) == R_abcd.get(i, j, k, l));
579  // For L_{cdab} = R_{abcd}, check that L_{klij} == R_{ijkl}
580  CHECK(L_cdab_returned.get(k, l, i, j) == R_abcd.get(i, j, k, l));
581  CHECK(L_cdab_filled.get(k, l, i, j) == R_abcd.get(i, j, k, l));
582  // For L_{cdba} = R_{abcd}, check that L_{klji} == R_{ijkl}
583  CHECK(L_cdba_returned.get(k, l, j, i) == R_abcd.get(i, j, k, l));
584  CHECK(L_cdba_filled.get(k, l, j, i) == R_abcd.get(i, j, k, l));
585  // For L_{dabc} = R_{abcd}, check that L_{lijk} == R_{ijkl}
586  CHECK(L_dabc_returned.get(l, i, j, k) == R_abcd.get(i, j, k, l));
587  CHECK(L_dabc_filled.get(l, i, j, k) == R_abcd.get(i, j, k, l));
588  // For L_{dacb} = R_{abcd}, check that L_{likj} == R_{ijkl}
589  CHECK(L_dacb_returned.get(l, i, k, j) == R_abcd.get(i, j, k, l));
590  CHECK(L_dacb_filled.get(l, i, k, j) == R_abcd.get(i, j, k, l));
591  // For L_{dbac} = R_{abcd}, check that L_{ljik} == R_{ijkl}
592  CHECK(L_dbac_returned.get(l, j, i, k) == R_abcd.get(i, j, k, l));
593  CHECK(L_dbac_filled.get(l, j, i, k) == R_abcd.get(i, j, k, l));
594  // For L_{dbca} = R_{abcd}, check that L_{ljki} == R_{ijkl}
595  CHECK(L_dbca_returned.get(l, j, k, i) == R_abcd.get(i, j, k, l));
596  CHECK(L_dbca_filled.get(l, j, k, i) == R_abcd.get(i, j, k, l));
597  // For L_{dcab} = R_{abcd}, check that L_{lkij} == R_{ijkl}
598  CHECK(L_dcab_returned.get(l, k, i, j) == R_abcd.get(i, j, k, l));
599  CHECK(L_dcab_filled.get(l, k, i, j) == R_abcd.get(i, j, k, l));
600  // For L_{dcba} = R_{abcd}, check that L_{lkji} == R_{ijkl}
601  CHECK(L_dcba_returned.get(l, k, j, i) == R_abcd.get(i, j, k, l));
602  CHECK(L_dcba_filled.get(l, k, j, i) == R_abcd.get(i, j, k, l));
603  }
604  }
605  }
606  }
607 
608  // Test with TempTensor for LHS tensor
609  if constexpr (not std::is_same_v<DataType, double>) {
610  // L_{abcd} = R_{abcd}
611  Variables<tmpl::list<::Tags::TempTensor<1, L_abcd_type>>> L_abcd_var{
612  used_for_size};
613  L_abcd_type& L_abcd_temp =
614  get<::Tags::TempTensor<1, L_abcd_type>>(L_abcd_var);
615  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexB, TensorIndexC,
616  TensorIndexD>(
617  make_not_null(&L_abcd_temp),
618  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
619 
620  // L_{abdc} = R_{abcd}
621  Variables<tmpl::list<::Tags::TempTensor<1, L_abdc_type>>> L_abdc_var{
622  used_for_size};
623  L_abdc_type& L_abdc_temp =
624  get<::Tags::TempTensor<1, L_abdc_type>>(L_abdc_var);
625  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexB, TensorIndexD,
626  TensorIndexC>(
627  make_not_null(&L_abdc_temp),
628  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
629 
630  // L_{acbd} = R_{abcd}
631  Variables<tmpl::list<::Tags::TempTensor<1, L_acbd_type>>> L_acbd_var{
632  used_for_size};
633  L_acbd_type& L_acbd_temp =
634  get<::Tags::TempTensor<1, L_acbd_type>>(L_acbd_var);
635  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexC, TensorIndexB,
636  TensorIndexD>(
637  make_not_null(&L_acbd_temp),
638  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
639 
640  // L_{acdb} = R_{abcd}
641  Variables<tmpl::list<::Tags::TempTensor<1, L_acdb_type>>> L_acdb_var{
642  used_for_size};
643  L_acdb_type& L_acdb_temp =
644  get<::Tags::TempTensor<1, L_acdb_type>>(L_acdb_var);
645  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexC, TensorIndexD,
646  TensorIndexB>(
647  make_not_null(&L_acdb_temp),
648  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
649 
650  // L_{adbc} = R_{abcd}
651  Variables<tmpl::list<::Tags::TempTensor<1, L_adbc_type>>> L_adbc_var{
652  used_for_size};
653  L_adbc_type& L_adbc_temp =
654  get<::Tags::TempTensor<1, L_adbc_type>>(L_adbc_var);
655  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexD, TensorIndexB,
656  TensorIndexC>(
657  make_not_null(&L_adbc_temp),
658  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
659 
660  // L_{adcb} = R_{abcd}
661  Variables<tmpl::list<::Tags::TempTensor<1, L_adcb_type>>> L_adcb_var{
662  used_for_size};
663  L_adcb_type& L_adcb_temp =
664  get<::Tags::TempTensor<1, L_adcb_type>>(L_adcb_var);
665  ::TensorExpressions::evaluate<TensorIndexA, TensorIndexD, TensorIndexC,
666  TensorIndexB>(
667  make_not_null(&L_adcb_temp),
668  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
669 
670  // L_{bacd} = R_{abcd}
671  Variables<tmpl::list<::Tags::TempTensor<1, L_bacd_type>>> L_bacd_var{
672  used_for_size};
673  L_bacd_type& L_bacd_temp =
674  get<::Tags::TempTensor<1, L_bacd_type>>(L_bacd_var);
675  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexA, TensorIndexC,
676  TensorIndexD>(
677  make_not_null(&L_bacd_temp),
678  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
679 
680  // L_{badc} = R_{abcd}
681  Variables<tmpl::list<::Tags::TempTensor<1, L_badc_type>>> L_badc_var{
682  used_for_size};
683  L_badc_type& L_badc_temp =
684  get<::Tags::TempTensor<1, L_badc_type>>(L_badc_var);
685  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexA, TensorIndexD,
686  TensorIndexC>(
687  make_not_null(&L_badc_temp),
688  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
689 
690  // L_{bcad} = R_{abcd}
691  Variables<tmpl::list<::Tags::TempTensor<1, L_bcad_type>>> L_bcad_var{
692  used_for_size};
693  L_bcad_type& L_bcad_temp =
694  get<::Tags::TempTensor<1, L_bcad_type>>(L_bcad_var);
695  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexC, TensorIndexA,
696  TensorIndexD>(
697  make_not_null(&L_bcad_temp),
698  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
699 
700  // L_{bcda} = R_{abcd}
701  Variables<tmpl::list<::Tags::TempTensor<1, L_bcda_type>>> L_bcda_var{
702  used_for_size};
703  L_bcda_type& L_bcda_temp =
704  get<::Tags::TempTensor<1, L_bcda_type>>(L_bcda_var);
705  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexC, TensorIndexD,
706  TensorIndexA>(
707  make_not_null(&L_bcda_temp),
708  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
709 
710  // L_{bdac} = R_{abcd}
711  Variables<tmpl::list<::Tags::TempTensor<1, L_bdac_type>>> L_bdac_var{
712  used_for_size};
713  L_bdac_type& L_bdac_temp =
714  get<::Tags::TempTensor<1, L_bdac_type>>(L_bdac_var);
715  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexD, TensorIndexA,
716  TensorIndexC>(
717  make_not_null(&L_bdac_temp),
718  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
719 
720  // L_{bdca} = R_{abcd}
721  Variables<tmpl::list<::Tags::TempTensor<1, L_bdca_type>>> L_bdca_var{
722  used_for_size};
723  L_bdca_type& L_bdca_temp =
724  get<::Tags::TempTensor<1, L_bdca_type>>(L_bdca_var);
725  ::TensorExpressions::evaluate<TensorIndexB, TensorIndexD, TensorIndexC,
726  TensorIndexA>(
727  make_not_null(&L_bdca_temp),
728  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
729 
730  // L_{cabd} = R_{abcd}
731  Variables<tmpl::list<::Tags::TempTensor<1, L_cabd_type>>> L_cabd_var{
732  used_for_size};
733  L_cabd_type& L_cabd_temp =
734  get<::Tags::TempTensor<1, L_cabd_type>>(L_cabd_var);
735  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexA, TensorIndexB,
736  TensorIndexD>(
737  make_not_null(&L_cabd_temp),
738  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
739 
740  // L_{cadb} = R_{abcd}
741  Variables<tmpl::list<::Tags::TempTensor<1, L_cadb_type>>> L_cadb_var{
742  used_for_size};
743  L_cadb_type& L_cadb_temp =
744  get<::Tags::TempTensor<1, L_cadb_type>>(L_cadb_var);
745  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexA, TensorIndexD,
746  TensorIndexB>(
747  make_not_null(&L_cadb_temp),
748  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
749 
750  // L_{cbad} = R_{abcd}
751  Variables<tmpl::list<::Tags::TempTensor<1, L_cbad_type>>> L_cbad_var{
752  used_for_size};
753  L_cbad_type& L_cbad_temp =
754  get<::Tags::TempTensor<1, L_cbad_type>>(L_cbad_var);
755  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexB, TensorIndexA,
756  TensorIndexD>(
757  make_not_null(&L_cbad_temp),
758  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
759 
760  // L_{cbda} = R_{abcd}
761  Variables<tmpl::list<::Tags::TempTensor<1, L_cbda_type>>> L_cbda_var{
762  used_for_size};
763  L_cbda_type& L_cbda_temp =
764  get<::Tags::TempTensor<1, L_cbda_type>>(L_cbda_var);
765  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexB, TensorIndexD,
766  TensorIndexA>(
767  make_not_null(&L_cbda_temp),
768  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
769 
770  // L_{cdab} = R_{abcd}
771  Variables<tmpl::list<::Tags::TempTensor<1, L_cdab_type>>> L_cdab_var{
772  used_for_size};
773  L_cdab_type& L_cdab_temp =
774  get<::Tags::TempTensor<1, L_cdab_type>>(L_cdab_var);
775  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexD, TensorIndexA,
776  TensorIndexB>(
777  make_not_null(&L_cdab_temp),
778  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
779 
780  // L_{cdba} = R_{abcd}
781  Variables<tmpl::list<::Tags::TempTensor<1, L_cdba_type>>> L_cdba_var{
782  used_for_size};
783  L_cdba_type& L_cdba_temp =
784  get<::Tags::TempTensor<1, L_cdba_type>>(L_cdba_var);
785  ::TensorExpressions::evaluate<TensorIndexC, TensorIndexD, TensorIndexB,
786  TensorIndexA>(
787  make_not_null(&L_cdba_temp),
788  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
789 
790  // L_{dabc} = R_{abcd}
791  Variables<tmpl::list<::Tags::TempTensor<1, L_dabc_type>>> L_dabc_var{
792  used_for_size};
793  L_dabc_type& L_dabc_temp =
794  get<::Tags::TempTensor<1, L_dabc_type>>(L_dabc_var);
795  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexA, TensorIndexB,
796  TensorIndexC>(
797  make_not_null(&L_dabc_temp),
798  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
799 
800  // L_{dacb} = R_{abcd}
801  Variables<tmpl::list<::Tags::TempTensor<1, L_dacb_type>>> L_dacb_var{
802  used_for_size};
803  L_dacb_type& L_dacb_temp =
804  get<::Tags::TempTensor<1, L_dacb_type>>(L_dacb_var);
805  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexA, TensorIndexC,
806  TensorIndexB>(
807  make_not_null(&L_dacb_temp),
808  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
809 
810  // L_{dbac} = R_{abcd}
811  Variables<tmpl::list<::Tags::TempTensor<1, L_dbac_type>>> L_dbac_var{
812  used_for_size};
813  L_dbac_type& L_dbac_temp =
814  get<::Tags::TempTensor<1, L_dbac_type>>(L_dbac_var);
815  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexB, TensorIndexA,
816  TensorIndexC>(
817  make_not_null(&L_dbac_temp),
818  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
819 
820  // L_{dbca} = R_{abcd}
821  Variables<tmpl::list<::Tags::TempTensor<1, L_dbca_type>>> L_dbca_var{
822  used_for_size};
823  L_dbca_type& L_dbca_temp =
824  get<::Tags::TempTensor<1, L_dbca_type>>(L_dbca_var);
825  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexB, TensorIndexC,
826  TensorIndexA>(
827  make_not_null(&L_dbca_temp),
828  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
829 
830  // L_{dcab} = R_{abcd}
831  Variables<tmpl::list<::Tags::TempTensor<1, L_dcab_type>>> L_dcab_var{
832  used_for_size};
833  L_dcab_type& L_dcab_temp =
834  get<::Tags::TempTensor<1, L_dcab_type>>(L_dcab_var);
835  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexC, TensorIndexA,
836  TensorIndexB>(
837  make_not_null(&L_dcab_temp),
838  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
839 
840  // L_{dcba} = R_{abcd}
841  Variables<tmpl::list<::Tags::TempTensor<1, L_dcba_type>>> L_dcba_var{
842  used_for_size};
843  L_dcba_type& L_dcba_temp =
844  get<::Tags::TempTensor<1, L_dcba_type>>(L_dcba_var);
845  ::TensorExpressions::evaluate<TensorIndexD, TensorIndexC, TensorIndexB,
846  TensorIndexA>(
847  make_not_null(&L_dcba_temp),
848  R_abcd(TensorIndexA, TensorIndexB, TensorIndexC, TensorIndexD));
849 
850  for (size_t i = 0; i < dim_a; ++i) {
851  for (size_t j = 0; j < dim_b; ++j) {
852  for (size_t k = 0; k < dim_c; ++k) {
853  for (size_t l = 0; l < dim_d; ++l) {
854  // For L_{abcd} = R_{abcd}, check that L_{ijkl} == R_{ijkl}
855  CHECK(L_abcd_temp.get(i, j, k, l) == R_abcd.get(i, j, k, l));
856  // For L_{abdc} = R_{abcd}, check that L_{ijlk} == R_{ijkl}
857  CHECK(L_abdc_temp.get(i, j, l, k) == R_abcd.get(i, j, k, l));
858  // For L_{acbd} = R_{abcd}, check that L_{ikjl} == R_{ijkl}
859  CHECK(L_acbd_temp.get(i, k, j, l) == R_abcd.get(i, j, k, l));
860  // For L_{acdb} = R_{abcd}, check that L_{iklj} == R_{ijkl}
861  CHECK(L_acdb_temp.get(i, k, l, j) == R_abcd.get(i, j, k, l));
862  // For L_{adbc} = R_{abcd}, check that L_{iljk} == R_{ijkl}
863  CHECK(L_adbc_temp.get(i, l, j, k) == R_abcd.get(i, j, k, l));
864  // For L_{adcb} = R_{abcd}, check that L_{ilkj} == R_{ijkl}
865  CHECK(L_adcb_temp.get(i, l, k, j) == R_abcd.get(i, j, k, l));
866  // For L_{bacd} = R_{abcd}, check that L_{jikl} == R_{ijkl}
867  CHECK(L_bacd_temp.get(j, i, k, l) == R_abcd.get(i, j, k, l));
868  // For L_{badc} = R_{abcd}, check that L_{jilk} == R_{ijkl}
869  CHECK(L_badc_temp.get(j, i, l, k) == R_abcd.get(i, j, k, l));
870  // For L_{bcad} = R_{abcd}, check that L_{jkil} == R_{ijkl}
871  CHECK(L_bcad_temp.get(j, k, i, l) == R_abcd.get(i, j, k, l));
872  // For L_{bcda} = R_{abcd}, check that L_{jkli} == R_{ijkl}
873  CHECK(L_bcda_temp.get(j, k, l, i) == R_abcd.get(i, j, k, l));
874  // For L_{bdac} = R_{abcd}, check that L_{jlik} == R_{ijkl}
875  CHECK(L_bdac_temp.get(j, l, i, k) == R_abcd.get(i, j, k, l));
876  // For L_{bdca} = R_{abcd}, check that L_{jlki} == R_{ijkl}
877  CHECK(L_bdca_temp.get(j, l, k, i) == R_abcd.get(i, j, k, l));
878  // For L_{cabd} = R_{abcd}, check that L_{kijl} == R_{ijkl}
879  CHECK(L_cabd_temp.get(k, i, j, l) == R_abcd.get(i, j, k, l));
880  // For L_{cadb} = R_{abcd}, check that L_{kilj} == R_{ijkl}
881  CHECK(L_cadb_temp.get(k, i, l, j) == R_abcd.get(i, j, k, l));
882  // For L_{cbad} = R_{abcd}, check that L_{kjil} == R_{ijkl}
883  CHECK(L_cbad_temp.get(k, j, i, l) == R_abcd.get(i, j, k, l));
884  // For L_{cbda} = R_{abcd}, check that L_{kjli} == R_{ijkl}
885  CHECK(L_cbda_temp.get(k, j, l, i) == R_abcd.get(i, j, k, l));
886  // For L_{cdab} = R_{abcd}, check that L_{klij} == R_{ijkl}
887  CHECK(L_cdab_temp.get(k, l, i, j) == R_abcd.get(i, j, k, l));
888  // For L_{cdba} = R_{abcd}, check that L_{klji} == R_{ijkl}
889  CHECK(L_cdba_temp.get(k, l, j, i) == R_abcd.get(i, j, k, l));
890  // For L_{dabc} = R_{abcd}, check that L_{lijk} == R_{ijkl}
891  CHECK(L_dabc_temp.get(l, i, j, k) == R_abcd.get(i, j, k, l));
892  // For L_{dacb} = R_{abcd}, check that L_{likj} == R_{ijkl}
893  CHECK(L_dacb_temp.get(l, i, k, j) == R_abcd.get(i, j, k, l));
894  // For L_{dbac} = R_{abcd}, check that L_{ljik} == R_{ijkl}
895  CHECK(L_dbac_temp.get(l, j, i, k) == R_abcd.get(i, j, k, l));
896  // For L_{dbca} = R_{abcd}, check that L_{ljki} == R_{ijkl}
897  CHECK(L_dbca_temp.get(l, j, k, i) == R_abcd.get(i, j, k, l));
898  // For L_{dcab} = R_{abcd}, check that L_{lkij} == R_{ijkl}
899  CHECK(L_dcab_temp.get(l, k, i, j) == R_abcd.get(i, j, k, l));
900  // For L_{dcba} = R_{abcd}, check that L_{lkji} == R_{ijkl}
901  CHECK(L_dcba_temp.get(l, k, j, i) == R_abcd.get(i, j, k, l));
902  }
903  }
904  }
905  }
906  }
907 }
908 
909 } // namespace TestHelpers::TensorExpressions
Symmetry.hpp
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:55
TensorExpressions::evaluate
void evaluate(const gsl::not_null< Tensor< X, LhsSymmetry, LhsIndexList > * > lhs_tensor, const TensorExpression< Derived, X, RhsSymmetry, RhsIndexList, tmpl::list< RhsTensorIndices... >> &rhs_tensorexpression)
Evaluate a RHS tensor expression to a tensor with the LHS index order set in the template parameters.
Definition: Evaluate.hpp:153
cstddef
cstdint
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:80
Variables.hpp
Gsl.hpp
Tensor.hpp
make_not_null
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,...
Definition: Gsl.hpp:880
numeric
type_traits
TMPL.hpp
cpp2b::iota
constexpr void iota(ForwardIterator first, ForwardIterator last, T value)
Definition: Numeric.hpp:20