Skip to content

Commit 5df4b80

Browse files
Fix plastic calculation for composite sections
1 parent f625987 commit 5df4b80

File tree

1 file changed

+61
-47
lines changed

1 file changed

+61
-47
lines changed

src/sectionproperties/analysis/plastic_section.py

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ def __init__(
3535
Args:
3636
geometry: Section geometry object
3737
"""
38+
# move geometry to geometric centroid
3839
self.geometry = geometry.align_center()
3940
self.geometry.compile_geometry()
4041

4142
# initialize variables to be defined later within calculate_plastic_force
42-
self._c_top = [0.0, 0.0]
43-
self._c_bot = [0.0, 0.0]
44-
self._f_top = 0.0
43+
self._f_list: list[float] = []
44+
self._cx_list: list[float] = []
45+
self._cy_list: list[float] = []
4546

4647
def calculate_plastic_properties(
4748
self,
@@ -89,7 +90,15 @@ def calculate_plastic_properties(
8990

9091
self.check_convergence(root_result=r, axis="x-axis")
9192
section.section_props.y_pc = y_pc
92-
section.section_props.sxx = self._f_top * abs(self._c_top[1] - self._c_bot[1])
93+
94+
# calculate plastic section moduli (plastic moment if composite)
95+
section.section_props.sxx = 0.0
96+
97+
# loop through each geometry force & y-centroid
98+
for f, c in zip(self._f_list, self._cy_list):
99+
# calculate distance from y-centroid to plastic centroid
100+
d_y = abs(c - y_pc)
101+
section.section_props.sxx += f * d_y
93102

94103
if verbose:
95104
self.print_verbose(d=y_pc, root_result=r, axis="x-axis")
@@ -107,7 +116,15 @@ def calculate_plastic_properties(
107116

108117
self.check_convergence(root_result=r, axis="y-axis")
109118
section.section_props.x_pc = x_pc
110-
section.section_props.syy = self._f_top * abs(self._c_top[0] - self._c_bot[0])
119+
120+
# calculate plastic section moduli (plastic moment if composite)
121+
section.section_props.syy = 0.0
122+
123+
# loop through each geometry force & x-centroid
124+
for f, c in zip(self._f_list, self._cx_list):
125+
# calculate distance from x-centroid to plastic centroid
126+
d_x = abs(c - x_pc)
127+
section.section_props.syy += f * d_x
111128

112129
if verbose:
113130
self.print_verbose(d=x_pc, root_result=r, axis="y-axis")
@@ -137,17 +154,20 @@ def calculate_plastic_properties(
137154
verbose=verbose,
138155
)
139156

140-
# calculate the centroids in the principal coordinate system
141-
c_top_p = fea.principal_coordinate(
142-
phi=section.section_props.phi, x=self._c_top[0], y=self._c_top[1]
143-
)
144-
c_bot_p = fea.principal_coordinate(
145-
phi=section.section_props.phi, x=self._c_bot[0], y=self._c_bot[1]
146-
)
147-
148157
self.check_convergence(root_result=r, axis="11-axis")
149158
section.section_props.y22_pc = y22_pc
150-
section.section_props.s11 = self._f_top * abs(c_top_p[1] - c_bot_p[1])
159+
160+
# calculate plastic section moduli (plastic moment if composite)
161+
section.section_props.s11 = 0.0
162+
163+
# loop through each geometry force & xy-centroid
164+
for f, cx, cy in zip(self._f_list, self._cx_list, self._cy_list):
165+
# convert centroid to principal coordinates
166+
c = fea.principal_coordinate(phi=section.section_props.phi, x=cx, y=cy)
167+
168+
# calculate distance from 22-centroid to plastic centroid
169+
d22 = abs(c[1] - y22_pc)
170+
section.section_props.s11 += f * d22
151171

152172
if verbose:
153173
self.print_verbose(d=y22_pc, root_result=r, axis="11-axis")
@@ -163,17 +183,20 @@ def calculate_plastic_properties(
163183
verbose=verbose,
164184
)
165185

166-
# calculate the centroids in the principal coordinate system
167-
c_top_p = fea.principal_coordinate(
168-
phi=section.section_props.phi, x=self._c_top[0], y=self._c_top[1]
169-
)
170-
c_bot_p = fea.principal_coordinate(
171-
phi=section.section_props.phi, x=self._c_bot[0], y=self._c_bot[1]
172-
)
173-
174186
self.check_convergence(root_result=r, axis="22-axis")
175187
section.section_props.x11_pc = x11_pc
176-
section.section_props.s22 = self._f_top * abs(c_top_p[0] - c_bot_p[0])
188+
189+
# calculate plastic section moduli (plastic moment if composite)
190+
section.section_props.s22 = 0.0
191+
192+
# loop through each geometry force & xy-centroid
193+
for f, cx, cy in zip(self._f_list, self._cx_list, self._cy_list):
194+
# convert centroid to principal coordinates
195+
c = fea.principal_coordinate(phi=section.section_props.phi, x=cx, y=cy)
196+
197+
# calculate distance from 11-centroid to plastic centroid
198+
d11 = abs(c[0] - x11_pc)
199+
section.section_props.s22 += f * d11
177200

178201
if verbose:
179202
self.print_verbose(d=x11_pc, root_result=r, axis="22-axis")
@@ -396,13 +419,13 @@ def calculate_plastic_force(
396419
p: Point on the axis line
397420
398421
Returns:
399-
Force in the above and below the axis line (``f_top``, ``f_bot``)
422+
Force in the geometries above and below the axis line (``f_top``, ``f_bot``)
400423
"""
401424
# initialise variables
402425
f_top, f_bot = 0.0, 0.0
403-
a_top, a_bot = 0.0, 0.0
404-
qx_top, qx_bot = 0.0, 0.0
405-
qy_top, qy_bot = 0.0, 0.0
426+
self._f_list = []
427+
self._cx_list = []
428+
self._cy_list = []
406429

407430
# split geometry above and below the line
408431
top_geoms, bot_geoms = self.geometry.split_section(point_i=p, vector=u)
@@ -415,12 +438,14 @@ def calculate_plastic_force(
415438
area_top = top_geom.calculate_area()
416439
cx, cy = top_geom.calculate_centroid()
417440

418-
# sum properties
419-
a_top += area_top
420-
qx_top += cy * area_top
421-
qy_top += cx * area_top
441+
# sum force
422442
f_top += f_y * area_top
423443

444+
# add force and centroids to list
445+
self._f_list.append(f_y * area_top)
446+
self._cx_list.append(cx)
447+
self._cy_list.append(cy)
448+
424449
if bot_geoms:
425450
# loop through all bottom geometries
426451
for bot_geom in bot_geoms:
@@ -429,23 +454,12 @@ def calculate_plastic_force(
429454
area_bot = bot_geom.calculate_area()
430455
cx, cy = bot_geom.calculate_centroid()
431456

432-
# sum properties
433-
a_bot += area_bot
434-
qx_bot += cy * area_bot
435-
qy_bot += cx * area_bot
457+
# sum force
436458
f_bot += f_y * area_bot
437459

438-
# calculate centroid of force action
439-
try:
440-
self._c_top = [qy_top / a_top, qx_top / a_top]
441-
self._f_top = f_top
442-
except ZeroDivisionError:
443-
self._c_top = [0.0, 0.0]
444-
self._f_top = 0.0
445-
446-
try:
447-
self._c_bot = [qy_bot / a_bot, qx_bot / a_bot]
448-
except ZeroDivisionError:
449-
self._c_bot = [0.0, 0.0]
460+
# add force and centroids to list
461+
self._f_list.append(f_y * area_bot)
462+
self._cx_list.append(cx)
463+
self._cy_list.append(cy)
450464

451465
return f_top, f_bot

0 commit comments

Comments
 (0)