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.

Tension bar

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)

Corner nodes of mesh

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)

Edges of mesh

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)

Triangulated mesh of nodes on each face

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.

Quadrilateral mesh of nodes on each face

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)

Tetrahedral elements from triangulated mesh of nodes

Below are the elements created from the quadrilateral mesh.

Tetrahedral elements from quadrilateral mesh of nodes

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.