Hypercube.hpp
2 // See LICENSE.txt for details.
3
4 #pragma once
5
6 #include <array>
7 #include <cstddef>
8 #include <limits>
9 #include <ostream>
10
13 #include "Utilities/Gsl.hpp"
14 #include "Utilities/Requires.hpp"
15 #include "Utilities/StdHelpers.hpp"
16
17 /*!
18  * \brief An element of dimension ElementDim on the boundary of a hypercube of
19  * dimension HypercubeDim
20  *
21  * A hypercube of dimension \f$n\f$ (HypercubeDim) is composed of
22  * \f$2^{n-k}\binom{n}{k}\f$ elements of dimension \f$k \leq n\f$
23  * (ElementDim). For example, a 3D cube has 8 vertices (\f$k=0\f$), 12 edges
24  * (\f$k=1\f$), 6 faces (\f$k=2\f$) and 1 cell (\f$k=3\f$). Each element is
25  * identified by the \f$k\f$ dimensions it shares with the parent hypercube
26  * and \f$n - k\f$ indices that specify whether it is located on the lower or
27  * upper side of the parent hypercube's remaining dimensions.
28  */
29 template <size_t ElementDim, size_t HypercubeDim>
31  static_assert(ElementDim <= HypercubeDim);
32
35
36  template <size_t NumIndices = HypercubeDim - ElementDim,
37  Requires<NumIndices == 0> = nullptr>
38  HypercubeElement() noexcept {
39  for (size_t d = 0; d < ElementDim; ++d) {
40  gsl::at(dimensions_in_parent_, d) = d;
41  }
42  }
43
44  template <size_t LocalElementDim = ElementDim,
47
48  template <typename... Indices, size_t LocalElementDim = ElementDim,
49  size_t LocalHypercubeDim = HypercubeDim,
50  Requires<(LocalElementDim == 0 and LocalHypercubeDim > 0 and
51  sizeof...(Indices) == LocalHypercubeDim)> = nullptr>
52  explicit HypercubeElement(Indices... indices) noexcept
53  : index_{{static_cast<Side>(indices)...}} {}
54
55  template <size_t LocalElementDim = ElementDim,
57  HypercubeElement(size_t dim_in_parent,
59
60  // @{
61  /// The parent hypercube's dimensions that this element shares
63
64  template <size_t LocalElementDim = ElementDim,
66  size_t dimension_in_parent() const noexcept;
67  // @}
68
69  // @{
70  /// Whether this element is located on the lower or upper side in those
71  /// dimensions that it does not share with its parent hypercube
72  const std::array<Side, HypercubeDim - ElementDim>& index() const noexcept;
73
74  const Side& side_in_parent_dimension(size_t d) const noexcept;
75
76  template <size_t NumIndices = HypercubeDim - ElementDim,
77  Requires<NumIndices == 1> = nullptr>
78  const Side& side() const noexcept {
79  return index_[0];
80  }
81  // @}
82
83  bool operator==(const HypercubeElement& rhs) const noexcept {
84  return dimensions_in_parent_ == rhs.dimensions_in_parent_ and
85  index_ == rhs.index_;
86  }
87
88  bool operator!=(const HypercubeElement& rhs) const noexcept {
89  return not(*this == rhs);
90  }
91
92  private:
93  std::array<size_t, ElementDim> dimensions_in_parent_{};
94  std::array<Side, HypercubeDim - ElementDim> index_{};
95 };
96
97 template <size_t ElementDim, size_t HypercubeDim>
98 std::ostream& operator<<(
99  std::ostream& os,
100  const HypercubeElement<ElementDim, HypercubeDim>& element) noexcept;
101
102 /// A vertex in a Dim-dimensional hypercube
103 template <size_t Dim>
105
106 /// An edge in a Dim-dimensional hypercube
107 template <size_t Dim>
109
110 /// A face in a Dim-dimensional hypercube
111 template <size_t Dim>
113
114 /// A cell in a Dim-dimensional hypercube
115 template <size_t Dim>
117
118 /*!
119  * \brief Iterator over all ElementDim-dimensional elements on the boundary of
120  * a HypercubeDim-dimensional hypercube.
121  *
122  * \see HypercubeElement
123  */
124 template <size_t ElementDim, size_t HypercubeDim>
126  static_assert(
127  ElementDim <= HypercubeDim,
128  "Hypercube element dimension must not exceed hypercube dimension.");
129
130  public:
131  static constexpr size_t num_indices = HypercubeDim - ElementDim;
132
133  /// The number of ElementDim-dimensional elements on the boundary of a
134  /// HypercubeDim-dimensional hypercube.
135  static constexpr size_t size() noexcept {
136  return two_to_the(num_indices) * factorial(HypercubeDim) /
137  factorial(ElementDim) / factorial(num_indices);
138  }
139
140  HypercubeElementsIterator() noexcept;
141
142  static HypercubeElementsIterator begin() noexcept;
143
144  static HypercubeElementsIterator end() noexcept;
145
146  HypercubeElementsIterator& operator++() noexcept;
147
148  // NOLINTNEXTLINE(cert-dcl21-cpp) returned object doesn't need to be const
149  HypercubeElementsIterator operator++(int) noexcept;
150
151  HypercubeElement<ElementDim, HypercubeDim> operator*() const noexcept;
152
153  private:
154  template <size_t LocalElementDim = ElementDim,
155  Requires<(LocalElementDim > 0)> = nullptr>
156  void increment_dimension_in_parent(size_t d) noexcept;
157
158  template <size_t LocalElementDim, size_t LocalHypercubeDim>
160  friend bool operator==(
161  const HypercubeElementsIterator<LocalElementDim, LocalHypercubeDim>& lhs,
162  const HypercubeElementsIterator<LocalElementDim, LocalHypercubeDim>&
163  rhs) noexcept;
164
165  std::array<size_t, ElementDim> dimensions_in_parent_{};
166  size_t index_ = std::numeric_limits<size_t>::max();
167 };
168
169 template <size_t ElementDim, size_t HypercubeDim>
170 bool operator!=(
173
174 /// Iterate over all vertices in a Dim-dimensional hypercube
175 template <size_t Dim>
177
178 /// Iterate over all edges in a Dim-dimensional hypercube
179 template <size_t Dim>
181
182 /// Iterate over all faces in a Dim-dimensional hypercube
183 template <size_t Dim>
185
186 /// Iterate over all cells in a Dim-dimensional hypercube
187 template <size_t Dim>
gsl::at
constexpr T & at(std::array< T, N > &arr, Size index)
Retrieve a entry from a container, with checks in Debug mode that the index being retrieved is valid.
Definition: Gsl.hpp:125
two_to_the
constexpr T two_to_the(T n)
Definition: ConstantExpressions.hpp:36
HypercubeElementsIterator
Iterator over all ElementDim-dimensional elements on the boundary of a HypercubeDim-dimensional hyper...
Definition: Hypercube.hpp:125
std::rel_ops::operator!=
T operator!=(T... args)
HypercubeElement::index
const std::array< Side, HypercubeDim - ElementDim > & index() const noexcept
Whether this element is located on the lower or upper side in those dimensions that it does not share...
Definition: Hypercube.cpp:78
Side.hpp
factorial
constexpr uint64_t factorial(const uint64_t n) noexcept
Compute the factorial of .
Definition: ConstantExpressions.hpp:89
HypercubeElementsIterator::size
static constexpr size_t size() noexcept
The number of ElementDim-dimensional elements on the boundary of a HypercubeDim-dimensional hypercube...
Definition: Hypercube.hpp:135
std::ostream
cstddef
array
HypercubeElement::dimensions_in_parent
const std::array< size_t, ElementDim > & dimensions_in_parent() const noexcept
The parent hypercube's dimensions that this element shares.
Definition: Hypercube.cpp:64
ConstantExpressions.hpp
HypercubeElement
An element of dimension ElementDim on the boundary of a hypercube of dimension HypercubeDim
Definition: Hypercube.hpp:30
Side
Side
Definition: Side.hpp:17
limits
Gsl.hpp
Requires.hpp
StdHelpers.hpp
Requires
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t
Definition: Requires.hpp:67
std::numeric_limits::max
T max(T... args)
ostream