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

[Spring] Add fixed weak constraint and examples #4750

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Apply changes to RestShapeSpringForceField
  • Loading branch information
bakpaul committed Dec 10, 2024
commit 937acc8ad9f547c63e05e079bd41f2aaba0dcbff
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@
#include <sofa/core/topology/TopologySubsetIndices.h>
#include <sofa/type/vector.h>
#include <sofa/linearalgebra/EigenSparseMatrix.h>
#include <sofa/core/objectmodel/RenamedData.h>


namespace sofa::core::behavior
@@ -71,38 +72,27 @@ class FixedWeakConstraint : public core::behavior::ForceField<DataTypes>
typedef core::objectmodel::Data<VecDeriv> DataVecDeriv;

DataSubsetIndex d_indices; ///< points controlled by the rest shape springs
core::objectmodel::lifecycle::RemovedData d_points{this,"v24.12","v25.06","points","This data has been replaced by \'indices\'. Please update your scene."};

Data<bool> d_fixAll; ///< points controlled by the rest shape springs
Data< VecReal > d_stiffness; ///< stiffness values between the actual position and the rest shape position
Data< VecReal > d_angularStiffness; ///< angularStiffness assigned when controlling the rotation of the points
Data< bool > d_drawSpring; ///< draw Spring
Data< sofa::type::RGBAColor > d_springColor; ///< spring color. (default=[0.0,1.0,0.0,1.0])


protected:
FixedWeakConstraint();
static constexpr type::fixed_array<bool, coord_total_size> s_defaultActiveDirections = sofa::type::makeHomogeneousArray<bool, coord_total_size>(true);
/// Link to be set to the topology container in the component graph.
SingleLink<FixedWeakConstraint<DataTypes>, sofa::core::topology::BaseMeshTopology, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology;


public:
/// BaseObject initialization method.
void bwdInit() override ;
void reinit() override ;

/// Add the forces.
void addForce(const core::MechanicalParams* mparams, DataVecDeriv& f, const DataVecCoord& x, const DataVecDeriv& v) override;
/// Link to be set to the topology container in the component graph.
SingleLink<FixedWeakConstraint<DataTypes>, sofa::core::topology::BaseMeshTopology, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology;

void addDForce(const core::MechanicalParams* mparams, DataVecDeriv& df, const DataVecDeriv& dx) override;

SReal getPotentialEnergy(const core::MechanicalParams* mparams, const DataVecCoord& x) const override
{
SOFA_UNUSED(mparams);
SOFA_UNUSED(x);

msg_warning() << "Method getPotentialEnergy not implemented yet.";
return 0.0;
}
SReal getPotentialEnergy(const core::MechanicalParams* mparams, const DataVecCoord& x) const override;

/// Brings ForceField contribution to the global system stiffness matrix.
void addKToMatrix(const core::MechanicalParams* mparams, const sofa::core::behavior::MultiMatrixAccessor* matrix ) override;
@@ -113,16 +103,18 @@ class FixedWeakConstraint : public core::behavior::ForceField<DataTypes>


protected :
FixedWeakConstraint();
static constexpr type::fixed_array<bool, coord_total_size> s_defaultActiveDirections = sofa::type::makeHomogeneousArray<bool, coord_total_size>(true);

virtual const DataVecCoord* getExtPosition() const;
virtual const VecIndex& getIndices() const;
virtual const VecIndex& getExtIndices() const;
virtual const type::fixed_array<bool, coord_total_size>& getActiveDirections() const;
virtual const bool checkState();

bool checkOutOfBoundsIndices(const VecIndex &indices, const sofa::Size dimension);
virtual bool checkOutOfBoundsIndices();

bool checkOutOfBoundsIndices(const VecIndex &indices, const sofa::Size dimension);
};

