Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
opstool 1.0.25 documentation
Light Logo Dark Logo

Quick Start

  • Installation
  • Known Issues
  • Quick Start
    • Two-Dimensional Moment Frame Analysis
    • Quick Model and Eigen Visualization
    • 606 m Mega-tall Building
  • Features

User Guide

  • Pre-Processing
    • Fiber Section Mesh
    • Converting GMSH to OpenSeesPy
    • Convert Tcl code to OpenSeesPy commands
    • Automatic Unit Conversion
    • Quickly apply gravity loads and obtain mass and stiffness matrices
    • Loads Processing
  • Post-Processing
    • Eigenvalue Results
    • Node Response
    • Frame element Response
    • Post-processing for fiber section responses
    • Truss element Response
    • Shell element Response
    • Planar element response
    • Brick element Response
    • Simple cantilever for load-controlled sensitivity analysis
    • Unit conversion in post-processing
  • Visualization
    • Plotyly-Based Visualization
      • Model Geometry
      • Eigen
      • Nodal Responses Visualization
      • Frame Element Responses
      • Truss Element Responses
      • Shell Element Responses
      • Plane stress quad model visualization
      • Solid Element Responses
    • Pyvista-Based Visualization
      • Model Geometry
      • Eigen
      • Nodal Responses Visualization
      • Frame Element Responses
      • Truss Element Responses
      • Shell Element Responses
      • Plane stress quad model visualization
      • Solid Element Responses
  • Analysis
    • Smart Analysis
    • Moment Curvature Analysis of Section
    • Linear Buckling Analysis
    • Response Spectrum Analysis

Examples

  • Post-Processing
  • Pre-Processing
  • Fiber Section Mesh
    • Post-Processing
      • Reinforced Concrete Frame Pushover Analysis
      • Dry single BbarBrick element with pressure dependent material
      • Cantilever Bending Roll-up (corotational)
      • Double-Layer Shallow Dome
      • Remove and Add Elements
      • Excavation Supported by Cantilevered Sheet Pile Wall
      • Modal analysis of a cooling tower
      • Fluid-structure interaction
      • 3D Nonlinear beam-column elements Gravity load analysis followed by transient analysis
      • Two storey steel moment frame with W-sections for displacement-controlled sensitivity analysis
      • Soil-Structure Interaction
    • Pre-Processing
      • Gmsh2OPS: Case 1
      • Gmsh2OPS: Case 2
      • 3D Beam Element Example - A Dome Structure
      • Gmsh2OPS: Linear shell arch model
    • Fiber Section Mesh
      • Bridge superstructure section
      • Concrete-Filled Steel Tube (CFST) Section Meshing
      • Steel-Concrete Composite Section Meshing
      • Hollow Rectangular RC Section
      • Interaction with sectionproperties

API Reference

  • Global Functions
    • set_opensees_module
    • load_ops_examples
    • add_ops_hints_file
    • run_model
    • print_version
  • Preprocessing
    • Fiber Section Mesh
      • FiberSecMesh
      • SecMesh
      • create_material
      • create_polygon_patch
      • create_circle_patch
      • create_patch_from_dxf
      • create_polygon_points
      • create_circle_points
      • offset
      • line_offset
      • poly_offset
      • set_patch_material
      • vis_fiber_sec_real
      • opstool.pre.section.section
      • opstool.pre.section.fiber
      • opstool.pre.section.patch
      • opstool.pre.section.layer
      • opstool.pre.section.plot_fiber_sec_cmds
    • tcl2py
    • Gmsh2OPS
    • UnitSystem
    • create_gravity_load
    • gen_grav_load
    • transform_beam_uniform_load
    • transform_beam_point_load
    • transform_surface_uniform_load
    • apply_load_distribution
    • get_node_coord
    • get_node_mass
    • get_mck
    • ModelMass
    • find_void_nodes
    • remove_void_nodes
  • Postprocessing
    • get_nodal_responses_info
    • get_element_responses_info
    • set_odb_path
    • set_odb_format
    • update_unit_system
    • reset_unit_system
    • plot_nodal_responses
    • plot_element_responses
    • save_model_data
    • save_eigen_data
    • save_linear_buckling_data
    • CreateODB
    • get_nodal_responses
    • get_element_responses
    • get_sensitivity_responses
    • get_model_data
    • get_eigen_data
    • get_linear_buckling_data
  • Visualization
    • set_plot_props
    • set_plot_colors
    • plot_model
    • plot_eigen
    • plot_eigen_animation
    • plot_eigen_table
    • plot_nodal_responses
    • plot_nodal_responses_animation
    • plot_truss_responses
    • plot_truss_responses_animation
    • plot_frame_responses
    • plot_frame_responses_animation
    • plot_unstruct_responses
    • plot_unstruct_responses_animation
    • set_plot_props
    • set_plot_colors
    • plot_model
    • plot_eigen
    • plot_eigen_animation
    • plot_nodal_responses
    • plot_nodal_responses_animation
    • plot_truss_responses
    • plot_truss_responses_animation
    • plot_frame_responses
    • plot_frame_responses_animation
    • plot_unstruct_responses
    • plot_unstruct_responses_animation
    • get_nodal_responses_dataset
    • get_unstruct_responses_dataset
  • Analysis
    • SmartAnalyze
    • MomentCurvature

