A previous post compared the natural periods computed by OpenSees for a relatively simple one-story, one-bay, elastic frame to published ETABS results. Many easy to make modeling choices (mass distribution, rigid joint offsets, relative stiffness, etc.) led to “incorrect” periods.
The “correct” modeling choices gave periods from OpenSees that were very close to ETABS–close enough to hit “Publish” and share the post online.
| Mode | Theoretical (sec) | ETABS (sec) | OpenSees (sec) |
| 1 | 0.1389 | 0.1389 | 0.1385 |
| 2 | 0.1254 | 0.1254 | 0.1254 |
| 3 | 0.070 | 0.0702 | 0.06966 |
But something was still slightly amiss with the first and third periods, both of which exhibit torsional response. Then Bashar Hariri pointed out on LinkedIn that torsion was neglected in the elements of the ETABS model.
I sat on this one for a while because it’s not very easy to neglect torsion with a 3D beam-column element in OpenSees.
- The
elasticBeamColumnelement requires torsional inputs G and J - The
forceBeamColumnelement requires at least one of its sections to have torsional stiffness GJ (so that the element can invert basic flexibility), otherwise the element uses a default torsional stiffness of GJ/L=1e10 - The
dispBeamColumnelement does not need torsional stiffness to form its basic stiffness, so this element is the best bet to completely neglect torsion
An elastic section with dispBeamColumn elements should do the trick, but the elastic section requires GJ as well. Aaaccck!
Living in the force-based-element-centric world of OpenSees, I never considered not having torsion in the section when I wrote the elastic section. The force-based element needs torsion, so all frame elements must need it, right?
Fortunately, there’s a way forward that does not require modifying C++ code. Use a sectionAggregator with elastic materials assigned to the P, Mz, and My force-deformation relationships, then put these sections in dispBeamColumn elements. For example, with the beams B1, B2, B3, and B4.
# Instead of this...
#ops.section('Elastic',3,1000*E,A,Iz,Iy,1000*G,J)
# Do this...
ops.uniaxialMaterial('Elastic',5,1000*E*A)
ops.uniaxialMaterial('Elastic',6,1000*E*Iz)
ops.uniaxialMaterial('Elastic',7,1000*E*Iy)
ops.section('Aggregator',3,5,'P',6,'Mz',7,'My')
# Then use dispBeamColumn instead of forceBeamColumn
Similarly, you can make this change for the columns C1, C2, C3, and C4, but only applying the 1000 factor to the section area, A.
With this change applied to all elements in the model (see the original post for the full script), the OpenSees periods move closer to ETABS.
| Mode | Theoretical (sec) | ETABS (sec) | OpenSees (sec) |
| 1 | 0.1389 | 0.1389 | 0.1389 |
| 2 | 0.1254 | 0.1254 | 0.1254 |
| 3 | 0.070 | 0.0702 | 0.0703 |
Thank you, Bashar!

Very interesting! Thanks for sharing this experience which shows, one more time, how important every input is to OpenSees.
LikeLiked by 1 person
On the money matches are satisfying.
In the past, when I was had to compare to methods that neglect torsion, I restrained the twisting degree-of-freedom at every node along the length of the member I was investigating. https://doi.org/10.1061/(ASCE)ST.1943-541X.0002224
LikeLiked by 1 person
Hello Sir, I am very new to this and I have been trying to get the same results using the mentioned method but somehow I have failed to obtain the same result. If you could point out my mistake that would be of great help.
ops.uniaxialMaterial(‘Elastic’,5,1000*E*A)
ops.uniaxialMaterial(‘Elastic’,6,1000*E*Iz)
ops.uniaxialMaterial(‘Elastic’,7,1000*E*Iy)
ops.section(‘Aggregator’,3,5,’P’,6,’Mz’,7,’My’)
ops.beamIntegration(‘Legendre’,3,3,2)
# B1,B2
ops.geomTransf(‘Linear’,3,0,1,0)
ops.element(‘dispBeamColumn’,5,11,12,3,3)
ops.element(‘dispBeamColumn’,6,13,14,3,3)
# B3,B4
ops.geomTransf(‘Linear’,4,1,0,0)
ops.element(‘dispBeamColumn’,7,11,13,4,3)
ops.element(‘dispBeamColumn’,8,12,14,4,3)
ops.node(10, L/2, L/2, H)
ops.fix(10, 0, 0, 1, 1, 1, 0)
ops.rigidDiaphragm(3, 10, 11, 12, 13, 14)
LikeLike
If you are new to OpenSees, I recommend you start with smaller 2D models like this:
https://portwooddigital.com/2020/11/03/how-to-load-beams/
LikeLike
Thank You for replying. I am not sure how to reply to this comment. I guess I made a mistake by being vague about my knowledge about opensees by saying that I am new. To clarify I am learning opensees and I am at this step of verification. I wanted to have closer result of opensees model and etabs model. So, any pointers in this regard is very appreciated.
LikeLike
Great post and very instructive Prof. Scott. I’m going to cite it in a paper I’m writing now.
LikeLiked by 1 person
Thanks! Here’s a list of others who have cited blog posts: https://scholar.google.com/scholar?q=%22portwood+digital%22
And here’s how to cite a post: https://portwooddigital.com/2021/04/21/how-to-cite-a-blog-post/
LikeLike
Hi, Professor Scott. Does bypassing torsional inputs “G” and “J” similar to having 0 torsional stiffness when assembling stiffness matrix? May I know why we have to go such lengths like using section aggregator in bypassing torsional inputs rather than reducing torsional rigidity to a negligible value? Is there some concepts that I have overlooked?
I manage to get the same results by reducing “J” to a negligible value.
From your code, I just modified the following (see bold texts):
Columns
Beams
In neglecting shear deformation on beams, I multiplied 1000 on “A” instead of “G” to not affect the torsional rigidity. Neglecting torsional rigidity is then achieved by reducing “J”.
I hope to hear from you soon. Thank you.
LikeLike
The aggregator is one way to neglect torsion. I’m not sure having very low torsional stiffness is the best approach, but I haven’t looked at this model in a while.
LikeLike