OpenSees Cloud
OpenSees AMI
How to Mesh Shells
Original Post - 15 Nov 2023 - Michael H. Scott
Visit Structural Analysis Is Simple on Substack.
If you have created a mesh of planar (2D) elements in OpenSees, creating
a mesh of shell elements (3D) is not that different. You can use either
the block2D
command or Minjie’s line
and mesh
commands.
However, you will quickly find that the block2D
command–2D because the
mesh is planar, not because the command is somehow limited to 2D models,
which it is not–is difficult to use for several reasons:
- You have to manually tie together the nodes of adjacent blocks
- You have little control over the node numbers generated by the
block2D
command - You have to know the pattern of node and element numbers if you want to do anything useful with the generated mesh
- You can only generate four node elements, whereas three node elements are more friendly to arbitrary meshes.
So, you’ll struggle to mesh anything more than a single block with
block2D
. But if you insist, go ahead and knock your block off!
The remainder of this post shows how to use the line
and mesh
commands
for shell models. The steps draw heavily upon a prior post on
two-dimensional meshing, so I recommend you read that post first.
A plate fixed on one side is shown below along with the corresponding beam analogy.
When the plate is subjected to its self-weight, the distributed load on the beam model is \(w=\rho g (th)\). The free end deflection is \(wL^4/(8EI)\) where \(I=ht^3/12\).
We first create corner nodes for the mesh. Although the plate can be meshed in one piece, I’m meshing with two irregular pieces for the sake of demonstration.
import openseespy.opensees as ops
L = 50.0
h = 10.0
t = 1.0
ops.wipe()
ops.model('basic','-ndm',3,'-ndf',6)
ops.node(1,0,-h/2,0)
ops.node(2,0,h/2,0)
ops.node(3,0.7*L,-h/2,0)
ops.node(4,0.3*L,h/2,0)
ops.node(5,L,-h/2,0)
ops.node(6,L,h/2,0)
The nodes are shown below, plotted using opsvis.
Then, we define line meshes of nodes to connect the control nodes. Each line mesh has 6 DOFs/node and a unique tag which will be used for element meshing.
c = h/5 # Mesh size
ops.mesh('line',1,2,*[1,3],0,6,c)
ops.mesh('line',2,2,*[3,4],0,6,c)
ops.mesh('line',3,2,*[4,2],0,6,c)
ops.mesh('line',4,2,*[2,1],0,6,c)
ops.mesh('line',5,2,*[3,5],0,6,c)
ops.mesh('line',6,2,*[5,6],0,6,c)
ops.mesh('line',7,2,*[6,4],0,6,c)
As shown below, we have created lines of nodes around the regions to be meshed.
We can now create two meshes of shell elements. Due to the mesh
irregularity, we have to use triangular shell elements, e.g., ShellDKGT
.
The triangulated meshes are created around the two areas enclosed by
line meshes with tags 1-2-3-4 and 5-6-7-2.
ops.section('ElasticMembranePlateSection',1,E,v,t,rho)
ops.mesh('tri',10,4,*[1,2,3,4],0,6,c,'ShellDKGT',1)
ops.mesh('tri',11,4,*[5,6,7,2],0,6,c,'ShellDKGT',1)
The resulting shell elements are shown below.
Finally, applying self-weight to the shells, imposing boundary conditions using the fixX command, then performing a static analysis, we get the deflected shape shown below.
Try this example yourself using reasonable material properties. Verify that the free end plate deflection matches the beam equation. For me, I obtained a free end deflection of 0.0914 for the shell model and deflection of 0.0938 from the analogous beam equation.