Skip to content

Instantly share code, notes, and snippets.

@jnbrunet
Created July 14, 2021 13:26
Show Gist options
  • Save jnbrunet/79a3a9d493d2dc4458433356bc037e04 to your computer and use it in GitHub Desktop.
Save jnbrunet/79a3a9d493d2dc4458433356bc037e04 to your computer and use it in GitHub Desktop.
Simple example of a cantilever beam simulation where the displacement vector is saved into a mesh file at every steps.
import Sofa, SofaRuntime
import meshio, numpy as np
class Exporter (Sofa.Core.Controller):
def __init__(self, *args, **kwargs):
Sofa.Core.Controller.__init__(self, *args, **kwargs)
self.step_id = 0
def onAnimateEndEvent(self, e):
x = self.getContext().mo.position.array()
x0 = self.getContext().mo.rest_position.array()
u = x - x0
cells = self.getContext().topology.tetrahedra.array()
von_mises = self.getContext().ff.vonMisesPerNode.array()
filename = f'beam_step_{self.step_id}.vtu'
meshio.write(filename, meshio.Mesh(points=x0, cells={'tetra':cells}, point_data={'u':u, 'von_mises':von_mises}))
print(f'Mesh exported at {filename}')
self.step_id += 1
def createScene(root):
root.addObject(Exporter(name='exporter'))
root.addObject('RequiredPlugin', pluginName=['SofaBaseMechanics', 'SofaBoundaryCondition', 'SofaEngine', 'SofaImplicitOdeSolver', 'SofaSimpleFem', 'SofaSparseSolver'])
root.addObject('VisualStyle', displayFlags='showBehaviorModels showForceFields')
root.addObject('RegularGridTopology', name='grid', min=[-7.5, -7.5, 0], max=[7.5, 7.5, 80], n=[9, 9, 21])
root.addObject('StaticSolver', newton_iterations=10, absolute_residual_tolerance_threshold=1e-10, printLog=True)
root.addObject('SparseLDLSolver', template="CompressedRowSparseMatrixMat3x3d")
root.addObject('MechanicalObject', name='mo', position='@grid.position')
root.addObject('TetrahedronSetGeometryAlgorithms')
root.addObject('TetrahedronSetTopologyModifier')
root.addObject('TetrahedronSetTopologyContainer', name='topology')
root.addObject('Hexa2TetraTopologicalMapping', input='@grid', output='@topology')
root.addObject('TetrahedronFEMForceField', name='ff', poissonRatio=0.45, youngModulus=5000, method='large', computeVonMisesStress=1, listening=True)
root.addObject('BoxROI', name='dirichlet_roi', box=[-7.5, -7.5, -0.9, 7.5, 7.5, 0.1])
root.addObject('FixedConstraint', indices='@dirichlet_roi.indices')
root.addObject('BoxROI', name='neumann_roi', box=[-7.5, -7.5, 79.9, 7.5, 7.5, 80.1])
root.addObject('TriangleSetGeometryAlgorithms')
root.addObject('TrianglePressureForceField', pressure=[0, -50, 0], triangleList='@neumann_roi.trianglesInROI')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment