Command manual

Command list

Python scripting

Python scripting

Python scriptning extends the functionality of *FUNCTION and *PARAMETER with a more powerful way of defining custom workflow. This document describes the basics of how it can used.

IMPETUS Afea Solver uses Python 3 and it is embedded in the Windows version. Linux users must install python3 from the package manager. For use of external modules installed from pip, Python 3 must also be installed externally on Windows systems.

Writing the Python script

If you are not familiar with Python, please, check out the tutorial and documentation below:

The basics steps are: 1 read the input data (parameters), 2 do the necessary calculations and 3 return the desired value. It's important that the function actually returns a value, else the return value will be set to zero. It's also important to know that function names are case sensitive.

The example below shows a module named py_module with the function func(). The function contains one parameter called time. This parameter is passed on from the input deck in the *FUNCTION command.

Python script: py_module.py
def func(time):
    if time < 1.0:
        return 0.5
    else:
        return 1.0

Including a Python script (module) into the simulation

In order to use a function defined in Python, the file needs to be added with the *SCRIPT_PYTHON command. The name of the file must end with an .py extension. Script files loaded into Python are treated as modules with the file name as module name. Be aware that the name of the module is case sensitive.

# Adding the python file *SCRIPT_PYTHON
py_module.py

The code above loads py_module.py as a module with the name py_module. It will later be used in the *FUNCTION command.

Calling Python function from *FUNCTION

Calling a Python function works just like calling one of the built-in functions. It must, however, be preceded by the module name seperated with a period. Example:
module_name.function_name(...)

*FUNCTION
1000
epsp * py_module.funcA(fxc(1), pres) *FUNCTION
2000
py_module.funcB(epsp)

One can also call two different functions from two different modules. In this example, we load python_file_A.py and python_file_B.py. Both of these modules will work independently from each other.

Any parameters that can be used in *FUNCTION, can also be sent into the python function.

*SCRIPT_PYTHON
python_file_A.py python_file_B.py *FUNCTION
1000
python_file_A.func(epsp) * python_file_B.func(t)

Calling Python function from *PARAMETER

Calling a Python function from *PARAMETER is essentially the same as calling from *FUNCTION. The difference is that the returned value is assigned to variable, and the function is only executed once during the initialization.

Python functions called from *PARAMETER can also return a Python list (array) of variables. If a list is returned from Python, then the varaible in the input deck will be defined as a vector.

For usage with *PARAMETER, the python file must be included before it is called from *PARAMETER.

*SCRIPT_PYTHON
python_file.py *PARAMETER
value = python_file.func(1, 2)

Conclusion & example

Summarize:

  • A script file (module) must be loaded with the *SCRIPT_PYTHON command.
  • Both module names and functions are case sensitive.
  • Functions must return a value, else it returns the value zero.
  • Print statements are good for debug purposes but should otherwise be avoided.
  • Python functions are called by both the module and function name, seperated by a period sign.

The example below shows the usage of the output interval for imp-output. We send in the variables: t (time) and fxc (contact force) into the function fuser(). This function evaluates the time and the contact force. If the contact force is less than 1.0, a larger output interval is returned. In every other case, a smaller output interval will returned. One exception is when the time passes 3.0e-4, then it will return a larger output interval.

*TIME 0.001 *OUTPUT fcn(1000) *SCRIPT_PYTHON output.py *FUNCTION "output interval" 1000 output.fuser(t, fxc(1))
Python script: output.py
def fuser(t, fxc):
    if fxc < 1.0 or t > 3.0e-4:
        return 1.0e-4 
    else:
        return 1.0e-5