structuralcodes 0.4.0__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of structuralcodes might be problematic. Click here for more details.

Files changed (52) hide show
  1. structuralcodes/__init__.py +1 -1
  2. structuralcodes/codes/ec2_2004/__init__.py +2 -0
  3. structuralcodes/codes/ec2_2004/shear.py +44 -4
  4. structuralcodes/codes/mc2010/__init__.py +18 -0
  5. structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py +2 -2
  6. structuralcodes/codes/mc2010/_concrete_punching.py +300 -388
  7. structuralcodes/core/base.py +116 -5
  8. structuralcodes/geometry/__init__.py +2 -8
  9. structuralcodes/geometry/_circular.py +3 -10
  10. structuralcodes/geometry/_geometry.py +58 -114
  11. structuralcodes/geometry/_rectangular.py +3 -10
  12. structuralcodes/geometry/_reinforcement.py +9 -14
  13. structuralcodes/geometry/profiles/__init__.py +19 -0
  14. structuralcodes/geometry/profiles/_base_profile.py +305 -0
  15. structuralcodes/geometry/profiles/_common_functions.py +194 -0
  16. structuralcodes/geometry/profiles/_he.py +192 -0
  17. structuralcodes/geometry/profiles/_ipe.py +130 -0
  18. structuralcodes/geometry/profiles/_ipn.py +329 -0
  19. structuralcodes/geometry/profiles/_ub.py +264 -0
  20. structuralcodes/geometry/profiles/_ubp.py +227 -0
  21. structuralcodes/geometry/profiles/_uc.py +276 -0
  22. structuralcodes/geometry/profiles/_upn.py +315 -0
  23. structuralcodes/materials/__init__.py +2 -1
  24. structuralcodes/materials/basic/__init__.py +11 -0
  25. structuralcodes/materials/basic/_elastic.py +69 -0
  26. structuralcodes/materials/basic/_elasticplastic.py +92 -0
  27. structuralcodes/materials/basic/_generic.py +43 -0
  28. structuralcodes/materials/concrete/__init__.py +3 -0
  29. structuralcodes/materials/concrete/_concrete.py +10 -1
  30. structuralcodes/materials/concrete/_concreteEC2_2004.py +14 -0
  31. structuralcodes/materials/concrete/_concreteEC2_2023.py +14 -0
  32. structuralcodes/materials/concrete/_concreteMC2010.py +19 -0
  33. structuralcodes/materials/constitutive_laws/__init__.py +3 -0
  34. structuralcodes/materials/constitutive_laws/_elasticplastic.py +2 -2
  35. structuralcodes/materials/constitutive_laws/_initial_strain.py +130 -0
  36. structuralcodes/materials/reinforcement/__init__.py +6 -0
  37. structuralcodes/materials/reinforcement/_reinforcement.py +10 -1
  38. structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py +15 -1
  39. structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py +15 -1
  40. structuralcodes/materials/reinforcement/_reinforcementMC2010.py +15 -1
  41. structuralcodes/sections/_generic.py +53 -14
  42. structuralcodes/sections/_rc_utils.py +15 -5
  43. structuralcodes/sections/section_integrators/__init__.py +3 -1
  44. structuralcodes/sections/section_integrators/_fiber_integrator.py +19 -11
  45. structuralcodes/sections/section_integrators/_marin_integrator.py +25 -20
  46. {structuralcodes-0.4.0.dist-info → structuralcodes-0.6.0.dist-info}/METADATA +2 -2
  47. structuralcodes-0.6.0.dist-info/RECORD +77 -0
  48. structuralcodes/geometry/_steel_sections.py +0 -2155
  49. structuralcodes-0.4.0.dist-info/RECORD +0 -63
  50. /structuralcodes/{sections/section_integrators → core}/_marin_integration.py +0 -0
  51. {structuralcodes-0.4.0.dist-info → structuralcodes-0.6.0.dist-info}/WHEEL +0 -0
  52. {structuralcodes-0.4.0.dist-info → structuralcodes-0.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,92 @@
1
+ """A material class with elastic plastic properties."""
2
+
3
+ import typing as t
4
+
5
+ from ...core.base import Material
6
+ from ..constitutive_laws import create_constitutive_law
7
+
8
+
9
+ class ElasticPlasticMaterial(Material):
10
+ """A material class with elastic plastic properties."""
11
+
12
+ _E: float
13
+ _fy: float
14
+ _Eh: float
15
+ _eps_su: float
16
+
17
+ def __init__(
18
+ self,
19
+ E: float,
20
+ fy: float,
21
+ density: float,
22
+ Eh: float = 0,
23
+ eps_su: t.Optional[float] = None,
24
+ initial_strain: t.Optional[float] = None,
25
+ initial_stress: t.Optional[float] = None,
26
+ strain_compatibility: t.Optional[float] = None,
27
+ name: t.Optional[str] = None,
28
+ ):
29
+ """Initialize a material with an elastic plastic constitutive law.
30
+
31
+ Arguments:
32
+ E (float): The Young's modulus.
33
+ fy (float): The yield stress.
34
+ density (float): The density.
35
+ Eh (float, optional): The hardening modulus, default value 0.
36
+ eps_su (float, optional): The ultimate strain, default value None.
37
+ initial_strain (Optional[float]): Initial strain of the material.
38
+ initial_stress (Optional[float]): Initial stress of the material.
39
+ strain_compatibility (Optional[bool]): Only relevant if
40
+ initial_strain or initial_stress are different from zero. If
41
+ True, the material deforms with the geometry. If False, the
42
+ stress in the material upon loading is kept constant
43
+ corresponding to the initial strain.
44
+ name (str, optional): The name of the material, default value None.
45
+ """
46
+ super().__init__(
47
+ density=density,
48
+ initial_strain=initial_strain,
49
+ initial_stress=initial_stress,
50
+ strain_compatibility=strain_compatibility,
51
+ name=name if name else 'ElasticPlasticMaterial',
52
+ )
53
+ self._E = E
54
+ self._fy = fy
55
+ self._Eh = Eh
56
+ self._eps_su = eps_su
57
+
58
+ self._constitutive_law = create_constitutive_law(
59
+ 'elasticplastic', self
60
+ )
61
+ self._apply_initial_strain()
62
+
63
+ @property
64
+ def E(self) -> float:
65
+ """Returns the Young's modulus."""
66
+ return self._E
67
+
68
+ @property
69
+ def fy(self) -> float:
70
+ """Returns the yield stress."""
71
+ return self._fy
72
+
73
+ @property
74
+ def Eh(self) -> float:
75
+ """Returns the hardening modulus."""
76
+ return self._Eh
77
+
78
+ @property
79
+ def eps_su(self) -> float:
80
+ """Returns the ultimate strain."""
81
+ return self._eps_su
82
+
83
+ def __elasticplastic__(self) -> dict:
84
+ """Returns kwargs for ElasticPlastic constitutive law with strain
85
+ hardening.
86
+ """
87
+ return {
88
+ 'E': self.E,
89
+ 'fy': self.fy,
90
+ 'Eh': self.Eh,
91
+ 'eps_su': self.eps_su,
92
+ }
@@ -0,0 +1,43 @@
1
+ """A generic material that could hold any type of constitutive law."""
2
+
3
+ import typing as t
4
+
5
+ from ...core.base import ConstitutiveLaw, Material
6
+
7
+
8
+ class GenericMaterial(Material):
9
+ """A material class that accepts any constitutive law."""
10
+
11
+ def __init__(
12
+ self,
13
+ density: float,
14
+ constitutive_law: ConstitutiveLaw,
15
+ initial_strain: t.Optional[float] = None,
16
+ initial_stress: t.Optional[float] = None,
17
+ strain_compatibility: t.Optional[bool] = None,
18
+ name: t.Optional[str] = None,
19
+ ):
20
+ """Initialize a material with a constitutive law.
21
+
22
+ Arguments:
23
+ density (float): The density.
24
+ constitutive_law (ConstitutiveLaw): The constitutive law of the
25
+ material.
26
+ initial_strain (Optional[float]): Initial strain of the material.
27
+ initial_stress (Optional[float]): Initial stress of the material.
28
+ strain_compatibility (Optional[bool]): Only relevant if
29
+ initial_strain or initial_stress are different from zero. If
30
+ True, the material deforms with the geometry. If False, the
31
+ stress in the material upon loading is kept constant
32
+ corresponding to the initial strain.
33
+ name (str, optional): The name of the material, default value None.
34
+ """
35
+ super().__init__(
36
+ density=density,
37
+ initial_strain=initial_strain,
38
+ initial_stress=initial_stress,
39
+ strain_compatibility=strain_compatibility,
40
+ name=name if name else 'GenericMaterial',
41
+ )
42
+ self._constitutive_law = constitutive_law
43
+ self._apply_initial_strain()
@@ -49,6 +49,9 @@ def create_concrete(
49
49
  desired standard. If None (default) the globally used design
50
50
  standard will be adopted. Otherwise the design standard specified
51
51
  will be used for the instance of the material.
52
+ **kwargs: Other valid keyword arguments that are collected and passed
53
+ to the specific concrete material. Please inspect the documentation
54
+ of the other concrete materials to see valid arguments.
52
55
 
53
56
  Raises:
54
57
  ValueError: if the design code is not valid or does not cover concrete
@@ -21,10 +21,19 @@ class Concrete(Material):
21
21
  density: float = 2400,
22
22
  gamma_c: t.Optional[float] = None,
23
23
  existing: t.Optional[bool] = False,
24
+ initial_strain: t.Optional[float] = None,
25
+ initial_stress: t.Optional[float] = None,
26
+ strain_compatibility: t.Optional[bool] = None,
24
27
  ) -> None:
25
28
  """Initializes an abstract concrete material."""
26
29
  name = name if name is not None else 'Concrete'
27
- super().__init__(density=density, name=name)
30
+ super().__init__(
31
+ density=density,
32
+ initial_strain=initial_strain,
33
+ initial_stress=initial_stress,
34
+ strain_compatibility=strain_compatibility,
35
+ name=name,
36
+ )
28
37
 
29
38
  self._fck = abs(fck)
30
39
  if existing:
@@ -46,6 +46,9 @@ class ConcreteEC2_2004(Concrete): # noqa: N801
46
46
  ConstitutiveLaw,
47
47
  ]
