SpECTRE Documentation Coverage Report
Current view: top level - DataStructures/Tensor/Expressions - SpatialSpacetimeIndex.hpp Hit Total Coverage
Commit: d0fc80462417e83e5cddfa1b9901bb4a9b6af4d6 Lines: 1 1 100.0 %
Date: 2024-03-29 00:33:31
Legend: Lines: hit not hit

          Line data    Source code
       1           1 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : #pragma once
       5             : 
       6             : #include <array>
       7             : #include <cstddef>
       8             : 
       9             : #include "DataStructures/Tensor/Expressions/TensorIndex.hpp"
      10             : #include "DataStructures/Tensor/IndexType.hpp"
      11             : #include "DataStructures/Tensor/Symmetry.hpp"
      12             : #include "Utilities/Algorithm.hpp"
      13             : #include "Utilities/ConstantExpressions.hpp"
      14             : #include "Utilities/Gsl.hpp"
      15             : #include "Utilities/MakeArray.hpp"
      16             : #include "Utilities/Requires.hpp"
      17             : #include "Utilities/TMPL.hpp"
      18             : 
      19             : /// \file
      20             : /// Defines functions and metafunctions used for helping evaluate
      21             : /// TensorExpression equations where generic spatial indices are used for
      22             : /// spacetime indices
      23             : 
      24             : namespace tenex {
      25             : namespace detail {
      26             : template <typename State, typename Element, typename Iteration,
      27             :           typename TensorIndexList>
      28             : struct spatial_spacetime_index_positions_impl {
      29             :   using type = typename std::conditional_t<
      30             :       Element::index_type == IndexType::Spacetime and
      31             :           not tmpl::at<TensorIndexList, Iteration>::is_spacetime,
      32             :       tmpl::push_back<State, tmpl::integral_constant<size_t, Iteration::value>>,
      33             :       State>;
      34             : };
      35             : 
      36             : /// \brief Given a generic index list and tensor index list, returns the list of
      37             : /// positions where the generic index is spatial and the tensor index is
      38             : /// spacetime
      39             : ///
      40             : /// \tparam TensorIndexList the generic index list
      41             : /// \tparam TensorIndexTypeList the list of
      42             : /// \ref SpacetimeIndex "TensorIndexType"s
      43             : template <typename TensorIndexTypeList, typename TensorIndexList>
      44             : using spatial_spacetime_index_positions = tmpl::enumerated_fold<
      45             :     TensorIndexTypeList, tmpl::list<>,
      46             :     spatial_spacetime_index_positions_impl<
      47             :         tmpl::_state, tmpl::_element, tmpl::_3, tmpl::pin<TensorIndexList>>,
      48             :     tmpl::size_t<0>>;
      49             : 
      50             : /// \brief Given a generic index list and tensor index list, returns the list of
      51             : /// positions where the generic index is spatial and the tensor index is
      52             : /// spacetime
      53             : ///
      54             : /// \tparam TensorIndexList the generic index list
      55             : /// \tparam TensorIndexTypeList the list of
      56             : /// \ref SpacetimeIndex "TensorIndexType"s
      57             : /// \return the list of positions where the generic index is spatial and the
      58             : /// tensor index is spacetime
      59             : template <typename TensorIndexTypeList, typename TensorIndexList>
      60             : constexpr auto get_spatial_spacetime_index_positions() {
      61             :   using spatial_spacetime_index_positions_ =
      62             :       spatial_spacetime_index_positions<TensorIndexTypeList, TensorIndexList>;
      63             :   using make_list_type = std::conditional_t<
      64             :       tmpl::size<spatial_spacetime_index_positions_>::value == 0, size_t,
      65             :       spatial_spacetime_index_positions_>;
      66             :   return make_array_from_list<make_list_type>();
      67             : }
      68             : 
      69             : /// @{
      70             : /// \brief Given a tensor symmetry and the positions of indices where a generic
      71             : /// spatial index is used for a spacetime index, this returns the symmetry
      72             : /// after making those indices nonsymmetric with others
      73             : ///
      74             : /// \details
      75             : /// Example: If `symmetry` is `[2, 1, 1, 1]` and
      76             : /// `spatial_spacetime_index_positions` is `[1]`, then position 1 is the only
      77             : /// position where a generic spatial index is used for a spacetime index. The
      78             : /// resulting symmetry will make the index at position 1 no longer be symmetric
      79             : /// with the indices at positions 2 and 3. Therefore, the resulting symmetry
      80             : /// will be equivalent to the form of `[3, 2, 1, 1]`.
      81             : ///
      82             : /// Note: the symmetry returned by this function is not necessarily in the
      83             : /// canonical form specified by ::Symmetry. In reality, for the example above,
      84             : /// this function would return `[2, 3, 1, 1]`.
      85             : ///
      86             : /// \param symmetry the input tensor symmetry to transform
      87             : /// \param spatial_spacetime_index_positions the positions of the indices of the
      88             : /// tensor where a generic spatial index is used for a spacetime index
      89             : /// \return the symmetry after making the `spatial_spacetime_index_positions` of
      90             : /// `symmetry` nonsymmetric with other indices
      91             : template <
      92             :     size_t NumIndices, size_t NumSpatialSpacetimeIndices,
      93             :     Requires<(NumIndices >= 2 and NumSpatialSpacetimeIndices != 0)> = nullptr>
      94             : constexpr std::array<std::int32_t, NumIndices>
      95             : get_spatial_spacetime_index_symmetry(
      96             :     const std::array<std::int32_t, NumIndices>& symmetry,
      97             :     const std::array<size_t, NumSpatialSpacetimeIndices>&
      98             :         spatial_spacetime_index_positions) {
      99             :   std::array<std::int32_t, NumIndices> spatial_spacetime_index_symmetry{};
     100             :   const std::int32_t max_symm_value =
     101             :       static_cast<std::int32_t>(*alg::max_element(symmetry));
     102             :   for (size_t i = 0; i < NumIndices; i++) {
     103             :     gsl::at(spatial_spacetime_index_symmetry, i) = gsl::at(symmetry, i);
     104             :   }
     105             :   for (size_t i = 0; i < NumSpatialSpacetimeIndices; i++) {
     106             :     gsl::at(spatial_spacetime_index_symmetry,
     107             :             gsl::at(spatial_spacetime_index_positions, i)) += max_symm_value;
     108             :   }
     109             : 
     110             :   return spatial_spacetime_index_symmetry;
     111             : }
     112             : 
     113             : template <
     114             :     size_t NumIndices, size_t NumSpatialSpacetimeIndices,
     115             :     Requires<(NumIndices < 2 or NumSpatialSpacetimeIndices == 0)> = nullptr>
     116             : constexpr std::array<std::int32_t, NumIndices>
     117             : get_spatial_spacetime_index_symmetry(
     118             :     const std::array<std::int32_t, NumIndices>& symmetry,
     119             :     const std::array<size_t, NumSpatialSpacetimeIndices>&
     120             :     /*spatial_spacetime_index_positions*/) {
     121             :   return symmetry;
     122             : }
     123             : /// @}
     124             : 
     125             : template <typename S, typename E>
     126             : struct replace_spatial_spacetime_indices_helper {
     127             :   using type = tmpl::replace_at<S, E, change_index_type<tmpl::at<S, E>>>;
     128             : };
     129             : 
     130             : // The list of indices resulting from taking `TensorIndexTypeList` and
     131             : // replacing the spacetime indices at positions `SpatialSpacetimeIndexPositions`
     132             : // with spatial indices
     133             : template <typename TensorIndexTypeList, typename SpatialSpacetimeIndexPositions>
     134             : using replace_spatial_spacetime_indices = tmpl::fold<
     135             :     SpatialSpacetimeIndexPositions, TensorIndexTypeList,
     136             :     replace_spatial_spacetime_indices_helper<tmpl::_state, tmpl::_element>>;
     137             : 
     138             : /// \brief Given a number of tensor indices of two tensors and the positions of
     139             : /// each tensor's spacetime indices for which a generic spatial index was used,
     140             : /// compute the shift in the multi-index values from the first tensor's
     141             : /// multi-indices to the second's
     142             : ///
     143             : /// \details
     144             : /// Example: If we have \f$R_{ijk} + S_{ijk}\f$, where  \f$R\f$'s first and
     145             : /// 2nd indices are spacetime and \f$S\f$' first index and third index are
     146             : /// spacetime, let \f$i = 0\f$, \f$j = 1\f$, and \f$k = 2\f$. The multi-index
     147             : /// that represents  \f$R_{012}\f$ is `{0 + 1, 1 + 1, 2} = {1, 2, 2}` and the
     148             : /// multi-index that represents \f$S_{012}\f$ is
     149             : /// `{0 + 1, 1, 2 + 1} = {1, 1, 3}`. The function returns the element-wise
     150             : /// shift that is applied to convert the first multi-index to the other, which,
     151             : /// in this case, would be: `{1, 1, 3} - {1, 2, 2} = {0, -1, 1}`.
     152             : ///
     153             : /// \tparam NumIndices number of indices of the two operands
     154             : /// \param positions1 first operand's index positions where a generic spatial
     155             : /// index is used for a spacetime index
     156             : /// \param positions2 second operand's index positions where a generic spatial
     157             : /// index is used for a spacetime index
     158             : /// \return the element-wise multi-index shift from the first operand's
     159             : /// multi-indices to the second's
     160             : template <size_t NumIndices, size_t NumPositions1, size_t NumPositions2>
     161             : constexpr std::array<std::int32_t, NumIndices>
     162             : spatial_spacetime_index_transformation_from_positions(
     163             :     const std::array<size_t, NumPositions1>& positions1,
     164             :     const std::array<size_t, NumPositions2>& positions2) {
     165             :   std::array<std::int32_t, NumIndices> transformation =
     166             :       make_array<NumIndices, std::int32_t>(0);
     167             :   for (size_t i = 0; i < NumPositions1; i++) {
     168             :     gsl::at(transformation, gsl::at(positions1, i))--;
     169             :   }
     170             :   for (size_t i = 0; i < NumPositions2; i++) {
     171             :     gsl::at(transformation, gsl::at(positions2, i))++;
     172             :   }
     173             :   return transformation;
     174             : }
     175             : }  // namespace detail
     176             : }  // namespace tenex

Generated by: LCOV version 1.14