structuralcodes 0.5.0__py3-none-any.whl → 0.6.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 (48) hide show
  1. structuralcodes/__init__.py +1 -1
  2. structuralcodes/codes/ec2_2004/shear.py +3 -2
  3. structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py +2 -2
  4. structuralcodes/core/base.py +138 -12
  5. structuralcodes/geometry/__init__.py +2 -8
  6. structuralcodes/geometry/_geometry.py +103 -19
  7. structuralcodes/geometry/_reinforcement.py +1 -3
  8. structuralcodes/geometry/profiles/__init__.py +33 -0
  9. structuralcodes/geometry/profiles/_base_profile.py +305 -0
  10. structuralcodes/geometry/profiles/_common_functions.py +307 -0
  11. structuralcodes/geometry/profiles/_hd.py +374 -0
  12. structuralcodes/geometry/profiles/_he.py +192 -0
  13. structuralcodes/geometry/profiles/_hp.py +319 -0
  14. structuralcodes/geometry/profiles/_ipe.py +130 -0
  15. structuralcodes/geometry/profiles/_ipn.py +329 -0
  16. structuralcodes/geometry/profiles/_l.py +528 -0
  17. structuralcodes/geometry/profiles/_li.py +217 -0
  18. structuralcodes/geometry/profiles/_u.py +173 -0
  19. structuralcodes/geometry/profiles/_ub.py +1356 -0
  20. structuralcodes/geometry/profiles/_ubp.py +227 -0
  21. structuralcodes/geometry/profiles/_uc.py +276 -0
  22. structuralcodes/geometry/profiles/_upe.py +133 -0
  23. structuralcodes/geometry/profiles/_upn.py +315 -0
  24. structuralcodes/geometry/profiles/_w.py +2157 -0
  25. structuralcodes/materials/basic/_elastic.py +18 -1
  26. structuralcodes/materials/basic/_elasticplastic.py +18 -1
  27. structuralcodes/materials/basic/_generic.py +18 -1
  28. structuralcodes/materials/concrete/__init__.py +3 -0
  29. structuralcodes/materials/concrete/_concrete.py +10 -1
  30. structuralcodes/materials/concrete/_concreteEC2_2004.py +15 -1
  31. structuralcodes/materials/concrete/_concreteEC2_2023.py +15 -1
  32. structuralcodes/materials/concrete/_concreteMC2010.py +20 -1
  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 +14 -0
  39. structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py +14 -0
  40. structuralcodes/materials/reinforcement/_reinforcementMC2010.py +14 -0
  41. structuralcodes/sections/section_integrators/__init__.py +3 -1
  42. structuralcodes/sections/section_integrators/_marin_integrator.py +1 -1
  43. {structuralcodes-0.5.0.dist-info → structuralcodes-0.6.1.dist-info}/METADATA +2 -2
  44. {structuralcodes-0.5.0.dist-info → structuralcodes-0.6.1.dist-info}/RECORD +47 -30
  45. structuralcodes/geometry/_steel_sections.py +0 -2155
  46. /structuralcodes/{sections/section_integrators → core}/_marin_integration.py +0 -0
  47. {structuralcodes-0.5.0.dist-info → structuralcodes-0.6.1.dist-info}/WHEEL +0 -0
  48. {structuralcodes-0.5.0.dist-info → structuralcodes-0.6.1.dist-info}/licenses/LICENSE +0 -0
@@ -15,6 +15,9 @@ class ElasticMaterial(Material):
15
15
  self,
16
16
  E: float,
17
17
  density: float,
18
+ initial_strain: t.Optional[float] = None,
19
+ initial_stress: t.Optional[float] = None,
20
+ strain_compatibility: t.Optional[float] = None,
18
21
  name: t.Optional[str] = None,
19
22
  ):
20
23
  """Initialize a material with an elastic plastic constitutive law.
@@ -22,11 +25,25 @@ class ElasticMaterial(Material):
22
25
  Arguments:
23
26
  E (float): The Young's modulus.
24
27
  density (float): The density.
28
+ initial_strain (Optional[float]): Initial strain of the material.
29
+ initial_stress (Optional[float]): Initial stress of the material.
30
+ strain_compatibility (Optional[bool]): Only relevant if
31
+ initial_strain or initial_stress are different from zero. If
32
+ True, the material deforms with the geometry. If False, the
33
+ stress in the material upon loading is kept constant
34
+ corresponding to the initial strain.
25
35
  name (str, optional): The name of the material, default value None.
26
36
  """
