3 #include <Caribou/config.h>
4 #include <Caribou/traits.h>
5 #include <Caribou/macros.h>
11 namespace caribou::geometry {
21 template<
class T,
class Enable =
void>
27 template<
typename Derived,
typename ScalarType = FLOATING_POINT_TYPE>
30 using Scalar = ScalarType;
32 template <INTEGER_TYPE Dim>
33 using Vector = Eigen::Matrix<Scalar, Dim, 1>;
35 template <INTEGER_TYPE Rows, INTEGER_TYPE Cols,
int Options = Eigen::ColMajor>
36 using Matrix = Eigen::Matrix<Scalar, Rows, Cols, Options>;
38 template <INTEGER_TYPE Rows, INTEGER_TYPE Cols,
int Options = Eigen::ColMajor>
39 using MatrixI = Eigen::Matrix<Scalar, Rows, Cols, Options>;
45 using LocalCoordinates = Vector<CanonicalDimension>;
46 using WorldCoordinates = Vector<Dimension>;
49 LocalCoordinates position;
57 inline auto number_of_nodes() const -> UNSIGNED_INTEGER_TYPE {
return self().get_number_of_nodes();}
64 inline auto node(
const UNSIGNED_INTEGER_TYPE & index)
const {
return self().get_node(index);};
67 inline auto nodes()
const {
return self().get_nodes();};
70 inline auto gauss_node(
const UNSIGNED_INTEGER_TYPE & index)
const ->
const GaussNode & {
return self().
gauss_nodes()[index];};
73 inline auto gauss_nodes() const -> const std::vector<GaussNode> & {
return self().get_gauss_nodes();};
77 if constexpr (element_has_boundaries_v<Derived>) {
78 return self().get_number_of_boundary_elements();
101 static_assert(element_has_boundaries_v<Derived>,
"This element type has no boundary elements defined.");
102 return self().get_boundary_elements_nodes();
119 static_assert(element_has_boundaries_v<Derived>,
"This element type has no boundary elements defined.");
122 Matrix<BoundaryElement::NumberOfNodesAtCompileTime, Dimension>
nodes;
123 for (Eigen::Index boundary_node_id = 0; boundary_node_id <
nodes.rows(); ++boundary_node_id) {
124 nodes.row(boundary_node_id) =
self().
node(node_indices[boundary_node_id]);
126 return BoundaryElement(
nodes);
139 inline auto L(
const LocalCoordinates & xi)
const -> Vector<NumberOfNodesAtCompileTime> {
return self().get_L(xi);};
151 inline auto dL(
const LocalCoordinates & xi)
const -> Matrix<NumberOfNodesAtCompileTime, CanonicalDimension> {
return self().get_dL(xi);};
154 inline auto center() const -> WorldCoordinates {
return self().get_center();}
224 const WorldCoordinates & coordinates,
225 const LocalCoordinates & starting_point,
226 const FLOATING_POINT_TYPE & residual_tolerance,
227 const UNSIGNED_INTEGER_TYPE & maximum_number_of_iterations)
const -> LocalCoordinates {
229 using namespace Eigen;
231 LocalCoordinates xi = starting_point;
232 UNSIGNED_INTEGER_TYPE iteration = 0;
233 FLOATING_POINT_TYPE squared_threshold = residual_tolerance*residual_tolerance;
237 FLOATING_POINT_TYPE r_norm_2 = residual.squaredNorm();
238 FLOATING_POINT_TYPE r0_norm_2 = r_norm_2;
240 if (r_norm_2 < squared_threshold) {
247 Matrix<Dimension, CanonicalDimension> J =
jacobian(xi);
249 LocalCoordinates dxi;
250 if constexpr (Dimension == CanonicalDimension) {
251 dxi.noalias() = J.inverse() * residual;
253 dxi.noalias() = (J.transpose()*J).inverse() * (J.transpose()*residual);
256 xi.noalias() = (xi + dxi).eval();
258 r_norm_2 = residual.squaredNorm();
262 while (iteration < maximum_number_of_iterations and r_norm_2 >= r0_norm_2*squared_threshold);
272 inline auto contains_local(
const LocalCoordinates & xi,
const FLOATING_POINT_TYPE & eps = 1e-10) const ->
bool {
273 return self().get_contains_local(xi, eps);
284 template <
typename MatrixType>
286 const Eigen::MatrixBase<MatrixType> & values)
const {
287 static_assert(Eigen::MatrixBase<MatrixType>::RowsAtCompileTime == NumberOfNodesAtCompileTime,
288 "The matrix containing the values at each nodes must have one node-value per row.");
289 constexpr
auto NbCols = Eigen::MatrixBase<MatrixType>::ColsAtCompileTime;
290 using MatrixScalar =
typename Eigen::MatrixBase<MatrixType>::Scalar;
291 const auto result = ((values.array().colwise() *
self().
L(coordinates).array().template cast<typename Eigen::MatrixBase<MatrixType>::Scalar>()).matrix().colwise().sum().transpose()).eval();
292 if constexpr (NbCols == 1) {
293 return static_cast<MatrixScalar
>(result[0]);
295 return result.template cast<MatrixScalar>();
377 inline auto jacobian (
const LocalCoordinates & coordinates)
const -> Matrix<Dimension, CanonicalDimension>
379 const auto shape_derivatives =
self().
dL(coordinates);
380 return self().
nodes().transpose() * shape_derivatives;
383 auto self() -> Derived& {
return *
static_cast<Derived*
>(
this); }
384 auto self()
const ->
const Derived& {
return *
static_cast<const Derived*
>(
this); }
389 using element_boundary_type_t =
typename traits<T>::BoundaryElementType;
392 struct element_has_boundaries<T, CLASS_REQUIRES(
393 caribou::internal::is_detected_v<element_boundary_type_t, T>
394 )> : std::true_type {};