Use User Subroutines

User subroutines can be used in the same way in optimization as is in a normal analysis.

However, if you choose to use the parallel finite difference method in optimization (the default when finite differencing is selected), then you should be aware of some special restrictions.

The parallel finite differencing approach in MotionSolve uses the Pickle module to communicate and receive data between the multiple processes.

Pickle implements an algorithm for serializing and de-serializing a Python object. “Pickling” is the process for converting a Python object hierarchy into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream is converted back into an object hierarchy.

The parallel finite differencing approach in MotionSolve uses “pickling” and “unpickling” to communicate and receive data between the multiple processes.

For finite differencing, the user subroutine should be “pickleable”. In our context, this means the user subroutine should always be defined at the top level the script. For example, if you want to define a marker with a routine called calci, it must be defined as a separate function at the top level:
from msolve.optimize import *
def calci(id,par,npar): 
    ……
You cannot define it in the scope of another function definition like this:
from msolve.optimize import *
def function1(……): 
…… 
   def calci(id,par,npar):
    ……

Likewise, you should not define the user subroutine as a class method. The class method is not recognized as a top-level object in Python although the class itself might be on the top level. In the following, calci, is not pickleable:

from msolve.optimize import *
class Fourbar(……): 
…… 
   def calci(self,id,par,npar):
    …… 

For more details on pickle, refer to the Python documentation on pickle.