Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[binding] Make Mass binding compatible with #2988 #305

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 103 additions & 1 deletion bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,126 @@
#include <sofa/linearalgebra/CompressedRowSparseMatrix.h>

#include <pybind11/eigen.h>
#include <SofaPython3/PythonEnvironment.h>
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<class TDOFType>
Mass_Trampoline<TDOFType>::Mass_Trampoline() = default;

template<class TDOFType>
Mass_Trampoline<TDOFType>::~Mass_Trampoline() = default;


template<class TDOFType>
void Mass_Trampoline<TDOFType>::init()
{
Mass<TDOFType>::init();

PythonEnvironment::gil acquire;

if (!mstate.get())
mstate.set(dynamic_cast< sofa::core::behavior::MechanicalState<DataTypes>* >(getContext()->getMechanicalState()));

if(!mstate.get())
throw py::type_error("Missing mechanical state.");

PYBIND11_OVERLOAD(void, Mass<TDOFType>, init,);
}


template<class TDOFType>
std::string Mass_Trampoline<TDOFType>::getClassName() const
{
PythonEnvironment::gil acquire {"getClassName"};

// Get the actual class name from python.
return py::str(py::cast(this).get_type().attr("__name__"));
}


template<class TDOFType>
bool Mass_Trampoline<TDOFType>::isDiagonal() const
{
PythonEnvironment::gil acquire;

PYBIND11_OVERLOAD_PURE(bool, Mass<TDOFType>, isDiagonal);
}


template<class TDOFType>
void Mass_Trampoline<TDOFType>::addGravitationalForce( const sofa::core::MechanicalParams* mparams, DataVecDeriv& f, const DataVecCoord& x, const DataVecDeriv& v, const Deriv& gravity)
{
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());
PYBIND11_OVERLOAD_PURE(void, Mass<TDOFType>, addGravitationalForce, mp, PythonFactory::toPython(&f), PythonFactory::toPython(&x), PythonFactory::toPython(&v), gravity);
}


template<class TDOFType>
SReal Mass_Trampoline<TDOFType>::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<TDOFType>, getGravitationalPotentialEnergy, mp, PythonFactory::toPython(&x), gravity);
}


template<class TDOFType>
void declare_mass(py::module &m) {
const std::string pyclass_name = std::string("Mass") + TDOFType::Name();
py::class_<Mass<TDOFType>, sofa::core::behavior::ForceField<TDOFType>, py_shared_ptr<Mass<TDOFType>>> f(m, pyclass_name.c_str(), py::multiple_inheritance(), sofapython3::doc::mass::massClass);
py::class_<Mass<TDOFType>, sofa::core::objectmodel::BaseObject, Mass_Trampoline<TDOFType>, py_shared_ptr<Mass<TDOFType>>> 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<typename TDOFType::Real, Eigen::RowMajor>;
using EigenMatrixMap = Eigen::Map<EigenSparseMatrix>;

f.def(py::init([](py::args &args, py::kwargs &kwargs) {
auto mass = sofa::core::sptr<Mass_Trampoline<TDOFType>> (new Mass_Trampoline<TDOFType>());

mass->f_listening.setValue(true);

if (args.size() == 1) mass->setName(py::cast<std::string>(args[0]));

py::object cc = py::cast(mass);
for (auto kv : kwargs) {
std::string key = py::cast<std::string>(kv.first);
py::object value = py::reinterpret_borrow<py::object>(kv.second);
if (key == "name") {
if (args.size() != 0) {
throw py::type_error("The name is set twice as a "
"named argument='" + py::cast<std::string>(value) + "' and as a"
"positional argument='" +
py::cast<std::string>(args[0]) + "'.");
}
}
BindingBase::SetAttr(cc, key, value);
}
return mass;
}));

f.def("assembleMMatrix", [](Mass<TDOFType>& self) -> EigenSparseMatrix
{
sofa::linearalgebra::CompressedRowSparseMatrix<Real> matrix;
Expand Down
29 changes: 28 additions & 1 deletion bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,37 @@

#pragma once

#include <pybind11/pybind11.h>
#include <sofa/core/behavior/BaseMass.h>
#include <sofa/core/behavior/Mass.h>
#include <sofa/defaulttype/VecTypes.h>
#include <sofa/core/MechanicalParams.h>

namespace sofapython3 {

template<class TDOFType>
class Mass_Trampoline : public sofa::core::behavior::Mass<TDOFType> {
public:
SOFA_CLASS(Mass_Trampoline, SOFA_TEMPLATE(sofa::core::behavior::Mass, TDOFType));
using sofa::core::behavior::Mass<TDOFType>::mstate;
using sofa::core::behavior::Mass<TDOFType>::getContext;
using typename sofa::core::behavior::Mass<TDOFType>::DataTypes;
using typename sofa::core::behavior::Mass<TDOFType>::Coord;
using typename sofa::core::behavior::Mass<TDOFType>::Deriv;
using typename sofa::core::behavior::Mass<TDOFType>::DataVecDeriv;
using typename sofa::core::behavior::Mass<TDOFType>::DataVecCoord;

Mass_Trampoline();
~Mass_Trampoline() 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);

} /// namespace sofapython3