[Topology] Segfaults on topological changes
Problem
Hi, this is related to https://github.com/sofa-framework/sofa/issues/3201.
Same as before, I want to cut a deformable object.
I wanted to check, if it is easier in total to replace the Hexahedra with Tetraeder for cutting.
Sadly, I sometimes (not always, not really reproducible) get segfaults when deleting elements.
This occurs both through mouse interaction, as well as the SofaCarving plugin.
So I guess there is some form of missing lock / set dirty on one of the components.
In other scenes, I also had that problem for TriangleSetTopologyContainer.
The minimal scene for reproducing the behavior is:
Click to expand!
import Sofa
import Sofa.Core
def createScene(
root_node: Sofa.Core.Node,
) -> Sofa.Core.Node:
plugin_list = [
"Sofa.Component.Collision.Detection.Algorithm", # [BVHNarrowPhase, BruteForceBroadPhase, DefaultPipeline]
"Sofa.Component.Collision.Detection.Intersection", # [NewProximityIntersection]
"Sofa.Component.Collision.Geometry", # [LineCollisionModel, PointCollisionModel, TriangleCollisionModel]
"Sofa.Component.Collision.Response.Contact", # [DefaultContactManager]
"Sofa.Component.Constraint.Projective", # [FixedConstraint]
"Sofa.Component.Engine.Select", # [BoxROI]
"Sofa.Component.LinearSolver.Iterative", # [CGLinearSolver]
"Sofa.Component.Mass", # [UniformMass]
"Sofa.Component.MechanicalLoad", # [PlaneForceField]
"Sofa.Component.ODESolver.Backward", # [EulerImplicitSolver]
"Sofa.Component.SolidMechanics.FEM.Elastic", # [FastTetrahedralCorotationalForceField]
"Sofa.Component.Topology.Container.Dynamic", # [HexahedronSetTopologyContainer, HexahedronSetTopologyModifier, TetraheopologyModifier]
"Sofa.Component.Topology.Container.Grid", # [RegularGridTopology]
"Sofa.Component.Topology.Mapping", # [Hexa2TetraTopologicalMapping, Quad2TriangleTopologicalMapping]
"Sofa.Component.Visual", # [VisualStyle]
"Sofa.GL.Component.Rendering3D", # [OglModel]
]
plugin_node = root_node.addChild("Plugins")
for plugin in plugin_list:
plugin_node.addObject("RequiredPlugin", pluginName=plugin, name=plugin)
root_node.addObject("DefaultAnimationLoop")
root_node.addObject("DefaultVisualManagerLoop")
root_node.addObject(
"VisualStyle",
displayFlags=["showVisual", "showForceFields", "showCollisionModels", "showBehaviorModels", "showInteractionForceFields"],
)
root_node.addObject("DefaultPipeline")
root_node.addObject("BruteForceBroadPhase")
root_node.addObject("BVHNarrowPhase")
root_node.addObject("DefaultContactManager", response="PenalityContactForceField")
root_node.addObject(
"NewProximityIntersection",
alarmDistance=3.0,
contactDistance=1.1,
)
root_node.gravity = [0.0, -98.1, 0.0]
scene_node = root_node.addChild("scene")
###################
# Topology Creation
###################
topology_node = scene_node.addChild("topologies")
grid_node = topology_node.addChild("grid")
grid = grid_node.addObject("RegularGridTopology", nx=12, ny=20, nz=2, xmin=-30.0, xmax=30.0, ymin=0.0, ymax=100.0, zmin=0.0, zmax=2.0)
grid_node.init()
hexahedra_node = topology_node.addChild("hexahedra")
grid_positions = grid.position.array()
grid_hexahedra = grid.hexahedra.array()
hexahedra_node.addObject("HexahedronSetTopologyContainer", hexahedra=grid_hexahedra.copy(), position=grid_positions.copy())
hexahedra_node.addObject("HexahedronSetTopologyModifier")
tetrahedra_node = hexahedra_node.addChild("tetras")
tetrahedron_topology = tetrahedra_node.addObject("TetrahedronSetTopologyContainer")
tetrahedra_node.addObject("TetrahedronSetTopologyModifier")
tetrahedra_node.addObject("Hexa2TetraTopologicalMapping")
triangle_node = hexahedra_node.addChild("triangles")
triangle_node.addObject("TriangleSetTopologyContainer")
triangle_node.addObject("TriangleSetTopologyModifier")
triangle_node.addObject("Quad2TriangleTopologicalMapping")
# TODO: why are there a different number of triangles in triangle_node and tetrahedra_node?
topology_node.init()
###################
# Deformable Object
###################
deformable_node = scene_node.addChild("deformable")
deformable_node.addObject("CGLinearSolver")
deformable_node.addObject("EulerImplicitSolver")
deformable_node.addObject(
"TetrahedronSetTopologyContainer",
tetrahedra=tetrahedron_topology.tetrahedra.array().copy(),
position=grid_positions.copy(),
)
deformable_node.addObject("TetrahedronSetTopologyModifier")
deformable_node.addObject("MechanicalObject", showObject=True, showObjectScale=2.0)
deformable_node.addObject("PointCollisionModel", group=0)
deformable_node.addObject("LineCollisionModel", group=0)
deformable_node.addObject("TriangleCollisionModel", group=0)
deformable_node.addObject("FastTetrahedralCorotationalForceField", youngModulus=60, poissonRatio=0.0)
deformable_node.addObject(
"PlaneForceField",
normal=[0, 0, 1],
d=0.0,
stiffness=3000,
damping=1,
showPlane=False,
showPlaneSize=100,
)
deformable_node.addObject("UniformMass", totalMass=0.2)
deformable_visual_node = deformable_node.addChild("visual")
deformable_visual_node.addObject("OglModel", color=[1.0, 0.0, 0.0])
deformable_visual_node.addObject("IdentityMapping")
box = deformable_node.addObject("BoxROI", box=(-35, -1, -1) + (35, 1, 5))
deformable_node.addObject("FixedConstraint", indices=box.indices.getLinkPath())
Environment
Context
- System: Ubuntu 20.04
- Version of SOFA: master branch at commit 95e9357da1a457a2a158dfc26012b214ac0aa889
- State: "Install directory"
Logs
Output on Segfault:
Click to expand!
########## SIG 11 - SIGSEGV: segfault ##########
sofa::helper::BackTrace::sig(int)
sofa::component::topology::container::dynamic::PointSetTopologyContainer::setPointTopologyToDirty()
sofa::component::topology::container::dynamic::PointSetTopologyModifier::removePointsWarning(sofa::type::vector<unsigned int, sofa::type::CPUMemoryManager<unsigned int> >&,
bool)
sofa::component::topology::container::dynamic::TetrahedronSetTopologyModifier::removeTetrahedraProcess(sofa::type::vector<unsigned int, sofa::type::CPUMemoryManager<unsigned
int> > const&, bool)
sofa::component::topology::container::dynamic::TetrahedronSetTopologyModifier::removeTetrahedra(sofa::type::vector<unsigned int, sofa::type::CPUMemoryManager<unsigned int> >
const&, bool)
sofa::gui::component::performer::TopologicalChangeManager::removeItemsFromTriangleModel(sofa::component::collision::geometry::TriangleCollisionModel<sofa::defaulttype::StdVe
ctorTypes<sofa::type::Vec<3u, double>, sofa::type::Vec<3u, double>, double> >*, sofa::type::vector<unsigned int, sofa::type::CPUMemoryManager<unsigned int> > const&) const
sofa::gui::component::performer::TopologicalChangeManager::removeItemsFromCollisionModel(sofa::core::CollisionModel*, unsigned int const&) const
sofa::gui::component::performer::RemovePrimitivePerformer<sofa::defaulttype::StdVectorTypes<sofa::type::Vec<3u, double>, sofa::type::Vec<3u, double>, double> >::execute()
sofa::gui::component::performer::BaseMouseInteractor::updatePosition(double)
sofa::simulation::BehaviorUpdatePositionVisitor::processNodeTopDown(sofa::simulation::Node*)
sofa::simulation::graph::DAGNode::executeVisitorTopDown(sofa::simulation::Visitor*, std::__cxx11::list<sofa::simulation::graph::DAGNode*, std::allocator<sofa::simulation::gr
aph::DAGNode*> >&, std::map<sofa::simulation::graph::DAGNode*, sofa::simulation::graph::DAGNode::StatusStruct, std::less<sofa::simulation::graph::DAGNode*>, std::allocator<std
::pair<sofa::simulation::graph::DAGNode* const, sofa::simulation::graph::DAGNode::StatusStruct> > >&, sofa::simulation::graph::DAGNode*)
sofa::simulation::graph::DAGNode::executeVisitorTopDown(sofa::simulation::Visitor*, std::__cxx11::list<sofa::simulation::graph::DAGNode*, std::allocator<sofa::simulation::gr
aph::DAGNode*> >&, std::map<sofa::simulation::graph::DAGNode*, sofa::simulation::graph::DAGNode::StatusStruct, std::less<sofa::simulation::graph::DAGNode*>, std::allocator<std
::pair<sofa::simulation::graph::DAGNode* const, sofa::simulation::graph::DAGNode::StatusStruct> > >&, sofa::simulation::graph::DAGNode*)
sofa::simulation::graph::DAGNode::executeVisitorTopDown(sofa::simulation::Visitor*, std::__cxx11::list<sofa::simulation::graph::DAGNode*, std::allocator<sofa::simulation::gr
aph::DAGNode*> >&, std::map<sofa::simulation::graph::DAGNode*, sofa::simulation::graph::DAGNode::StatusStruct, std::less<sofa::simulation::graph::DAGNode*>, std::allocator<std
::pair<sofa::simulation::graph::DAGNode* const, sofa::simulation::graph::DAGNode::StatusStruct> > >&, sofa::simulation::graph::DAGNode*)
sofa::simulation::graph::DAGNode::doExecuteVisitor(sofa::simulation::Visitor*, bool)
sofa::simulation::DefaultAnimationLoop::step(sofa::core::ExecParams const*, double)
sofa::simulation::Simulation::animate(sofa::simulation::Node*, double)
sofa::gui::qt::RealGUI::step()
QMetaObject::activate(QObject*, int, int, void**)
QTimer::timeout(QTimer::QPrivateSignal)
QObject::event(QEvent*)
QApplicationPrivate::notify_helper(QObject*, QEvent*)
QApplication::notify(QObject*, QEvent*)
QCoreApplication::notifyInternal2(QObject*, QEvent*)
QTimerInfoList::activateTimers()
g_main_context_dispatch
g_main_context_iteration
QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)
QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)
QCoreApplication::exec()
sofa::gui::qt::RealGUI::mainLoop()
sofa::gui::common::GUIManager::MainLoop(boost::intrusive_ptr<sofa::simulation::Node>, char const*)
__libc_start_main
zsh: segmentation fault (core dumped) ~/repos/sofa/build/master/bin/runSofa
I was able to catch the segfault during debugging:

Here a minimal scene to launch it on debug mode would be helpful
Here a minimal scene to launch it on debug mode would be helpful
There is an example in the question (collapseable element "Click to expand!") :D