OpenSees Cloud

OpenSees AMI

You Gotta Keep 'em Aggregated

Original Post - 04 Jul 2021 - Michael H. Scott

Visit Structural Analysis Is Simple on Substack.


The SectionAggregator was one of my few useful OpenSees ideas. This class gives a flexible way to combine, or aggregate, modes of force-deformation in a single section model.

The idea for SectionAggregator came from the Decorator software design pattern, the same pattern from which so many UniaxialMaterial wrappers were spawned (here and here). In fact, SectionDecorator was the working title for what would become SectionAggregator.

The need for SectionAggregator came from using force-based frame elements to model shear in reinforced concrete columns. With these elements, flexure and shear are coupled through element equilibrium, so adding a nonlinear shear force-deformation relationship to a fiber section will couple flexural and shear effects. Not as pure as coupling at the material level, but it gets the job done.

In general, there are two use cases for the SectionAggregator:

  1. Combine modes of force-deformation with a pre-existing section model; and
  2. Combine modes of force-deformation into a new section model.

In both cases, all of the aggregated modes are uncoupled from each other and uncoupled from the pre-existing section. A UniaxialMaterial object represents each mode of force-deformation.

Combine uniaxial materials with a section

The first use case adds modes of force-deformation response to a pre-defined section model, e.g., the aforementioned example of fiber section plus shear.

Fiber section plus uniaxial material

You first define your base section and uniaxialMaterial, then aggregate the objects into a new section. To indicate the mode of force-deformation, the aggregated materials are assigned a code: P, Mz, My, Vz, Vy, or T. We’ll add more codes for warping elements, new and old.

ops.section('Fiber',1)
ops.patch(...)
ops.layer(...)

ops.uniaxialMaterial('WhateverYouWant', shearTag, parameters...)

ops.section('Aggregator',2,shearTag,'Vy','-section',1)

Before moving on to 3D considerations and the second use case, here are some random bullets to consider with respect to the SectionAggregator in general:

Specific to 3D analysis, until this recent change in FiberSection3d, you had to use a SectionAggregator to attach torsional response to the section so that the force-based element wouldn’t try to invert a singular flexibility matrix. Now, as described in the post, that aggregation is handled internally, i.e., the FiberSection3d is P-Mz-My-T out of the box.

With torsion taken care of, you can aggregate modes of shear force-deformation to FiberSection3d as well–one in each direction or only one in one direction. I tried to make a figure for 3D aggregation, but it got a little messy, so here’s code instead.

ops.uniaxialMaterial('WhateverYouWant', torsionTag, parameters...)

ops.section('Fiber',3,'-torsion',torsionTag) # or ops.section('Fiber',3,'-GJ',GJ)
ops.patch(...)
ops.layer(...)

ops.uniaxialMaterial('WhateverYouWant', shearTag, parameters...)
# Define another uniaxial material if you want Vy and Vz to be different

ops.section('Aggregator',4,shearTag,'Vy',shearTag,'Vz','-section',3)

Combine uniaxial materials into a new section

The second use case for SectionAggregator is to derive all modes of section response from only uniaxial materials without an underlying section. For example, you can define uniaxial moment-curvature for a section, combined with axial force-deformation response, and potentially shear force-deformation response.

Aggregation of three uniaxial materials

ops.uniaxialMaterial('WhateverYouWant', axialTag, parameters...)
ops.uniaxialMaterial('WhateverYouWant', flexuralTag, parameters...)
ops.uniaxialMaterial('WhateverYouWant', shearTag, parameters...)

ops.section('Aggregator',5,axialTag,'P',flexuralTag,'Mz',shearTag,'Vy') 

For 3D models, you can aggregate axial, flexure, shear, and torsion from disparate uniaxial materials.

ops.uniaxialMaterial('WhateverYouWant', axialTag, parameters...)
ops.uniaxialMaterial('WhateverYouWant', flexuralTag, parameters...)
ops.uniaxialMaterial('WhateverYouWant', shearTag, parameters...)
ops.uniaxialMaterial('WhateverYouWant', torsionTag, parameters...)
# Define other uniaxial materials if you want My and Mz and/or Vy and Vz to be different

ops.section('Aggregator',6,torsionTag,'T',axialTag,'P',flexuralTag,'Mz',shearTag,'Vy',flexuralTag,'My',shearTag,'Vz')

You can put the aggregated uniaxial materials in any order you want–I intentionally put torsion first in the example code above. The beam-column elements (2D and 3D, force-based, displacement-based, and mixed) have switch statements to figure out which modes to use and in what order. For example, in ForceBeamColumn3D, you’ll see code like below.

Switch statement for section response

Although not shown here, the displacement-based and mixed elements do not account for shear and will simply ignore section shear response, whether it’s from SectionAggregator or something else, like an NDFiberSection. The cases for Vy and Vz are missing from the switch statements for these elements.

So, to wrap it up, you can combine anything you want in a SectionAggregator. I can’t show all combinations, but it should be apparent that the SectionAggregator mitigates a lot of unnecessary code duplication.