Caribou
BaseTetrahedron.h
1 #pragma once
2 
3 #include <Caribou/config.h>
4 #include <Caribou/constants.h>
5 #include <Caribou/Geometry/Element.h>
6 #include <Eigen/Core>
7 
8 
9 namespace caribou::geometry {
10 
11 template<typename Derived>
12 struct BaseTetrahedron : public Element<Derived> {
13  // Types
14  using Base = Element<Derived>;
15 
16  using LocalCoordinates = typename Base::LocalCoordinates;
17  using WorldCoordinates = typename Base::WorldCoordinates;
18 
19  using GaussNode = typename Base::GaussNode;
20 
21  template <UNSIGNED_INTEGER_TYPE Dim>
22  using Vector = typename Base::template Vector<Dim>;
23 
24  template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
25  using Matrix = typename Base::template Matrix<Rows, Cols>;
26 
27  // Constants
28  static constexpr auto CanonicalDimension = Base::CanonicalDimension;
29  static constexpr auto Dimension = Base::Dimension;
30  static constexpr auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
31  static constexpr auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
32 
33  static_assert(Dimension == 3, "Tetrahedrons can only be of dimension 3.");
34 
36  BaseTetrahedron() = default;
37 
39  template<typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
40  explicit BaseTetrahedron(Eigen::EigenBase<EigenType> & nodes) :p_nodes(nodes.derived().template cast<typename Base::Scalar>()) {}
41 
43  template<typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
44  explicit BaseTetrahedron(const Eigen::EigenBase<EigenType> & nodes) :p_nodes(nodes.derived().template cast<typename Base::Scalar>()) {}
45 
47  template <
48  typename ...Nodes,
49  REQUIRES(NumberOfNodesAtCompileTime == sizeof...(Nodes)+1)
50  >
51  explicit BaseTetrahedron(const WorldCoordinates & first_node, Nodes&&...remaining_nodes)
52  {
53  construct_from_nodes<0>(first_node, std::forward<Nodes>(remaining_nodes)...);
54  }
55 
56  // Public methods common to all tetrahedral types
57 
62  inline auto faces() const {
63  return self().get_boundary_elements_nodes();
64  }
65 
84  inline auto frame() const -> Matrix<3, 3>
85  {
86  // The u-axis of the computed frame
87  const auto u = (this->node(1) - this->node(0)).normalized();
88 
89  // The v-axis of the computed frame
90  auto v = (this->node(2) - this->node(0)).normalized();
91 
92  // The w-axis of the computed frame
93  const WorldCoordinates w = u.cross(v).normalized();
94 
95  // v-axis (recompute the v-axis in case u and v aren't orthogonal
96  v = w.cross(u).normalized();
97 
98  Matrix<3, 3> m;
99  m << u, v, w;
100 
101  return m;
102  }
103 
104 private:
105  // Implementations
106  friend struct Element<Derived>;
107  [[nodiscard]]
108  inline auto get_number_of_nodes() const {return NumberOfNodesAtCompileTime;}
109  inline auto get_number_of_gauss_nodes() const {return NumberOfGaussNodesAtCompileTime;}
110  inline auto get_node(const UNSIGNED_INTEGER_TYPE & index) const {return WorldCoordinates(p_nodes.row(index));};
111  inline auto get_nodes() const -> const auto & {return p_nodes;};
112  inline auto get_center() const {return Base::world_coordinates(LocalCoordinates({1/4., 1/4., 1/4.}));};
113  inline auto get_number_of_boundary_elements() const -> UNSIGNED_INTEGER_TYPE {return 4;};
114  inline auto get_contains_local(const LocalCoordinates & xi, const FLOATING_POINT_TYPE & eps) const -> bool {
115  const auto & u = xi[0];
116  const auto & v = xi[1];
117  const auto & w = xi[2];
118  return (u > -eps) and (v > -eps) and (w > -eps) and (1 - u - v - w > -eps);
119  }
120 
121  auto self() -> Derived& { return *static_cast<Derived*>(this); }
122  auto self() const -> const Derived& { return *static_cast<const Derived*>(this); }
123 
124  template <size_t index, typename ...Nodes, REQUIRES(sizeof...(Nodes) >= 1)>
125  inline
126  void construct_from_nodes(const WorldCoordinates & first_node, Nodes&&...remaining_nodes) {
127  p_nodes.row(index) = first_node;
128  construct_from_nodes<index+1>(std::forward<Nodes>(remaining_nodes)...);
129  }
130 
131  template <size_t index>
132  inline
133  void construct_from_nodes(const WorldCoordinates & last_node) {
134  p_nodes.row(index) = last_node;
135  }
136 protected:
137  Matrix<NumberOfNodesAtCompileTime, Dimension> p_nodes;
138 };
139 
140 }
caribou::geometry::BaseTetrahedron::BaseTetrahedron
BaseTetrahedron(Eigen::EigenBase< EigenType > &nodes)
Constructor from an Eigen matrix containing the positions of the tetra's nodes.
Definition: BaseTetrahedron.h:40
caribou::geometry::Element< Derived >::world_coordinates
auto world_coordinates(const LocalCoordinates &coordinates) const -> WorldCoordinates
Get the world coordinates of a point from its local coordinates.
Definition: Element.h:157
caribou::geometry::Element
Definition: Element.h:28
caribou::geometry::BaseTetrahedron::faces
auto faces() const
Get the list of node indices of the faces.
Definition: BaseTetrahedron.h:62
caribou::geometry::BaseTetrahedron
Definition: BaseTetrahedron.h:12
caribou::geometry::BaseTetrahedron::frame
auto frame() const -> Matrix< 3, 3 >
Extract the orthogonal frame of the element by computing the cross product of the unit vectors from t...
Definition: BaseTetrahedron.h:84
caribou::geometry::Element< Derived >::nodes
auto nodes() const
Get the set of nodes.
Definition: Element.h:67
caribou::geometry::BaseTetrahedron::BaseTetrahedron
BaseTetrahedron(const WorldCoordinates &first_node, Nodes &&...remaining_nodes)
Constructor from a serie of nodes.
Definition: BaseTetrahedron.h:51
caribou::geometry::BaseTetrahedron::BaseTetrahedron
BaseTetrahedron(const Eigen::EigenBase< EigenType > &nodes)
Constructor from an Eigen matrix containing the positions of the tetra's nodes.
Definition: BaseTetrahedron.h:44
caribou::geometry::BaseTetrahedron::BaseTetrahedron
BaseTetrahedron()=default
Default empty constructor.
caribou::geometry::Element< Derived >::node
auto node(const UNSIGNED_INTEGER_TYPE &index) const
Get the Node at given index.
Definition: Element.h:64