Object-oriented native Python version of OpenSees
Project description
o3seespy
Object-oriented native python version of OpenSees
Features
This package provides:
A ‘pythonic’ version of OpenSees - all input parameters to create OpenSees objects are all lowercase key-value arguments - all class objects are CamelCase - static string variables defined in ALL_CAPS - Where possible the exact name used in the original TCL version has been kept
Fully namespaced package allowing full auto-complete e.g. ‘o3.uniaxial_material.Steel01(…)’
Replication of underlying object-oriented C++ source code using Python objects.
Type checking of inputs before calling C++ OpenSees code, so that python debugging and errors can be viewed
In code documentation using python docstrings - can view the documentation within your IDE
Additional features for using OpenSees in python: - saving and loading data directly from OpenSees into numpy arrays - saving and loading data directly from OpenSees into json files - Save an entire model as a json file - allows efficient passing of models between servers
All object numbering handled by objects - no need for number tags!
Additional logic checking of optional inputs
How to Use
Installation
pip install o3seespy
Example: Dynamic inelastic SDOF analysis
import numpy as np
import matplotlib.pyplot as plt
import o3seespy as o3
from tests.conftest import TEST_DATA_DIR
# Load a ground motion
dt = 0.01
rec = np.loadtxt(TEST_DATA_DIR + 'test_motion_dt0p01.txt')
# Define inelastic SDOF
period = 1.0
xi = 0.05
mass = 1.0
f_yield = 1.5 # Reduce this to make it nonlinear
r_post = 0.0
# Initialise OpenSees instance
osi = o3.OpenSeesInstance(ndm=2, state=0)
# Establish nodes
bot_node = o3.node.Node(osi, 0, 0)
top_node = o3.node.Node(osi, 0, 0)
# Fix bottom node
o3.Fix3DOF(osi, top_node, o3.cc.FREE, o3.cc.FIXED, o3.cc.FIXED)
o3.Fix3DOF(osi, bot_node, o3.cc.FIXED, o3.cc.FIXED, o3.cc.FIXED)
# Set out-of-plane DOFs to be constrained
o3.EqualDOF(osi, top_node, bot_node, [o3.cc.DOF_Y, o3.cc.ROTZ])
# nodal mass (weight / g):
o3.Mass(osi, top_node, mass, 0., 0.)
# Define material
k_spring = 4 * np.pi ** 2 * mass / period ** 2
bilinear_mat = o3.uniaxial_material.Steel01(osi, fy=f_yield, e0=k_spring, b=r_post)
# Assign zero length element, # Note: pass actual node and material objects into element
o3.element.ZeroLength(osi, [bot_node, top_node], mats=[bilinear_mat], dirs=[o3.cc.DOF_X], r_flag=1)
# Define the dynamic analysis
load_tag_dynamic = 1
pattern_tag_dynamic = 1
# Define the dynamic analysis
acc_series = o3.time_series.Path(osi, dt=dt, values=-1 * rec) # should be negative
o3.pattern.UniformExcitation(osi, dir=o3.cc.X, accel_series=acc_series)
# set damping based on first eigen mode
angular_freq = o3.get_eigen(osi, solver='fullGenLapack', n=1)[0] ** 0.5
beta_k = 2 * xi / angular_freq
o3.rayleigh.Rayleigh(osi, alpha_m=0.0, beta_k=beta_k, beta_k_init=0.0, beta_k_comm=0.0)
# Run the dynamic analysis
o3.wipe_analysis(osi)
# Run the dynamic analysis
o3.algorithm.Newton(osi)
o3.system.SparseGeneral(osi)
o3.numberer.RCM(osi)
o3.constraints.Transformation(osi)
o3.integrator.Newmark(osi, gamma=0.5, beta=0.25)
o3.analysis.Transient(osi)
o3.test_check.EnergyIncr(osi, tol=1.0e-10, max_iter=10)
analysis_time = (len(rec) - 1) * dt
analysis_dt = 0.001
outputs = {
"time": [],
"rel_disp": [],
"rel_accel": [],
"rel_vel": [],
"force": []
}
while o3.get_time(osi) < analysis_time:
o3.analyze(osi, 1, analysis_dt)
curr_time = o3.get_time(osi)
outputs["time"].append(curr_time)
outputs["rel_disp"].append(o3.get_node_disp(osi, top_node, o3.cc.X))
outputs["rel_vel"].append(o3.get_node_vel(osi, top_node, o3.cc.X))
outputs["rel_accel"].append(o3.get_node_accel(osi, top_node, o3.cc.X))
o3.gen_reactions(osi)
outputs["force"].append(-o3.get_node_reaction(osi, bot_node, o3.cc.X)) # Negative since diff node
o3.wipe(osi)
for item in outputs:
outputs[item] = np.array(outputs[item])
plt.plot(outputs['time'], outputs['rel_disp'], label='o3seespy')
periods = np.array([period])
# Compare closed form elastic solution
from eqsig import sdof
resp_u, resp_v, resp_a = sdof.response_series(motion=rec, dt=dt, periods=periods, xi=xi)
plt.plot(np.arange(len(rec)) * dt, resp_u[0], ls='--', label='Elastic')
plt.legend()
plt.savefig('readme_example.png')
plt.show()
Useful material
Contributing
How do I get set up?
Run pip install -r requirements.txt
Package conventions
- All names should be the same as the OpenSees tcl version, except:
The name should be converted to snake_case for a parameter or function
The name should be converted to CamelCase for an Object
The name should be converted to ALL_CAPS for static variables
If the name matches a python special name (e.g. lambda, in) then it should be adjusted according to the dictionary
Objects should be namespaced based on the object type (e.g. element, material)
For parameter that are used across many objects (e.g. atmospheric pressure) a standard name should be used
OpenSees functions that collect a result are named ‘get_<function-name>’
OpenSees functions that generate results are named ‘gen_<function-name>’
How should youngs modulus be named?
Should all two node elements use i_node, j_node. Or make them all enter nodes as a list?
Testing
Tests are run with pytest
Locally run: pytest on the command line.
Tests are run on every push using travis, see the .travis.yml file
Deployment
To deploy the package to pypi.com you need to:
Push to the pypi branch. This executes the tests on circleci.com
Create a git tag and push to github, run: trigger_deploy.py or manually:
git tag 0.5.2 -m "version 0.5.2"
git push --tags origin pypi
Documentation
Built via Sphinx following: https://codeandchaos.wordpress.com/2012/07/30/sphinx-autodoc-tutorial-for-dummies/
For development mode
cd to docs
Run make html
Docstrings follow numpy convention (in progress): https://numpydoc.readthedocs.io/en/latest/format.html
To fix long_description in setup.py: pip install collective.checkdocs, python setup.py checkdocs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file o3seespy-3.4.0.7.tar.gz
.
File metadata
- Download URL: o3seespy-3.4.0.7.tar.gz
- Upload date:
- Size: 249.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9c78782ef9f0fbbf0b914115c56599462424e4769b0eb8884ff9f93968fc727a |
|
MD5 | c8386b6b97bea49e734ef4a8170e6b91 |
|
BLAKE2b-256 | 486bffddfecb1bef3ffdc042744a5b0efaafa470904b8a95b126f070825f94ad |