OpenSTRAN package

Submodules

OpenSTRAN.Coordinates module

class OpenSTRAN.Coordinates.Coordinate(x: float, y: float, z: float)[source]

Bases: object

A class representing a 3D coordinate in space.

Variables:
  • x – The x-coordinate in feet

  • y – The y-coordinate in feet

  • z – The z-coordinate in feet

  • coordinates – A tuple containing the (x, y, z) coordinates

  • vector – A numpy array representation of the coordinate vector

coordinates: tuple[float, float, float]
classmethod from_tuple(coordinates: tuple[float, float, float]) Self[source]

Create a Coordinate instance from a tuple of x, y, z values.

Parameters:

coordinates (tuple[float, float, float]) – A tuple containing (x, y, z) coordinate values

Returns:

A new Coordinate instance

Return type:

Self

properties() dict[str, Any][source]

Return the dataclass properties as a dictionary.

Returns:

Dictionary of this instance’s fields

Return type:

dict[str, Any]

vector: ndarray
x: float
y: float
z: float

OpenSTRAN.Member module

class OpenSTRAN.Member.Member(nodes: ~OpenSTRAN.Nodes.Nodes, node_i: ~OpenSTRAN.Node.Node, node_j: ~OpenSTRAN.Node.Node, i_release: bool, j_release: bool, E: float, Ixx: float, Iyy: float, A: float, G: float, J: float, mesh: int, bracing: str | list[float], shape: str, count: int = 0, submembers: dict[int, ~OpenSTRAN.Submember.SubMember] = <factory>)[source]

Bases: object

Represents a 3D space frame member connecting two nodes.

A member is a structural element that connects two nodes and can be discretized into submembers for analysis. It supports various boundary conditions, material properties, and loading conditions.

Variables:
  • nodes (Nodes) – Reference to the Nodes collection object.

  • node_i (Node) – Start node of the member.

  • node_j (Node) – End node of the member.

  • i_release (bool) – Boundary condition at node i (False = fixed, True = pinned).

  • j_release (bool) – Boundary condition at node j (False = fixed, True = pinned).

  • E (float) – Young’s modulus in ksi.

  • Ixx (float) – Strong axis moment of inertia in in^4.

  • Iyy (float) – Weak axis moment of inertia in in^4.

  • A (float) – Cross-sectional area in in^2.

  • G (float) – Shear modulus in ksi.

  • J (float) – Polar moment of inertia in in^4.

  • mesh (int) – Number of discretizations (submembers) along the member span.

  • bracing (str | list[float]) – Lateral bracing configuration. Can be ‘continuous’, ‘quarter’, ‘third’, ‘midspan’, or a list of bracing locations along the span.

  • shape (str) – Cross-sectional shape identifier.

  • length (float) – Calculated length of the member (in).

  • Cb (float) – Lateral-torsional buckling coefficient.

  • count (int) – Counter for submember creation.

  • submembers (dict[int, SubMember]) – Dictionary of submembers indexed by creation order.

A: float
Cb: float
E: float
G: float
Ixx: float
Iyy: float
J: float
add_distributed_load(Mag1: float, Mag2: float, direction: str, loc1: float, loc2: float)[source]

Apply a trapezoidal distributed load along the member.

Applies a distributed load with linearly varying magnitude over a specified portion of the member span. Handles loading that spans across multiple submembers by calculating equivalent nodal actions for each affected segment.

Parameters:
  • Mag1 (float) – Starting magnitude of the distributed load in kips.

  • Mag2 (float) – Ending magnitude of the distributed load in kips.

  • direction (str) – Load direction - global (‘X’, ‘Y’, ‘Z’) or local (‘x’, ‘y’, ‘z’).

  • loc1 (float) – Starting location of load along member span as percentage (0-100%).

  • loc2 (float) – Ending location of load along member span as percentage (0-100%).

Returns:

None

Return type:

None

Raises:

ValueError – If direction is not one of ‘X’, ‘Y’, ‘Z’, ‘x’, ‘y’, ‘z’.

