You can record section response in a frame element if you know the section number, or integration point, of the section whose response you would like to record. This is straightforward for distributed plasticity integration such as Lobatto or Legendre where section number 1 is at end I of the element and section number N is at end J. For example, to record response at section 3, your recorder would begin with the following:
ops.recorder('element',1,'section',3,...)
Instead of a magic number like 3, you could also use an expression like int(N/2)+1
.
But it gets a little complicated with plastic hinge integration. Which section number should you input to record the section response at end J of an element with HingeRadau plastic hinge integration?
A. 2
B. 4
C. 6
D. None of the above
The answer is at the end of this post. Be careful, there are a few “hidden” sections on the element interior for plastic hinge integration.
What if one day Frank or I became super malicious and decided to reorder the integration points coming out of Lobatto, Legendre, the plastic hinge integrations, or the dozen or so other numerical integration options? After all, addition is commutative.
To defend yourself against this unlikely sabotage, you can use the undocumented 'sectionX'
argument for your element recorders. Instead of a section number, you give a section location in the range x=[0,L] where L is the element length. The recorder will find the section closest to the specified location, just like what fiber recorders do with section (y,z) coordinates.
To record the response at the section closest to coordinate x=25 along a frame element, your recorder would start off as:
ops.recorder('element',1,'sectionX',25,...)
The remaining arguments for 'sectionX'
are exactly the same as the regular 'section'
recorder.
Answer: C. 6
Hi Prof. Scott,
Is there a way to get multiple sections in one recorder?
LikeLike
Hi Prof Scott,
Happy Easter.
I’m wondering whether SectionX works only with the displacement based elements. I tried with both element formulations. I got outputs only from the displacement based elements. I also checked with -xml option, force based elements are just blank. Can you please confirm that my findings are correct.
Thanks,
Gopal
LikeLike
Happy Easter, Gopal! A MWE would be helpful to see if there is an issue.
LikeLike
Sorry, what is MWE?
LikeLike
Oops, got it. A Min Working Example. I’ll uploading soon a cantilever column example.
LikeLike
Here is an MWE.
I considered three element types, namely force based, displacement based and mixed formulation. When I used all three be displacement based formulation, I get a fully working sectionX. When I changed all three be forced based formulation, I get outputs for sectionX= 2.5m and 5.0m, but sectionX=0.0 gives null output.
################################################
ops.wipe()
# Define model builder
ops.model(‘basic’, ‘-ndm’, 3, ‘-ndf’, 6)
# Define materials
# —————-
matTag = 1
fy, Es, b = 250.0*u.MPa, 200.0*u.GPa, 0.001
ops.uniaxialMaterial(“Steel01”, matTag, fy, Es, b)
# Define sections
# —————-
secTag = 1
secB, secD, secGJ = 250.0*u.mm, 250.0*u.mm, 10E9
widthDiv, depthDiv = 10, 10
secIJ = [-secD/2, -secB/2, secD/2, secB/2]
ops.section(‘Fiber’, secTag, ‘-GJ’, secGJ)
ops.patch(‘rect’, matTag, widthDiv, depthDiv, *secIJ)
# Define nodes
# ————
ops.node(1, 0., 0., 0.)
ops.node(2, 0., 0., 5.)
ops.node(3, 0., 0., 10.)
ops.node(4, 0., 0., 15.)
# Set boundary condition
# ———————-
ops.fix(1, 1, 1, 1, 1, 1, 1)
# Define elements
# —————-
geomTransTag = 1
ops.geomTransf(‘Corotational’, geomTransTag, -1.0, 0.0, 0.0)
intForceTag, numInt = 1, 5
ops.beamIntegration(‘Lobatto’, intForceTag, secTag, numInt)
ops.element(‘forceBeamColumn’, 1, 1, 2, geomTransTag, intForceTag)
intDispTag, numInt = 2, 5
ops.beamIntegration(‘Legendre’, intDispTag, secTag, numInt)
ops.element(‘dispBeamColumn’, 2, 2, 3, geomTransTag, intDispTag)
intMixTag, numInt = 3, 5
ops.beamIntegration(‘Legendre’, intMixTag, secTag, numInt)
ops.element(‘mixedBeamColumn’, 3, 3, 4, geomTransTag, intMixTag)
# Define recorders
# —————-
ops.recorder(‘Element’, ‘-xml’, ‘ele_curvature_start.txt’, ‘-precision’, 6, ‘-time’,
‘-closeOnWrite’, ‘-ele’, 1, 2, 3, ‘sectionX’, 0.0, ‘deformation’)
ops.recorder(‘Element’, ‘-xml’, ‘ele_curvature_mid.txt’, ‘-precision’, 6, ‘-time’,
‘-closeOnWrite’, ‘-ele’, 1, 2, 3, ‘sectionX’, 2.5, ‘deformation’)
ops.recorder(‘Element’, ‘-xml’, ‘ele_curvature_end.txt’, ‘-precision’, 6, ‘-time’,
‘-closeOnWrite’, ‘-ele’, 1, 2, 3, ‘sectionX’, 5.0, ‘deformation’)
# Define loads
# ————
ops.timeSeries(“Linear”, 1)
ops.pattern(“Plain”, 1, 1)
ops.load(4, 80.0, 0., 0., 0., 0., 0.)
# Analysis parameters
# ——————-
ops.system(“BandSPD”)
ops.numberer(“RCM”)
ops.constraints(“Plain”)
ops.integrator(“LoadControl”, 1.0/10)
ops.algorithm(“Linear”)
ops.analysis(“Static”)
# Perform the analysis
# ——————–
ops.analyze(10)
LikeLike
Thanks! Looks like sectionX was not implemented for mixed and force-based 3D elements. It’s fixed now: https://github.com/OpenSees/OpenSees/pull/832
LikeLiked by 1 person
Hello again,
I have a small issue with the sectionX command. I’m getting a blank output when I tried record curvatures at a point, say mid-point of a list of elements. For example,
ops.recorder(‘element’,*[1, 2, 3],’sectionX’,[0.5, 0.6, 1.0],…)
However, ops.recorder(‘element’,*[1, 2, 3],’sectionX’,0.0,…) works fine.
Can you please comment whether with the current implementation, it is possible to achieve this.
LikeLike
The ‘sectionX’ option only works for a single x value.
LikeLike