structuralcodes 0.0.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 +17 -0
- structuralcodes/codes/__init__.py +79 -0
- structuralcodes/codes/ec2_2004/__init__.py +133 -0
- structuralcodes/codes/ec2_2004/_concrete_material_properties.py +239 -0
- structuralcodes/codes/ec2_2004/_reinforcement_material_properties.py +104 -0
- structuralcodes/codes/ec2_2004/_section_7_3_crack_control.py +941 -0
- structuralcodes/codes/ec2_2004/annex_b_shrink_and_creep.py +257 -0
- structuralcodes/codes/ec2_2004/shear.py +506 -0
- structuralcodes/codes/ec2_2023/__init__.py +104 -0
- structuralcodes/codes/ec2_2023/_annexB_time_dependent.py +17 -0
- structuralcodes/codes/ec2_2023/_section5_materials.py +1160 -0
- structuralcodes/codes/ec2_2023/_section9_sls.py +325 -0
- structuralcodes/codes/mc2010/__init__.py +169 -0
- structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py +704 -0
- structuralcodes/codes/mc2010/_concrete_interface_different_casting_times.py +104 -0
- structuralcodes/codes/mc2010/_concrete_material_properties.py +463 -0
- structuralcodes/codes/mc2010/_concrete_punching.py +543 -0
- structuralcodes/codes/mc2010/_concrete_shear.py +749 -0
- structuralcodes/codes/mc2010/_concrete_torsion.py +164 -0
- structuralcodes/codes/mc2010/_reinforcement_material_properties.py +105 -0
- structuralcodes/core/__init__.py +1 -0
- structuralcodes/core/_section_results.py +211 -0
- structuralcodes/core/base.py +260 -0
- structuralcodes/geometry/__init__.py +25 -0
- structuralcodes/geometry/_geometry.py +875 -0
- structuralcodes/geometry/_steel_sections.py +2155 -0
- structuralcodes/materials/__init__.py +9 -0
- structuralcodes/materials/concrete/__init__.py +82 -0
- structuralcodes/materials/concrete/_concrete.py +114 -0
- structuralcodes/materials/concrete/_concreteEC2_2004.py +477 -0
- structuralcodes/materials/concrete/_concreteEC2_2023.py +435 -0
- structuralcodes/materials/concrete/_concreteMC2010.py +494 -0
- structuralcodes/materials/constitutive_laws.py +979 -0
- structuralcodes/materials/reinforcement/__init__.py +84 -0
- structuralcodes/materials/reinforcement/_reinforcement.py +172 -0
- structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py +103 -0
- structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py +93 -0
- structuralcodes/materials/reinforcement/_reinforcementMC2010.py +98 -0
- structuralcodes/sections/__init__.py +23 -0
- structuralcodes/sections/_generic.py +1249 -0
- structuralcodes/sections/_reinforcement.py +115 -0
- structuralcodes/sections/section_integrators/__init__.py +14 -0
- structuralcodes/sections/section_integrators/_factory.py +41 -0
- structuralcodes/sections/section_integrators/_fiber_integrator.py +238 -0
- structuralcodes/sections/section_integrators/_marin_integration.py +47 -0
- structuralcodes/sections/section_integrators/_marin_integrator.py +222 -0
- structuralcodes/sections/section_integrators/_section_integrator.py +49 -0
- structuralcodes-0.0.1.dist-info/METADATA +40 -0
- structuralcodes-0.0.1.dist-info/RECORD +50 -0
- structuralcodes-0.0.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,1160 @@
|
|
|
1
|
+
"""Functions from Section 5 of EN 1992-1-1:2023."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import typing as t
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import scipy.interpolate
|
|
8
|
+
|
|
9
|
+
from structuralcodes.codes import mc2010
|
|
10
|
+
|
|
11
|
+
VALID_STRENGTH_DEV_CLASSES = ('CS', 'CN', 'CR', 'SLOW', 'NORMAL', 'RAPID')
|
|
12
|
+
|
|
13
|
+
DUCTILITY_CLASSES = {
|
|
14
|
+
'A': {
|
|
15
|
+
'epsuk': 2.5e-2,
|
|
16
|
+
'k': 1.05,
|
|
17
|
+
},
|
|
18
|
+
'B': {
|
|
19
|
+
'epsuk': 5.0e-2,
|
|
20
|
+
'k': 1.08,
|
|
21
|
+
},
|
|
22
|
+
'C': {
|
|
23
|
+
'epsuk': 7.5e-2,
|
|
24
|
+
'k': 1.15,
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def fcm(fck: float, delta_f: float = 8.0) -> float:
|
|
30
|
+
"""Determines the mean strength of concrete from its characteristic value.
|
|
31
|
+
|
|
32
|
+
EN 1992-1-1:2023, Table 5.1.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
fck (float): Is the characteristic compressive strength in MPa.
|
|
36
|
+
|
|
37
|
+
Keyword Args:
|
|
38
|
+
delta_s (float): The increment in MPa to compute the mean compressive
|
|
39
|
+
strength.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
float: The mean compressive strength in MPa
|
|
43
|
+
"""
|
|
44
|
+
return mc2010.fcm(fck, delta_f)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def fctm(fck: float) -> float:
|
|
48
|
+
"""Compute the mean concrete tensile strength from the characteristic
|
|
49
|
+
compressive strength.
|
|
50
|
+
|
|
51
|
+
EN 1992-1-1:2023, Table 5.1.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
fck (float): The characteristic compressive strength in MPa.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
float: The mean tensile strength in MPa.
|
|
58
|
+
"""
|
|
59
|
+
if abs(fck) <= 50:
|
|
60
|
+
return 0.3 * math.pow(abs(fck), 2 / 3)
|
|
61
|
+
return 1.1 * math.pow(abs(fck), 1 / 3)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def fctk_5(fctm: float) -> float:
|
|
65
|
+
"""Compute the 5% mean concrete tensile strength fractile.
|
|
66
|
+
|
|
67
|
+
EN 1992-1-1:2023, Table 5.1.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
fctm (float): The mean concrete tensile strength in MPa.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
float: The 5% mean concrete tensile strength fractile in MPa.
|
|
74
|
+
"""
|
|
75
|
+
return abs(fctm) * 0.7
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def fctk_95(fctm: float) -> float:
|
|
79
|
+
"""Compute the 95% mean concrete tensile strength fractile.
|
|
80
|
+
|
|
81
|
+
EN 1992-1-1:2023, Table 5.1.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
fctm (float): The mean concrete tensile strength in MPa.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
float: The 5% mean concrete tensile strength fractile in MPa.
|
|
88
|
+
"""
|
|
89
|
+
return abs(fctm) * 1.3
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def Ecm(fcm: float, kE: float = 9500) -> float:
|
|
93
|
+
"""Computes the secant modulus between sigma_c=0 and sigma_c=0.4*fcm.
|
|
94
|
+
|
|
95
|
+
EN 1992-1-1:2023, Eq. (5.1).
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
fcm (float): The mean compressive strength in MPa.
|
|
99
|
+
|
|
100
|
+
Keyword Args:
|
|
101
|
+
kE (float): Coefficient relating the aggregates used in concrete.
|
|
102
|
+
Default value is 9500, but it can vary from 5000 to 13000.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
float: The secant concrete modulus in MPa.
|
|
106
|
+
|
|
107
|
+
Raises:
|
|
108
|
+
ValueError: If fcm is less than 0.
|
|
109
|
+
ValueError: If kE is not between 5000 and 13000.
|
|
110
|
+
"""
|
|
111
|
+
if fcm < 0:
|
|
112
|
+
raise ValueError(f'fcm={fcm} cannot be less than 0')
|
|
113
|
+
if kE < 5000:
|
|
114
|
+
raise ValueError(f'kE={kE} cannot be less than 5000')
|
|
115
|
+
if kE > 13000:
|
|
116
|
+
raise ValueError(f'kE={kE} cannot be larger than 13000')
|
|
117
|
+
|
|
118
|
+
return kE * math.pow(fcm, 1 / 3)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def hn(Ac: float, u: float) -> float:
|
|
122
|
+
"""Computes the notional size of a given concrete cross-section.
|
|
123
|
+
|
|
124
|
+
EN 1992-1-1:2023, Table 5.2.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
Ac (float): The concrete cross-sectional area in (mm2).
|
|
128
|
+
u (float): The perimeter exposed to drying (mm).
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
float: The notional size (mm).
|
|
132
|
+
|
|
133
|
+
Raises:
|
|
134
|
+
ValueError: If Ac is less than 0.
|
|
135
|
+
ValueError: If u is less than 0.
|
|
136
|
+
"""
|
|
137
|
+
if Ac < 0:
|
|
138
|
+
raise ValueError(f'Ac={Ac} cannot be less than 0')
|
|
139
|
+
if u < 0:
|
|
140
|
+
raise ValueError(f'u={u} cannot be less than 0')
|
|
141
|
+
|
|
142
|
+
return 2 * Ac / u
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def A_phi_correction_exp(
|
|
146
|
+
hn: float, atm_conditions: t.Literal['dry', 'humid']
|
|
147
|
+
) -> float:
|
|
148
|
+
"""Computes the correction exponent for the modification for the phi_50y_t0
|
|
149
|
+
with respect the fck value.
|
|
150
|
+
|
|
151
|
+
EN 1992-1-1:2023, Table 5.2.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
hn (float): The notional size in mm.
|
|
155
|
+
atm_conditions (str): 'dry' or 'humid'.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
float: The correction exponent value.
|
|
159
|
+
|
|
160
|
+
Raises:
|
|
161
|
+
ValueError: If hn is less than 100 or greater than 1000.
|
|
162
|
+
ValueError: If atm_conditions is not 'dry' or 'humid'.
|
|
163
|
+
"""
|
|
164
|
+
if hn < 100:
|
|
165
|
+
raise ValueError(f'hn={hn} cannot be less than 100')
|
|
166
|
+
if hn > 1000:
|
|
167
|
+
raise ValueError(f'hn={hn} cannot be larger than 1000')
|
|
168
|
+
|
|
169
|
+
atm_conditions = atm_conditions.lower().strip()
|
|
170
|
+
x = (100, 200, 500, 1000)
|
|
171
|
+
if atm_conditions == 'dry':
|
|
172
|
+
y = (0.82, 0.79, 0.75, 0.72)
|
|
173
|
+
elif atm_conditions == 'humid':
|
|
174
|
+
y = (0.71, 0.68, 0.66, 0.64)
|
|
175
|
+
else:
|
|
176
|
+
raise ValueError(
|
|
177
|
+
f'atm_conditions={atm_conditions} can only take '
|
|
178
|
+
+ '"dry" and "humid" as values'
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
interpol = scipy.interpolate.interp1d(x, y)
|
|
182
|
+
return interpol(hn)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def phi_correction_factor(fck: float, A_exponent: float) -> float:
|
|
186
|
+
"""Computes the correction factor for the computation of the phi_50y_t0.
|
|
187
|
+
|
|
188
|
+
EN 1992-1-1:2023, Table 5.2.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
fck (float): Characteristic strength of concrete in MPa.
|
|
192
|
+
A_exponent (float): The A correction exponent value.
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
float: The correction factor value.
|
|
196
|
+
|
|
197
|
+
Raises:
|
|
198
|
+
ValueError: If fck is not between 12 and 100 MPa.
|
|
199
|
+
ValueError: If A_exponent is not between 0.64 and 0.82.
|
|
200
|
+
"""
|
|
201
|
+
if fck < 12:
|
|
202
|
+
raise ValueError(f'fck={fck} cannot be less than 12')
|
|
203
|
+
if fck > 100:
|
|
204
|
+
raise ValueError(f'fck={fck} cannot be larger than 100')
|
|
205
|
+
if A_exponent < 0.64:
|
|
206
|
+
raise ValueError(f'A_exponent={A_exponent} cannot be less than 0.64')
|
|
207
|
+
if A_exponent > 0.82:
|
|
208
|
+
raise ValueError(f'A_exponent={A_exponent} cannot be less than 0.82')
|
|
209
|
+
|
|
210
|
+
return math.pow(35 / fck, A_exponent)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def phi_50y_t0(
|
|
214
|
+
t0: float,
|
|
215
|
+
atm_conditions: t.Literal['dry', 'humid'],
|
|
216
|
+
hn: float,
|
|
217
|
+
strength_dev_class: t.Literal['CS', 'CN', 'CR', 'slow', 'normal', 'rapid'],
|
|
218
|
+
) -> float:
|
|
219
|
+
"""Computes the creep coefficient of plain concrete at 50 years of loading.
|
|
220
|
+
Interpolation is linear between values.
|
|
221
|
+
|
|
222
|
+
EN 1992-1-1:2023, Table 5.2.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
t0 (float): Age at loading [days].
|
|
226
|
+
atm_conditions (str): 'dry' or 'humid'.
|
|
227
|
+
hn (float): The notional size in mm.
|
|
228
|
+
strength_dev_class (str): Strength development class 'CS', 'CN', 'CR',
|
|
229
|
+
'slow', 'normal' or 'rapid'.
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
float: The creep coefficient.
|
|
233
|
+
|
|
234
|
+
Raises:
|
|
235
|
+
ValueError: If t0 is less than 1.
|
|
236
|
+
ValueError: If atm_conditions is not 'dry' or 'humid'.
|
|
237
|
+
ValueError: If hn is less than 100 or larger than 1000.
|
|
238
|
+
ValueError: If strength_dev_class is not 'CS', 'CN',
|
|
239
|
+
'CR', 'slow', 'normal' or 'rapid'.
|
|
240
|
+
ValueError: If combination of t0 and hn is out of scope.
|
|
241
|
+
"""
|
|
242
|
+
if t0 < 1:
|
|
243
|
+
raise ValueError(f't0={t0} cannot be less than 1')
|
|
244
|
+
|
|
245
|
+
atm_conditions = atm_conditions.lower().strip()
|
|
246
|
+
if atm_conditions not in ('dry', 'humid'):
|
|
247
|
+
raise ValueError(
|
|
248
|
+
f'atm_conditions={atm_conditions} must be "dry" or "humid"'
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
if hn < 100:
|
|
252
|
+
raise ValueError(f'hn={hn} must be larger or equal than 100')
|
|
253
|
+
if hn > 1000:
|
|
254
|
+
raise ValueError(f'hn={hn} must be less or equal than 1000')
|
|
255
|
+
|
|
256
|
+
strength_dev_class = strength_dev_class.upper().strip()
|
|
257
|
+
if strength_dev_class not in VALID_STRENGTH_DEV_CLASSES:
|
|
258
|
+
raise ValueError(
|
|
259
|
+
f'strength_dev_class={strength_dev_class} must be'
|
|
260
|
+
+ '"CS", "CN", "CR", "slow", "normal" or "rapid"'
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
if strength_dev_class in ('CS', 'SLOW'):
|
|
264
|
+
_t = (3, 10, 32, 91, 365)
|
|
265
|
+
elif strength_dev_class in ('CN', 'NORMAL'):
|
|
266
|
+
_t = (1, 7, 28, 91, 365)
|
|
267
|
+
elif strength_dev_class in ('CR', 'RAPID'):
|
|
268
|
+
_t = (1, 3, 23, 91, 365)
|
|
269
|
+
|
|
270
|
+
h_v = (100, 200, 500, 1000)
|
|
271
|
+
|
|
272
|
+
if atm_conditions == 'dry':
|
|
273
|
+
values = (
|
|
274
|
+
4.2,
|
|
275
|
+
3.8,
|
|
276
|
+
3.4,
|
|
277
|
+
3.1,
|
|
278
|
+
3.1,
|
|
279
|
+
2.8,
|
|
280
|
+
2.5,
|
|
281
|
+
2.3,
|
|
282
|
+
2.4,
|
|
283
|
+
2.2,
|
|
284
|
+
1.9,
|
|
285
|
+
1.8,
|
|
286
|
+
1.9,
|
|
287
|
+
1.7,
|
|
288
|
+
1.5,
|
|
289
|
+
1.4,
|
|
290
|
+
1.4,
|
|
291
|
+
1.3,
|
|
292
|
+
1.1,
|
|
293
|
+
1.0,
|
|
294
|
+
)
|
|
295
|
+
elif atm_conditions == 'humid':
|
|
296
|
+
values = (
|
|
297
|
+
3.0,
|
|
298
|
+
2.8,
|
|
299
|
+
2.6,
|
|
300
|
+
2.5,
|
|
301
|
+
2.2,
|
|
302
|
+
2.1,
|
|
303
|
+
2.0,
|
|
304
|
+
1.9,
|
|
305
|
+
1.7,
|
|
306
|
+
1.6,
|
|
307
|
+
1.6,
|
|
308
|
+
1.5,
|
|
309
|
+
1.4,
|
|
310
|
+
1.3,
|
|
311
|
+
1.2,
|
|
312
|
+
1.2,
|
|
313
|
+
1.0,
|
|
314
|
+
0.9,
|
|
315
|
+
0.9,
|
|
316
|
+
0.8,
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
grid = np.array(np.meshgrid(_t, h_v)).T.reshape(-1, 2)
|
|
320
|
+
p = (t0, hn)
|
|
321
|
+
|
|
322
|
+
interp = scipy.interpolate.griddata(grid, values, p, method='linear')
|
|
323
|
+
_phi_50y_t0 = float(interp)
|
|
324
|
+
|
|
325
|
+
if math.isnan(_phi_50y_t0) or math.isnan(_phi_50y_t0):
|
|
326
|
+
raise ValueError('Combination of t0, hn out of scope')
|
|
327
|
+
|
|
328
|
+
return _phi_50y_t0
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def eps_cs_50y( # noqa: PLR0912
|
|
332
|
+
fck_28: float,
|
|
333
|
+
atm_conditions: t.Literal['dry', 'humid'],
|
|
334
|
+
hn: float,
|
|
335
|
+
strength_dev_class: t.Literal['CS', 'CN', 'CR', 'slow', 'normal', 'rapid'],
|
|
336
|
+
) -> float:
|
|
337
|
+
"""Computes the nominal total shrinkage in ‰ for concrete after a duration
|
|
338
|
+
of drying of 50 years.
|
|
339
|
+
|
|
340
|
+
EN 1992-1-1:2023, Table 5.3.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
fck_28 (float): Characteristic strength at 28 days in MPa
|
|
344
|
+
atm_conditions (str): 'dry' or 'humid'.
|
|
345
|
+
hn (float): The notional size in mm.
|
|
346
|
+
strength_dev_class (str): Strength development class 'CS', 'CN', 'CR',
|
|
347
|
+
'slow', 'normal' or 'rapid'.
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
float: The nominal shrinkage value in percent.
|
|
351
|
+
|
|
352
|
+
Raises:
|
|
353
|
+
ValueError: If fck_28 is less than 20 MPa or larger than 80 MPa.
|
|
354
|
+
ValueError: If atm_conditions is not 'dry' or 'humid'.
|
|
355
|
+
ValueError: If hn is less than 100 or larger than 1000.
|
|
356
|
+
ValueError: If strength_dev_class is not CS', 'CN', 'CR',
|
|
357
|
+
'slow', 'normal' or 'rapid'.
|
|
358
|
+
ValueError: If combination of fck_28 and hn is out of scope.
|
|
359
|
+
"""
|
|
360
|
+
if fck_28 < 20:
|
|
361
|
+
raise ValueError(f'fck_28={fck_28} cannot be less than 20')
|
|
362
|
+
if fck_28 > 80:
|
|
363
|
+
raise ValueError(f'fck_28={fck_28} cannot be larger than 80')
|
|
364
|
+
|
|
365
|
+
atm_conditions = atm_conditions.lower().strip()
|
|
366
|
+
if atm_conditions not in ('dry', 'humid'):
|
|
367
|
+
raise ValueError(
|
|
368
|
+
f'atm_conditions={atm_conditions} must be "dry" or "humid"'
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
if hn < 100:
|
|
372
|
+
raise ValueError(f'hn={hn} must be larger or equal than 100')
|
|
373
|
+
if hn > 1000:
|
|
374
|
+
raise ValueError(f'hn={hn} must be less or equal than 1000')
|
|
375
|
+
|
|
376
|
+
strength_dev_class = strength_dev_class.upper().strip()
|
|
377
|
+
if strength_dev_class == 'SLOW':
|
|
378
|
+
strength_dev_class = 'CS'
|
|
379
|
+
elif strength_dev_class == 'NORMAL':
|
|
380
|
+
strength_dev_class = 'CN'
|
|
381
|
+
elif strength_dev_class == 'RAPID':
|
|
382
|
+
strength_dev_class = 'CR'
|
|
383
|
+
|
|
384
|
+
if strength_dev_class == 'CS':
|
|
385
|
+
fck_v = (20, 35, 50)
|
|
386
|
+
elif strength_dev_class == 'CN':
|
|
387
|
+
fck_v = (20, 35, 50, 80)
|
|
388
|
+
elif strength_dev_class == 'CR':
|
|
389
|
+
fck_v = (35, 50, 80)
|
|
390
|
+
else:
|
|
391
|
+
raise ValueError(
|
|
392
|
+
f'strength_dev_class={strength_dev_class} '
|
|
393
|
+
+ 'must be "CS", "CN", "CR", "slow", "normal" or "rapid"'
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
h_v = (100, 200, 500, 1000)
|
|
397
|
+
|
|
398
|
+
data = {
|
|
399
|
+
'dry': {
|
|
400
|
+
'CS': (
|
|
401
|
+
0.57,
|
|
402
|
+
0.56,
|
|
403
|
+
0.48,
|
|
404
|
+
0.36,
|
|
405
|
+
0.53,
|
|
406
|
+
0.51,
|
|
407
|
+
0.45,
|
|
408
|
+
0.35,
|
|
409
|
+
0.49,
|
|
410
|
+
0.48,
|
|
411
|
+
0.43,
|
|
412
|
+
0.35,
|
|
413
|
+
),
|
|
414
|
+
'CN': (
|
|
415
|
+
0.67,
|
|
416
|
+
0.65,
|
|
417
|
+
0.56,
|
|
418
|
+
0.41,
|
|
419
|
+
0.60,
|
|
420
|
+
0.59,
|
|
421
|
+
0.51,
|
|
422
|
+
0.39,
|
|
423
|
+
0.55,
|
|
424
|
+
0.54,
|
|
425
|
+
0.48,
|
|
426
|
+
0.37,
|
|
427
|
+
0.48,
|
|
428
|
+
0.48,
|
|
429
|
+
0.43,
|
|
430
|
+
0.36,
|
|
431
|
+
),
|
|
432
|
+
'CR': (
|
|
433
|
+
0.76,
|
|
434
|
+
0.74,
|
|
435
|
+
0.65,
|
|
436
|
+
0.48,
|
|
437
|
+
0.67,
|
|
438
|
+
0.66,
|
|
439
|
+
0.58,
|
|
440
|
+
0.44,
|
|
441
|
+
0.55,
|
|
442
|
+
0.54,
|
|
443
|
+
0.49,
|
|
444
|
+
0.39,
|
|
445
|
+
),
|
|
446
|
+
},
|
|
447
|
+
'humid': {
|
|
448
|
+
'CS': (
|
|
449
|
+
0.33,
|
|
450
|
+
0.32,
|
|
451
|
+
0.28,
|
|
452
|
+
0.21,
|
|
453
|
+
0.31,
|
|
454
|
+
0.31,
|
|
455
|
+
0.27,
|
|
456
|
+
0.22,
|
|
457
|
+
0.30,
|
|
458
|
+
0.29,
|
|
459
|
+
0.27,
|
|
460
|
+
0.23,
|
|
461
|
+
),
|
|
462
|
+
'CN': (
|
|
463
|
+
0.38,
|
|
464
|
+
0.37,
|
|
465
|
+
0.32,
|
|
466
|
+
0.24,
|
|
467
|
+
0.34,
|
|
468
|
+
0.34,
|
|
469
|
+
0.30,
|
|
470
|
+
0.24,
|
|
471
|
+
0.31,
|
|
472
|
+
0.31,
|
|
473
|
+
0.28,
|
|
474
|
+
0.23,
|
|
475
|
+
0.30,
|
|
476
|
+
0.30,
|
|
477
|
+
0.28,
|
|
478
|
+
0.25,
|
|
479
|
+
),
|
|
480
|
+
'CR': (
|
|
481
|
+
0.42,
|
|
482
|
+
0.41,
|
|
483
|
+
0.36,
|
|
484
|
+
0.28,
|
|
485
|
+
0.36,
|
|
486
|
+
0.35,
|
|
487
|
+
0.32,
|
|
488
|
+
0.26,
|
|
489
|
+
0.31,
|
|
490
|
+
0.30,
|
|
491
|
+
0.28,
|
|
492
|
+
0.25,
|
|
493
|
+
),
|
|
494
|
+
},
|
|
495
|
+
}
|
|
496
|
+
values = data.get(atm_conditions).get(strength_dev_class)
|
|
497
|
+
|
|
498
|
+
grid = np.array(np.meshgrid(fck_v, h_v)).T.reshape(-1, 2)
|
|
499
|
+
p = (fck_28, hn)
|
|
500
|
+
|
|
501
|
+
interp = scipy.interpolate.griddata(grid, values, p, method='linear')
|
|
502
|
+
_eps_cs_50y = float(interp)
|
|
503
|
+
|
|
504
|
+
if math.isnan(_eps_cs_50y):
|
|
505
|
+
raise ValueError('Combination of fck_28, hn out of scope')
|
|
506
|
+
|
|
507
|
+
return _eps_cs_50y
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def eta_cc(fck: float, fck_ref: float = 40) -> float:
|
|
511
|
+
"""Computes the factor to measure the difference between the undistributed
|
|
512
|
+
compressive strength of a cylinder and the effective compressive strength
|
|
513
|
+
in a structural member.
|
|
514
|
+
|
|
515
|
+
EN 1992-1-1:2023, Eq. (5.4).
|
|
516
|
+
|
|
517
|
+
Args:
|
|
518
|
+
fck (float): The characterisitic compressive strength in MPa.
|
|
519
|
+
|
|
520
|
+
Keyword Args:
|
|
521
|
+
fck_ref (float, optional): The reference compressive strength MPa.
|
|
522
|
+
|
|
523
|
+
Returns:
|
|
524
|
+
float: The value of the factor eta_cc.
|
|
525
|
+
|
|
526
|
+
Raises:
|
|
527
|
+
ValueError: If fck is less than 12 MPa.
|
|
528
|
+
ValueError: If fkc_ref is less or equal to 0.
|
|
529
|
+
"""
|
|
530
|
+
if fck < 12:
|
|
531
|
+
raise ValueError(f'fck={fck} must be larger or equal than 12 MPa')
|
|
532
|
+
if fck_ref <= 0:
|
|
533
|
+
raise ValueError(f'fck_ref={fck_ref} must be larger than 0')
|
|
534
|
+
|
|
535
|
+
return min(math.pow(fck_ref / fck, 1 / 3), 1)
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
def k_tc(
|
|
539
|
+
t_ref: float,
|
|
540
|
+
t0: float,
|
|
541
|
+
strength_dev_class: t.Literal['CS', 'CN', 'CR', 'slow', 'normal', 'rapid'],
|
|
542
|
+
) -> float:
|
|
543
|
+
"""Computes the factor for considering the effect of high sustained loads
|
|
544
|
+
and of time of loading on concrete compressive strength.
|
|
545
|
+
|
|
546
|
+
EN 1992-1-1:2023, Eq. (5.3).
|
|
547
|
+
|
|
548
|
+
Args:
|
|
549
|
+
t_ref (float): The reference time in days.
|
|
550
|
+
t0 (float): Age at loading in days.
|
|
551
|
+
strength_dev_class (str): Strength development class 'CS', 'CN', 'CR',
|
|
552
|
+
'slow', 'normal', 'rapid'.
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
float: The factor value.
|
|
556
|
+
|
|
557
|
+
Raises:
|
|
558
|
+
ValueError: If t_ref is less than 0.
|
|
559
|
+
ValueError: If t0 is less than 0.
|
|
560
|
+
ValueError: If strength_dev_class is not 'CS', 'CN', 'CR', 'slow',
|
|
561
|
+
'normal', 'rapid'.
|
|
562
|
+
"""
|
|
563
|
+
if t_ref < 0:
|
|
564
|
+
raise ValueError(f't_ref={t_ref} must be larger than 0')
|
|
565
|
+
if t0 < 0:
|
|
566
|
+
raise ValueError(f't0={t0} must be larger than 0')
|
|
567
|
+
|
|
568
|
+
strength_dev_class = strength_dev_class.upper().strip()
|
|
569
|
+
|
|
570
|
+
if strength_dev_class not in VALID_STRENGTH_DEV_CLASSES:
|
|
571
|
+
raise ValueError(
|
|
572
|
+
f'strength_dev_class={strength_dev_class}'
|
|
573
|
+
+ f'should can only take {VALID_STRENGTH_DEV_CLASSES}'
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
if (
|
|
577
|
+
strength_dev_class in ('CR', 'CN', 'RAPID', 'NORMAL')
|
|
578
|
+
and t_ref <= 28
|
|
579
|
+
and t0 > 90
|
|
580
|
+
):
|
|
581
|
+
return 1
|
|
582
|
+
|
|
583
|
+
if strength_dev_class in ('CS', 'SLOW') and t_ref <= 56 and t0 > 90:
|
|
584
|
+
return 1
|
|
585
|
+
|
|
586
|
+
return 0.85
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
def fcd(fck: float, eta_cc: float, k_tc: float, gamma_c: float) -> float:
|
|
590
|
+
"""Computes the value of the design compressive strength of concrete.
|
|
591
|
+
|
|
592
|
+
EN 1992-1-1:2023, Eq. (5.3).
|
|
593
|
+
|
|
594
|
+
Args:
|
|
595
|
+
fck (float): Characteristic compressive strength in MPa.
|
|
596
|
+
eta_cc (float): Factor for measuring the difference between the
|
|
597
|
+
undistributed compressive strength of a cylinder and the effective
|
|
598
|
+
compressive strength in the real structural member.
|
|
599
|
+
k_tc (float): Factor for taking into consideration high sustained
|
|
600
|
+
loads and of time of loading.
|
|
601
|
+
gamma_c (float): Partial factor of concrete.
|
|
602
|
+
|
|
603
|
+
Returns:
|
|
604
|
+
float: The design compressive strength of concrete in MPa.
|
|
605
|
+
|
|
606
|
+
Raises:
|
|
607
|
+
ValueError: If fck is less than 12 MPa.
|
|
608
|
+
ValueError: If _etc_cc is not between 0 and 1.
|
|
609
|
+
ValueError: If gamma_c is less than 1.
|
|
610
|
+
"""
|
|
611
|
+
if fck < 12:
|
|
612
|
+
raise ValueError(f'fck={fck} must be larger or equal than 12 MPa')
|
|
613
|
+
if eta_cc < 0 or eta_cc > 1:
|
|
614
|
+
raise ValueError(f'eta_cc={eta_cc} must be between 0 and 1')
|
|
615
|
+
if gamma_c < 1:
|
|
616
|
+
raise ValueError(f'gamma_c={gamma_c} must be larger or equal to 1')
|
|
617
|
+
|
|
618
|
+
return eta_cc * k_tc * fck / gamma_c
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def k_tt(
|
|
622
|
+
t_ref: float,
|
|
623
|
+
strength_dev_class: t.Literal['CS', 'CN', 'CR', 'slow', 'normal', 'rapid'],
|
|
624
|
+
) -> float:
|
|
625
|
+
"""Computes the factor for considering the effect of high sustained loads
|
|
626
|
+
and of time of loading on concrete tensile strength.
|
|
627
|
+
|
|
628
|
+
EN 1992-1-1:2023, Eq. (5.5).
|
|
629
|
+
|
|
630
|
+
Args:
|
|
631
|
+
t_ref (float): The reference time in days.
|
|
632
|
+
strength_dev_class (str): Strength development class 'CS', 'CN', 'CR',
|
|
633
|
+
'slow', 'normal' or 'rapid'.
|
|
634
|
+
|
|
635
|
+
Returns:
|
|
636
|
+
float: The factor value.
|
|
637
|
+
|
|
638
|
+
Raises:
|
|
639
|
+
ValueError: If t_ref is less than 0.
|
|
640
|
+
ValueError: If strength_dev_class is not 'CS', 'CN', 'CR', 'slow',
|
|
641
|
+
'normal' or 'rapid'.
|
|
642
|
+
"""
|
|
643
|
+
if t_ref < 0:
|
|
644
|
+
raise ValueError(f't_ref={t_ref} must be larger than 0')
|
|
645
|
+
|
|
646
|
+
strength_dev_class = strength_dev_class.upper().strip()
|
|
647
|
+
|
|
648
|
+
if strength_dev_class not in VALID_STRENGTH_DEV_CLASSES:
|
|
649
|
+
raise ValueError(
|
|
650
|
+
f'strength_dev_class={strength_dev_class}'
|
|
651
|
+
+ 'should can only take "CS", "CN", "CR", "slow"'
|
|
652
|
+
+ '"normal", "rapid" as values',
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
if strength_dev_class in ('CR', 'CN', 'RAPID', 'NORMAL') and t_ref <= 28:
|
|
656
|
+
return 0.8
|
|
657
|
+
|
|
658
|
+
if strength_dev_class in ('CS', 'SLOW') and t_ref <= 56:
|
|
659
|
+
return 0.8
|
|
660
|
+
|
|
661
|
+
return 0.7
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def fctd(fctk_5: float, k_tt: float, gamma_c: float) -> float:
|
|
665
|
+
"""Computes the value of the design tensile strength of concrete.
|
|
666
|
+
|
|
667
|
+
EN 1992-1-1:2023, Eq. (5.5).
|
|
668
|
+
|
|
669
|
+
Args:
|
|
670
|
+
fctk_5 (float): The 5% mean concrete tensile strength fractile in MPa.
|
|
671
|
+
k_tt (float): The factor for considering the effect of high sustained
|
|
672
|
+
loads and of time of loading on concrete tensile strength.
|
|
673
|
+
gamma_c (float): Partial factor of concrete.
|
|
674
|
+
|
|
675
|
+
Returns:
|
|
676
|
+
float: The design tensile strength of concrete in MPa.
|
|
677
|
+
|
|
678
|
+
Raises:
|
|
679
|
+
ValueError: If fctk_5 is less than 0.
|
|
680
|
+
ValueError: If gamma_c is less than 1.
|
|
681
|
+
"""
|
|
682
|
+
if fctk_5 < 0:
|
|
683
|
+
raise ValueError(f'fctk_5={fctk_5} must be larger or equal to 0')
|
|
684
|
+
if gamma_c < 1:
|
|
685
|
+
raise ValueError(f'gamma_c={gamma_c} must be larger or equal to 1')
|
|
686
|
+
|
|
687
|
+
return k_tt * fctk_5 / gamma_c
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
def eps_c1(fcm: float) -> float:
|
|
691
|
+
"""Computes the strain at maximum compressive strength of concrete (fcm)
|
|
692
|
+
for the Sargin constitutive law.
|
|
693
|
+
|
|
694
|
+
EN 1992-1-1:2023, Eq. (5.9).
|
|
695
|
+
|
|
696
|
+
Args:
|
|
697
|
+
fcm (float): The mean strength of concrete in MPa.
|
|
698
|
+
|
|
699
|
+
Returns:
|
|
700
|
+
float: The strain at maximum compressive strength of concrete.
|
|
701
|
+
|
|
702
|
+
Raises:
|
|
703
|
+
ValueError: If fcm is less than 12+8MPa.
|
|
704
|
+
"""
|
|
705
|
+
if fcm < 20:
|
|
706
|
+
raise ValueError(f'fcm={fcm} must be larger or equal to 12+8MPa')
|
|
707
|
+
|
|
708
|
+
return min(0.7 * math.pow(fcm, 1 / 3), 2.8) / 1000
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
def eps_cu1(fcm: float) -> float:
|
|
712
|
+
"""Computes the strain at concrete failure of concrete.
|
|
713
|
+
|
|
714
|
+
EN 1992-1-1:2023, Eq. (5.10).
|
|
715
|
+
|
|
716
|
+
Args:
|
|
717
|
+
fcm (float): The mean strength of concrete in MPa.
|
|
718
|
+
|
|
719
|
+
Returns:
|
|
720
|
+
float: The maximum strength at failure of concrete.
|
|
721
|
+
|
|
722
|
+
Raises:
|
|
723
|
+
ValueError: If fcm is less than 12+8MPa.
|
|
724
|
+
"""
|
|
725
|
+
if fcm < 20:
|
|
726
|
+
raise ValueError(f'fcm={fcm} must be larger or equal to 12+8MPa')
|
|
727
|
+
|
|
728
|
+
return min(2.8 + 14 * (1 - fcm / 108) ** 4, 3.5) / 1000
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
def k_sargin(
|
|
732
|
+
Ecm: float,
|
|
733
|
+
fcm: float,
|
|
734
|
+
eps_c1: float,
|
|
735
|
+
) -> float:
|
|
736
|
+
"""Computes the coefficient k for Sargin constitutive law in compression.
|
|
737
|
+
|
|
738
|
+
EN 1992-1-1:2003, eq. (5.7)
|
|
739
|
+
|
|
740
|
+
Args:
|
|
741
|
+
Ecm (float): the secant modulus between sigma_c=0 and sigma_c=0.4*fcm
|
|
742
|
+
in MPa
|
|
743
|
+
fcm (float): the mean compressive strength of concrete in MPa
|
|
744
|
+
eps_c1 (float): the strain of concrete at stress fcm
|
|
745
|
+
|
|
746
|
+
Returns:
|
|
747
|
+
float: the coefficient k for Sargin constitutive law
|
|
748
|
+
|
|
749
|
+
Raises:
|
|
750
|
+
ValueError: if Ecm is less or equal to 0
|
|
751
|
+
ValueError: if fcm is less than 12+8MPa
|
|
752
|
+
ValueError: if eps_c1 is less or equal to 0
|
|
753
|
+
"""
|
|
754
|
+
if Ecm <= 0:
|
|
755
|
+
raise ValueError(f'Ecm={Ecm} must be larger than 0')
|
|
756
|
+
if fcm < 20:
|
|
757
|
+
raise ValueError(f'fcm={fcm} must be larger or equal to 12+8MPa')
|
|
758
|
+
if eps_c1 <= 0:
|
|
759
|
+
raise ValueError(f'eps_c1={eps_c1} must be larger than 0')
|
|
760
|
+
return 1.05 * Ecm * eps_c1 / fcm
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
def eps_c2() -> float:
|
|
764
|
+
"""The strain at maximum compressive stress of concrete for the
|
|
765
|
+
parabolic-rectangular law.
|
|
766
|
+
|
|
767
|
+
EN 1992-1-1:2023, Eq. 8.4
|
|
768
|
+
|
|
769
|
+
Returns:
|
|
770
|
+
float: The strain at maximum compressive stress, absolute value, no
|
|
771
|
+
unit.
|
|
772
|
+
"""
|
|
773
|
+
return 2.0e-3
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
def eps_cu2() -> float:
|
|
777
|
+
"""The ultimate strain of the parabolic-rectangular law.
|
|
778
|
+
|
|
779
|
+
EN 1992-1-1:2023, Eq. 8.4
|
|
780
|
+
|
|
781
|
+
Returns:
|
|
782
|
+
float: The ultimate strain, absolute value, no unit.
|
|
783
|
+
"""
|
|
784
|
+
return 3.5e-3
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
def n_parabolic_rectangular() -> float:
|
|
788
|
+
"""The exponent in the parabolic-rectangular law.
|
|
789
|
+
|
|
790
|
+
EN 1992-1-1:2023, Eq. 8.4
|
|
791
|
+
Returns:
|
|
792
|
+
float: The exponent n, absolute value, no unit.
|
|
793
|
+
"""
|
|
794
|
+
return 2.0
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
def weight_c(concrete_type: t.Literal['nc', 'npc']) -> float:
|
|
798
|
+
"""Returns the mean unit weight of concrete in kN/m3.
|
|
799
|
+
|
|
800
|
+
EN 1992-1-1:2023, 5.1.6-5.
|
|
801
|
+
|
|
802
|
+
Args:
|
|
803
|
+
concrete_type (str): 'nc' for normal concrete, or 'npc' for normal
|
|
804
|
+
plain concrete.
|
|
805
|
+
|
|
806
|
+
Returns:
|
|
807
|
+
float: Mean unit weight in kN/m3.
|
|
808
|
+
|
|
809
|
+
Raises:
|
|
810
|
+
ValueError: If concrete_type is not 'nc' or 'npc'.
|
|
811
|
+
"""
|
|
812
|
+
concrete_type = concrete_type.lower().strip()
|
|
813
|
+
|
|
814
|
+
if concrete_type == 'nc':
|
|
815
|
+
return 25
|
|
816
|
+
if concrete_type == 'npc':
|
|
817
|
+
return 24
|
|
818
|
+
|
|
819
|
+
raise ValueError(
|
|
820
|
+
f'concrete_type={concrete_type} can only take'
|
|
821
|
+
+ '"nc" or "npc" as values'
|
|
822
|
+
)
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
def alpha_c_th() -> float:
|
|
826
|
+
"""Returns the linear coefficient of thermal expansion in 1/Cº for
|
|
827
|
+
concrete.
|
|
828
|
+
|
|
829
|
+
EN 1992-1-1:2023, 5.1.6-6.
|
|
830
|
+
|
|
831
|
+
Returns:
|
|
832
|
+
float: The linear coefficient of thermal expansion in 1/Cº for
|
|
833
|
+
concrete.
|
|
834
|
+
"""
|
|
835
|
+
return 10 * 10e-6
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
def Es() -> float:
|
|
839
|
+
"""Returns the value of the modulus of elasticity for weldable reinforcing
|
|
840
|
+
steel.
|
|
841
|
+
|
|
842
|
+
EN 1992-1-1:2023, 5.2.4-3.
|
|
843
|
+
|
|
844
|
+
Returns:
|
|
845
|
+
float: Modulus of elasticity in MPa.
|
|
846
|
+
"""
|
|
847
|
+
return 200000
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
def alpha_s_th() -> float:
|
|
851
|
+
"""Returns the linear coefficient of thermal expansion in 1/Cº for weldable
|
|
852
|
+
reinforced steel.
|
|
853
|
+
|
|
854
|
+
EN 1992-1-1:2023, 5.2.4-5
|
|
855
|
+
|
|
856
|
+
Returns:
|
|
857
|
+
float: The linear coefficient of thermal expansion in 1/Cº for weldable
|
|
858
|
+
reinforcement steel.
|
|
859
|
+
"""
|
|
860
|
+
return 10 * 10e-6
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
def weight_s() -> float:
|
|
864
|
+
"""Returns the mean unit weight of reinforced steel for the purposes of
|
|
865
|
+
design in kN/m3.
|
|
866
|
+
|
|
867
|
+
EN 1992-1-1:2023.2.4-4.
|
|
868
|
+
|
|
869
|
+
Returns:
|
|
870
|
+
float: The mean unit weight in kN/m3.
|
|
871
|
+
"""
|
|
872
|
+
return 78.5
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
def fyd(fyk: float, gamma_s: float) -> float:
|
|
876
|
+
"""Design value for the yielding stress for welding reinforcing steel.
|
|
877
|
+
|
|
878
|
+
EN 1992-1-1:2023, Eq (5.11).
|
|
879
|
+
|
|
880
|
+
Args:
|
|
881
|
+
fyk (float): Characteristic yield stress for the steel in MPa.
|
|
882
|
+
gamma_s (float): Safety coefficient.
|
|
883
|
+
|
|
884
|
+
Returns:
|
|
885
|
+
float: Design yielding stress for steel in MPa.
|
|
886
|
+
|
|
887
|
+
Raises:
|
|
888
|
+
ValueError: If fyk is less than 0.
|
|
889
|
+
ValueError: If gamma_s is less than 1.
|
|
890
|
+
"""
|
|
891
|
+
if fyk < 0:
|
|
892
|
+
raise ValueError(f'fyk={fyk} cannot be less than 0')
|
|
893
|
+
if gamma_s < 1:
|
|
894
|
+
raise ValueError(f'gamma_s={gamma_s} must be larger or equal to 1')
|
|
895
|
+
|
|
896
|
+
return fyk / gamma_s
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
def eps_ud(eps_uk: float, gamma_s: float) -> float:
|
|
900
|
+
"""Design value for the ultimate limit strain welding reinforcing steel.
|
|
901
|
+
|
|
902
|
+
EN 1992-1-1:2023, 5.2.4-2.
|
|
903
|
+
|
|
904
|
+
Args:
|
|
905
|
+
eps_uk (float): Characteristic ultimate limit strain.
|
|
906
|
+
gamma_s (float): Safety coefficient.
|
|
907
|
+
|
|
908
|
+
Returns:
|
|
909
|
+
float: Design ultimate strain limit.
|
|
910
|
+
|
|
911
|
+
Raises:
|
|
912
|
+
ValueError: If eps_uk is less than 0.
|
|
913
|
+
ValueError: If gamma_s is less than 1.
|
|
914
|
+
"""
|
|
915
|
+
if eps_uk < 0:
|
|
916
|
+
raise ValueError(f'eps_uk={eps_uk} must be equal or larger to 0')
|
|
917
|
+
if gamma_s < 1:
|
|
918
|
+
raise ValueError(f'gamma_s={gamma_s} must be larger or equal to 1')
|
|
919
|
+
|
|
920
|
+
return eps_uk / gamma_s
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
def sigma_s(
|
|
924
|
+
eps: float, fy: float, k: float, eps_u: float, Es: float = 200000
|
|
925
|
+
) -> float:
|
|
926
|
+
"""Compute the stress for welded reinforcing steel in MPa for a given
|
|
927
|
+
strain.
|
|
928
|
+
|
|
929
|
+
EN 1992-1-1:2023, 5.2.4.
|
|
930
|
+
|
|
931
|
+
Args:
|
|
932
|
+
eps (float): The strain value.
|
|
933
|
+
fy (float): The yielding stress in MPa. Use fyd for the design
|
|
934
|
+
strength, and fyk for the characteristic strength.
|
|
935
|
+
k (float): Curve parameter. Ratio between the ultimate stress and the
|
|
936
|
+
yielding stress. k = 1 for horizontal post-elastic branch without
|
|
937
|
+
strain limit.
|
|
938
|
+
eps_u (float): Ultimate strain at failure. Use eps_ud for the design
|
|
939
|
+
ultimate strain, and eps_uk for the characteristic ultimate strain.
|
|
940
|
+
|
|
941
|
+
Keyword Args:
|
|
942
|
+
Es (float): The modulus of elasticity for reinforcing steel.
|
|
943
|
+
|
|
944
|
+
Returns:
|
|
945
|
+
float: The nominal stress in MPa.
|
|
946
|
+
|
|
947
|
+
Raises:
|
|
948
|
+
ValueError: If eps is less than 0 or larger than eps_uk.
|
|
949
|
+
ValueError: If Es is less or equal to 0.
|
|
950
|
+
ValueError: If fy is less or equal to 0.
|
|
951
|
+
ValueError: If k is less than 1.
|
|
952
|
+
ValueError: If eps_u is less or equal to 0 and k > 1.
|
|
953
|
+
"""
|
|
954
|
+
if eps < 0:
|
|
955
|
+
raise ValueError(f'eps={eps} must be larger or equal to 0')
|
|
956
|
+
if eps_u <= 0:
|
|
957
|
+
raise ValueError(f'eps_u={eps_u} must be larger than 0')
|
|
958
|
+
if eps > eps_u and k > 1:
|
|
959
|
+
raise ValueError(
|
|
960
|
+
f'eps={eps} must be equal o less than'
|
|
961
|
+
+ 'eps_uk={eps_u} when k is larger than 1'
|
|
962
|
+
)
|
|
963
|
+
if Es <= 0:
|
|
964
|
+
raise ValueError(f'Es={Es} must be larger than 0')
|
|
965
|
+
if fy <= 0:
|
|
966
|
+
raise ValueError(f'fyk={fy} must be larger than 0')
|
|
967
|
+
if k < 0:
|
|
968
|
+
raise ValueError(f'k={k} must be larger than 1')
|
|
969
|
+
|
|
970
|
+
eps_y = fy / Es
|
|
971
|
+
|
|
972
|
+
# If in elastic area
|
|
973
|
+
if eps <= eps_y:
|
|
974
|
+
return eps * Es
|
|
975
|
+
|
|
976
|
+
# If in plastic area
|
|
977
|
+
m = fy * (k - 1) / (eps_u - eps_y)
|
|
978
|
+
return fy + m * (eps - eps_y)
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
def p_steel_stress_params(
|
|
982
|
+
prestress_class: t.Literal[
|
|
983
|
+
'Y1560',
|
|
984
|
+
'Y1670',
|
|
985
|
+
'Y1770',
|
|
986
|
+
'Y1860',
|
|
987
|
+
'Y1770',
|
|
988
|
+
'Y1860',
|
|
989
|
+
'Y1960',
|
|
990
|
+
'Y2060',
|
|
991
|
+
'Y1030',
|
|
992
|
+
'Y1050',
|
|
993
|
+
'Y1100',
|
|
994
|
+
'Y1230',
|
|
995
|
+
],
|
|
996
|
+
element: t.Literal['W', 'S', 'B'],
|
|
997
|
+
) -> t.Tuple[float, float]:
|
|
998
|
+
"""Computes the stress-diagram parameters fp01k and fpk.
|
|
999
|
+
|
|
1000
|
+
EN 1992-1-1:2023, 5.3.3.
|
|
1001
|
+
|
|
1002
|
+
Args:
|
|
1003
|
+
prestress_class (str): Possible values: Y1560, Y1670,
|
|
1004
|
+
Y1770, Y1860, Y1770, Y1860, Y1960, Y2060,
|
|
1005
|
+
Y1030, Y1050, Y1100 and Y1230
|
|
1006
|
+
element (str): Element type, 'W' for Wires, 'S' for Strands, and 'B'
|
|
1007
|
+
for Bars.
|
|
1008
|
+
|
|
1009
|
+
Returns:
|
|
1010
|
+
Tuple(float, float): With the value of fp01k and fpk in MPa.
|
|
1011
|
+
|
|
1012
|
+
Raises:
|
|
1013
|
+
ValueError: If combination of prestress_class and element is not a
|
|
1014
|
+
possible value from the range.
|
|
1015
|
+
"""
|
|
1016
|
+
prestress_class = prestress_class.upper().strip()
|
|
1017
|
+
element = element.upper().strip()
|
|
1018
|
+
data = {
|
|
1019
|
+
'W': {
|
|
1020
|
+
'Y1570': (1380, 1570),
|
|
1021
|
+
'Y1670': (1470, 1670),
|
|
1022
|
+
'Y1770': (1550, 1770),
|
|
1023
|
+
'Y1860': (1650, 1860),
|
|
1024
|
+
},
|
|
1025
|
+
'S': {
|
|
1026
|
+
'Y1770': (1560, 1770),
|
|
1027
|
+
'Y1860': (1640, 1860),
|
|
1028
|
+
'Y1960': (1740, 1960),
|
|
1029
|
+
'Y2060': (1830, 2060),
|
|
1030
|
+
},
|
|
1031
|
+
'B': {
|
|
1032
|
+
'Y1030': (835, 1030),
|
|
1033
|
+
'Y1050': (950, 1050),
|
|
1034
|
+
'Y1100': (900, 1100),
|
|
1035
|
+
'Y1230': (1080, 1230),
|
|
1036
|
+
},
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
if element not in data:
|
|
1040
|
+
raise ValueError(f'element={element} has not a valid value')
|
|
1041
|
+
|
|
1042
|
+
material = data[element]
|
|
1043
|
+
|
|
1044
|
+
if prestress_class not in material:
|
|
1045
|
+
raise ValueError(
|
|
1046
|
+
f'prestress_class={prestress_class} has not a valid value'
|
|
1047
|
+
)
|
|
1048
|
+
|
|
1049
|
+
return material[prestress_class]
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
def fpd(fp01k: float, gamma_P: float) -> float:
|
|
1053
|
+
"""Computes the design value for the prestressing steel stress.
|
|
1054
|
+
|
|
1055
|
+
EN 1992-1-1:2023, 5.3.3.
|
|
1056
|
+
|
|
1057
|
+
Args:
|
|
1058
|
+
fp01k (float): The 0.1% proof stress in MPa.
|
|
1059
|
+
gamma_P (float): The safety coefficient.
|
|
1060
|
+
|
|
1061
|
+
Returns:
|
|
1062
|
+
float: The design value for the design prestressing steel stress in
|
|
1063
|
+
MPa.
|
|
1064
|
+
|
|
1065
|
+
Raises:
|
|
1066
|
+
ValueError: If fp01k is less than 0.
|
|
1067
|
+
ValueError: If gamma_P is less than 1.
|
|
1068
|
+
"""
|
|
1069
|
+
if fp01k < 0:
|
|
1070
|
+
raise ValueError(f'fp01k={fp01k} must be larger or equal to 0')
|
|
1071
|
+
if gamma_P < 1:
|
|
1072
|
+
raise ValueError(f'gamma_P={gamma_P} must be larger or equal than 1')
|
|
1073
|
+
|
|
1074
|
+
return fp01k / gamma_P
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
def sigma_p(
|
|
1078
|
+
eps: float,
|
|
1079
|
+
fpy: float,
|
|
1080
|
+
fpu: float,
|
|
1081
|
+
eps_u: float = 0.035,
|
|
1082
|
+
Ep: float = 190000,
|
|
1083
|
+
) -> float:
|
|
1084
|
+
"""Computes the stress for prestressing steel as a function of the strain.
|
|
1085
|
+
|
|
1086
|
+
EN 1992-1-1:2023, 5.3.3.
|
|
1087
|
+
|
|
1088
|
+
Args:
|
|
1089
|
+
eps (float): Strain value.
|
|
1090
|
+
fpy (float): Yielding stress of the steel in MPa. Use fd for design
|
|
1091
|
+
stress values, and fp01k for nominal stress values.
|
|
1092
|
+
fpu (float): The maximum stress at eps_u in MPa. Use fpd for design
|
|
1093
|
+
stress values, fpk for nominal stress values, and fpu == fpy for
|
|
1094
|
+
horizontal post-elastic branch without strain limit.
|
|
1095
|
+
|
|
1096
|
+
Keyword Args:
|
|
1097
|
+
eps_u (float): Ultimate strain. Use eps_uk = 0.035 for nominal ultimate
|
|
1098
|
+
strain, and eps_ud for design ultimate strain.
|
|
1099
|
+
Ep (float): Modulus of elasticity of prestressing steel in MPa.
|
|
1100
|
+
|
|
1101
|
+
Raises:
|
|
1102
|
+
ValueError: If eps is less than 0 or larger than eps_u.
|
|
1103
|
+
ValueError: If fpy is less or equal to 0.
|
|
1104
|
+
ValueError: If fpu is less than fpy.
|
|
1105
|
+
ValueError: If eps_u is lower or equal to 0.
|
|
1106
|
+
ValueError: If _Ep is less or equal to 0.
|
|
1107
|
+
"""
|
|
1108
|
+
if eps < 0:
|
|
1109
|
+
raise ValueError(f'eps={eps} must be larger or equal to 0')
|
|
1110
|
+
if eps_u <= 0:
|
|
1111
|
+
raise ValueError(f'eps_u={eps_u} must be larger than 0')
|
|
1112
|
+
if eps_u < eps and fpy != fpu:
|
|
1113
|
+
raise ValueError(f'eps_u={eps_u} must be larger than eps={eps}')
|
|
1114
|
+
if fpy <= 0:
|
|
1115
|
+
raise ValueError(f'fpy={fpy} must be larger than 0')
|
|
1116
|
+
if fpu < fpy:
|
|
1117
|
+
raise ValueError(f'fpu={fpy} must be larger or equal to fpy={fpy}')
|
|
1118
|
+
if Ep <= 0:
|
|
1119
|
+
raise ValueError(f'Ep={Ep} must be larger than 0')
|
|
1120
|
+
|
|
1121
|
+
eps_y = fpy / Ep
|
|
1122
|
+
|
|
1123
|
+
# If elastic
|
|
1124
|
+
if eps <= eps_y:
|
|
1125
|
+
return eps * Ep
|
|
1126
|
+
|
|
1127
|
+
# If plastic
|
|
1128
|
+
m = (fpu - fpy) / (eps_u - eps_y)
|
|
1129
|
+
return fpy + m * (eps - eps_y)
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
def reinforcement_duct_props(
|
|
1133
|
+
fyk: float,
|
|
1134
|
+
ductility_class: t.Literal['A', 'B', 'C'],
|
|
1135
|
+
) -> t.Dict[str, float]:
|
|
1136
|
+
"""Return a dict with the minimum characteristic ductility properties for
|
|
1137
|
+
reinforcement ductility class.
|
|
1138
|
+
|
|
1139
|
+
EUROCODE 2 1992-1-1:2023, Tab. 5.5.
|
|
1140
|
+
|
|
1141
|
+
Args:
|
|
1142
|
+
fyk (float): The characteristic yield strength.
|
|
1143
|
+
ductility_class (Literal['A', 'B', 'C']): The reinforcement ductility
|
|
1144
|
+
class designation.
|
|
1145
|
+
|
|
1146
|
+
Returns:
|
|
1147
|
+
Dict[str, float]: A dict with the characteristik strain value at the
|
|
1148
|
+
ultimate stress level (epsuk), and the characteristic ultimate stress
|
|
1149
|
+
(ftk).
|
|
1150
|
+
"""
|
|
1151
|
+
duct_props = DUCTILITY_CLASSES.get(ductility_class.upper(), None)
|
|
1152
|
+
if duct_props is None:
|
|
1153
|
+
raise ValueError(
|
|
1154
|
+
'The no properties was found for the provided ductility class '
|
|
1155
|
+
f'({ductility_class}).'
|
|
1156
|
+
)
|
|
1157
|
+
return {
|
|
1158
|
+
'epsuk': duct_props['epsuk'],
|
|
1159
|
+
'ftk': duct_props['k'] * fyk,
|
|
1160
|
+
}
|