structuralcodes 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of structuralcodes might be problematic. Click here for more details.
- structuralcodes/__init__.py +1 -1
- structuralcodes/codes/ec2_2004/_concrete_creep_and_shrinkage.py +1 -1
- structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py +105 -73
- structuralcodes/core/_section_results.py +5 -19
- structuralcodes/core/base.py +26 -11
- structuralcodes/geometry/__init__.py +10 -1
- structuralcodes/geometry/_circular.py +81 -0
- structuralcodes/geometry/_geometry.py +1 -1
- structuralcodes/geometry/_rectangular.py +83 -0
- structuralcodes/geometry/_reinforcement.py +132 -5
- structuralcodes/materials/constitutive_laws/_bilinearcompression.py +46 -1
- structuralcodes/materials/constitutive_laws/_elastic.py +19 -0
- structuralcodes/materials/constitutive_laws/_elasticplastic.py +55 -0
- structuralcodes/materials/constitutive_laws/_parabolarectangle.py +57 -0
- structuralcodes/materials/constitutive_laws/_userdefined.py +44 -0
- structuralcodes/sections/__init__.py +2 -0
- structuralcodes/sections/_generic.py +161 -24
- structuralcodes/sections/_rc_utils.py +114 -0
- structuralcodes/sections/section_integrators/_fiber_integrator.py +204 -108
- structuralcodes/sections/section_integrators/_marin_integrator.py +273 -102
- structuralcodes/sections/section_integrators/_section_integrator.py +28 -4
- {structuralcodes-0.2.0.dist-info → structuralcodes-0.3.0.dist-info}/METADATA +2 -2
- {structuralcodes-0.2.0.dist-info → structuralcodes-0.3.0.dist-info}/RECORD +24 -21
- {structuralcodes-0.2.0.dist-info → structuralcodes-0.3.0.dist-info}/WHEEL +1 -1
|
@@ -7,7 +7,8 @@ import typing as t
|
|
|
7
7
|
import warnings
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
|
-
from numpy.typing import ArrayLike
|
|
10
|
+
from numpy.typing import ArrayLike, NDArray
|
|
11
|
+
from scipy.linalg import lu_factor, lu_solve
|
|
11
12
|
from shapely import MultiPolygon
|
|
12
13
|
from shapely.ops import unary_union
|
|
13
14
|
|
|
@@ -20,7 +21,7 @@ from structuralcodes.geometry import (
|
|
|
20
21
|
)
|
|
21
22
|
from structuralcodes.materials.constitutive_laws import Elastic
|
|
22
23
|
|
|
23
|
-
from .section_integrators import integrator_factory
|
|
24
|
+
from .section_integrators import SectionIntegrator, integrator_factory
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
class GenericSection(Section):
|
|
@@ -82,7 +83,7 @@ class GenericSection(Section):
|
|
|
82
83
|
self._gross_properties = None
|
|
83
84
|
|
|
84
85
|
@property
|
|
85
|
-
def gross_properties(self) -> s_res.
|
|
86
|
+
def gross_properties(self) -> s_res.SectionProperties:
|
|
86
87
|
"""Return the gross properties of the section."""
|
|
87
88
|
if self._gross_properties is None:
|
|
88
89
|
self._gross_properties = (
|
|
@@ -94,6 +95,8 @@ class GenericSection(Section):
|
|
|
94
95
|
class GenericSectionCalculator(SectionCalculator):
|
|
95
96
|
"""Calculator class implementing analysis algorithms for code checks."""
|
|
96
97
|
|
|
98
|
+
integrator: SectionIntegrator
|
|
99
|
+
|
|
97
100
|
def __init__(
|
|
98
101
|
self,
|
|
99
102
|
sec: GenericSection,
|
|
@@ -123,17 +126,17 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
123
126
|
self._n_max = None
|
|
124
127
|
self._n_min = None
|
|
125
128
|
|
|
126
|
-
def _calculate_gross_section_properties(self) -> s_res.
|
|
129
|
+
def _calculate_gross_section_properties(self) -> s_res.SectionProperties:
|
|
127
130
|
"""Calculates the gross section properties of the GenericSection.
|
|
128
131
|
|
|
129
132
|
This function is private and called when the section is created.
|
|
130
133
|
It stores the result into the result object.
|
|
131
134
|
|
|
132
135
|
Returns:
|
|
133
|
-
|
|
136
|
+
SectionProperties: The gross properties of the section.
|
|
134
137
|
"""
|
|
135
138
|
# It will use the algorithms for generic sections
|
|
136
|
-
gp = s_res.
|
|
139
|
+
gp = s_res.SectionProperties()
|
|
137
140
|
|
|
138
141
|
# Computation of perimeter using shapely
|
|
139
142
|
polygon = unary_union(
|
|
@@ -335,7 +338,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
335
338
|
|
|
336
339
|
def find_equilibrium_fixed_pivot(
|
|
337
340
|
self, geom: CompoundGeometry, n: float, yielding: bool = False
|
|
338
|
-
) -> t.
|
|
341
|
+
) -> t.List[float]:
|
|
339
342
|
"""Find the equilibrium changing curvature fixed a pivot.
|
|
340
343
|
The algorithm uses bisection algorithm between curvature
|
|
341
344
|
of balanced failure and 0. Selected the pivot point as
|
|
@@ -349,8 +352,8 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
349
352
|
yielding (bool): ...
|
|
350
353
|
|
|
351
354
|
Returns:
|
|
352
|
-
|
|
353
|
-
|
|
355
|
+
List(float): 3 floats: Axial strain at (0,0), and curvatures of y*
|
|
356
|
+
and z* axes. Note that being uniaxial bending,
|
|
354
357
|
curvature along z* is 0.0.
|
|
355
358
|
"""
|
|
356
359
|
# Number of maximum iteration for the bisection algorithm
|
|
@@ -369,6 +372,10 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
369
372
|
) = self.integrator.integrate_strain_response_on_geometry(
|
|
370
373
|
geom, strain, tri=self.triangulated_data, mesh_size=self.mesh_size
|
|
371
374
|
)
|
|
375
|
+
# save the triangulation data
|
|
376
|
+
if self.triangulated_data is None and tri is not None:
|
|
377
|
+
self.triangulated_data = tri
|
|
378
|
+
|
|
372
379
|
# Check if there is equilibrium with this strain distribution
|
|
373
380
|
chi_a = strain[1]
|
|
374
381
|
dn_a = n_int - n
|
|
@@ -414,9 +421,6 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
414
421
|
s = f'Last iteration reached a unbalance of {dn_c}'
|
|
415
422
|
raise ValueError(f'Maximum number of iterations reached.\n{s}')
|
|
416
423
|
# Found equilibrium
|
|
417
|
-
# save the triangulation data
|
|
418
|
-
if self.triangulated_data is None:
|
|
419
|
-
self.triangulated_data = tri
|
|
420
424
|
# Return the strain distribution
|
|
421
425
|
return [eps_0, chi_c, 0]
|
|
422
426
|
|
|
@@ -496,7 +500,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
496
500
|
) = self.integrator.integrate_strain_response_on_geometry(
|
|
497
501
|
geom, [eps_0, curv, 0], tri=self.triangulated_data
|
|
498
502
|
)
|
|
499
|
-
if self.triangulated_data is None:
|
|
503
|
+
if self.triangulated_data is None and tri is not None:
|
|
500
504
|
self.triangulated_data = tri
|
|
501
505
|
dn_a = n_int - n
|
|
502
506
|
# It may occur that dn_a is already almost zero (in eqiulibrium)
|
|
@@ -557,7 +561,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
557
561
|
self.section.geometry, [eps_p, 0, 0], tri=tri
|
|
558
562
|
)
|
|
559
563
|
|
|
560
|
-
if self.triangulated_data is None:
|
|
564
|
+
if self.triangulated_data is None and tri is not None:
|
|
561
565
|
self.triangulated_data = tri
|
|
562
566
|
return n_min, n_max
|
|
563
567
|
|
|
@@ -604,25 +608,60 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
604
608
|
self.triangulated_data = rotated_triangulated_data
|
|
605
609
|
|
|
606
610
|
def integrate_strain_profile(
|
|
607
|
-
self,
|
|
608
|
-
|
|
609
|
-
|
|
611
|
+
self,
|
|
612
|
+
strain: ArrayLike,
|
|
613
|
+
integrate: t.Literal['stress', 'modulus'] = 'stress',
|
|
614
|
+
) -> t.Union[t.Tuple[float, float, float], NDArray]:
|
|
615
|
+
"""Integrate a strain profile returning stress resultants or tangent
|
|
616
|
+
section stiffness matrix.
|
|
610
617
|
|
|
611
618
|
Arguments:
|
|
612
619
|
strain (ArrayLike): Represents the deformation plane. The strain
|
|
613
620
|
should have three entries representing respectively: axial
|
|
614
621
|
strain (At 0,0 coordinates), curv_y, curv_z.
|
|
622
|
+
integrate (str): a string indicating the quantity to integrate over
|
|
623
|
+
the section. It can be 'stress' or 'modulus'. When 'stress'
|
|
624
|
+
is selected, the return value will be the stress resultants N,
|
|
625
|
+
My, Mz, while if 'modulus' is selected, the return will be the
|
|
626
|
+
tangent section stiffness matrix (default is 'stress').
|
|
615
627
|
|
|
616
628
|
Returns:
|
|
617
|
-
Tuple(float, float, float): N, My and Mz
|
|
629
|
+
Union(Tuple(float, float, float),NDArray): N, My and Mz when
|
|
630
|
+
`integrate='stress'`, or a numpy array representing the stiffness
|
|
631
|
+
matrix then `integrate='modulus'`.
|
|
632
|
+
|
|
633
|
+
Examples:
|
|
634
|
+
result = self.integrate_strain_profile(strain,integrate='tangent')
|
|
635
|
+
# `result` will be the tangent stiffness matrix (a 3x3 numpy array)
|
|
636
|
+
|
|
637
|
+
result = self.integrate_strain_profile(strain)
|
|
638
|
+
# `result` will be a tuple containing section forces (N, My, Mz)
|
|
639
|
+
|
|
640
|
+
Raises:
|
|
641
|
+
ValueError: If a unkown value is passed to the `integrate`
|
|
642
|
+
parameter.
|
|
618
643
|
"""
|
|
619
|
-
|
|
644
|
+
result = self.integrator.integrate_strain_response_on_geometry(
|
|
620
645
|
geo=self.section.geometry,
|
|
621
646
|
strain=strain,
|
|
647
|
+
integrate=integrate,
|
|
622
648
|
tri=self.triangulated_data,
|
|
623
649
|
mesh_size=self.mesh_size,
|
|
624
650
|
)
|
|
625
|
-
|
|
651
|
+
|
|
652
|
+
# Save triangulation data for future use
|
|
653
|
+
if self.triangulated_data is None and result[-1] is not None:
|
|
654
|
+
self.triangulated_data = result[-1]
|
|
655
|
+
|
|
656
|
+
# manage the returning from integrate_strain_response_on_geometry:
|
|
657
|
+
# this function returns one of the two:
|
|
658
|
+
# a. float, float, float, tri (i.e. N, My, Mz, tri)
|
|
659
|
+
# b. (NDArray, tri) (i.e. section stiff matrix, tri)
|
|
660
|
+
# We need to return only forces or stifness
|
|
661
|
+
# (without triangultion data)
|
|
662
|
+
if len(result) == 2:
|
|
663
|
+
return result[0]
|
|
664
|
+
return result[:-1]
|
|
626
665
|
|
|
627
666
|
def calculate_bending_strength(
|
|
628
667
|
self, theta=0, n=0
|
|
@@ -664,13 +703,15 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
664
703
|
if self.triangulated_data is not None:
|
|
665
704
|
# Rotate back also triangulated data!
|
|
666
705
|
self._rotate_triangulated_data(theta)
|
|
706
|
+
# Rotate also curvature!
|
|
707
|
+
strain_rotated = T @ np.array([[strain[1]], [strain[2]]])
|
|
667
708
|
|
|
668
709
|
# Create result object
|
|
669
710
|
res = s_res.UltimateBendingMomentResults()
|
|
670
711
|
res.theta = theta
|
|
671
712
|
res.n = N
|
|
672
|
-
res.chi_y =
|
|
673
|
-
res.chi_z =
|
|
713
|
+
res.chi_y = strain_rotated[0, 0]
|
|
714
|
+
res.chi_z = strain_rotated[1, 0]
|
|
674
715
|
res.eps_a = strain[0]
|
|
675
716
|
res.m_y = M[0, 0]
|
|
676
717
|
res.m_z = M[1, 0]
|
|
@@ -969,7 +1010,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
969
1010
|
mesh_size=self.mesh_size,
|
|
970
1011
|
)
|
|
971
1012
|
)
|
|
972
|
-
if self.triangulated_data is None:
|
|
1013
|
+
if self.triangulated_data is None and tri is not None:
|
|
973
1014
|
self.triangulated_data = tri
|
|
974
1015
|
forces[i, 0] = N
|
|
975
1016
|
forces[i, 1] = My
|
|
@@ -1239,7 +1280,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
1239
1280
|
tri=self.triangulated_data,
|
|
1240
1281
|
)
|
|
1241
1282
|
)
|
|
1242
|
-
if self.triangulated_data is None:
|
|
1283
|
+
if self.triangulated_data is None and tri is not None:
|
|
1243
1284
|
self.triangulated_data = tri
|
|
1244
1285
|
forces[i, 0] = N
|
|
1245
1286
|
forces[i, 1] = My
|
|
@@ -1285,3 +1326,99 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
1285
1326
|
res.strains[i, 2] = res_bend_strength.chi_z
|
|
1286
1327
|
|
|
1287
1328
|
return res
|
|
1329
|
+
|
|
1330
|
+
def calculate_strain_profile(
|
|
1331
|
+
self,
|
|
1332
|
+
n,
|
|
1333
|
+
my,
|
|
1334
|
+
mz,
|
|
1335
|
+
initial: bool = False,
|
|
1336
|
+
max_iter: int = 10,
|
|
1337
|
+
tol: float = 1e-6,
|
|
1338
|
+
) -> t.List[float]:
|
|
1339
|
+
"""Get the strain plane for a given axial force and biaxial bending.
|
|
1340
|
+
|
|
1341
|
+
Args:
|
|
1342
|
+
n (float): Axial load.
|
|
1343
|
+
my (float): Bending moment around y-axis.
|
|
1344
|
+
mz (float): Bending moment around z-axis.
|
|
1345
|
+
initial (bool): If True the modified newton with initial tanget is
|
|
1346
|
+
used (default = False).
|
|
1347
|
+
max_iter (int): the maximum number of iterations in the iterative
|
|
1348
|
+
process (default = 10).
|
|
1349
|
+
tol (float): the tolerance for convergence test in terms of strain
|
|
1350
|
+
increment.
|
|
1351
|
+
|
|
1352
|
+
Returns:
|
|
1353
|
+
List(float): 3 floats: Axial strain at (0,0), and curvatures of the
|
|
1354
|
+
section around y and z axes.
|
|
1355
|
+
"""
|
|
1356
|
+
# Get the gometry
|
|
1357
|
+
geom = self.section.geometry
|
|
1358
|
+
|
|
1359
|
+
# Collect loads in a numpy array
|
|
1360
|
+
loads = np.array([n, my, mz])
|
|
1361
|
+
|
|
1362
|
+
# Compute initial tangent stiffness matrix
|
|
1363
|
+
stiffness_tangent, tri = (
|
|
1364
|
+
self.integrator.integrate_strain_response_on_geometry(
|
|
1365
|
+
geom,
|
|
1366
|
+
[0, 0, 0],
|
|
1367
|
+
integrate='modulus',
|
|
1368
|
+
tri=self.triangulated_data,
|
|
1369
|
+
)
|
|
1370
|
+
)
|
|
1371
|
+
# eventually save the triangulation data
|
|
1372
|
+
if self.triangulated_data is None and tri is not None:
|
|
1373
|
+
self.triangulated_data = tri
|
|
1374
|
+
|
|
1375
|
+
# Calculate strain plane with Newton Rhapson Iterative method
|
|
1376
|
+
num_iter = 0
|
|
1377
|
+
strain = np.zeros(3)
|
|
1378
|
+
|
|
1379
|
+
# Factorize once the stiffness matrix if using initial
|
|
1380
|
+
if initial:
|
|
1381
|
+
# LU factorization
|
|
1382
|
+
# (maybe also Choelesky could work if matrix always SPD?)
|
|
1383
|
+
lu, piv = lu_factor(stiffness_tangent)
|
|
1384
|
+
|
|
1385
|
+
# Do Newton loops
|
|
1386
|
+
while True:
|
|
1387
|
+
# Check if number of iterations exceeds the maximum
|
|
1388
|
+
if num_iter > max_iter:
|
|
1389
|
+
break
|
|
1390
|
+
|
|
1391
|
+
# Calculate response and residuals
|
|
1392
|
+
response = np.array(self.integrate_strain_profile(strain=strain))
|
|
1393
|
+
residual = loads - response
|
|
1394
|
+
|
|
1395
|
+
if initial:
|
|
1396
|
+
# Solve using the decomposed matrix
|
|
1397
|
+
delta_strain = lu_solve((lu, piv), residual)
|
|
1398
|
+
else:
|
|
1399
|
+
# Calculate the current tangent stiffness
|
|
1400
|
+
stiffness_tangent, _ = (
|
|
1401
|
+
self.integrator.integrate_strain_response_on_geometry(
|
|
1402
|
+
geom,
|
|
1403
|
+
strain,
|
|
1404
|
+
integrate='modulus',
|
|
1405
|
+
tri=self.triangulated_data,
|
|
1406
|
+
)
|
|
1407
|
+
)
|
|
1408
|
+
|
|
1409
|
+
# Solve using the current tangent stiffness
|
|
1410
|
+
delta_strain = np.linalg.solve(stiffness_tangent, residual)
|
|
1411
|
+
|
|
1412
|
+
# Update the strain
|
|
1413
|
+
strain += delta_strain
|
|
1414
|
+
|
|
1415
|
+
num_iter += 1
|
|
1416
|
+
|
|
1417
|
+
# Check for convergence:
|
|
1418
|
+
if np.linalg.norm(delta_strain) < tol:
|
|
1419
|
+
break
|
|
1420
|
+
|
|
1421
|
+
if num_iter >= max_iter:
|
|
1422
|
+
raise StopIteration('Maximum number of iterations reached.')
|
|
1423
|
+
|
|
1424
|
+
return strain.tolist()
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""A collection of functions related to reinforced concrete sections."""
|
|
2
|
+
|
|
3
|
+
import typing as t
|
|
4
|
+
|
|
5
|
+
import structuralcodes.core._section_results as s_res
|
|
6
|
+
from structuralcodes.geometry import CompoundGeometry, SurfaceGeometry
|
|
7
|
+
from structuralcodes.materials.constitutive_laws import Elastic, UserDefined
|
|
8
|
+
from structuralcodes.sections import GenericSection
|
|
9
|
+
from structuralcodes.sections.section_integrators import FiberIntegrator
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def calculate_elastic_cracked_properties(
|
|
13
|
+
section: GenericSection,
|
|
14
|
+
theta: float = 0,
|
|
15
|
+
return_cracked_section: bool = False,
|
|
16
|
+
) -> t.Union[
|
|
17
|
+
s_res.SectionProperties, t.Tuple[s_res.SectionProperties, CompoundGeometry]
|
|
18
|
+
]:
|
|
19
|
+
"""Calculates the cracked section properties of a reinforced concrete
|
|
20
|
+
section. (GenericSection). Materials in surface geometries and point
|
|
21
|
+
geometries are elastic-linear in order to make the cracking properties
|
|
22
|
+
independent of the stress state. Tension in all surface geometries is
|
|
23
|
+
neglected.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
section (GenericSection): The section to use as basis for the
|
|
27
|
+
calculation.
|
|
28
|
+
theta (float): Angle of the neutral axis to the horizontal in radians.
|
|
29
|
+
theta=0 implies upper compression block.
|
|
30
|
+
return_cracked_section (bool): If true, returns also the cracked
|
|
31
|
+
section.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
t.Union[SectionProperties, t.Tuple[SectionProperties, GenericSection]]:
|
|
35
|
+
SectionProperties data of a cracked section (i.e cracked section
|
|
36
|
+
properties) and (if return_cracked_section is True) the cracked
|
|
37
|
+
section.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def create_surface_geometries(polygons_list, material):
|
|
41
|
+
"""Process shapely polygons to SurfaceGeometries."""
|
|
42
|
+
# Create an empty list to store SurfaceGeometry objects
|
|
43
|
+
surface_geometries = []
|
|
44
|
+
|
|
45
|
+
# Iterate over the list of polygons and create SurfaceGeometry for each
|
|
46
|
+
for polygon in polygons_list:
|
|
47
|
+
# Create a new SurfaceGeometry for the current polygon
|
|
48
|
+
surface_geometry = SurfaceGeometry(polygon, material)
|
|
49
|
+
# Add the new SurfaceGeometry to the list
|
|
50
|
+
surface_geometries.append(surface_geometry)
|
|
51
|
+
|
|
52
|
+
return CompoundGeometry(surface_geometries)
|
|
53
|
+
|
|
54
|
+
if not section.geometry.reinforced_concrete:
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
rotated_geometry = section.geometry.rotate(-theta)
|
|
58
|
+
|
|
59
|
+
for geo in rotated_geometry.geometries:
|
|
60
|
+
Ec = geo.material.get_tangent(eps=0)
|
|
61
|
+
elastic_concrete = UserDefined([-100, 0], [-100 * Ec, 0])
|
|
62
|
+
geo._material = elastic_concrete
|
|
63
|
+
|
|
64
|
+
for pg in rotated_geometry.point_geometries:
|
|
65
|
+
Es = pg.material.get_tangent(eps=0)
|
|
66
|
+
elastic_steel = Elastic(Es, 'elastic steel')
|
|
67
|
+
pg._material = elastic_steel
|
|
68
|
+
|
|
69
|
+
curv = -1e-5 # Any curvature should return the same mechanical properties.
|
|
70
|
+
# Find the equilibrium with fixed curvature
|
|
71
|
+
eps = section.section_calculator.find_equilibrium_fixed_curvature(
|
|
72
|
+
rotated_geometry, 0, curv, 0
|
|
73
|
+
)[0]
|
|
74
|
+
z_na = -eps / curv # distance to neutral fibre
|
|
75
|
+
|
|
76
|
+
# Cutting concrete geometries and retaining the compressed block
|
|
77
|
+
cut_geom = None
|
|
78
|
+
for part in rotated_geometry.geometries:
|
|
79
|
+
upper_div, lower_div = part.split(((0, z_na), 0))
|
|
80
|
+
# Convert to SurfaceGeometry
|
|
81
|
+
subpart = create_surface_geometries(upper_div, part.material)
|
|
82
|
+
if cut_geom is None:
|
|
83
|
+
cut_geom = subpart
|
|
84
|
+
else:
|
|
85
|
+
cut_geom += subpart
|
|
86
|
+
|
|
87
|
+
# Add reinforcement geometries
|
|
88
|
+
for reinf in rotated_geometry.point_geometries:
|
|
89
|
+
cut_geom += reinf
|
|
90
|
+
|
|
91
|
+
# return geoemtry to original rotation
|
|
92
|
+
cracked_geom = cut_geom.rotate(theta)
|
|
93
|
+
|
|
94
|
+
# Define the cracked section
|
|
95
|
+
if isinstance(section.section_calculator.integrator, FiberIntegrator):
|
|
96
|
+
mesh_size = getattr(
|
|
97
|
+
section.section_calculator.integrator, 'mesh_size', 0.01
|
|
98
|
+
)
|
|
99
|
+
cracked_sec = GenericSection(
|
|
100
|
+
cracked_geom,
|
|
101
|
+
integrator='fiber',
|
|
102
|
+
mesh_size=mesh_size,
|
|
103
|
+
)
|
|
104
|
+
else:
|
|
105
|
+
cracked_sec = GenericSection(cracked_geom, integrator='marin')
|
|
106
|
+
|
|
107
|
+
cracked_prop = cracked_sec.gross_properties
|
|
108
|
+
|
|
109
|
+
if return_cracked_section:
|
|
110
|
+
result = (cracked_prop, cracked_geom)
|
|
111
|
+
else:
|
|
112
|
+
result = cracked_prop
|
|
113
|
+
|
|
114
|
+
return result
|