A finite element model of a simple truss is created, and static analysis is performed.
This example is of a linear-elastic three bar truss, as shown in the figure above, subject to static loads. The purpose of this example is to develop the basic concepts used for performing structural analysis with OpenSees. This includes the definition of nodes, materials, elements, loads and constraints.
We begin the simulation by creating a
Model
, which will manage
the nodes, elements, loading and state.
This is done through either Python or Tcl as follows:
where we’ve specified 2
for the spatial dimension ndm
, and
2
for the number of degrees of freedom ndf
.
Next we define the four nodes of the structural model by specifying
a tag which identifies the node, and coordinates in the
plane.
In general, the node
constructor must be passed ndm
coordinates.
The restraints are now defined at the nodes with reactions (ie, nodes 1
, 2
, and 3
).
The restraints at the nodes with reactions (ie, nodes 1
, 2
, and 3
)
are then defined. This is done with the
fix
method, whose first argument
is an integer node tag and second argument a tuple containing a 1
or 0
for degree of freedom at the node.
Since the truss elements have the same elastic properties,
a single Elastic
material is defined. The first
argument assigns the tag 1
to the material, and the
second specifies a Young’s modulus of 3000
.
Finally, define the elements. The syntax for creating the truss element requires the following arguments:
"Truss"
,1
through 3
,10.0
for element 1
and 5.0
for elements 2
and 3
.1
The final step before we can configure and run the analysis is to define
some loading. In this case we have two point loads at the apex of
the truss (node 4
).
In OpenSees, loads are assigned to load patterns, which define how loads
are scaled with each load step.
In Python, the simplest way to represent a nodal load is by a dictionary with
node numbers as keys, and corresponding load vector as values. For the problem at
hand, we want to apply a load to node 4
with 100
units in the
direction, and
-50
units in the
direction; the corresponding definition is:
We then add a
"Plain"
load pattern to the model with these loads,
and use the "Linear"
option
to specify that it should be increased linearly with each new load step.
Note that it is common to define the
load
data structure inside the call to thepattern
function. This looks like:
Next we configure that analysis procedure.
The model is linear, so we use the
Linear
algorithm
.
Even though the solution is linear, we have to select a procedure for
applying the load, which is called an Integrator
.
For this problem, the
LoadControl
integrator
is selected, which
advances the solution by incrementing the load factor by 1.0
each time the analyze
command is called.
Once all the components of an analysis are defined, the Analysis
itself is defined. For this problem a Static
analysis is used.
Finally, one analysis step is performed by invoking
analyze
:
When the analysis is complete the state of node 4
obtained using
nodeDisp
and printed to the screen:
The output looks like:
u4 = [0.5300927771322836, -0.1778936384693177]
When using Python, the model
variable can be passed directly to the veux
library’s
render
function as follows:
import veux
# Render the model
artist = veux.render(model, model.nodeDisp, canvas="plotly")
veux.serve(artist)