SpECTRE Documentation Coverage Report
Current view: top level - Domain/Structure - Direction.hpp Hit Total Coverage
Commit: d0fc80462417e83e5cddfa1b9901bb4a9b6af4d6 Lines: 20 32 62.5 %
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             : /// \file
       5             : /// Defines class template Direction.
       6             : 
       7             : #pragma once
       8             : 
       9             : #include <array>
      10             : #include <cstddef>
      11             : #include <functional>
      12             : #include <iosfwd>
      13             : 
      14             : #include "Domain/Structure/Side.hpp"
      15             : 
      16             : namespace PUP {
      17             : class er;
      18             : }  // namespace PUP
      19             : 
      20             : /// \ingroup ComputationalDomainGroup
      21             : /// A particular Side along a particular coordinate Axis.
      22             : template <size_t VolumeDim>
      23           1 : class Direction {
      24             :  public:
      25           0 :   static constexpr const size_t volume_dim = VolumeDim;
      26             : 
      27             :   /// The logical-coordinate names of each dimension
      28             :   enum class Axis;
      29             : 
      30             :   /// Construct by specifying an Axis and a Side.
      31           1 :   Direction(Axis axis, Side side) : axis_(axis), side_(side) {}
      32             : 
      33             :   /// Construct by specifying a dimension and a Side.
      34           1 :   Direction(size_t dimension, Side side);
      35             : 
      36             :   /// Default constructor for Charm++ serialization.
      37           1 :   Direction();
      38             : 
      39             :   /// The dimension of the Direction
      40           1 :   size_t dimension() const { return static_cast<size_t>(axis_); }
      41             : 
      42             :   /// The Axis of the Direction
      43           1 :   Axis axis() const { return axis_; }
      44             : 
      45             :   /// The side of the Direction
      46           1 :   Side side() const { return side_; }
      47             : 
      48             :   /// The sign for the normal to the Side.
      49           1 :   double sign() const { return (Side::Lower == side_ ? -1.0 : 1.0); }
      50             : 
      51             :   /// The opposite Direction.
      52           1 :   Direction<VolumeDim> opposite() const;
      53             : 
      54             :   // An array of all logical Directions for a given dimensionality.
      55             :   static const std::array<Direction<VolumeDim>, 2 * VolumeDim>&
      56           0 :   all_directions();
      57             : 
      58             :   /// @{
      59             :   /// Helper functions for creating specific Directions.
      60             :   /// These are labeled by the logical-coordinate names (Xi,Eta,Zeta).
      61             :   // Note: these are functions because they contain static_assert.
      62           1 :   static Direction<VolumeDim> lower_xi();
      63           1 :   static Direction<VolumeDim> upper_xi();
      64           1 :   static Direction<VolumeDim> lower_eta();
      65           1 :   static Direction<VolumeDim> upper_eta();
      66           1 :   static Direction<VolumeDim> lower_zeta();
      67           1 :   static Direction<VolumeDim> upper_zeta();
      68             :   /// @}
      69             : 
      70             :   /// Serialization for Charm++
      71             :   // NOLINTNEXTLINE(google-runtime-references)
      72           1 :   void pup(PUP::er& p);
      73             : 
      74             :  private:
      75           0 :   Axis axis_{Axis::Xi};
      76           0 :   Side side_{Side::Lower};
      77             : };
      78             : 
      79             : /// Output operator for a Direction.
      80             : template <size_t VolumeDim>
      81           1 : std::ostream& operator<<(std::ostream& os,
      82             :                          const Direction<VolumeDim>& direction);
      83             : 
      84             : //##############################################################################
      85             : // INLINE DEFINITIONS
      86             : //##############################################################################
      87             : 
      88             : /// \cond
      89             : // clang-tidy: redundant declaration false positive. Needs to be here because of
      90             : // the Axis enum, otherwise won't compile.
      91             : template <size_t VolumeDim>
      92             : Direction<VolumeDim>::Direction() = default;  // NOLINT
      93             : 
      94             : // Needed in order to address warning; ignorning -Wpedantic is needed.
      95             : // Bug 61491
      96             : // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61491
      97             : #pragma GCC diagnostic push
      98             : #pragma GCC diagnostic ignored "-Wpedantic"
      99             : template <>
     100             : enum class Direction<1>::Axis{Xi = 0};
     101             : 
     102             : template <>
     103             : enum class Direction<2>::Axis{Xi = 0, Eta = 1};
     104             : 
     105             : template <>
     106             : enum class Direction<3>::Axis{Xi = 0, Eta = 1, Zeta = 2};
     107             : #pragma GCC diagnostic pop
     108             : 
     109             : template <size_t VolumeDim>
     110             : inline Direction<VolumeDim> Direction<VolumeDim>::lower_xi() {
     111             :   return Direction(Direction<VolumeDim>::Axis::Xi, Side::Lower);
     112             : }
     113             : 
     114             : template <size_t VolumeDim>
     115             : inline Direction<VolumeDim> Direction<VolumeDim>::upper_xi() {
     116             :   return Direction(Direction<VolumeDim>::Axis::Xi, Side::Upper);
     117             : }
     118             : 
     119             : template <size_t VolumeDim>
     120             : inline Direction<VolumeDim> Direction<VolumeDim>::lower_eta() {
     121             :   static_assert(VolumeDim == 2 or VolumeDim == 3, "VolumeDim must be 2 or 3.");
     122             :   return Direction(Direction<VolumeDim>::Axis::Eta, Side::Lower);
     123             : }
     124             : 
     125             : template <size_t VolumeDim>
     126             : inline Direction<VolumeDim> Direction<VolumeDim>::upper_eta() {
     127             :   static_assert(VolumeDim == 2 or VolumeDim == 3, "VolumeDim must be 2 or 3.");
     128             :   return Direction(Direction<VolumeDim>::Axis::Eta, Side::Upper);
     129             : }
     130             : 
     131             : template <size_t VolumeDim>
     132             : inline Direction<VolumeDim> Direction<VolumeDim>::lower_zeta() {
     133             :   static_assert(VolumeDim == 3, "VolumeDim must be 3.");
     134             :   return Direction(Direction<VolumeDim>::Axis::Zeta, Side::Lower);
     135             : }
     136             : 
     137             : template <size_t VolumeDim>
     138             : inline Direction<VolumeDim> Direction<VolumeDim>::upper_zeta() {
     139             :   static_assert(VolumeDim == 3, "VolumeDim must be 3.");
     140             :   return Direction(Direction<VolumeDim>::Axis::Zeta, Side::Upper);
     141             : }
     142             : 
     143             : template <size_t VolumeDim>
     144             : inline Direction<VolumeDim> Direction<VolumeDim>::opposite() const {
     145             :   return Direction<VolumeDim>(axis_, ::opposite(side_));
     146             : }
     147             : 
     148             : template <>
     149             : inline const std::array<Direction<1>, 2>& Direction<1>::all_directions() {
     150             :   const static auto directions = std::array<Direction<1>, 2>{
     151             :       {Direction<1>::lower_xi(), Direction<1>::upper_xi()}};
     152             :   return directions;
     153             : }
     154             : 
     155             : template <>
     156             : inline const std::array<Direction<2>, 4>& Direction<2>::all_directions() {
     157             :   const static auto directions = std::array<Direction<2>, 4>{
     158             :       {Direction<2>::lower_xi(), Direction<2>::upper_xi(),
     159             :        Direction<2>::lower_eta(), Direction<2>::upper_eta()}};
     160             :   return directions;
     161             : }
     162             : 
     163             : template <>
     164             : inline const std::array<Direction<3>, 6>& Direction<3>::all_directions() {
     165             :   const static auto directions = std::array<Direction<3>, 6>{
     166             :       {Direction<3>::lower_xi(), Direction<3>::upper_xi(),
     167             :        Direction<3>::lower_eta(), Direction<3>::upper_eta(),
     168             :        Direction<3>::lower_zeta(), Direction<3>::upper_zeta()}};
     169             :   return directions;
     170             : }
     171             : /// \endcond
     172             : 
     173             : template <size_t VolumeDim>
     174           0 : bool operator==(const Direction<VolumeDim>& lhs,
     175             :                 const Direction<VolumeDim>& rhs) {
     176             :   return lhs.dimension() == rhs.dimension() and lhs.sign() == rhs.sign();
     177             : }
     178             : 
     179             : template <size_t VolumeDim>
     180           0 : bool operator!=(const Direction<VolumeDim>& lhs,
     181             :                 const Direction<VolumeDim>& rhs) {
     182             :   return not(lhs == rhs);
     183             : }
     184             : 
     185             : /// Define an ordering of directions first by axis (xi, eta, zeta), then by side
     186             : /// (lower, upper). There's no particular reason for this choice of ordering.
     187             : template <size_t VolumeDim>
     188           1 : bool operator<(const Direction<VolumeDim>& lhs,
     189             :                const Direction<VolumeDim>& rhs);
     190             : 
     191             : template <size_t VolumeDim>
     192           0 : bool operator>(const Direction<VolumeDim>& lhs,
     193             :                const Direction<VolumeDim>& rhs) {
     194             :   return rhs < lhs;
     195             : }
     196             : template <size_t VolumeDim>
     197           0 : bool operator<=(const Direction<VolumeDim>& lhs,
     198             :                 const Direction<VolumeDim>& rhs) {
     199             :   return !(lhs > rhs);
     200             : }
     201             : template <size_t VolumeDim>
     202           0 : bool operator>=(const Direction<VolumeDim>& lhs,
     203             :                 const Direction<VolumeDim>& rhs) {
     204             :   return !(lhs < rhs);
     205             : }
     206             : 
     207             : template <size_t VolumeDim>
     208           0 : size_t hash_value(const Direction<VolumeDim>& d) {
     209             :   return std::hash<size_t>{}(d.dimension()) xor std::hash<double>{}(d.sign());
     210             : }
     211             : 
     212             : namespace std {
     213             : template <size_t VolumeDim>
     214             : struct hash<Direction<VolumeDim>> {
     215             :   size_t operator()(const Direction<VolumeDim>& d) const {
     216             :     return hash_value(d);
     217             :   }
     218             : };
     219             : }  // namespace std
     220             : 
     221             : /// \ingroup ComputationalDomainGroup
     222             : /// Provides a perfect hash if the size of the hash table is `2 * Dim`. To take
     223             : /// advantage of this, use the `FixedHashMap` class.
     224             : template <size_t Dim>
     225           1 : struct DirectionHash {
     226             :   template <size_t MaxSize>
     227           0 :   static constexpr bool is_perfect = MaxSize == 2 * Dim;
     228             : 
     229           0 :   size_t operator()(const Direction<Dim>& t) {
     230             :     return 2 * t.dimension() + (t.side() == Side::Upper ? 1 : 0);
     231             :   }
     232             : };

Generated by: LCOV version 1.14