Model Order Reduction Example


In this python notebook exemple we will see with 2 real examples how to reduce a model from one of your sofa scene thanks to the Model Order Reduction plugin done by the INRIA research team Defrost.

the two examples will be :

../../_images/diamondReal.pngDiamond robot

../../_images/Starfish_Real.pngStarfish robot

After these expample presentation we can now proceed to the reduction. First we have to prepare it by setting a bunch of parameters while explaining there purpose (here the parameters will be set twice, one for the diamond and one for the starfish so you will be able to switch easily between each example)

User Paramters

Before defining the reduction parameters, here are some “import” commands that will be useful for this python notebook:

# Import
import os
import sys


from mor.gui import utility
from mor.reduction import ReduceModel
from mor.reduction.container import ObjToAnimate

1. Paths to the SOFA scene, mesh and outputs:

  • The scene you want to work on
  • The folder containing its mesh
  • The folder where you want the results to be put in
# Important path
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication(sys.argv)

originalScene = utility.openFileName('Select the SOFA scene you want to reduce')
meshes = utility.openFilesNames('Select the meshes & visual of your scene')
outputDir = utility.openDirName('Select the directory tha will contain all the results')

# if you haven't install PyQt the previous function won't work
# As an alternative you can enter the absolute path to the conresponding files directly:
# originalScene = /PathToMy/Original/Scene

2. The different reduction parameters


  • *ie : list containing the SOFA path from the rootnode to the model you want to reduce
nodesToReduce_DIAMOND = ['/modelNode']
nodesToReduce_STARFISH =['/model']


Contain a list of object from the class ObjToAnimate.

A ObjToAnimate will define an object to “animate” during the shaking.

There are 3 main parameter to this object :

  • location : Path to obj/node we want to animate
  • animFct : the animation function we will use (here we use defaultShaking)
  • all the argument that will be passed to the animFct we have chose

For example here we want to animate the node named “nord”, but we won’t specify the animFct so the default animation function will be used and be applied on the first default object it will find. The default function will need 3 additionnal parameters :

  • incrPeriod (float): Period between each increment
  • incr (float): Value of each increment
  • rangeOfAction (float): Until which value the data will increase

nord = ObjToAnimate(“nord”, incr=5,incrPeriod=10,rangeOfAction=40)

# animation parameters

nodesToReduce = ['/modelNode']
nord = ObjToAnimate("modelNode/nord", incr=5,incrPeriod=10,rangeOfAction=40)
sud = ObjToAnimate("modelNode/sud", incr=5,incrPeriod=10,rangeOfAction=40)
est = ObjToAnimate("modelNode/est", incr=5,incrPeriod=10,rangeOfAction=40)
ouest = ObjToAnimate("modelNode/ouest", incr=5,incrPeriod=10,rangeOfAction=40)
listObjToAnimate_DIAMOND = [nord,ouest,sud,est]

centerCavity = ObjToAnimate("model/centerCavity", incr=350,incrPeriod=2,rangeOfAction=3500)
rearLeftCavity = ObjToAnimate("model/rearLeftCavity", incr=200,incrPeriod=2,rangeOfAction=2000)
rearRightCavity = ObjToAnimate("model/rearRightCavity", incr=200,incrPeriod=2,rangeOfAction=2000)
frontLeftCavity = ObjToAnimate("model/frontLeftCavity", incr=200,incrPeriod=2,rangeOfAction=2000)
frontRightCavity = ObjToAnimate("model/frontRightCavity", incr=200,incrPeriod=2,rangeOfAction=2000)
listObjToAnimate_STARFISH = [centerCavity,rearLeftCavity,rearRightCavity,frontLeftCavity,frontRightCavity]

Modes parameters

  • addRigidBodyModes (Defines if our reduce model will be able to translate along the x, y , z directions)
  • tolModes ( Defines the level of accuracy we want to select the reduced basis modes)
addRigidBodyModes_DIAMOND = [0,0,0]
addRigidBodyModes_STARFISH = [1,1,1]

tolModes = 0.001
  • tolGIE
    • tolerance used in the greedy algorithm selecting the reduced integration domain(RID). Values are between 0 and 0.1 . High values will lead to RIDs with very few elements, while values approaching 0 will lead to large RIDs. Typically set to 0.05.
# Tolerance
tolGIE =  0.05

3 – Optional parameters

# Optionnal
verbose = False
nbrCPU = 4
packageName = 'test'
addToLib = False

We can now execute one of the reduction we choose with all these parameters



The execution is done with an object from the class ReduceModel. we initialize it with all the previous argument either for the Diamond or Starfish example

# Initialization of our script
nodesToReduce = nodesToReduce_DIAMOND # nodesToReduce_STARFISH
listObjToAnimate = listObjToAnimate_DIAMOND # listObjToAnimate_STARFISH
addRigidBodyModes = addRigidBodyModes_DIAMOND # addRigidBodyModes_STARFISH

reduceMyModel = ReduceModel(    originalScene,  
                                meshes = meshes,
                                packageName = packageName,
                                addToLib = addToLib,
                                verbose = verbose,
                                addRigidBodyModes = addRigidBodyModes)

We can finally perform the actual reduction. here is a schematic to resume the differents steps we will perform :

MOR Process SchematicMOR Process Schematic

Phase 1


We modify the original scene to do the first step of MOR :

  • We add animation to each actuators we want for our model
  • And add a writeState componant to save the shaking resulting states

Phase 2


With the previous result we combine all the generated state files into one to be able to extract from it the different mode

# Plot result
with open(reduceMyModel.packageBuilder.debugDir+'Sdata.txt') as f:
    content = f.readlines()
content = [x.strip() for x in content]

data = [go.Bar(x=range(1, len(content)+1),

iplot(data, filename='jupyter/basic_bar')
print("Maximum number of Modes : ")

Phase 3


We launch again a set of sofa scene with the sofa launcher with the same previous arguments but with a different scene

This scene take the previous one and add the model order reduction component:

  • HyperReducedFEMForceField
  • MechanicalMatrixMapperMOR
  • ModelOrderReductionMapping and produce an Hyper Reduced description of the model

Phase 4


Final step : we gather again all the results of the previous scenes into one and then compute the RID and Weigts with it. Additionnally we also compute the Active Nodes

reducedScene = reduceMyModel.phase4()

End of example you can now go test the results in the folder you have designed at the beginning of this tutorial

To go Further

Links to additional information about the plugin:

Publication in IEEE Transactions On Robotics

Plugin website

Plugin doc