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.

Files changed (50) hide show
  1. structuralcodes/__init__.py +17 -0
  2. structuralcodes/codes/__init__.py +79 -0
  3. structuralcodes/codes/ec2_2004/__init__.py +133 -0
  4. structuralcodes/codes/ec2_2004/_concrete_material_properties.py +239 -0
  5. structuralcodes/codes/ec2_2004/_reinforcement_material_properties.py +104 -0
  6. structuralcodes/codes/ec2_2004/_section_7_3_crack_control.py +941 -0
  7. structuralcodes/codes/ec2_2004/annex_b_shrink_and_creep.py +257 -0
  8. structuralcodes/codes/ec2_2004/shear.py +506 -0
  9. structuralcodes/codes/ec2_2023/__init__.py +104 -0
  10. structuralcodes/codes/ec2_2023/_annexB_time_dependent.py +17 -0
  11. structuralcodes/codes/ec2_2023/_section5_materials.py +1160 -0
  12. structuralcodes/codes/ec2_2023/_section9_sls.py +325 -0
  13. structuralcodes/codes/mc2010/__init__.py +169 -0
  14. structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py +704 -0
  15. structuralcodes/codes/mc2010/_concrete_interface_different_casting_times.py +104 -0
  16. structuralcodes/codes/mc2010/_concrete_material_properties.py +463 -0
  17. structuralcodes/codes/mc2010/_concrete_punching.py +543 -0
  18. structuralcodes/codes/mc2010/_concrete_shear.py +749 -0
  19. structuralcodes/codes/mc2010/_concrete_torsion.py +164 -0
  20. structuralcodes/codes/mc2010/_reinforcement_material_properties.py +105 -0
  21. structuralcodes/core/__init__.py +1 -0
  22. structuralcodes/core/_section_results.py +211 -0
  23. structuralcodes/core/base.py +260 -0
  24. structuralcodes/geometry/__init__.py +25 -0
  25. structuralcodes/geometry/_geometry.py +875 -0
  26. structuralcodes/geometry/_steel_sections.py +2155 -0
  27. structuralcodes/materials/__init__.py +9 -0
  28. structuralcodes/materials/concrete/__init__.py +82 -0
  29. structuralcodes/materials/concrete/_concrete.py +114 -0
  30. structuralcodes/materials/concrete/_concreteEC2_2004.py +477 -0
  31. structuralcodes/materials/concrete/_concreteEC2_2023.py +435 -0
  32. structuralcodes/materials/concrete/_concreteMC2010.py +494 -0
  33. structuralcodes/materials/constitutive_laws.py +979 -0
  34. structuralcodes/materials/reinforcement/__init__.py +84 -0
  35. structuralcodes/materials/reinforcement/_reinforcement.py +172 -0
  36. structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py +103 -0
  37. structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py +93 -0
  38. structuralcodes/materials/reinforcement/_reinforcementMC2010.py +98 -0
  39. structuralcodes/sections/__init__.py +23 -0
  40. structuralcodes/sections/_generic.py +1249 -0
  41. structuralcodes/sections/_reinforcement.py +115 -0
  42. structuralcodes/sections/section_integrators/__init__.py +14 -0
  43. structuralcodes/sections/section_integrators/_factory.py +41 -0
  44. structuralcodes/sections/section_integrators/_fiber_integrator.py +238 -0
  45. structuralcodes/sections/section_integrators/_marin_integration.py +47 -0
  46. structuralcodes/sections/section_integrators/_marin_integrator.py +222 -0
  47. structuralcodes/sections/section_integrators/_section_integrator.py +49 -0
  48. structuralcodes-0.0.1.dist-info/METADATA +40 -0
  49. structuralcodes-0.0.1.dist-info/RECORD +50 -0
  50. structuralcodes-0.0.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,9 @@
