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 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 really, 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 *N _{p}*, not the section tag.

You can also record the deformations at all *N _{p}* 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.

We’ll use a single force-based frame element with *N _{p}*=6 Gauss-Lobatto points. Each section is discretized into fibers and each fiber has a bilinear stress-strain relationship with

*E*=29000 ksi,

*F*=50 ksi, and 0.5% strain-hardening.

_{y}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.

After increasing the applied end moments to 1.1*M _{y}*, the beam yields and the curvature distribution becomes nonlinear.

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.