#if !defined(SOFA_COMPONENT_FORCEFIELD_FixedWeakConstraint_CPP)
Original file line number Diff line number Diff line change
@@ -81,26 +81,26 @@ const bool FixedWeakConstraint<DataTypes>::checkState()
{
if (d_stiffness.getValue().empty())
{
msg_info() << "No stiffness is defined, assuming equal stiffness on each node, k = 100.0 ";
msg_info(this) << "No stiffness is defined, assuming equal stiffness on each node, k = 100.0 ";
d_stiffness.setValue({static_cast<Real>(100)});
}

if (l_topology.empty())
{
msg_info() << "link to Topology container should be set to ensure right behavior. First Topology found in current context will be used.";
msg_info(this) << "link to Topology container should be set to ensure right behavior. First Topology found in current context will be used.";
l_topology.set(this->getContext()->getMeshTopologyLink());
}

if (sofa::core::topology::BaseMeshTopology* _topology = l_topology.get())
{
msg_info() << "Topology path used: '" << l_topology.getLinkedPath() << "'";
msg_info(this) << "Topology path used: '" << l_topology.getLinkedPath() << "'";

// Initialize topological changes support
d_indices.createTopologyHandler(_topology);
}
else
{
msg_info() << "Cannot find the topology: topological changes will not be supported";
msg_info(this) << "Cannot find the topology: topological changes will not be supported";
}


@@ -115,15 +115,15 @@ const bool FixedWeakConstraint<DataTypes>::checkState()

if (as.size() < s.size())
{
msg_info() << "'stiffness' is larger than 'angularStiffness', add the default value (100.0) to the missing entries.";
msg_info(this) << "'stiffness' is larger than 'angularStiffness', add the default value (100.0) to the missing entries.";

for(size_t i = as.size();i<s.size();i++)
{
as.push_back(100.0);
}
}else if (as.size() > s.size())
{
msg_info() << "'stiffness' is smaller than 'angularStiffness', clamp the extra values in angularStiffness.";
msg_info(this) << "'stiffness' is smaller than 'angularStiffness', clamp the extra values in angularStiffness.";
as.resize(s.size());
}
}
@@ -229,6 +229,9 @@ const type::fixed_array<bool, FixedWeakConstraint<DataTypes>::coord_total_size>&
template<class DataTypes>
void FixedWeakConstraint<DataTypes>::addForce(const MechanicalParams* mparams , DataVecDeriv& f, const DataVecCoord& x, const DataVecDeriv& v )
{
if (this->d_componentState.getValue() != core::objectmodel::ComponentState::Valid)
return;

SOFA_UNUSED(mparams);
SOFA_UNUSED(v);

@@ -333,6 +336,9 @@ void FixedWeakConstraint<DataTypes>::addForce(const MechanicalParams* mparams ,
template<class DataTypes>
void FixedWeakConstraint<DataTypes>::addDForce(const MechanicalParams* mparams, DataVecDeriv& df, const DataVecDeriv& dx)
{
if (this->d_componentState.getValue() != core::objectmodel::ComponentState::Valid)
return;

WriteAccessor< DataVecDeriv > df1 = df;
ReadAccessor< DataVecDeriv > dx1 = dx;
Real kFactor = (Real)sofa::core::mechanicalparams::kFactorIncludingRayleighDamping(mparams, this->rayleighStiffness.getValue());
@@ -400,10 +406,22 @@ void FixedWeakConstraint<DataTypes>::addDForce(const MechanicalParams* mparams,

}

template<class DataTypes>
SReal FixedWeakConstraint<DataTypes>::getPotentialEnergy(const core::MechanicalParams* mparams, const DataVecCoord& x) const
{
SOFA_UNUSED(mparams);
SOFA_UNUSED(x);

msg_warning() << "Method getPotentialEnergy not implemented yet.";
return 0.0;
}

template<class DataTypes>
void FixedWeakConstraint<DataTypes>::addKToMatrix(const MechanicalParams* mparams, const MultiMatrixAccessor* matrix )
{
if (this->d_componentState.getValue() != core::objectmodel::ComponentState::Valid)
return;

const MultiMatrixAccessor::MatrixRef mref = matrix->getMatrix(this->mstate);
BaseMatrix* mat = mref.matrix;
const unsigned int offset = mref.offset;
@@ -457,6 +475,9 @@ void FixedWeakConstraint<DataTypes>::addKToMatrix(const MechanicalParams* mparam
template<class DataTypes>
void FixedWeakConstraint<DataTypes>::buildStiffnessMatrix(core::behavior::StiffnessMatrix* matrix)
{
if (this->d_componentState.getValue() != core::objectmodel::ComponentState::Valid)
return;

const VecReal& k = d_stiffness.getValue();
const VecReal& k_a = d_angularStiffness.getValue();
const auto & activeDirections = getActiveDirections();
@@ -512,6 +533,9 @@ void FixedWeakConstraint<DataTypes>::buildDampingMatrix(
template<class DataTypes>
void FixedWeakConstraint<DataTypes>::draw(const VisualParams *vparams)
{
if (this->d_componentState.getValue() != core::objectmodel::ComponentState::Valid)
return;

if (!vparams->displayFlags().getShowForceFields() || !d_drawSpring.getValue())
return; /// \todo put this in the parent class

Original file line number Diff line number Diff line change
@@ -29,6 +29,8 @@
#include <sofa/core/topology/TopologySubsetIndices.h>
#include <sofa/type/vector.h>
#include <sofa/linearalgebra/EigenSparseMatrix.h>
#include <sofa/component/solidmechanics/spring/FixedWeakConstraint.h>
#include <sofa/core/objectmodel/DataCallback.h>


namespace sofa::core::behavior
@@ -48,12 +50,12 @@ namespace sofa::component::solidmechanics::spring
* An external MechanicalState reference can also be passed to the ForceField as rest shape position.
*/
template<class DataTypes>
class RestShapeSpringsForceField : public core::behavior::ForceField<DataTypes>
class RestShapeSpringsForceField : public FixedWeakConstraint<DataTypes>
{
public:
SOFA_CLASS(SOFA_TEMPLATE(RestShapeSpringsForceField, DataTypes), SOFA_TEMPLATE(core::behavior::ForceField, DataTypes));
SOFA_CLASS(SOFA_TEMPLATE(RestShapeSpringsForceField, DataTypes), SOFA_TEMPLATE(FixedWeakConstraint, DataTypes));

typedef core::behavior::ForceField<DataTypes> Inherit;
typedef FixedWeakConstraint<DataTypes> Inherit;
typedef typename DataTypes::VecCoord VecCoord;
typedef typename DataTypes::VecDeriv VecDeriv;
typedef typename DataTypes::Coord Coord;
@@ -70,72 +72,31 @@ class RestShapeSpringsForceField : public core::behavior::ForceField<DataTypes>
typedef core::objectmodel::Data<VecCoord> DataVecCoord;
typedef core::objectmodel::Data<VecDeriv> DataVecDeriv;

DataSubsetIndex d_points; ///< points controlled by the rest shape springs
Data< VecReal > d_stiffness; ///< stiffness values between the actual position and the rest shape position
Data< VecReal > d_angularStiffness; ///< angularStiffness assigned when controlling the rotation of the points
Data< type::vector< CPos > > d_pivotPoints; ///< global pivot points used when translations instead of the rigid mass centers
Data< VecIndex > d_external_points; ///< points from the external Mechanical State that define the rest shape springs
Data< bool > d_recompute_indices; ///< Recompute indices (should be false for BBOX)
Data< bool > d_drawSpring; ///< draw Spring
Data< sofa::type::RGBAColor > d_springColor; ///< spring color. (default=[0.0,1.0,0.0,1.0])
Data< type::fixed_array<bool, coord_total_size> > d_activeDirections; ///< directions (translation, and rotation in case of Rigids) in which the spring is active
Data< VecIndex > d_externalIndices; ///< points from the external Mechanical State that define the rest shape springs
core::objectmodel::lifecycle::RemovedData d_external_points{this,"v24.12","v25.06","external_points","This data has been replaced by \'externalIndices\'. Please update your scene."};
core::objectmodel::DataCallback c_fixAllCallback;

SingleLink<RestShapeSpringsForceField<DataTypes>, sofa::core::behavior::MechanicalState< DataTypes >, BaseLink::FLAG_STOREPATH|BaseLink::FLAG_STRONGLINK> l_restMState;
linearalgebra::EigenBaseSparseMatrix<typename DataTypes::Real> matS;

protected:
RestShapeSpringsForceField();

static constexpr type::fixed_array<bool, coord_total_size> s_defaultActiveDirections = sofa::type::makeHomogeneousArray<bool, coord_total_size>(true);
SingleLink<RestShapeSpringsForceField<DataTypes>, sofa::core::topology::BaseMeshTopology, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology;

public:
/// BaseObject initialization method.
void bwdInit() override ;
void parse(core::objectmodel::BaseObjectDescription *arg) override ;
void reinit() override ;

/// Add the forces.
void addForce(const core::MechanicalParams* mparams, DataVecDeriv& f, const DataVecCoord& x, const DataVecDeriv& v) override;
/// Link to be set to the topology container in the component graph.
SingleLink<RestShapeSpringsForceField<DataTypes>, sofa::core::topology::BaseMeshTopology, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology;

void addDForce(const core::MechanicalParams* mparams, DataVecDeriv& df, const DataVecDeriv& dx) override;

SReal getPotentialEnergy(const core::MechanicalParams* mparams, const DataVecCoord& x) const override
{
SOFA_UNUSED(mparams);
SOFA_UNUSED(x);

msg_warning() << "Method getPotentialEnergy not implemented yet.";
return 0.0;
}

/// Brings ForceField contribution to the global system stiffness matrix.
void addKToMatrix(const core::MechanicalParams* mparams, const sofa::core::behavior::MultiMatrixAccessor* matrix ) override;
void buildStiffnessMatrix(core::behavior::StiffnessMatrix* matrix) override;
void buildDampingMatrix(core::behavior::DampingMatrix* matrix) override;

void draw(const core::visual::VisualParams* vparams) override;


const DataVecCoord* getExtPosition() const;
const VecIndex& getIndices() const { return m_indices; }
const VecIndex& getExtIndices() const { return (useRestMState ? m_ext_indices : m_indices); }

protected :
RestShapeSpringsForceField();

void recomputeIndices();
bool checkOutOfBoundsIndices();
bool checkOutOfBoundsIndices(const VecIndex &indices, const sofa::Size dimension);

virtual const DataVecCoord* getExtPosition() const override;
virtual const VecIndex& getExtIndices() const override;
virtual const type::fixed_array<bool, coord_total_size>& getActiveDirections() const override;

VecIndex m_indices;
VecIndex m_ext_indices;
type::vector<CPos> m_pivots;
virtual bool checkOutOfBoundsIndices();

private :

bool useRestMState{}; /// An external MechanicalState is used as rest reference.
bool m_useRestMState; /// An external MechanicalState is used as rest reference.
};

#if !defined(SOFA_COMPONENT_FORCEFIELD_RESTSHAPESPRINGSFORCEFIELD_CPP)
Loading