3 #include <Caribou/config.h>
4 #include <Caribou/constants.h>
5 #include <Caribou/Geometry/Element.h>
8 namespace caribou::geometry {
10 template<
typename Derived>
15 using LocalCoordinates =
typename Base::LocalCoordinates;
16 using WorldCoordinates =
typename Base::WorldCoordinates;
18 using GaussNode =
typename Base::GaussNode;
20 template <UNSIGNED_INTEGER_TYPE Dim>
21 using Vector =
typename Base::template Vector<Dim>;
23 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
24 using Matrix =
typename Base::template Matrix<Rows, Cols>;
27 static constexpr
auto CanonicalDimension = Base::CanonicalDimension;
28 static constexpr
auto Dimension = Base::Dimension;
29 static constexpr
auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
30 static constexpr
auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
32 static_assert(Dimension == 2 or Dimension == 3,
"Quads can only be of dimension 2 or 3.");
38 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
39 explicit BaseQuad(Eigen::EigenBase<EigenType> &
nodes) :p_nodes(
nodes.derived().template cast<typename
Base::Scalar>()) {}
42 template<
typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
43 explicit BaseQuad(
const Eigen::EigenBase<EigenType> &
nodes) :p_nodes(
nodes.derived().template cast<typename
Base::Scalar>()) {}
48 REQUIRES(NumberOfNodesAtCompileTime ==
sizeof...(Nodes)+1)
50 explicit BaseQuad(
const WorldCoordinates & first_node, Nodes&&...remaining_nodes)
52 construct_from_nodes<0>(first_node, std::forward<Nodes>(remaining_nodes)...);
62 return self().get_boundary_elements_nodes();
75 inline auto frame() const -> Matrix<Dimension, Dimension>
77 return frame(LocalCoordinates::Zero());
103 frame(
const LocalCoordinates & local_point)
const -> Matrix<Dimension, Dimension>
115 const auto point_to_u = projected_on_u - p;
118 const auto point_to_v = projected_on_v - p;
121 const auto u = point_to_u.normalized();
124 auto v = point_to_v.normalized();
126 Matrix<Dimension, Dimension> m {};
127 if constexpr (Dimension == 3) {
129 const WorldCoordinates w = u.cross(v).normalized();
140 friend struct Element<Derived>;
142 inline auto get_number_of_nodes()
const {
return NumberOfNodesAtCompileTime;}
143 inline auto get_number_of_gauss_nodes()
const {
return NumberOfGaussNodesAtCompileTime;}
144 inline auto get_node(
const UNSIGNED_INTEGER_TYPE & index)
const {
return WorldCoordinates(p_nodes.row(index));};
145 inline auto get_nodes() const -> const auto & {
return p_nodes;};
147 inline auto get_number_of_boundary_elements() const -> UNSIGNED_INTEGER_TYPE {
return 4;};
148 inline auto get_contains_local(
const LocalCoordinates & xi,
const FLOATING_POINT_TYPE & eps)
const ->
bool {
149 const auto & u = xi[0];
150 const auto & v = xi[1];
151 return IN_CLOSED_INTERVAL(-1-eps, u, 1+eps) and
152 IN_CLOSED_INTERVAL(-1-eps, v, 1+eps);
155 auto self() -> Derived& {
return *
static_cast<Derived*
>(
this); }
156 auto self()
const ->
const Derived& {
return *
static_cast<const Derived*
>(
this); }
158 template <
size_t index,
typename ...Nodes, REQUIRES(
sizeof...(Nodes) >= 1)>
160 void construct_from_nodes(
const WorldCoordinates & first_node, Nodes&&...remaining_nodes) {
161 p_nodes.row(index) = first_node;
162 construct_from_nodes<index+1>(std::forward<Nodes>(remaining_nodes)...);
165 template <
size_t index>
167 void construct_from_nodes(
const WorldCoordinates & last_node) {
168 p_nodes.row(index) = last_node;
171 Matrix<NumberOfNodesAtCompileTime, Dimension> p_nodes;