add_mesh(nodes: Nodes, node_i: Node, node_j: Node, mesh: int, l: float) list[Node][source]

Create intermediate mesh nodes along the member span.

Generates evenly spaced nodes along the member length based on the mesh parameter. These nodes are used as intermediary connection points for submembers in the discretization process.

Parameters:
  • nodes (Nodes) – Collection of nodes in the model

  • node_i (Node) – Start node of the member

  • node_j (Node) – End node of the member

  • mesh (int) – Number of equal segments to divide the member into

  • l (float) – Total length of the member in inches

Returns:

List of intermediate mesh nodes along the member

Return type:

list[Node]

add_point_load(mag: float, direction: str, location: float) None[source]

Apply a concentrated point load to the member.

Applies a point load at a specified location along the member span. The load can be specified in either global (X, Y, Z) or local (x, y, z) coordinates. The method calculates equivalent nodal actions and distributes loads to the appropriate nodes and submembers.

Parameters:
  • mag (float) – Magnitude of the load in kips.

  • direction (str) – Load direction - global (‘X’, ‘Y’, ‘Z’) or local (‘x’, ‘y’, ‘z’).

  • location (float) – Load location as percentage of member span (0-100%).

Returns:

None

Return type:

None

Raises:

ValueError – If direction is not one of ‘X’, ‘Y’, ‘Z’, ‘x’, ‘y’, ‘z’.

add_submember(node_i: Node, node_j: Node, i_release: bool, j_release: bool, E: float, Ixx: float, Iyy: float, A: float, G: float, J: float) None[source]

Add a submember to the member collection.

Creates a new submember element connecting two nodes with specified boundary conditions and material properties. The submember is stored in the submembers dictionary using an auto-incremented counter.

Parameters:
  • node_i (Node) – Start node of the submember

  • node_j (Node) – End node of the submember

  • i_release (bool) – Release condition at start node (False = fixed, True = pinned)

  • j_release (bool) – Release condition at end node (False = fixed, True = pinned)

  • E (float) – Young’s modulus in ksi

  • Ixx (float) – Strong axis moment of inertia in in^4

  • Iyy (float) – Weak axis moment of inertia in in^4

  • A (float) – Cross-sectional area in in^2

  • G (float) – Shear modulus in ksi

  • J (float) – Polar moment of inertia in in^4

Returns:

None

Return type:

None

bracing: str | list[float]
calculate_Cb() float[source]

Calculate the lateral-torsional buckling coefficient (Cb) for the member.

Computes Cb based on moment variation along unbraced spans using the standard AISC formula: Cb = 12.5*Mmax / (2.5*Mmax + 3*Ma + 4*Mb + 3*Mc). The calculation accounts for lateral bracing locations and interpolates moments at quarter-span points. The result is limited to a maximum of 3.0.

Returns:

The lateral-torsional buckling coefficient, limited to 3.0 maximum.

Return type:

float

calculate_length(node_i: Node, node_j: Node) float[source]

Calculate the length of the member using the Euclidean distance formula.

Computes the 3D distance between two nodes based on their coordinate positions in the global reference frame.

Parameters:
  • node_i (Node) – Start node of the member

  • node_j (Node) – End node of the member

Returns:

The length of the member in inches

Return type:

float

count: int
i_release: bool
j_release: bool
length: float
mesh: int
node_i: Node
node_j: Node
nodes: Nodes
properties() dict[str, Any][source]

Return all member properties as a dictionary.

Converts the dataclass instance into a dictionary representation containing all field names and their current values.

Returns:

Dictionary containing all member attributes and their values

Return type:

dict[str, Any]

second_order() None[source]

Apply second-order (P-delta) effects to account for geometric nonlinearity.

Constructs and adds geometric stiffness matrices to all submembers to account for second-order effects including P-delta moments. This modifies the local stiffness matrix of each submember by including the effects of axial forces on bending behavior.

Returns:

None

Return type:

None

shape: str
submembers: dict[int, SubMember]

OpenSTRAN.Members module

