From 51199394f00b2754c67e7332365ec78b4f6a22a8 Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Thu, 8 Sep 2022 14:28:43 +0200 Subject: [PATCH 1/3] [binding] Make Mass binding compatible with #2988 --- bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp index abee20b5..b9146b70 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp @@ -43,7 +43,7 @@ using sofa::core::behavior::Mass; template void declare_mass(py::module &m) { const std::string pyclass_name = std::string("Mass") + TDOFType::Name(); - py::class_, sofa::core::behavior::ForceField, py_shared_ptr>> f(m, pyclass_name.c_str(), sofapython3::doc::mass::massClass); + py::class_, py_shared_ptr>> f(m, pyclass_name.c_str(), sofapython3::doc::mass::massClass); using Real = typename TDOFType::Real; using EigenSparseMatrix = Eigen::SparseMatrix; From 3beda6ac9b32a86298e8e503c573b8206b203c93 Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Fri, 9 Sep 2022 17:49:55 +0200 Subject: [PATCH 2/3] update the binding of Mass further to new inheritance, no more FF --- .../SofaPython3/Sofa/Core/Binding_Mass.cpp | 61 ++++++++++++++++++- .../src/SofaPython3/Sofa/Core/Binding_Mass.h | 23 ++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp index b9146b70..aa46a685 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp @@ -31,24 +31,83 @@ #include #include +#include +using sofapython3::PythonEnvironment; /// Makes an alias for the pybind11 namespace to increase readability. namespace py { using namespace pybind11; } +/// To bring in the `_a` literal +using namespace pybind11::literals; namespace sofapython3 { using sofa::core::behavior::Mass; +template +Mass_Trampoline::Mass_Trampoline() = default; + +template +Mass_Trampoline::~Mass_Trampoline() = default; + +template +std::string Mass_Trampoline::getClassName() const +{ + PythonEnvironment::gil acquire {"getClassName"}; + + // Get the actual class name from python. + return py::str(py::cast(this).get_type().attr("__name__")); +} + +template +void Mass_Trampoline::init() +{ + Mass::init(); + + PythonEnvironment::gil acquire; + + if (!mstate.get()) + mstate.set(dynamic_cast< sofa::core::behavior::MechanicalState* >(getContext()->getMechanicalState())); + + if(!mstate.get()) + throw py::type_error("Missing mechanical state."); + + PYBIND11_OVERLOAD(void, Mass, init,); +} + template void declare_mass(py::module &m) { const std::string pyclass_name = std::string("Mass") + TDOFType::Name(); - py::class_, py_shared_ptr>> f(m, pyclass_name.c_str(), sofapython3::doc::mass::massClass); + py::class_, sofa::core::objectmodel::BaseObject, Mass_Trampoline, py_shared_ptr>> f(m, pyclass_name.c_str(), py::dynamic_attr(), py::multiple_inheritance(), sofapython3::doc::mass::massClass); using Real = typename TDOFType::Real; using EigenSparseMatrix = Eigen::SparseMatrix; using EigenMatrixMap = Eigen::Map; + f.def(py::init([](py::args &args, py::kwargs &kwargs) { + auto mass = sofa::core::sptr> (new Mass_Trampoline()); + + mass->f_listening.setValue(true); + + if (args.size() == 1) mass->setName(py::cast(args[0])); + + py::object cc = py::cast(mass); + for (auto kv : kwargs) { + std::string key = py::cast(kv.first); + py::object value = py::reinterpret_borrow(kv.second); + if (key == "name") { + if (args.size() != 0) { + throw py::type_error("The name is set twice as a " + "named argument='" + py::cast(value) + "' and as a" + "positional argument='" + + py::cast(args[0]) + "'."); + } + } + BindingBase::SetAttr(cc, key, value); + } + return mass; + })); + f.def("assembleMMatrix", [](Mass& self) -> EigenSparseMatrix { sofa::linearalgebra::CompressedRowSparseMatrix matrix; diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h index 826b78da..7d725f2c 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h @@ -20,10 +20,31 @@ #pragma once -#include +#include +#include +#include +#include namespace sofapython3 { +template +class Mass_Trampoline : public sofa::core::behavior::Mass { +public: + SOFA_CLASS(Mass_Trampoline, SOFA_TEMPLATE(sofa::core::behavior::Mass, TDOFType)); + using sofa::core::behavior::Mass::mstate; + using sofa::core::behavior::Mass::getContext; + using typename sofa::core::behavior::Mass::DataTypes; + using typename sofa::core::behavior::Mass::Coord; + using typename sofa::core::behavior::Mass::DataVecDeriv; + using typename sofa::core::behavior::Mass::DataVecCoord; + + Mass_Trampoline(); + ~Mass_Trampoline() override; + + std::string getClassName() const override; + void init() override; +}; + void moduleAddMass(pybind11::module &m); } /// namespace sofapython3 From 16f0ae816413a0fc366e5004d33063083efc9c17 Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Wed, 21 Sep 2022 11:36:46 +0200 Subject: [PATCH 3/3] add missing virtual pure function from Mass --- .../SofaPython3/Sofa/Core/Binding_Mass.cpp | 57 ++++++++++++++++--- .../src/SofaPython3/Sofa/Core/Binding_Mass.h | 8 ++- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp index aa46a685..b6ae245c 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp @@ -50,6 +50,24 @@ Mass_Trampoline::Mass_Trampoline() = default; template Mass_Trampoline::~Mass_Trampoline() = default; + +template +void Mass_Trampoline::init() +{ + Mass::init(); + + PythonEnvironment::gil acquire; + + if (!mstate.get()) + mstate.set(dynamic_cast< sofa::core::behavior::MechanicalState* >(getContext()->getMechanicalState())); + + if(!mstate.get()) + throw py::type_error("Missing mechanical state."); + + PYBIND11_OVERLOAD(void, Mass, init,); +} + + template std::string Mass_Trampoline::getClassName() const { @@ -59,22 +77,47 @@ std::string Mass_Trampoline::getClassName() const return py::str(py::cast(this).get_type().attr("__name__")); } + template -void Mass_Trampoline::init() +bool Mass_Trampoline::isDiagonal() const { - Mass::init(); + PythonEnvironment::gil acquire; + + PYBIND11_OVERLOAD_PURE(bool, Mass, isDiagonal); +} + +template +void Mass_Trampoline::addGravitationalForce( const sofa::core::MechanicalParams* mparams, DataVecDeriv& f, const DataVecCoord& x, const DataVecDeriv& v, const Deriv& gravity) +{ PythonEnvironment::gil acquire; - if (!mstate.get()) - mstate.set(dynamic_cast< sofa::core::behavior::MechanicalState* >(getContext()->getMechanicalState())); + // pass bFactor, kFactor, energy + py::dict mp = py::dict("time"_a=getContext()->getTime(), + "mFactor"_a=mparams->mFactor(), + "bFactor"_a=mparams->bFactor(), + "kFactor"_a=mparams->kFactor(), + "isImplicit"_a=mparams->implicit()); + PYBIND11_OVERLOAD_PURE(void, Mass, addGravitationalForce, mp, PythonFactory::toPython(&f), PythonFactory::toPython(&x), PythonFactory::toPython(&v), gravity); +} - if(!mstate.get()) - throw py::type_error("Missing mechanical state."); - PYBIND11_OVERLOAD(void, Mass, init,); +template +SReal Mass_Trampoline::getGravitationalPotentialEnergy( const sofa::core::MechanicalParams* mparams, const DataVecCoord& x, const Deriv& gravity) const +{ + PythonEnvironment::gil acquire; + + // pass bFactor, kFactor, energy + py::dict mp = py::dict("time"_a=getContext()->getTime(), + "mFactor"_a=mparams->mFactor(), + "bFactor"_a=mparams->bFactor(), + "kFactor"_a=mparams->kFactor(), + "isImplicit"_a=mparams->implicit(), + "energy"_a=mparams->energy()); + PYBIND11_OVERLOAD_PURE(SReal, Mass, getGravitationalPotentialEnergy, mp, PythonFactory::toPython(&x), gravity); } + template void declare_mass(py::module &m) { const std::string pyclass_name = std::string("Mass") + TDOFType::Name(); diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h index 7d725f2c..71a0fedb 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h @@ -35,14 +35,20 @@ class Mass_Trampoline : public sofa::core::behavior::Mass { using sofa::core::behavior::Mass::getContext; using typename sofa::core::behavior::Mass::DataTypes; using typename sofa::core::behavior::Mass::Coord; + using typename sofa::core::behavior::Mass::Deriv; using typename sofa::core::behavior::Mass::DataVecDeriv; using typename sofa::core::behavior::Mass::DataVecCoord; Mass_Trampoline(); ~Mass_Trampoline() override; - std::string getClassName() const override; void init() override; + std::string getClassName() const override; + + bool isDiagonal() const override; + + void addGravitationalForce( const sofa::core::MechanicalParams* mparams, DataVecDeriv& f, const DataVecCoord& x, const DataVecDeriv& v, const Deriv& gravity) override; + SReal getGravitationalPotentialEnergy( const sofa::core::MechanicalParams* mparams, const DataVecCoord& x, const Deriv& gravity) const override; }; void moduleAddMass(pybind11::module &m);