OpenSees Cloud
OpenSees AMI
A Vector in the x-z Plane
Original Post - 08 Aug 2020 - Michael H. Scott
Visit Structural Analysis Is Simple on Substack.
Three-dimensional frame elements require user input for the local element axes. Although the local x axis points from node I to node J, there is no automatic way to define the local y and z axes, i.e., how the section axes line up with the element. In two-dimensions, this is not an issue because the local z axis coincides with global Z, perpendicular to the X-Y plane of the model.
In OpenSees, the user must specify vxz, a vector in the local x-z plane of 3D frame elements. Then, the geometric transformation class computes the local y axis from vxz\(\times\)x, followed by the local z axis from x\(\times\)y. Note that the vxz vector can be the actual local z axis, but it cannot be equal to \(\pm\)x.
I’ve never liked this approach to specifying the orientation of 3D frame elements. I have a hard time figuring out a vector in the x-z plane because I am not very good at geometry. But, even for people who are good at geometry, it is very easy to accidentally rotate the local y and z axes with this approach.
Consider the beam shown below. If we switch the I and J nodes but keep the same vxz, the local y and z axes rotate by 180 degrees. This lack of invariance can be a problem when defining member loads along the local y axis to produce bending about the z axis, e.g., for beams in a 3D frame model.
Specifying a vector in the local x-y, let’s call it vxy, would resolve the lack of invariance for the local y axis. First compute local z from x\(\times\)vxy, then compute local y from z\(\times\)x. The local z axis is flipped, but that is not too important when you’re applying member loads only along the local y axis.
But this post isn’t about member loads in 3D, nor is it about writing new constructors that take vxy as input to the 3D geometric transformation classes. This post is about figuring out the vxz input for OpenSees 3D frame elements without causing a migraine. So, if you want to define your elements such that global vertical is in the local x-y plane, take an extra step in your input file and let Python calculate the local x-z vector that OpenSees expects.
# Local x-axis from nodal coordinates
XYZI = ops.nodeCoord(ndI)
XYZJ = ops.nodeCoord(ndJ)
xaxis = np.subtract(XYZJ,XYZI)
# Vectors in the local x-y and x-z planes
vecxy = [0,1,0] # What you want (vecxy is global vertical)
vecxz = np.cross(xaxis,vecxy) # What OpenSees expects
ops.geomTransf('Linear',1,*vecxz)
In addition to elements that lie in a global horizontal plane, this approach will produce the correct local axes for inclined elements that are axisymmetric about the global vertical axis. This is good news for vectorphobes like me. Of course, elements whose local x axis aligns with global vertical remain a special case.