Skip to content

Commit

Permalink
Merge pull request #480 from robbievanleeuwen/feature/composite-shape…
Browse files Browse the repository at this point in the history
…-factors

Add shape factors for composite analyses
  • Loading branch information
robbievanleeuwen authored Oct 31, 2024
2 parents 416caf2 + 5c53a28 commit 388b367
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 79 deletions.
2 changes: 2 additions & 0 deletions docs/user_guide/results.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ Plastic Analysis
~sectionproperties.analysis.section.Section.get_pc_p
~sectionproperties.analysis.section.Section.get_mp
~sectionproperties.analysis.section.Section.get_mp_p
~sectionproperties.analysis.section.Section.get_sf
~sectionproperties.analysis.section.Section.get_sf_p

.. _label-material-affects-results:

Expand Down
75 changes: 40 additions & 35 deletions src/sectionproperties/analysis/plastic_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,46 +204,51 @@ def calculate_plastic_properties(
if progress and task is not None:
progress.update(task_id=task, advance=1)

# if there are no materials specified, calculate shape factors
# calculate shape factors
props = section.section_props

if (
props.sxx is None
or props.syy is None
or props.s11 is None
or props.s22 is None
):
msg = "Property save failed."
raise RuntimeError(msg)

# for a geometric only analysis sf = s / z
if list(set(section.materials)) == [pre.DEFAULT_MATERIAL]:
if (
section.section_props.zxx_plus
and section.section_props.zxx_minus
and section.section_props.zyy_plus
and section.section_props.zyy_minus
props.zxx_plus
and props.zxx_minus
and props.zyy_plus
and props.zyy_minus
):
section.section_props.sf_xx_plus = (
section.section_props.sxx / section.section_props.zxx_plus
)
section.section_props.sf_xx_minus = (
section.section_props.sxx / section.section_props.zxx_minus
)
section.section_props.sf_yy_plus = (
section.section_props.syy / section.section_props.zyy_plus
)
section.section_props.sf_yy_minus = (
section.section_props.syy / section.section_props.zyy_minus
)
props.sf_xx_plus = props.sxx / props.zxx_plus
props.sf_xx_minus = props.sxx / props.zxx_minus
props.sf_yy_plus = props.syy / props.zyy_plus
props.sf_yy_minus = props.syy / props.zyy_minus
if (
section.section_props.s11
and section.section_props.s22
and section.section_props.z11_plus
and section.section_props.z11_minus
and section.section_props.z22_plus
and section.section_props.z22_minus
props.z11_plus
and props.z11_minus
and props.z22_plus
and props.z22_minus
):
section.section_props.sf_11_plus = (
section.section_props.s11 / section.section_props.z11_plus
)
section.section_props.sf_11_minus = (
section.section_props.s11 / section.section_props.z11_minus
)
section.section_props.sf_22_plus = (
section.section_props.s22 / section.section_props.z22_plus
)
section.section_props.sf_22_minus = (
section.section_props.s22 / section.section_props.z22_minus
)
props.sf_11_plus = props.s11 / props.z11_plus
props.sf_11_minus = props.s11 / props.z11_minus
props.sf_22_plus = props.s22 / props.z22_plus
props.sf_22_minus = props.s22 / props.z22_minus
else:
if props.my_xx and props.my_yy:
props.sf_xx_plus = props.sxx / props.my_xx
props.sf_xx_minus = props.sf_xx_plus
props.sf_yy_plus = props.syy / props.my_yy
props.sf_yy_minus = props.sf_yy_plus
if props.my_11 and props.my_22:
props.sf_11_plus = props.s11 / props.my_11
props.sf_11_minus = props.sf_11_plus
props.sf_22_plus = props.s22 / props.my_22
props.sf_22_minus = props.sf_22_plus

if progress and task is not None:
progress.update(
Expand Down
43 changes: 25 additions & 18 deletions src/sectionproperties/analysis/section.py
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,8 @@ def calculate_plastic_properties(
Note:
If materials are specified, the values calculated for the plastic section
moduli are displayed as plastic moments (i.e :math:`M_p = f_y S`) and the
shape factors are not calculated.
shape factors are calculated as the ratio between the plastic moment and the
yield moment.
Warning:
The geometric properties must be calculated prior to the calculation of the
Expand All @@ -1197,7 +1198,7 @@ def calculate_plastic_properties(
- Plastic centroids (centroidal and principal axes)
- Plastic section moduli (centroidal and principal axes)
- Shape factors, non-composite only (centroidal and principal axes)
- Shape factors (centroidal and principal axes)
"""
# check that a geometric analysis has been performed
if self.section_props.cx is None:
Expand Down Expand Up @@ -3167,22 +3168,25 @@ def get_mp_p(self) -> tuple[float, float]:
def get_sf(self) -> tuple[float, float, float, float]:
"""Returns the cross-section centroidal axis shape factors.
This is a geometric only property, as such this can only be returned if material
properties have *not* been applied to the cross-section.
For a geometric-only analysis, the shape factor is defined as the ratio between
the plastic section modulus and the elastic section modulus. For a composite
analysis the shape factors is defined as the ratio between the plastic moment
and the yield moment.
.. note::
For composite analyses, the ``plus`` values will always equal the ``minus``
values as the yield moment occurs when the first fibre reaches its yield
strength. For geometric-only analyses, the elastic section moduli is
calculated with respect to the top and bottom fibres (i.e. ``plus`` and
``minus``).
Returns:
Centroidal axis shape factors with respect to the top and bottom fibres
(``sf_xx_plus``, ``sf_xx_minus``, ``sf_yy_plus``, ``sf_yy_minus``)
Raises:
RuntimeError: If material properties have been applied
RuntimeError: If a plastic analysis has not been performed
"""
if self.is_composite():
msg = "Attempting to get a geometric only property for a composite analysis"
msg += " (material properties have been applied)."
raise RuntimeError(msg)

if (
self.section_props.sf_xx_plus is None
or self.section_props.sf_xx_minus is None
Expand All @@ -3202,22 +3206,25 @@ def get_sf(self) -> tuple[float, float, float, float]:
def get_sf_p(self) -> tuple[float, float, float, float]:
"""Returns the cross-section principal axis shape factors.
This is a geometric only property, as such this can only be returned if material
properties have *not* been applied to the cross-section.
For a geometric-only analysis, the shape factor is defined as the ratio between
the plastic section modulus and the elastic section modulus. For a composite
analysis the shape factors is defined as the ratio between the plastic moment
and the yield moment.
.. note::
For composite analyses, the ``plus`` values will always equal the ``minus``
values as the yield moment occurs when the first fibre reaches its yield
strength. For geometric-only analyses, the elastic section moduli is
calculated with respect to the top and bottom fibres (i.e. ``plus`` and
``minus``).
Returns:
Principal bending axis shape factors with respect to the top and bottom
fibres (``sf_11_plus``, ``sf_11_minus``, ``sf_22_plus``, ``sf_22_minus``)
Raises:
RuntimeError: If material properties have been applied
RuntimeError: If a plastic analysis has not been performed
"""
if self.is_composite():
msg = "Attempting to get a geometric only property for a composite analysis"
msg += " (material properties have been applied)."
raise RuntimeError(msg)

if (
self.section_props.sf_11_plus is None
or self.section_props.sf_11_minus is None
Expand Down
38 changes: 18 additions & 20 deletions src/sectionproperties/post/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ def print_results(
try:
my_xx, my_yy = section.get_my()
table.add_row("my_xx", f"{my_xx:>{fmt}}")
table.add_row("my_yy-", f"{my_yy:>{fmt}}")
table.add_row("my_yy", f"{my_yy:>{fmt}}")
except RuntimeError:
pass

Expand Down Expand Up @@ -735,7 +735,7 @@ def print_results(
try:
my_11, my_22 = section.get_my_p()
table.add_row("my_11", f"{my_11:>{fmt}}")
table.add_row("my_22-", f"{my_22:>{fmt}}")
table.add_row("my_22", f"{my_22:>{fmt}}")
except RuntimeError:
pass

Expand Down Expand Up @@ -913,26 +913,24 @@ def print_results(
pass

# print cross-section sf
if not is_composite:
try:
sf_xx_plus, sf_xx_minus, sf_yy_plus, sf_yy_minus = section.get_sf()
table.add_row("sf_xx+", f"{sf_xx_plus:>{fmt}}")
table.add_row("sf_xx-", f"{sf_xx_minus:>{fmt}}")
table.add_row("sf_yy+", f"{sf_yy_plus:>{fmt}}")
table.add_row("sf_yy-", f"{sf_yy_minus:>{fmt}}")
except RuntimeError:
pass
try:
sf_xx_plus, sf_xx_minus, sf_yy_plus, sf_yy_minus = section.get_sf()
table.add_row("sf_xx+", f"{sf_xx_plus:>{fmt}}")
table.add_row("sf_xx-", f"{sf_xx_minus:>{fmt}}")
table.add_row("sf_yy+", f"{sf_yy_plus:>{fmt}}")
table.add_row("sf_yy-", f"{sf_yy_minus:>{fmt}}")
except RuntimeError:
pass

# print cross-section sf_p
if not is_composite:
try:
sf_11_plus, sf_11_minus, sf_22_plus, sf_22_minus = section.get_sf_p()
table.add_row("sf_11+", f"{sf_11_plus:>{fmt}}")
table.add_row("sf_11-", f"{sf_11_minus:>{fmt}}")
table.add_row("sf_22+", f"{sf_22_plus:>{fmt}}")
table.add_row("sf_22-", f"{sf_22_minus:>{fmt}}")
except RuntimeError:
pass
try:
sf_11_plus, sf_11_minus, sf_22_plus, sf_22_minus = section.get_sf_p()
table.add_row("sf_11+", f"{sf_11_plus:>{fmt}}")
table.add_row("sf_11-", f"{sf_11_minus:>{fmt}}")
table.add_row("sf_22+", f"{sf_22_plus:>{fmt}}")
table.add_row("sf_22-", f"{sf_22_minus:>{fmt}}")
except RuntimeError:
pass

console = Console()
console.print(table)
Expand Down
31 changes: 31 additions & 0 deletions tests/analysis/test_yield_moment.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ def test_rectangle():
assert check_yield_index(stress, "sig_zz_m11") == pytest.approx(1.0)
assert check_yield_index(stress, "sig_zz_m22") == pytest.approx(1.0)

# check shape factors
sec.calculate_plastic_properties()
sf_xx, _, sf_yy, _ = sec.get_sf()
sf_11, _, sf_22, _ = sec.get_sf_p()
assert sf_xx == pytest.approx(1.5)
assert sf_yy == pytest.approx(1.5)
assert sf_11 == pytest.approx(1.5)
assert sf_22 == pytest.approx(1.5)


def test_rectangle_rotated():
"""Test the yield moment of a simple rotated rectangle."""
Expand All @@ -92,6 +101,12 @@ def test_rectangle_rotated():
assert check_yield_index(stress, "sig_zz_m11") == pytest.approx(1.0)
assert check_yield_index(stress, "sig_zz_m22") == pytest.approx(1.0)

# check shape factors
sec.calculate_plastic_properties()
sf_11, _, sf_22, _ = sec.get_sf_p()
assert sf_11 == pytest.approx(1.5)
assert sf_22 == pytest.approx(1.5)


def test_isection():
"""Test the yield moment of an isection."""
Expand Down Expand Up @@ -119,6 +134,22 @@ def test_isection():
assert check_yield_index(stress, "sig_zz_m11") == pytest.approx(1.0)
assert check_yield_index(stress, "sig_zz_m22") == pytest.approx(1.0)

# check that shape factors with a geometric-only analysis match the composite
sec.calculate_plastic_properties()
sf_xx_c, _, sf_yy_c, _ = sec.get_sf()

geom = i_section(d=200, b=100, t_f=10, t_w=5, r=12, n_r=8)
geom.create_mesh(mesh_sizes=0, coarse=True)
sec = Section(geometry=geom)
sec.calculate_geometric_properties()
sec.calculate_plastic_properties()

sf_xx_plus, sf_xx_minus, sf_yy_plus, sf_yy_minus = sec.get_sf()
assert sf_xx_c == pytest.approx(sf_xx_plus)
assert sf_xx_c == pytest.approx(sf_xx_minus)
assert sf_yy_c == pytest.approx(sf_yy_plus)
assert sf_yy_c == pytest.approx(sf_yy_minus)


def test_rectangle_composite():
"""Test the yield moment of a composite rectangular section."""
Expand Down
6 changes: 0 additions & 6 deletions tests/post/test_get_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,19 +798,13 @@ def test_get_plastic(sec_no_mat_and_mat):
assert sf_yy_plus == pytest.approx(1.5)
assert sf_yy_minus == pytest.approx(1.5)

with pytest.raises(RuntimeError):
rect_mat.get_sf()

# check sf_p
sf_11_plus, sf_11_minus, sf_22_plus, sf_22_minus = rect_no_mat.get_sf_p()
assert sf_11_plus == pytest.approx(1.5)
assert sf_11_minus == pytest.approx(1.5)
assert sf_22_plus == pytest.approx(1.5)
assert sf_22_minus == pytest.approx(1.5)

with pytest.raises(RuntimeError):
rect_mat.get_sf_p()


def test_get_effective_material():
"""Tests effective material properties."""
Expand Down

0 comments on commit 388b367

Please sign in to comment.