class OpenSTRAN.Members.Members(nodes: Nodes, count: int = 0, members: dict[int, ~OpenSTRAN.Member.Member]=<factory>)[source]

Bases: object

Container class for managing member (element) objects.

Variables:
  • nodes – Reference to the global Nodes collection

  • count – Number of members added to the collection

  • members – Mapping of member ID to Member object

addMember(node_i: Node, node_j: Node, i_release: bool = False, j_release: bool = False, E: float = 29000.0, Ixx: float = 88.6, Iyy: float = 2.36, A: float = 4.16, G: float = 12000.0, J: float = 0.0704, mesh: int = 50, bracing: str = 'continuous', shape: str = 'W12x14') Member[source]

Add a member to the model.

Parameters:
  • node_i (Node) – Start node of the member

  • node_j (Node) – End node of the member

  • i_release (bool) – True if start node is released (pinned). Defaults to False.

  • j_release (bool) – True if end node is released (pinned). Defaults to False.

  • E (float) – Young’s modulus in ksi. Defaults to 29000.0.

  • Ixx (float) – Moment of inertia about the strong axis in in^4. Defaults to 88.6.

  • Iyy (float) – Moment of inertia about the weak axis in in^4. Defaults to 2.36.

  • A (float) – Cross-sectional area in in^2. Defaults to 4.16.

  • G (float) – Shear modulus in ksi. Defaults to 12000.0.

  • J (float) – Polar moment of inertia in in^4. Defaults to 0.0704.

  • mesh (int) – Number of discretizations per member. Defaults to 50.

  • bracing (str) – Bracing type (e.g., “continuous”). Defaults to “continuous”.

  • shape (str) – Section shape name (e.g., “W12x14”). Defaults to “W12x14”.

Returns:

The created Member instance

Return type:

Member

Example:
>>> M1 = frame.members.addMember(N1, N2)
>>> M2 = frame.members.addMember(N2, N3)
count: int
members: dict[int, Member]
nodes: Nodes
properties() dict[str, Any][source]

Return the dataclass properties as a dictionary.

Returns:

Dictionary of this instance’s fields

Return type:

dict[str, Any]

OpenSTRAN.Node module

class OpenSTRAN.Node.Node(coordinates: Coordinate, node_ID: int, mesh_node: bool = False, Fx: float = 0.0, Fy: float = 0.0, Fz: float = 0.0, Mx: float = 0.0, My: float = 0.0, Mz: float = 0.0, Ux: float = 0.0, Uy: float = 0.0, Uz: float = 0.0, phi_x: float = 0.0, phi_y: float = 0.0, phi_z: float = 0.0, eFx: float = 0.0, eFy: float = 0.0, eFz: float = 0.0, eMx: float = 0.0, eMy: float = 0.0, eMz: float = 0.0, Rx: float = 0.0, Ry: float = 0.0, Rz: float = 0.0, Rmx: float = 0.0, Rmy: float = 0.0, Rmz: float = 0.0, plane: str | None = None, restraint: list[int] = <factory>)[source]

Bases: object

A class representing a node in the structural analysis model.

Variables:
  • coordinates – The coordinate object defining the node’s position

  • node_ID – Unique identifier for the node

  • mesh_node – Indicates if this is a mesh node. Defaults to False

  • Fx – Applied force in the x-direction in kips. Defaults to 0.0

  • Fy – Applied force in the y-direction in kips. Defaults to 0.0

  • Fz – Applied force in the z-direction in kips. Defaults to 0.0

  • Mx – Applied moment about the x-axis in kip-ft. Defaults to 0.0

  • My – Applied moment about the y-axis in kip-ft. Defaults to 0.0

  • Mz – Applied moment about the z-axis in kip-ft. Defaults to 0.0

  • restraint – List of 6 integers indicating restrained degrees of freedom [Ux, Uy, Uz, φx, φy, φz]. Defaults to [0, 0, 0, 0, 0, 0]

  • plane – The plane associated with the node. Defaults to None

