Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <utility>
9 :
10 : #include "DataStructures/Tensor/Expressions/SpatialSpacetimeIndex.hpp"
11 : #include "DataStructures/Tensor/Expressions/TensorIndexTransformation.hpp"
12 : #include "DataStructures/Tensor/Expressions/TimeIndex.hpp"
13 : #include "DataStructures/Tensor/Structure.hpp"
14 : #include "DataStructures/Tensor/Symmetry.hpp"
15 : #include "Utilities/Algorithm.hpp"
16 : #include "Utilities/TMPL.hpp"
17 :
18 : namespace tenex {
19 : /*!
20 : * \ingroup TensorExpressionsGroup
21 : * \brief Determines and stores a LHS tensor's symmetry and index list from a
22 : * RHS tensor expression and desired LHS index order
23 : *
24 : * \details Given the generic index order of a RHS TensorExpression and the
25 : * generic index order of the desired LHS Tensor, this creates a mapping between
26 : * the two that is then used to determine the (potentially reordered) ordering
27 : * of the elements of the desired LHS Tensor's ::Symmetry, typelist of
28 : * \ref SpacetimeIndex "TensorIndexType"s, and Tensor_detail::Structure. This
29 : * struct is used to determine the LHS Tensor's properties when they are not
30 : * supplied by the user: when a user uses the `evaluate` overload that returns
31 : * the LHS as opposed to the overload that takes an empty LHS Tensor as an
32 : * argument.
33 : *
34 : * Note: If a generic spatial index is used for a spacetime index in the RHS
35 : * tensor, its corresponding index in the LHS tensor type will be a spatial
36 : * index with the same valence, frame, and number of spatial dimensions. If a
37 : * concrete time index is used for a spacetime index in the RHS tensor, the
38 : * index will not appear in the LHS tensor (i.e. there will NOT be a
39 : * corresponding LHS index where only the time index of that index has been
40 : * computed and its spatial indices are empty). Therefore, the
41 : * `LhsTensorIndexList` may not contain time indices (`ti::t` nor `ti::T`).
42 : *
43 : * @tparam RhsTensorIndexList the typelist of TensorIndex of the RHS
44 : * TensorExpression
45 : * @tparam LhsTensorIndexList the typelist of TensorIndexs of the desired LHS
46 : * tensor
47 : * @tparam RhsSymmetry the ::Symmetry of the RHS indices
48 : * @tparam RhsTensorIndexTypeList the RHS TensorExpression's typelist of
49 : * \ref SpacetimeIndex "TensorIndexType"s
50 : */
51 : template <typename RhsTensorIndexList, typename LhsTensorIndexList,
52 : typename RhsSymmetry, typename RhsTensorIndexTypeList,
53 : size_t NumLhsIndices = tmpl::size<LhsTensorIndexList>::value,
54 : size_t NumRhsIndices = tmpl::size<RhsTensorIndexList>::value,
55 : typename LhsIndexSequence = std::make_index_sequence<NumLhsIndices>>
56 1 : struct LhsTensorSymmAndIndices;
57 :
58 : template <typename... RhsTensorIndices, typename... LhsTensorIndices,
59 : std::int32_t... RhsSymm, typename RhsTensorIndexTypeList,
60 : size_t NumLhsIndices, size_t NumRhsIndices, size_t... LhsInts>
61 : struct LhsTensorSymmAndIndices<
62 : tmpl::list<RhsTensorIndices...>, tmpl::list<LhsTensorIndices...>,
63 : tmpl::integral_list<std::int32_t, RhsSymm...>, RhsTensorIndexTypeList,
64 : NumLhsIndices, NumRhsIndices, std::index_sequence<LhsInts...>> {
65 : static_assert((... and (not tt::is_time_index<LhsTensorIndices>::value)),
66 : "LHS generic indices cannot contain the concrete time index.");
67 : // LHS generic indices, RHS generic indices, and the mapping between them
68 : static constexpr std::array<size_t, NumLhsIndices> lhs_tensorindex_values = {
69 : {LhsTensorIndices::value...}};
70 : static constexpr std::array<size_t, NumRhsIndices> rhs_tensorindex_values = {
71 : {RhsTensorIndices::value...}};
72 : static constexpr std::array<size_t, NumLhsIndices> rhs_to_lhs_map =
73 : compute_tensorindex_transformation(rhs_tensorindex_values,
74 : lhs_tensorindex_values);
75 :
76 : // Compute symmetry of RHS after spacetime indices using generic spatial
77 : // indices are swapped for spatial indices
78 : static constexpr std::array<std::int32_t, NumRhsIndices> rhs_symmetry = {
79 : {RhsSymm...}};
80 : using rhs_spatial_spacetime_index_positions_ =
81 : detail::spatial_spacetime_index_positions<
82 : RhsTensorIndexTypeList, tmpl::list<RhsTensorIndices...>>;
83 : using make_list_type = std::conditional_t<
84 : tmpl::size<rhs_spatial_spacetime_index_positions_>::value == 0, size_t,
85 : rhs_spatial_spacetime_index_positions_>;
86 : static constexpr auto rhs_spatial_spacetime_index_positions =
87 : make_array_from_list<make_list_type>();
88 : static constexpr std::array<std::int32_t, NumRhsIndices>
89 : rhs_spatial_spacetime_index_symmetry =
90 : detail::get_spatial_spacetime_index_symmetry(
91 : rhs_symmetry, rhs_spatial_spacetime_index_positions);
92 :
93 : // Compute index list of RHS after spacetime indices using generic spatial
94 : // indices are made nonsymmetric to other indices
95 : using rhs_spatial_spacetime_tensorindextype_list =
96 : detail::replace_spatial_spacetime_indices<
97 : RhsTensorIndexTypeList, rhs_spatial_spacetime_index_positions_>;
98 :
99 : // Desired LHS Tensor's Symmetry, typelist of TensorIndexTypes, and Structure
100 : using symmetry = Symmetry<
101 : rhs_spatial_spacetime_index_symmetry[rhs_to_lhs_map[LhsInts]]...>;
102 : using tensorindextype_list =
103 : tmpl::list<tmpl::at_c<rhs_spatial_spacetime_tensorindextype_list,
104 : rhs_to_lhs_map[LhsInts]>...>;
105 : using structure =
106 : Tensor_detail::Structure<symmetry,
107 : tmpl::at_c<tensorindextype_list, LhsInts>...>;
108 : };
109 : } // namespace tenex
|