48
48
  ] = 'parabolarectangle',
49
+ initial_strain: t.Optional[float] = None,
50
+ initial_stress: t.Optional[float] = None,
51
+ strain_compatibility: t.Optional[bool] = None,
49
52
  fcm: t.Optional[float] = None,
50
53
  fctm: t.Optional[float] = None,
51
54
  fctk_5: t.Optional[float] = None,
@@ -80,6 +83,13 @@ class ConcreteEC2_2004(Concrete): # noqa: N801
80
83
  law type for concrete. (valid options for string: 'elastic',
81
84
  'parabolarectangle', 'bilinearcompression', 'sargin',
82
85
  'popovics').
86
+ initial_strain (Optional[float]): Initial strain of the material.
87
+ initial_stress (Optional[float]): Initial stress of the material.
88
+ strain_compatibility (Optional[bool]): Only relevant if
89
+ initial_strain or initial_stress are different from zero. If
90
+ True, the material deforms with the geometry. If False, the
91
+ stress in the material upon loading is kept constant
92
+ corresponding to the initial strain.
83
93
  fcm (float, optional): The mean compressive strength.
84
94
  fctm (float, optional): The mean tensile strength.
85
95
  fctk_5 (float, optional): The 5% fractile for the tensile strength.
@@ -130,6 +140,9 @@ class ConcreteEC2_2004(Concrete): # noqa: N801
130
140
  density=density,
