Animation loop
All the scenes in SOFA must include an AnimationLoop. This class rules all the steps of the simulation and the system resolution, which succeed each other in a specific order. At each time step, the animation loop triggers each event (solving the matrix system, managing the constraints, detecting the collision, etc.) through a Visitor mechanism (see below). In a scene, if no animation loop is defined, a "DefaultAnimationLoop" is automatically created. Otherwise, in an XML format, it can be written:
In an XML format, this would be written as follows:
<Node name="root" dt="0.01" gravity="0 9.81 0">
<DefaultAnimationLoop />
</Node>
Several AnimationLoops are already available in SOFA:

DefaultAnimationLoop: this is the default animation loop as the name indicates! This animation loop is included by default at the root node of the graph, if no animation loop is specified in the scene. With a DefaultAnimationLoop, the loop of one simulation step follows:
 build and solve all linear systems in the scene : collision and time integration to compute the new values of the dofs
 update the context (dt++)
 update the mappings
 update the bounding box (volume covering all objects of the scene)

MultiTagAnimationLoop: this animation loops works by labelling components using different tags. With a MultiTagAnimationLoop, the loop of one simulation step is the same as the DefaultAnimationLoop, except that one tag is solved after another, given a list of tags:
 build and solve all linear systems in the scene
 for all components and nodes using the first tag
 then the second tag … and so on
 update the context
 update the mappings
 update the bounding box

MultiStepAnimationLoop: given one time step, this animation loop allows for running several collision (C) and several integration time in one step (I), where C and I can be different. If the time step is dt=0.01, the number of collision step C=2 and the number of integration step is I=4, the loop of one simulation step follows:
 compute C=4 times the collision pipeline (4 collision steps)
 for each collision step, solve I=4 times the linear system due to integration. The integration time step is therefore dt’ = dt / (C.I) = 0.00125 (8 integration steps).
 update the context
 update the mappings
 update the bounding box : this means that the visualization is done once at each time step dt=0.01

FreeAnimationLoop: this animation loop is used for simulation involving constraints and collisions. With a FreeAnimationLoop, the loop of one simulation step follows:
 build and solve all linear systems in the scene without constraints and save the "free" values of the dofs
 collisions are computed
 constraints are finally used to correct the "free" dofs in order to take into account the collisions & constraints
 update the mappings
 update the bounding box
Visitors
During the different steps of the simulation (initialization, system assembly, solving, visualization), information needs to be recovered from all the graph nodes. An implicit mechanism based on Visitor enables this. You can find the abstract Visitor class in the SofaSimulation package.
For each of these steps, the operation implemented with the visitor can be described as:
 a graph traversal,
 abstract methods depending on the triggered action (ex: clearing a global vector, or accumulating forces),
 and vector identificators.
Visitors traverse the scene topdown and bottomup and call the corresponding virtual functions at each graph node traversal. Visitors are therefore used to trigger actions by calling the associated virtual functions (e.g. animating the simulation, accumulating forces). Algorithmic operations on the simulated objects are implemented by deriving the Visitor class and overloading its virtual functions topDown( ) and bottomUp( ). This approach hides the scene structure (parent, children) from the components, for more implementation flexibility and a better control of the execution model. Moreover, various parallelism strategies can be applied independently of the mechanical computations performed at each node. The data structure is actually extended from strict hierarchies to directed acyclic graphs to handle more general kinematic dependencies. The topdown node traversals are pruned unless all the parents of the current node have been traversed already, so that nodes with multiple parents are traversed only once all their parents have been traversed. The bottomup traversals are made in the reverse order.
Example: accumulating the forces. Accumulating forces is used to compute all the forces (internal or external) applied on our object. The solver then triggers the associate Visitor and the action is propagated through the graph and calls the appropriate (bottomup) methods at each force and mapping node. All components able to compute forces will accumulate their contributions. This information is finally gathered in the MechanicalObject and the solver will use this "force" vector to solve the mathematical system.
Fig. 4 – Traversing Visitors triggered for the accumulateForce() action
Sequence diagram
Here is the usual sequence diagram of a SOFA simulation.
Fig. 5 – Sequence diagram of a SOFA simulation
More about the Visitors can be found here.
Last modified: 5 October 2018