OpenSees Cloud
OpenSees AMI
Three-Dimensional Meshing
Original Post - 19 Dec 2021 - Michael H. Scott
Visit Structural Analysis Is Simple on Substack.
Two previous posts showed how to use Minjie’s meshing functions to create line meshes for beam-column elements and 2D meshes for solid elements. This post will complete the trilogy by showing how to make a 3D mesh for solid elements.
The bar shown below is the same model used in the post on 2D meshing.
To begin a 3D solid model of the bar, define nodes for the eight corner points.
import openseespy.opensees as ops
ops.wipe()
ops.model('basic','-ndm',3,'-ndf',3)
L = 10
h = 2
t = 1
ops.node(1,0, t/2, h/2)
ops.node(2,0,-t/2, h/2)
ops.node(3,0,-t/2,-h/2)
ops.node(4,0, t/2,-h/2)
ops.node(5,L, t/2, h/2)
ops.node(6,L,-t/2, h/2)
ops.node(7,L,-t/2,-h/2)
ops.node(8,L, t/2,-h/2)
The next step is to define line meshes for the edges of the bar. Each of the 12 edges has a tag, followed by information about the end points of each line, the type (use 0 when not FSI), the number of DOFs per node, and the spacing of the nodes along each line.
c = t/2
# tag Npts nodes type dof size
ops.mesh('line',1, 2, *[1,4], 0, 3, c)
ops.mesh('line',2, 2, *[4,3], 0, 3, c)
ops.mesh('line',3, 2, *[3,2], 0, 3, c)
ops.mesh('line',4, 2, *[2,1], 0, 3, c)
ops.mesh('line',5, 2, *[5,8], 0, 3, c)
ops.mesh('line',6, 2, *[8,7], 0, 3, c)
ops.mesh('line',7, 2, *[7,6], 0, 3, c)
ops.mesh('line',8, 2, *[6,5], 0, 3, c)
ops.mesh('line', 9, 2, *[1,5], 0, 3, c)
ops.mesh('line',10, 2, *[2,6], 0, 3, c)
ops.mesh('line',11, 2, *[3,7], 0, 3, c)
ops.mesh('line',12, 2, *[4,8], 0, 3, c)
Compared to 2D meshing, 3D meshing requires an extra step before creating elements–nodes must be generated over each of the six faces of the bar. Call the mesh command with mesh tag, the number of lines that circumscribe the face, the line tags, the type (still 0), DOFs per node, and mesh size–but leave off the element arguments.
meshType = 'tri'
#meshType = 'quad'
# tag Nlines lines type dof size
ops.mesh(meshType,13, 4, *[1,2,3,4], 0, 3, c)
ops.mesh(meshType,14, 4, *[5,6,7,8], 0, 3, c)
ops.mesh(meshType,15, 4, *[4,9,8,10], 0, 3, c)
ops.mesh(meshType,16, 4, *[2,12,6,11],0, 3, c)
ops.mesh(meshType,17, 4, *[3,11,7,10],0, 3, c)
ops.mesh(meshType,18, 4, *[1,12,5,9], 0, 3, c)
For a
quadrilateral mesh
on each face, simply change 'tri'
to 'quad'
.
The nodes created on all six faces are shown below. Yeah, it’s a little
crowded, but when you give this a try, you can zoom and rotate the view
to see what’s going on.
With nodes on all six faces of the bar, we can now create the element
mesh. The only element available for 3D meshing with the mesh commands
is the
four node tetrahedral element.
For brick elements, your only option for now is to use the
block3D
command.
E = 29000
v = 0.3
ops.nDMaterial('ElasticIsotropic',1,E,v)
# tag Nlines lines type dof size <ele args>
ops.mesh('tet',20, 6,*[13,14,15,16,17,18], 0, 3, c, 'FourNodeTetrahedron',1)
Below are the elements created from the quadrilateral mesh.
Again, the views are pretty crowded, but you can zoom and rotate when you give this a try.
To apply boundary conditions along a surface, you can use fixX
, fixY
,
and fixZ
. To fix the displacements of all nodes with X-coordinate equal
to 0, use the following command.
# X 1 2 3
ops.fixX(0,1,1,1)
As far as I know, there’s no easy way to apply traction stresses to solid models in OpenSees. While this functionality can be implemented via scripts, it should be implemented within the OpenSees core.
The meshes shown in this post were plotted using the
opsvis
package
developed by
Seweryn Kokot.