131
141
  existing=False,
132
142
  gamma_c=gamma_c,
143
+ initial_strain=initial_strain,
144
+ initial_stress=initial_stress,
145
+ strain_compatibility=strain_compatibility,
133
146
  )
134
147
  self._alpha_cc = alpha_cc
135
148
  self._fcm = abs(fcm) if fcm is not None else None
@@ -165,6 +178,7 @@ class ConcreteEC2_2004(Concrete): # noqa: N801
165
178
  raise ValueError(
166
179
  'The provided constitutive law is not valid for concrete.'
167
180
  )
181
+ self._apply_initial_strain()
168
182
 
169
183
  def __post_init__(self):
170
184
  """Validator for the attributes that are set in the constructor."""
@@ -48,6 +48,9 @@ class ConcreteEC2_2023(Concrete): # noqa: N801
48
48
  ConstitutiveLaw,
49
49
  ]
50
50
  ] = 'parabolarectangle',
51
+ initial_strain: t.Optional[float] = None,
52
+ initial_stress: t.Optional[float] = None,
53
+ strain_compatibility: t.Optional[bool] = None,
51
54
  fcm: t.Optional[float] = None,
52
55
  fctm: t.Optional[float] = None,
53
56
  fctk_5: t.Optional[float] = None,
@@ -80,6 +83,13 @@ class ConcreteEC2_2023(Concrete): # noqa: N801
80
83
  law type for concrete. (valid options for string: 'elastic',
81
84
  'parabolarectangle', 'bilinearcompression', 'sargin',
82
85
  'popovics').
