OpenSees Cloud
OpenSees AMI
Two-Dimensional Meshing
Original Post - 29 Nov 2021 - Michael H. Scott
Visit Structural Analysis Is Simple on Substack.
Although the material and element models are there, OpenSees is not well known for solid finite element analysis. Creating a good mesh is key to solid FEA and there aren’t many meshing tools implemented in OpenSees.
The OG block2D
and block3D
commands work fine, but you have to manually
join or tie adjacent meshes with loops and equalDOF
commands. Just be
sure to use the Transformation constraint handler. If no re-meshing is
required during an analysis, you’re better off to create a mesh using a
third party tool then import the nodes and connectivity to OpenSees.
But what do you do when re-meshing is required during an analysis? For example, in a PFEM analysis, the fluid domain along the fluid-structure interface requires frequent re-meshing. Using a third party meshing tool would be virtually impossible.
To make re-meshing tractable for PFEM analyses in OpenSees, Minjie implemented triangular and tetrahedral meshing routines–and he did it in a way that the routines can be used for not just fluid elements, but also for solid elements.
This post will show how to use Minjie’s functions to analyze the bar
shown below with a 2D mesh of
Tri31
triangular plane stress elements.
First define nodes for the mesh corner points.
import openseespy.opensees as ops
ops.wipe()
ops.model('basic','-ndm',2,'-ndf',2)
L = 10
h = 2
t = 1
ops.node(1,0,-h/2)
ops.node(2,0,h/2)
ops.node(3,L,h/2)
ops.node(4,L,-h/2)
Next, define line meshes around the perimeter. Each line has a tag, followed by the number of points that define the line, the nodes for those points, the type (use 0 when not FSI), the number of DOFs for each node, the size (spacing) of the nodes to be generated along the line.
c = h/5
# tag Npts nodes type dof size
ops.mesh('line',1, 2, *[1,2], 0, 2, c)
ops.mesh('line',2, 2, *[2,3], 0, 2, c)
ops.mesh('line',3, 2, *[3,4], 0, 2, c)
ops.mesh('line',4, 2, *[4,1], 0, 2, c)
Although not shown in this post, the advantage of line meshes is you don’t have to tie meshes together after creating elements. Instead, you just create element meshes based on the pre-defined lines.
For 2D meshes, you have two options: either make triangle elements in a triangulated mesh or make triangles from a quadrilateral mesh. Similar to the line mesh, there is a tag, lines that circumscribe the mesh, the type (still 0), DOFs per node, and the mesh size. The remaining arguments create elements–pass the element type, then all the information that would come after the nodes in the regular element command.
E = 29000
v = 0.3
ops.nDMaterial('ElasticIsotropic',1,E,v)
# tag Nlines lines type dof size <ele args>
ops.mesh('tri',5, 4, *[4,3,2,1], 0, 2, c, 'tri31',t,'PlaneStress',1)
The triangulated mesh is shown below.
Try changing the mesh size to see what happens.
If instead, you want a more regular mesh, you can make triangles out of
quadrilateral–just use 'quad'
instead of 'tri'
.
# tag Nlines lines type dof size <ele args>
ops.mesh('quad',5, 4, *[1,2,3,4], 0, 2, c, 'tri31',t,'PlaneStress',1)
The resulting mesh is shown below. The mesh size for the quadrilateral mesh doesn’t matter–the elements are always generated from the grid made by the points along each line.
To apply boundary conditions along a line, you can use the fixX
and fixY
commands (fixZ
is available for 3D problems). The following command
fixes the X and Y displacement (DOF 1 and 2) of all nodes with
X-coordinate equal to zero.
# X 1 2
ops.fixX(0,1,1)
The meshes shown in this post were plotted using the
opsvis
package
developed by
Seweryn Kokot.
Meshing a three-dimensional domain is a little more involved, so I will address that in another post.