TensorAsExpressionRank4TestHelpers.hpp
2 // See LICENSE.txt for details.
3
4 #pragma once
5
6 #include <cstddef>
7 #include <iterator>
8 #include <numeric>
9
13
14 namespace TestHelpers::TensorExpressions {
15 /// \ingroup TestingFrameworkGroup
16 /// \brief Test that the transformation between LHS and RHS multi-indices and
17 /// the subsequent computed RHS multi-index of a rank 4 tensor is correctly
18 /// computed by the functions of TensorAsExpression, according to the orders of
19 /// the LHS and RHS generic indices
20 ///
21 /// \details The functions tested are:
22 /// - TensorAsExpression::compute_index_transformation
23 /// - TensorAsExpression::compute_rhs_multi_index
24 ///
25 /// If we consider the RHS tensor's generic indices to be (a, b, c, d), there
26 /// are 24 permutations that are possible orderings of the LHS tensor's generic
27 /// indices, such as: (a, b, c, d), (a, b, d, c), (a, c, b, d), etc. For each of
28 /// these cases, this test checks that for each LHS component's multi-index, the
29 /// equivalent RHS multi-index is correctly computed.
30 ///
31 /// \param tensorindex_a the first TensorIndex used on the RHS of the
32 /// TensorExpression, e.g. ti_a
33 /// \param tensorindex_b the second TensorIndex used on the RHS of the
34 /// TensorExpression, e.g. ti_B
35 /// \param tensorindex_c the third TensorIndex used on the RHS of the
36 /// TensorExpression, e.g. ti_c
37 /// \param tensorindex_d the fourth TensorIndex used on the RHS of the
38 /// TensorExpression, e.g. ti_D
39 template <typename TensorIndexA, typename TensorIndexB, typename TensorIndexC,
40  typename TensorIndexD>
42  const TensorIndexA& tensorindex_a, const TensorIndexB& tensorindex_b,
43  const TensorIndexC& tensorindex_c,
44  const TensorIndexD& tensorindex_d) noexcept {
45  const size_t dim_a = 4;
46  const size_t dim_b = 2;
47  const size_t dim_c = 3;
48  const size_t dim_d = 1;
49
50  const IndexType indextype_a =
51  TensorIndexA::is_spacetime ? IndexType::Spacetime : IndexType::Spatial;
52  const IndexType indextype_b =
53  TensorIndexB::is_spacetime ? IndexType::Spacetime : IndexType::Spatial;
54  const IndexType indextype_c =
55  TensorIndexC::is_spacetime ? IndexType::Spacetime : IndexType::Spatial;
56  const IndexType indextype_d =
57  TensorIndexD::is_spacetime ? IndexType::Spacetime : IndexType::Spatial;
58
59  Tensor<
60  double, Symmetry<4, 3, 2, 1>,
61  index_list<Tensor_detail::TensorIndexType<dim_a, TensorIndexA::valence,
62  Frame::Inertial, indextype_a>,
63  Tensor_detail::TensorIndexType<dim_b, TensorIndexB::valence,
64  Frame::Inertial, indextype_b>,
65  Tensor_detail::TensorIndexType<dim_c, TensorIndexC::valence,
66  Frame::Inertial, indextype_c>,
67  Tensor_detail::TensorIndexType<dim_d, TensorIndexD::valence,
68  Frame::Inertial, indextype_d>>>
69  rhs_tensor{};
70  std::iota(rhs_tensor.begin(), rhs_tensor.end(), 0.0);
71  // Get TensorExpression from RHS tensor
72  const auto R_abcd_expr =
73  rhs_tensor(tensorindex_a, tensorindex_b, tensorindex_c, tensorindex_d);
74
75  const std::array<size_t, 4> index_order_abcd = {
76  TensorIndexA::value, TensorIndexB::value, TensorIndexC::value,
77  TensorIndexD::value};
78  const std::array<size_t, 4> index_order_abdc = {
79  TensorIndexA::value, TensorIndexB::value, TensorIndexD::value,
80  TensorIndexC::value};
81  const std::array<size_t, 4> index_order_acbd = {
82  TensorIndexA::value, TensorIndexC::value, TensorIndexB::value,
83  TensorIndexD::value};
84  const std::array<size_t, 4> index_order_acdb = {
85  TensorIndexA::value, TensorIndexC::value, TensorIndexD::value,
86  TensorIndexB::value};
87  const std::array<size_t, 4> index_order_adbc = {
88  TensorIndexA::value, TensorIndexD::value, TensorIndexB::value,
89  TensorIndexC::value};
90  const std::array<size_t, 4> index_order_adcb = {
91  TensorIndexA::value, TensorIndexD::value, TensorIndexC::value,
92  TensorIndexB::value};
93
94  const std::array<size_t, 4> index_order_bacd = {
95  TensorIndexB::value, TensorIndexA::value, TensorIndexC::value,
96  TensorIndexD::value};
97  const std::array<size_t, 4> index_order_badc = {
98  TensorIndexB::value, TensorIndexA::value, TensorIndexD::value,
99  TensorIndexC::value};
100  const std::array<size_t, 4> index_order_bcad = {
101  TensorIndexB::value, TensorIndexC::value, TensorIndexA::value,
102  TensorIndexD::value};
103  const std::array<size_t, 4> index_order_bcda = {
104  TensorIndexB::value, TensorIndexC::value, TensorIndexD::value,
105  TensorIndexA::value};
106  const std::array<size_t, 4> index_order_bdac = {
107  TensorIndexB::value, TensorIndexD::value, TensorIndexA::value,
108  TensorIndexC::value};
109  const std::array<size_t, 4> index_order_bdca = {
110  TensorIndexB::value, TensorIndexD::value, TensorIndexC::value,
111  TensorIndexA::value};
112
113  const std::array<size_t, 4> index_order_cabd = {
114  TensorIndexC::value, TensorIndexA::value, TensorIndexB::value,
115  TensorIndexD::value};
116  const std::array<size_t, 4> index_order_cadb = {
117  TensorIndexC::value, TensorIndexA::value, TensorIndexD::value,
118  TensorIndexB::value};
119  const std::array<size_t, 4> index_order_cbad = {
120  TensorIndexC::value, TensorIndexB::value, TensorIndexA::value,
121  TensorIndexD::value};
122  const std::array<size_t, 4> index_order_cbda = {
123  TensorIndexC::value, TensorIndexB::value, TensorIndexD::value,
124  TensorIndexA::value};
125  const std::array<size_t, 4> index_order_cdab = {
126  TensorIndexC::value, TensorIndexD::value, TensorIndexA::value,
127  TensorIndexB::value};
128  const std::array<size_t, 4> index_order_cdba = {
129  TensorIndexC::value, TensorIndexD::value, TensorIndexB::value,
130  TensorIndexA::value};
131
132  const std::array<size_t, 4> index_order_dabc = {
133  TensorIndexD::value, TensorIndexA::value, TensorIndexB::value,
134  TensorIndexC::value};
135  const std::array<size_t, 4> index_order_dacb = {
136  TensorIndexD::value, TensorIndexA::value, TensorIndexC::value,
137  TensorIndexB::value};
138  const std::array<size_t, 4> index_order_dbac = {
139  TensorIndexD::value, TensorIndexB::value, TensorIndexA::value,
140  TensorIndexC::value};
141  const std::array<size_t, 4> index_order_dbca = {
142  TensorIndexD::value, TensorIndexB::value, TensorIndexC::value,
143  TensorIndexA::value};
144  const std::array<size_t, 4> index_order_dcab = {
145  TensorIndexD::value, TensorIndexC::value, TensorIndexA::value,
146  TensorIndexB::value};
147  const std::array<size_t, 4> index_order_dcba = {
148  TensorIndexD::value, TensorIndexC::value, TensorIndexB::value,
149  TensorIndexA::value};
150
151  const std::array<size_t, 4> actual_abcd_to_abcd_transformation =
152  R_abcd_expr.compute_index_transformation(index_order_abcd);
153  const std::array<size_t, 4> expected_abcd_to_abcd_transformation = {0, 1, 2,
154  3};
155  const std::array<size_t, 4> actual_abdc_to_abcd_transformation =
156  R_abcd_expr.compute_index_transformation(index_order_abdc);
157  const std::array<size_t, 4> expected_abdc_to_abcd_transformation = {0, 1, 3,
158  2};
159  const std::array<size_t, 4> actual_acbd_to_abcd_transformation =
160  R_abcd_expr.compute_index_transformation(index_order_acbd);
161  const std::array<size_t, 4> expected_acbd_to_abcd_transformation = {0, 2, 1,
162  3};
163  const std::array<size_t, 4> actual_acdb_to_abcd_transformation =
164  R_abcd_expr.compute_index_transformation(index_order_acdb);
165  const std::array<size_t, 4> expected_acdb_to_abcd_transformation = {0, 3, 1,
166  2};
167  const std::array<size_t, 4> actual_adbc_to_abcd_transformation =
169  const std::array<size_t, 4> expected_adbc_to_abcd_transformation = {0, 2, 3,
170  1};
171  const std::array<size_t, 4> actual_adcb_to_abcd_transformation =
173  const std::array<size_t, 4> expected_adcb_to_abcd_transformation = {0, 3, 2,
174  1};
175
176  const std::array<size_t, 4> actual_bacd_to_abcd_transformation =
177  R_abcd_expr.compute_index_transformation(index_order_bacd);
178  const std::array<size_t, 4> expected_bacd_to_abcd_transformation = {1, 0, 2,
179  3};
180  const std::array<size_t, 4> actual_badc_to_abcd_transformation =
182  const std::array<size_t, 4> expected_badc_to_abcd_transformation = {1, 0, 3,
183  2};
184  const std::array<size_t, 4> actual_bcad_to_abcd_transformation =
186  const std::array<size_t, 4> expected_bcad_to_abcd_transformation = {2, 0, 1,
187  3};
188  const std::array<size_t, 4> actual_bcda_to_abcd_transformation =
189  R_abcd_expr.compute_index_transformation(index_order_bcda);
190  const std::array<size_t, 4> expected_bcda_to_abcd_transformation = {3, 0, 1,
191  2};
192  const std::array<size_t, 4> actual_bdac_to_abcd_transformation =
193  R_abcd_expr.compute_index_transformation(index_order_bdac);
194  const std::array<size_t, 4> expected_bdac_to_abcd_transformation = {2, 0, 3,
195  1};
196  const std::array<size_t, 4> actual_bdca_to_abcd_transformation =
197  R_abcd_expr.compute_index_transformation(index_order_bdca);
198  const std::array<size_t, 4> expected_bdca_to_abcd_transformation = {3, 0, 2,
199  1};
200
201  const std::array<size_t, 4> actual_cabd_to_abcd_transformation =
202  R_abcd_expr.compute_index_transformation(index_order_cabd);
203  const std::array<size_t, 4> expected_cabd_to_abcd_transformation = {1, 2, 0,
204  3};
205  const std::array<size_t, 4> actual_cadb_to_abcd_transformation =
207  const std::array<size_t, 4> expected_cadb_to_abcd_transformation = {1, 3, 0,
208  2};
209  const std::array<size_t, 4> actual_cbad_to_abcd_transformation =
211  const std::array<size_t, 4> expected_cbad_to_abcd_transformation = {2, 1, 0,
212  3};
213  const std::array<size_t, 4> actual_cbda_to_abcd_transformation =
214  R_abcd_expr.compute_index_transformation(index_order_cbda);
215  const std::array<size_t, 4> expected_cbda_to_abcd_transformation = {3, 1, 0,
216  2};
217  const std::array<size_t, 4> actual_cdab_to_abcd_transformation =
218  R_abcd_expr.compute_index_transformation(index_order_cdab);
219  const std::array<size_t, 4> expected_cdab_to_abcd_transformation = {2, 3, 0,
220  1};
221  const std::array<size_t, 4> actual_cdba_to_abcd_transformation =
222  R_abcd_expr.compute_index_transformation(index_order_cdba);
223  const std::array<size_t, 4> expected_cdba_to_abcd_transformation = {3, 2, 0,
224  1};
225
226  const std::array<size_t, 4> actual_dabc_to_abcd_transformation =
227  R_abcd_expr.compute_index_transformation(index_order_dabc);
228  const std::array<size_t, 4> expected_dabc_to_abcd_transformation = {1, 2, 3,
229  0};
230  const std::array<size_t, 4> actual_dacb_to_abcd_transformation =
231  R_abcd_expr.compute_index_transformation(index_order_dacb);
232  const std::array<size_t, 4> expected_dacb_to_abcd_transformation = {1, 3, 2,
233  0};
234  const std::array<size_t, 4> actual_dbac_to_abcd_transformation =
235  R_abcd_expr.compute_index_transformation(index_order_dbac);
236  const std::array<size_t, 4> expected_dbac_to_abcd_transformation = {2, 1, 3,
237  0};
238  const std::array<size_t, 4> actual_dbca_to_abcd_transformation =
239  R_abcd_expr.compute_index_transformation(index_order_dbca);
240  const std::array<size_t, 4> expected_dbca_to_abcd_transformation = {3, 1, 2,
241  0};
242  const std::array<size_t, 4> actual_dcab_to_abcd_transformation =
243  R_abcd_expr.compute_index_transformation(index_order_dcab);
244  const std::array<size_t, 4> expected_dcab_to_abcd_transformation = {2, 3, 1,
245  0};
246  const std::array<size_t, 4> actual_dcba_to_abcd_transformation =
247  R_abcd_expr.compute_index_transformation(index_order_dcba);
248  const std::array<size_t, 4> expected_dcba_to_abcd_transformation = {3, 2, 1,
249  0};
250
251  CHECK(actual_abcd_to_abcd_transformation ==
252  expected_abcd_to_abcd_transformation);
253  CHECK(actual_abdc_to_abcd_transformation ==
254  expected_abdc_to_abcd_transformation);
255  CHECK(actual_acbd_to_abcd_transformation ==
256  expected_acbd_to_abcd_transformation);
257  CHECK(actual_acdb_to_abcd_transformation ==
258  expected_acdb_to_abcd_transformation);
263
264  CHECK(actual_bacd_to_abcd_transformation ==
265  expected_bacd_to_abcd_transformation);
270  CHECK(actual_bcda_to_abcd_transformation ==
271  expected_bcda_to_abcd_transformation);
272  CHECK(actual_bdac_to_abcd_transformation ==
273  expected_bdac_to_abcd_transformation);
274  CHECK(actual_bdca_to_abcd_transformation ==
275  expected_bdca_to_abcd_transformation);
276
277  CHECK(actual_cabd_to_abcd_transformation ==
278  expected_cabd_to_abcd_transformation);
283  CHECK(actual_cbda_to_abcd_transformation ==
284  expected_cbda_to_abcd_transformation);
285  CHECK(actual_cdab_to_abcd_transformation ==
286  expected_cdab_to_abcd_transformation);
287  CHECK(actual_cdba_to_abcd_transformation ==
288  expected_cdba_to_abcd_transformation);
289
290  CHECK(actual_dabc_to_abcd_transformation ==
291  expected_dabc_to_abcd_transformation);
292  CHECK(actual_dacb_to_abcd_transformation ==
293  expected_dacb_to_abcd_transformation);
294  CHECK(actual_dbac_to_abcd_transformation ==
295  expected_dbac_to_abcd_transformation);
296  CHECK(actual_dbca_to_abcd_transformation ==
297  expected_dbca_to_abcd_transformation);
298  CHECK(actual_dcab_to_abcd_transformation ==
299  expected_dcab_to_abcd_transformation);
300  CHECK(actual_dcba_to_abcd_transformation ==
301  expected_dcba_to_abcd_transformation);
302
303  for (size_t i = 0; i < dim_a; i++) {
304  for (size_t j = 0; j < dim_b; j++) {
305  for (size_t k = 0; k < dim_c; k++) {
306  for (size_t l = 0; l < dim_d; l++) {
307  const std::array<size_t, 4> ijkl = {i, j, k, l};
308  const std::array<size_t, 4> ijlk = {i, j, l, k};
309  const std::array<size_t, 4> ikjl = {i, k, j, l};
310  const std::array<size_t, 4> iklj = {i, k, l, j};
311  const std::array<size_t, 4> iljk = {i, l, j, k};
312  const std::array<size_t, 4> ilkj = {i, l, k, j};
313
314  const std::array<size_t, 4> jikl = {j, i, k, l};
315  const std::array<size_t, 4> jilk = {j, i, l, k};
316  const std::array<size_t, 4> jkil = {j, k, i, l};
317  const std::array<size_t, 4> jkli = {j, k, l, i};
318  const std::array<size_t, 4> jlik = {j, l, i, k};
319  const std::array<size_t, 4> jlki = {j, l, k, i};
320
321  const std::array<size_t, 4> kijl = {k, i, j, l};
322  const std::array<size_t, 4> kilj = {k, i, l, j};
323  const std::array<size_t, 4> kjil = {k, j, i, l};
324  const std::array<size_t, 4> kjli = {k, j, l, i};
325  const std::array<size_t, 4> klij = {k, l, i, j};
326  const std::array<size_t, 4> klji = {k, l, j, i};
327
328  const std::array<size_t, 4> lijk = {l, i, j, k};
329  const std::array<size_t, 4> likj = {l, i, k, j};
330  const std::array<size_t, 4> ljik = {l, j, i, k};
331  const std::array<size_t, 4> ljki = {l, j, k, i};
332  const std::array<size_t, 4> lkij = {l, k, i, j};
333  const std::array<size_t, 4> lkji = {l, k, j, i};
334
335  // For L_{abcd} = R_{abcd}, check that L_{ijkl} == R_{ijkl}
336  CHECK(R_abcd_expr.compute_rhs_multi_index(
337  ijkl, expected_abcd_to_abcd_transformation) == ijkl);
338  // For L_{abdc} = R_{abcd}, check that L_{ijkl} == R_{ijlk}
339  CHECK(R_abcd_expr.compute_rhs_multi_index(
340  ijkl, expected_abdc_to_abcd_transformation) == ijlk);
341  // For L_{acbd} = R_{abcd}, check that L_{ijkl} == R_{ikjl}
342  CHECK(R_abcd_expr.compute_rhs_multi_index(
343  ijkl, expected_acbd_to_abcd_transformation) == ikjl);
344  // For L_{acdb} = R_{abcd}, check that L_{ijkl} == R_{iljk}
345  CHECK(R_abcd_expr.compute_rhs_multi_index(
346  ijkl, expected_acdb_to_abcd_transformation) == iljk);
347  // For L_{adbc} = R_{abcd}, check that L_{ijkl} == R_{iklj}
348  CHECK(R_abcd_expr.compute_rhs_multi_index(
350  // For L_{adcb} = R_{abcd}, check that L_{ijkl} == R_{ilkj}
351  CHECK(R_abcd_expr.compute_rhs_multi_index(
353
354  // For L_{bacd} = R_{abcd}, check that L_{ijkl} == R_{jikl}
355  CHECK(R_abcd_expr.compute_rhs_multi_index(
356  ijkl, expected_bacd_to_abcd_transformation) == jikl);
357  // For L_{badc} = R_{abcd}, check that L_{ijkl} == R_{jilk}
358  CHECK(R_abcd_expr.compute_rhs_multi_index(
360  // For L_{bcad} = R_{abcd}, check that L_{ijkl} == R_{kijl}
361  CHECK(R_abcd_expr.compute_rhs_multi_index(
363  // For L_{bcda} = R_{abcd}, check that L_{ijkl} == R_{lijk}
364  CHECK(R_abcd_expr.compute_rhs_multi_index(
365  ijkl, expected_bcda_to_abcd_transformation) == lijk);
366  // For L_{bdac} = R_{abcd}, check that L_{ijkl} == R_{kilj}
367  CHECK(R_abcd_expr.compute_rhs_multi_index(
368  ijkl, expected_bdac_to_abcd_transformation) == kilj);
369  // For L_{bdca} = R_{abcd}, check that L_{ijkl} == R_{likj}
370  CHECK(R_abcd_expr.compute_rhs_multi_index(
371  ijkl, expected_bdca_to_abcd_transformation) == likj);
372
373  // For L_{cabd} = R_{abcd}, check that L_{ijkl} == R_{jkil}
374  CHECK(R_abcd_expr.compute_rhs_multi_index(
375  ijkl, expected_cabd_to_abcd_transformation) == jkil);
376  // For L_{cadb} = R_{abcd}, check that L_{ijkl} == R_{jlik}
377  CHECK(R_abcd_expr.compute_rhs_multi_index(
379  // For L_{cbad} = R_{abcd}, check that L_{ijkl} == R_{kjil}
380  CHECK(R_abcd_expr.compute_rhs_multi_index(
382  // For L_{cbda} = R_{abcd}, check that L_{ijkl} == R_{ljik}
383  CHECK(R_abcd_expr.compute_rhs_multi_index(
384  ijkl, expected_cbda_to_abcd_transformation) == ljik);
385  // For L_{cdab} = R_{abcd}, check that L_{ijkl} == R_{klij}
386  CHECK(R_abcd_expr.compute_rhs_multi_index(
387  ijkl, expected_cdab_to_abcd_transformation) == klij);
388  // For L_{cdba} = R_{abcd}, check that L_{ijkl} == R_{lkij}
389  CHECK(R_abcd_expr.compute_rhs_multi_index(
390  ijkl, expected_cdba_to_abcd_transformation) == lkij);
391
392  // For L_{dabc} = R_{abcd}, check that L_{ijkl} == R_{jkli}
393  CHECK(R_abcd_expr.compute_rhs_multi_index(
394  ijkl, expected_dabc_to_abcd_transformation) == jkli);
395  // For L_{dacb} = R_{abcd}, check that L_{ijkl} == R_{jlki}
396  CHECK(R_abcd_expr.compute_rhs_multi_index(
397  ijkl, expected_dacb_to_abcd_transformation) == jlki);
398  // For L_{dbac} = R_{abcd}, check that L_{ijkl} == R_{kjli}
399  CHECK(R_abcd_expr.compute_rhs_multi_index(
400  ijkl, expected_dbac_to_abcd_transformation) == kjli);
401  // For L_{dbca} = R_{abcd}, check that L_{ijkl} == R_{ljki}
402  CHECK(R_abcd_expr.compute_rhs_multi_index(
403  ijkl, expected_dbca_to_abcd_transformation) == ljki);
404  // For L_{dcab} = R_{abcd}, check that L_{ijkl} == R_{klji}
405  CHECK(R_abcd_expr.compute_rhs_multi_index(
406  ijkl, expected_dcab_to_abcd_transformation) == klji);
407  // For L_{dcba} = R_{abcd}, check that L_{ijkl} == R_{lkji}
408  CHECK(R_abcd_expr.compute_rhs_multi_index(
409  ijkl, expected_dcba_to_abcd_transformation) == lkji);
410  }
411  }
412  }
413  }
414 }
415 } // namespace TestHelpers::TensorExpressions
Frame::Inertial
Definition: IndexType.hpp:44
TensorExpression.hpp
IndexType.hpp
iterator
TestHelpers::TensorExpressions::test_tensor_as_expression_rank_4
void test_tensor_as_expression_rank_4(const TensorIndexA &tensorindex_a, const TensorIndexB &tensorindex_b, const TensorIndexC &tensorindex_c, const TensorIndexD &tensorindex_d) noexcept
Test that the transformation between LHS and RHS multi-indices and the subsequent computed RHS multi-...
Definition: TensorAsExpressionRank4TestHelpers.hpp:41
IndexType::Spatial
@ Spatial
The TensorIndexType is purely spatial.
IndexType::Spacetime
@ Spacetime
The TensorIndexType is a spacetime index.
cstddef
std::array
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
IndexType
IndexType
Definition: IndexType.hpp:134
Tensor.hpp
numeric
cpp2b::iota
constexpr void iota(ForwardIterator first, ForwardIterator last, T value)
Definition: Numeric.hpp:20