86
+ initial_strain (Optional[float]): Initial strain of the material.
87
+ initial_stress (Optional[float]): Initial stress of the material.
88
+ strain_compatibility (Optional[bool]): Only relevant if
89
+ initial_strain or initial_stress are different from zero. If
90
+ True, the material deforms with the geometry. If False, the
91
+ stress in the material upon loading is kept constant
92
+ corresponding to the initial strain.
83
93
  fcm (float, optional): The mean compressive strength.
84
94
  fctm (float, optional): The mean tensile strength.
85
95
  fctk_5 (float, optional): The 5% fractile for the tensile strength.
@@ -124,6 +134,9 @@ class ConcreteEC2_2023(Concrete): # noqa: N801
124
134
  density=density,
125
135
  existing=False,
126
136
  gamma_c=gamma_c,
137
+ initial_strain=initial_strain,
138
+ initial_stress=initial_stress,
139
+ strain_compatibility=strain_compatibility,
127
140
  )
128
141
  self._kE = kE
129
142
  self._strength_dev_class = strength_dev_class.strip().lower()
@@ -158,6 +171,7 @@ class ConcreteEC2_2023(Concrete): # noqa: N801
158
171
  raise ValueError(
159
172
  'The provided constitutive law is not valid for concrete.'
160
173
  )
174
+ self._apply_initial_strain()
161
175
 
162
176
  def __post_init__(self):
163
177
  """Validator for the attributes that are set in the constructor."""
@@ -48,6 +48,9 @@ class ConcreteMC2010(Concrete):
48
48
  ConstitutiveLaw,
49
49
  ]
50
50
  ] = 'parabolarectangle',
51
+ initial_strain: t.Optional[float] = None,
52
+ initial_stress: t.Optional[float] = None,
53
+ strain_compatibility: t.Optional[bool] = None,
51
54
  fcm: t.Optional[float] = None,
52
55
  fctm: t.Optional[float] = None,
53
56
  fctkmin: t.Optional[float] = None,
@@ -77,6 +80,18 @@ class ConcreteMC2010(Concrete):
77
80
  alpha_cc (float, optional): A factor for considering long-term
78
81
  effects on the strength, and effects that arise from the way
79
82
  the load is applied.
83
+ consitutive_law (ConstitutiveLaw | str): A valid ConstitutiveLaw
84
+ object for concrete or a string defining a valid constitutive
85
+ law type for concrete. (valid options for string: 'elastic',
86
+ 'parabolarectangle', 'bilinearcompression', 'sargin',
87
+ 'popovics').
88
+ initial_strain (Optional[float]): Initial strain of the material.
89
+ initial_stress (Optional[float]): Initial stress of the material.
90
+ strain_compatibility (Optional[bool]): Only relevant if
91
+ initial_strain or initial_stress are different from zero. If
92
+ True, the material deforms with the geometry. If False, the
93
+ stress in the material upon loading is kept constant
94
+ corresponding to the initial strain.
80
95
  fcm (float, optional): The mean compressive strength.
81
96
  fctm (float, optional): The mean tensile strength.
82
97
  fctkmin (float, optional): The minimum tensile strength.
@@ -126,6 +141,9 @@ class ConcreteMC2010(Concrete):
126
141
  name=name,
127
142
  density=density,
128
143
  gamma_c=gamma_c,
144
+ initial_strain=initial_strain,
145
+ initial_stress=initial_stress,
146
+ strain_compatibility=strain_compatibility,
129
147
  )
130
148
  self._alpha_cc = alpha_cc
131
149
  self._fcm = abs(fcm) if fcm is not None else None
@@ -162,6 +180,7 @@ class ConcreteMC2010(Concrete):
162
180
  raise ValueError(
163
181
  'The provided constitutive law is not valid for concrete.'
164
182
  )
