Skip to content

Commit c3b0ef2

Browse files
Add docs, tests, get methods for yield moment
1 parent 92090b6 commit c3b0ef2

File tree

5 files changed

+145
-2
lines changed

5 files changed

+145
-2
lines changed

docs/user_guide/results.rst

+2
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,12 @@ Geometric Analysis
9999
~sectionproperties.analysis.section.Section.get_c
100100
~sectionproperties.analysis.section.Section.get_eic
101101
~sectionproperties.analysis.section.Section.get_ez
102+
~sectionproperties.analysis.section.Section.get_my
102103
~sectionproperties.analysis.section.Section.get_rc
103104
~sectionproperties.analysis.section.Section.get_eip
104105
~sectionproperties.analysis.section.Section.get_phi
105106
~sectionproperties.analysis.section.Section.get_ezp
107+
~sectionproperties.analysis.section.Section.get_my_p
106108
~sectionproperties.analysis.section.Section.get_rp
107109
~sectionproperties.analysis.section.Section.get_nu_eff
108110
~sectionproperties.analysis.section.Section.get_e_eff

docs/user_guide/theory.rst

+5
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,11 @@ extreme (min. and max.) coordinates of the cross-section in the x and y-directio
420420
Z_{yy}^+ = \frac{I_{\overline{yy}}}{x_{max} - x_c} \\
421421
Z_{yy}^- = \frac{I_{\overline{yy}}}{x_c - x_{min}} \\
422422
423+
Yield Moments
424+
~~~~~~~~~~~~~
425+
426+
TODO
427+
423428
.. _label-theory-plastic-section-moduli:
424429

425430
Plastic Section Moduli

src/sectionproperties/analysis/section.py

+64-1
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def calculate_geometric_properties(self) -> None:
202202
- Centroidal section moduli
203203
- Radii of gyration
204204
- Principal axis properties
205+
- Yield moments (composite only)
205206
"""
206207

207208
def calculate_geom(progress: Progress | None = None) -> None:
@@ -259,11 +260,21 @@ def calculate_geom(progress: Progress | None = None) -> None:
259260
)
260261
self.section_props.e_eff = self.section_props.ea / self.section_props.area
261262
self.section_props.g_eff = self.section_props.ga / self.section_props.area
263+
264+
# calculate derived properties
262265
self.section_props.calculate_elastic_centroid()
263266
self.section_props.calculate_centroidal_properties(
264267
node_list=self.mesh["vertices"]
265268
)
266269

270+
# calculate yield moments
271+
self.section_props.my_xx = 0.0
272+
self.section_props.my_yy = 0.0
273+
self.section_props.my_11 = 0.0
274+
self.section_props.my_22 = 0.0
275+
276+
# TODO: calculate yield moments
277+
267278
if progress and task is not None:
268279
msg = "[bold green]:white_check_mark: Geometric analysis complete"
269280
progress.update(task_id=task, description=msg)
@@ -1120,7 +1131,7 @@ def calculate_plastic_properties(
11201131
11211132
- Plastic centroids (centroidal and principal axes)
11221133
- Plastic section moduli (centroidal and principal axes)
1123-
- Shape factors, non-composite only (centroidal and principal axe)
1134+
- Shape factors, non-composite only (centroidal and principal axes)
11241135
"""
11251136
# check that a geometric analysis has been performed
11261137
if self.section_props.cx is None:
@@ -2240,6 +2251,32 @@ def get_ez(
22402251
self.section_props.zyy_minus / e_ref,
22412252
)
22422253

2254+
def get_my(self) -> tuple[float, float]:
2255+
"""Returns the yield moment for bending about the centroidal axis.
2256+
2257+
This is a composite only property, as such this can only be returned if material
2258+
properties have been applied to the cross-section.
2259+
2260+
Returns:
2261+
Yield moment for bending about the centroidal ``x`` and ``y`` axes
2262+
(``my_xx``, ``my_yy``)
2263+
2264+
Raises:
2265+
RuntimeError: If material properties have *not* been applied
2266+
RuntimeError: If a geometric analysis has not been performed
2267+
"""
2268+
if not self.is_composite():
2269+
msg = "Attempting to get a composite only property for a geometric analysis"
2270+
msg += " (material properties have not been applied). Consider using"
2271+
msg += " get_z()."
2272+
raise RuntimeError(msg)
2273+
2274+
if self.section_props.my_xx is None or self.section_props.my_yy is None:
2275+
msg = "Conduct a geometric analysis."
2276+
raise RuntimeError(msg)
2277+
2278+
return (self.section_props.my_xx, self.section_props.my_yy)
2279+
22432280
def get_rc(self) -> tuple[float, float]:
22442281
"""Returns the cross-section centroidal radii of gyration.
22452282
@@ -2418,6 +2455,32 @@ def get_ezp(
24182455
self.section_props.z22_minus / e_ref,
24192456
)
24202457

2458+
def get_my_p(self) -> tuple[float, float]:
2459+
"""Returns the yield moment for bending about the principal axis.
2460+
2461+
This is a composite only property, as such this can only be returned if material
2462+
properties have been applied to the cross-section.
2463+
2464+
Returns:
2465+
Yield moment for bending about the principal ``11`` and ``22`` axes
2466+
(``my_11``, ``my_22``)
2467+
2468+
Raises:
2469+
RuntimeError: If material properties have *not* been applied
2470+
RuntimeError: If a geometric analysis has not been performed
2471+
"""
2472+
if not self.is_composite():
2473+
msg = "Attempting to get a composite only property for a geometric analysis"
2474+
msg += " (material properties have not been applied). Consider using"
2475+
msg += " get_zp()."
2476+
raise RuntimeError(msg)
2477+
2478+
if self.section_props.my_11 is None or self.section_props.my_22 is None:
2479+
msg = "Conduct a geometric analysis."
2480+
raise RuntimeError(msg)
2481+
2482+
return (self.section_props.my_11, self.section_props.my_22)
2483+
24212484
def get_rp(self) -> tuple[float, float]:
24222485
"""Returns the cross-section principal radii of gyration.
24232486

