From 09aa513d9b76dae973e28f4a72c083c245eb60e4 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Wed, 2 Sep 2026 14:09:26 +0200 Subject: [PATCH 1/6] explicit position vector in getPotentialEnergy --- .../fem/elastic/HexahedronFEMForceFieldAndMass.h | 9 ++------- .../tensormass/TetrahedralTensorMassForceField.h | 7 +------ .../tensormass/TetrahedralTensorMassForceField.inl | 4 +--- .../Core/src/sofa/core/behavior/BaseForceField.cpp | 5 +++++ .../Core/src/sofa/core/behavior/BaseForceField.h | 11 +++++++---- .../Core/src/sofa/core/behavior/ForceField.h | 2 +- .../Core/src/sofa/core/behavior/ForceField.inl | 7 +++++-- Sofa/framework/Core/src/sofa/core/behavior/Mass.h | 3 ++- Sofa/framework/Core/src/sofa/core/behavior/Mass.inl | 7 +++++-- .../sofa/core/behavior/MixedInteractionForceField.h | 2 +- .../sofa/core/behavior/MixedInteractionForceField.inl | 8 ++++++-- .../sofa/core/behavior/PairInteractionForceField.h | 2 +- .../sofa/core/behavior/PairInteractionForceField.inl | 8 ++++++-- Sofa/framework/Simulation/Core/test/Visitor_test.cpp | 4 ++-- 14 files changed, 45 insertions(+), 34 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceFieldAndMass.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceFieldAndMass.h index d6e8b1531a1..ae9160a0161 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceFieldAndMass.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceFieldAndMass.h @@ -97,14 +97,9 @@ class HexahedronFEMForceFieldAndMass : virtual public core::behavior::Mass::initNeighbourhoodPoints() {} template -SReal TetrahedralTensorMassForceField::getPotentialEnergy(const core::MechanicalParams* /* mparams */) const +SReal TetrahedralTensorMassForceField::getPotentialEnergy(const core::MechanicalParams* /* mparams */, const DataVecCoord& x) const { SCOPED_TIMER("getPotentialEnergy"); - const VecCoord& x = this->mstate->read(core::vec_id::read_access::position)->getValue(); - SReal energy=0; unsigned int v0,v1; diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp index 2d7a2781d1c..c57c243fada 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp @@ -46,6 +46,11 @@ void BaseForceField::addMBKdx(const MechanicalParams* mparams, MultiVecDerivId d } } +SReal BaseForceField::getPotentialEnergy(const MechanicalParams* mparams) const +{ + return this->getPotentialEnergy(mparams, mparams->x()); +} + void BaseForceField::addBToMatrix(const MechanicalParams* /*mparams*/, const sofa::core::behavior::MultiMatrixAccessor* /*matrix*/) { } diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h index 76c2fc2361b..81eabecf85a 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h @@ -134,10 +134,13 @@ class SOFA_CORE_API BaseForceField : public virtual StateAccessor /// \brief Get the potential energy associated to this ForceField during the /// last call of addForce( const MechanicalParams* mparams ); - /// - /// Used to estimate the total energy of the system by some - /// post-stabilization techniques. - virtual SReal getPotentialEnergy( const MechanicalParams* mparams = mechanicalparams::defaultInstance() ) const=0; + /// \note Used to estimate the total energy of the system by some post-stabilization techniques. + /// \param mparams + /// \param xId The potential energy is evaluated on this vector of generalized coordinates + virtual SReal getPotentialEnergy(const MechanicalParams* mparams, + ConstMultiVecCoordId xId) const = 0; + + virtual SReal getPotentialEnergy( const MechanicalParams* mparams = mechanicalparams::defaultInstance() ) const final; /// @} diff --git a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h index 91e87c4abeb..28f2fc84d2c 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h @@ -116,7 +116,7 @@ class ForceField : public BaseForceField, public virtual SingleStateAccessor::addDForce(const MechanicalParams* mparams, MultiVecD } template -SReal ForceField::getPotentialEnergy(const MechanicalParams* mparams) const +SReal ForceField::getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const { if (this->mstate) - return getPotentialEnergy(mparams, *mparams->readX(this->mstate.get())); + { + const DataVecCoord* x = xId[this->mstate.get()].read(); assert(x); + return getPotentialEnergy(mparams, *x); + } return 0; } diff --git a/Sofa/framework/Core/src/sofa/core/behavior/Mass.h b/Sofa/framework/Core/src/sofa/core/behavior/Mass.h index 1dec7f93119..1cad0f8dc71 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/Mass.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/Mass.h @@ -103,8 +103,9 @@ class Mass : virtual public ForceField, public BaseMass /// /// This method retrieves the positions vector and call the internal /// getPotentialEnergy(const MechanicalParams*, const VecCoord&) method implemented by the component. - SReal getPotentialEnergy( const MechanicalParams* mparams) const override; + SReal getPotentialEnergy( const MechanicalParams* mparams, ConstMultiVecCoordId xId) const override; SReal getPotentialEnergy( const MechanicalParams* mparams, const DataVecCoord& x ) const override; + using BaseForceField::getPotentialEnergy; /// $ m = ( Mv, cross(x,Mv)+Iw ) $ diff --git a/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl b/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl index 78041353ccc..6f79afc33d0 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl @@ -120,10 +120,13 @@ SReal Mass::getKineticEnergy(const MechanicalParams* /*mparams*/, con template -SReal Mass::getPotentialEnergy(const MechanicalParams* mparams) const +SReal Mass::getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const { if (this->mstate) - return getPotentialEnergy(mparams /* PARAMS FIRST */, *mparams->readX(this->mstate.get())); + { + const DataVecCoord* x = xId[this->mstate.get()].read(); assert(x); + return getPotentialEnergy(mparams, *x); + } return 0.0; } diff --git a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h index 4dc05954b5f..ffb8d2f6b7e 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h @@ -106,7 +106,7 @@ class MixedInteractionForceField : public BaseInteractionForceField, public Pair /// This method retrieves the x vector from the MechanicalState and call /// the internal getPotentialEnergy(const VecCoord&,const VecCoord&) method implemented by /// the component. - SReal getPotentialEnergy(const MechanicalParams* mparams) const override; + SReal getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const override; /// Given the current position and velocity states, update the current force /// vector by computing and adding the forces associated with this diff --git a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl index 8cbd487f143..23deb40be80 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl @@ -73,10 +73,14 @@ void MixedInteractionForceField::addDForce(const Mechani template -SReal MixedInteractionForceField::getPotentialEnergy(const MechanicalParams* mparams) const +SReal MixedInteractionForceField::getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const { if (this->mstate1 && this->mstate2) - return getPotentialEnergy(mparams, *mparams->readX(this->mstate1.get()),*mparams->readX(this->mstate2.get())); + { + const DataVecCoord1* x1 = xId[this->mstate1.get()].read(); assert(x1); + const DataVecCoord2* x2 = xId[this->mstate2.get()].read(); assert(x2); + return getPotentialEnergy(mparams, *x1, *x2); + } else return 0; } diff --git a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h index 20db861a697..a16a976b39a 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h @@ -138,7 +138,7 @@ class PairInteractionForceField : public BaseInteractionForceField, public PairS /// This method retrieves the x vector from the MechanicalState and call /// the internal getPotentialEnergy(const VecCoord&,const VecCoord&) method implemented by /// the component. - SReal getPotentialEnergy(const MechanicalParams* mparams) const override; + SReal getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const override; /// Get the potential energy associated to this ForceField. /// diff --git a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl index 61e666c2e87..9fe6c973e85 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl @@ -76,12 +76,16 @@ void PairInteractionForceField::addDForce(const MechanicalParams* mpa } template -SReal PairInteractionForceField::getPotentialEnergy(const MechanicalParams* mparams) const +SReal PairInteractionForceField::getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const { auto state1 = this->mstate1.get(); auto state2 = this->mstate2.get(); if (state1 && state2) - return getPotentialEnergy(mparams, *mparams->readX(state1),*mparams->readX(state2)); + { + const DataVecCoord* x1 = xId[state1].read(); assert(x1); + const DataVecCoord* x2 = xId[state2].read(); assert(x2); + return getPotentialEnergy(mparams, *x1, *x2); + } else return 0.0; } diff --git a/Sofa/framework/Simulation/Core/test/Visitor_test.cpp b/Sofa/framework/Simulation/Core/test/Visitor_test.cpp index 3954dc81256..d6b24a0219e 100644 --- a/Sofa/framework/Simulation/Core/test/Visitor_test.cpp +++ b/Sofa/framework/Simulation/Core/test/Visitor_test.cpp @@ -90,7 +90,7 @@ class TestForceField : public core::behavior::BaseForceField public: void addForce(const core::MechanicalParams* mparams, core::MultiVecDerivId fId) override {} void addDForce(const core::MechanicalParams* mparams, core::MultiVecDerivId dfId) override {} - SReal getPotentialEnergy(const core::MechanicalParams* mparams) const override { return {}; } + SReal getPotentialEnergy(const core::MechanicalParams* mparams, core::ConstMultiVecCoordId dxId) const override { return {}; } void addKToMatrix(const core::MechanicalParams* mparams, const sofa::core::behavior::MultiMatrixAccessor* matrix) override {} }; @@ -116,7 +116,7 @@ class TestInteractionForceField : public core::behavior::BaseInteractionForceFie public: void addForce(const core::MechanicalParams* mparams, core::MultiVecDerivId fId) override {} void addDForce(const core::MechanicalParams* mparams, core::MultiVecDerivId dfId) override {} - SReal getPotentialEnergy(const core::MechanicalParams* mparams) const override { return {}; } + SReal getPotentialEnergy(const core::MechanicalParams* mparams, core::ConstMultiVecCoordId) const override { return {}; } }; class TestMapping : public core::BaseMapping From be296912ab6d3a4f7d56dd6f8a9bdd3d19ae1bbc Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Wed, 2 Sep 2026 14:12:21 +0200 Subject: [PATCH 2/6] deprecate the old overload --- .../Core/src/sofa/core/behavior/BaseForceField.h | 1 + Sofa/framework/Core/src/sofa/core/config.h.in | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h index 81eabecf85a..cbfaf614375 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h @@ -140,6 +140,7 @@ class SOFA_CORE_API BaseForceField : public virtual StateAccessor virtual SReal getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const = 0; + SOFA_ATTRIBUTE_DEPRECATED__GETPOTENTIALENERGY_OVERLOAD() virtual SReal getPotentialEnergy( const MechanicalParams* mparams = mechanicalparams::defaultInstance() ) const final; /// @} diff --git a/Sofa/framework/Core/src/sofa/core/config.h.in b/Sofa/framework/Core/src/sofa/core/config.h.in index 616e0e3ede1..fc857c72bf4 100644 --- a/Sofa/framework/Core/src/sofa/core/config.h.in +++ b/Sofa/framework/Core/src/sofa/core/config.h.in @@ -133,4 +133,11 @@ SOFA_ATTRIBUTE_DEPRECATED("v26.06", "v29.06", "Use toBaseComponent instead.") #else #define SOFA_CORE_DEPRECATED_REMOVE_CONTEXT() \ SOFA_ATTRIBUTE_DISABLED("v26.12", "v27.12", "Use BaseContext instead of Context.") -#endif \ No newline at end of file +#endif + +#ifdef SOFA_BUILD_SOFA_CORE +#define SOFA_ATTRIBUTE_DEPRECATED__GETPOTENTIALENERGY_OVERLOAD() +#else +#define SOFA_ATTRIBUTE_DEPRECATED__GETPOTENTIALENERGY_OVERLOAD() \ + SOFA_ATTRIBUTE_DEPRECATED("v26.12", "v27.06", "getPotentialEnergy must be called by providing the position vector.") +#endif From ae5caa8fa109ccf32665d071d241c5583a705f00 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Wed, 2 Sep 2026 14:33:27 +0200 Subject: [PATCH 3/6] explicit the x vector at the call sites --- .../backward/VariationalSymplecticSolver.cpp | 0 .../framework/Core/src/sofa/core/behavior/Mass.inl | 12 ++++++++---- .../src/sofa/simulation/MechanicalOperations.cpp | 12 +++++++++--- .../src/sofa/simulation/MechanicalOperations.h | 2 ++ .../Core/src/sofa/simulation/config.h.in | 14 ++++++++++++++ .../MechanicalComputeEnergyVisitor.cpp | 11 ++++++++--- .../MechanicalComputeEnergyVisitor.h | 8 ++++++-- 7 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 Sofa/Component/ODESolver/Backward/src/sofa/component/odesolver/backward/VariationalSymplecticSolver.cpp diff --git a/Sofa/Component/ODESolver/Backward/src/sofa/component/odesolver/backward/VariationalSymplecticSolver.cpp b/Sofa/Component/ODESolver/Backward/src/sofa/component/odesolver/backward/VariationalSymplecticSolver.cpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl b/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl index 6f79afc33d0..eb4b291243b 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl @@ -220,10 +220,14 @@ void Mass::exportGnuplot(const MechanicalParams* mparams, SReal time) { if (m_gnuplotFileEnergy!=nullptr) { - (*m_gnuplotFileEnergy) << time <<"\t"<< this->getKineticEnergy(mparams) - <<"\t"<< this->getPotentialEnergy(mparams) - <<"\t"<< this->getPotentialEnergy(mparams) - +this->getKineticEnergy(mparams)<< std::endl; + assert(mparams); + auto xId = mparams->x(); + const auto kineticEnergy = this->getKineticEnergy(mparams); + const auto potentialEnergy = this->getPotentialEnergy(mparams, xId); + (*m_gnuplotFileEnergy) << time <<"\t"<< kineticEnergy + <<"\t"<< potentialEnergy + <<"\t"<< potentialEnergy + +kineticEnergy<< std::endl; } } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp index d6c0e0b020d..7bc1df15508 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp @@ -194,16 +194,22 @@ void MechanicalOperations::projectPosition(core::MultiVecCoordId x, SReal time) executeVisitor( MechanicalProjectPositionVisitor(&mparams, time, x) ); } -/// Apply projective constraints to the given velocity vector -void MechanicalOperations::computeEnergy(SReal &kineticEnergy, SReal &potentialEnergy) +void MechanicalOperations::computeEnergy(core::ConstMultiVecCoordId xId, + SReal& kineticEnergy, SReal& potentialEnergy) { kineticEnergy = 0; potentialEnergy = 0; - MechanicalComputeEnergyVisitor energyVisitor(&mparams); + MechanicalComputeEnergyVisitor energyVisitor(&mparams, xId); executeVisitor(&energyVisitor); kineticEnergy = energyVisitor.getKineticEnergy(); potentialEnergy = energyVisitor.getPotentialEnergy(); } + +void MechanicalOperations::computeEnergy(SReal &kineticEnergy, SReal &potentialEnergy) +{ + computeEnergy(mparams.x(), kineticEnergy, potentialEnergy); +} + /// Apply projective constraints to the given velocity vector void MechanicalOperations::projectVelocity(core::MultiVecDerivId v, SReal time) { diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h index be3e21be8ef..c0ac6434d51 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h @@ -77,6 +77,8 @@ class SOFA_SIMULATION_CORE_API MechanicalOperations void integrateVelocity(core::MultiVecDerivId res, core::ConstMultiVecCoordId x, core::ConstMultiVecDerivId v, SReal dt); ///< res = x + v.dt void accFromF(core::MultiVecDerivId a, core::ConstMultiVecDerivId f); ///< a = M^-1 . f /// Compute Energy + void computeEnergy(core::ConstMultiVecCoordId xId, SReal &kineticEnergy, SReal &potentialEnergy); + SOFA_ATTRIBUTE_DEPRECATED__COMPUTEENERGY_OVERLOAD() void computeEnergy(SReal &kineticEnergy, SReal &potentialEnergy); /// Compute the current force (given the latest propagated position and velocity) void computeForce(core::MultiVecDerivId result, bool clear = true, bool accumulate = true); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/config.h.in b/Sofa/framework/Simulation/Core/src/sofa/simulation/config.h.in index 2fc18d1225a..8f4907cb202 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/config.h.in +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/config.h.in @@ -221,3 +221,17 @@ #define SOFA_ATTRIBUTE_DEPRECATED__MECHANICALOPERATIONS_PRINTWITHELAPSEDTIME() \ SOFA_ATTRIBUTE_DISABLED("v26.12", "v27.06", "This method is unused.") #endif + +#ifdef SOFA_BUILD_SOFA_SIMULATION_CORE +#define SOFA_ATTRIBUTE_DEPRECATED__MECHANICALCOMPUTEENERGYVISITOR_CONSTRUCTOR_OVERLOAD() +#else +#define SOFA_ATTRIBUTE_DEPRECATED__MECHANICALCOMPUTEENERGYVISITOR_CONSTRUCTOR_OVERLOAD() \ + SOFA_ATTRIBUTE_DISABLED("v26.12", "v27.06", "Constructor must be used by providing the x vector.") +#endif + +#ifdef SOFA_BUILD_SOFA_SIMULATION_CORE +#define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEENERGY_OVERLOAD() +#else +#define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEENERGY_OVERLOAD() \ + SOFA_ATTRIBUTE_DISABLED("v26.12", "v27.06", "computeEnergy must be used by providing the x vector.") +#endif diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeEnergyVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeEnergyVisitor.cpp index 4659d4e9d98..218b6e5e28a 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeEnergyVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeEnergyVisitor.cpp @@ -29,11 +29,16 @@ namespace sofa::simulation::mechanicalvisitor MechanicalComputeEnergyVisitor::MechanicalComputeEnergyVisitor(const sofa::core::MechanicalParams* mparams) : sofa::simulation::MechanicalVisitor(mparams) - , m_kineticEnergy(0.) - , m_potentialEnergy(0.) { + assert(mparams); + m_xId = mparams->x(); } +MechanicalComputeEnergyVisitor::MechanicalComputeEnergyVisitor( + const sofa::core::MechanicalParams* mparams, core::ConstMultiVecCoordId xId) + : sofa::simulation::MechanicalVisitor(mparams) + , m_xId(xId) +{} MechanicalComputeEnergyVisitor::~MechanicalComputeEnergyVisitor() { @@ -59,7 +64,7 @@ Visitor::Result MechanicalComputeEnergyVisitor::fwdMass(simulation::Node* /*node /// Process the BaseForceField Visitor::Result MechanicalComputeEnergyVisitor::fwdForceField(simulation::Node* /*node*/, sofa::core::behavior::BaseForceField* f) { - m_potentialEnergy += (SReal)f->getPotentialEnergy(); + m_potentialEnergy += (SReal)f->getPotentialEnergy(mparams, m_xId); return RESULT_CONTINUE; } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeEnergyVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeEnergyVisitor.h index 4820c18dad2..1d15585b0c8 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeEnergyVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeEnergyVisitor.h @@ -35,12 +35,16 @@ Compute the amount of mechanical energy */ class SOFA_SIMULATION_CORE_API MechanicalComputeEnergyVisitor : public sofa::simulation::MechanicalVisitor { - SReal m_kineticEnergy; - SReal m_potentialEnergy; + SReal m_kineticEnergy {}; + SReal m_potentialEnergy {}; + core::ConstMultiVecCoordId m_xId; public: + SOFA_ATTRIBUTE_DEPRECATED__MECHANICALCOMPUTEENERGYVISITOR_CONSTRUCTOR_OVERLOAD() MechanicalComputeEnergyVisitor(const sofa::core::MechanicalParams* mparams); + MechanicalComputeEnergyVisitor(const sofa::core::MechanicalParams* mparams, core::ConstMultiVecCoordId xId); + ~MechanicalComputeEnergyVisitor() override; SReal getKineticEnergy(); From 2b35c12395005809c89fffed13749b901b649e2d Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 25 Sep 2026 14:10:40 +0200 Subject: [PATCH 4/6] remove redundant override --- Sofa/framework/Core/src/sofa/core/behavior/Mass.h | 5 ----- Sofa/framework/Core/src/sofa/core/behavior/Mass.inl | 12 ------------ 2 files changed, 17 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/Mass.h b/Sofa/framework/Core/src/sofa/core/behavior/Mass.h index 1cad0f8dc71..6f512951dea 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/Mass.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/Mass.h @@ -99,11 +99,6 @@ class Mass : virtual public ForceField, public BaseMass SReal getKineticEnergy( const MechanicalParams* mparams) const override; virtual SReal getKineticEnergy( const MechanicalParams* mparams, const DataVecDeriv& v) const; - /// $ e = M g x $ - /// - /// This method retrieves the positions vector and call the internal - /// getPotentialEnergy(const MechanicalParams*, const VecCoord&) method implemented by the component. - SReal getPotentialEnergy( const MechanicalParams* mparams, ConstMultiVecCoordId xId) const override; SReal getPotentialEnergy( const MechanicalParams* mparams, const DataVecCoord& x ) const override; using BaseForceField::getPotentialEnergy; diff --git a/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl b/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl index eb4b291243b..af7659392ba 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/Mass.inl @@ -118,18 +118,6 @@ SReal Mass::getKineticEnergy(const MechanicalParams* /*mparams*/, con return 0.0; } - -template -SReal Mass::getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const -{ - if (this->mstate) - { - const DataVecCoord* x = xId[this->mstate.get()].read(); assert(x); - return getPotentialEnergy(mparams, *x); - } - return 0.0; -} - template SReal Mass::getPotentialEnergy(const MechanicalParams* /*mparams*/, const DataVecCoord& /*x*/) const { From e1abc77b7b29cd7f94b81806945b5721c5f91f32 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 25 Sep 2026 14:13:33 +0200 Subject: [PATCH 5/6] fix TetrahedralTensorMassForceField --- .../TetrahedralTensorMassForceField.inl | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Sofa/Component/SolidMechanics/TensorMass/src/sofa/component/solidmechanics/tensormass/TetrahedralTensorMassForceField.inl b/Sofa/Component/SolidMechanics/TensorMass/src/sofa/component/solidmechanics/tensormass/TetrahedralTensorMassForceField.inl index f16a196fb86..92f0410f321 100644 --- a/Sofa/Component/SolidMechanics/TensorMass/src/sofa/component/solidmechanics/tensormass/TetrahedralTensorMassForceField.inl +++ b/Sofa/Component/SolidMechanics/TensorMass/src/sofa/component/solidmechanics/tensormass/TetrahedralTensorMassForceField.inl @@ -224,7 +224,7 @@ void TetrahedralTensorMassForceField::applyTetrahedronDestruction(con } -template +template TetrahedralTensorMassForceField::TetrahedralTensorMassForceField() : _initialPoints(0) , updateMatrix(true) @@ -238,12 +238,12 @@ TetrahedralTensorMassForceField::TetrahedralTensorMassForceField() { } -template +template TetrahedralTensorMassForceField::~TetrahedralTensorMassForceField() { } -template void +template void TetrahedralTensorMassForceField::init() { this->Inherited::init(); @@ -353,25 +353,23 @@ SReal TetrahedralTensorMassForceField::getPotentialEnergy(const core: Deriv force,dp; Deriv dp0,dp1; - for(int i=0; igetEdge(i)[0]; - v1=m_topology->getEdge(i)[1]; - dp0=x[v0]-_initialPoints[v0]; - dp1=x[v1]-_initialPoints[v1]; - dp = dp1-dp0; - force=einfo->DfDx*dp; - energy+=dot(force,dp1); - force=einfo->DfDx.multTranspose(dp); - energy-=dot(force,dp0); + einfo = &edgeInf[i]; + v0 = m_topology->getEdge(i)[0]; + v1 = m_topology->getEdge(i)[1]; + dp0 = xAccessor[v0] - _initialPoints[v0]; + dp1 = xAccessor[v1] - _initialPoints[v1]; + dp = dp1 - dp0; + force = einfo->DfDx * dp; + energy += dot(force, dp1); + force = einfo->DfDx.multTranspose(dp); + energy -= dot(force, dp0); } - energy/=-2.0; - - msg_info() << "energy="< From 31e974e9c9bad69ff7078ff641fc7fcda8a46fd5 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 25 Sep 2026 14:48:18 +0200 Subject: [PATCH 6/6] fix compilation --- Sofa/framework/Core/src/sofa/core/behavior/BaseMass.cpp | 5 +++++ Sofa/framework/Core/src/sofa/core/behavior/BaseMass.h | 5 ++++- Sofa/framework/Core/src/sofa/core/behavior/ForceField.h | 2 +- Sofa/framework/Core/src/sofa/core/behavior/Mass.h | 1 + .../Core/src/sofa/core/behavior/PairInteractionForceField.h | 1 + Sofa/framework/Simulation/Core/test/Visitor_test.cpp | 2 +- 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseMass.cpp b/Sofa/framework/Core/src/sofa/core/behavior/BaseMass.cpp index 340ee5a4ae9..2260fef9f02 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseMass.cpp +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseMass.cpp @@ -49,6 +49,11 @@ bool BaseMass::removeInNode( objectmodel::BaseNode* node ) return true; } +SReal BaseMass::getPotentialEnergy(const MechanicalParams* mparams) const +{ + return this->getPotentialEnergy(mparams, mparams->x()); +} + void BaseMass::buildMassMatrix(sofa::core::behavior::MassMatrixAccumulator* matrices) { static std::set hasEmittedWarning; diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseMass.h b/Sofa/framework/Core/src/sofa/core/behavior/BaseMass.h index d2e28de59b5..258622f10d5 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseMass.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseMass.h @@ -72,7 +72,10 @@ class SOFA_CORE_API BaseMass : public virtual StateAccessor /// vMv/2 virtual SReal getKineticEnergy(const MechanicalParams* mparams = mechanicalparams::defaultInstance()) const = 0; /// Mgx - virtual SReal getPotentialEnergy(const MechanicalParams* mparams = mechanicalparams::defaultInstance()) const = 0; + virtual SReal getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const = 0; + + SOFA_ATTRIBUTE_DEPRECATED__GETPOTENTIALENERGY_OVERLOAD() + virtual SReal getPotentialEnergy(const MechanicalParams* mparams = mechanicalparams::defaultInstance()) const final; /// (Mv,xMv+Iw) (linear and angular momenta against world origin) virtual type::Vec6 getMomentum(const MechanicalParams* mparams = mechanicalparams::defaultInstance()) const = 0; diff --git a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h index 28f2fc84d2c..963588e1fac 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h @@ -119,7 +119,7 @@ class ForceField : public BaseForceField, public virtual SingleStateAccessor, public BaseMass SReal getKineticEnergy( const MechanicalParams* mparams) const override; virtual SReal getKineticEnergy( const MechanicalParams* mparams, const DataVecDeriv& v) const; + SReal getPotentialEnergy( const MechanicalParams* mparams, ConstMultiVecCoordId x) const override { return ForceField::getPotentialEnergy(mparams, x); } SReal getPotentialEnergy( const MechanicalParams* mparams, const DataVecCoord& x ) const override; using BaseForceField::getPotentialEnergy; diff --git a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h index a16a976b39a..d31faa14bcb 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h @@ -139,6 +139,7 @@ class PairInteractionForceField : public BaseInteractionForceField, public PairS /// the internal getPotentialEnergy(const VecCoord&,const VecCoord&) method implemented by /// the component. SReal getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const override; + using BaseForceField::getPotentialEnergy; /// Get the potential energy associated to this ForceField. /// diff --git a/Sofa/framework/Simulation/Core/test/Visitor_test.cpp b/Sofa/framework/Simulation/Core/test/Visitor_test.cpp index d6b24a0219e..99a32cac9a0 100644 --- a/Sofa/framework/Simulation/Core/test/Visitor_test.cpp +++ b/Sofa/framework/Simulation/Core/test/Visitor_test.cpp @@ -101,7 +101,7 @@ class TestMass : public core::behavior::BaseMass void accFromF(const core::MechanicalParams* mparams, core::MultiVecDerivId aid) override {} void addGravityToV(const core::MechanicalParams* mparams, core::MultiVecDerivId vid) override {} SReal getKineticEnergy(const core::MechanicalParams* mparams) const override { return {}; } - SReal getPotentialEnergy(const core::MechanicalParams* mparams) const override { return {}; } + SReal getPotentialEnergy(const core::MechanicalParams* mparams, core::ConstMultiVecCoordId x) const override { return {}; } type::Vec6 getMomentum(const core::MechanicalParams* mparams) const override { return {}; } void addMToMatrix(const core::MechanicalParams* mparams, const sofa::core::behavior::MultiMatrixAccessor* matrix) override {} void initGnuplot(const std::string path) override {}