183
+ self._apply_initial_strain()
165
184
 
166
185
  def __post_init__(self):
167
186
  """Validator for the attributes that are set in the constructor."""
@@ -6,6 +6,7 @@ from ...core.base import ConstitutiveLaw, Material
6
6
  from ._bilinearcompression import BilinearCompression
7
7
  from ._elastic import Elastic
8
8
  from ._elasticplastic import ElasticPlastic
9
+ from ._initial_strain import InitialStrain
9
10
  from ._parabolarectangle import ParabolaRectangle
10
11
  from ._popovics import Popovics
11
12
  from ._sargin import Sargin
@@ -19,6 +20,7 @@ __all__ = [
19
20
  'Popovics',
20
21
  'Sargin',
21
22
  'UserDefined',
23
+ 'InitialStrain',
22
24
  'get_constitutive_laws_list',
23
25
  'create_constitutive_law',
24
26
  ]
@@ -31,6 +33,7 @@ CONSTITUTIVE_LAWS: t.Dict[str, ConstitutiveLaw] = {
31
33
  'parabolarectangle': ParabolaRectangle,
32
34
  'popovics': Popovics,
33
35
  'sargin': Sargin,
36
+ 'initialstrain': InitialStrain,
34
37
  }
35
38
 
36
39
 
@@ -34,8 +34,8 @@ class ElasticPlastic(ConstitutiveLaw):
34
34
 
35
35
  Keyword Arguments:
36
36
  Eh (float): The hardening modulus.