27
- super().__init__(density=density, name=name)
37
+ super().__init__(
38
+ density=density,
39
+ initial_strain=initial_strain,
40
+ initial_stress=initial_stress,
41
+ strain_compatibility=strain_compatibility,
42
+ name=name if name else 'ElasticMaterial',
43
+ )
28
44
  self._E = E
29
45
  self._constitutive_law = create_constitutive_law('elastic', self)
46
+ self._apply_initial_strain()
30
47
 
31
48
  @property
32
49
  def E(self) -> float:
@@ -21,6 +21,9 @@ class ElasticPlasticMaterial(Material):
21
21
  density: float,
22
22
  Eh: float = 0,
23
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,
24
27
  name: t.Optional[str] = None,
25
28
  ):
26
29
  """Initialize a material with an elastic plastic constitutive law.
@@ -31,9 +34,22 @@ class ElasticPlasticMaterial(Material):
31
34
  density (float): The density.
32
35
  Eh (float, optional): The hardening modulus, default value 0.
33
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.
34
44
  name (str, optional): The name of the material, default value None.
35
45
  """
36
- super().__init__(density=density, name=name)
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
+ )
37
53
  self._E = E
38
54
  self._fy = fy
39
55
  self._Eh = Eh
@@ -42,6 +58,7 @@ class ElasticPlasticMaterial(Material):
42
58
  self._constitutive_law = create_constitutive_law(
43
59
  'elasticplastic', self
44
60
  )
61
+ self._apply_initial_strain()
45
62
 
46
63
  @property
47
64
  def E(self) -> float:
@@ -12,6 +12,9 @@ class GenericMaterial(Material):
12
12
  self,
13
13
  density: float,
14
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,
15
18
  name: t.Optional[str] = None,
16
19
  ):
17
20
  """Initialize a material with a constitutive law.
@@ -20,7 +23,21 @@ class GenericMaterial(Material):
20
23
  density (float): The density.
21
24
  constitutive_law (ConstitutiveLaw): The constitutive law of the
22
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.
23
33
  name (str, optional): The name of the material, default value None.
24
34
  """
25
- super().__init__(density=density, name=name)
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
+ )
26
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."""
@@ -507,7 +521,7 @@ class ConcreteEC2_2004(Concrete): # noqa: N801
507
521
  def __sargin__(self) -> dict:
508
522
  """Returns kwargs for creating a Sargin const law."""
509
523
  return {
510
- 'fc': self.fcd(),
524
+ 'fc': self.fcm,
511
525
  'eps_c1': self.eps_c1,
512
526
  'eps_cu1': self.eps_cu1,
513
527
  'k': self.k_sargin,
@@ -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."""
@@ -477,7 +491,7 @@ class ConcreteEC2_2023(Concrete): # noqa: N801
477
491
  def __sargin__(self) -> dict:
478
492
  """Returns kwargs for creating a Sargin const law."""
479
493
  return {
480
- 'fc': self.fcd(),
494
+ 'fc': self.fcm,
481
495
  'eps_c1': self.eps_c1,
482
496
  'eps_cu1': self.eps_cu1,
483
497
  'k': self.k_sargin,
@@ -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."""
@@ -523,7 +542,7 @@ class ConcreteMC2010(Concrete):
523
542
  def __sargin__(self) -> dict:
524
543
  """Returns kwargs for creating a Sargin const law."""
525
544
  return {
526
- 'fc': self.fcd(),
545
+ 'fc': self.fcm,
527
546
  'eps_c1': self.eps_c1,
528
547
  'eps_cu1': self.eps_cu1,
529
548
  'k': self.k_sargin,
@@ -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."""
@@ -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."""
@@ -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."""
@@ -1,8 +1,10 @@
1
1
  """Classes for integrating the response of sections."""
2
2
 
3
+ from structuralcodes.core._marin_integration import marin_integration
4
+
3
5
  from ._factory import integrator_factory
4
6
  from ._fiber_integrator import FiberIntegrator
5
- from ._marin_integrator import MarinIntegrator, marin_integration
7
+ from ._marin_integrator import MarinIntegrator
6
8
  from ._section_integrator import SectionIntegrator
7
9
 
8
10
  __all__ = [
@@ -10,13 +10,13 @@ from numpy.typing import ArrayLike, NDArray
10
10
  from shapely import MultiLineString, MultiPolygon, Polygon
11
11
  from shapely.geometry.polygon import orient
12
12
 
13
+ from structuralcodes.core._marin_integration import marin_integration
13
14
  from structuralcodes.geometry import (
14
15
  CompoundGeometry,
15
16
  SurfaceGeometry,
16
17
  create_line_point_angle,
17
18
  )
18
19
 
19
- from ._marin_integration import marin_integration
20
20
  from ._section_integrator import SectionIntegrator
21
21
 
22
22