Caribou
Domain.h
1 #pragma once
2 
3 #include <Caribou/config.h>
4 #include <Caribou/macros.h>
5 #include <Caribou/constants.h>
6 #include <Caribou/Topology/BaseDomain.h>
7 #include <Caribou/Topology/BarycentricContainer.h>
8 #include <Caribou/Geometry/Element.h>
9 
10 #include <vector>
11 #include <array>
12 
13 namespace caribou::topology {
14 
20  template <typename Element>
21  class DomainStorage {};
22 
74  template <typename Mesh, typename Element, typename NodeIndex = UNSIGNED_INTEGER_TYPE>
75  class Domain final : public BaseDomain, private DomainStorage<Element> {
76  friend Mesh;
77  public:
78  static constexpr INTEGER_TYPE Dimension = geometry::traits<Element>::Dimension;
79  using MeshType = Mesh;
80  using ElementType = Element;
81  using NodeIndexType = NodeIndex;
82 
89  using ElementsIndices = Eigen::Matrix<NodeIndex, Eigen::Dynamic, geometry::traits<Element>::NumberOfNodesAtCompileTime, Eigen::RowMajor>;
90 
94  using ElementIndices = Eigen::Matrix<NodeIndex, geometry::traits<Element>::NumberOfNodesAtCompileTime, 1>;
95 
97  Domain() = delete;
98 
100  Domain(const Domain & other) noexcept
101  : DomainStorage<Element>(other), p_mesh(other.p_mesh), p_buffer(other.p_buffer), p_elements(other.p_elements) {}
102 
103 // /*! Move constructor */
104 // Domain(Domain && other) noexcept {
105 // swap(*this, other);
106 // }
107 
109  auto operator=(Domain other) noexcept -> Domain & {
110  swap(*this, other);
111  return *this;
112  }
113 
115  ~Domain() final = default;
116 
120  [[nodiscard]]
121  auto canonical_dimension() const -> UNSIGNED_INTEGER_TYPE final {
123  }
124 
128  [[nodiscard]]
129  auto number_of_nodes_per_elements() const -> UNSIGNED_INTEGER_TYPE final;
130 
134  [[nodiscard]]
135  auto number_of_elements() const -> UNSIGNED_INTEGER_TYPE final;
136 
144  template<typename EigenMatrix>
145  inline auto element(const UNSIGNED_INTEGER_TYPE & element_id, const Eigen::DenseBase<EigenMatrix> & positions) const -> Element;
146 
152  inline auto element(const UNSIGNED_INTEGER_TYPE & element_id) const -> Element;
153 
160  inline auto element_indices(const UNSIGNED_INTEGER_TYPE & index) const;
161 
165  inline auto mesh() const -> const Mesh & {
166  return *p_mesh;
167  }
168 
176  template <typename Derived>
177  inline auto embed(const Eigen::MatrixBase<Derived> & points) const -> BarycentricContainer<Domain> {
178  return {this, points};
179  }
180 
181  protected:
182 
183  friend void swap(Domain & first, Domain& second) noexcept
184  {
185  // enable ADL
186  using std::swap;
187  swap(first.p_buffer, second.p_buffer);
188  swap(first.p_elements, second.p_elements);
189  }
190 
196  Domain(const Mesh * mesh, const ElementsIndices & elements)
197  : p_mesh(mesh), p_buffer(elements), p_elements(p_buffer.data(), p_buffer.rows(), p_buffer.cols(), {p_buffer.cols(), 1}) {}
198 
204  Domain(const Mesh * mesh, ElementsIndices & elements)
205  : p_mesh(mesh), p_buffer(elements), p_elements(p_buffer.data(), p_buffer.rows(), p_buffer.cols(), {p_buffer.cols(), 1}) {}
206 
213  Domain(const Mesh * mesh, const ElementsIndices * elements)
214  : p_mesh(mesh), p_buffer(), p_elements(elements->data(), elements->rows(), elements->cols(), {elements->cols(), 1}) {}
215 
222  explicit Domain(const Mesh * mesh, const NodeIndex * data, const Eigen::Index & number_of_elements, const Eigen::Index & number_of_nodes_per_elements)
224 
231  explicit Domain(const Mesh * mesh, const NodeIndex * data, const Eigen::Index & number_of_elements, const Eigen::Index & number_of_nodes_per_elements, Eigen::Index outer_stride, Eigen::Index inner_stride)
232  : p_mesh(mesh), p_buffer(), p_elements(data, number_of_elements, number_of_nodes_per_elements, {outer_stride, inner_stride}) {}
233 
235  const Mesh * p_mesh;
236 
241 
244  Eigen::Map<const ElementsIndices, Eigen::Unaligned, Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>> p_elements;
245  };
246 
247  // -------------------------------------------------------------------------------------
248  // IMPLEMENTATION
249  // -------------------------------------------------------------------------------------
250  // Implementation of methods that can be specialized later for an explicit Element type
251  // -------------------------------------------------------------------------------------
252 
253  template <typename Mesh, typename Element, typename NodeIndex>
255  return p_elements.cols();
256  }
257 
258  template <typename Mesh, typename Element, typename NodeIndex>
259  auto Domain<Mesh, Element, NodeIndex>::number_of_elements() const -> UNSIGNED_INTEGER_TYPE {
260  return p_elements.rows();
261  }
262 
263  template <typename Mesh, typename Element, typename NodeIndex>
264  inline auto Domain<Mesh, Element, NodeIndex>::element_indices(const UNSIGNED_INTEGER_TYPE & index) const {
265  caribou_assert(index < number_of_elements() and "Trying to get an element that does not exists.");
266 
267  return Eigen::Map<const Eigen::Matrix<NodeIndex, geometry::traits<Element>::NumberOfNodesAtCompileTime, 1>, Eigen::Unaligned, Eigen::Stride<1, Eigen::Dynamic>>(
268  p_elements.row(index).data(), {1, p_elements.innerStride()}
269  );
270  }
271 
272  template <typename Mesh, typename Element, typename NodeIndex>
273  template<typename EigenMatrix>
274  inline auto Domain<Mesh, Element, NodeIndex>::element(const UNSIGNED_INTEGER_TYPE & element_id, const Eigen::DenseBase<EigenMatrix> & positions) const -> Element {
275  caribou_assert(element_id < number_of_elements() &&
276  "Trying to get the element #"+std::to_string(element_id) + ", but the domain only has " +
277  std::to_string(number_of_elements()) + " elements."
278  );
279 
280  using NodeMatrix = typename geometry::Element<Element>::template Matrix<geometry::traits<Element>::NumberOfNodesAtCompileTime, Dimension>;
281  NodeMatrix node_positions;
282  if constexpr (geometry::traits<Element>::NumberOfNodesAtCompileTime == caribou::Dynamic) {
283  node_positions.resize(number_of_nodes_per_elements(), Dimension);
284  }
285 
286  const auto node_indices = element_indices(element_id);
287  for (std::size_t i = 0; i < node_indices.size(); ++i) {
288  node_positions.row(i) = positions.row(node_indices[i]);
289  }
290 
291  return Element(node_positions);
292  }
293 
294  template <typename Mesh, typename Element, typename NodeIndex>
295  inline auto Domain<Mesh, Element, NodeIndex>::element(const UNSIGNED_INTEGER_TYPE & element_id) const -> Element {
296  caribou_assert(element_id < number_of_elements() &&
297  ("Trying to get the element #"+std::to_string(element_id) + ", but the domain only has " +
298  std::to_string(number_of_elements()) + " elements.").c_str()
299  );
300 
301  return Element(mesh().positions(element_indices(element_id)));
302  }
303 }
caribou::topology::Domain::element_indices
auto element_indices(const UNSIGNED_INTEGER_TYPE &index) const
Definition: Domain.h:264
caribou::topology::Domain::mesh
auto mesh() const -> const Mesh &
Definition: Domain.h:165
caribou::geometry::Element
Definition: Element.h:28
caribou::topology::Domain::element
auto element(const UNSIGNED_INTEGER_TYPE &element_id, const Eigen::DenseBase< EigenMatrix > &positions) const -> Element
Definition: Domain.h:274
caribou::topology::Domain
Definition: Domain.h:75
caribou::topology::Domain::Domain
Domain(const Mesh *mesh, ElementsIndices &elements)
Definition: Domain.h:204
caribou::topology::Domain::Domain
Domain(const Mesh *mesh, const ElementsIndices &elements)
Definition: Domain.h:196
caribou::topology::Domain::number_of_nodes_per_elements
auto number_of_nodes_per_elements() const -> UNSIGNED_INTEGER_TYPE final
Get the number of nodes an element of this domain has.
Definition: Domain.h:254
caribou::topology::Domain::ElementsIndices
Eigen::Matrix< NodeIndex, Eigen::Dynamic, geometry::traits< Element >::NumberOfNodesAtCompileTime, Eigen::RowMajor > ElementsIndices
Definition: Domain.h:89
caribou::topology::Domain::p_buffer
ElementsIndices p_buffer
Buffer containing the element indices.
Definition: Domain.h:240
caribou::topology::Domain::Domain
Domain(const Mesh *mesh, const ElementsIndices *elements)
Definition: Domain.h:213
caribou::topology::Domain::Domain
Domain(const Mesh *mesh, const NodeIndex *data, const Eigen::Index &number_of_elements, const Eigen::Index &number_of_nodes_per_elements)
Definition: Domain.h:222
caribou::topology::Domain::p_elements
Eigen::Map< const ElementsIndices, Eigen::Unaligned, Eigen::Stride< Eigen::Dynamic, Eigen::Dynamic > > p_elements
Actual pointer to the element indices.
Definition: Domain.h:244
caribou::geometry::traits
Definition: Element.h:14
caribou::topology::Domain::canonical_dimension
auto canonical_dimension() const -> UNSIGNED_INTEGER_TYPE final
Get the canonical dimension of the element contained in this domain, ie, the number of coordinates of...
Definition: Domain.h:121
caribou::topology::Domain::Domain
Domain(const Domain &other) noexcept
Definition: Domain.h:100
caribou::topology::Mesh
Definition: Mesh.h:16
caribou::topology::Domain::p_mesh
const Mesh * p_mesh
The mesh associated with this domain.
Definition: Domain.h:235
caribou::topology::BaseDomain
A domain is subspace of a mesh containing a set of points and the topological relation between them.
Definition: BaseDomain.h:13
caribou::topology::Domain::operator=
auto operator=(Domain other) noexcept -> Domain &
Definition: Domain.h:109
caribou::topology::BarycentricContainer
The BarycentricContainer class allows to embed nodes into a container domain.
Definition: BarycentricContainer.h:28
caribou::topology::Domain::Domain
Domain(const Mesh *mesh, const NodeIndex *data, const Eigen::Index &number_of_elements, const Eigen::Index &number_of_nodes_per_elements, Eigen::Index outer_stride, Eigen::Index inner_stride)
Definition: Domain.h:231
caribou::topology::Domain::number_of_elements
auto number_of_elements() const -> UNSIGNED_INTEGER_TYPE final
Get the number of elements contained in the domain.
Definition: Domain.h:259
caribou::topology::Domain::~Domain
~Domain() final=default
caribou::topology::Domain::embed
auto embed(const Eigen::MatrixBase< Derived > &points) const -> BarycentricContainer< Domain >
Embed a set of nodes (in world coordinates) inside this domain.
Definition: Domain.h:177
caribou::topology::Domain::ElementIndices
Eigen::Matrix< NodeIndex, geometry::traits< Element >::NumberOfNodesAtCompileTime, 1 > ElementIndices
Definition: Domain.h:94
caribou::topology::Domain::Domain
Domain()=delete