Opensees Package - "Failed to import on Windows" Problem

Hello All,

I am a structural engineer who tries to use opensees package inside dynamo then I could create parametric structural analysis. The problem is that:

I have followed procedure that is explained below for adding external packages.

In the light of the information I have created a simple script that gives me attached warning. Can anyone face with similar problem?

Looks like the latest version of OpenSeesPy requires Python version 3.11. I am not sure if the default Dynamo engine covers that build - the initial was 3.8 if I recall. Check what Python version you’re using by calling sys.version - something like

import sys
OUT = sys.version

It is 3.9.12

And as such the latest version of OpenSeesPy package won’t work. You’ll need to find a version which is built for Python 3.9. I believe you will also need to install OpenSees itself, so be sure to get the version of OpenSees which was built for the OpenSeesPy version which you wind up using. The OpenSeesPy GitHub is likely a better place to get help with this task.

Alternatively you can look into Robot Structural Analysis or other tools (I have seen applications which are entirely Python based work).

Try using the OpenSeesPyWin package. I was able to get it running after installing Tcl. Sorry, for finding this late, but I’m very curious to see if small calculations could automated using OpenSees, e.g. resizing single frames without export/import/analysis. This is at least an example of opensees running in Dynamo Python, but I’m still in Python 3.8 rather than 3.9.

import os
import sys
import ctypes
import traceback

# Add the directory containing tcl86t.dll to the DLL search path
tcl_path = 'C:\\ActiveTcl\\bin'
if os.path.exists(tcl_path):
    os.add_dll_directory(tcl_path)

# Verify if the Tcl DLL exists
tcl_dll_path = os.path.join(tcl_path, 'tcl86t.dll')
if os.path.exists(tcl_dll_path):
    try:
        # Load the Tcl DLL with full path
        ctypes.CDLL(tcl_dll_path)
        result = "Tcl DLL loaded successfully!"
    except Exception as e:
        result = "Error loading Tcl DLL: {}".format(e)
else:
    result = "Tcl DLL not found at {}".format(tcl_dll_path)

# Add the directory containing opensees.pyd to the DLL search path
openseespywin_path = 'C:\\Users\\USJP722564\\AppData\\Local\\python-3.8.3-embed-amd64\\Lib\\site-packages\\openseespywin'
if os.path.exists(openseespywin_path):
    os.add_dll_directory(openseespywin_path)

# Verify if the OpenSeesPyWin PYD exists
opensees_pyd_path = os.path.join(openseespywin_path, 'opensees.pyd')
if os.path.exists(opensees_pyd_path):
    try:
        # Load the OpenSees PYD
        ctypes.CDLL(opensees_pyd_path)
        result += "\nOpenSeesPyWin PYD loaded successfully!"
    except Exception as e:
        result += "\nError loading OpenSeesPyWin PYD: {}".format(e)
else:
    result += "\nOpenSeesPyWin PYD not found at {}".format(opensees_pyd_path)

# Set TCL_LIBRARY and TK_LIBRARY environment variables explicitly
os.environ['TCL_LIBRARY'] = 'C:\\ActiveTcl\\lib\\tcl8.6'
os.environ['TK_LIBRARY'] = 'C:\\ActiveTcl\\lib\\tk8.6'

# Try to import OpenSeesPyWin with detailed logging
try:
    from openseespywin.opensees import *
    result += "\nOpenSeesPyWin imported successfully!"

    # Inputs
    node_coords = IN[0]  # List of node coordinates
    connectivity = IN[1]  # List of connectivity pairs
    fixities = IN[2]  # List of dictionaries with fixity and node id
    
    # Initialize OpenSees model
    wipe()
    model('basic', '-ndm', 2, '-ndf', 3)
    
    # Define nodes
    for i, coords in enumerate(node_coords, start=1):
        node(i, *coords)
    
    # Define truss elements (connectivity)
    uniaxialMaterial('Elastic', 1, 3000.0)
    for i, (start, end) in enumerate(connectivity, start=1):
        element('truss', i, start, end, 1.0, 1)
    
    # Define boundary conditions (fixities)
    for fixity in fixities:
        node_id = fixity['Node']
        fixity_value = fixity['Fixity']
        
        if fixity_value == 3:  # Pinned condition
            fix(node_id, 1, 1, 0)  # Constrain translation, free rotation
        else:  # Unpinned condition
            fix(node_id, 0, 0, 0)  # No constraints
    
    # Define loads (example: applying a unit load to the last node)
    timeSeries('Linear', 1)
    pattern('Plain', 1, 1)
    load(len(node_coords), 0.0, -1.0)  # Example load applied to the last node
    
    # Define analysis settings
    system('BandSPD')
    numberer('Plain')
    constraints('Plain')
    integrator('LoadControl', 1.0)
    algorithm('Newton')
    analysis('Static')
    
    # Perform the analysis
    analyze(1)
    
    # Get results
    node_displacements = []
    for i in range(1, len(node_coords) + 1):
        disp = nodeDisp(i)
        node_displacements.append(disp)
    
    result += "\nAnalysis completed successfully!"
    result += "\nNode Displacements: {}".format(node_displacements)
    
except ImportError as e:
    result += "\nError importing OpenSeesPyWin: {}".format(e)
except Exception as e:
    error_details = traceback.format_exc()
    result += "\nAn error occurred: {}".format(e)
    result += "\nError details: {}".format(error_details)

OUT = result