Fx: float
Fy: float
Fz: float
Mx: float
My: float
Mz: float
Rmx: float
Rmy: float
Rmz: float
Rx: float
Ry: float
Rz: float
Ux: float
Uy: float
Uz: float
add_load(mag: float, lType: str = 'moment', direction: str = 'y') None[source]

Add a load to the node.

Parameters:
  • mag (float) – Magnitude of the load. Units are kips for forces and kip-ft for moments.

  • lType (str) – Type of load. Either ‘moment’ or ‘force’. Defaults to ‘moment’.

  • direction (str) – Direction of the load. ‘X’, ‘Y’, or ‘Z’. Defaults to ‘y’.

Note:

For moments, the magnitude is multiplied by 12 (kip-in to kip-ft conversion)

add_restraint(restraint: list[int]) None[source]

Add restraint to the nodal degrees of freedom.

Parameters:

restraint (list[int]) –

List of 6 integers (0 or 1) indicating which degrees of freedom are restrained. Format: [Ux, Uy, Uz, φx, φy, φz], where 1 means restrained and 0 means free. Examples:

  • Pinned node: [1, 1, 1, 0, 0, 0]

  • Fixed node: [1, 1, 1, 1, 1, 1]

  • Roller in x-direction: [0, 1, 1, 0, 0, 0]

Raises:

ValueError – If restraint is not a list of exactly 6 integers, each being 0 or 1

coordinates: Coordinate
eFx: float
eFy: float
eFz: float
eMx: float
eMy: float
eMz: float
mesh_node: bool
node_ID: int
phi_x: float
phi_y: float
phi_z: float
plane: str | None
properties() dict[str, Any][source]

Return the dataclass properties as a dictionary.

Returns:

Dictionary of this instance’s fields

Return type:

dict[str, Any]

restraint: list[int]

OpenSTRAN.Nodes module

class OpenSTRAN.Nodes.Nodes(plane: str | None = None, count: int = 0, nodes: dict[int, ~OpenSTRAN.Node.Node]=<factory>, x: list[float] = <factory>, y: list[float] = <factory>, z: list[float] = <factory>)[source]

Bases: object

A container class for managing user-defined node objects in the structural model.

Variables:
  • plane – The plane constraint associated with the nodes

  • count – The total number of nodes added

  • nodes – Dictionary mapping node IDs to Node objects

  • x – List of x-coordinates

  • y – List of y-coordinates

  • z – List of z-coordinates

add_node(x: float, y: float, z: float, mesh_node: bool = False) Node[source]

Add a node to the model at the specified coordinates.

Parameters:
  • x (float) – x-coordinate in feet

  • y (float) – y-coordinate in feet

  • z (float) – z-coordinate in feet

  • mesh_node (bool) – Whether this is a mesh node. Defaults to False.

Returns:

The added or existing node object

Return type:

Node

Example:
>>> N1 = frame.nodes.add_node(0, 0, 0)
>>> N2 = frame.nodes.add_node(0, 10, 0)
>>> N3 = frame.nodes.add_node(10, 10, 0)
>>> N4 = frame.nodes.add_node(10, 0, 0)
count: int
find_node(x: float, y: float, z: float) Node | None[source]

Find a node in the model at the specified coordinates.

Parameters:
  • x (float) – x-coordinate in feet

  • y (float) – y-coordinate in feet

  • z (float) – z-coordinate in feet

Returns:

The matching node object if found, None otherwise

Return type:

Node | None

nodes: dict[int, Node]
plane: str | None
properties() dict[str, Any][source]

Return the dataclass properties as a dictionary.

Returns:

Dictionary of this instance’s fields

Return type:

dict[str, Any]

x: list[float]
y: list[float]
z: list[float]

OpenSTRAN.Solver module

class OpenSTRAN.Solver.Solver[source]

Bases: object

Solver class for structural finite element analysis.

This class performs finite element analysis on structural models by assembling the global stiffness matrix, applying boundary conditions, and solving for nodal displacements and member forces.

Variables:
  • nDoF – Total number of degrees of freedom in the structure

  • pinDoF – List of pinned (rotational) degrees of freedom indices

  • restrainedDoF – List of restrained degrees of freedom indices

  • Kp – Primary stiffness matrix for the structure

  • force_vector – Global force vector with applied loads

  • global_displacement_vector – Global displacement vector at all nodes

  • global_force_vector – Global reaction force vector

