OpenSees Cloud

OpenSees AMI

How to Record Section Curvature

Original Post - 10 Apr 2022 - Michael H. Scott

Visit Structural Analysis Is Simple on Substack.


I’ve seen recently a few people compute curvature for an OpenSees fiber section by dividing the difference between top and bottom uniaxial fiber strains by the distance between the fibers. While there’s nothing technically wrong with this approach, it’s a lot of work and it’s error prone. In addition, this approach implies that using a fiber section is the only way to record curvature.

This approach to curvature calculation reminds me of undergraduate structural analysis. When asked to find the direction cosines of a 3-4-5 right triangle, many students will first find an angle from the arctangent function, then take cosine and sine of that angle. But they could have dispensed with the trig functions altogether and simply used 3/5 and 4/5 directly.

Just like the structural analysis students who miscalculate or truncate that 53.13010235 or 36.86989765 degree angle before taking cosine or sine, when you attempt to calculate curvature from uniaxial fiber strains, you’re going to make a sign error and/or use the wrong distance between top and bottom fibers. And what’s “top” and “bottom” in 3D with curvature about two section axes?

Nothing in OpenSees, or structural analysis in general, is that difficult.

You can bypass all those error prone calculations and record the curvature directly. I mean, where do you think uniaxial fiber strains come from in the first place? Yeah, from axial deformation and curvatures with the “plane sections remain plane” kinematic assumption!



With my rant now complete, let’s see a couple ways to get curvature directly from a section. The following examples assume a frame element, e.g. force-based, displacement-based, or mixed.

You can record the section deformations at a specific section in a specific frame element. For example, at section 2 of element 1.

ops.recorder('Element','-file','e2.out','-ele',1,'section',2,'deformation')

Note that the section number is the integration point number, from 1 to Np, not the section tag.

You can also record the deformations at all Np sections in an element by omitting the section number from the recorder, e.g., for element 1.

ops.recorder('Element','-file','eAll.out','-ele',1,'section','deformation')

If you prefer to obtain the section deformations in real time during an analysis, you can use the eleResponse function instead of recorders. Pass the same arguments to eleResponse that you would pass to the recorder.

# Element 1, section number 2
e2 = ops.eleResponse(1,'section',2,'deformation')

# Element 1, all sections
eAll = ops.eleResponse(1,'section','deformation')

Change deformation to force in all of the above and you get section forces.

Using these recorders, it’s easy to plot the internal distributions of moment and curvature for a frame element. Consider the W18x76 shown below loaded in anti-symmetric bending.

Simple beam with applied end moments

We’ll use a single force-based frame element with Np=6 Gauss-Lobatto points. Each section is discretized into fibers and each fiber has a bilinear stress-strain relationship with E=29000 ksi, Fy=50 ksi, and 0.5% strain-hardening.

When the applied end moments are equal to half of the yield moment, the response is linear-elastic and we obtain the moment and curvature distributions shown below.

Curvature distribution prior to yield

After increasing the applied end moments to 1.1My, the beam yields and the curvature distribution becomes nonlinear.

Curvature distribution after yield

The fibers are there, contributing to section stress resultants, blissfully unaware of the curvatures that contributed to their strains.

And of course you can record section deformations for frame elements defined by direct moment-curvature as well as nonlinear elements with elastic sections. Try it for yourself. No fibers required.