Recording the response of a single fiber in a fiber section is a common ask. You will need to use an Element recorder, but what you can record in each fiber is defined in the UniaxialMaterial::setResponse() method. The most common option is
'stressStrain', which gives the fiber stress-strain response history.
After setResponse() drills down to the section level, there are three options to specify the fiber whose response you would like to record.
1. Fiber index – Let’s get this option out of the way. You can specify the index (from the internal array of material pointers; 0,…,Nf-1) of the fiber you want to record.
Although I’m pretty sure I coded this option, I don’t know how anyone would know the index of a particular fiber. Perhaps this was a useful option for debugging?
2. Fiber closest to a section coordinate – You can ask the recorder to find the fiber closest to section coordinates that you specify.
The section y–z axes are shown below.
3. Fiber with a specified material tag closest to a section coordinate – Just like option 2, but restricts the search to only fibers with the specified material tag. This option is useful for sections with overlapping fibers, e.g., steel and concrete fibers in a reinforced concrete section, where you want to be sure you get the correct fiber.
The same three options are available for FiberSection2d and 3d as well as NDFiberSection2d and 3d.
What comes before
'fiber' depends on the element. For zero length section elements, which are convenient for moment-curvature and axial-moment interaction analysis, you input
'fiber', and then one of the three options shown above.
For the beam-column elements (displacement-based, force-based, and mixed), you can specify a section (integration point) number (1,…,Np; in sequence from node I to node J) and then give the fiber arguments.
A lesser known, but more direct, option is to find the section closest to a specified x-coordinate (0 to L from node I to node J) along a beam-column element.
For the sake of demonstration, we’ll do moment-curvature analysis of an RC section with a single layer of longitudinal steel reinforcement.
Using a zeroLengthSection element with displacement control on the nodal rotation, we know the curvature is the nodal rotation and the moment is the load factor. The model uses basic material models–Concrete01 with standard inputs for compressive and spalling strains, and EPP Steel01–for the fibers.
import openseespy.opensees as ops kip = 1.0 inch = 1.0 ft = 12*inch ksi = kip/inch**2 fc = 4*ksi fy = 60*ksi E = 29000*ksi Abar = 0.79*inch**2 h = 24*inch b = 16*inch ops.wipe() ops.model('basic','-ndm',2,'-ndf',3) ops.node(1,0,0); ops.fix(1,1,1,1) ops.node(2,0,0); ops.fix(2,0,1,0) ops.uniaxialMaterial('Concrete01',1,fc,0.002,0,0.006) ops.uniaxialMaterial('Steel01',2,fy,E,0) ops.section('Fiber',1) ops.patch('rect',1,20,1,-h/2,-b/2,h/2,b/2) ops.layer('straight',2,3,Abar,-h/2+2.5*inch,b/2-2.5*inch,-h/2+2.5*inch,-b/2+2.5*inch) ops.element('zeroLengthSection',1,1,2,1) ops.timeSeries('Linear',1) ops.pattern('Plain',1,1) ops.load(2,0,0,1) Ky = 0.003/(h/2) # ballpark estimate of yield curvature ops.integrator('DisplacementControl',2,3,Ky/100) ops.analysis('Static') epsc = 0 while epsc > -0.003: ops.analyze(1) epsc = ops.nodeDisp(2,1) - h/2*ops.nodeDisp(2,3) ops.wipe()
The analysis stops when the strain at the compression face reaches 0.003. Note that the strain in the extreme compression fiber will be a little less than 0.003 because the strain is sampled at the center of the fiber.
The resulting moment-curvature response is shown below.
With the Whitney stress block (WSB) approximation, the nominal moment strength should be 239.3 kip-ft. The load factor reported by OpenSees is 239.5 kip-ft. For reinforced concrete, that is exact. You can also use the displacements of node 2 to determine the depth to the neutral axis, which also matches the WSB approximation.
Now, let’s define three fiber recorders: A – fiber closest to compression face (y=h/2); B – fiber closest to tension face (y=-h/2); and C – steel fiber closest to tension face.
For 2D problems, bending is about the z-axis, so only the y-coordinate matters when specifying the fiber location. The recorder ignores the z-coordinate, but you still have to input something in its place–0 is perfectly fine.
# Compression fiber ops.recorder('Element','-ele',1,'-file','fiberA.out','section','fiber',h/2,0,'stressStrain') # Tension fiber ops.recorder('Element','-ele',1,'-file','fiberB.out','section','fiber',-h/2,0,'stressStrain') # Tension fiber - steel ops.recorder('Element','-ele',1,'-file','fiberC.out','section','fiber',-h/2,0,2,'stressStrain')
The stress-strain response from each fiber is shown below
Fiber A shows the concrete stress-strain response in compression; fiber B shows the concrete tension response (zero stress); and fiber C shows the EPP response of the reinforcing steel.
Let me know if you run into any problems recording fiber response. There’s been some changes in the code lately that could have temporarily broken this functionality.