6 #include <sofa/version.h>
7 #include <sofa/core/behavior/ForceField.h>
8 #include <sofa/core/topology/BaseMeshTopology.h>
10 #include <Caribou/config.h>
11 #include <Caribou/constants.h>
12 #include <Caribou/Geometry/Element.h>
13 #include <Caribou/Geometry/Triangle.h>
14 #include <Caribou/Geometry/Quad.h>
15 #include <Caribou/Geometry/Tetrahedron.h>
16 #include <Caribou/Geometry/Hexahedron.h>
18 #include <SofaCaribou/Material/HyperelasticMaterial.h>
20 #include <Eigen/Sparse>
21 #include <Eigen/Dense>
23 #if (defined(SOFA_VERSION) && SOFA_VERSION < 201299)
24 namespace sofa {
using Index =
unsigned int; }
27 namespace SofaCaribou::forcefield {
29 using namespace sofa::core;
30 using namespace sofa::core::objectmodel;
31 using namespace sofa::core::behavior;
34 template <std::
size_t Dim>
struct SofaVecType {};
35 template <>
struct SofaVecType<1> {
using Type = sofa::defaulttype::Vec1Types; };
36 template <>
struct SofaVecType<2> {
using Type = sofa::defaulttype::Vec2Types; };
37 template <>
struct SofaVecType<3> {
using Type = sofa::defaulttype::Vec3Types; };
39 template <
typename GaussNode, INTEGER_TYPE NumberOfGaussNodesAtCompileTime>
41 using Type = std::array<GaussNode, static_cast<std::size_t>(NumberOfGaussNodesAtCompileTime)>;
44 template <
typename GaussNode>
46 using Type = std::vector<GaussNode>;
49 template <
typename Element>
50 class HyperelasticForcefield :
public ForceField<typename SofaVecType<caribou::geometry::traits<Element>::Dimension>::Type> {
55 using DataTypes =
typename SofaVecType<caribou::geometry::traits<Element>::Dimension>::Type;
56 using Inherit = ForceField<DataTypes>;
57 using VecCoord =
typename DataTypes::VecCoord;
58 using VecDeriv =
typename DataTypes::VecDeriv;
59 using Coord =
typename DataTypes::Coord;
60 using Deriv =
typename DataTypes::Deriv;
61 using Real =
typename Coord::value_type;
63 using LocalCoordinates =
typename caribou::geometry::Element<Element>::LocalCoordinates;
64 using WorldCoordinates =
typename caribou::geometry::Element<Element>::WorldCoordinates;
70 template<
int nRows,
int nColumns>
73 template<
int nRows,
int nColumns,
int Options=0>
76 template<
int nRows,
int nColumns>
77 using Map = Eigen::Map<const Matrix<nRows, nColumns>>;
83 using MapVector = Eigen::Map<const Vector<nRows>>;
85 using Mat33 = Matrix<3, 3>;
86 using Vec3 = Vector<3>;
88 template <
typename ObjectType>
89 using Link = SingleLink<HyperelasticForcefield<Element>, ObjectType, BaseLink::FLAG_STRONGLINK>;
94 Real jacobian_determinant;
95 Matrix<NumberOfNodes, Dimension> dN_dx;
96 Mat33 F = Mat33::Identity();
100 using GaussContainer =
typename GaussContainer<GaussNode, NumberOfGaussNodes>::Type;
107 getTemplateName() const -> std::
string override {
108 return templateName(
this);
114 static auto canCreate(HyperelasticForcefield<Element>* o, BaseContext* context, BaseObjectDescription* arg) -> bool;
116 void init()
override;
119 const MechanicalParams* mparams,
121 const Data<VecCoord>& d_x,
122 const Data<VecDeriv>& d_v)
override;
125 const MechanicalParams* ,
127 const Data<VecDeriv>& )
override;
129 SReal getPotentialEnergy(
130 const MechanicalParams* ,
131 const Data<VecCoord>& )
const override;
133 void addKToMatrix(sofa::defaulttype::BaseMatrix * , SReal ,
unsigned int & )
override;
135 void computeBBox(
const sofa::core::ExecParams* params,
bool onlyVisible)
override;
137 void draw(
const sofa::core::visual::VisualParams* vparams)
override;
147 return p_elements_quadrature_nodes[element_id];
151 auto K() -> Eigen::SparseMatrix<Real> {
162 std::vector<Eigen::Triplet<Real>> triplets;
163 triplets.reserve(p_K.size()*2);
164 for (
int k = 0; k < p_K.outerSize(); ++k) {
165 for (
typename Eigen::SparseMatrix<Real>::InnerIterator it(p_K, k); it; ++it) {
166 const auto i = it.row();
167 const auto j = it.col();
168 const auto v = it.value();
170 triplets.emplace_back(i, j, v);
171 triplets.emplace_back(j, i, v);
173 triplets.emplace_back(i, i, v);
178 Eigen::SparseMatrix<Real> K;
179 K.resize(p_K.rows(), p_K.cols());
180 K.setFromTriplets(triplets.begin(), triplets.end());
186 auto eigenvalues() ->
const Vector<Eigen::Dynamic> &;
211 virtual auto get_element_nodes_indices(
const std::size_t &)
const ->
const sofa::Index * {
216 virtual void initialize_elements();
219 virtual void update_stiffness();
222 virtual auto get_gauss_nodes(
const std::size_t & element_id,
const Element & element)
const -> GaussContainer;
225 Link<sofa::core::topology::BaseMeshTopology> d_topology_container;
226 Link<material::HyperelasticMaterial<DataTypes>> d_material;
227 Data<bool> d_enable_multithreading;
228 Data<double> d_drawScale;
231 std::vector<GaussContainer> p_elements_quadrature_nodes;
232 Eigen::SparseMatrix<Real> p_K;
233 Eigen::Matrix<Real, Eigen::Dynamic, 1> p_eigenvalues;
234 bool K_is_up_to_date =
false;
235 bool eigenvalues_are_up_to_date =
false;
239 template <>
auto HyperelasticForcefield<caribou::geometry::Tetrahedron < caribou::Linear>>::number_of_elements() const -> std::
size_t;
240 template <> auto HyperelasticForcefield<caribou::geometry::Tetrahedron < caribou::Linear>>::mesh_is_compatible(const sofa::core::topology::BaseMeshTopology * topology) ->
bool;
241 template <> auto HyperelasticForcefield<caribou::geometry::Tetrahedron < caribou::Linear>>::get_element_nodes_indices(const std::
size_t & element_id) const -> const sofa::Index *;
242 template <> auto HyperelasticForcefield<caribou::geometry::Tetrahedron < caribou::Linear>>::templateName(const HyperelasticForcefield<caribou::geometry::Tetrahedron < caribou::Linear>> *) -> std::
string;
243 extern template class HyperelasticForcefield<caribou::geometry::Tetrahedron < caribou::Linear>>;
246 template <> auto HyperelasticForcefield<caribou::geometry::Hexahedron < caribou::Linear>>::number_of_elements() const -> std::
size_t;
247 template <> auto HyperelasticForcefield<caribou::geometry::Hexahedron < caribou::Linear>>::mesh_is_compatible(const sofa::core::topology::BaseMeshTopology * topology) ->
bool;
248 template <> auto HyperelasticForcefield<caribou::geometry::Hexahedron < caribou::Linear>>::get_element_nodes_indices(const std::
size_t & element_id) const -> const sofa::Index *;
249 template <> auto HyperelasticForcefield<caribou::geometry::Hexahedron < caribou::Linear>>::templateName(const HyperelasticForcefield<caribou::geometry::Hexahedron < caribou::Linear>> *) -> std::
string;
250 extern template class HyperelasticForcefield<caribou::geometry::Hexahedron < caribou::Linear>>;