structuralcodes 0.2.0__py3-none-any.whl → 0.3.1__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 +101 -0
- structuralcodes/geometry/_geometry.py +7 -2
- structuralcodes/geometry/_rectangular.py +101 -0
- structuralcodes/geometry/_reinforcement.py +132 -5
- structuralcodes/materials/constitutive_laws/_bilinearcompression.py +56 -10
- 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.1.dist-info}/METADATA +2 -2
- {structuralcodes-0.2.0.dist-info → structuralcodes-0.3.1.dist-info}/RECORD +24 -21
- {structuralcodes-0.2.0.dist-info → structuralcodes-0.3.1.dist-info}/WHEEL +1 -1
|
@@ -6,11 +6,15 @@ import typing as t
|
|
|
6
6
|
from math import atan2, cos, sin
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
|
-
from numpy.typing import ArrayLike
|
|
9
|
+
from numpy.typing import ArrayLike, NDArray
|
|
10
10
|
from shapely import MultiLineString, MultiPolygon, Polygon
|
|
11
11
|
from shapely.geometry.polygon import orient
|
|
12
12
|
|
|
13
|
-
from structuralcodes.geometry import
|
|
13
|
+
from structuralcodes.geometry import (
|
|
14
|
+
CompoundGeometry,
|
|
15
|
+
SurfaceGeometry,
|
|
16
|
+
create_line_point_angle,
|
|
17
|
+
)
|
|
14
18
|
|
|
15
19
|
from ._marin_integration import marin_integration
|
|
16
20
|
from ._section_integrator import SectionIntegrator
|
|
@@ -19,102 +23,104 @@ from ._section_integrator import SectionIntegrator
|
|
|
19
23
|
class MarinIntegrator(SectionIntegrator):
|
|
20
24
|
"""Section integrator based on the Marin algorithm."""
|
|
21
25
|
|
|
22
|
-
def
|
|
26
|
+
def _rotate_geometry(
|
|
23
27
|
self, geo: CompoundGeometry, strain: ArrayLike
|
|
24
|
-
) -> t.Tuple[float,
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
Calculate the stresses based on strains in a set of points.
|
|
28
|
-
|
|
29
|
-
Keyword Arguments:
|
|
30
|
-
geo (CompoundGeometry): The geometry of the section.
|
|
31
|
-
strain (ArrayLike): The strains and curvatures of the section,
|
|
32
|
-
given in the format (ea, ky, kz) which are i) strain at 0,0,
|
|
33
|
-
ii) curvature y axis, iii) curvature z axis.
|
|
34
|
-
mesh_size: Percentage of area (number from 0 to 1) max for triangle
|
|
35
|
-
elements.
|
|
36
|
-
|
|
37
|
-
Returns:
|
|
38
|
-
Tuple(float, Tuple(ndarray, ndarray, ndarray)): The prepared input
|
|
39
|
-
represented as the angle of rotation computed (needed for rotating
|
|
40
|
-
back the resultants) and as a tuple with 3 ndarrys collecting
|
|
41
|
-
respectively y, z and stress coefficients for each sub-part.
|
|
28
|
+
) -> t.Tuple[float, CompoundGeometry, ArrayLike]:
|
|
29
|
+
"""This function returns the geometry, strain and angle in a rotated
|
|
30
|
+
CRS for which bending is uniaxial.
|
|
42
31
|
"""
|
|
43
|
-
#
|
|
44
|
-
# - For each geo:
|
|
45
|
-
# - ask constitutive law strain limits and coefficients
|
|
46
|
-
# - For each material part, the part should furthermore be split
|
|
47
|
-
# according to constant, linear and parabolic stress distribution.
|
|
48
|
-
# - For each part collect coordinates y and z in separate np.ndarray
|
|
49
|
-
# iterables, and stress coefficients in a two-dimensional np.ndarray.
|
|
50
|
-
#
|
|
51
|
-
# The method should therefore return a tuple that collects the y, z,
|
|
52
|
-
# and stress coefficients for each part.
|
|
53
|
-
prepared_input = []
|
|
54
|
-
# 1. Rotate section in order to have neutral axis horizontal
|
|
32
|
+
# Rotate section in order to have neutral axis horizontal
|
|
55
33
|
angle = -atan2(strain[2], strain[1])
|
|
56
34
|
|
|
57
35
|
rotated_geom = geo.rotate(angle)
|
|
58
|
-
#
|
|
36
|
+
# Determine strain in this rotated CRS
|
|
59
37
|
strain_rotated = [strain[0], (strain[2] ** 2 + strain[1] ** 2) ** 0.5]
|
|
60
38
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
39
|
+
return angle, rotated_geom, strain_rotated
|
|
40
|
+
|
|
41
|
+
def _get_input_polygon(
|
|
42
|
+
self, polygon: Polygon, coeffs: ArrayLike, input: list
|
|
43
|
+
):
|
|
44
|
+
"""Appends to input list the coordinates and coefficient of polygon."""
|
|
45
|
+
# Let's be sure to orient in the right way
|
|
46
|
+
if polygon.is_empty:
|
|
47
|
+
return
|
|
48
|
+
polygon = orient(polygon, 1)
|
|
49
|
+
if not polygon.exterior.is_ccw:
|
|
50
|
+
raise ValueError(
|
|
51
|
+
'The exterior of a polygon should have vertices \
|
|
52
|
+
ordered ccw'
|
|
53
|
+
)
|
|
54
|
+
# Manage exterior part
|
|
55
|
+
x, y = polygon.exterior.coords.xy
|
|
56
|
+
x = np.array(x)
|
|
57
|
+
y = np.array(y)
|
|
58
|
+
input.append((0, np.array(x), np.array(y), np.array(coeffs)))
|
|
59
|
+
# Manage holes
|
|
60
|
+
for i in polygon.interiors:
|
|
61
|
+
if i.is_ccw:
|
|
62
|
+
raise ValueError('A inner hole should have cw coordinates')
|
|
63
|
+
x, y = i.coords.xy
|
|
64
|
+
input.append((0, np.array(x), np.array(y), np.array(coeffs)))
|
|
65
|
+
|
|
66
|
+
def _get_coefficcients(
|
|
67
|
+
self,
|
|
68
|
+
geo: SurfaceGeometry,
|
|
69
|
+
strain: ArrayLike,
|
|
70
|
+
integrate: t.Literal['stress', 'modulus'] = 'stress',
|
|
71
|
+
) -> t.Tuple[t.List[t.Tuple], t.List[t.Tuple]]:
|
|
72
|
+
"""Get Marin coefficients."""
|
|
73
|
+
if integrate == 'stress':
|
|
74
|
+
if hasattr(geo.material, '__marin__'):
|
|
75
|
+
strains, coeffs = geo.material.__marin__(strain=strain)
|
|
66
76
|
else:
|
|
67
77
|
raise AttributeError(
|
|
68
|
-
f'The material object {
|
|
69
|
-
not have implement the __marin__ function. \
|
|
70
|
-
Please implement the function or use another integrator
|
|
71
|
-
|
|
78
|
+
f'The material object {geo.material} of geometry {geo} \
|
|
79
|
+
does not have implement the __marin__ function. \
|
|
80
|
+
Please implement the function or use another integrator,\
|
|
81
|
+
like '
|
|
72
82
|
'Fibre'
|
|
73
83
|
''
|
|
74
84
|
)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# Manage exterior part
|
|
88
|
-
x, y = polygon.exterior.coords.xy
|
|
89
|
-
x = np.array(x)
|
|
90
|
-
y = np.array(y)
|
|
91
|
-
prepared_input.append(
|
|
92
|
-
(0, np.array(x), np.array(y), np.array(coeffs))
|
|
85
|
+
elif integrate == 'modulus':
|
|
86
|
+
if hasattr(geo.material, '__marin_tangent__'):
|
|
87
|
+
strains, coeffs = geo.material.__marin_tangent__(strain=strain)
|
|
88
|
+
else:
|
|
89
|
+
raise AttributeError(
|
|
90
|
+
f'The material object {geo.material} of geometry {geo} \
|
|
91
|
+
does not have implement the __marin_tangent__ function\
|
|
92
|
+
. \
|
|
93
|
+
Please implement the function or use another integrato\
|
|
94
|
+
r, like '
|
|
95
|
+
'Fibre'
|
|
96
|
+
''
|
|
93
97
|
)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
'A inner hole should have cw coordinates'
|
|
99
|
-
)
|
|
100
|
-
x, y = i.coords.xy
|
|
101
|
-
prepared_input.append(
|
|
102
|
-
(0, np.array(x), np.array(y), np.array(coeffs))
|
|
103
|
-
)
|
|
98
|
+
else:
|
|
99
|
+
raise ValueError(f'Unknown integrate type: {integrate}')
|
|
100
|
+
|
|
101
|
+
return strains, coeffs
|
|
104
102
|
|
|
103
|
+
def _process_surface_geometries(
|
|
104
|
+
self,
|
|
105
|
+
geo: CompoundGeometry,
|
|
106
|
+
strain: ArrayLike,
|
|
107
|
+
input: t.List,
|
|
108
|
+
integrate: t.Literal['stress', 'modulus'] = 'stress',
|
|
109
|
+
):
|
|
110
|
+
"""Process Surface geometries filling the input data for each one."""
|
|
111
|
+
# For each SurfaceGeometry on the CompoundGeometry:
|
|
112
|
+
for g in geo.geometries:
|
|
113
|
+
# Get coefficients and strain limits from constitutive law
|
|
114
|
+
strains, coeffs = self._get_coefficcients(g, strain, integrate)
|
|
115
|
+
|
|
116
|
+
# Subdivide the polygon at the different strain limits
|
|
105
117
|
if strains is None:
|
|
106
|
-
|
|
118
|
+
self._get_input_polygon(g.polygon, coeffs[0], input)
|
|
107
119
|
else:
|
|
108
120
|
for p in range(len(strains)):
|
|
109
121
|
# Create the two lines for selecting the needed part
|
|
110
|
-
y0 = (
|
|
111
|
-
|
|
112
|
-
/ strain_rotated[1]
|
|
113
|
-
)
|
|
114
|
-
y1 = (
|
|
115
|
-
-(strain_rotated[0] - strains[p][1])
|
|
116
|
-
/ strain_rotated[1]
|
|
117
|
-
)
|
|
122
|
+
y0 = -(strain[0] - strains[p][0]) / strain[1]
|
|
123
|
+
y1 = -(strain[0] - strains[p][1]) / strain[1]
|
|
118
124
|
if y0 > y1:
|
|
119
125
|
y0, y1 = y1, y0
|
|
120
126
|
bbox = g.polygon.bounds
|
|
@@ -126,29 +132,94 @@ class MarinIntegrator(SectionIntegrator):
|
|
|
126
132
|
|
|
127
133
|
if isinstance(result, Polygon):
|
|
128
134
|
# If the result is a single polygon
|
|
129
|
-
|
|
135
|
+
self._get_input_polygon(result, coeffs[p], input)
|
|
130
136
|
elif isinstance(result, MultiPolygon):
|
|
131
137
|
# If the result is a MultiPolygon
|
|
132
138
|
for polygon in result.geoms:
|
|
133
|
-
|
|
139
|
+
self._get_input_polygon(polygon, coeffs[p], input)
|
|
140
|
+
|
|
141
|
+
def _process_point_geometries(
|
|
142
|
+
self,
|
|
143
|
+
geo: CompoundGeometry,
|
|
144
|
+
strain: ArrayLike,
|
|
145
|
+
input: t.List,
|
|
146
|
+
integrate: t.Literal['stress', 'modulus'] = 'stress',
|
|
147
|
+
):
|
|
148
|
+
"""Process Point geometries filling the input data."""
|
|
134
149
|
# Tentative proposal for managing reinforcement (PointGeometry)
|
|
135
150
|
x = []
|
|
136
151
|
y = []
|
|
137
|
-
|
|
138
|
-
for pg in
|
|
152
|
+
IA = []
|
|
153
|
+
for pg in geo.point_geometries:
|
|
139
154
|
xp, yp = pg._point.coords.xy
|
|
140
155
|
xp = xp[0]
|
|
141
156
|
yp = yp[0]
|
|
142
157
|
A = pg.area
|
|
143
|
-
|
|
158
|
+
strain_ = strain[0] + strain[1] * yp
|
|
144
159
|
x.append(xp)
|
|
145
160
|
y.append(yp)
|
|
146
|
-
|
|
147
|
-
|
|
161
|
+
if integrate == 'stress':
|
|
162
|
+
IA.append(pg.material.get_stress(strain_) * A)
|
|
163
|
+
elif integrate == 'modulus':
|
|
164
|
+
IA.append(pg.material.get_tangent(strain_) * A)
|
|
165
|
+
input.append((1, np.array(x), np.array(y), np.array(IA)))
|
|
166
|
+
|
|
167
|
+
def prepare_input(
|
|
168
|
+
self,
|
|
169
|
+
geo: CompoundGeometry,
|
|
170
|
+
strain: ArrayLike,
|
|
171
|
+
integrate: t.Literal['stress', 'modulus'] = 'stress',
|
|
172
|
+
) -> t.Tuple[float, t.Tuple[np.ndarray, np.ndarray, np.ndarray]]:
|
|
173
|
+
"""Prepare general input to the integration of stress or material
|
|
174
|
+
modulus in the section.
|
|
175
|
+
|
|
176
|
+
Calculate the stress resultants or tangent section stiffness based on
|
|
177
|
+
strains in a set of points.
|
|
178
|
+
|
|
179
|
+
Keyword Arguments:
|
|
180
|
+
geo (CompoundGeometry): The geometry of the section.
|
|
181
|
+
strain (ArrayLike): The strains and curvatures of the section,
|
|
182
|
+
given in the format (ea, ky, kz) which are i) strain at 0,0,
|
|
183
|
+
ii) curvature y axis, iii) curvature z axis.
|
|
184
|
+
integrate (str): a string indicating the quantity to integrate over
|
|
185
|
+
the section. It can be 'stress' or 'modulus'. When 'stress'
|
|
186
|
+
is selected, the return value will be the stress resultants N,
|
|
187
|
+
My, Mz, while if 'modulus' is selected, the return will be the
|
|
188
|
+
section stiffness matrix (default is 'stress').
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Tuple(float, Tuple(ndarray, ndarray, ndarray)): The prepared input
|
|
192
|
+
represented as the angle of rotation computed (needed for rotating
|
|
193
|
+
back the resultants) and as a tuple with 3 ndarrys collecting
|
|
194
|
+
respectively y, z and stress coefficients for each sub-part.
|
|
195
|
+
|
|
196
|
+
Raises:
|
|
197
|
+
ValueError: If a unkown value is passed to the `integrate`
|
|
198
|
+
parameter.
|
|
199
|
+
"""
|
|
200
|
+
# The method should therefore return a tuple that collects the y, z,
|
|
201
|
+
# and stress coefficients for each part.
|
|
202
|
+
prepared_input = []
|
|
203
|
+
# Rotate section in order to have neutral axis horizontal
|
|
204
|
+
angle, rotated_geom, strain_rotated = self._rotate_geometry(
|
|
205
|
+
geo, strain
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# Process all the surface geometries splitting them and appending
|
|
209
|
+
# coefficients and strain limits to prepared_input
|
|
210
|
+
self._process_surface_geometries(
|
|
211
|
+
rotated_geom, strain_rotated, prepared_input, integrate
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Process all the point geometries (i.e. reinforcement) splitting them
|
|
215
|
+
# and appending coefficients and strain limits to prepared_input
|
|
216
|
+
self._process_point_geometries(
|
|
217
|
+
rotated_geom, strain_rotated, prepared_input, integrate
|
|
218
|
+
)
|
|
148
219
|
|
|
149
220
|
return angle, prepared_input
|
|
150
221
|
|
|
151
|
-
def
|
|
222
|
+
def integrate_stress(
|
|
152
223
|
self,
|
|
153
224
|
angle: float,
|
|
154
225
|
prepared_input: t.List[
|
|
@@ -161,10 +232,10 @@ class MarinIntegrator(SectionIntegrator):
|
|
|
161
232
|
prepared_input (List): The prepared input from .prepare_input().
|
|
162
233
|
|
|
163
234
|
Returns:
|
|
164
|
-
Tuple(float, float, float): The stress resultants N,
|
|
235
|
+
Tuple(float, float, float): The stress resultants N, My and Mz.
|
|
165
236
|
"""
|
|
166
237
|
# Set the stress resultants to zero
|
|
167
|
-
N,
|
|
238
|
+
N, My, Mz = 0.0, 0.0, 0.0
|
|
168
239
|
|
|
169
240
|
# Loop through all parts of the section and add contributions
|
|
170
241
|
for i, y, z, stress_coeff in prepared_input:
|
|
@@ -176,47 +247,147 @@ class MarinIntegrator(SectionIntegrator):
|
|
|
176
247
|
area_moments_N = np.array(
|
|
177
248
|
[marin_integration(y, z, 0, k) for k in range(n)]
|
|
178
249
|
)
|
|
179
|
-
|
|
250
|
+
area_moments_My = np.array(
|
|
180
251
|
[marin_integration(y, z, 0, k + 1) for k in range(n)]
|
|
181
252
|
)
|
|
182
|
-
|
|
253
|
+
area_moments_Mz = np.array(
|
|
183
254
|
[marin_integration(y, z, 1, k) for k in range(n)]
|
|
184
255
|
)
|
|
185
256
|
|
|
186
257
|
# Calculate contributions to stress resultants
|
|
187
258
|
N += sum(stress_coeff * area_moments_N)
|
|
188
|
-
Mx += sum(stress_coeff * area_moments_Mx)
|
|
189
259
|
My += sum(stress_coeff * area_moments_My)
|
|
260
|
+
Mz -= sum(stress_coeff * area_moments_Mz)
|
|
190
261
|
elif i == 1:
|
|
191
262
|
# Reinforcement
|
|
192
263
|
N += sum(stress_coeff)
|
|
193
|
-
|
|
194
|
-
|
|
264
|
+
My += sum(stress_coeff * z)
|
|
265
|
+
Mz -= sum(stress_coeff * y)
|
|
195
266
|
|
|
196
267
|
# Rotate back to section CRS
|
|
197
268
|
T = np.array([[cos(-angle), -sin(-angle)], [sin(-angle), cos(-angle)]])
|
|
198
|
-
M = T @ np.array([[
|
|
269
|
+
M = T @ np.array([[My], [Mz]])
|
|
199
270
|
|
|
200
271
|
return N, M[0, 0], M[1, 0]
|
|
201
272
|
|
|
273
|
+
def integrate_modulus(
|
|
274
|
+
self,
|
|
275
|
+
angle: float,
|
|
276
|
+
prepared_input: t.List[
|
|
277
|
+
t.Tuple[int, np.ndarray, np.ndarray, np.ndarray]
|
|
278
|
+
],
|
|
279
|
+
) -> NDArray[np.float64]:
|
|
280
|
+
"""Integrate material modulus over the geometry.
|
|
281
|
+
|
|
282
|
+
Arguments:
|
|
283
|
+
prepared_input (List): The prepared input from .prepare_input().
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
ndarray: The section stiffness matrix as a (3, 3) ndarray.
|
|
287
|
+
"""
|
|
288
|
+
# Create the stiffness matrix
|
|
289
|
+
stiffness = np.zeros((3, 3), dtype=np.float64)
|
|
290
|
+
|
|
291
|
+
# Create a map of indices
|
|
292
|
+
# (i,j), m, offset, sign
|
|
293
|
+
indices = [
|
|
294
|
+
((0, 0), 0, 0, 1),
|
|
295
|
+
((0, 1), 0, 1, 1),
|
|
296
|
+
((0, 2), 1, 0, -1),
|
|
297
|
+
((1, 1), 0, 2, 1),
|
|
298
|
+
((1, 2), 1, 1, -1),
|
|
299
|
+
((2, 2), 2, 0, 1),
|
|
300
|
+
]
|
|
301
|
+
|
|
302
|
+
# Loop through all parts of the section and add contributions
|
|
303
|
+
for id, y, z, modulus_coeff in prepared_input:
|
|
304
|
+
if id == 0:
|
|
305
|
+
# Find integration order from shape of stress coeff array
|
|
306
|
+
n = modulus_coeff.shape[0]
|
|
307
|
+
|
|
308
|
+
# Calculate needed area moments
|
|
309
|
+
for (i, j), m, offset, sign in indices:
|
|
310
|
+
area_moments = np.array(
|
|
311
|
+
[
|
|
312
|
+
marin_integration(y, z, m, k + offset)
|
|
313
|
+
for k in range(n)
|
|
314
|
+
]
|
|
315
|
+
)
|
|
316
|
+
stiffness[i, j] += sign * sum(modulus_coeff * area_moments)
|
|
317
|
+
elif id == 1:
|
|
318
|
+
# Reinforcement
|
|
319
|
+
stiffness[0, 0] += sum(modulus_coeff)
|
|
320
|
+
stiffness[0, 1] += sum(modulus_coeff * z)
|
|
321
|
+
stiffness[0, 2] -= sum(modulus_coeff * y)
|
|
322
|
+
stiffness[1, 1] += sum(modulus_coeff * z * z)
|
|
323
|
+
stiffness[1, 2] -= sum(modulus_coeff * y * z)
|
|
324
|
+
stiffness[2, 2] += sum(modulus_coeff * y * y)
|
|
325
|
+
|
|
326
|
+
# Apply for simmetry
|
|
327
|
+
stiffness[1, 0] = stiffness[0, 1]
|
|
328
|
+
stiffness[2, 0] = stiffness[0, 2]
|
|
329
|
+
stiffness[2, 1] = stiffness[1, 2]
|
|
330
|
+
|
|
331
|
+
# Rotate back to section CRS
|
|
332
|
+
T = np.array([[cos(-angle), -sin(-angle)], [sin(-angle), cos(-angle)]])
|
|
333
|
+
T = T @ np.array([[100], [-100]])
|
|
334
|
+
|
|
335
|
+
T = np.array(
|
|
336
|
+
[
|
|
337
|
+
[1, 0, 0],
|
|
338
|
+
[0, cos(-angle), sin(-angle)],
|
|
339
|
+
[0, -sin(-angle), cos(-angle)],
|
|
340
|
+
]
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
return T.T @ stiffness @ T
|
|
344
|
+
|
|
202
345
|
def integrate_strain_response_on_geometry(
|
|
203
|
-
self,
|
|
346
|
+
self,
|
|
347
|
+
geo: CompoundGeometry,
|
|
348
|
+
strain: ArrayLike,
|
|
349
|
+
integrate: t.Literal['stress', 'modulus'] = 'stress',
|
|
350
|
+
**kwargs,
|
|
204
351
|
):
|
|
205
|
-
"""Integrate the
|
|
352
|
+
"""Integrate strees or material modulus in the section with the marin
|
|
353
|
+
algorithm.
|
|
354
|
+
|
|
355
|
+
Calculate the stress resultants or tangent section stiffness based on
|
|
356
|
+
strains in a set of points.
|
|
206
357
|
|
|
207
358
|
Arguments:
|
|
208
359
|
geo (CompoundGeometry): The geometry of the section.
|
|
209
360
|
strain (ArrayLike): The strains and curvatures of the section,
|
|
210
361
|
given in the format (ea, ky, kz) which are i) strain at 0,0,
|
|
211
362
|
ii) curvature y axis, iii) curvature z axis.
|
|
363
|
+
integrate (str): a string indicating the quantity to integrate over
|
|
364
|
+
the section. It can be 'stress' or 'modulus'. When 'stress'
|
|
365
|
+
is selected, the return value will be the stress resultants N,
|
|
366
|
+
My, Mz, while if 'modulus' is selected, the return will be the
|
|
212
367
|
|
|
213
368
|
Returns:
|
|
214
|
-
Tuple(Tuple(float, float, float),
|
|
215
|
-
|
|
369
|
+
Tuple(Union(Tuple(float, float, float), np.ndarray), None): The
|
|
370
|
+
first element is either a tuple of floats (for the stress
|
|
371
|
+
resultants (N, My, Mz) when `integrate='stress'`, or a numpy
|
|
372
|
+
array representing the stiffness matrix then `integrate='modulus'`.
|
|
373
|
+
|
|
374
|
+
Example:
|
|
375
|
+
result, _ = integrate_strain_response_on_geometry(geo, strain,
|
|
376
|
+
integrate='tanent')
|
|
377
|
+
# `result` will be the stiffness matrix (a 3x3 numpy array) if
|
|
378
|
+
# `integrate='modulus'`
|
|
379
|
+
|
|
380
|
+
Raises:
|
|
381
|
+
ValueError: If a unkown value is passed to the `integrate`
|
|
382
|
+
parameter.
|
|
216
383
|
"""
|
|
217
384
|
del kwargs
|
|
218
385
|
# Prepare the general input based on the geometry and the input strains
|
|
219
|
-
angle, prepared_input = self.prepare_input(geo, strain)
|
|
386
|
+
angle, prepared_input = self.prepare_input(geo, strain, integrate)
|
|
220
387
|
|
|
221
388
|
# Return the calculated response
|
|
222
|
-
|
|
389
|
+
if integrate == 'stress':
|
|
390
|
+
return *self.integrate_stress(angle, prepared_input), None
|
|
391
|
+
if integrate == 'modulus':
|
|
392
|
+
return self.integrate_modulus(angle, prepared_input), None
|
|
393
|
+
raise ValueError(f'Unknown integrate type: {integrate}')
|
|
@@ -13,18 +13,22 @@ class SectionIntegrator(abc.ABC):
|
|
|
13
13
|
"""Abstract base class for section integrators."""
|
|
14
14
|
|
|
15
15
|
@abc.abstractmethod
|
|
16
|
-
def prepare_input(
|
|
17
|
-
|
|
16
|
+
def prepare_input(
|
|
17
|
+
self, geo: CompoundGeometry, strain: ArrayLike, integrate: str
|
|
18
|
+
):
|
|
19
|
+
"""Prepare general input to the stress integration method.
|
|
18
20
|
|
|
19
21
|
Args:
|
|
20
22
|
geo (CompoundGeometry): The geometry to integrate over.
|
|
21
23
|
strain (ArrayLike): The scalar strain components necessary for
|
|
22
24
|
describing the assumed strain distribution over the geometry.
|
|
25
|
+
integrate (str): The integrand, i.e., the quantity to be integrated
|
|
26
|
+
over the section.
|
|
23
27
|
"""
|
|
24
28
|
raise NotImplementedError
|
|
25
29
|
|
|
26
30
|
@abc.abstractmethod
|
|
27
|
-
def
|
|
31
|
+
def integrate_stress(self, *prepared_input, **kwargs):
|
|
28
32
|
"""Integrate stresses over the geometry.
|
|
29
33
|
|
|
30
34
|
The input to this method is generated by the prepare_input method. It
|
|
@@ -39,9 +43,29 @@ class SectionIntegrator(abc.ABC):
|
|
|
39
43
|
"""
|
|
40
44
|
raise NotImplementedError
|
|
41
45
|
|
|
46
|
+
@abc.abstractmethod
|
|
47
|
+
def integrate_modulus(self, *prepared_input, **kwargs):
|
|
48
|
+
"""Integrate material modulus over the geometry.
|
|
49
|
+
|
|
50
|
+
The input to this method is generated by the prepare_input method. It
|
|
51
|
+
also takes kwargs depending on the concrete implementation.
|
|
52
|
+
|
|
53
|
+
Arguments:
|
|
54
|
+
*prepared_input: The input prepared by the prepare_input method.
|
|
55
|
+
|
|
56
|
+
Keyword Arguments:
|
|
57
|
+
**kwargs: Keyword arguments depending on the concrete
|
|
58
|
+
implementation.
|
|
59
|
+
"""
|
|
60
|
+
raise NotImplementedError
|
|
61
|
+
|
|
42
62
|
@abc.abstractmethod
|
|
43
63
|
def integrate_strain_response_on_geometry(
|
|
44
|
-
self,
|
|
64
|
+
self,
|
|
65
|
+
geo: CompoundGeometry,
|
|
66
|
+
strain: ArrayLike,
|
|
67
|
+
integrate: str,
|
|
68
|
+
**kwargs,
|
|
45
69
|
):
|
|
46
70
|
"""Integrate stresses over the geometry to obtain the response due to
|
|
47
71
|
strains.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: structuralcodes
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: A Python package that contains models from structural design codes.
|
|
5
5
|
Author-email: fib - International Federation for Structural Concrete <info@fib-international.org>
|
|
6
6
|
Requires-Python: >=3.8
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
structuralcodes/__init__.py,sha256=
|
|
1
|
+
structuralcodes/__init__.py,sha256=KmmtACP7x6UA9QFVuSMxm22R39LlSE8AbhjRvA5Xirc,390
|
|
2
2
|
structuralcodes/codes/__init__.py,sha256=g5xMAJ3jEZHFd0cypvZY6lMCi7XeVEntsO8zHzI2mWc,2803
|
|
3
3
|
structuralcodes/codes/ec2_2004/__init__.py,sha256=DljXFNrCGE1lZIOsgyZgJ7Xo-xUidJomDrDKyfOHcH8,2431
|
|
4
|
-
structuralcodes/codes/ec2_2004/_concrete_creep_and_shrinkage.py,sha256=
|
|
4
|
+
structuralcodes/codes/ec2_2004/_concrete_creep_and_shrinkage.py,sha256=Vbxxc3g0WZz2qFWDlfrVvC-uxMO2YJpfclnHxRPMuYQ,15301
|
|
5
5
|
structuralcodes/codes/ec2_2004/_concrete_material_properties.py,sha256=Ol51tzcVOHUvc2Vea24WQJ4FABxXc-9cB5RVu2N1pio,5964
|
|
6
6
|
structuralcodes/codes/ec2_2004/_reinforcement_material_properties.py,sha256=_ZlvdHcOswu1Ge1XjSvt4j5ue-znDceMOlA0s528IqM,2779
|
|
7
7
|
structuralcodes/codes/ec2_2004/_section_7_3_crack_control.py,sha256=a91tWQKNTxB2SpSKu0Wtm-P5GdmifRLggNlEHIQ3XMY,31981
|
|
@@ -11,7 +11,7 @@ structuralcodes/codes/ec2_2023/_annexB_time_dependent.py,sha256=ykRAHBHzqtMSErkV
|
|
|
11
11
|
structuralcodes/codes/ec2_2023/_section5_materials.py,sha256=-vYowBVcebyPyuGvX3wLfxiePdM0OrBgRrYil71Vd88,32384
|
|
12
12
|
structuralcodes/codes/ec2_2023/_section9_sls.py,sha256=l1d3xcALAweU9jAAf1d91TJaGB_0p-eMzbRGuhfKydQ,11252
|
|
13
13
|
structuralcodes/codes/mc2010/__init__.py,sha256=g2J2GTIy9jbLTVq_yF4DXau4WLmAkpmMTgnD4QmW2vI,2844
|
|
14
|
-
structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py,sha256=
|
|
14
|
+
structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py,sha256=lQAj8n0TVhRvttVFF9YLVNzCRo3O3wIqWvBdZRu9vDk,24295
|
|
15
15
|
structuralcodes/codes/mc2010/_concrete_interface_different_casting_times.py,sha256=x_n9Z9WEPY6DFf8Og5UIERPivNh-O_3RM4ZnGBy64cs,3570
|
|
16
16
|
structuralcodes/codes/mc2010/_concrete_material_properties.py,sha256=MTz70-9iaN_s0Z8gJksCEzP0Yza4pPfZ-vOI30pzbw4,12362
|
|
17
17
|
structuralcodes/codes/mc2010/_concrete_punching.py,sha256=ZG2P7WXIRcFh5sGlmHP20BsJbz0o44cFO51FCru2kXw,17431
|
|
@@ -20,11 +20,13 @@ structuralcodes/codes/mc2010/_concrete_torsion.py,sha256=QBFnCYTOnP6FjN0MgX9iBrX
|
|
|
20
20
|
structuralcodes/codes/mc2010/_reinforcement_material_properties.py,sha256=FELmgMcCrHlajGwQNRRHb8nqKnMCsLso1OyjonsTAdk,2842
|
|
21
21
|
structuralcodes/codes/mc2020/__init__.py,sha256=5hrAfBtAeG69N_lroFpG10_ZKB1SuNlKBnuHug2DI3E,174
|
|
22
22
|
structuralcodes/core/__init__.py,sha256=spnvZIm_w3jX_lV-v3bloDjgHh8lrH6UHpA1Nv1zeAI,55
|
|
23
|
-
structuralcodes/core/_section_results.py,sha256=
|
|
24
|
-
structuralcodes/core/base.py,sha256=
|
|
25
|
-
structuralcodes/geometry/__init__.py,sha256=
|
|
26
|
-
structuralcodes/geometry/
|
|
27
|
-
structuralcodes/geometry/
|
|
23
|
+
structuralcodes/core/_section_results.py,sha256=MzUGThcxmZvyp0UBwxEiUAx2qz49UTlIo7MqoPEy3xk,7968
|
|
24
|
+
structuralcodes/core/base.py,sha256=l8CgvUyz034F5HRyx6fBpiZvVRnD3cBDqJOTeuEV2hY,9505
|
|
25
|
+
structuralcodes/geometry/__init__.py,sha256=STc2chf49NkWlnpcfB8n4mYWmR633VsKtbfyG8ylQ7s,771
|
|
26
|
+
structuralcodes/geometry/_circular.py,sha256=vYk5mBY0bh_qqX_RrXn_NTE2iwPBvC-Uku3_AJEIZgQ,3557
|
|
27
|
+
structuralcodes/geometry/_geometry.py,sha256=HE2pJaUdjgeFWp7WNA9Rm1Bt7QI6_Bjn-ePt6aO7AcY,31544
|
|
28
|
+
structuralcodes/geometry/_rectangular.py,sha256=PLKgz998qDjcn76JjVW08fexN0jAke0K6yNeaOynqOQ,3458
|
|
29
|
+
structuralcodes/geometry/_reinforcement.py,sha256=2l4I2tm5YEy9Oeqlzt1GulljSW0k5_4_iG6quvhlSRk,9097
|
|
28
30
|
structuralcodes/geometry/_steel_sections.py,sha256=UdJmhhnK8r5gEfBzvWsMFHGs5gmuoOhFoduBanlRMQg,60225
|
|
29
31
|
structuralcodes/materials/__init__.py,sha256=r5E5vsXVKB-BGZXTnEbsrYJbH6rr6Xlc_b4LlcUPIbc,173
|
|
30
32
|
structuralcodes/materials/concrete/__init__.py,sha256=GRD5WcbYrnE4iN-L7qVkhVTi7w_PUP7pnbGueOaVeFs,2576
|
|
@@ -33,26 +35,27 @@ structuralcodes/materials/concrete/_concreteEC2_2004.py,sha256=gWG3O9yeGw3UeftCj
|
|
|
33
35
|
structuralcodes/materials/concrete/_concreteEC2_2023.py,sha256=vguNzlfoPuaieTVw9T3xWU0wb230WvER4Vy1jswcdlo,14017
|
|
34
36
|
structuralcodes/materials/concrete/_concreteMC2010.py,sha256=lHy-WYiVpXPwiNAyjUBxuGWuGFd0-Uirh6KiolMH4MY,15313
|
|
35
37
|
structuralcodes/materials/constitutive_laws/__init__.py,sha256=r817qyeimqZyyan2mU8cVwjwMkiB--f-BOIBSzXKiZo,2954
|
|
36
|
-
structuralcodes/materials/constitutive_laws/_bilinearcompression.py,sha256=
|
|
37
|
-
structuralcodes/materials/constitutive_laws/_elastic.py,sha256=
|
|
38
|
-
structuralcodes/materials/constitutive_laws/_elasticplastic.py,sha256=
|
|
39
|
-
structuralcodes/materials/constitutive_laws/_parabolarectangle.py,sha256=
|
|
38
|
+
structuralcodes/materials/constitutive_laws/_bilinearcompression.py,sha256=wap9cPSj4baeAZ4dqSfajWb5wdidkpkcT2pgb2QHrBk,6083
|
|
39
|
+
structuralcodes/materials/constitutive_laws/_elastic.py,sha256=xxSneoCW41AQy0vj3_x-sTuvE_SsS1kutaG_NbqAWbk,4306
|
|
40
|
+
structuralcodes/materials/constitutive_laws/_elasticplastic.py,sha256=VXA4wgkfL8NdGnZa7AQX_TL-JCpEBjMVumIwQhhloFY,8118
|
|
41
|
+
structuralcodes/materials/constitutive_laws/_parabolarectangle.py,sha256=9GeY0HuFE5l9L61OoKi-M5MgQemJpcKccysN0SQ0oXM,8609
|
|
40
42
|
structuralcodes/materials/constitutive_laws/_popovics.py,sha256=dpXFQ9KHE245C9dgOLz9KXYHZiAYrRan5exgj0j_JxM,4322
|
|
41
43
|
structuralcodes/materials/constitutive_laws/_sargin.py,sha256=WJGw0EtqkPh-d3N6vTPRIfhE1Ypyc16JpGcoi-0U1A8,3495
|
|
42
|
-
structuralcodes/materials/constitutive_laws/_userdefined.py,sha256=
|
|
44
|
+
structuralcodes/materials/constitutive_laws/_userdefined.py,sha256=vr01SyZTQvDimJLJN3-shvhIevvt9_qRtiy8OjodKQQ,9925
|
|
43
45
|
structuralcodes/materials/reinforcement/__init__.py,sha256=-UA04GSNN6_xLKqnH_5taiOmgxYwD_wtT6Nw8UbfkJY,2757
|
|
44
46
|
structuralcodes/materials/reinforcement/_reinforcement.py,sha256=zrSdBvHKTYqOHpkJzxit8w_b2JG2pggviOvgZyH246Q,5029
|
|
45
47
|
structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py,sha256=svLpubjaTH_DepwY68TQIA8fRwadoAE3Y3KsyViGQHk,3265
|
|
46
48
|
structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py,sha256=3tKpFcMNYK52s5K2K_PctRcuSgwZTe-QXX3xziHPUno,2887
|
|
47
49
|
structuralcodes/materials/reinforcement/_reinforcementMC2010.py,sha256=az_IAQJNKSF6Vv9KMoXjWTdYkWI6xcEm7s8i8GETn3A,2939
|
|
48
|
-
structuralcodes/sections/__init__.py,sha256=
|
|
49
|
-
structuralcodes/sections/_generic.py,sha256=
|
|
50
|
+
structuralcodes/sections/__init__.py,sha256=gUGqiv8zyhiMmxEFme8E9nC2b3aJKs3ieBYz6X2GVFY,545
|
|
51
|
+
structuralcodes/sections/_generic.py,sha256=ZsqOOTQJwj1VtXbpcxao1y21qK16QGq7xZ0jOwBsRcU,55744
|
|
52
|
+
structuralcodes/sections/_rc_utils.py,sha256=KZGVyQNSsbol7Dcyx7StoN1ybzrXMeKlyIFdXAauJW0,4229
|
|
50
53
|
structuralcodes/sections/section_integrators/__init__.py,sha256=PK4ixV0XrfHXN-itIrB1r90npoWo3aIJqMcenqcaees,399
|
|
51
54
|
structuralcodes/sections/section_integrators/_factory.py,sha256=MHp14hfWU-oXTiIutCKLJEC47LirYsHgEAAmHVtnFMY,1242
|
|
52
|
-
structuralcodes/sections/section_integrators/_fiber_integrator.py,sha256=
|
|
55
|
+
structuralcodes/sections/section_integrators/_fiber_integrator.py,sha256=7On87ESqRDorV4YdaOTq9h55XaJFC5h6mMN4ys6DYos,12873
|
|
53
56
|
structuralcodes/sections/section_integrators/_marin_integration.py,sha256=SZgya6d_Tequ3jez7UEBlYioZepW2IDKaAxn_6WrMbU,1563
|
|
54
|
-
structuralcodes/sections/section_integrators/_marin_integrator.py,sha256=
|
|
55
|
-
structuralcodes/sections/section_integrators/_section_integrator.py,sha256=
|
|
56
|
-
structuralcodes-0.
|
|
57
|
-
structuralcodes-0.
|
|
58
|
-
structuralcodes-0.
|
|
57
|
+
structuralcodes/sections/section_integrators/_marin_integrator.py,sha256=wdgscIWTIRfkPPafI77Lk4-FmtQLDNw2kanMkhNkfTc,15392
|
|
58
|
+
structuralcodes/sections/section_integrators/_section_integrator.py,sha256=aPYuUpqeQLYauVi3_uJoEtXPSuXn79Aau3GTlISn-sI,2355
|
|
59
|
+
structuralcodes-0.3.1.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
|
|
60
|
+
structuralcodes-0.3.1.dist-info/METADATA,sha256=G539Pjz7ht10TNndNfxWOJUh0_YZg1Rbpc3_d2o8k18,2444
|
|
61
|
+
structuralcodes-0.3.1.dist-info/RECORD,,
|