AddMemberToKp(node_ID_i: int, node_ID_j: int, i_release: bool, j_release: bool, KG: ndarray) None[source]

Add member stiffness contributions to the global stiffness matrix.

Extracts the appropriate submatrix from the member’s global stiffness matrix based on end releases and assembles it into the primary stiffness matrix at the correct locations corresponding to the member’s nodes.

Parameters:
  • node_ID_i (int) – Node ID at the start of the member

  • node_ID_j (int) – Node ID at the end of the member

  • i_release (bool) – Whether the i-node has rotational releases (pinned)

  • j_release (bool) – Whether the j-node has rotational releases (pinned)

  • KG (numpy.ndarray) – Global stiffness matrix of the member (12x12 or reduced)

Returns:

None

Return type:

None

solve(nodes: Nodes, members: Members) None[source]

Solve the structural system for displacements and member forces.

This method performs a complete finite element analysis including:

  • Assembly of the global stiffness matrix

  • Application of boundary conditions

  • Solution for nodal displacements using matrix reduction

  • Computation of member forces and reactions

  • Removal of equivalent nodal actions (distributed loads)

Parameters:
  • nodes (Nodes) – Collection of nodes in the structural model

  • members (Members) – Collection of members in the structural model

Returns:

None

Return type:

None

OpenSTRAN.Submember module

class OpenSTRAN.Submember.SubMember(node_i: Node, node_j: Node, i_release: bool, j_release: bool, E: float, Ixx: float, Iyy: float, A: float, G: float, J: float, ENAs: dict[str, list[float]]=<factory>, results: dict[str, list[float]]=<factory>)[source]

Bases: object

A 3D space-frame submember between mesh nodes.

A discretized sub-element between two mesh nodes containing geometry, section properties, and methods to build local and geometric stiffness matrices.

Variables:
  • node_i – Start node of the submember

  • node_j – End node of the submember

  • i_release – Release (pinned) flag at the start node

  • j_release – Release (pinned) flag at the end node

  • E – Young’s modulus

  • Ixx – Moment of inertia about the strong axis

  • Iyy – Moment of inertia about the weak axis

  • A – Cross-sectional area

  • G – Shear modulus

  • J – Polar moment of inertia

  • length – Submember length (computed)

  • rotation_matrix – Rotation matrix from local to global coordinates

  • transformation_matrix – Transformation matrix for coordinate conversion

  • Kl – Local stiffness matrix

  • Kg – Global stiffness matrix

A: float
E: float
ENAs: dict[str, list[float]]
G: float
Ixx: float
Iyy: float
J: float
Kg: ndarray
Kl: ndarray
build_geometric_stiffness_matrix() ndarray[source]

Compute the geometric (P-Delta) stiffness matrix from results.

Uses the axial and moment results stored in self.results to assemble the geometric stiffness matrix for second-order effects.

Returns:

Geometric stiffness matrix in local element DOFs.

Return type:

np.ndarray

build_rotation_matrix(node_i: Node, node_j: Node, i_release: bool, j_release: bool) ndarray[source]

Build the rotation/transformation matrix for the submember.

Establishes the local x,y,z unit vectors using a Gram-Schmidt approach and constructs the transformation matrix between the local element frame and the global frame. The size of the returned matrix depends on release conditions.

Parameters:
  • node_i (Node) – Start node.

  • node_j (Node) – End node.

  • i_release (bool) – Release flag at node i.

  • j_release (bool) – Release flag at node j.

Returns:

Transformation matrix mapping local DOFs to global DOFs.

Return type:

np.ndarray

build_stiffness_matrix(E: float, Izz: float, Iyy: float, A: float, G: float, J: float, l: float) ndarray[source]
calculate_length(node_i: Node, node_j: Node) float[source]

Compute Euclidean length between two nodes.

Parameters:
  • node_i (Node) – Start node.

  • node_j (Node) – End node.

