OpenSeesPy
OpenSeesPy is a Python 3 interpreter for the Open System for Earthquake Engineering Simulation (OpenSees), a powerful software framework for finite element analysis. It provides robust capabilities for structural analysis, including linear, nonlinear, static, and dynamic analysis of structures. Currently at version 3.8.0.0, the library is actively developed with frequent updates and releases.
Common errors
-
ModuleNotFoundError: No module named 'openseespy.opensees'
cause The openseespy package is either not installed or not installed in the active Python environment.fixEnsure `openseespy` is installed in your current environment: `pip install openseespy`. If using virtual environments (conda, venv), activate the correct environment before installation and running. -
OpenSeesError: domain.cpp:166:setElement(): WARNING element tag 1 already exists - will be ignored.
cause Attempting to create an element (or node, material, etc.) with a tag (ID) that has already been used in the current model. This often happens when re-running parts of a script or iterating without clearing the model.fixCall `ops.wipe()` at the beginning of your script or before defining a new model to clear any previous definitions. Ensure unique tags for all model components. -
OpenSeesError: (some command) - missing a required argument (some_argument)
cause An OpenSeesPy command was called without providing all the necessary arguments, or arguments are in the wrong order.fixConsult the OpenSeesPy documentation for the specific command to verify the required arguments and their order. Pay close attention to optional arguments and flags. -
OpenSeesError: StaticAnalysis::analyze() - the Newton-Raphson algorithm failed to converge in 10 iterations
cause The numerical solver failed to find a converged solution within the specified number of iterations, often due to highly nonlinear behavior, numerical instability, or an ill-posed model.fixReview your model for instabilities (e.g., zero stiffness, incorrect boundary conditions, very large loads). Try adjusting analysis parameters such as the `test` command's tolerance or number of iterations, or the `integrator`'s load increment. Consider using different `algorithm` or `system` commands.
Warnings
- breaking OpenSeesPy requires Python 3.10 or newer. Installing with older Python versions (e.g., Python 3.6, which was previously supported) will lead to installation or runtime failures.
- gotcha Commercial redistribution or use in commercial applications/cloud services requires a specific license, similar to OpenSees. The PyPI package is free for research, education, and internal use.
- gotcha OpenSeesPy commands are sensitive to Python data types. Explicit casting (e.g., `float()`) may be necessary where an `int` might implicitly be used but a `float` is expected by the underlying OpenSees C++ routines, leading to unexpected behavior or errors.
- gotcha Many internal OpenSees errors are caught and re-raised as Python `OpenSeesError` exceptions. If not handled, these will terminate your script, making it difficult to debug or implement robust iterative analyses.
- gotcha It is crucial to call `ops.wipe()` at the beginning of any new model definition script or before starting a new analysis in the same session. Failing to do so can lead to residual model data from previous runs, causing incorrect or unexpected results.
Install
-
pip install openseespy
Imports
- ops
import openseespy
import openseespy.opensees as ops
- opsplt
import openseespy.postprocessing.Get_Rendering as opsplt
Quickstart
import openseespy.opensees as ops
# 1. Start a new model
ops.wipe()
ops.model('basic', '-ndm', 2, '-ndf', 3)
# 2. Define nodes
ops.node(1, 0.0, 0.0)
ops.node(2, 100.0, 0.0)
ops.node(3, 0.0, 100.0)
# 3. Set boundary conditions
ops.fix(1, 1, 1, 1) # Node 1: Fixed in x, y, and rotation
ops.fix(2, 0, 1, 0) # Node 2: Fixed in y
# 4. Define material
# uniaxialMaterial('Elastic', matTag, E)
ops.uniaxialMaterial('Elastic', 1, 200000.0) # Steel, E in appropriate units
# 5. Define elements (e.g., truss element)
# element('truss', eleTag, iNode, jNode, A, matTag)
ops.element('truss', 1, 1, 3, 10.0, 1)
ops.element('truss', 2, 2, 3, 10.0, 1)
# 6. Define loads
# Create a time series (constant load factor)
ops.timeSeries('Constant', 1)
# Create a plain load pattern
ops.pattern('Plain', 1, 1)
# Apply nodal load (Node 3: -10kN in y-direction)
ops.load(3, 0.0, -10.0, 0.0)
# 7. Setup analysis
ops.constraints('Plain')
ops.numberer('RCM')
ops.system('BandSPD')
ops.test('NormDispIncr', 1e-6, 10)
ops.algorithm('Linear')
ops.integrator('LoadControl', 0.1)
ops.analysis('Static')
# 8. Perform analysis
ops.analyze(10)
# 9. Get results (example: node 3 displacement)
disp_y = ops.nodeDisp(3, 2)
print(f"Vertical displacement at node 3: {disp_y:.4f}")
ops.wipe() # Clear the model from memory