Theory Reference

  • Stress and Strength Criteria
yexiang92/opstool 1.0.25
Back to top
View this page
Edit this page

Note

Go to the end to download the full example code.

Modal analysis of a cooling tower¶

To OpenSeesPy Model¶

import openseespy.opensees as ops

import opstool as opst
ops.wipe()
ops.model("basic", "-ndm", 3, "-ndf", 6)
E, nu, rho = 2.76e10, 0.166, 2244.0  # Pa, kg/m3
ops.nDMaterial("ElasticIsotropic", 1, E, nu, rho)
secTag = 11
ops.section("PlateFiber", secTag, 1, 0.305)

Read gmsh

GMSH2OPS = opst.pre.Gmsh2OPS(ndm=3, ndf=6)
GMSH2OPS.read_gmsh_file("utils/forma11c.msh")
Info:: 1 Physical Names.
Info:: 1821 Nodes; MaxNodeTag 1821; MinNodeTag 1.
Info:: 2009 Elements; MaxEleTag 2009; MinEleTag 1.
Info:: Geometry Information >>>
53 Entities: 37 Point; 12 Curves; 4 Surfaces; 0 Volumes.

Info:: Physical Groups Information >>>
1 Physical Groups.
Physical Group names: ['Boundary']

Info:: Mesh Information >>>
1821 Nodes; MaxNodeTag 1821; MinNodeTag 1.
1972 Elements; MaxEleTag 2009; MinEleTag 1.

Create OpenSeesPy node commands based on all nodes defined in the GMSH file

node_tags = GMSH2OPS.create_node_cmds()
dim_entity_tags = GMSH2OPS.get_dim_entity_tags()
dim_entity_tags_2D = [item for item in dim_entity_tags if item[0] == 2]

Create OpenSeesPy element commands for specific entities

ele_tags_n4 = GMSH2OPS.create_element_cmds(
    ops_ele_type="ASDShellQ4",  # OpenSeesPy element type
    ops_ele_args=[secTag],  # Additional arguments for the element (e.g., section tag)
    dim_entity_tags=dim_entity_tags_2D,
)
Using ASDShellQ4 - Developed by: Massimo Petracca, Guido Camata, ASDEA Software Technology

Apply boundary conditions

boundary_dim_tags = GMSH2OPS.get_boundary_dim_tags(physical_group_names="Boundary", include_self=True)
print(boundary_dim_tags)
fix_ntags = GMSH2OPS.create_fix_cmds(dim_entity_tags=boundary_dim_tags, dofs=[1] * 6)
removed_node_tags = opst.pre.remove_void_nodes()
[(0, 55), (0, 59), (0, 61), (0, 63), (1, 6), (1, 9), (1, 12), (1, 15)]
Info:: Free nodes with tags [57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85] have been removed!

Visualize the model

opst.vis.pyvista.plot_model(show_outline=True).show()
ex forma11c

Modal analysis

opst.post.save_eigen_data(odb_tag="eigen", mode_tag=60)
fig = opst.vis.pyvista.plot_eigen(mode_tags=12, odb_tag="eigen", subplots=True)
fig.show()
ex forma11c
Using DomainModalProperties - Developed by: Massimo Petracca, Guido Camata, ASDEA Software Technology
OPSTOOL™ ::  Eigen data has been saved to G:\opstool\docs\.opstool.output/EigenData-eigen.zarr!
OPSTOOL™ ::  Loading eigen data from G:\opstool\docs\.opstool.output/EigenData-eigen.zarr ...

