diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Types/Binding_CompressedRowSparseMatrix.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Types/Binding_CompressedRowSparseMatrix.cpp
new file mode 100644
index 00000000..62b337fd
--- /dev/null
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Types/Binding_CompressedRowSparseMatrix.cpp
@@ -0,0 +1,96 @@
+/******************************************************************************
+* SOFA, Simulation Open-Framework Architecture *
+* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU Lesser General Public License as published by *
+* the Free Software Foundation; either version 2.1 of the License, or (at *
+* your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
+* for more details. *
+* *
+* You should have received a copy of the GNU Lesser General Public License *
+* along with this program. If not, see . *
+*******************************************************************************
+* Contact information: contact@sofa-framework.org *
+******************************************************************************/
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+namespace py { using namespace pybind11; }
+
+namespace sofapython3
+{
+
+template
+typename sofa::linearalgebra::CompressedRowSparseMatrixToEigenSparseVec::EigenSparseMatrix
+toEigen(const sofa::linearalgebra::CompressedRowSparseMatrixConstraint& matrix)
+{
+ static sofa::linearalgebra::CompressedRowSparseMatrixToEigenSparseVec convert;
+ return convert(matrix);
+}
+
+template
+void bindCompressedRowSparseMatrixConstraint(pybind11::module& m)
+{
+ static_assert(sofa::type::trait::is_specialization_of_v,
+ "Template argument must be a specialization of CompressedRowSparseMatrixConstraint");
+
+ py::class_, sofa::core::objectmodel::BaseData,
+ std::unique_ptr, pybind11::nodelete> > crsmc(m, MatrixDeriv::Name() );
+
+ crsmc.def_property_readonly("value", [](sofa::Data& self)
+ {
+ sofa::helper::ReadAccessor accessor(self);
+ return toEigen(accessor.ref());
+ });
+
+ PythonFactory::registerType(MatrixDeriv::Name(), [](sofa::core::BaseData* data) -> py::object {
+ auto matrix = reinterpret_cast*>(data);
+ return py::cast(matrix);
+ });
+}
+
+/**
+ * Given a template parameter pack, create the bindings of all the templates in
+ * the pack, making sure that there are no duplicate types.
+ */
+template
+void bindAllCompressedRowSparseMatrixConstraintTypes(pybind11::module& m)
+{
+ static_assert(!(std::is_same_v || ...), "Error: Duplicate types found!");
+
+ bindCompressedRowSparseMatrixConstraint(m);
+ if constexpr (sizeof...(Args) > 0)
+ {
+ bindAllCompressedRowSparseMatrixConstraintTypes(m);
+ }
+}
+
+void moduleAddCompressedRowSparseMatrix(pybind11::module& m)
+{
+ using namespace sofa::defaulttype;
+
+ bindAllCompressedRowSparseMatrixConstraintTypes<
+ Vec1Types::MatrixDeriv,
+ Vec2Types::MatrixDeriv,
+ Vec3Types::MatrixDeriv,
+ Vec6Types::MatrixDeriv,
+ Rigid2Types::MatrixDeriv,
+ Rigid3Types::MatrixDeriv
+ >(m);
+}
+
+}
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Types/Binding_CompressedRowSparseMatrix.h b/bindings/Sofa/src/SofaPython3/Sofa/Types/Binding_CompressedRowSparseMatrix.h
new file mode 100644
index 00000000..13eeb571
--- /dev/null
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Types/Binding_CompressedRowSparseMatrix.h
@@ -0,0 +1,29 @@
+/******************************************************************************
+* SOFA, Simulation Open-Framework Architecture *
+* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU Lesser General Public License as published by *
+* the Free Software Foundation; either version 2.1 of the License, or (at *
+* your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
+* for more details. *
+* *
+* You should have received a copy of the GNU Lesser General Public License *
+* along with this program. If not, see . *
+*******************************************************************************
+* Contact information: contact@sofa-framework.org *
+******************************************************************************/
+
+#pragma once
+
+#include
+
+namespace sofapython3 {
+
+void moduleAddCompressedRowSparseMatrix(pybind11::module& m);
+
+} // namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Types/CMakeLists.txt b/bindings/Sofa/src/SofaPython3/Sofa/Types/CMakeLists.txt
index d741b52a..0c279a51 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Types/CMakeLists.txt
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Types/CMakeLists.txt
@@ -2,10 +2,12 @@ project(Bindings.Sofa.Types)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BoundingBox.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/Binding_CompressedRowSparseMatrix.h
)
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Submodule_Types.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Binding_CompressedRowSparseMatrix.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BoundingBox.cpp
)
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Types/Submodule_Types.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Types/Submodule_Types.cpp
index 86324bc3..be65bed8 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Types/Submodule_Types.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Types/Submodule_Types.cpp
@@ -22,6 +22,8 @@
#include
#include
+#include
+
namespace sofapython3 {
/// The first parameter must be named the same as the module file to load.
@@ -42,6 +44,7 @@ PYBIND11_MODULE(Types, types)
)doc";
moduleAddBoundingBox(types);
+ moduleAddCompressedRowSparseMatrix(types);
}
} // namespace sofapython3
diff --git a/examples/access_constraint_matrix.py b/examples/access_constraint_matrix.py
new file mode 100644
index 00000000..e8caae07
--- /dev/null
+++ b/examples/access_constraint_matrix.py
@@ -0,0 +1,66 @@
+# Required import for python
+import Sofa
+import SofaRuntime
+import numpy as np
+
+
+# Function called when the scene graph is being created
+def createScene(root):
+ root.addObject("RequiredPlugin", pluginName=["Sofa.Component.AnimationLoop",
+ "Sofa.Component.Constraint.Lagrangian.Correction",
+ "Sofa.Component.Constraint.Lagrangian.Model",
+ "Sofa.Component.Constraint.Lagrangian.Solver",
+ "Sofa.Component.Constraint.Projective",
+ "Sofa.Component.IO.Mesh",
+ "Sofa.Component.LinearSolver.Direct",
+ "Sofa.Component.Mapping.MappedMatrix",
+ "Sofa.Component.Mass",
+ "Sofa.Component.ODESolver.Backward",
+ "Sofa.Component.Topology.Container.Dynamic",
+ "Sofa.Component.Mapping.NonLinear",
+ "Sofa.Component.StateContainer"
+ ])
+
+ root.addObject("FreeMotionAnimationLoop", solveVelocityConstraintFirst=True)
+ root.addObject("GenericConstraintSolver", tolerance=1e-9, maxIterations=1000)
+ root.addObject("StringMeshCreator", name="loader", resolution="20")
+
+ root.addObject("EulerImplicitSolver")
+ root.addObject("EigenSimplicialLLT", template='CompressedRowSparseMatrixMat3x3d')
+ root.addObject("GenericConstraintCorrection")
+
+ root.addObject("EdgeSetTopologyContainer", name="topo", position="@loader.position", edges="@loader.edges")
+ mechanical_object = root.addObject("MechanicalObject", name="defoDOF", template="Vec3d")
+ root.addObject("EdgeSetGeometryAlgorithms", drawEdges=True)
+ root.addObject("FixedProjectiveConstraint", indices=[0])
+ root.addObject("MeshMatrixMass", name="mass", totalMass="1e-3", lumping=True)
+
+ ext = root.addChild("extensionsNode")
+ ext.addObject("MechanicalObject", template="Vec1d", name="extensionsDOF")
+ ext.addObject("DistanceMapping", name="distanceMapping", topology="@topo")
+ ext.addObject("UniformLagrangianConstraint", template="Vec1d", iterative=True)
+
+ root.addObject(MatrixAccessController('MatrixAccessor', name='matrixAccessor', mechanical_object=mechanical_object))
+
+
+class MatrixAccessController(Sofa.Core.Controller):
+
+ def __init__(self, *args, **kwargs):
+ Sofa.Core.Controller.__init__(self, *args, **kwargs)
+ self.mechanical_object = kwargs.get("mechanical_object")
+
+ def onBuildConstraintSystemEndEvent(self, event):
+ constraint_matrix = self.mechanical_object.constraint.value
+
+ print(self.mechanical_object.constraint.linkpath)
+
+ print('====================================')
+ print('Constraint matrix in constraint space')
+ print('====================================')
+ print('dtype: ' + str(constraint_matrix.dtype))
+ print('shape: ' + str(constraint_matrix.shape))
+ print('ndim: ' + str(constraint_matrix.ndim))
+
+ print(constraint_matrix)
+
+