Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <type_traits> 8 : 9 : #include "DataStructures/Tensor/IndexType.hpp" 10 : #include "DataStructures/Tensor/Metafunctions.hpp" 11 : #include "DataStructures/Tensor/Tensor.hpp" 12 : #include "DataStructures/VectorImpl.hpp" 13 : #include "Utilities/Array.hpp" 14 : #include "Utilities/Gsl.hpp" 15 : #include "Utilities/StdArrayHelpers.hpp" 16 : #include "Utilities/TMPL.hpp" 17 : 18 : /// \ingroup TensorGroup 19 : /// \brief Combines a time component of a tensor with spatial components to 20 : /// produce a spacetime tensor. 21 : /// 22 : /// \details Combines a time component of a tensor with spatial components to 23 : /// produce a spacetime tensor. Specifically, the components of the result 24 : /// are views to the inputs. Can do so for a tensor of any rank, but 25 : /// requires that the new index is the first index of the resulting tensor, 26 : /// replacing the position of the spatial index in the input spatial tensor. 27 : /// For instance, it may combine \f$ \phi \f$ with \f$ A^i \f$ into 28 : /// \f$ A^a = \left(\phi, A^i\right) \f$, or it may combine \f$ A^a{}_b{}_c \f$ 29 : /// with \f$ B_i{}^a{}_b{}_c \f$ into 30 : /// \f$ C_a{}^b{}_c{}_d = \left(A^b{}_c{}_d, B_i{}^b{}_c{}_d\right)\f$, 31 : /// but it may not combine \f$ A^i{}_a \f$ with \f$ B^i{}_j{}_a \f$ to produce 32 : /// a tensor of the form \f$ C^i{}_a{}_b \f$. 33 : /// 34 : /// \tparam SpatialDim the number of spatial dimensions in the input and output 35 : /// tensors 36 : /// \tparam Ul whether the new index is covariant or contravariant (must match 37 : /// that of the spatial index of the input spatial tensor) 38 : /// \tparam Frame the frame of the new spacetime index (must match that of the 39 : /// spatial index of the input spatial tensor) 40 : template <size_t SpatialDim, UpLo Ul, typename Frame, typename DataType, 41 : typename SymmList, typename IndexList> 42 1 : void combine_spacetime_view( 43 : gsl::not_null<TensorMetafunctions::prepend_spacetime_index< 44 : Tensor<DataType, SymmList, IndexList>, SpatialDim, Ul, Frame>*> 45 : spacetime_tensor, 46 : const Tensor<DataType, SymmList, IndexList>& time_tensor, 47 : const TensorMetafunctions::prepend_spatial_index< 48 : Tensor<DataType, SymmList, IndexList>, SpatialDim, Ul, Frame>& 49 : spatial_tensor) { 50 : for (size_t storage_index = 0; 51 : storage_index < Tensor<DataVector, SymmList, IndexList>::size(); 52 : ++storage_index) { 53 : const auto u_multi_index = 54 : Tensor<DataVector, SymmList, 55 : IndexList>::structure::get_canonical_tensor_index(storage_index); 56 : if constexpr (std::is_same_v<DataType, DataVector>) { 57 : const auto dtu_multi_index = prepend(u_multi_index, 0_st); 58 : make_const_view( 59 : make_not_null(&std::as_const(spacetime_tensor->get(dtu_multi_index))), 60 : time_tensor.get(u_multi_index), 0, 61 : time_tensor.get(u_multi_index).size()); 62 : for (size_t i = 0; i < SpatialDim; i++) { 63 : const auto du_multi_index = prepend(u_multi_index, i + 1); 64 : const auto diu_multi_index = prepend(u_multi_index, i); 65 : make_const_view(make_not_null(&std::as_const( 66 : spacetime_tensor->get(du_multi_index))), 67 : spatial_tensor.get(diu_multi_index), 0, 68 : spatial_tensor.get(diu_multi_index).size()); 69 : } 70 : } else { 71 : const auto dtu_multi_index = prepend(u_multi_index, 0_st); 72 : spacetime_tensor->get(dtu_multi_index) = time_tensor.get(u_multi_index); 73 : for (size_t i = 0; i < SpatialDim; ++i) { 74 : const auto du_multi_index = prepend(u_multi_index, i + 1); 75 : const auto diu_multi_index = prepend(u_multi_index, i); 76 : spacetime_tensor->get(du_multi_index) = 77 : spatial_tensor.get(diu_multi_index); 78 : } 79 : } 80 : } 81 : }