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