Returns:

Length between node_i and node_j.

Return type:

float

i_release: bool
j_release: bool
length: float
node_i: Node
node_j: Node
properties() dict[str, Any][source]

Return all submember properties as a dictionary.

Converts the dataclass instance into a dictionary representation containing all field names and their current values.

Returns:

Dictionary containing all member attributes and their values

Return type:

dict[str, Any]

results: dict[str, list[float]]
rotation_matrix: ndarray
transformation_matrix: ndarray

OpenSTRAN.model module

class OpenSTRAN.model.Model(plane: str | None = None)[source]

Bases: object

3D space frame structural model.

This class represents a three-dimensional space frame for finite element analysis. The model neglects deformations due to transverse shear stresses and torsional warping, operating under the assumption that such effects are negligible in typical civil engineering applications.

Parameters:

plane (str | None) – Constrains the model to a two-dimensional plane. Valid values are ‘xy’, ‘yz’, or ‘xz’. If None, the model is fully three-dimensional.

Variables:
  • nodes – Collection of nodes in the structure

  • members – Collection of members (elements) in the structure

  • solver – Solver instance for performing structural analysis

Example:
>>> import OpenSTRAN
>>> frame_2d = OpenSTRAN.Model(plane='xy')
>>> frame_3d = OpenSTRAN.Model()
localMaxima(forces: list[float]) list[bool][source]

Identify local maxima in a force distribution.

Determines which points in the force distribution represent local maxima by comparing adjacent values, accounting for numerical precision with near-equal comparisons.

Parameters:

forces (list[float]) – List of force values along a member or structure

Returns:

Boolean list indicating local maxima positions

Return type:

list[bool]

localMinima(forces: list[float]) list[bool][source]

Identify local minima in a force distribution.

Determines which points in the force distribution represent local minima by comparing adjacent values, accounting for numerical precision with near-equal comparisons.

Parameters:

forces (list[float]) – List of force values along a member or structure

Returns:

Boolean list indicating local minima positions

Return type:

list[bool]

maxMbrForces() None[source]

Calculate maximum member forces and identify local extrema.

Computes the maximum values for all member internal forces (axial, shear, torsion, and bending moments) and identifies their local maxima and minima distributions along members.

Returns:

None

Return type:

None

Sets the following instance attributes:

  • axial_max, axial_maxima, axial_minima: Axial force results

  • torque_max, torque_maxima, torque_minima: Torsional moment results

  • Vy_max, Vy_maxima, Vy_minima: Y-direction shear force results

  • Vz_max, Vz_maxima, Vz_minima: Z-direction shear force results

  • Mzz_max, Mzz_maxima, Mzz_minima: Major axis bending moment results

  • Myy_max, Myy_maxima, Myy_minima: Minor axis bending moment results

maxReactions() None[source]

Calculate maximum reaction forces and moments at restrained nodes.

Computes the maximum absolute values of reaction forces and moments across all support nodes in the structure.

Returns:

None

Return type:

None

Sets the following instance attributes:

  • Rx_max: Maximum X-direction reaction force

  • Ry_max: Maximum Y-direction reaction force

  • Rz_max: Maximum Z-direction reaction force

  • Rmx_max: Maximum X-direction reaction moment

  • Rmy_max: Maximum Y-direction reaction moment

  • Rmz_max: Maximum Z-direction reaction moment

reactions() None[source]

Print nodal reactions to console.

Displays all reaction forces (Rx, Ry, Rz) and reaction moments (Mx, My, Mz) at all restrained support nodes in a formatted table.

Returns:

None

Return type:

None

solve() None[source]

Solve the structural system and compute reactions and member forces.

This method performs a complete finite element analysis including:

  • Assembly and solution of the global stiffness system

  • Calculation of nodal reactions at restrained DOFs

  • Determination of member forces and local extrema

Returns:

None

Return type:

None

Module contents

OpenSTRAN - Open-source Structural Analysis Package.

A Python package for 3D finite element analysis of space frames. This package provides tools for structural modeling and analysis.