From d3086c1a24d14ff1159a5798e89681aef1d2304f Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 31 Aug 2026 10:53:50 +0200 Subject: [PATCH 01/15] [Core] Explicit dx vector in `addDForce` --- .../Core/src/sofa/core/behavior/BaseForceField.h | 5 +++-- .../Core/src/sofa/core/behavior/ForceField.h | 3 ++- .../Core/src/sofa/core/behavior/ForceField.inl | 7 +++++-- .../core/behavior/MixedInteractionForceField.h | 3 ++- .../core/behavior/MixedInteractionForceField.inl | 13 +++++++++---- .../sofa/core/behavior/PairInteractionForceField.h | 3 ++- .../core/behavior/PairInteractionForceField.inl | 14 +++++++++----- 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h index b6dcfc1938e..f4a7c90b199 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h @@ -106,9 +106,10 @@ class SOFA_CORE_API BaseForceField : public virtual StateAccessor /// \param mparams /// - \a mparams->mFactor() is the coefficient for mass contributions (i.e. second-order derivatives term in the ODE) /// - \a mparams->kFactor() is the coefficient for stiffness contributions (i.e. DOFs term in the ODE) - /// - \a mparams->readDx() input vector /// \param dfId the output vector - virtual void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId )=0; + /// \param dxId the dx input vector + virtual void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, + ConstMultiVecDerivId dxId = ConstMultiVecDerivId(vec_id::read_access::dx) )=0; /// \brief Accumulate the contribution of M, B, and/or K matrices multiplied /// by the dx vector with the given coefficients. diff --git a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h index 7c598c1547a..0164155cf72 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h @@ -99,7 +99,8 @@ class ForceField : public BaseForceField, public virtual SingleStateAccessor::addForce(const MechanicalParams* mparams, MultiVecDe } template -void ForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId ) +void ForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) { if (mparams && this->mstate) { @@ -63,7 +63,10 @@ void ForceField::addDForce(const MechanicalParams* mparams, MultiVecD mparams->setKFactorUsed(false); #endif - addDForce(mparams, *dfId[this->mstate.get()].write(), *mparams->readDx(this->mstate.get())); + Data* df = dfId[this->mstate.get()].write(); assert(df); + const Data* dx = dxId[this->mstate.get()].read(); assert(dx); + + addDForce(mparams, *df, *dx); #ifndef NDEBUG if (!mparams->getKFactorUsed()) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h index 5017b486947..7c5377dc190 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h @@ -95,7 +95,8 @@ class MixedInteractionForceField : public BaseInteractionForceField, public Pair /// This method retrieves the force and dx vector from the two MechanicalState /// and call the internal addDForce(VecDeriv1&,VecDeriv2&,const VecDeriv1&,const VecDeriv2&,SReal,SReal) /// method implemented by the component. - void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId ) override; + void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, + ConstMultiVecDerivId dxId = ConstMultiVecDerivId(vec_id::read_access::dx)) override; /// Get the potential energy associated to this ForceField. diff --git a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl index a711daf4bae..981650a5e8e 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl @@ -60,15 +60,20 @@ void MixedInteractionForceField::addForce( } template -void MixedInteractionForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId ) +void MixedInteractionForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) { if (this->mstate1 && this->mstate2) { auto state1 = this->mstate1.get(); auto state2 = this->mstate2.get(); - addDForce( mparams, - *dfId[state1].write() , *dfId[state2].write() , - *mparams->readDx(state1) , *mparams->readDx(state2) ); + + Data* df1 = dfId[state1].write(); assert(df1); + Data* df2 = dfId[state2].write(); assert(df2); + + const Data* dx1 = dxId[state1].read(); assert(dx1); + const Data* dx2 = dxId[state2].read(); assert(dx2); + + addDForce(mparams, *df1, *df2, *dx1, *dx2); } } diff --git a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h index 1c7670e57c3..0b6dc117612 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h @@ -108,7 +108,8 @@ class PairInteractionForceField : public BaseInteractionForceField, public PairS /// This method retrieves the force and dx vector from the two MechanicalState /// and call the internal addDForce(VecDeriv&,VecDeriv&,const VecDeriv&,const VecDeriv&,SReal,SReal) /// method implemented by the component. - void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId ) override; + void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, + ConstMultiVecDerivId dxId = ConstMultiVecDerivId(vec_id::read_access::dx) ) override; /// Compute the force derivative given a small displacement from the /// position and velocity used in the previous call to addForce(). diff --git a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl index 0575440c3f3..463fe2ef92f 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl @@ -66,15 +66,19 @@ void PairInteractionForceField::addForce(const MechanicalParams* mpar } template -void PairInteractionForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId ) +void PairInteractionForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) { auto state1 = this->mstate1.get(); - auto state2 = this->mstate2.get(); + auto state2 = this->mstate2.get(); if (state1 && state2) { - addDForce( - mparams, *dfId[state1].write(), *dfId[state2].write(), - *mparams->readDx(state1), *mparams->readDx(state2)); + Data* df1 = dfId[state1].write(); assert(df1); + Data* df2 = dfId[state2].write(); assert(df2); + + const Data* dx1 = dxId[state1].read(); assert(dx1); + const Data* dx2 = dxId[state2].read(); assert(dx2); + + addDForce(mparams, *df1, *df2, *dx1, *dx2); } else msg_error() << "PairInteractionForceField::addDForce(const MechanicalParams* /*mparams*/, MultiVecDerivId /*fId*/ ), mstate missing"; From 3233db47ac7945d641de73c7bc25bce84fe52ba0 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 31 Aug 2026 11:01:36 +0200 Subject: [PATCH 02/15] explicit dx vector in addMBKdx --- Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp index 827d4bf05c1..8a601bcf5f8 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp @@ -48,7 +48,7 @@ void BaseForceField::addMBKdx(const MechanicalParams* mparams, MultiVecDerivId d if (kFactor != 0.0 || bFactor != 0.0) { - addDForce(mparams, dfId); + addDForce(mparams, dfId, ConstMultiVecDerivId(vec_id::read_access::dx)); } } From 3cbe42804d658e2601fe00b947e9cdd42fd043f5 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 31 Aug 2026 11:02:28 +0200 Subject: [PATCH 03/15] explicit dx vector in MechanicalComputeDfVisitor --- .../simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp index 8f8200fb06d..b6d6d9c0ca3 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp @@ -29,7 +29,7 @@ namespace sofa::simulation::mechanicalvisitor Visitor::Result MechanicalComputeDfVisitor::fwdForceField(simulation::Node* /*node*/, core::behavior::BaseForceField* ff) { - ff->addDForce(this->mparams, res); + ff->addDForce(this->mparams, res, core::ConstMultiVecDerivId(core::vec_id::read_access::dx)); return RESULT_CONTINUE; } From 0c0855aaa116f7e54ff4186b9c13f174b7f2f52d Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 31 Aug 2026 14:22:23 +0200 Subject: [PATCH 04/15] avoid ambiguity of an optional parameter --- .../Core/src/sofa/core/behavior/BaseForceField.cpp | 5 +++++ .../Core/src/sofa/core/behavior/BaseForceField.h | 13 +++++++++---- .../Core/src/sofa/core/behavior/ForceField.h | 3 +-- .../sofa/core/behavior/MixedInteractionForceField.h | 3 +-- .../sofa/core/behavior/PairInteractionForceField.h | 3 +-- Sofa/framework/Core/src/sofa/core/config.h.in | 7 +++++++ .../framework/Simulation/Core/test/Visitor_test.cpp | 4 ++-- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp index 8a601bcf5f8..a2740268ed4 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp @@ -41,6 +41,11 @@ void BaseForceField::addForce(const MechanicalParams* mparams, MultiVecDerivId f addForce(mparams, fId, mparams->x(), mparams->v()); } +void BaseForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) +{ + this->addDForce(mparams, dfId, ConstMultiVecDerivId(vec_id::read_access::dx)); +} + void BaseForceField::addMBKdx(const MechanicalParams* mparams, MultiVecDerivId dfId) { const auto kFactor = sofa::core::mechanicalparams::kFactorIncludingRayleighDamping(mparams,rayleighStiffness.getValue()); diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h index f4a7c90b199..2a2b5aa2945 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h @@ -104,12 +104,17 @@ class SOFA_CORE_API BaseForceField : public virtual StateAccessor /// and B is the damping matrix (associated with viscous forces). /// /// \param mparams - /// - \a mparams->mFactor() is the coefficient for mass contributions (i.e. second-order derivatives term in the ODE) - /// - \a mparams->kFactor() is the coefficient for stiffness contributions (i.e. DOFs term in the ODE) + /// - \a mparams->mFactor() is the coefficient for mass contributions (i.e. second-order + /// derivatives term in the ODE) + /// - \a mparams->kFactor() is the coefficient for stiffness contributions (i.e. DOFs term in + /// the ODE) /// \param dfId the output vector /// \param dxId the dx input vector - virtual void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, - ConstMultiVecDerivId dxId = ConstMultiVecDerivId(vec_id::read_access::dx) )=0; + virtual void addDForce(const MechanicalParams* mparams, + MultiVecDerivId dfId, ConstMultiVecDerivId dxId) = 0; + + virtual void SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_OVERLOAD() + addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) final; /// \brief Accumulate the contribution of M, B, and/or K matrices multiplied /// by the dx vector with the given coefficients. diff --git a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h index 0164155cf72..3edbb5f22af 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h @@ -99,8 +99,7 @@ class ForceField : public BaseForceField, public virtual SingleStateAccessor Date: Mon, 31 Aug 2026 14:46:26 +0200 Subject: [PATCH 05/15] explicit dx in visitor and MechanicalOperations --- .../src/sofa/core/behavior/BaseForceField.h | 4 ++-- .../sofa/simulation/MechanicalOperations.cpp | 20 +++++++------------ .../sofa/simulation/MechanicalOperations.h | 6 ++++-- .../Core/src/sofa/simulation/config.h.in | 14 +++++++++++++ .../MechanicalComputeDfVisitor.h | 20 +++++++++++++++---- 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h index 2a2b5aa2945..5151dc29826 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h @@ -113,8 +113,8 @@ class SOFA_CORE_API BaseForceField : public virtual StateAccessor virtual void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) = 0; - virtual void SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_OVERLOAD() - addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) final; + virtual SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_OVERLOAD() + void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) final; /// \brief Accumulate the contribution of M, B, and/or K matrices multiplied /// by the dx vector with the given coefficients. diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp index 79d700ab702..01ad1222f99 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp @@ -272,9 +272,12 @@ void MechanicalOperations::computeForce(core::MultiVecDerivId result, bool clear computeForce(result, mparams.x(), mparams.v(), clear, accumulate); } - -/// Compute the current force delta (given the latest propagated displacement) void MechanicalOperations::computeDf(core::MultiVecDerivId df, bool clear, bool accumulate) +{ + computeDf(df, sofa::core::vec_id::read_access::dx, clear, accumulate); +} + +void MechanicalOperations::computeDf(core::MultiVecDerivId df, core::ConstMultiVecDerivId dx, bool clear, bool accumulate) { setDf(df); if (clear) @@ -282,22 +285,13 @@ void MechanicalOperations::computeDf(core::MultiVecDerivId df, bool clear, bool executeVisitor( MechanicalResetForceVisitor(&mparams, df, false) ); // finish(); } - executeVisitor( MechanicalComputeDfVisitor( &mparams, df, accumulate) ); + executeVisitor( MechanicalComputeDfVisitor( &mparams, df, dx, accumulate) ); } /// Compute the current force delta (given the latest propagated velocity) void MechanicalOperations::computeDfV(core::MultiVecDerivId df, bool clear, bool accumulate) { - const core::ConstMultiVecDerivId dx = mparams.dx(); - mparams.setDx(mparams.v()); - setDf(df); - if (clear) - { - executeVisitor( MechanicalResetForceVisitor(&mparams, df, false) ); - //finish(); - } - executeVisitor( MechanicalComputeDfVisitor(&mparams, df, accumulate) ); - mparams.setDx(dx); + computeDf(df, mparams.v(), clear, accumulate); } /// accumulate $ df += (m M + b B + k K) dx $ (given the latest propagated displacement) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h index eebd1893dbb..b7ba8b49a19 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h @@ -90,9 +90,11 @@ class SOFA_SIMULATION_CORE_API MechanicalOperations bool clear = true, bool accumulate = true); SOFA_ATTRIBUTE_DEPRECATED__COMPUTEFORCE_OVERLOAD() void computeForce(core::MultiVecDerivId result, bool clear = true, bool accumulate = true); - /// Compute the current force delta (given the latest propagated displacement) + /// Compute the current force delta, (given the latest propagated displacement) SOFA_ATTRIBUTE_DEPRECATED__MECHANICALOPERATIONS_COMPUTEDF() - void computeDf(core::MultiVecDerivId df, bool clear = true, bool accumulate = true); + void SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDF_OVERLOAD() computeDf(core::MultiVecDerivId df, bool clear = true, bool accumulate = true); + /// Compute the current force delta, given the provided propagated displacement + void computeDf(core::MultiVecDerivId df, core::ConstMultiVecDerivId dx, bool clear = true, bool accumulate = true); /// Compute the current force delta (given the latest propagated velocity) SOFA_ATTRIBUTE_DEPRECATED__MECHANICALOPERATIONS_COMPUTEDFV() void computeDfV(core::MultiVecDerivId df, 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 27524378019..0d2b500be91 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/config.h.in +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/config.h.in @@ -284,3 +284,17 @@ #define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEENERGY_OVERLOAD() \ SOFA_ATTRIBUTE_DISABLED("v26.12", "v27.06", "computeEnergy must be used by providing the x vector.") #endif + +#ifdef SOFA_BUILD_SOFA_CORE +#define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDF_OVERLOAD() +#else +#define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDF_OVERLOAD() \ + SOFA_ATTRIBUTE_DEPRECATED("v26.12", "v27.06", "computeDf must be used by providing the dx vector.") +#endif + +#ifdef SOFA_BUILD_SOFA_CORE +#define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDFVISITOR_CONSTRUCTOR_OVERLOAD() +#else +#define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDFVISITOR_CONSTRUCTOR_OVERLOAD() \ + SOFA_ATTRIBUTE_DEPRECATED("v26.12", "v27.06", "Constructor must be used by providing the dx vector.") +#endif diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h index 0c0d9c588cb..d789fc6dc26 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h @@ -33,21 +33,33 @@ class SOFA_SIMULATION_CORE_API MechanicalComputeDfVisitor : public MechanicalVis { public: sofa::core::MultiVecDerivId res; + sofa::core::ConstMultiVecDerivId dx; bool accumulate; ///< Accumulate everything back to the DOFs through the mappings - MechanicalComputeDfVisitor(const sofa::core::MechanicalParams* mechaparams, sofa::core::MultiVecDerivId resvecid) - : MechanicalVisitor(mechaparams) , res(resvecid), accumulate(true) + + MechanicalComputeDfVisitor(const sofa::core::MechanicalParams* mechaparams, + sofa::core::MultiVecDerivId resvecid, + sofa::core::ConstMultiVecDerivId dxvecid, + bool bAccumulate = true + ) + : MechanicalVisitor(mechaparams) , res(resvecid), dx(dxvecid), accumulate(bAccumulate) { #ifdef SOFA_DUMP_VISITOR_INFO setReadWriteVectors(); #endif } - MechanicalComputeDfVisitor(const sofa::core::MechanicalParams* mechaparams, sofa::core::MultiVecDerivId resvecid, bool bAccumulate) - : MechanicalVisitor(mechaparams) , res(resvecid), accumulate(bAccumulate) + + SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDFVISITOR_CONSTRUCTOR_OVERLOAD() + MechanicalComputeDfVisitor(const sofa::core::MechanicalParams* mechaparams, + sofa::core::MultiVecDerivId resvecid, + bool bAccumulate = true + ) + : MechanicalVisitor(mechaparams) , res(resvecid), dx(sofa::core::vec_id::read_access::dx), accumulate(bAccumulate) { #ifdef SOFA_DUMP_VISITOR_INFO setReadWriteVectors(); #endif } + Result fwdForceField(simulation::Node* /*node*/,sofa::core::behavior::BaseForceField* ff) override; void bwdMechanicalMapping(simulation::Node* /*node*/, sofa::core::BaseMapping* map) override; From 5c10092f6ccdbef6f99078a9dfa74a7aebc85e15 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 31 Aug 2026 14:53:57 +0200 Subject: [PATCH 06/15] hope to fix --- Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h index 5151dc29826..8ff89f818da 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h @@ -113,8 +113,8 @@ class SOFA_CORE_API BaseForceField : public virtual StateAccessor virtual void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) = 0; - virtual SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_OVERLOAD() - void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) final; + SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_OVERLOAD() + virtual void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) final; /// \brief Accumulate the contribution of M, B, and/or K matrices multiplied /// by the dx vector with the given coefficients. From b5bcdb066571b57f6d4f1c0a9c31bcff47260f7d Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Wed, 2 Sep 2026 10:43:01 +0200 Subject: [PATCH 07/15] fix call to addDForce in MechanicalComputeDfVisitor --- .../simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp index b6d6d9c0ca3..8bfdf8acb03 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp @@ -29,7 +29,7 @@ namespace sofa::simulation::mechanicalvisitor Visitor::Result MechanicalComputeDfVisitor::fwdForceField(simulation::Node* /*node*/, core::behavior::BaseForceField* ff) { - ff->addDForce(this->mparams, res, core::ConstMultiVecDerivId(core::vec_id::read_access::dx)); + ff->addDForce(this->mparams, res, dx); return RESULT_CONTINUE; } From 1730843959344c62491966484595ba0b37b97601 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Wed, 2 Sep 2026 11:13:44 +0200 Subject: [PATCH 08/15] use dx from mparams instead of hard-coded --- Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp | 4 ++-- .../simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp index a2740268ed4..9a5faf02448 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp @@ -43,7 +43,7 @@ void BaseForceField::addForce(const MechanicalParams* mparams, MultiVecDerivId f void BaseForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) { - this->addDForce(mparams, dfId, ConstMultiVecDerivId(vec_id::read_access::dx)); + this->addDForce(mparams, dfId, mparams->dx()); } void BaseForceField::addMBKdx(const MechanicalParams* mparams, MultiVecDerivId dfId) @@ -53,7 +53,7 @@ void BaseForceField::addMBKdx(const MechanicalParams* mparams, MultiVecDerivId d if (kFactor != 0.0 || bFactor != 0.0) { - addDForce(mparams, dfId, ConstMultiVecDerivId(vec_id::read_access::dx)); + addDForce(mparams, dfId, mparams->dx()); } } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h index d789fc6dc26..dc326534499 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h @@ -53,7 +53,9 @@ class SOFA_SIMULATION_CORE_API MechanicalComputeDfVisitor : public MechanicalVis sofa::core::MultiVecDerivId resvecid, bool bAccumulate = true ) - : MechanicalVisitor(mechaparams) , res(resvecid), dx(sofa::core::vec_id::read_access::dx), accumulate(bAccumulate) + : MechanicalVisitor(mechaparams) , + res(resvecid), + dx(mechaparams ? mechaparams->dx() : core::vec_id::read_access::dx), accumulate(bAccumulate) { #ifdef SOFA_DUMP_VISITOR_INFO setReadWriteVectors(); From a1caf21961f19ec74ea3301f0b6757663456ac62 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Wed, 2 Sep 2026 11:55:57 +0200 Subject: [PATCH 09/15] add assert --- Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp index 9a5faf02448..43c7fbcbc23 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp @@ -43,6 +43,7 @@ void BaseForceField::addForce(const MechanicalParams* mparams, MultiVecDerivId f void BaseForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) { + assert(mparams); this->addDForce(mparams, dfId, mparams->dx()); } @@ -53,6 +54,7 @@ void BaseForceField::addMBKdx(const MechanicalParams* mparams, MultiVecDerivId d if (kFactor != 0.0 || bFactor != 0.0) { + assert(mparams); addDForce(mparams, dfId, mparams->dx()); } } From cb33871a9060f50fa289547e148ffebfa46d1168 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Tue, 8 Sep 2026 10:01:48 +0200 Subject: [PATCH 10/15] correct macro define --- .../framework/Simulation/Core/src/sofa/simulation/config.h.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 0d2b500be91..7628f788a00 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/config.h.in +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/config.h.in @@ -285,14 +285,14 @@ SOFA_ATTRIBUTE_DISABLED("v26.12", "v27.06", "computeEnergy must be used by providing the x vector.") #endif -#ifdef SOFA_BUILD_SOFA_CORE +#ifdef SOFA_BUILD_SOFA_SIMULATION_CORE #define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDF_OVERLOAD() #else #define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDF_OVERLOAD() \ SOFA_ATTRIBUTE_DEPRECATED("v26.12", "v27.06", "computeDf must be used by providing the dx vector.") #endif -#ifdef SOFA_BUILD_SOFA_CORE +#ifdef SOFA_BUILD_SOFA_SIMULATION_CORE #define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDFVISITOR_CONSTRUCTOR_OVERLOAD() #else #define SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDFVISITOR_CONSTRUCTOR_OVERLOAD() \ From 2a70032305ec39c2ea24666cf1f6c210ca902a51 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 11 Sep 2026 14:40:05 +0200 Subject: [PATCH 11/15] add x and v vectors --- .../src/sofa/core/behavior/BaseForceField.cpp | 4 +- .../src/sofa/core/behavior/BaseForceField.h | 11 ++++-- .../Core/src/sofa/core/behavior/ForceField.h | 28 +++++++++++++- .../src/sofa/core/behavior/ForceField.inl | 23 ++++++++++-- .../behavior/MixedInteractionForceField.h | 37 +++++++++++++++---- .../behavior/MixedInteractionForceField.inl | 32 ++++++++++++++-- .../core/behavior/PairInteractionForceField.h | 33 ++++++++++++++--- .../behavior/PairInteractionForceField.inl | 34 ++++++++++++++++- Sofa/framework/Core/src/sofa/core/config.h.in | 9 ++++- .../MechanicalComputeDfVisitor.cpp | 2 +- .../Simulation/Core/test/Visitor_test.cpp | 4 +- 11 files changed, 184 insertions(+), 33 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp index 43c7fbcbc23..e515819279f 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.cpp @@ -44,7 +44,7 @@ void BaseForceField::addForce(const MechanicalParams* mparams, MultiVecDerivId f void BaseForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) { assert(mparams); - this->addDForce(mparams, dfId, mparams->dx()); + this->addDForce(mparams, dfId, mparams->dx(), mparams->x(), mparams->v()); } void BaseForceField::addMBKdx(const MechanicalParams* mparams, MultiVecDerivId dfId) @@ -55,7 +55,7 @@ void BaseForceField::addMBKdx(const MechanicalParams* mparams, MultiVecDerivId d if (kFactor != 0.0 || bFactor != 0.0) { assert(mparams); - addDForce(mparams, dfId, mparams->dx()); + addDForce(mparams, dfId, mparams->dx(), mparams->x(), mparams->v()); } } diff --git a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h index 8ff89f818da..3eb13c9cf1f 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/BaseForceField.h @@ -98,7 +98,7 @@ class SOFA_CORE_API BaseForceField : public virtual StateAccessor /// /// If the ForceField can be represented as a matrix, this method computes /// \f[ - /// df += kFactor K dx + bFactor B dx + /// df += kFactor K(x) dx + bFactor B(v) dx /// \f] /// where K is the stiffness matrix (associated with forces which derive from a potential), /// and B is the damping matrix (associated with viscous forces). @@ -108,10 +108,13 @@ class SOFA_CORE_API BaseForceField : public virtual StateAccessor /// derivatives term in the ODE) /// - \a mparams->kFactor() is the coefficient for stiffness contributions (i.e. DOFs term in /// the ODE) - /// \param dfId the output vector - /// \param dxId the dx input vector + /// \param dfId the cotangent output vector + /// \param dxId the tangent input vector + /// \param xId the position input vector + /// \param vId the velocity input vector virtual void addDForce(const MechanicalParams* mparams, - MultiVecDerivId dfId, ConstMultiVecDerivId dxId) = 0; + MultiVecDerivId dfId, ConstMultiVecDerivId dxId, + ConstMultiVecCoordId xId, ConstMultiVecDerivId vId) = 0; SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_OVERLOAD() virtual void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId) final; diff --git a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h index 3edbb5f22af..ad72a53b27f 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/ForceField.h @@ -99,7 +99,8 @@ class ForceField : public BaseForceField, public virtual SingleStateAccessor::addForce(const MechanicalParams* mparams, MultiVecDe } template -void ForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) +void ForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, + ConstMultiVecDerivId dxId, ConstMultiVecCoordId xId, ConstMultiVecDerivId vId) { if (mparams && this->mstate) { @@ -65,8 +66,17 @@ void ForceField::addDForce(const MechanicalParams* mparams, MultiVecD Data* df = dfId[this->mstate.get()].write(); assert(df); const Data* dx = dxId[this->mstate.get()].read(); assert(dx); + const Data* x = xId[this->mstate.get()].read(); assert(x); + const Data* v = vId[this->mstate.get()].read(); assert(v); - addDForce(mparams, *df, *dx); + const AddDForceVectors vectors { + .df = *df, + .dx = *dx, + .x = *x, + .v = *v + }; + + doAddDForce(mparams, vectors); #ifndef NDEBUG if (!mparams->getKFactorUsed()) @@ -82,7 +92,14 @@ void ForceField::addDForce(const MechanicalParams* mparams, MultiVecD } } -template +template +void ForceField::doAddDForce(const MechanicalParams* mparams, const AddDForceVectors& vectors) +{ + // compatibility with legacy `addDForce`. + addDForce(mparams, vectors.df, vectors.dx); +} + +template SReal ForceField::getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const { if (this->mstate) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h index 4ba2e057db8..0faacaeebe3 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.h @@ -90,12 +90,9 @@ class MixedInteractionForceField : public BaseInteractionForceField, public Pair /// explicitly (i.e. using its value at the beginning of the timestep). /// /// If the ForceField can be represented as a matrix, this method computes - /// $ df += kFactor K dx + bFactor B dx $ - /// - /// This method retrieves the force and dx vector from the two MechanicalState - /// and call the internal addDForce(VecDeriv1&,VecDeriv2&,const VecDeriv1&,const VecDeriv2&,SReal,SReal) - /// method implemented by the component. - void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) override; + /// $ df += kFactor K(x) dx + bFactor B(v) dx $ + void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId, + ConstMultiVecCoordId xId, ConstMultiVecDerivId vId) override; /// Get the potential energy associated to this ForceField. @@ -132,7 +129,12 @@ class MixedInteractionForceField : public BaseInteractionForceField, public Pair /// /// This method must be implemented by the component, and is usually called /// by the generic MixedInteractionForceField::addDForce() method. - + /// + /// + /// ******************** WARNING ******************** + /// This overload is deprecated!!! Use `doAddDForce` instead. + /// + SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_DERIVED() virtual void addDForce(const MechanicalParams* mparams, DataVecDeriv1& df1, DataVecDeriv2& df2, const DataVecDeriv1& dx1, const DataVecDeriv2& dx2)=0; /// Get the potential energy associated to this ForceField. @@ -155,6 +157,27 @@ class MixedInteractionForceField : public BaseInteractionForceField, public Pair BaseMechanicalState* getMechModel1() override { return Inherit2::getMechModel1(); } BaseMechanicalState* getMechModel2() override { return Inherit2::getMechModel2(); } + +protected: + + // all vectors involved in the addDForce operation + template + struct AddDForceVectors + { + sofa::DataVecDeriv_t& df; + const sofa::DataVecDeriv_t& dx; + const sofa::DataVecCoord_t& x; + const sofa::DataVecDeriv_t& v; + }; + + // Computes df += kFactor K(x) dx + bFactor B(v) dx + // with: + // K the derivative of the forces wrt the position + // B the derivative of the forces wrt the velocity + virtual void doAddDForce(const MechanicalParams* mparams, + const AddDForceVectors& vectors1, + const AddDForceVectors& vectors2); + }; #if !defined(SOFA_CORE_BEHAVIOR_MIXEDINTERACTIONFORCEFIELD_CPP) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl index 981650a5e8e..7ed6c68490f 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/MixedInteractionForceField.inl @@ -60,7 +60,8 @@ void MixedInteractionForceField::addForce( } template -void MixedInteractionForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) +void MixedInteractionForceField::addDForce(const MechanicalParams* mparams, + MultiVecDerivId dfId, ConstMultiVecDerivId dxId, ConstMultiVecCoordId xId, ConstMultiVecDerivId vId) { if (this->mstate1 && this->mstate2) { @@ -73,11 +74,36 @@ void MixedInteractionForceField::addDForce(const Mechani const Data* dx1 = dxId[state1].read(); assert(dx1); const Data* dx2 = dxId[state2].read(); assert(dx2); - addDForce(mparams, *df1, *df2, *dx1, *dx2); + const Data* x1 = xId[state1].read(); assert(x1); + const Data* x2 = xId[state2].read(); assert(x2); + + const Data* v1 = vId[state1].read(); assert(v1); + const Data* v2 = vId[state2].read(); assert(v2); + + const AddDForceVectors vectors1 { + .df = *df1, + .dx = *dx1, + .x = *x1, + .v = *v1 + }; + + const AddDForceVectors vectors2 { + .df = *df2, + .dx = *dx2, + .x = *x2, + .v = *v2 + }; + + doAddDForce(mparams, vectors1, vectors2); } } - +template +void MixedInteractionForceField::doAddDForce( + const MechanicalParams* mparams, const AddDForceVectors& vectors1, + const AddDForceVectors& vectors2) +{ +} template SReal MixedInteractionForceField::getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const diff --git a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h index 9e16b162be7..75ef173266f 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h +++ b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.h @@ -103,12 +103,13 @@ class PairInteractionForceField : public BaseInteractionForceField, public PairS /// explicitly (i.e. using its value at the beginning of the timestep). /// /// If the ForceField can be represented as a matrix, this method computes - /// $ df += kFactor K dx + bFactor B dx $ + /// $ df += kFactor K(x) dx + bFactor B(v) dx $ /// /// This method retrieves the force and dx vector from the two MechanicalState /// and call the internal addDForce(VecDeriv&,VecDeriv&,const VecDeriv&,const VecDeriv&,SReal,SReal) /// method implemented by the component. - void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) override; + void addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId, + ConstMultiVecCoordId xId, ConstMultiVecDerivId vId) override; /// Compute the force derivative given a small displacement from the /// position and velocity used in the previous call to addForce(). @@ -123,10 +124,12 @@ class PairInteractionForceField : public BaseInteractionForceField, public PairS /// This method must be implemented by the component, and is usually called /// by the generic PairInteractionForceField::addDForce() method. /// - /// To support old components that implement the deprecated addForce method - /// without scalar coefficients, it defaults to using a temporaty vector to - /// compute $ K dx $ and then manually scaling all values by kFactor. - + /// + /// + /// ******************** WARNING ******************** + /// This overload is deprecated!!! Use `doAddDForce` instead. + /// + SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_DERIVED() virtual void addDForce(const MechanicalParams* mparams, DataVecDeriv& df1, DataVecDeriv& df2, const DataVecDeriv& dx1, const DataVecDeriv& dx2)=0; @@ -219,6 +222,24 @@ class PairInteractionForceField : public BaseInteractionForceField, public PairS return name; } +protected: + + // all vectors involved in the addDForce operation + struct AddDForceVectors + { + DataVecDeriv& df; + const DataVecDeriv& dx; + const DataVecCoord& x; + const DataVecDeriv& v; + }; + + // Computes df += kFactor K(x) dx + bFactor B(v) dx + // with: + // K the derivative of the forces wrt the position + // B the derivative of the forces wrt the velocity + virtual void doAddDForce(const MechanicalParams* mparams, + const AddDForceVectors& vectors1, const AddDForceVectors& vectors2); + }; #if !defined(SOFA_CORE_BEHAVIOR_PAIRINTERACTIONFORCEFIELD_CPP) diff --git a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl index 463fe2ef92f..4d035da2e72 100644 --- a/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl +++ b/Sofa/framework/Core/src/sofa/core/behavior/PairInteractionForceField.inl @@ -66,7 +66,8 @@ void PairInteractionForceField::addForce(const MechanicalParams* mpar } template -void PairInteractionForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, ConstMultiVecDerivId dxId) +void PairInteractionForceField::addDForce(const MechanicalParams* mparams, MultiVecDerivId dfId, + ConstMultiVecDerivId dxId, ConstMultiVecCoordId xId, ConstMultiVecDerivId vId) { auto state1 = this->mstate1.get(); auto state2 = this->mstate2.get(); @@ -78,12 +79,41 @@ void PairInteractionForceField::addDForce(const MechanicalParams* mpa const Data* dx1 = dxId[state1].read(); assert(dx1); const Data* dx2 = dxId[state2].read(); assert(dx2); - addDForce(mparams, *df1, *df2, *dx1, *dx2); + const Data* x1 = xId[state1].read(); assert(x1); + const Data* x2 = xId[state2].read(); assert(x2); + + const Data* v1 = vId[state1].read(); assert(v1); + const Data* v2 = vId[state2].read(); assert(v2); + + const AddDForceVectors vectors1 { + .df = *df1, + .dx = *dx1, + .x = *x1, + .v = *v1 + }; + + const AddDForceVectors vectors2 { + .df = *df2, + .dx = *dx2, + .x = *x2, + .v = *v2 + }; + + doAddDForce(mparams, vectors1, vectors2); } else msg_error() << "PairInteractionForceField::addDForce(const MechanicalParams* /*mparams*/, MultiVecDerivId /*fId*/ ), mstate missing"; } +template +void PairInteractionForceField::doAddDForce(const MechanicalParams* mparams, + const AddDForceVectors& vectors1, + const AddDForceVectors& vectors2) +{ + // compatibility with legacy `addDForce`. + addDForce(mparams, vectors1.df, vectors2.df, vectors1.dx, vectors2.dx); +} + template SReal PairInteractionForceField::getPotentialEnergy(const MechanicalParams* mparams, ConstMultiVecCoordId xId) const { diff --git a/Sofa/framework/Core/src/sofa/core/config.h.in b/Sofa/framework/Core/src/sofa/core/config.h.in index 56c27cff0ee..fcb20cef9f8 100644 --- a/Sofa/framework/Core/src/sofa/core/config.h.in +++ b/Sofa/framework/Core/src/sofa/core/config.h.in @@ -151,5 +151,12 @@ SOFA_ATTRIBUTE_DEPRECATED("v26.12", "v27.12", "Use BaseContext instead of Contex #define SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_OVERLOAD() #else #define SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_OVERLOAD() \ - SOFA_ATTRIBUTE_DEPRECATED("v26.12", "v27.06", "addDForce must be used by providing the dx vector.") + SOFA_ATTRIBUTE_DEPRECATED("v26.12", "v27.06", "addDForce must be used by providing the dx, x and v vectors.") +#endif + +#ifdef SOFA_BUILD_SOFA_CORE +#define SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_DERIVED() +#else +#define SOFA_ATTRIBUTE_DEPRECATED__ADDDFORCE_DERIVED() \ + SOFA_ATTRIBUTE_DEPRECATED("v26.12", "v27.06", "Use doAddDForce instead.") #endif diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp index 8bfdf8acb03..831f96b85d2 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp @@ -29,7 +29,7 @@ namespace sofa::simulation::mechanicalvisitor Visitor::Result MechanicalComputeDfVisitor::fwdForceField(simulation::Node* /*node*/, core::behavior::BaseForceField* ff) { - ff->addDForce(this->mparams, res, dx); + ff->addDForce(this->mparams, res, dx, this->mparams->x(), this->mparams->v()); return RESULT_CONTINUE; } diff --git a/Sofa/framework/Simulation/Core/test/Visitor_test.cpp b/Sofa/framework/Simulation/Core/test/Visitor_test.cpp index 6377d8ee0c2..75c4da6cd4c 100644 --- a/Sofa/framework/Simulation/Core/test/Visitor_test.cpp +++ b/Sofa/framework/Simulation/Core/test/Visitor_test.cpp @@ -95,7 +95,7 @@ class TestForceField : public core::behavior::BaseForceField SOFA_UNUSED(mparams); SOFA_UNUSED(fId); } - void addDForce(const core::MechanicalParams* mparams, core::MultiVecDerivId dfId, core::ConstMultiVecDerivId dxId) override + void addDForce(const core::MechanicalParams*, core::MultiVecDerivId, core::ConstMultiVecDerivId, core::ConstMultiVecCoordId, core::ConstMultiVecDerivId) override { SOFA_UNUSED(mparams); SOFA_UNUSED(dfId); @@ -181,7 +181,7 @@ class TestInteractionForceField : public core::behavior::BaseInteractionForceFie SOFA_UNUSED(mparams); SOFA_UNUSED(fId); } - void addDForce(const core::MechanicalParams* mparams, core::MultiVecDerivId dfId, core::ConstMultiVecDerivId dxId) override + void addDForce(const core::MechanicalParams*, core::MultiVecDerivId, core::ConstMultiVecDerivId, core::ConstMultiVecCoordId, core::ConstMultiVecDerivId) override { SOFA_UNUSED(mparams); SOFA_UNUSED(dfId); From 9fdebd784f9426232496e91f7ed2194e76b61d38 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 11 Sep 2026 15:05:07 +0200 Subject: [PATCH 12/15] adapt code --- .../src/sofa/simulation/MechanicalOperations.cpp | 12 ++++++++---- .../Core/src/sofa/simulation/MechanicalOperations.h | 2 +- .../mechanicalvisitor/MechanicalComputeDfVisitor.cpp | 2 +- .../mechanicalvisitor/MechanicalComputeDfVisitor.h | 6 +++++- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp index 01ad1222f99..0b0973abecd 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.cpp @@ -274,10 +274,13 @@ void MechanicalOperations::computeForce(core::MultiVecDerivId result, bool clear void MechanicalOperations::computeDf(core::MultiVecDerivId df, bool clear, bool accumulate) { - computeDf(df, sofa::core::vec_id::read_access::dx, clear, accumulate); + computeDf(df, sofa::core::vec_id::read_access::dx, + sofa::core::vec_id::read_access::position, + sofa::core::vec_id::read_access::velocity, + clear, accumulate); } -void MechanicalOperations::computeDf(core::MultiVecDerivId df, core::ConstMultiVecDerivId dx, bool clear, bool accumulate) +void MechanicalOperations::computeDf(core::MultiVecDerivId df, core::ConstMultiVecDerivId dx, core::ConstMultiVecCoordId x, core::ConstMultiVecDerivId v, bool clear, bool accumulate) { setDf(df); if (clear) @@ -285,13 +288,14 @@ void MechanicalOperations::computeDf(core::MultiVecDerivId df, core::ConstMultiV executeVisitor( MechanicalResetForceVisitor(&mparams, df, false) ); // finish(); } - executeVisitor( MechanicalComputeDfVisitor( &mparams, df, dx, accumulate) ); + executeVisitor( MechanicalComputeDfVisitor( &mparams, df, dx, x, v, accumulate) ); } /// Compute the current force delta (given the latest propagated velocity) void MechanicalOperations::computeDfV(core::MultiVecDerivId df, bool clear, bool accumulate) { - computeDf(df, mparams.v(), clear, accumulate); + computeDf(df, mparams.v(), sofa::core::vec_id::read_access::position, + sofa::core::vec_id::read_access::velocity, clear, accumulate); } /// accumulate $ df += (m M + b B + k K) dx $ (given the latest propagated displacement) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h index b7ba8b49a19..2d1a40f55b8 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h @@ -94,7 +94,7 @@ class SOFA_SIMULATION_CORE_API MechanicalOperations SOFA_ATTRIBUTE_DEPRECATED__MECHANICALOPERATIONS_COMPUTEDF() void SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDF_OVERLOAD() computeDf(core::MultiVecDerivId df, bool clear = true, bool accumulate = true); /// Compute the current force delta, given the provided propagated displacement - void computeDf(core::MultiVecDerivId df, core::ConstMultiVecDerivId dx, bool clear = true, bool accumulate = true); + void computeDf(core::MultiVecDerivId df, core::ConstMultiVecDerivId dx, core::ConstMultiVecCoordId x, core::ConstMultiVecDerivId v, bool clear = true, bool accumulate = true); /// Compute the current force delta (given the latest propagated velocity) SOFA_ATTRIBUTE_DEPRECATED__MECHANICALOPERATIONS_COMPUTEDFV() void computeDfV(core::MultiVecDerivId df, bool clear = true, bool accumulate = true); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp index 831f96b85d2..4304ca04852 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.cpp @@ -29,7 +29,7 @@ namespace sofa::simulation::mechanicalvisitor Visitor::Result MechanicalComputeDfVisitor::fwdForceField(simulation::Node* /*node*/, core::behavior::BaseForceField* ff) { - ff->addDForce(this->mparams, res, dx, this->mparams->x(), this->mparams->v()); + ff->addDForce(this->mparams, res, dx, x, v); return RESULT_CONTINUE; } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h index dc326534499..b88b913a3d3 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h @@ -34,14 +34,18 @@ class SOFA_SIMULATION_CORE_API MechanicalComputeDfVisitor : public MechanicalVis public: sofa::core::MultiVecDerivId res; sofa::core::ConstMultiVecDerivId dx; + sofa::core::ConstMultiVecCoordId x; + sofa::core::ConstMultiVecDerivId v; bool accumulate; ///< Accumulate everything back to the DOFs through the mappings MechanicalComputeDfVisitor(const sofa::core::MechanicalParams* mechaparams, sofa::core::MultiVecDerivId resvecid, sofa::core::ConstMultiVecDerivId dxvecid, + sofa::core::ConstMultiVecCoordId xvecid, + sofa::core::ConstMultiVecDerivId vvecid, bool bAccumulate = true ) - : MechanicalVisitor(mechaparams) , res(resvecid), dx(dxvecid), accumulate(bAccumulate) + : MechanicalVisitor(mechaparams) , res(resvecid), dx(dxvecid), x(xvecid), v(vvecid), accumulate(bAccumulate) { #ifdef SOFA_DUMP_VISITOR_INFO setReadWriteVectors(); From 37b7e4b640e23a943b546501a2ccd3053a710521 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 11 Sep 2026 15:08:46 +0200 Subject: [PATCH 13/15] fix rebase --- .../Simulation/Core/src/sofa/simulation/MechanicalOperations.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h index 2d1a40f55b8..5a59ecb0f15 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/MechanicalOperations.h @@ -92,7 +92,7 @@ class SOFA_SIMULATION_CORE_API MechanicalOperations void computeForce(core::MultiVecDerivId result, bool clear = true, bool accumulate = true); /// Compute the current force delta, (given the latest propagated displacement) SOFA_ATTRIBUTE_DEPRECATED__MECHANICALOPERATIONS_COMPUTEDF() - void SOFA_ATTRIBUTE_DEPRECATED__COMPUTEDF_OVERLOAD() computeDf(core::MultiVecDerivId df, bool clear = true, bool accumulate = true); + void computeDf(core::MultiVecDerivId df, bool clear = true, bool accumulate = true); /// Compute the current force delta, given the provided propagated displacement void computeDf(core::MultiVecDerivId df, core::ConstMultiVecDerivId dx, core::ConstMultiVecCoordId x, core::ConstMultiVecDerivId v, bool clear = true, bool accumulate = true); /// Compute the current force delta (given the latest propagated velocity) From dce2373bbdb9c5e254714e3157077ece8a1a047b Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Tue, 29 Sep 2026 14:37:18 +0200 Subject: [PATCH 14/15] fix merge --- .../Simulation/Core/test/Visitor_test.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Sofa/framework/Simulation/Core/test/Visitor_test.cpp b/Sofa/framework/Simulation/Core/test/Visitor_test.cpp index 75c4da6cd4c..9df970aefc1 100644 --- a/Sofa/framework/Simulation/Core/test/Visitor_test.cpp +++ b/Sofa/framework/Simulation/Core/test/Visitor_test.cpp @@ -95,10 +95,15 @@ class TestForceField : public core::behavior::BaseForceField SOFA_UNUSED(mparams); SOFA_UNUSED(fId); } - void addDForce(const core::MechanicalParams*, core::MultiVecDerivId, core::ConstMultiVecDerivId, core::ConstMultiVecCoordId, core::ConstMultiVecDerivId) override + void addDForce(const core::MechanicalParams* mparams, core::MultiVecDerivId dfId, + core::ConstMultiVecDerivId dxId, core::ConstMultiVecCoordId xId, + core::ConstMultiVecDerivId vId) override { SOFA_UNUSED(mparams); SOFA_UNUSED(dfId); + SOFA_UNUSED(dxId); + SOFA_UNUSED(xId); + SOFA_UNUSED(vId); } SReal getPotentialEnergy(const core::MechanicalParams* mparams, core::ConstMultiVecCoordId dxId) const override { @@ -181,10 +186,15 @@ class TestInteractionForceField : public core::behavior::BaseInteractionForceFie SOFA_UNUSED(mparams); SOFA_UNUSED(fId); } - void addDForce(const core::MechanicalParams*, core::MultiVecDerivId, core::ConstMultiVecDerivId, core::ConstMultiVecCoordId, core::ConstMultiVecDerivId) override + void addDForce(const core::MechanicalParams* mparams, core::MultiVecDerivId dfId, + core::ConstMultiVecDerivId dxId, core::ConstMultiVecCoordId xId, + core::ConstMultiVecDerivId vId) override { SOFA_UNUSED(mparams); SOFA_UNUSED(dfId); + SOFA_UNUSED(dxId); + SOFA_UNUSED(xId); + SOFA_UNUSED(vId); } SReal getPotentialEnergy(const core::MechanicalParams* mparams, core::ConstMultiVecCoordId) const override { From 79d0604609adb3eca4dc4ae24deed61eef970714 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Tue, 6 Oct 2026 21:58:55 +0200 Subject: [PATCH 15/15] fix deprecated constructor --- .../mechanicalvisitor/MechanicalComputeDfVisitor.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h index b88b913a3d3..c85d2b8fe0c 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mechanicalvisitor/MechanicalComputeDfVisitor.h @@ -57,9 +57,12 @@ class SOFA_SIMULATION_CORE_API MechanicalComputeDfVisitor : public MechanicalVis sofa::core::MultiVecDerivId resvecid, bool bAccumulate = true ) - : MechanicalVisitor(mechaparams) , - res(resvecid), - dx(mechaparams ? mechaparams->dx() : core::vec_id::read_access::dx), accumulate(bAccumulate) + : MechanicalVisitor(mechaparams) + , res(resvecid) + , dx(mechaparams ? mechaparams->dx() : core::vec_id::read_access::dx) + , x(mechaparams ? mechaparams->x() : core::vec_id::read_access::position) + , v(mechaparams ? mechaparams->v() : core::vec_id::read_access::velocity) + , accumulate(bAccumulate) { #ifdef SOFA_DUMP_VISITOR_INFO setReadWriteVectors();