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;
@@ -177,10 +180,10 @@ namespace sofapython3
177180
178181
179182 template <class TDOFType >
180- void declare_forcefield (py::module &m, std::string typestr ) {
181- std::string pyclass_name = std::string (" ForceField" ) + typestr ;
183+ void declare_forcefield (py::module &m) {
184+ const std::string pyclass_name = std::string (" ForceField" ) + TDOFType::Name () ;
182185 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-
186+
184187 f.def (py::init ([](py::args &args, py::kwargs &kwargs) {
185188 auto ff = sofa::core::sptr<ForceField_Trampoline<TDOFType>> (new ForceField_Trampoline<TDOFType>());
186189
@@ -204,15 +207,50 @@ namespace sofapython3
204207 }
205208 return ff;
206209 }));
210+
211+ using Real = typename TDOFType::Real;
212+ using EigenSparseMatrix = Eigen::SparseMatrix<typename TDOFType::Real, Eigen::RowMajor>;
213+ using EigenMatrixMap = Eigen::Map<EigenSparseMatrix>;
214+
215+ f.def (" assembleKMatrix" , [](ForceField<TDOFType>& self) -> EigenSparseMatrix
216+ {
217+ sofa::linearalgebra::CompressedRowSparseMatrix<Real> matrix;
218+
219+ if (const auto * mstate = self.getMState ())
220+ {
221+ const auto matrixSize = static_cast <sofa::linearalgebra::BaseMatrix::Index>(mstate->getMatrixSize ());
222+ matrix.resize (matrixSize, matrixSize);
223+
224+ sofa::core::behavior::DefaultMultiMatrixAccessor accessor;
225+ accessor.addMechanicalState (mstate);
226+ accessor.setGlobalMatrix (&matrix);
227+
228+ auto mparams = *MechanicalParams::defaultInstance ();
229+ mparams.setKFactor (1 .).setMFactor (0 .).setBFactor (0 .);
230+
231+ self.addKToMatrix (&mparams, &accessor);
232+ }
233+ matrix.compress ();
234+
235+ return EigenMatrixMap (matrix.rows (), matrix.cols (), matrix.getColsValue ().size (),
236+ (typename EigenMatrixMap::StorageIndex*)matrix.rowBegin .data (),
237+ (typename EigenMatrixMap::StorageIndex*)matrix.colsIndex .data (),
238+ matrix.colsValue .data ());
239+ }, sofapython3::doc::forceField::assembleKMatrix);
240+
241+ PythonFactory::registerType<ForceField<TDOFType>>([](sofa::core::objectmodel::Base* object)
242+ {
243+ return py::cast (dynamic_cast <ForceField<TDOFType>*>(object));
244+ });
207245 }
208246
209247
210248void 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 " );
249+ declare_forcefield<Vec3dTypes>(m);
250+ declare_forcefield<Vec2dTypes>(m);
251+ declare_forcefield<Vec1dTypes>(m);
252+ declare_forcefield<Rigid3dTypes>(m);
253+ declare_forcefield<Rigid2dTypes>(m);
216254}
217255
218256} // namespace sofapython3
0 commit comments