-
Notifications
You must be signed in to change notification settings - Fork 311
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
[SofaBaseMechanics] Fix UniformMass topology changes handling mode. #2377
Changes from 9 commits
a65046d
17e6e9c
698c9e3
035a2a3
900e053
037e15b
9c601b9
7b56d6c
79eb452
e2bfac1
86c6a27
adeed7a
3efb0aa
76afe1c
d71f2f5
1d7e680
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,8 @@ | |
#include <sofa/defaulttype/BaseVector.h> | ||
#include <sofa/core/objectmodel/DataFileName.h> | ||
#include <sofa/core/topology/BaseMeshTopology.h> | ||
#include <SofaBaseTopology/TopologyData.h> | ||
#include <SofaBaseTopology/TopologySubsetIndices.h> | ||
|
||
namespace sofa::component::mass | ||
{ | ||
|
@@ -47,6 +49,8 @@ class UniformMass : public core::behavior::Mass<DataTypes> | |
typedef typename Coord::value_type Real; | ||
typedef core::objectmodel::Data<VecCoord> DataVecCoord; | ||
typedef core::objectmodel::Data<VecDeriv> DataVecDeriv; | ||
typedef type::vector<Index> SetIndexArray; | ||
typedef sofa::component::topology::TopologySubsetIndices SetIndex; | ||
typedef TMassType MassType; | ||
|
||
Data<MassType> d_vertexMass; ///< single value defining the mass of each particle | ||
|
@@ -65,8 +69,7 @@ class UniformMass : public core::behavior::Mass<DataTypes> | |
/// indices outside of this range are discarded (useful for parallelization | ||
/// using mesh partitionning) | ||
Data< type::Vec<2,int> > d_localRange; | ||
Data< type::vector<int> > d_indices; ///< optional local DOF indices. Any computation involving only indices outside of this list are discarded | ||
|
||
SetIndex d_indices; ///< optional local DOF indices. Any computation involving only indices outside of this list are discarded | ||
Data<bool> d_handleTopologicalChanges; ///< The mass and totalMass are recomputed on particles add/remove. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could add the info specifying why this option exists (UniformMass works also only with DOFs - without TopologyContainer in the scene) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New proposal: remove the data, and keep it as a private variable of the UniformMass class. |
||
Data<bool> d_preserveTotalMass; ///< Prevent totalMass from decreasing when removing particles. | ||
|
||
|
@@ -123,8 +126,6 @@ class UniformMass : public core::behavior::Mass<DataTypes> | |
virtual void initFromTotalMass(); | ||
/// @} | ||
|
||
void handleTopologyChange() override; | ||
|
||
void addMDx(const core::MechanicalParams* mparams, DataVecDeriv& f, const DataVecDeriv& dx, SReal factor) override; | ||
void accFromF(const core::MechanicalParams* mparams, DataVecDeriv& a, const DataVecDeriv& f) override; | ||
void addForce(const core::MechanicalParams* mparams, DataVecDeriv& f, const DataVecCoord& x, const DataVecDeriv& v) override; | ||
|
@@ -148,6 +149,7 @@ class UniformMass : public core::behavior::Mass<DataTypes> | |
|
||
|
||
private: | ||
void updateMassOnResize(sofa::Size newSize); | ||
|
||
template<class T> | ||
void drawRigid3DImpl(const core::visual::VisualParams* vparams) ; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ | |
#include <sofa/defaulttype/DataTypeInfo.h> | ||
#include <SofaBaseMechanics/AddMToMatrixFunctor.h> | ||
#include <sofa/core/behavior/MultiMatrixAccessor.h> | ||
#include <SofaBaseTopology/TopologyData.inl> | ||
#include <sofa/core/topology/TopologyChange.h> | ||
#include <sofa/core/MechanicalParams.h> | ||
|
||
|
@@ -133,8 +134,8 @@ void UniformMass<DataTypes, MassType>::initDefaultImpl() | |
|
||
Mass<DataTypes>::init(); | ||
|
||
WriteAccessor<Data<vector<int> > > indices = d_indices; | ||
|
||
WriteAccessor<Data<SetIndexArray > > indices = d_indices; | ||
if(mstate==nullptr) | ||
{ | ||
msg_warning(this) << "Missing mechanical state. \n" | ||
|
@@ -167,6 +168,27 @@ void UniformMass<DataTypes, MassType>::initDefaultImpl() | |
indices.push_back(i); | ||
} | ||
|
||
if (d_handleTopologicalChanges.getValue()) | ||
{ | ||
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."; | ||
l_topology.set(this->getContext()->getMeshTopologyLink()); | ||
} | ||
|
||
BaseMeshTopology* meshTopology = l_topology.get(); | ||
if (meshTopology != nullptr) | ||
{ | ||
msg_info() << "Topology path used: '" << l_topology.getLinkedPath() << "'"; | ||
|
||
d_indices.createTopologyHandler(meshTopology); | ||
d_indices.addTopologyEventCallBack(sofa::core::topology::TopologyChangeType::ENDING_EVENT, [this](const core::topology::TopologyChange* eventTopo) { | ||
updateMassOnResize(d_indices.getValue().size()); | ||
}); | ||
} | ||
else | ||
msg_warning() << "handleTopologicalChanges has been set to true but not valid topology has been found at:'" << l_topology.getLinkedPath() << "'"; | ||
epernod marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
//If user defines the vertexMass, use this as the mass | ||
if (d_vertexMass.isSet()) | ||
|
@@ -338,107 +360,18 @@ void UniformMass<DataTypes, MassType>::initFromTotalMass() | |
|
||
|
||
template <class DataTypes, class MassType> | ||
void UniformMass<DataTypes, MassType>::handleTopologyChange() | ||
void UniformMass<DataTypes, MassType>::updateMassOnResize(sofa::Size newSize) | ||
{ | ||
if (l_topology.empty()) | ||
if (d_preserveTotalMass.getValue()) | ||
{ | ||
msg_info() << "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()); | ||
Real newVertexMass = d_totalMass.getValue() / Real(newSize); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check if newSize == 0 |
||
d_vertexMass.setValue(static_cast<MassType>(newVertexMass)); | ||
} | ||
|
||
BaseMeshTopology *meshTopology = l_topology.get(); | ||
msg_info() << "Topology path used: '" << l_topology.getLinkedPath() << "'"; | ||
|
||
if ( meshTopology != nullptr && mstate->getSize()>0 ) | ||
else | ||
{ | ||
list< const TopologyChange * >::const_iterator it = meshTopology->beginChange(); | ||
list< const TopologyChange * >::const_iterator itEnd = meshTopology->endChange(); | ||
|
||
while ( it != itEnd ) | ||
{ | ||
switch ( ( *it )->getChangeType() ) | ||
{ | ||
// POINTS ADDED ----------------- | ||
case core::topology::POINTSADDED: | ||
if ( d_handleTopologicalChanges.getValue()) | ||
{ | ||
WriteAccessor<Data<vector<int> > > indices = d_indices; | ||
size_t sizeIndices = indices.size(); | ||
const auto& pointsAdded = ( static_cast< const sofa::core::topology::PointsAdded * >( *it ) )->getIndexArray(); | ||
size_t nbPointsAdded = pointsAdded.size(); | ||
|
||
for(size_t i=0; i<nbPointsAdded; i++) | ||
{ | ||
indices.push_back(int(pointsAdded[i])); | ||
} | ||
|
||
size_t newNbPoints = sizeIndices+nbPointsAdded; | ||
|
||
if (d_preserveTotalMass.getValue()) | ||
{ | ||
Real newVertexMass = d_totalMass.getValue() / Real(newNbPoints); | ||
d_vertexMass.setValue( static_cast< MassType >( newVertexMass ) ); | ||
} | ||
else | ||
{ | ||
d_totalMass.setValue (Real(newNbPoints) * Real(d_vertexMass.getValue()) ); | ||
} | ||
this->cleanTracker(); | ||
} | ||
break; | ||
|
||
// POINTS REMOVED ----------------- | ||
case core::topology::POINTSREMOVED: | ||
if ( d_handleTopologicalChanges.getValue()) | ||
{ | ||
WriteAccessor<Data<vector<int> > > indices = d_indices; | ||
size_t sizeIndices = indices.size(); | ||
const auto& pointsRemoved = ( static_cast< const sofa::core::topology::PointsRemoved * >( *it ) )->getArray(); | ||
size_t nbPointsRemoved = pointsRemoved.size(); | ||
|
||
size_t count=0; | ||
for(size_t i=0; i<nbPointsRemoved; i++) | ||
{ | ||
for(size_t j=0; j<sizeIndices; j++) | ||
{ | ||
if(indices[j] == int(pointsRemoved[i])) | ||
{ | ||
count++; | ||
} | ||
else | ||
indices[i] = indices[i+count]; | ||
} | ||
} | ||
|
||
size_t newNbPoints = sizeIndices-nbPointsRemoved; | ||
indices.resize(newNbPoints); | ||
|
||
if(newNbPoints<=0) | ||
{ | ||
msg_warning() << "All points removed"; | ||
return; | ||
} | ||
|
||
if (d_preserveTotalMass.getValue()) | ||
{ | ||
Real newVertexMass = d_totalMass.getValue() / Real(newNbPoints); | ||
d_vertexMass.setValue( static_cast< MassType >( newVertexMass ) ); | ||
} | ||
else | ||
{ | ||
d_totalMass.setValue (Real(newNbPoints) * Real(d_vertexMass.getValue()) ); | ||
} | ||
this->cleanTracker(); | ||
} | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
|
||
++it; | ||
} | ||
d_totalMass.setValue(Real(newSize) * Real(d_vertexMass.getValue())); | ||
} | ||
this->cleanTracker(); | ||
epernod marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
|
||
|
@@ -452,7 +385,7 @@ void UniformMass<DataTypes, MassType>::addMDx ( const core::MechanicalParams*, | |
helper::WriteAccessor<DataVecDeriv> res = vres; | ||
helper::ReadAccessor<DataVecDeriv> dx = vdx; | ||
|
||
WriteAccessor<Data<vector<int> > > indices = d_indices; | ||
WriteAccessor<Data<SetIndexArray > > indices = d_indices; | ||
|
||
MassType m = d_vertexMass.getValue(); | ||
if ( factor != 1.0 ) | ||
|
@@ -471,7 +404,7 @@ void UniformMass<DataTypes, MassType>::accFromF ( const core::MechanicalParams*, | |
WriteOnlyAccessor<DataVecDeriv> a = va; | ||
ReadAccessor<DataVecDeriv> f = vf; | ||
|
||
ReadAccessor<Data<vector<int> > > indices = d_indices; | ||
ReadAccessor<Data<SetIndexArray > > indices = d_indices; | ||
|
||
MassType m = d_vertexMass.getValue(); | ||
for ( unsigned int i=0; i<indices.size(); i++ ) | ||
|
@@ -537,7 +470,7 @@ void UniformMass<DataTypes, MassType>::addForce ( const core::MechanicalParams*, | |
|
||
|
||
|
||
ReadAccessor<Data<vector<int> > > indices = d_indices; | ||
ReadAccessor<Data<SetIndexArray > > indices = d_indices; | ||
|
||
// add weight and inertia force | ||
if (this->m_separateGravity.getValue()) for ( unsigned int i=0; i<indices.size(); i++ ) | ||
|
@@ -556,7 +489,7 @@ SReal UniformMass<DataTypes, MassType>::getKineticEnergy ( const MechanicalParam | |
SOFA_UNUSED(params); | ||
|
||
ReadAccessor<DataVecDeriv> v = d_v; | ||
ReadAccessor<Data<vector<int> > > indices = d_indices; | ||
ReadAccessor<Data<SetIndexArray > > indices = d_indices; | ||
|
||
SReal e = 0; | ||
const MassType& m = d_vertexMass.getValue(); | ||
|
@@ -573,7 +506,7 @@ SReal UniformMass<DataTypes, MassType>::getPotentialEnergy ( const MechanicalPar | |
{ | ||
SOFA_UNUSED(params); | ||
ReadAccessor<DataVecCoord> x = d_x; | ||
ReadAccessor<Data<vector<int> > > indices = d_indices; | ||
ReadAccessor<Data<SetIndexArray > > indices = d_indices; | ||
|
||
SReal e = 0; | ||
const MassType& m = d_vertexMass.getValue(); | ||
|
@@ -623,7 +556,7 @@ void UniformMass<DataTypes, MassType>::addMToMatrix (const MechanicalParams *mpa | |
|
||
Real mFactor = Real(sofa::core::mechanicalparams::mFactorIncludingRayleighDamping(mparams, this->rayleighMass.getValue())); | ||
|
||
ReadAccessor<Data<vector<int> > > indices = d_indices; | ||
ReadAccessor<Data<SetIndexArray > > indices = d_indices; | ||
for ( unsigned int i=0; i<indices.size(); i++ ) | ||
calc ( r.matrix, m, int(r.offset + N*indices[i]), mFactor); | ||
} | ||
|
@@ -660,8 +593,11 @@ void UniformMass<DataTypes, MassType>::draw(const VisualParams* vparams) | |
if (!mstate.get()) | ||
return; | ||
|
||
if (!d_showCenterOfGravity.getValue()) | ||
return; | ||
|
||
ReadAccessor<VecCoord> x = mstate->read(ConstVecCoordId::position())->getValue(); | ||
ReadAccessor<Data<vector<int> > > indices = d_indices; | ||
ReadAccessor<Data<SetIndexArray > > indices = d_indices; | ||
|
||
Coord gravityCenter; | ||
std::vector< sofa::type::Vector3 > points; | ||
|
@@ -670,14 +606,13 @@ void UniformMass<DataTypes, MassType>::draw(const VisualParams* vparams) | |
sofa::type::Vector3 p; | ||
p = DataTypes::getCPos(x[indices[i]]); | ||
|
||
points.push_back ( p ); | ||
points.push_back ( p ); | ||
gravityCenter += x[indices[i]]; | ||
} | ||
|
||
|
||
if ( d_showCenterOfGravity.getValue() ) | ||
vparams->drawTool()->drawSpheres(points, 0.01, sofa::type::RGBAColor::yellow()); | ||
|
||
{ | ||
gravityCenter /= x.size(); | ||
gravityCenter /= indices.size(); | ||
const sofa::type::RGBAColor color = sofa::type::RGBAColor::yellow(); | ||
|
||
Real axisSize = d_showAxisSize.getValue(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same
SetIndex
is actually quite confusing, it's hiding that it corresponds to a data..There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok what name do you want?
This is the same typedef as in all constraints component. Like FixedConstraint