Modal Properties

modal_props, eigen_vectors = opst.post.get_eigen_data(odb_tag="eigen")
modal_props = modal_props.to_pandas()
modal_props.head()
OPSTOOL™ ::  Loading eigen data from G:\opstool\docs\.opstool.output/EigenData-eigen.zarr ...
Properties eigenLambda eigenOmega eigenFrequency eigenPeriod partiFactorMX partiFactorMY partiFactorRMZ partiFactorMZ partiFactorRMX partiFactorRMY partiMassMX partiMassMY partiMassRMZ partiMassMZ partiMassRMX partiMassRMY partiMassesCumuMX partiMassesCumuMY partiMassesCumuRMZ partiMassesCumuMZ partiMassesCumuRMX partiMassesCumuRMY partiMassRatiosMX partiMassRatiosMY partiMassRatiosRMZ partiMassRatiosMZ partiMassRatiosRMX partiMassRatiosRMY partiMassRatiosCumuMX partiMassRatiosCumuMY partiMassRatiosCumuRMZ partiMassRatiosCumuMZ partiMassRatiosCumuRMX partiMassRatiosCumuRMY
modeTags
1 51.13809 7.151090 1.138131 0.878633 2.133296e-10 6.395783e-11 -5.687698e-10 2.489633e-11 -2.639758e-10 6.281351e-09 4.550953e-20 4.090604e-21 3.234991e-19 6.198272e-22 6.968322e-20 3.945537e-17 4.550953e-20 4.090604e-21 3.234991e-19 6.198272e-22 6.968322e-20 3.945537e-17 1.869924e-25 1.680773e-26 7.347386e-28 2.546785e-27 1.156468e-28 6.548041e-26 1.869924e-25 1.680773e-26 7.347386e-28 2.546785e-27 1.156468e-28 6.548041e-26
2 51.13809 7.151090 1.138131 0.878633 4.024028e-10 -5.398455e-11 -8.745127e-10 -9.774598e-12 -1.394169e-09 1.480870e-08 1.619280e-19 2.914332e-21 7.647724e-19 9.554276e-23 1.943708e-18 2.192975e-16 2.074375e-19 7.004936e-21 1.088271e-18 7.153699e-22 2.013392e-18 2.587528e-16 6.653400e-25 1.197459e-26 1.736969e-27 3.925721e-28 3.225792e-27 3.639476e-25 8.523324e-25 2.878232e-26 2.471707e-27 2.939357e-27 3.341439e-27 4.294281e-25
3 53.64215 7.324080 1.165664 0.857880 3.396294e-10 -4.563913e-10 3.302614e-09 -1.937277e-12 1.743117e-08 1.145287e-08 1.153482e-19 2.082930e-19 1.090726e-17 3.753041e-24 3.038457e-16 1.311683e-16 3.227857e-19 2.152980e-19 1.199553e-17 7.191230e-22 3.058590e-16 3.899211e-16 4.739498e-25 8.558474e-25 2.477282e-26 1.542073e-29 5.042644e-25 2.176878e-25 1.326282e-24 8.846298e-25 2.724453e-26 2.954778e-27 5.076058e-25 6.471158e-25
4 53.64215 7.324080 1.165664 0.857880 -6.006892e-11 -2.575128e-10 -1.834748e-10 -4.978899e-12 9.513005e-09 -2.254505e-09 3.608275e-21 6.631284e-20 3.366300e-20 2.478944e-23 9.049726e-17 5.082791e-18 3.263940e-19 2.816108e-19 1.202919e-17 7.439124e-22 3.963563e-16 3.950039e-16 1.482591e-26 2.724704e-25 7.645618e-29 1.018564e-28 1.501899e-25 8.435437e-27 1.341108e-24 1.157100e-24 2.732098e-26 3.056634e-27 6.577957e-25 6.555512e-25
5 59.58843 7.719354 1.228573 0.813952 4.042192e-10 6.548266e-10 5.770587e-10 1.697122e-12 -2.767511e-08 1.639054e-08 1.633932e-19 4.287978e-19 3.329967e-19 2.880222e-24 7.659116e-16 2.686497e-16 4.897872e-19 7.104086e-19 1.236219e-17 7.467926e-22 1.162268e-15 6.636535e-16 6.713602e-25 1.761872e-24 7.563098e-28 1.183444e-29 1.271112e-24 4.458529e-25 2.012468e-24 2.918972e-24 2.807729e-26 3.068468e-27 1.928908e-24 1.101404e-24


