structuralcodes 0.0.2__tar.gz → 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of structuralcodes might be problematic. Click here for more details.
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/PKG-INFO +10 -2
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/README.md +9 -1
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/__init__.py +1 -1
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/__init__.py +29 -6
- structuralcodes-0.1.0/structuralcodes/codes/mc2020/__init__.py +7 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/core/_section_results.py +67 -17
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/core/base.py +3 -3
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/geometry/__init__.py +3 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/geometry/_geometry.py +51 -37
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/geometry/_steel_sections.py +2 -2
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/constitutive_laws.py +36 -34
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/sections/__init__.py +0 -3
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/sections/_generic.py +28 -20
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/pyproject.toml +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2004/__init__.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2004/_concrete_material_properties.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2004/_reinforcement_material_properties.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2004/_section_7_3_crack_control.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2004/annex_b_shrink_and_creep.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2004/shear.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2023/__init__.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2023/_annexB_time_dependent.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2023/_section5_materials.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2023/_section9_sls.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/__init__.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_interface_different_casting_times.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_material_properties.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_punching.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_shear.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_torsion.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_reinforcement_material_properties.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/core/__init__.py +0 -0
- {structuralcodes-0.0.2/structuralcodes/sections → structuralcodes-0.1.0/structuralcodes/geometry}/_reinforcement.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/__init__.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/concrete/__init__.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/concrete/_concrete.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/concrete/_concreteEC2_2004.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/concrete/_concreteEC2_2023.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/concrete/_concreteMC2010.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/reinforcement/__init__.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/reinforcement/_reinforcement.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/reinforcement/_reinforcementMC2010.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/sections/section_integrators/__init__.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/sections/section_integrators/_factory.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/sections/section_integrators/_fiber_integrator.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/sections/section_integrators/_marin_integration.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/sections/section_integrators/_marin_integrator.py +0 -0
- {structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/sections/section_integrators/_section_integrator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: structuralcodes
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: A Python package that contains models from structural design codes.
|
|
5
5
|
Author-email: fib - International Federation for Structural Concrete <info@fib-international.org>
|
|
6
6
|
Requires-Python: >=3.8
|
|
@@ -17,11 +17,15 @@ Project-URL: source, https://github.com/fib-international/structuralcodes
|
|
|
17
17
|
|
|
18
18
|
*A Python library for structural engineering calculations.*
|
|
19
19
|
|
|
20
|
-
[](https://badge.fury.io/py/structuralcodes)
|
|
21
21
|
[](https://github.com/charliermarsh/ruff)
|
|
22
22
|
[](https://github.com/charliermarsh/ruff)
|
|
23
23
|
[](https://fib-international.github.io/structuralcodes/)
|
|
24
24
|
|
|
25
|
+
[](https://github.com/fib-international/structuralcodes/actions/workflows/build.yaml)
|
|
26
|
+
[](https://github.com/fib-international/structuralcodes/actions/workflows/create-release.yml)
|
|
27
|
+
[](https://github.com/fib-international/structuralcodes/actions/workflows/sphinx.yml)
|
|
28
|
+
|
|
25
29
|
## How to install
|
|
26
30
|
|
|
27
31
|
StructuralCodes is available on PyPI and can be installed using `pip`:
|
|
@@ -38,3 +42,7 @@ Read the [quickstart guide](https://fib-international.github.io/structuralcodes/
|
|
|
38
42
|
|
|
39
43
|
Check out our docs for how to get started [contributing](https://fib-international.github.io/structuralcodes/contributing/) to StructuralCodes.
|
|
40
44
|
|
|
45
|
+
## Versioning
|
|
46
|
+
|
|
47
|
+
Check out our docs to see how we handle [versioning](https://fib-international.github.io/structuralcodes/versioning/).
|
|
48
|
+
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
*A Python library for structural engineering calculations.*
|
|
4
4
|
|
|
5
|
-
[](https://badge.fury.io/py/structuralcodes)
|
|
6
6
|
[](https://github.com/charliermarsh/ruff)
|
|
7
7
|
[](https://github.com/charliermarsh/ruff)
|
|
8
8
|
[](https://fib-international.github.io/structuralcodes/)
|
|
9
9
|
|
|
10
|
+
[](https://github.com/fib-international/structuralcodes/actions/workflows/build.yaml)
|
|
11
|
+
[](https://github.com/fib-international/structuralcodes/actions/workflows/create-release.yml)
|
|
12
|
+
[](https://github.com/fib-international/structuralcodes/actions/workflows/sphinx.yml)
|
|
13
|
+
|
|
10
14
|
## How to install
|
|
11
15
|
|
|
12
16
|
StructuralCodes is available on PyPI and can be installed using `pip`:
|
|
@@ -22,3 +26,7 @@ Read the [quickstart guide](https://fib-international.github.io/structuralcodes/
|
|
|
22
26
|
## Contribution guidelines
|
|
23
27
|
|
|
24
28
|
Check out our docs for how to get started [contributing](https://fib-international.github.io/structuralcodes/contributing/) to StructuralCodes.
|
|
29
|
+
|
|
30
|
+
## Versioning
|
|
31
|
+
|
|
32
|
+
Check out our docs to see how we handle [versioning](https://fib-international.github.io/structuralcodes/versioning/).
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
import types
|
|
4
4
|
import typing as t
|
|
5
5
|
|
|
6
|
-
from . import ec2_2004, ec2_2023, mc2010
|
|
6
|
+
from . import ec2_2004, ec2_2023, mc2010, mc2020
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
9
|
'mc2010',
|
|
10
|
+
'mc2020',
|
|
10
11
|
'ec2_2023',
|
|
11
12
|
'ec2_2004',
|
|
12
13
|
'set_design_code',
|
|
@@ -23,25 +24,43 @@ _NATIONAL_ANNEX: t.Optional[str] = None
|
|
|
23
24
|
# Design code registry
|
|
24
25
|
_DESIGN_CODES = {
|
|
25
26
|
'mc2010': mc2010,
|
|
27
|
+
'mc2020': mc2020,
|
|
26
28
|
'ec2_2004': ec2_2004,
|
|
27
29
|
'ec2_2023': ec2_2023,
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
|
|
31
|
-
def set_design_code(
|
|
33
|
+
def set_design_code(
|
|
34
|
+
design_code: t.Optional[t.Union[str, types.ModuleType]] = None,
|
|
35
|
+
) -> None:
|
|
32
36
|
"""Set the current design code globally.
|
|
33
37
|
|
|
34
38
|
Args:
|
|
35
|
-
design_code (str): The abbreviation of the code
|
|
39
|
+
design_code (Union[str, Moduletype]): The abbreviation of the code
|
|
40
|
+
(str), or a module that represents the code (ModuleType).
|
|
36
41
|
|
|
37
42
|
Note:
|
|
38
43
|
Call get_design_codes() to get a list of the available codes.
|
|
39
44
|
"""
|
|
40
45
|
global _CODE # pylint: disable=W0603
|
|
41
|
-
if design_code is
|
|
46
|
+
if design_code is None:
|
|
47
|
+
# Reset to None
|
|
48
|
+
_CODE = None
|
|
49
|
+
elif isinstance(design_code, str) and design_code.lower() in _DESIGN_CODES:
|
|
50
|
+
# The design code abbreviation is valid
|
|
42
51
|
_CODE = _DESIGN_CODES.get(design_code.lower())
|
|
52
|
+
elif isinstance(design_code, types.ModuleType) and all(
|
|
53
|
+
name in dir(design_code)
|
|
54
|
+
for name in ('__title__', '__year__', '__materials__')
|
|
55
|
+
):
|
|
56
|
+
# The module is a valid design code
|
|
57
|
+
_CODE = design_code
|
|
43
58
|
else:
|
|
44
|
-
|
|
59
|
+
raise ValueError(
|
|
60
|
+
f'{design_code} is not a valid abbreviation for a design code, or'
|
|
61
|
+
' a valid module representing a design code.\nType '
|
|
62
|
+
'get_design_codes() to list the available design codes.'
|
|
63
|
+
)
|
|
45
64
|
|
|
46
65
|
|
|
47
66
|
def get_design_codes() -> t.List[str]:
|
|
@@ -75,5 +94,9 @@ def _use_design_code(
|
|
|
75
94
|
Call get_design_codes() to get a list of the available codes.
|
|
76
95
|
"""
|
|
77
96
|
if design_code is None:
|
|
97
|
+
# Returned the globally set design code
|
|
78
98
|
return _CODE
|
|
79
|
-
|
|
99
|
+
|
|
100
|
+
# Set design code before returning
|
|
101
|
+
set_design_code(design_code)
|
|
102
|
+
return _CODE
|
|
@@ -175,37 +175,87 @@ class UltimateBendingMomentResults:
|
|
|
175
175
|
|
|
176
176
|
|
|
177
177
|
@dataclass
|
|
178
|
-
class
|
|
178
|
+
class InteractionDomain:
|
|
179
|
+
"""Class for storing common data on all interaction domain results.
|
|
180
|
+
|
|
181
|
+
Attributes:
|
|
182
|
+
strains (numpy.Array): A numpy array with shape (n, 3) containing ea,
|
|
183
|
+
ky and kz.
|
|
184
|
+
forces (numpy.Array): A numpy array with shape (n, 3) containing n, my
|
|
185
|
+
and mz.
|
|
186
|
+
field_num (numpy.Array): a numpy array with shape (n,) containing a
|
|
187
|
+
number between 1 and 6 indicating the failure field.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
# array with shape (n,3) containing ea, ky, kz:
|
|
191
|
+
strains: ArrayLike = None
|
|
192
|
+
# array with shape(n,3) containing N, My, Mz
|
|
193
|
+
forces: ArrayLike = None
|
|
194
|
+
# array with shape(n,) containing the field number from 1 to 6
|
|
195
|
+
field_num: ArrayLike = None
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def n(self):
|
|
199
|
+
"""Return axial force."""
|
|
200
|
+
if self.forces is None:
|
|
201
|
+
return None
|
|
202
|
+
return self.forces[:, 0]
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def m_y(self):
|
|
206
|
+
"""Return my."""
|
|
207
|
+
if self.forces is None:
|
|
208
|
+
return None
|
|
209
|
+
return self.forces[:, 1]
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def m_z(self):
|
|
213
|
+
"""Return mz."""
|
|
214
|
+
if self.forces is None:
|
|
215
|
+
return None
|
|
216
|
+
return self.forces[:, 2]
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def e_a(self):
|
|
220
|
+
"""Return ea."""
|
|
221
|
+
if self.strains is None:
|
|
222
|
+
return None
|
|
223
|
+
return self.strains[:, 0]
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def k_y(self):
|
|
227
|
+
"""Return ky."""
|
|
228
|
+
if self.strains is None:
|
|
229
|
+
return None
|
|
230
|
+
return self.strains[:, 1]
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def k_z(self):
|
|
234
|
+
"""Return kz."""
|
|
235
|
+
if self.strains is None:
|
|
236
|
+
return None
|
|
237
|
+
return self.strains[:, 2]
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@dataclass
|
|
241
|
+
class NMMInteractionDomain(InteractionDomain):
|
|
179
242
|
"""Class for storing the NMM interaction domain results."""
|
|
180
243
|
|
|
181
244
|
num_theta: int = 0 # number of discretizations along the angle
|
|
182
245
|
num_axial: int = 0 # number of discretizations along axial load axis
|
|
183
246
|
|
|
184
|
-
strains: ArrayLike = None # array with shape (n,3) containing strains
|
|
185
|
-
forces: ArrayLike = None # array with shape(n,3) containing N, My, Mz
|
|
186
|
-
|
|
187
247
|
|
|
188
248
|
@dataclass
|
|
189
|
-
class NMInteractionDomain:
|
|
249
|
+
class NMInteractionDomain(InteractionDomain):
|
|
190
250
|
"""Class for storing the NM interaction domain results."""
|
|
191
251
|
|
|
192
252
|
theta: float = 0 # the inclination of n.a.
|
|
193
253
|
num_axial: float = 0 # number of discretizations along axial load axis
|
|
194
254
|
|
|
195
|
-
n: ArrayLike = None # Axial loads
|
|
196
|
-
m_y: ArrayLike = None # Moments My
|
|
197
|
-
m_z: ArrayLike = None # Moments Mz
|
|
198
|
-
|
|
199
|
-
strains: ArrayLike = None
|
|
200
|
-
|
|
201
255
|
|
|
202
256
|
@dataclass
|
|
203
|
-
class MMInteractionDomain:
|
|
257
|
+
class MMInteractionDomain(InteractionDomain):
|
|
204
258
|
"""Class for storing the MM interaction domain results."""
|
|
205
259
|
|
|
206
260
|
num_theta: float = 0 # number of discretizations along the angle
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
theta: ArrayLike = None # Angle theta respect axis Y
|
|
210
|
-
m_y: ArrayLike = None # Moments My
|
|
211
|
-
m_z: ArrayLike = None # Moments Mz
|
|
261
|
+
theta: ArrayLike = None # Array with shape (n,) containing the angle of NA
|
|
@@ -101,7 +101,7 @@ class ConstitutiveLaw(abc.ABC):
|
|
|
101
101
|
@abc.abstractmethod
|
|
102
102
|
def get_ultimate_strain(self) -> t.Tuple[float, float]:
|
|
103
103
|
"""Each constitutive law should provide a method to return the
|
|
104
|
-
ultimate strain (
|
|
104
|
+
ultimate strain (negative and positive).
|
|
105
105
|
"""
|
|
106
106
|
|
|
107
107
|
def preprocess_strains_with_limits(self, eps: ArrayLike) -> ArrayLike:
|
|
@@ -109,7 +109,7 @@ class ConstitutiveLaw(abc.ABC):
|
|
|
109
109
|
near to ultimate strain limits to exactly ultimate strain limit.
|
|
110
110
|
"""
|
|
111
111
|
eps = np.atleast_1d(np.asarray(eps))
|
|
112
|
-
|
|
112
|
+
eps_min, eps_max = self.get_ultimate_strain()
|
|
113
113
|
|
|
114
114
|
idxs = np.isclose(eps, np.zeros_like(eps) + eps_max, atol=1e-6)
|
|
115
115
|
eps[idxs] = eps_max
|
|
@@ -138,7 +138,7 @@ class ConstitutiveLaw(abc.ABC):
|
|
|
138
138
|
# All values are zero for x > 0
|
|
139
139
|
return None
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
eps_min, eps_max = self.get_ultimate_strain()
|
|
142
142
|
eps_max = min(eps_max, 1)
|
|
143
143
|
# Analise positive branch
|
|
144
144
|
eps = np.linspace(0, eps_max, 10000)
|
|
@@ -7,6 +7,7 @@ from ._geometry import (
|
|
|
7
7
|
SurfaceGeometry,
|
|
8
8
|
create_line_point_angle,
|
|
9
9
|
)
|
|
10
|
+
from ._reinforcement import add_reinforcement, add_reinforcement_line
|
|
10
11
|
from ._steel_sections import HE, IPE, IPN, UB, UBP, UC, UPN
|
|
11
12
|
|
|
12
13
|
__all__ = [
|
|
@@ -22,4 +23,6 @@ __all__ = [
|
|
|
22
23
|
'UBP',
|
|
23
24
|
'IPN',
|
|
24
25
|
'UPN',
|
|
26
|
+
'add_reinforcement',
|
|
27
|
+
'add_reinforcement_line',
|
|
25
28
|
]
|
|
@@ -22,17 +22,6 @@ from structuralcodes.core.base import ConstitutiveLaw, Material
|
|
|
22
22
|
from structuralcodes.materials.concrete import Concrete
|
|
23
23
|
from structuralcodes.materials.constitutive_laws import Elastic
|
|
24
24
|
|
|
25
|
-
# Useful classes and functions: where to put?????? (core?
|
|
26
|
-
# utility folder in sections? here in this file?)
|
|
27
|
-
# Polygons, LineStrings, Points, MultiLyneStrings, MultiPolygons etc.
|
|
28
|
-
|
|
29
|
-
# to think: dataclass or class?
|
|
30
|
-
# Note that some things are already computed (like area) by shapely
|
|
31
|
-
# like: polygon.area, polygon.centroid, etc.
|
|
32
|
-
|
|
33
|
-
# For now dataclass, if we need convert to regular class,
|
|
34
|
-
# init commented for now
|
|
35
|
-
|
|
36
25
|
|
|
37
26
|
class Geometry:
|
|
38
27
|
"""Base class for a geometry object."""
|
|
@@ -154,11 +143,12 @@ class PointGeometry(Geometry):
|
|
|
154
143
|
self._density = density
|
|
155
144
|
if isinstance(material, Material):
|
|
156
145
|
self._density = material.density
|
|
157
|
-
|
|
146
|
+
self._material = material.constitutive_law
|
|
147
|
+
elif isinstance(material, ConstitutiveLaw):
|
|
148
|
+
self._material = material
|
|
158
149
|
|
|
159
150
|
self._point = point
|
|
160
151
|
self._diameter = diameter
|
|
161
|
-
self._material = material
|
|
162
152
|
self._area = np.pi * diameter**2 / 4.0
|
|
163
153
|
|
|
164
154
|
@property
|
|
@@ -172,7 +162,7 @@ class PointGeometry(Geometry):
|
|
|
172
162
|
return self._area
|
|
173
163
|
|
|
174
164
|
@property
|
|
175
|
-
def material(self) ->
|
|
165
|
+
def material(self) -> ConstitutiveLaw:
|
|
176
166
|
"""Returns the point material."""
|
|
177
167
|
return self._material
|
|
178
168
|
|
|
@@ -341,10 +331,12 @@ class SurfaceGeometry:
|
|
|
341
331
|
holes.
|
|
342
332
|
"""
|
|
343
333
|
|
|
334
|
+
_material: ConstitutiveLaw
|
|
335
|
+
|
|
344
336
|
def __init__(
|
|
345
337
|
self,
|
|
346
338
|
poly: Polygon,
|
|
347
|
-
|
|
339
|
+
material: t.Union[Material, ConstitutiveLaw],
|
|
348
340
|
density: t.Optional[float] = None,
|
|
349
341
|
concrete: bool = False,
|
|
350
342
|
) -> None:
|
|
@@ -352,7 +344,7 @@ class SurfaceGeometry:
|
|
|
352
344
|
|
|
353
345
|
Arguments:
|
|
354
346
|
poly (shapely.Polygon): A Shapely polygon.
|
|
355
|
-
|
|
347
|
+
material (Union(Material, ConstitutiveLaw)): A Material or
|
|
356
348
|
ConsitutiveLaw class applied to the geometry.
|
|
357
349
|
density (Optional(float)): When a ConstitutiveLaw is passed as mat,
|
|
358
350
|
the density can be provided by this argument. When mat is a
|
|
@@ -365,25 +357,25 @@ class SurfaceGeometry:
|
|
|
365
357
|
f'poly need to be a valid shapely.geometry.Polygon object. \
|
|
366
358
|
{repr(poly)}'
|
|
367
359
|
)
|
|
368
|
-
if not isinstance(
|
|
369
|
-
|
|
360
|
+
if not isinstance(material, Material) and not isinstance(
|
|
361
|
+
material, ConstitutiveLaw
|
|
370
362
|
):
|
|
371
363
|
raise TypeError(
|
|
372
364
|
f'mat should be a valid structuralcodes.base.Material \
|
|
373
365
|
or structuralcodes.base.ConstitutiveLaw object. \
|
|
374
|
-
{repr(
|
|
366
|
+
{repr(material)}'
|
|
375
367
|
)
|
|
376
|
-
self.
|
|
368
|
+
self._polygon = poly
|
|
377
369
|
# Pass a constitutive law to the SurfaceGeometry
|
|
378
370
|
self._density = density
|
|
379
|
-
if isinstance(
|
|
380
|
-
self._density =
|
|
381
|
-
if isinstance(
|
|
371
|
+
if isinstance(material, Material):
|
|
372
|
+
self._density = material.density
|
|
373
|
+
if isinstance(material, Concrete):
|
|
382
374
|
concrete = True
|
|
383
|
-
|
|
375
|
+
material = material.constitutive_law
|
|
384
376
|
|
|
385
|
-
self.
|
|
386
|
-
self.
|
|
377
|
+
self._material = material
|
|
378
|
+
self._concrete = concrete
|
|
387
379
|
|
|
388
380
|
@property
|
|
389
381
|
def area(self) -> float:
|
|
@@ -408,6 +400,21 @@ class SurfaceGeometry:
|
|
|
408
400
|
"""Returns the density."""
|
|
409
401
|
return self._density
|
|
410
402
|
|
|
403
|
+
@property
|
|
404
|
+
def material(self) -> ConstitutiveLaw:
|
|
405
|
+
"""Returns the Constitutive law."""
|
|
406
|
+
return self._material
|
|
407
|
+
|
|
408
|
+
@property
|
|
409
|
+
def concrete(self) -> bool:
|
|
410
|
+
"""Returns true if the geometry material is Concrete."""
|
|
411
|
+
return self._concrete
|
|
412
|
+
|
|
413
|
+
@property
|
|
414
|
+
def polygon(self) -> Polygon:
|
|
415
|
+
"""Returns the Shapely Polygon."""
|
|
416
|
+
return self._polygon
|
|
417
|
+
|
|
411
418
|
def calculate_extents(self) -> t.Tuple[float, float, float, float]:
|
|
412
419
|
"""Calculate extents of SurfaceGeometry.
|
|
413
420
|
|
|
@@ -528,7 +535,9 @@ class SurfaceGeometry:
|
|
|
528
535
|
for g in other.geometries:
|
|
529
536
|
sub_polygon = sub_polygon - g.polygon
|
|
530
537
|
|
|
531
|
-
return SurfaceGeometry(
|
|
538
|
+
return SurfaceGeometry(
|
|
539
|
+
poly=sub_polygon, material=material, density=density
|
|
540
|
+
)
|
|
532
541
|
|
|
533
542
|
def _repr_svg_(self) -> str:
|
|
534
543
|
"""Returns the svg representation."""
|
|
@@ -546,7 +555,7 @@ class SurfaceGeometry:
|
|
|
546
555
|
"""
|
|
547
556
|
return SurfaceGeometry(
|
|
548
557
|
poly=affinity.translate(self.polygon, dx, dy),
|
|
549
|
-
|
|
558
|
+
material=self.material,
|
|
550
559
|
density=self._density,
|
|
551
560
|
)
|
|
552
561
|
|
|
@@ -573,7 +582,7 @@ class SurfaceGeometry:
|
|
|
573
582
|
poly=affinity.rotate(
|
|
574
583
|
self.polygon, angle, origin=point, use_radians=use_radians
|
|
575
584
|
),
|
|
576
|
-
|
|
585
|
+
material=self.material,
|
|
577
586
|
density=self._density,
|
|
578
587
|
)
|
|
579
588
|
|
|
@@ -616,7 +625,7 @@ class SurfaceGeometry:
|
|
|
616
625
|
new_material = Elastic(E=geo.material.get_tangent(eps=0)[0])
|
|
617
626
|
|
|
618
627
|
return SurfaceGeometry(
|
|
619
|
-
poly=geo.polygon,
|
|
628
|
+
poly=geo.polygon, material=new_material, density=geo._density
|
|
620
629
|
)
|
|
621
630
|
|
|
622
631
|
# here we can also add static methods like:
|
|
@@ -635,13 +644,15 @@ def _process_geometries_multipolygon(
|
|
|
635
644
|
materials: t.Optional[
|
|
636
645
|
t.Union[t.List[Material], Material, ConstitutiveLaw]
|
|
637
646
|
],
|
|
638
|
-
) -> list:
|
|
647
|
+
) -> list[Geometry]:
|
|
639
648
|
"""Process geometries for initialization."""
|
|
640
649
|
checked_geometries = []
|
|
641
650
|
# a MultiPolygon is provided
|
|
642
651
|
if isinstance(materials, (ConstitutiveLaw, Material)):
|
|
643
652
|
for g in geometries.geoms:
|
|
644
|
-
checked_geometries.append(
|
|
653
|
+
checked_geometries.append(
|
|
654
|
+
SurfaceGeometry(poly=g, material=materials)
|
|
655
|
+
)
|
|
645
656
|
elif isinstance(materials, list):
|
|
646
657
|
# the list of materials is provided, one for each polygon
|
|
647
658
|
if len(geometries.geoms) != len(materials):
|
|
@@ -649,13 +660,13 @@ def _process_geometries_multipolygon(
|
|
|
649
660
|
'geometries and materials should have the same length'
|
|
650
661
|
)
|
|
651
662
|
for g, m in zip(geometries.geoms, materials):
|
|
652
|
-
checked_geometries.append(SurfaceGeometry(poly=g,
|
|
663
|
+
checked_geometries.append(SurfaceGeometry(poly=g, material=m))
|
|
653
664
|
return checked_geometries
|
|
654
665
|
|
|
655
666
|
|
|
656
667
|
def _process_geometries_list(
|
|
657
668
|
geometries: t.List[Geometry],
|
|
658
|
-
) -> t.Tuple[list, list]:
|
|
669
|
+
) -> t.Tuple[list[SurfaceGeometry], list[PointGeometry]]:
|
|
659
670
|
"""Process geometries for initialization."""
|
|
660
671
|
# a list of SurfaceGeometry is provided
|
|
661
672
|
checked_geometries = []
|
|
@@ -680,6 +691,8 @@ class CompoundGeometry(Geometry):
|
|
|
680
691
|
properties.
|
|
681
692
|
"""
|
|
682
693
|
|
|
694
|
+
geometries: t.List[Geometry]
|
|
695
|
+
|
|
683
696
|
def __init__(
|
|
684
697
|
self,
|
|
685
698
|
geometries: t.Union[t.List[Geometry], MultiPolygon],
|
|
@@ -689,8 +702,9 @@ class CompoundGeometry(Geometry):
|
|
|
689
702
|
|
|
690
703
|
Arguments:
|
|
691
704
|
geometries (Union(List(Geometry), MultiPolygon)): A list of
|
|
692
|
-
|
|
693
|
-
(in this case also a list of
|
|
705
|
+
Geometry objects (i.e. PointGeometry or SurfaceGeometry) or a
|
|
706
|
+
shapely MultiPolygon object (in this latter case also a list of
|
|
707
|
+
materials should be given).
|
|
694
708
|
materials (Optional(List(Material), Material)): A material (applied
|
|
695
709
|
to all polygons) or a list of materials. In this case the
|
|
696
710
|
number of polygons should match the number of materials.
|
|
@@ -712,7 +726,7 @@ class CompoundGeometry(Geometry):
|
|
|
712
726
|
# useful for representation in svg
|
|
713
727
|
geoms_representation = [g.polygon for g in self.geometries]
|
|
714
728
|
geoms_representation += [
|
|
715
|
-
pg.
|
|
729
|
+
pg.point.buffer(pg.diameter / 2)
|
|
716
730
|
for pg in self.point_geometries
|
|
717
731
|
]
|
|
718
732
|
self.geom = MultiPolygon(geoms_representation)
|
|
@@ -228,8 +228,8 @@ class BaseProfile:
|
|
|
228
228
|
xmax = max(abs(bounds[0]), bounds[2])
|
|
229
229
|
ymax = max(abs(bounds[1]), bounds[3])
|
|
230
230
|
# Then compute section modulus
|
|
231
|
-
self._Wely = self.
|
|
232
|
-
self._Welz = self.
|
|
231
|
+
self._Wely = self.Iy / ymax
|
|
232
|
+
self._Welz = self.Iz / xmax
|
|
233
233
|
|
|
234
234
|
@property
|
|
235
235
|
def Wely(self) -> float:
|
{structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/constitutive_laws.py
RENAMED
|
@@ -64,11 +64,11 @@ class Elastic(ConstitutiveLaw):
|
|
|
64
64
|
return strains, coeff
|
|
65
65
|
|
|
66
66
|
def get_ultimate_strain(self, **kwargs) -> t.Tuple[float, float]:
|
|
67
|
-
"""Return the ultimate strain (
|
|
67
|
+
"""Return the ultimate strain (negative and positive)."""
|
|
68
68
|
# There is no real strain limit, so set it to very large values
|
|
69
69
|
# unlesse specified by the user differently
|
|
70
70
|
del kwargs
|
|
71
|
-
return self._eps_su or (100,
|
|
71
|
+
return self._eps_su or (-100, 100)
|
|
72
72
|
|
|
73
73
|
def set_ultimate_strain(
|
|
74
74
|
self, eps_su=t.Union[float, t.Tuple[float, float]]
|
|
@@ -76,19 +76,20 @@ class Elastic(ConstitutiveLaw):
|
|
|
76
76
|
"""Set ultimate strains for Elastic Material if needed.
|
|
77
77
|
|
|
78
78
|
Arguments:
|
|
79
|
-
eps_su (float or (float, float)): Defining ultimate strain
|
|
80
|
-
single value is provided the same is adopted for both
|
|
81
|
-
and
|
|
79
|
+
eps_su (float or (float, float)): Defining ultimate strain. If a
|
|
80
|
+
single value is provided the same is adopted for both negative
|
|
81
|
+
and positive strains. If a tuple is provided, it should be
|
|
82
|
+
given as (negative, positive).
|
|
82
83
|
"""
|
|
83
84
|
if isinstance(eps_su, float):
|
|
84
|
-
self._eps_su = (abs(eps_su),
|
|
85
|
+
self._eps_su = (-abs(eps_su), abs(eps_su))
|
|
85
86
|
elif isinstance(eps_su, tuple):
|
|
86
87
|
if len(eps_su) < 2:
|
|
87
88
|
raise ValueError(
|
|
88
89
|
'Two values need to be provided when setting the tuple'
|
|
89
90
|
)
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
eps_su_n = eps_su[0]
|
|
92
|
+
eps_su_p = eps_su[1]
|
|
92
93
|
if eps_su_p < eps_su_n:
|
|
93
94
|
eps_su_p, eps_su_n = eps_su_n, eps_su_p
|
|
94
95
|
if eps_su_p < 0:
|
|
@@ -99,7 +100,7 @@ class Elastic(ConstitutiveLaw):
|
|
|
99
100
|
raise ValueError(
|
|
100
101
|
'Negative utimate strain should be non-positive'
|
|
101
102
|
)
|
|
102
|
-
self._eps_su = (
|
|
103
|
+
self._eps_su = (eps_su_n, eps_su_p)
|
|
103
104
|
else:
|
|
104
105
|
raise ValueError(
|
|
105
106
|
'set_ultimate_strain requires a single value or a tuple \
|
|
@@ -185,8 +186,8 @@ class ElasticPlastic(ConstitutiveLaw):
|
|
|
185
186
|
"""
|
|
186
187
|
strains = []
|
|
187
188
|
coeff = []
|
|
188
|
-
|
|
189
|
-
|
|
189
|
+
eps_sy_n, eps_sy_p = self.get_ultimate_strain(yielding=True)
|
|
190
|
+
eps_su_n, eps_su_p = self.get_ultimate_strain()
|
|
190
191
|
if strain[1] == 0:
|
|
191
192
|
# Uniform strain equal to strain[0]
|
|
192
193
|
# Understand in which branch are we
|
|
@@ -233,13 +234,13 @@ class ElasticPlastic(ConstitutiveLaw):
|
|
|
233
234
|
def get_ultimate_strain(
|
|
234
235
|
self, yielding: bool = False
|
|
235
236
|
) -> t.Tuple[float, float]:
|
|
236
|
-
"""Return the ultimate strain (
|
|
237
|
+
"""Return the ultimate strain (negative and positive)."""
|
|
237
238
|
if yielding:
|
|
238
|
-
return (self._eps_sy,
|
|
239
|
+
return (-self._eps_sy, self._eps_sy)
|
|
239
240
|
# If not specified eps
|
|
240
241
|
if self._eps_su is None:
|
|
241
|
-
return (self._eps_sy * 2,
|
|
242
|
-
return (self._eps_su,
|
|
242
|
+
return (-self._eps_sy * 2, self._eps_sy * 2)
|
|
243
|
+
return (-self._eps_su, self._eps_su)
|
|
243
244
|
|
|
244
245
|
|
|
245
246
|
class ParabolaRectangle(ConstitutiveLaw):
|
|
@@ -399,10 +400,10 @@ class ParabolaRectangle(ConstitutiveLaw):
|
|
|
399
400
|
def get_ultimate_strain(
|
|
400
401
|
self, yielding: bool = False
|
|
401
402
|
) -> t.Tuple[float, float]:
|
|
402
|
-
"""Return the ultimate strain (
|
|
403
|
+
"""Return the ultimate strain (negative and positive)."""
|
|
403
404
|
if yielding:
|
|
404
|
-
return (
|
|
405
|
-
return (
|
|
405
|
+
return (self._eps_0, 100)
|
|
406
|
+
return (self._eps_u, 100)
|
|
406
407
|
|
|
407
408
|
|
|
408
409
|
class BilinearCompression(ConstitutiveLaw):
|
|
@@ -509,10 +510,10 @@ class BilinearCompression(ConstitutiveLaw):
|
|
|
509
510
|
def get_ultimate_strain(
|
|
510
511
|
self, yielding: bool = False
|
|
511
512
|
) -> t.Tuple[float, float]:
|
|
512
|
-
"""Return the ultimate strain (
|
|
513
|
+
"""Return the ultimate strain (negative and positive)."""
|
|
513
514
|
if yielding:
|
|
514
|
-
return (
|
|
515
|
-
return (
|
|
515
|
+
return (self._eps_c, 100)
|
|
516
|
+
return (self._eps_cu, 100)
|
|
516
517
|
|
|
517
518
|
|
|
518
519
|
class Sargin(ConstitutiveLaw):
|
|
@@ -602,10 +603,10 @@ class Sargin(ConstitutiveLaw):
|
|
|
602
603
|
def get_ultimate_strain(
|
|
603
604
|
self, yielding: bool = False
|
|
604
605
|
) -> t.Tuple[float, float]:
|
|
605
|
-
"""Return the ultimate strain (
|
|
606
|
+
"""Return the ultimate strain (negative and positive)."""
|
|
606
607
|
if yielding:
|
|
607
|
-
return (
|
|
608
|
-
return (
|
|
608
|
+
return (self._eps_c1, 100)
|
|
609
|
+
return (self._eps_cu1, 100)
|
|
609
610
|
|
|
610
611
|
|
|
611
612
|
class Popovics(ConstitutiveLaw):
|
|
@@ -713,10 +714,10 @@ class Popovics(ConstitutiveLaw):
|
|
|
713
714
|
def get_ultimate_strain(
|
|
714
715
|
self, yielding: bool = False
|
|
715
716
|
) -> t.Tuple[float, float]:
|
|
716
|
-
"""Return the ultimate strain (
|
|
717
|
+
"""Return the ultimate strain (negative and positive)."""
|
|
717
718
|
if yielding:
|
|
718
|
-
return (
|
|
719
|
-
return (
|
|
719
|
+
return (self._eps_c, 100)
|
|
720
|
+
return (self._eps_cu, 100)
|
|
720
721
|
|
|
721
722
|
|
|
722
723
|
class UserDefined(ConstitutiveLaw):
|
|
@@ -875,9 +876,9 @@ class UserDefined(ConstitutiveLaw):
|
|
|
875
876
|
return strains, coeff
|
|
876
877
|
|
|
877
878
|
def get_ultimate_strain(self, **kwargs) -> t.Tuple[float, float]:
|
|
878
|
-
"""Return the ultimate strain (
|
|
879
|
+
"""Return the ultimate strain (negative and positive)."""
|
|
879
880
|
del kwargs
|
|
880
|
-
return (self.
|
|
881
|
+
return (self._ultimate_strain_n, self._ultimate_strain_p)
|
|
881
882
|
|
|
882
883
|
def set_ultimate_strain(
|
|
883
884
|
self, eps_su=t.Union[float, t.Tuple[float, float]]
|
|
@@ -885,9 +886,10 @@ class UserDefined(ConstitutiveLaw):
|
|
|
885
886
|
"""Set ultimate strains for Elastic Material if needed.
|
|
886
887
|
|
|
887
888
|
Arguments:
|
|
888
|
-
eps_su (float or (float, float)): Defining ultimate strain
|
|
889
|
-
single value is provided the same is adopted for both
|
|
890
|
-
and
|
|
889
|
+
eps_su (float or (float, float)): Defining ultimate strain. If a
|
|
890
|
+
single value is provided the same is adopted for both negative
|
|
891
|
+
and positive strains. If a tuple is provided, it should be
|
|
892
|
+
given as (negative, positive).
|
|
891
893
|
"""
|
|
892
894
|
if isinstance(eps_su, float):
|
|
893
895
|
self._ultimate_strain_p = abs(eps_su)
|
|
@@ -897,8 +899,8 @@ class UserDefined(ConstitutiveLaw):
|
|
|
897
899
|
raise ValueError(
|
|
898
900
|
'Two values need to be provided when setting the tuple'
|
|
899
901
|
)
|
|
900
|
-
|
|
901
|
-
|
|
902
|
+
eps_su_n = eps_su[0]
|
|
903
|
+
eps_su_p = eps_su[1]
|
|
902
904
|
if eps_su_p < eps_su_n:
|
|
903
905
|
eps_su_p, eps_su_n = eps_su_n, eps_su_p
|
|
904
906
|
if eps_su_p < 0:
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Main entry point for sections."""
|
|
2
2
|
|
|
3
3
|
from ._generic import GenericSection, GenericSectionCalculator
|
|
4
|
-
from ._reinforcement import add_reinforcement, add_reinforcement_line
|
|
5
4
|
from .section_integrators import (
|
|
6
5
|
FiberIntegrator,
|
|
7
6
|
MarinIntegrator,
|
|
@@ -13,8 +12,6 @@ from .section_integrators import (
|
|
|
13
12
|
__all__ = [
|
|
14
13
|
'GenericSection',
|
|
15
14
|
'GenericSectionCalculator',
|
|
16
|
-
'add_reinforcement',
|
|
17
|
-
'add_reinforcement_line',
|
|
18
15
|
'SectionIntegrator',
|
|
19
16
|
'FiberIntegrator',
|
|
20
17
|
'MarinIntegrator',
|
|
@@ -291,14 +291,14 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
291
291
|
for g in geom.geometries + geom.point_geometries:
|
|
292
292
|
for other_g in geom.geometries + geom.point_geometries:
|
|
293
293
|
# if g != other_g:
|
|
294
|
-
eps_p = g.material.get_ultimate_strain(yielding=yielding)[
|
|
294
|
+
eps_p = g.material.get_ultimate_strain(yielding=yielding)[1]
|
|
295
295
|
if isinstance(g, SurfaceGeometry):
|
|
296
296
|
y_p = g.polygon.bounds[1]
|
|
297
297
|
elif isinstance(g, PointGeometry):
|
|
298
298
|
y_p = g._point.coords[0][1]
|
|
299
299
|
eps_n = other_g.material.get_ultimate_strain(
|
|
300
300
|
yielding=yielding
|
|
301
|
-
)[
|
|
301
|
+
)[0]
|
|
302
302
|
if isinstance(other_g, SurfaceGeometry):
|
|
303
303
|
y_n = other_g.polygon.bounds[3]
|
|
304
304
|
elif isinstance(other_g, PointGeometry):
|
|
@@ -610,8 +610,8 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
610
610
|
axial load.
|
|
611
611
|
|
|
612
612
|
Arguments:
|
|
613
|
-
theta (float): Inclination of n.a. respect to section y axis
|
|
614
|
-
default = 0.
|
|
613
|
+
theta (float): Inclination of n.a. respect to section y axis in
|
|
614
|
+
radians, default = 0.
|
|
615
615
|
n (float): Axial load applied to the section (+: tension, -:
|
|
616
616
|
compression), default = 0.
|
|
617
617
|
|
|
@@ -667,7 +667,8 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
667
667
|
n.a. and axial load.
|
|
668
668
|
|
|
669
669
|
Arguments:
|
|
670
|
-
theta (float): Inclination of n.a. respect to y axis
|
|
670
|
+
theta (float): Inclination of n.a. respect to y axis in radians,
|
|
671
|
+
default = 0.
|
|
671
672
|
n (float): Axial load applied to the section (+: tension, -:
|
|
672
673
|
compression), default = 0.
|
|
673
674
|
chi_first (float): The first value of the curvature, default =
|
|
@@ -866,7 +867,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
866
867
|
"""Calculate the NM interaction domain.
|
|
867
868
|
|
|
868
869
|
Arguments:
|
|
869
|
-
theta (float): Inclination of n.a. respect to y axis
|
|
870
|
+
theta (float): Inclination of n.a. respect to y axis in radians
|
|
870
871
|
(Optional, default = 0).
|
|
871
872
|
num_1 (int): Number of strain profiles in field 1
|
|
872
873
|
(Optional, default = 1).
|
|
@@ -913,7 +914,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
913
914
|
)
|
|
914
915
|
|
|
915
916
|
# Get ultimate strain profiles for theta angle
|
|
916
|
-
strains = self._compute_ultimate_strain_profiles(
|
|
917
|
+
strains, field_num = self._compute_ultimate_strain_profiles(
|
|
917
918
|
theta=theta,
|
|
918
919
|
num_1=num_1,
|
|
919
920
|
num_2=num_2,
|
|
@@ -948,9 +949,8 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
948
949
|
|
|
949
950
|
# Save to results
|
|
950
951
|
res.strains = strains
|
|
951
|
-
res.
|
|
952
|
-
res.
|
|
953
|
-
res.n = forces[:, 0]
|
|
952
|
+
res.forces = forces
|
|
953
|
+
res.field_num = field_num
|
|
954
954
|
|
|
955
955
|
return res
|
|
956
956
|
|
|
@@ -1047,6 +1047,9 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
1047
1047
|
raise ValueError(f'Type of spacing not known: {type}')
|
|
1048
1048
|
|
|
1049
1049
|
# For generation of fields 1 and 2 pivot on positive strain
|
|
1050
|
+
field_num = np.repeat(
|
|
1051
|
+
[1, 2, 3, 4, 5, 6], [num_1, num_2, num_3, num_4, num_5, num_6]
|
|
1052
|
+
)
|
|
1050
1053
|
# Field 1: pivot on positive strain
|
|
1051
1054
|
eps_n = _np_space(eps_p_b, 0, num_1, type_1, endpoint=False)
|
|
1052
1055
|
eps_p = np.zeros_like(eps_n) + eps_p_b
|
|
@@ -1098,16 +1101,15 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
1098
1101
|
eps_n = np.append(eps_n, eps_n_6)
|
|
1099
1102
|
eps_p = np.append(eps_p, eps_p_6)
|
|
1100
1103
|
|
|
1101
|
-
#
|
|
1104
|
+
# compute strain components
|
|
1102
1105
|
kappa_y = (eps_n - eps_p) / (y_n - y_p)
|
|
1103
1106
|
eps_a = eps_n - kappa_y * y_n
|
|
1104
|
-
kappa_z = np.zeros_like(kappa_y)
|
|
1105
1107
|
|
|
1106
1108
|
# rotate back components to work in section CRS
|
|
1107
1109
|
T = np.array([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]])
|
|
1108
|
-
components = np.vstack((kappa_y,
|
|
1110
|
+
components = np.vstack((kappa_y, np.zeros_like(kappa_y)))
|
|
1109
1111
|
rotated_components = T @ components
|
|
1110
|
-
return np.column_stack((eps_a, rotated_components.T))
|
|
1112
|
+
return np.column_stack((eps_a, rotated_components.T)), field_num
|
|
1111
1113
|
|
|
1112
1114
|
def calculate_nmm_interaction_domain(
|
|
1113
1115
|
self,
|
|
@@ -1180,7 +1182,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
1180
1182
|
strains = np.empty((0, 3))
|
|
1181
1183
|
for theta in thetas:
|
|
1182
1184
|
# Get ultimate strain profiles for theta angle
|
|
1183
|
-
strain = self._compute_ultimate_strain_profiles(
|
|
1185
|
+
strain, field_num = self._compute_ultimate_strain_profiles(
|
|
1184
1186
|
theta=theta,
|
|
1185
1187
|
num_1=num_1,
|
|
1186
1188
|
num_2=num_2,
|
|
@@ -1216,6 +1218,7 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
1216
1218
|
# Save to results
|
|
1217
1219
|
res.strains = strains
|
|
1218
1220
|
res.forces = forces
|
|
1221
|
+
res.field_num = field_num
|
|
1219
1222
|
|
|
1220
1223
|
return res
|
|
1221
1224
|
|
|
@@ -1234,16 +1237,21 @@ class GenericSectionCalculator(SectionCalculator):
|
|
|
1234
1237
|
# Prepare the results
|
|
1235
1238
|
res = s_res.MMInteractionDomain()
|
|
1236
1239
|
res.num_theta = num_theta
|
|
1237
|
-
res.n = n
|
|
1238
1240
|
# Create array of thetas
|
|
1239
1241
|
res.theta = np.linspace(0, np.pi * 2, num_theta)
|
|
1240
1242
|
# Initialize the result's arrays
|
|
1241
|
-
res.
|
|
1242
|
-
res.
|
|
1243
|
+
res.forces = np.zeros((num_theta, 3))
|
|
1244
|
+
res.strains = np.zeros((num_theta, 3))
|
|
1243
1245
|
# Compute strength for given angle of NA
|
|
1244
1246
|
for i, th in enumerate(res.theta):
|
|
1245
1247
|
res_bend_strength = self.calculate_bending_strength(theta=th, n=n)
|
|
1246
|
-
|
|
1247
|
-
res.
|
|
1248
|
+
# Save forces
|
|
1249
|
+
res.forces[i, 0] = n
|
|
1250
|
+
res.forces[i, 1] = res_bend_strength.m_y
|
|
1251
|
+
res.forces[i, 2] = res_bend_strength.m_z
|
|
1252
|
+
# Save strains
|
|
1253
|
+
res.strains[i, 0] = res_bend_strength.eps_a
|
|
1254
|
+
res.strains[i, 1] = res_bend_strength.chi_y
|
|
1255
|
+
res.strains[i, 2] = res_bend_strength.chi_z
|
|
1248
1256
|
|
|
1249
1257
|
return res
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/ec2_2023/_section9_sls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_punching.py
RENAMED
|
File without changes
|
{structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_shear.py
RENAMED
|
File without changes
|
{structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/codes/mc2010/_concrete_torsion.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/concrete/__init__.py
RENAMED
|
File without changes
|
{structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/concrete/_concrete.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{structuralcodes-0.0.2 → structuralcodes-0.1.0}/structuralcodes/materials/reinforcement/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|