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,260 @@
1
+ """Abstract base classes."""
2
+
3
+ from __future__ import annotations # To have clean hints of ArrayLike in docs
4
+
5
+ import abc
6
+ import typing as t
7
+ import warnings
8
+
9
+ import numpy as np
10
+ from numpy.typing import ArrayLike
11
+
12
+ import structuralcodes.core._section_results as s_res
13
+
14
+
15
+ class Material(abc.ABC):
16
+ """Abstract base class for materials."""
17
+
18
+ _constitutive_law = None
19
+
20
+ def __init__(self, density: float, name: t.Optional[str] = None) -> None:
21
+ """Initializes an instance of a new material.
22
+
23
+ Args:
24
+ density (float): density of the material in kg/m3
25
+
26
+ Keyword Args:
27
+ name (Optional[str]): descriptive name of the material
28
+ """
29
+ self._density = abs(density)
30
+ self._name = name if name is not None else 'Material'
31
+
32
+ def update_attributes(self, updated_attributes: t.Dict) -> None:
33
+ """Function for updating the attributes specified in the input
34
+ dictionary.
35
+
36
+ Args:
37
+ updated_attributes (dict): the dictionary of parameters to be
38
+ updated (not found parameters are skipped with a warning)
39
+ """
40
+ for key, value in updated_attributes.items():
41
+ if not hasattr(self, '_' + key):
42
+ str_list_keys = ', '.join(updated_attributes.keys())
43
+ str_warn = (
44
+ f"WARNING: attribute '{key}' not found."
45
+ " Ignoring the entry.\n"
46
+ f"Used keys in the call: {str_list_keys}"
47
+ )
48
+ warnings.warn(str_warn)
49
+ continue
50
+ setattr(self, '_' + key, value)
51
+
52
+ @property
53
+ def constitutive_law(self):
54
+ """Returns the ConstitutiveLaw of the object."""
55
+ return self._constitutive_law
56
+
57
+ @property
58
+ def name(self):
59
+ """Returns the name of the material."""
60
+ return self._name
61
+
62
+ @property
63
+ def density(self):
64
+ """Returns the density of the material in kg/m3."""
65
+ return self._density
66
+
67
+
68
+ class ConstitutiveLaw(abc.ABC):
69
+ """Abstract base class for constitutive laws."""
70
+
71
+ __materials__: t.Tuple[str] = ()
72
+ constitutive_law_counter: t.ClassVar[int] = 0
73
+
74
+ def __init__(self, name: t.Optional[str] = None) -> None:
75
+ """Initialize a ConstitutiveLaw object."""
76
+ self.id = self.constitutive_law_counter
77
+ self._name = name if name is not None else f'ConstitutiveLaw_{self.id}'
78
+ self._increase_global_counter()
79
+
80
+ @property
81
+ def name(self):
82
+ """Returns the name of the constitutive law."""
83
+ return self._name
84
+
85
+ @classmethod
86
+ def _increase_global_counter(cls):
87
+ cls.constitutive_law_counter += 1
88
+
89
+ @abc.abstractmethod
90
+ def get_stress(self, eps: ArrayLike) -> ArrayLike:
91
+ """Each constitutive law should provide a method to return the
92
+ stress given the strain level.
93
+ """
94
+
95
+ @abc.abstractmethod
96
+ def get_tangent(self, eps: ArrayLike) -> ArrayLike:
97
+ """Each constitutive law should provide a method to return the
98
+ tangent at a given strain level.
99
+ """
100
+
101
+ @abc.abstractmethod
102
+ def get_ultimate_strain(self) -> t.Tuple[float, float]:
103
+ """Each constitutive law should provide a method to return the
104
+ ultimate strain (positive and negative).
105
+ """
106
+
107
+ def preprocess_strains_with_limits(self, eps: ArrayLike) -> ArrayLike:
108
+ """Preprocess strain arrays setting those strains sufficiently
109
+ near to ultimate strain limits to exactly ultimate strain limit.
110
+ """
111
+ eps = np.atleast_1d(np.asarray(eps))
112
+ eps_max, eps_min = self.get_ultimate_strain()
113
+
114
+ idxs = np.isclose(eps, np.zeros_like(eps) + eps_max, atol=1e-6)
115
+ eps[idxs] = eps_max
116
+ idxs = np.isclose(eps, np.zeros_like(eps) + eps_min, atol=1e-6)
117
+ eps[idxs] = eps_min
118
+
119
+ return eps
120
+
121
+ def __marin__(self, **kwargs):
122
+ """Function for getting the strain limits and coefficients
123
+ for marin integration.
124
+
125
+ By default the law is discretized as a piecewise linear
126
+ function. Then marin coefficients are computed based on this
127
+ discretization.
128
+ """
129
+
130
+ # Discretize the constitutive law in a "smart way"
131
+ def find_x_lim(x, y):
132
+ # Check if there are non-zero values for x > 0
133
+ if np.any(y[0:] != 0):
134
+ # Find the last non-zero index for x > 0
135
+ non_zero_indices = np.nonzero(y[0:])[0]
136
+ x_lim_index = 0 + non_zero_indices[-1]
137
+ return x[x_lim_index]
138
+ # All values are zero for x > 0
139
+ return None
140
+
141
+ eps_max, eps_min = self.get_ultimate_strain()
142
+ eps_max = min(eps_max, 1)
143
+ # Analise positive branch
144
+ eps = np.linspace(0, eps_max, 10000)
145
+ sig = self.get_stress(eps)
146
+ sig[(sig < np.max(sig) * 1e-6)] = 0
147
+ eps_lim = find_x_lim(eps, sig)
148
+ # Now discretize the function in 10 steps for positive part
149
+ eps_pos = (
150
+ np.linspace(0, -eps_min, 1)
151
+ if eps_lim is None
152
+ else np.linspace(0, eps_lim, 10)
153
+ )
154
+ # Analise negative branch
155
+ eps = np.linspace(0, eps_min, 10000)
156
+ sig = -self.get_stress(eps)
157
+ sig[(sig < np.max(sig) * 1e-6)] = 0
158
+ eps_lim = find_x_lim(-eps, sig)
159
+ # Now discretize the function in 10 steps for negative part
160
+ eps_neg = (
161
+ np.linspace(eps_min, 0, 1, endpoint=False)
162
+ if eps_lim is None
163
+ else np.linspace(-eps_lim, 0, 10, endpoint=False)
164
+ )
165
+
166
+ eps = np.concatenate((eps_neg, eps_pos))
167
+ sig = self.get_stress(eps)
168
+ from structuralcodes.materials.constitutive_laws import UserDefined
169
+
170
+ # Return Marin coefficients for linearized version
171
+ return UserDefined(eps, sig).__marin__(**kwargs)
172
+
173
+ def get_secant(self, eps: float) -> float:
174
+ """Method to return the
175
+ secant at a given strain level.
176
+ """
177
+ if eps != 0:
178
+ sig = self.get_stress(eps)
179
+ return sig / eps
180
+ return self.get_tangent(eps)
181
+
182
+
183
+ class Section(abc.ABC):
184
+ """Abstract base class for a cross secion.
185
+ The section is defined by local axes y and z (mapped to x and y cartesian
186
+ plane respectively).
187
+ """
188
+
189
+ section_counter: t.ClassVar[int] = 0
190
+
191
+ def __init__(self, name: t.Optional[str] = None) -> None:
192
+ """Initialize a Section object."""
193
+ self.id = self.section_counter
194
+ self._name = name if name is not None else f'Section_{self.id}'
195
+ self._increase_global_counter()
196
+
197
+ @property
198
+ def name(self):
199
+ """Returns the name of the section."""
200
+ return self._name
201
+
202
+ @classmethod
203
+ def _increase_global_counter(cls):
204
+ cls.section_counter += 1
205
+
206
+
207
+ class SectionCalculator(abc.ABC):
208
+ """Abstract class for SectionCalculators
209
+ defining the interface.
210
+ """
211
+
212
+ def __init__(self, section: Section) -> None:
213
+ """Initialization of SectionCalculator object, providing
214
+ a Section object.
215
+ """
216
+ self.section = section
217
+
218
+ @abc.abstractmethod
219
+ def _calculate_gross_section_properties(self) -> s_res.GrossProperties:
220
+ """Calculates the gross section properties of the section
221
+ This function is private and called when the section is created
222
+ It stores the result into the result object.
223
+
224
+ Returns:
225
+ gross_section_properties (GrossSection)
226
+ """
227
+
228
+ @abc.abstractmethod
229
+ def calculate_bending_strength(
230
+ self, theta=0, n=0
231
+ ) -> s_res.UltimateBendingMomentResults:
232
+ """Calculates the bending strength for given inclination of n.a.
233
+ and axial load.
234
+
235
+ Input:
236
+ theta (float, default = 0): inclination of n.a. respect to y axis
237
+ n (float, default = 0): axial load applied to the section (+: tension,
238
+ -: compression)
239
+
240
+ Return:
241
+ ultimate_bending_moment_result (UltimateBendingMomentResult)
242
+ """
243
+
244
+ @abc.abstractmethod
245
+ def calculate_moment_curvature(
246
+ self, theta=0, n=0
247
+ ) -> s_res.MomentCurvatureResults:
248
+ """Calculates the moment-curvature relation for given inclination of
249
+ n.a. and axial load.
250
+
251
+ Input:
252
+ theta (float, default = 0): inclination of n.a. respect to y axis
253
+ n (float, default = 0): axial load applied to the section
254
+ (+: tension, -: compression)
255
+ chi_incr (float, default = 1e-8): the curvature increment for the
256
+ analysis
257
+
258
+ Return:
259
+ moment_curvature_result (MomentCurvatureResults)
260
+ """
@@ -0,0 +1,25 @@
1
+ """Main entry point for geometry."""
2
+
3
+ from ._geometry import (
4
+ CompoundGeometry,
5
+ Geometry,
6
+ PointGeometry,
7
+ SurfaceGeometry,
8
+ create_line_point_angle,
9
+ )
10
+ from ._steel_sections import HE, IPE, IPN, UB, UBP, UC, UPN
11
+
12
+ __all__ = [
13
+ 'Geometry',
14
+ 'PointGeometry',
15
+ 'SurfaceGeometry',
16
+ 'CompoundGeometry',
17
+ 'create_line_point_angle',
18
+ 'IPE',
19
+ 'HE',
20
+ 'UB',
21
+ 'UC',
22
+ 'UBP',
23
+ 'IPN',
24
+ 'UPN',
25
+ ]