3 #include <Caribou/config.h>
4 #include <Caribou/constants.h>
5 #include <Caribou/Geometry/Element.h>
9 namespace caribou::geometry {
11 template<
typename Derived>
16 using LocalCoordinates =
typename Base::LocalCoordinates;
17 using WorldCoordinates =
typename Base::WorldCoordinates;
19 using GaussNode =
typename Base::GaussNode;
21 template <UNSIGNED_INTEGER_TYPE Dim>
22 using Vector =
typename Base::template Vector<Dim>;
24 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
25 using Matrix =
typename Base::template Matrix<Rows, Cols>;
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;
33 static_assert(Dimension == 3,
"Tetrahedrons can only be of dimension 3.");
39 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
43 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
49 REQUIRES(NumberOfNodesAtCompileTime ==
sizeof...(Nodes)+1)
51 explicit BaseTetrahedron(
const WorldCoordinates & first_node, Nodes&&...remaining_nodes)
53 construct_from_nodes<0>(first_node, std::forward<Nodes>(remaining_nodes)...);
63 return self().get_boundary_elements_nodes();
84 inline auto frame() const -> Matrix<3, 3>
87 const auto u = (this->
node(1) - this->
node(0)).normalized();
90 auto v = (this->
node(2) - this->
node(0)).normalized();
93 const WorldCoordinates w = u.cross(v).normalized();
96 v = w.cross(u).normalized();
106 friend struct Element<Derived>;
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;};
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);
121 auto self() -> Derived& {
return *
static_cast<Derived*
>(
this); }
122 auto self()
const ->
const Derived& {
return *
static_cast<const Derived*
>(
this); }
124 template <
size_t index,
typename ...Nodes, REQUIRES(
sizeof...(Nodes) >= 1)>
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)...);
131 template <
size_t index>
133 void construct_from_nodes(
const WorldCoordinates & last_node) {
134 p_nodes.row(index) = last_node;
137 Matrix<NumberOfNodesAtCompileTime, Dimension> p_nodes;