Using OOFEM from Python¶
Besides being a standalone solver, OOFEM can be used as a Python module. This is useful when the analysis is only one step of a larger workflow — a parameter study, an optimization loop, or postprocessing with numpy and matplotlib — and when you want to implement a new component (a material model, a boundary condition, a time function) in Python rather than in C++.
This section is only a short overview. The Python interface is documented in full in the OOFEM Python bindings manual.
Getting the module¶
Configure the build with USE_PYBIND_BINDINGS (see Installation),
which produces an oofempy module in the build directory. Make the build directory visible to Python:
$ export PYTHONPATH=/home/user/oofem.build:$PYTHONPATH
Running an existing input file¶
The shortest useful thing you can do is to run an ordinary input file and drive the solution loop yourself:
import oofempy
dr = oofempy.OOFEMTXTDataReader("beam2d_1.in")
problem = oofempy.InstanciateProblem(dr, oofempy.problemMode.processor, 0, None, False)
problem.checkProblemConsistency()
problem.init()
problem.solveYourself()
problem.terminateAnalysis()
This is exactly what the oofem executable does, and it produces the same
output file. Once the problem object exists, though, you can reach into it
between steps — query nodal unknowns, change boundary condition values, and
solve again — which is what makes the interface worth using.
Building a problem programmatically¶
The whole input file can also be bypassed: every component (domain, nodes, elements, cross sections, materials, boundary conditions, functions, sets) has a corresponding Python constructor, so a model can be assembled directly in Python without any input file at all. See the “Building a problem” chapter of the Python bindings manual for the pattern, and the bindings/python/tests directory for complete working examples, which are part of the test suite and therefore always up to date with the current interface.
Calling Python from the input file¶
The traffic also goes the other way: an ordinary input file can refer to code written in Python, and OOFEM will call it during the analysis. Two independent build options are involved.
A build configured with USE_PYTHON_EXTENSION embeds a Python interpreter
and enables components driven by Python expressions:
pythonexpressionA function whose value (and optionally its time derivatives) is given as a Python expression in the
f,dfdtandd2fdt2fields, or read from a file named byfpath. Usable anywhere a function is, so any boundary condition can be given an arbitrary time variation without recompiling.userdefdirichletbc,usrdefboundaryloadA Dirichlet boundary condition and a boundary load whose values are evaluated by user-supplied Python code, which lets them depend on position and on the state of the analysis.
A build configured with USE_PYBIND_BINDINGS additionally provides
pythonmaterial, a material model implemented in Python. The input record
names the Python module to import and the object within it to use (the
module and object fields). That object must provide
hasMaterialModeCapability, giveCharacteristicMatrix,
giveCharacteristicVector and giveCharacteristicValue — and optionally
printOutputAt — mirroring the C++ material interface; per-integration-point
history is kept for it in a Python dictionary that OOFEM commits or rolls back
along with the rest of the solution state. This is the fastest route to trying
out a new constitutive model, at the cost of the per-call overhead of the
Python interpreter.