src/sectionproperties/post/post.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ class SectionProperties:
7272
negative extreme value of the 11-axis
7373
r11_c: Radius of gyration about the principal 11-axis.
7474
r22_c: Radius of gyration about the principal 22-axis.
75+
my_xx: Yield moment about the x-axis
76+
my_yy: Yield moment about the y-axis
77+
my_11: Yield moment about the 11-axis
78+
my_22: Yield moment about the 22-axis
7579
j: Torsion constant
7680
omega: Warping function
7781
psi_shear: Psi shear function
@@ -165,6 +169,10 @@ class SectionProperties:
165169
r11_c: float | None = None
166170
r22_c: float | None = None
167171
j: float | None = None
172+
my_xx: float | None = None
173+
my_yy: float | None = None
174+
my_11: float | None = None
175+
my_22: float | None = None
168176
omega: npt.NDArray[np.float64] | None = None
169177
psi_shear: npt.NDArray[np.float64] | None = None
170178
phi_shear: npt.NDArray[np.float64] | None = None
@@ -278,7 +286,7 @@ def calculate_centroidal_properties(
278286
else:
279287
self.phi = np.arctan2(self.ixx_c - self.i11_c, self.ixy_c) * 180 / np.pi
280288

281-
# initialise min, max variables TODO: check for `if xxx:` where xxx is float
289+
# initialise min, max variables
282290
if self.phi is not None:
283291
x1, y2 = fea.principal_coordinate(
284292
phi=self.phi,

tests/analysis/test_yield_moment.py

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""Tests for the yield moment calculation."""
2+
3+
import pytest
4+
5+
from sectionproperties.analysis import Section
6+
from sectionproperties.pre import Material
7+
from sectionproperties.pre.library import rectangular_section
8+
9+
STEEL = Material(
10+
name="Steel",
11+
elastic_modulus=200e3,
12+
poissons_ratio=0.3,
13+
yield_strength=500,
14+
density=7.85e-6,
15+
color="grey",
16+
)
17+
18+
19+
def test_get_without_analysis():
20+
"""Test for raising an error if a geometric analysis has not been performed."""
21+
geom = rectangular_section(d=50, b=50)
22+
geom.create_mesh(mesh_sizes=0, coarse=True)
23+
sec = Section(geometry=geom)
24+
25+
with pytest.raises(RuntimeError, match="Conduct a geometric analysis."):
26+
sec.get_my()
27+
28+
with pytest.raises(RuntimeError, match="Conduct a geometric analysis."):
29+
sec.get_my_p()
30+
31+
32+
def test_non_composite():
33+
"""Test for raising an error for non-composite analyses."""
34+
geom = rectangular_section(d=50, b=50)
35+
geom.create_mesh(mesh_sizes=0, coarse=True)
36+
sec = Section(geometry=geom)
37+
sec.calculate_geometric_properties()
38+
39+
with pytest.raises(RuntimeError, match="Attempting to get a composite only"):
40+
sec.get_my()
41+
42+
with pytest.raises(RuntimeError, match="Attempting to get a composite only"):
43+
sec.get_my_p()
44+
45+
46+
def test_rectangle():
47+
"""Test the yield moment of a simple rectangle."""
48+
geom = rectangular_section(d=100, b=50, material=STEEL)
49+
geom.create_mesh(mesh_sizes=0, coarse=True)
50+
sec = Section(geometry=geom)
51+
sec.calculate_geometric_properties()
52+
53+
my_xx, my_yy = sec.get_my()
54+
my_11, my_22 = sec.get_my()
55+
56+
my_xx_calc = 50 * 100 * 100 / 4 * 500
57+
my_yy_calc = 100 * 50 * 50 / 4 * 500
58+
59+
assert my_xx == pytest.approx(my_xx_calc)
60+
assert my_yy == pytest.approx(my_yy_calc)
61+
assert my_11 == pytest.approx(my_xx_calc)
62+
assert my_22 == pytest.approx(my_yy_calc)
63+
64+
65+
# TODO: add more tests

0 commit comments

Comments
 (0)