SpECTRE Documentation Coverage Report
Current view: top level - DataStructures/Tensor - IndexType.hpp Hit Total Coverage
Commit: 13732b46b6725478a0972e5abbf2d5c85faeaf3b Lines: 16 23 69.6 %
Date: 2024-05-01 20:05:12
Legend: Lines: hit not hit

          Line data    Source code
       1           1 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : /// \file
       5             : /// Defines classes representing tensor indices
       6             : 
       7             : #pragma once
       8             : 
       9             : #include <cstddef>
      10             : #include <ostream>
      11             : #include <string>
      12             : #include <type_traits>
      13             : 
      14             : #include "Utilities/Literals.hpp"  // IWYU pragma: keep
      15             : #include "Utilities/TMPL.hpp"
      16             : 
      17             : /// \ingroup TensorGroup
      18             : /// Whether a \ref SpacetimeIndex "TensorIndexType" is covariant or
      19             : /// contravariant
      20           1 : enum class UpLo {
      21             :   /// Contravariant, or Upper index
      22             :   Up,
      23             :   /// Covariant, or Lower index
      24             :   Lo
      25             : };
      26             : 
      27             : /// \cond HIDDEN_SYMBOLS
      28             : inline std::ostream& operator<<(std::ostream& os, const UpLo& ul) {
      29             :   return os << (ul == UpLo::Up ? "Up"s : "Lo"s);
      30             : }
      31             : /// \endcond
      32             : 
      33             : /// \ingroup TensorGroup
      34             : /// Indicates the ::Frame that a \ref SpacetimeIndex "TensorIndexType"
      35             : /// is in.
      36           1 : namespace Frame {
      37             : /// \ingroup TensorGroup
      38             : /// Marks a Frame as being "physical" in the sense that it is meaningful to
      39             : /// evaluate an analytic solution in that frame.
      40           1 : struct FrameIsPhysical {};
      41             : 
      42           0 : struct BlockLogical {};
      43           0 : struct ElementLogical {};
      44           0 : struct Fluid {};
      45           0 : struct Grid {};
      46           0 : struct Inertial : FrameIsPhysical {};
      47           0 : struct Distorted {};
      48             : /// Represents an index that is not in a known frame, e.g. some internal
      49             : /// intermediate frame that is irrelevant to the interface.
      50           1 : struct NoFrame {};
      51             : 
      52             : /// Represents a spherical-coordinate frame that is associated with a
      53             : /// Cartesian frame, e.g. \f$(r,\theta,\phi)\f$ associated with the Inertial
      54             : /// frame, as used on an apparent horizon or a wave-extraction surface.
      55             : template <typename CartesianFrame>
      56           1 : struct Spherical {};
      57             : 
      58             : /// \ingroup TensorGroup
      59             : /// Returns std::true_type if the frame is "physical" in the sense that it is
      60             : /// meaningful to evaluate an analytic solution in that frame.
      61             : /// \example
      62             : /// \snippet Test_Tensor.cpp is_frame_physical
      63             : template <typename CheckFrame>
      64           1 : using is_frame_physical =
      65             :     std::integral_constant<bool,
      66             :                            std::is_base_of<FrameIsPhysical, CheckFrame>::value>;
      67             : 
      68             : /// \ingroup TensorGroup
      69             : /// Returns true if the frame is "physical" in the sense that it is
      70             : /// meaningful to evaluate an analytic solution in that frame.
      71             : /// \example
      72             : /// \snippet Test_Tensor.cpp is_frame_physical
      73             : template <typename CheckFrame>
      74           1 : constexpr bool is_frame_physical_v = is_frame_physical<CheckFrame>::value;
      75             : 
      76             : /// \cond HIDDEN_SYMBOLS
      77             : inline std::ostream& operator<<(std::ostream& os,
      78             :                                 const Frame::BlockLogical& /*meta*/) {
      79             :   return os << "BlockLogical";
      80             : }
      81             : inline std::ostream& operator<<(std::ostream& os,
      82             :                                 const Frame::ElementLogical& /*meta*/) {
      83             :   return os << "ElementLogical";
      84             : }
      85             : inline std::ostream& operator<<(std::ostream& os,
      86             :                                 const Frame::Fluid& /*meta*/) {
      87             :   return os << "Fluid";
      88             : }
      89             : inline std::ostream& operator<<(std::ostream& os,
      90             :                                 const Frame::Grid& /*meta*/) {
      91             :   return os << "Grid";
      92             : }
      93             : inline std::ostream& operator<<(std::ostream& os,
      94             :                                 const Frame::Inertial& /*meta*/) {
      95             :   return os << "Inertial";
      96             : }
      97             : inline std::ostream& operator<<(std::ostream& os,
      98             :                                 const Frame::Distorted& /*meta*/) {
      99             :   return os << "Distorted";
     100             : }
     101             : inline std::ostream& operator<<(std::ostream& os,
     102             :                                 const Frame::NoFrame& /*meta*/) {
     103             :   return os << "NoFrame";
     104             : }
     105             : /// \endcond
     106             : 
     107             : /// \ingroup TensorGroup
     108             : /// The frame-dependent prefix used when constructing the string returned by the
     109             : /// name function of a tag.
     110             : ///
     111             : /// For Frame::Inertial it is the empty string, otherwise, it is the name of
     112             : /// the Frame followed by an underscore (as the name will be used in I/O).
     113             : /// \example
     114             : /// \snippet Hydro/Test_Tags.cpp prefix_example
     115             : template <typename Fr>
     116           1 : inline std::string prefix();
     117             : 
     118             : /// \cond HIDDEN_SYMBOLS
     119             : template <>
     120             : inline std::string prefix<Frame::BlockLogical>() {
     121             :   return "BlockLogical_";
     122             : }
     123             : 
     124             : template <>
     125             : inline std::string prefix<Frame::ElementLogical>() {
     126             :   return "ElementLogical_";
     127             : }
     128             : 
     129             : template <>
     130             : inline std::string prefix<Frame::Fluid>() {
     131             :   return "Fluid_";
     132             : }
     133             : 
     134             : template <>
     135             : inline std::string prefix<Frame::Grid>() {
     136             :   return "Grid_";
     137             : }
     138             : 
     139             : template <>
     140             : inline std::string prefix<Frame::Inertial>() {
     141             :   return "";
     142             : }
     143             : 
     144             : template <>
     145             : inline std::string prefix<Frame::Distorted>() {
     146             :   return "Distorted_";
     147             : }
     148             : /// \endcond
     149             : }  // namespace Frame
     150             : 
     151             : /// \ingroup TensorGroup
     152             : /// Indicates whether the \ref SpacetimeIndex "TensorIndexType" is
     153             : /// Spatial or Spacetime
     154           1 : enum class IndexType : char {
     155             :   /// The \ref SpatialIndex "TensorIndexType" is purely spatial
     156             :   Spatial,
     157             :   /// The \ref SpacetimeIndex "TensorIndexType" is a spacetime index
     158             :   Spacetime
     159             : };
     160             : 
     161             : /// \cond HIDDEN_SYMBOLS
     162             : inline std::ostream& operator<<(std::ostream& os, const IndexType& index_type) {
     163             :   return os << (index_type == IndexType::Spatial ? "Spatial" : "Spacetime");
     164             : }
     165             : /// \endcond
     166             : 
     167             : namespace Tensor_detail {
     168             : /// \ingroup TensorGroup
     169             : /// A ::TensorIndexType holds information about what type of index an index of a
     170             : /// Tensor is. It holds the information about the number of spatial dimensions,
     171             : /// whether the index is covariant or contravariant (::UpLo), the ::Frame the
     172             : /// index is in, and whether the Index is Spatial or Spacetime.
     173             : /// \tparam SpatialDim the spatial dimensionality of the TensorIndex
     174             : /// \tparam Ul either UpLo::Up or UpLo::Lo for contra or covariant
     175             : /// \tparam Fr the Frame the TensorIndex is in
     176             : /// \tparam Index either IndexType::Spatial or IndexType::Spacetime
     177             : template <size_t SpatialDim, UpLo Ul, typename Fr, IndexType Index>
     178             : struct TensorIndexType {
     179             :   static_assert(SpatialDim > 0,
     180             :                 "Cannot have a spatial dimensionality less than 1 (one) in a "
     181             :                 "TensorIndexType");
     182             :   using value_type = decltype(SpatialDim);
     183             :   static constexpr value_type dim =
     184             :       Index == IndexType::Spatial ? SpatialDim
     185             :                                   : SpatialDim + static_cast<value_type>(1);
     186             :   // value is here just so that some generic metafunctions can retrieve the dim
     187             :   // easily
     188             :   static constexpr value_type value = dim;
     189             :   static constexpr UpLo ul = Ul;
     190             :   using Frame = Fr;
     191             :   static constexpr IndexType index_type = Index;
     192             : };
     193             : }  // namespace Tensor_detail
     194             : 
     195             : /// \ingroup TensorGroup
     196             : /// A SpatialIndex holds information about the number of spatial
     197             : /// dimensions, whether the index is covariant or contravariant (::UpLo), and
     198             : /// the ::Frame the index is in.
     199             : /// \tparam SpatialDim the spatial dimensionality of the \ref
     200             : /// SpatialIndex "TensorIndexType"
     201             : /// \tparam Ul either UpLo::Up or UpLo::Lo for contra or covariant
     202             : /// \tparam Fr the ::Frame the \ref SpatialIndex "TensorIndexType"
     203             : /// is in
     204             : template <size_t SpatialDim, UpLo Ul, typename Fr>
     205           1 : using SpatialIndex =
     206             :     Tensor_detail::TensorIndexType<SpatialDim, Ul, Fr, IndexType::Spatial>;
     207             : 
     208             : /// \ingroup TensorGroup
     209             : /// A SpacetimeIndex holds information about the number of spatial
     210             : /// dimensions, whether the index is covariant or contravariant (::UpLo), and
     211             : /// the ::Frame the index is in.
     212             : ///
     213             : /// \tparam SpatialDim the spatial dimensionality of the \ref
     214             : /// SpacetimeIndex "TensorIndexType"
     215             : /// \tparam Ul either UpLo::Up or UpLo::Lo for contra or covariant
     216             : /// \tparam Fr the ::Frame the \ref SpacetimeIndex "TensorIndexType"
     217             : /// is in
     218             : template <size_t SpatialDim, UpLo Ul, typename Fr>
     219           1 : using SpacetimeIndex =
     220             :     Tensor_detail::TensorIndexType<SpatialDim, Ul, Fr, IndexType::Spacetime>;
     221             : 
     222             : namespace tt {
     223             : /// @{
     224             : /// \ingroup TensorGroup TypeTraitsGroup
     225             : /// Inherits from std::true_type if T is a \ref SpacetimeIndex
     226             : /// "TensorIndexType"
     227             : /// \tparam T the type to check
     228             : template <typename T>
     229           1 : struct is_tensor_index_type : std::false_type {};
     230             : /// \cond HIDDEN_SYMBOLS
     231             : template <size_t SpatialDim, UpLo Ul, typename Fr, IndexType Index>
     232             : struct is_tensor_index_type<
     233             :     Tensor_detail::TensorIndexType<SpatialDim, Ul, Fr, Index>>
     234             :     : std::true_type {};
     235             : /// \endcond
     236             : /// \see is_tensor_index_type
     237             : template <typename T>
     238           1 : using is_tensor_index_type_t = typename is_tensor_index_type<T>::type;
     239             : /// @}
     240             : }  // namespace tt
     241             : 
     242             : /// \ingroup TensorGroup
     243             : /// Change the \ref SpacetimeIndex "TensorIndexType" to be covariant
     244             : /// if it's contravariant and vice-versa
     245             : ///
     246             : /// Here is an example of how to use ::change_index_up_lo
     247             : /// \snippet Test_Tensor.cpp change_up_lo
     248             : ///
     249             : /// \tparam Index the \ref SpacetimeIndex "TensorIndexType" to change
     250             : template <typename Index>
     251           1 : using change_index_up_lo = Tensor_detail::TensorIndexType<
     252             :     Index::index_type == IndexType::Spatial ? Index::value : Index::value - 1,
     253             :     Index::ul == UpLo::Up ? UpLo::Lo : UpLo::Up, typename Index::Frame,
     254             :     Index::index_type>;
     255             : 
     256             : template <typename... Ts>
     257           0 : using index_list = tmpl::list<Ts...>;
     258             : 
     259             : /// \ingroup TensorGroup
     260             : /// Change the \ref SpacetimeIndex "TensorIndexType" to be spacetime
     261             : /// if it's spatial and vice versa
     262             : ///
     263             : /// \tparam Index the \ref SpacetimeIndex "TensorIndexType" to change
     264             : template <typename Index>
     265           1 : using change_index_type = Tensor_detail::TensorIndexType<
     266             :     Index::index_type == IndexType::Spatial ? Index::dim : Index::dim - 1,
     267             :     Index::ul, typename Index::Frame,
     268             :     Index::index_type == IndexType::Spatial ? IndexType::Spacetime
     269             :                                             : IndexType::Spatial>;

Generated by: LCOV version 1.14