2828#include < sofa/core/behavior/MechanicalState.h>
2929#include < sofa/core/behavior/ForceField.h>
3030#include < sofa/core/MechanicalParams.h>
31- #include < sofa/core/behavior/MultiMatrixAccessor.h>
31+ #include < sofa/core/behavior/DefaultMultiMatrixAccessor.h>
32+ #include < sofa/linearalgebra/CompressedRowSparseMatrix.h>
33+
34+ #include < pybind11/eigen.h>
3235
3336#include < SofaPython3/PythonEnvironment.h>
3437using sofapython3::PythonEnvironment;
@@ -49,6 +52,7 @@ namespace sofapython3
4952 using sofa::defaulttype::Vec3dTypes;
5053 using sofa::defaulttype::Vec2dTypes;
5154 using sofa::defaulttype::Vec1dTypes;
55+ using sofa::defaulttype::Vec6dTypes;
5256 using sofa::defaulttype::Rigid3dTypes;
5357 using sofa::defaulttype::Rigid2dTypes;
5458
@@ -177,10 +181,10 @@ namespace sofapython3
177181
178182
179183 template <class TDOFType >
180- void declare_forcefield (py::module &m, std::string typestr ) {
181- std::string pyclass_name = std::string (" ForceField" ) + typestr ;
184+ void declare_forcefield (py::module &m) {
185+ const std::string pyclass_name = std::string (" ForceField" ) + TDOFType::Name () ;
182186 py::class_<ForceField<TDOFType>, BaseObject, ForceField_Trampoline<TDOFType>, py_shared_ptr<ForceField<TDOFType>>> f (m, pyclass_name.c_str (), py::dynamic_attr (), py::multiple_inheritance (), sofapython3::doc::forceField::forceFieldClass);
183-
187+
184188 f.def (py::init ([](py::args &args, py::kwargs &kwargs) {
185189 auto ff = sofa::core::sptr<ForceField_Trampoline<TDOFType>> (new ForceField_Trampoline<TDOFType>());
186190
@@ -204,15 +208,54 @@ namespace sofapython3
204208 }
205209 return ff;
206210 }));
211+
212+ using Real = typename TDOFType::Real;
213+ using EigenSparseMatrix = Eigen::SparseMatrix<typename TDOFType::Real, Eigen::RowMajor>;
214+ using EigenMatrixMap = Eigen::Map<EigenSparseMatrix>;
215+
216+ f.def (" assembleKMatrix" , [](ForceField<TDOFType>& self) -> EigenSparseMatrix
217+ {
218+ sofa::linearalgebra::CompressedRowSparseMatrix<Real> matrix;
219+
220+ if (const auto * mstate = self.getMState ())
221+ {
222+ const auto matrixSize = static_cast <sofa::linearalgebra::BaseMatrix::Index>(mstate->getMatrixSize ());
223+ matrix.resize (matrixSize, matrixSize);
224+
225+ sofa::core::behavior::DefaultMultiMatrixAccessor accessor;
226+ accessor.addMechanicalState (mstate);
227+ accessor.setGlobalMatrix (&matrix);
228+
229+ auto mparams = *MechanicalParams::defaultInstance ();
230+ mparams.setKFactor (1 .).setMFactor (0 .).setBFactor (0 .);
231+
232+ self.addKToMatrix (&mparams, &accessor);
233+ }
234+ matrix.compress ();
235+
236+ if (matrix.getColsValue ().empty () || matrix.rowBegin .empty () || matrix.colsIndex .empty ())
237+ return {};
238+
239+ return EigenMatrixMap (matrix.rows (), matrix.cols (), matrix.getColsValue ().size (),
240+ (typename EigenMatrixMap::StorageIndex*)matrix.rowBegin .data (),
241+ (typename EigenMatrixMap::StorageIndex*)matrix.colsIndex .data (),
242+ matrix.colsValue .data ());
243+ }, sofapython3::doc::forceField::assembleKMatrix);
244+
245+ PythonFactory::registerType<ForceField<TDOFType>>([](sofa::core::objectmodel::Base* object)
246+ {
247+ return py::cast (dynamic_cast <ForceField<TDOFType>*>(object));
248+ });
207249 }
208250
209251
210252void moduleAddForceField (py::module &m) {
211- declare_forcefield<Vec3dTypes>(m, " Vec3d" );
212- declare_forcefield<Vec2dTypes>(m, " Vec2d" );
213- declare_forcefield<Vec1dTypes>(m, " Vec1d" );
214- declare_forcefield<Rigid3dTypes>(m, " Rigid3d" );
215- declare_forcefield<Rigid2dTypes>(m, " Rigid2d" );
253+ declare_forcefield<Vec3dTypes>(m);
254+ declare_forcefield<Vec2dTypes>(m);
255+ declare_forcefield<Vec1dTypes>(m);
256+ declare_forcefield<Vec6dTypes>(m);
257+ declare_forcefield<Rigid3dTypes>(m);
258+ declare_forcefield<Rigid2dTypes>(m);
216259}
217260
218261} // namespace sofapython3
0 commit comments