1
+ """Main entry point for materials."""
2
+
3
+ from . import concrete, constitutive_laws, reinforcement
4
+
5
+ __all__ = [
6
+ 'concrete',
7
+ 'constitutive_laws',
8
+ 'reinforcement',
9
+ ]
@@ -0,0 +1,82 @@
1
+ """Concrete material."""
2
+
3
+ import typing as t
4
+
5
+ from structuralcodes.codes import _use_design_code
6
+
7
+ from ._concrete import Concrete
8
+ from ._concreteEC2_2004 import ConcreteEC2_2004
9
+ from ._concreteEC2_2023 import ConcreteEC2_2023
10
+ from ._concreteMC2010 import ConcreteMC2010
11
+
12
+ __all__ = [
13
+ 'create_concrete',
14
+ 'Concrete',
15
+ 'ConcreteMC2010',
16
+ 'ConcreteEC2_2023',
17
+ 'ConcreteEC2_2004',
18
+ ]
19
+
20
+ CONCRETES: t.Dict[str, Concrete] = {
21
+ 'fib Model Code 2010': ConcreteMC2010,
22
+ 'EUROCODE 2 1992-1-1:2004': ConcreteEC2_2004,
23
+ 'EUROCODE 2 1992-1-1:2023': ConcreteEC2_2023,
24
+ }
25
+
26
+
27
+ def create_concrete(
28
+ fck: float,
29
+ name: t.Optional[str] = None,
30
+ density: float = 2400.0,
31
+ gamma_c: t.Optional[float] = None,
32
+ existing: bool = False,
33
+ design_code: t.Optional[str] = None,
34
+ **kwargs,
35
+ ) -> t.Optional[Concrete]:
36
+ """A factory function to create the correct type of concrete based on the
37
+ desired design code.
38
+
39
+ Arguments:
40
+ fck (float): Characteristic strength of concrete in MPa. (if existing
41
+ it is intended as the mean strength).
42
+
43
+ Keyword Arguments:
44
+ density (float): Density of Concrete in kg/m3 (default: 2400).
45
+ gamma_c (Optional(float)): The partial factor for concrete.
46
+ existing (bool): Boolean indicating if the concrete is of an existing
47
+ structure (default: False).
48
+ design_code (str): Optional string (default: None) indicating the
49
+ desired standard. If None (default) the globally used design
50
+ standard will be adopted. Otherwise the design standard specified
51
+ will be used for the instance of the material.
52
+
53
+ Raises:
54
+ ValueError: if the design code is not valid or does not cover concrete
55
+ as a material.
56
+ """
57
+ # Get the code from the global variable
58
+ _code = _use_design_code(design_code)
59
+
60
+ # Check if the code is a proper concrete code
61
+ code = None
62
+ if _code is not None and 'concrete' in _code.__materials__:
63
+ code = _code
64
+ if code is None:
65
+ raise ValueError(
66
+ 'The design code is not set, either use '
67
+ 'structuralcodes.code.set_designcode, or provide a valid '
68
+ 'string in the function.'
69
+ )
70
+
71
+ # Create the proper concrete object
72
+ current_concrete = CONCRETES.get(code.__title__, None)
73
+ if current_concrete is not None:
74
+ return current_concrete(
75
+ fck=fck,
76
+ name=name,
77
+ density=density,
78
+ gamma_c=gamma_c,
79
+ existing=existing,
80
+ **kwargs,
81
+ )
82
+ return None
@@ -0,0 +1,114 @@
1
+ """Core implementation of the concrete material."""
2
+
3
+ import abc
4
+ import typing as t
5
+
6
+ from structuralcodes.core.base import ConstitutiveLaw, Material
7
+ from structuralcodes.materials.constitutive_laws import create_constitutive_law
8
+
9
+
10
+ class Concrete(Material):
11
+ """The abstract concrete material."""
12
+
13
+ _fck: float
14
+ _gamma_c: t.Optional[float] = None
15
+ _existing: bool
16
+ _constitutive_law: t.Optional[ConstitutiveLaw] = None
17
+
18
+ def __init__(
19
+ self,
20
+ fck: float,
21
+ name: t.Optional[str] = None,
22
+ density: float = 2400,
23
+ gamma_c: t.Optional[float] = None,
24
+ existing: t.Optional[bool] = False,
25
+ ) -> None:
26
+ """Initializes an abstract concrete material."""
27
+ name = name if name is not None else 'Concrete'
28
+ super().__init__(density=density, name=name)
29
+
30
+ self._fck = abs(fck)
31
+ if existing:
32
+ raise NotImplementedError(
33
+ 'Existing concrete feature not implemented yet'
34
+ )
35
+ self._existing = existing
36
+ self._gamma_c = gamma_c
37
+ self._constitutive_law = None
38
+
39
+ @property
40
+ def fck(self) -> float:
41
+ """Returns fck in MPa."""
42
+ return self._fck
43
+
44
+ @fck.setter
45
+ def fck(self, fck: float) -> None:
46
+ """Setter for fck (in MPa)."""
47
+ self._fck = abs(fck)
48
+ self._reset_attributes()
49
+
50
+ @abc.abstractmethod
51
+ def _reset_attributes(self):
52
+ """Each concrete should define its own _reset_attributes method. This
53
+ is because fck setting, reset the object arguments.
54
+ """
55
+
56
+ @property
57
+ def constitutive_law(self) -> ConstitutiveLaw:
58
+ """Returns the constitutive law object."""
59
+ if self._constitutive_law is None:
60
+ self.constitutive_law = 'parabolarectangle'
61
+ return self._constitutive_law
62
+
63
+ @constitutive_law.setter
64
+ def constitutive_law(
65
+ self,
66
+ constitutive_law: t.Union[
67
+ ConstitutiveLaw,
68
+ t.Literal['elastic', 'parabolarectangle', 'sargin', 'popovics'],
69
+ ],
70
+ ) -> None:
71
+ """Setter for constitutive law.
72
+
73
+ Arguments:
74
+ consitutive_law (ConstitutiveLaw | str): A valid ConstitutiveLaw
75
+ object for concrete or a string defining a valid constitutive
76
+ law type for concrete. (valid options for string: 'elastic',
77
+ 'parabolarectangle', 'bilinearcompression', 'sargin',
78
+ 'popovics').
79
+ """
80
+ if constitutive_law is None:
81
+ raise ValueError(
82
+ 'At least a constitutive law or a string defining the '
83
+ 'constitutive law must be provided.'
84
+ )
85
+ if isinstance(constitutive_law, str):
86
+ constitutive_law = create_constitutive_law(
87
+ constitutive_law_name=constitutive_law, material=self
88
+ )
89
+
90
+ if isinstance(constitutive_law, ConstitutiveLaw):
91
+ if 'concrete' in constitutive_law.__materials__:
92
+ self._constitutive_law = constitutive_law
93
+ else:
94
+ raise ValueError(
95
+ 'The constitutive law selected is not suitable '
96
+ 'for being used with a concrete material.'
97
+ )
98
+ else:
99
+ raise ValueError(
100
+ f'The constitutive law {constitutive_law} could not be created'
101
+ )
102
+
103
+ @property
104
+ @abc.abstractmethod
105
+ def gamma_c(self) -> float:
106
+ """Each concrete should implement its own getter for the partial factor
107
+ in order to interact with the globally set national annex.
108
+ """
109
+
110
+ @abc.abstractmethod
111
+ def fcd(self) -> float:
112
+ """Each concrete should implement its own method for calculating the
113
+ design compressive strength.
114
+ """
@@ -0,0 +1,477 @@
1
+ """The concrete class for EC2 2004 Concrete Material."""
2
+
3
+ import typing as t
4
+ import warnings
5
+
6
+ from structuralcodes.codes import ec2_2004
7
+
8
+ from ._concrete import Concrete
9
+
10
+
11
+ class ConcreteEC2_2004(Concrete): # noqa: N801
12
+ """Concrete implementation for EC2 2004."""
13
+
14
+ # computed attributes
15
+ _fcm: t.Optional[float] = None
16
+ _fctm: t.Optional[float] = None
17
+ _fctk_5: t.Optional[float] = None
18
+ _fctk_95: t.Optional[float] = None
19
+ _Ecm: t.Optional[float] = None
20
+ _alpha_cc: t.Optional[float] = None
21
+ _eps_c1: t.Optional[float] = None
22
+ _eps_cu1: t.Optional[float] = None
23
+ _k_sargin: t.Optional[float] = None
24
+ _eps_c2: t.Optional[float] = None
25
+ _eps_cu2: t.Optional[float] = None
26
+ _n_parabolic_rectangular: t.Optional[float] = None
27
+ _eps_c3: t.Optional[float] = None
28
+ _eps_cu3: t.Optional[float] = None
29
+
30
+ def __init__(
31
+ self,
32
+ fck: float,
33
+ name: t.Optional[str] = None,
34
+ density: float = 2400,
35
+ gamma_c: t.Optional[float] = None,
36
+ alpha_cc: t.Optional[float] = None,
37
+ **kwargs,
38
+ ) -> None:
39
+ """Initializes a new instance of Concrete for EC2 2004.
40
+
41
+ Arguments:
42
+ fck (float): Characteristic strength in MPa if concrete is not
43
+ existing.
44
+
45
+ Keyword Arguments:
46
+ name (str): A descriptive name for concrete.
47
+ density (float): Density of material in kg/m3 (default: 2400).
48
+ gamma_c (float, optional): partial factor of concrete (default is
49
+ 1.5).
50
+ alpha_cc (float, optional): A factor for considering long-term
51
+ effects on the strength, and effects that arise from the way
52
+ the load is applied.
53
+ """
54
+ del kwargs
55
+ if name is None:
56
+ name = f'C{round(fck):d}'
57
+ super().__init__(
58
+ fck=fck,
59
+ name=name,
60
+ density=density,
61
+ existing=False,
62
+ gamma_c=gamma_c,
63
+ )
64
+ self._alpha_cc = alpha_cc
65
+
66
+ def _reset_attributes(self):
67
+ self._fcm = None
68
+ self._fctm = None
69
+ self._fctk_5 = None
70
+ self._fctk_95 = None
71
+ self._Ecm = None
72
+ self._eps_c1 = None
73
+ self._eps_cu1 = None
74
+ self._k_sargin = None
75
+ self._eps_c2 = None
76
+ self._eps_cu2 = None
77
+ self._n_parabolic_rectangular = None
78
+ self._eps_c3 = None
79
+ self._eps_cu3 = None
80
+
81
+ @property
82
+ def fcm(self) -> float:
83
+ """Returns fcm in MPa.
84
+
85
+ Returns:
86
+ float: The mean compressive strength in MPa.
87
+ """
88
+ if self._fcm is None:
89
+ self._fcm = ec2_2004.fcm(self._fck)
90
+ return self._fcm
91
+
92
+ @fcm.setter
93
+ def fcm(self, value: float):
94
+ """Sets a user defined value for fcm.
95
+
96
+ Arguments:
97
+ value (float): The value of fcm in MPa.
98
+
99
+ Raises:
100
+ ValueError: If value is lower than fck.
101
+ """
102
+ if abs(value) <= self._fck:
103
+ raise ValueError(
104
+ (
105
+ 'Mean compressive strength cannot be lower than',
106
+ 'characteristic strength.\n',
107
+ 'Current characteristing strength: ',
108
+ f'fck = {self._fck}.',
109
+ f'Current value: value = {value}',
110
+ )
111
+ )
112
+ self._fcm = abs(value)
113
+
114
+ @property
115
+ def fctm(self) -> float:
116
+ """Returns fctm in MPa.
117
+
118
+ Returns:
119
+ float: The mean tensile strength in MPa.
120
+ """
121
+ if self._fctm is None:
122
+ self._fctm = ec2_2004.fctm(self._fck)
123
+ return self._fctm
124
+
125
+ @fctm.setter
126
+ def fctm(self, value: float):
127
+ """Sets a user defined value for fctm.
128
+
129
+ Arguments:
130
+ value (float): The value of fctm in MPa.
131
+ """
132
+ if value > 0.5 * self._fck:
133
+ warnings.warn(
134
+ 'A suspect value of fctm has been input. Please check.'
135
+ )
136
+ self._fctm = abs(value)
137
+
138
+ @property
139
+ def fctk_5(self) -> float:
140
+ """Returns fctk_5 in MPa.
141
+
142
+ Returns:
143
+ float: The lower bound tensile strength in MPa.
144
+ """
145
+ if self._fctk_5 is not None:
146
+ return self._fctk_5
147
+ return ec2_2004.fctk_5(self.fctm)
148
+
149
+ @fctk_5.setter
150
+ def fctk_5(self, value: float):
151
+ """Sets a user defined value for fctk_5.
152
+
153
+ Arguments:
154
+ value (float): The value of fctk_5 in MPa.
155
+ """
156
+ self._fctk_5 = abs(value)
157
+
158
+ @property
159
+ def fctk_95(self) -> float:
160
+ """Returns fctk_95 in MPa.
161
+
162
+ Returns:
163
+ float: The upper bound tensile strength in MPa.
164
+ """
165
+ if self._fctk_95 is not None:
166
+ return self._fctk_95
167
+
168
+ return ec2_2004.fctk_95(self.fctm)
169
+
170
+ @fctk_95.setter
171
+ def fctk_95(self, value: float):
172
+ """Sets a user defined value for fctk_95.
173
+
174
+ Arguments:
175
+ value (float): The value of fctk_95 in MPa.
176
+ """
177
+ self._fctk_95 = abs(value)
178
+
179
+ @property
180
+ def Ecm(self) -> float:
181
+ """Returns Ecm in MPa.
182
+
183
+ Returns:
184
+ float: The upper bound tensile strength in MPa.
185
+ """
186
+ if self._Ecm is not None:
187
+ return self._Ecm
188
+
189
+ return ec2_2004.Ecm(self.fcm)
190
+
191
+ @Ecm.setter
192
+ def Ecm(self, value: float):
193
+ """Sets a user defined value for Ecm.
194
+
195
+ Arguments:
196
+ value (float): The value of Ecm in MPa.
197
+ """
198
+ self._Ecm = abs(value)
199
+
200
+ def fcd(self) -> float:
201
+ """Return the design compressive strength in MPa.
202
+
203
+ Returns:
204
+ float: The design compressive strength of concrete in MPa.
205
+ """
206
+ # This method should perhaps become a property, but is left as a method
207
+ # for now, to be consistent with other concretes.
208
+ return ec2_2004.fcd(
209
+ self.fck, alpha_cc=self.alpha_cc, gamma_c=self.gamma_c
210
+ )
211
+
212
+ @property
213
+ def gamma_c(self) -> float:
214
+ """The partial factor for concrete."""
215
+ # Here we should implement the interaction with the globally set
216
+ # national annex. For now, we simply return the default value.
217
+ return self._gamma_c or 1.5
218
+
219
+ @property
220
+ def alpha_cc(self) -> float:
221
+ """The alpha_cc factor."""
222
+ # Here we should implement the interaction with the globally set
223
+ # national annex. For now, we simply return the default value.
224
+ return self._alpha_cc or 1.0
225
+
226
+ @property
227
+ def eps_c1(self) -> float:
228
+ """Returns the strain at maximum compressive strength of concrete (fcm)
229
+ for the Sargin constitutive law.
230
+
231
+ Returns:
232
+ float: The strain at maximum compressive strength of concrete.
233
+ """
234
+ self._eps_c1 = self._eps_c1 or ec2_2004.eps_c1(self.fcm)
235
+ return self._eps_c1
236
+
237
+ @eps_c1.setter
238
+ def eps_c1(self, value: float):
239
+ """Sets a user defined value for strain at peak strength for Sargin
240
+ constitutive law.
241
+
242
+ Arguments:
243
+ value (float): The new value for eps_c1, no units.
244
+ """
245
+ if abs(value) >= 0.1:
246
+ warnings.warn(
247
+ 'A suspect value is input for eps_c1 that should be a pure'
248
+ ' number without units. Plase check ({value} given).'
249
+ )
250
+ self._eps_c1 = value
251
+
252
+ @property
253
+ def eps_cu1(self) -> float:
254
+ """Returns the strain at concrete failure of concrete.
255
+
256
+ Returns:
257
+ float: The maximum strength at failure of concrete.
258
+ """
259
+ self._eps_cu1 = self._eps_cu1 or ec2_2004.eps_cu1(self.fcm)
260
+ return self._eps_cu1
261
+
262
+ @eps_cu1.setter
263
+ def eps_cu1(self, value: float):
264
+ """Sets the nominal ultimate strain for Sargin constitutive law.
265
+
266
+ Arguments:
267
+ value (float): The new value for eps_cu1, no units.
268
+ """
269
+ if abs(value) >= 0.1:
270
+ warnings.warn(
271
+ 'A suspect value is input for eps_cu1 that should be a pure'
272
+ ' number without units. Plase check ({value} given).'
273
+ )
274
+ self._eps_cu1 = value
275
+
276
+ @property
277
+ def k_sargin(self) -> float:
278
+ """Returns the coefficient for Sargin constitutive law.
279
+
280
+ Returns:
281
+ float: The plastic coefficient for Sargin law.
282
+ """
283
+ self._k_sargin = self._k_sargin or ec2_2004.k_sargin(
284
+ Ecm=self.Ecm,
285
+ fcm=self.fcm,
286
+ eps_c1=self.eps_c1,
287
+ )
288
+ return self._k_sargin
289
+
290
+ @k_sargin.setter
291
+ def k_sargin(self, value: float):
292
+ """Sets the the coefficient for Sargin constitutive law.
293
+
294
+ Arguments:
295
+ value (float): The new value for k, no units.
296
+
297
+ Raises:
298
+ ValueError: If value < 0.
299
+ """
300
+ if value < 0:
301
+ raise ValueError(f'n should be a positive value ({value} given)')
302
+ self._k_sargin = value
303
+
304
+ @property
305
+ def eps_c2(self) -> float:
306
+ """Returns the strain at maximum compressive strength of concrete (fcd)
307
+ for the Parabola-rectangle constitutive law.
308
+
309
+ Returns:
310
+ float: The strain at maximum compressive strength of concrete.
311
+ """
312
+ self._eps_c2 = self._eps_c2 or ec2_2004.eps_c2(self.fck)
313
+ return self._eps_c2
314
+
315
+ @eps_c2.setter
316
+ def eps_c2(self, value: float):
317
+ """Sets the strain at maximum compressive strength of concrete (fcd)
318
+ for the Parabola-rectangle constitutive law.
319
+
320
+ Arguments:
321
+ value (float): The new value for eps_c2, no units.
322
+ """
323
+ if abs(value) >= 0.1:
324
+ warnings.warn(
325
+ 'A suspect value is input for eps_c2 that should be a pure'
326
+ ' number without units. Plase check ({value} given).'
327
+ )
328
+ self._eps_c2 = value
329
+
330
+ @property
331
+ def eps_cu2(self) -> float:
332
+ """Returns the strain at concrete failure of concrete for the
333
+ Parabola-rectangle constitutive law.
334
+
335
+ Returns:
336
+ float: The maximum strain at failure of concrete.
337
+ """
338
+ self._eps_cu2 = self._eps_cu2 or ec2_2004.eps_cu2(self.fck)
339
+ return self._eps_cu2
340
+
341
+ @eps_cu2.setter
342
+ def eps_cu2(self, value: float):
343
+ """Sets the strain at concrete failure of concrete for the
344
+ Parabola-rectangle constitutive law.
345
+
346
+ Arguments:
347
+ value (float): The new value for eps_cu2, no units.
348
+ """
349
+ if abs(value) >= 0.1:
350
+ warnings.warn(
351
+ 'A suspect value is input for eps_cu2 that should be a pure'
352
+ ' number without units. Plase check ({value} given).'
353
+ )
354
+ self._eps_cu2 = value
355
+
356
+ @property
357
+ def n_parabolic_rectangular(self) -> float:
358
+ """Returns the coefficient for Parabola-rectangle constitutive law.
359
+
360
+ Returns:
361
+ float: The exponent for Parabola-rectangle law.
362
+ """
363
+ self._n_parabolic_rectangular = (
364
+ self._n_parabolic_rectangular
365
+ or ec2_2004.n_parabolic_rectangular(self.fck)
366
+ )
367
+ return self._n_parabolic_rectangular
368
+
369
+ @n_parabolic_rectangular.setter
370
+ def n_parabolic_rectangular(self, value: float):
371
+ """Sets the coefficient for Parabola-rectangle constitutive law.
372
+
373
+ Arguments:
374
+ value (float): The new value for n, no units.
375
+
376
+ Raises:
377
+ ValueError: If value < 0.
378
+ """
379
+ if value < 0:
380
+ raise ValueError(f'n should be a positive value ({value} given)')
381
+ if value >= 5:
382
+ warnings.warn(
383
+ 'A suspect value is input for eps_cu2 that should be a pure'
384
+ ' number without units. Plase check ({value} given).'
385
+ )
386
+ self._n_parabolic_rectangular = value
387
+
388
+ @property
389
+ def eps_c3(self) -> float:
390
+ """Returns the strain at maximum compressive strength of concrete (fcd)
391
+ for the Bi-linear constitutive law.
392
+
393
+ Returns:
394
+ float: The strain at maximum compressive strength of concrete.
395
+ """
396
+ self._eps_c3 = self._eps_c3 or ec2_2004.eps_c3(self.fck)
397
+ return self._eps_c3
398
+
399
+ @eps_c3.setter
400
+ def eps_c3(self, value: float):
401
+ """Sets the strain at maximum compressive strength of concrete (fcd)
402
+ for the Bi-linear constitutive law.
403
+
404
+ Arguments:
405
+ value (float): The new value for eps_c3, no units.
406
+ """
407
+ if abs(value) >= 0.1:
408
+ warnings.warn(
409
+ 'A suspect value is input for eps_c3 that should be a pure'
410
+ ' number without units. Plase check ({value} given).'
411
+ )
412
+ self._eps_c3 = value
413
+
414
+ @property
415
+ def eps_cu3(self) -> float:
416
+ """Returns the strain at concrete failure of concrete for the Bi-linear
417
+ constitutive law.
418
+
419
+ Returns:
420
+ float: The maximum strain at failure of concrete.
421
+ """
422
+ self._eps_cu3 = self._eps_cu3 or ec2_2004.eps_cu3(self.fck)
423
+ return self._eps_cu3
424
+
425
+ @eps_cu3.setter
426
+ def eps_cu3(self, value: float):
427
+ """Sets the strain at concrete failure of concrete for the Bi-linear
428
+ constitutive law.
429
+
430
+ Arguments:
431
+ value (float): The new value for eps_cu3, no units.
432
+ """
433
+ if abs(value) >= 0.1:
434
+ warnings.warn(
435
+ 'A suspect value is input for eps_cu3 that should be a pure'
436
+ ' number without units. Plase check ({value} given).'
437
+ )
438
+ self._eps_cu3 = value
439
+
440
+ def __elastic__(self) -> dict:
441
+ """Returns kwargs for creating an elastic constitutive law."""
442
+ return {'E': self.Ecm}
443
+
444
+ def __bilinearcompression__(self) -> dict:
445
+ """Returns kwargs for Bi-linear constitutive law."""
446
+ return {
447
+ 'fc': self.fcd(),
448
+ 'eps_c': self.eps_c3,
449
+ 'eps_cu': self.eps_cu3,
450
+ }
451
+
452
+ def __parabolarectangle__(self) -> dict:
453
+ """Returns kwargs for creating a parabola rectangle const law."""
454
+ return {
455
+ 'fc': self.fcd(),
456
+ 'eps_0': self.eps_c2,
457
+ 'eps_u': self.eps_cu2,
458
+ 'n': self.n_parabolic_rectangular,
459
+ }
460
+
461
+ def __sargin__(self) -> dict:
462
+ """Returns kwargs for creating a Sargin const law."""
463
+ return {
464
+ 'fc': self.fcd(),
465
+ 'eps_c1': self.eps_c1,
466
+ 'eps_cu1': self.eps_cu1,
467
+ 'k': self.k_sargin,
468
+ }
469
+
470
+ def __popovics__(self) -> dict:
471
+ """Returns kwargs for creating a Sargin const law."""
472
+ return {
473
+ 'fc': self.fcd(),
474
+ 'eps_c': self.eps_c1,
475
+ 'eps_cu': self.eps_cu1,
476
+ 'Ec': self.Ecm,
477
+ }