37
- eps_su (float): The ultimate strain.
38
- name (str): A descriptive name for the constitutive law.
37
+ eps_su (float, optional): The ultimate strain.
38
+ name (str, optional): A descriptive name for the constitutive law.
39
39
  """
40
40
  name = name if name is not None else 'ElasticPlasticLaw'
41
41
  super().__init__(name=name)
@@ -0,0 +1,130 @@
1
+ """Initial strain constitutive law."""
2
+
3
+ from __future__ import annotations # To have clean hints of ArrayLike in docs
4
+
5
+ import typing as t
6
+
7
+ import numpy as np
8
+ from numpy.typing import ArrayLike
9
+
10
+ from ...core.base import ConstitutiveLaw
11
+
12
+
13
+ class InitialStrain(ConstitutiveLaw):
14
+ """Class for initial strain Constitutive Law."""
15
+
16
+ _strain_compatibility: bool = True
17
+
18
+ __materials__: t.Tuple[str] = (
19
+ 'steel',
20
+ 'rebars',
21
+ 'concrete',
22
+ )
23
+
24
+ _wrapped_law: ConstitutiveLaw = None
25
+
26
+ def __init__(
27
+ self,
28
+ constitutive_law: ConstitutiveLaw,
29
+ initial_strain: float,
30
+ strain_compatibility: bool = True,
31
+ name: t.Optional[str] = None,
32
+ ) -> None:
33
+ """Initialize an Initial Strain Constitutive Law.
34
+
35
+ This constitutive law is a wrapper for another constitutive law
36
+ that assigns an initial strain.
37
+
38
+ Arguments:
39
+ constitutive_law (ConstitutiveLaw): Wrapped constitutive law.
40
+ initial_strain (float): The initial strain to be applied.
41
+ strain_compatibility (bool): If True, the strain compatibility is
42
+ enforced, otherwise the strain compatibility is released. This
43
+ is helpful for instance for modelling unbonded tendons.
44
+ Default value True.
45
+ """
46
+ name = name if name is not None else 'InitialStrainLaw'
47
+ super().__init__(name=name)
48
+ if not isinstance(constitutive_law, ConstitutiveLaw):
49
+ raise TypeError(
50
+ f'Expected a ConstitutiveLaw instance, '
51
+ f'got {type(constitutive_law)}'
52
+ )
53
+ self._wrapped_law = constitutive_law
54
+ self._initial_strain = initial_strain
55
+ self._initial_stress = self._wrapped_law.get_stress(initial_strain)
56
+ self._strain_compatibility = strain_compatibility
57
+
58
+ @property
59
+ def strain_compatibility(self) -> bool:
60
+ """Return the strain compatibility status."""
61
+ return self._strain_compatibility
62
+
63
+ @property
64
+ def wrapped_law(self) -> ConstitutiveLaw:
65
+ """Return the wrapped constitutive law."""
66
+ return self._wrapped_law
67
+
68
+ def get_stress(
69
+ self, eps: t.Union[float, ArrayLike]
70
+ ) -> t.Union[float, ArrayLike]:
71
+ """Return the stress given strain."""
72
+ stress = self._wrapped_law.get_stress(eps + self._initial_strain)
73
+ if not self._strain_compatibility:
74
+ # If strain compatibility is enforced, return initial stress
75
+ return np.ones_like(stress) * self._initial_stress
76
+ return stress
77
+
78
+ def get_tangent(
79
+ self, eps: t.Union[float, ArrayLike]
80
+ ) -> t.Union[float, ArrayLike]:
81
+ """Return the tangent for given strain."""
82
+ if not self._strain_compatibility:
83
+ return self._wrapped_law.get_tangent(0) * 1e-6
84
+ return self._wrapped_law.get_tangent(eps + self._initial_strain)
85
+
86
+ def __marin__(
87
+ self, strain: t.Tuple[float, float]
88
+ ) -> t.Tuple[t.List[t.Tuple], t.List[t.Tuple]]:
89
+ """Returns coefficients and strain limits for Marin integration in a
90
+ simply formatted way.
91
+
92
+ Arguments:
93
+ strain (float, float): Tuple defining the strain profile: eps =
94
+ strain[0] + strain[1]*y.
95
+
96
+ Example:
97
+ [(0, -0.002), (-0.002, -0.003)]
98
+ [(a0, a1, a2), (a0)]
99
+ """
100
+ return self._wrapped_law.__marin__(
101
+ strain=[strain[0] + self._initial_strain, strain[1]]
102
+ )
103
+
104
+ def __marin_tangent__(
105
+ self, strain: t.Tuple[float, float]
106
+ ) -> t.Tuple[t.List[t.Tuple], t.List[t.Tuple]]:
107
+ """Returns coefficients and strain limits for Marin integration of
108
+ tangent in a simply formatted way.
109
+
110
+ Arguments:
111
+ strain (float, float): Tuple defining the strain profile: eps =
112
+ strain[0] + strain[1]*y.
113
+
114
+ Example:
115
+ [(0, -0.002), (-0.002, -0.003)]
116
+ [(a0, a1, a2), (a0)]
117
+ """
118
+ return self._wrapped_law.__marin_tangent__(
119
+ strain=[strain[0] + self._initial_strain, strain[1]]
120
+ )
121
+
122
+ def get_ultimate_strain(
123
+ self, yielding: bool = False
124
+ ) -> t.Tuple[float, float]:
125
+ """Return the ultimate strain (negative and positive)."""
126
+ ult_strain = self._wrapped_law.get_ultimate_strain(yielding=yielding)
127
+ return (
128
+ ult_strain[0] - self._initial_strain,
129
+ ult_strain[1] - self._initial_strain,
130
+ )
@@ -33,6 +33,7 @@ def create_reinforcement(
33
33
  name: t.Optional[str] = None,
34
34
  density: float = 7850,
35
35
  design_code: t.Optional[str] = None,
36
+ **kwargs,
36
37
  ) -> t.Optional[Reinforcement]:
37
38
  """A factory function to create the correct type of reinforcement based on
38
39
  the desired design code.
@@ -50,6 +51,10 @@ def create_reinforcement(
50
51
  desired standard. If None (default) the globally used design
51
52
  standard will be adopted. Otherwise the design standard specified
52
53
  will be used for the instance of the material.
54
+ **kwargs: Other valid keyword arguments that are collected and passed
55
+ to the specific reinforcement material. Please inspect the
56
+ documentation of the other reinforcement materials to see valid
57
+ arguments.
53
58
 
54
59
  Raises:
55
60
  ValueError: If the design code is not valid or does not cover
@@ -80,5 +85,6 @@ def create_reinforcement(
80
85
  ftk=ftk,
81
86
  epsuk=epsuk,
82
87
  gamma_s=gamma_s,
88
+ **kwargs,
83
89
  )
84
90
  return None
@@ -24,10 +24,19 @@ class Reinforcement(Material):
24
24
  epsuk: float,
25
25
  gamma_s: t.Optional[float] = None,
26
26
  name: t.Optional[str] = None,
27
+ initial_strain: t.Optional[float] = None,
28
+ initial_stress: t.Optional[float] = None,
29
+ strain_compatibility: t.Optional[bool] = None,
27
30
  ) -> None:
