Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 63 additions & 34 deletions structuralcodes/sections/_beam_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,56 +320,85 @@ def get_balanced_failure_strain(
rotated frame y*z* it is a case of uniaxial bending).
"""
chi_min = 1e10
for g in geom.geometries + geom.point_geometries:
for other_g in geom.geometries + geom.point_geometries:
# This is left on purpose: even if tempted we should not do
# this check:
# if g != other_g:
eps_p = g.material.constitutive_law.get_ultimate_strain(
# Check if the section is a reinforced concrete section:
# If it is, we need to obtain the "yield" strain of concrete
# (-0.002 for default parabola-rectangle concrete)
is_rc_section = self.section.geometry.reinforced_concrete

# Pre-process all data to avoid expensive calls in the double loop
# below
geom_strain_data = {}
all_geometries = geom.geometries + geom.point_geometries

for g in all_geometries:
# Initialize empty dict
geom_strain_data.setdefault(
g,
{
'eps_p': None,
'eps_n': None,
'y_p': None,
'y_n': None,
},
)

# Find ultimate strain given the 'yielding' arg to the function
geom_strain_data[g]['eps_p'] = (
g.material.constitutive_law.get_ultimate_strain(
yielding=yielding
)[1]
if isinstance(g, SurfaceGeometry):
y_p = g.polygon.bounds[1]
elif isinstance(g, PointGeometry):
y_p = g._point.coords[0][1]
# Check if the section is a reinforced concrete section:
# If it is, we need to obtain the "yield" strain of concrete
# (-0.002 for default parabola-rectangle concrete)
# If the geometry is not concrete, don't get the yield strain
# If it is not a reinforced concrete section, return
# the yield strain if asked.
is_rc_section = self.section.geometry.reinforced_concrete
is_concrete_geom = (
isinstance(other_g, SurfaceGeometry) and other_g.concrete
)
)

use_yielding = (
yielding
if (
(is_rc_section and is_concrete_geom)
or (not is_rc_section)
)
else False
# Find bounding coordinate
if isinstance(g, SurfaceGeometry):
geom_strain_data[g]['y_p'] = g.polygon.bounds[1]
elif isinstance(g, PointGeometry):
geom_strain_data[g]['y_p'] = g._point.coords[0][1]

if isinstance(g, SurfaceGeometry):
geom_strain_data[g]['y_n'] = g.polygon.bounds[3]
elif isinstance(g, PointGeometry):
geom_strain_data[g]['y_n'] = g._point.coords[0][1]

# If the geometry is not concrete, don't get the yield strain
# If it is not a reinforced concrete section, return
# the yield strain if asked.
is_concrete_geom = isinstance(g, SurfaceGeometry) and g.concrete

use_yielding = (
yielding
if (
(is_rc_section and is_concrete_geom) or (not is_rc_section)
)
else False
)

eps_n = other_g.material.constitutive_law.get_ultimate_strain(
geom_strain_data[g]['eps_n'] = (
g.material.constitutive_law.get_ultimate_strain(
yielding=use_yielding
)[0]

if isinstance(other_g, SurfaceGeometry):
y_n = other_g.polygon.bounds[3]
elif isinstance(other_g, PointGeometry):
y_n = other_g._point.coords[0][1]
)
for g, this_geom_strain_data in geom_strain_data.items():
# This is left on purpose: even if tempted we should not do
# this check:
# if g != other_g:
eps_p = this_geom_strain_data['eps_p']
y_p = this_geom_strain_data['y_p']
for _, other_geom_strain_data in geom_strain_data.items():
eps_n = other_geom_strain_data['eps_n']
y_n = other_geom_strain_data['y_n']
if y_p >= y_n:
continue
chi = -(eps_p - eps_n) / (y_p - y_n)
# print(y_p,eps_p,y_n,eps_n,chi)

if chi < chi_min:
chi_min = chi
eps_0 = eps_n + chi_min * y_n
y_n_min = y_n
y_p_min = y_p

y_p, y_n = y_p_min, y_n_min

# In standard CRS negative curvature stretches bottom fiber
strain = [eps_0, -chi_min, 0]
return (y_n, y_p, strain)
Expand Down
Loading