Model Order Reduction NoteBook

Introduction

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 :

Diamond robot

Starfish 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

sys.path.append(os.getcwd()+'/../python')

# MOR IMPORT
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 where you want the results to be put in

# Select Output Dir and original scene name & path
from PyQt5 import QtWidgets
app = QtWidgets.QApplication(sys.argv)

originalScene = utility.openFileName('Select the SOFA scene you want to reduce')
outputDir = utility.openDirName('Select the directory that will contain all the results')

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

2. The different reduction parameters

nodeToReduce

contains the SOFA path from the rootnode to the model you want to reduce.

nodesToReduce_DIAMOND = ['/modelNode']
nodesToReduce_STARFISH =['/model']

listObjToAnimate

Contains a list of objects from the class ObjToAnimate.

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

There are 3 main parameters 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 arguments that will be passed to the animFct we have chosen.

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

  • incrPeriod (float): Period between each increment

  • incr (float): Value of each increment

  • rangeOfAction (float): Until which value the data will increase

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

# animation parameters

### CABLE-DRIVEN PARALLEL ROBOT PARAMETERS
north = ObjToAnimate("modelNode/north", incr=5,incrPeriod=10,rangeOfAction=40)
south = ObjToAnimate("modelNode/south", incr=5,incrPeriod=10,rangeOfAction=40)
east = ObjToAnimate("modelNode/east", incr=5,incrPeriod=10,rangeOfAction=40)
west = ObjToAnimate("modelNode/west", incr=5,incrPeriod=10,rangeOfAction=40)
listObjToAnimate_DIAMOND = [north,south,east,west]

### MULTIGAIT SOFT ROBOT PARAMETERS
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
  • verbose

    can bring more useful log while doing a reduction.

  • nbrCPU

    depending on the number of ObjToAnimate you have previously declared, the reduction process will need to launch many sofa scenes with different animation patterns. To do that faster we can parallelise this process by indicating a number of CPU and doing so the number of scenes that will be run simultaneously.

  • addToLib & packageName

    These 2 variables are to be used if you want at the end of the reduction to create a reusable python module of the result that will be placed in /python/morlib to import and use it easily in your scene.

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

Execution

Initialization

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,  
                                nodesToReduce,
                                listObjToAnimate,
                                tolModes,tolGIE,
                                outputDir,
                                packageName = packageName,
                                addToLib = addToLib,
                                verbose = verbose,
                                addRigidBodyModes = addRigidBodyModes)

We can finally perform the actual reduction.

phase1

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

reduceMyModel.phase1()

phase2

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

reduceMyModel.phase2()
print("Maximum number of Modes : ")
reduceMyModel.reductionParam.nbrOfModes

phase3

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

reduceMyModel.phase3()

phase4

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