28
31
  """Initializes an abstract reinforcement material."""
29
32
  name = name if name is not None else 'Reinforcement'
30
- super().__init__(density, name)
33
+ super().__init__(
34
+ density=density,
35
+ initial_strain=initial_strain,
36
+ initial_stress=initial_stress,
37
+ strain_compatibility=strain_compatibility,
38
+ name=name,
39
+ )
31
40
 
32
41
  self._fyk = abs(fyk)
33
42
  self._Es = abs(Es)
@@ -31,6 +31,9 @@ class ReinforcementEC2_2004(Reinforcement): # noqa: N801
31
31
  ConstitutiveLaw,
32
32
  ]
33
33
  ] = 'elasticplastic',
34
+ initial_strain: t.Optional[float] = None,
35
+ initial_stress: t.Optional[float] = None,
36
+ strain_compatibility: t.Optional[bool] = None,
34
37
  ):
35
38
  """Initializes a new instance of Reinforcement for EC2 2004.
36
39
 
@@ -53,6 +56,13 @@ class ReinforcementEC2_2004(Reinforcement): # noqa: N801
53
56
  constitutive law type for reinforcement. (valid options for
54
57
  string: 'elastic', 'elasticplastic', or
55
58
  'elasticperfectlyplastic').
59
+ initial_strain (Optional[float]): Initial strain of the material.
60
+ initial_stress (Optional[float]): Initial stress of the material.
61
+ strain_compatibility (Optional[bool]): Only relevant if
62
+ initial_strain or initial_stress are different from zero. If
63
+ True, the material deforms with the geometry. If False, the
64
+ stress in the material upon loading is kept constant
65
+ corresponding to the initial strain.
56
66
 
57
67
  Raises:
58
68
  ValueError: If the constitutive law name is not available for the
@@ -71,6 +81,9 @@ class ReinforcementEC2_2004(Reinforcement): # noqa: N801
71
81
  ftk=ftk,
72
82
  epsuk=epsuk,
73
83
  gamma_s=gamma_s,
84
+ initial_strain=initial_strain,
85
+ initial_stress=initial_stress,
86
+ strain_compatibility=strain_compatibility,
74
87
  )
75
88
  self._gamma_eps = gamma_eps
76
89
  self._constitutive_law = (
@@ -84,6 +97,7 @@ class ReinforcementEC2_2004(Reinforcement): # noqa: N801
84
97
  raise ValueError(
85
98
  'The provided constitutive law is not valid for reinforcement.'
86
99
  )
100
+ self._apply_initial_strain()
87
101
 
88
102
  def fyd(self) -> float:
89
103
  """The design yield strength."""
@@ -129,7 +143,7 @@ class ReinforcementEC2_2004(Reinforcement): # noqa: N801
129
143
  """Returns kwargs for ElasticPlastic constitutive law with strain
130
144
  hardening.
131
145
  """
132
- Eh = (self.ftd() - self.fyd()) / (self.epsuk - self.epsyd)
146
+ Eh = (self.ftd() - self.fyd()) / (self.epsud() - self.epsyd)
133
147
  return {
134
148
  'E': self.Es,
135
149
  'fy': self.fyd(),
@@ -30,6 +30,9 @@ class ReinforcementEC2_2023(Reinforcement): # noqa: N801
30
30
  ConstitutiveLaw,
31
31
  ]
32
32
  ] = 'elasticplastic',
33
+ initial_strain: t.Optional[float] = None,
34
+ initial_stress: t.Optional[float] = None,
35
+ strain_compatibility: t.Optional[bool] = None,
33
36
  ):
34
37
  """Initializes a new instance of Reinforcement for EC2 2023.
35
38
 
@@ -50,6 +53,13 @@ class ReinforcementEC2_2023(Reinforcement): # noqa: N801
50
53
  constitutive law type for reinforcement. (valid options for
51
54
  string: 'elastic', 'elasticplastic', or
52
55
  'elasticperfectlyplastic').