modal_props.loc[[1, 47, 48, 60], "eigenFrequency"]

You can compare this with Code-Aster, which uses DKT shell elements. See ~ Model C: Modal analysis of a cooling tower

Gmsh model¶

You can find modeling instructions at: Creating quadrilateral surface meshes with gmsh

import json
import math

import gmsh

Initialize gmsh

gmsh.initialize()

gmsh.model.add("forma11c_gmsh")

forma11c_profile.json can be downloaded from here

# Read the profile coordinates
with open("utils/forma11c_profile.json") as file_id:
    coords = json.load(file_id)

Set a default element size

el_size = 1.0

# Add profile points
v_profile = []
for coord in coords:
    v = gmsh.model.occ.addPoint(coord[0], coord[1], coord[2], el_size)
    v_profile.append(v)

Add spline going through profile points

l1 = gmsh.model.occ.addBSpline(v_profile)
# Create copies and rotate
l2 = gmsh.model.occ.copy([(1, l1)])
l3 = gmsh.model.occ.copy([(1, l1)])
l4 = gmsh.model.occ.copy([(1, l1)])

# Rotate the copy
gmsh.model.occ.rotate(l2, 0, 0, 0, 0, 0, 1, math.pi / 2)
gmsh.model.occ.rotate(l3, 0, 0, 0, 0, 0, 1, math.pi)
gmsh.model.occ.rotate(l4, 0, 0, 0, 0, 0, 1, 3 * math.pi / 2)

Sweep the lines

surf1 = gmsh.model.occ.revolve([(1, l1)], 0, 0, 0, 0, 0, 1, math.pi / 2)
surf2 = gmsh.model.occ.revolve(l2, 0, 0, 0, 0, 0, 1, math.pi / 2)
surf3 = gmsh.model.occ.revolve(l3, 0, 0, 0, 0, 0, 1, math.pi / 2)
surf4 = gmsh.model.occ.revolve(l4, 0, 0, 0, 0, 0, 1, math.pi / 2)

Join the surfaces

surf5 = gmsh.model.occ.fragment(surf1, surf2)
surf6 = gmsh.model.occ.fragment(surf3, surf4)
surf7 = gmsh.model.occ.fragment(surf5[0], surf6[0])
gmsh.model.occ.remove_all_duplicates()
gmsh.model.occ.synchronize()
num_nodes_circ = 15
for curve in gmsh.model.occ.getEntities(1):
    gmsh.model.mesh.setTransfiniteCurve(curve[1], num_nodes_circ)
num_nodes_vert = 32
vertical_curves = [7, 10, 13, 17]
for curve in vertical_curves:
    gmsh.model.mesh.setTransfiniteCurve(curve, num_nodes_vert)
for surf in gmsh.model.occ.getEntities(2):
    gmsh.model.mesh.setTransfiniteSurface(surf[1])
gmsh.option.setNumber("Mesh.RecombineAll", 1)
gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 1)
gmsh.option.setNumber("Mesh.Recombine3DLevel", 2)
gmsh.option.setNumber("Mesh.ElementOrder", 1)

Important: Note that we use names to distinguish groups, so please do not overlook this! We use the “Boundary” group to include 4 lines

gmsh.model.addPhysicalGroup(dim=1, tags=[6, 9, 12, 15], tag=1, name="Boundary")

Generate mesh

gmsh.model.mesh.generate(dim=2)
gmsh.option.setNumber("Mesh.SaveAll", 1)
gmsh.write("utils/forma11c.msh")
# gmsh.fltk.run()

Total running time of the script: (0 minutes 4.215 seconds)

Download Jupyter notebook: ex-forma11c.ipynb

Download Python source code: ex-forma11c.py

Download zipped: ex-forma11c.zip

Gallery generated by Sphinx-Gallery

Next
Fluid-structure interaction
Previous
Excavation Supported by Cantilevered Sheet Pile Wall
Copyright © 2025, Yexiang Yan
Made with Sphinx and @pradyunsg's Furo
On this page
  • Modal analysis of a cooling tower
    • To OpenSeesPy Model
    • Gmsh model