56
+ initial_strain (Optional[float]): Initial strain of the material.
57
+ initial_stress (Optional[float]): Initial stress of the material.
58
+ strain_compatibility (Optional[bool]): Only relevant if
59
+ initial_strain or initial_stress are different from zero. If
60
+ True, the material deforms with the geometry. If False, the
61
+ stress in the material upon loading is kept constant
62
+ corresponding to the initial strain.
53
63
 
54
64
  Raises:
55
65
  ValueError: If the constitutive law name is not available for the
@@ -67,6 +77,9 @@ class ReinforcementEC2_2023(Reinforcement): # noqa: N801
67
77
  ftk=ftk,
68
78
  epsuk=epsuk,
69
79
  gamma_s=gamma_s,
80
+ initial_strain=initial_strain,
81
+ initial_stress=initial_stress,
82
+ strain_compatibility=strain_compatibility,
70
83
  )
71
84
  self._constitutive_law = (
72
85
  constitutive_law
@@ -79,6 +92,7 @@ class ReinforcementEC2_2023(Reinforcement): # noqa: N801
79
92
  raise ValueError(
80
93
  'The provided constitutive law is not valid for reinforcement.'
81
94
  )
95
+ self._apply_initial_strain()
82
96
 
83
97
  def fyd(self) -> float:
84
98
  """The design yield strength."""
@@ -117,7 +131,7 @@ class ReinforcementEC2_2023(Reinforcement): # noqa: N801
117
131
  """Returns kwargs for ElasticPlastic constitutive law with strain
118
132
  hardening.
119
133
  """
120
- Eh = (self.ftd() - self.fyd()) / (self.epsuk - self.epsyd)
134
+ Eh = (self.ftd() - self.fyd()) / (self.epsud() - self.epsyd)
121
135
  return {
122
136
  'E': self.Es,
123
137
  'fy': self.fyd(),
@@ -31,6 +31,9 @@ class ReinforcementMC2010(Reinforcement):
31
31
  ConstitutiveLaw,
32
32
  ]
33
33
  ] = 'elasticplastic',
34
+ initial_strain: t.Optional[float] = None,
35
+ initial_stress: t.Optional[float] = None,
36
+ strain_compatibility: t.Optional[bool] = None,
34
37
  ):
35
38
  """Initializes a new instance of Reinforcement for MC2010.
36
39
 
@@ -53,6 +56,13 @@ class ReinforcementMC2010(Reinforcement):
53
56
  constitutive law type for reinforcement. (valid options for
54
57
  string: 'elastic', 'elasticplastic', or
55
58
  'elasticperfectlyplastic').
59
+ initial_strain (Optional[float]): Initial strain of the material.
60
+ initial_stress (Optional[float]): Initial stress of the material.
61
+ strain_compatibility (Optional[bool]): Only relevant if
62
+ initial_strain or initial_stress are different from zero. If
63
+ True, the material deforms with the geometry. If False, the
64
+ stress in the material upon loading is kept constant
65
+ corresponding to the initial strain.
56
66
 
57
67
  Raises:
58
68
  ValueError: If the constitutive law name is not available for the
@@ -71,6 +81,9 @@ class ReinforcementMC2010(Reinforcement):
71
81
  ftk=ftk,
72
82
  epsuk=epsuk,
73
83
  gamma_s=gamma_s,
84
+ initial_strain=initial_strain,
85
+ initial_stress=initial_stress,
86
+ strain_compatibility=strain_compatibility,
74
87
  )
75
88
  self._gamma_eps = gamma_eps
76
89
  self._constitutive_law = (
@@ -84,6 +97,7 @@ class ReinforcementMC2010(Reinforcement):
84
97
  raise ValueError(
85
98
  'The provided constitutive law is not valid for reinforcement.'
86
99
  )
100
+ self._apply_initial_strain()
87
101
 
88
102
  def fyd(self) -> float:
89
103
  """The design yield strength."""
@@ -125,7 +139,7 @@ class ReinforcementMC2010(Reinforcement):
125
139
  """Returns kwargs for ElasticPlastic constitutive law with strain
126
140
  hardening.
127
141
  """
128
- Eh = (self.ftd() - self.fyd()) / (self.epsuk - self.epsyd)
142
+ Eh = (self.ftd() - self.fyd()) / (self.epsud() - self.epsyd)
129
143
  return {
130
144
  'E': self.Es,
131
145
  'fy': self.fyd(),