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.
- structuralcodes/__init__.py +1 -1
- structuralcodes/codes/ec2_2004/__init__.py +2 -0
- structuralcodes/codes/ec2_2004/shear.py +44 -4
- structuralcodes/codes/mc2010/__init__.py +18 -0
- structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py +2 -2
- structuralcodes/codes/mc2010/_concrete_punching.py +300 -388
- structuralcodes/core/base.py +116 -5
- structuralcodes/geometry/__init__.py +2 -8
- structuralcodes/geometry/_circular.py +3 -10
- structuralcodes/geometry/_geometry.py +58 -114
- structuralcodes/geometry/_rectangular.py +3 -10
- structuralcodes/geometry/_reinforcement.py +9 -14
- structuralcodes/geometry/profiles/__init__.py +19 -0
- structuralcodes/geometry/profiles/_base_profile.py +305 -0
- structuralcodes/geometry/profiles/_common_functions.py +194 -0
- structuralcodes/geometry/profiles/_he.py +192 -0
- structuralcodes/geometry/profiles/_ipe.py +130 -0
- structuralcodes/geometry/profiles/_ipn.py +329 -0
- structuralcodes/geometry/profiles/_ub.py +264 -0
- structuralcodes/geometry/profiles/_ubp.py +227 -0
- structuralcodes/geometry/profiles/_uc.py +276 -0
- structuralcodes/geometry/profiles/_upn.py +315 -0
- structuralcodes/materials/__init__.py +2 -1
- structuralcodes/materials/basic/__init__.py +11 -0
- structuralcodes/materials/basic/_elastic.py +69 -0
- structuralcodes/materials/basic/_elasticplastic.py +92 -0
- structuralcodes/materials/basic/_generic.py +43 -0
- structuralcodes/materials/concrete/__init__.py +3 -0
- structuralcodes/materials/concrete/_concrete.py +10 -1
- structuralcodes/materials/concrete/_concreteEC2_2004.py +14 -0
- structuralcodes/materials/concrete/_concreteEC2_2023.py +14 -0
- structuralcodes/materials/concrete/_concreteMC2010.py +19 -0
- structuralcodes/materials/constitutive_laws/__init__.py +3 -0
- structuralcodes/materials/constitutive_laws/_elasticplastic.py +2 -2
- structuralcodes/materials/constitutive_laws/_initial_strain.py +130 -0
- structuralcodes/materials/reinforcement/__init__.py +6 -0
- structuralcodes/materials/reinforcement/_reinforcement.py +10 -1
- structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py +15 -1
- structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py +15 -1
- structuralcodes/materials/reinforcement/_reinforcementMC2010.py +15 -1
- structuralcodes/sections/_generic.py +53 -14
- structuralcodes/sections/_rc_utils.py +15 -5
- structuralcodes/sections/section_integrators/__init__.py +3 -1
- structuralcodes/sections/section_integrators/_fiber_integrator.py +19 -11
- structuralcodes/sections/section_integrators/_marin_integrator.py +25 -20
- {structuralcodes-0.4.0.dist-info → structuralcodes-0.6.0.dist-info}/METADATA +2 -2
- structuralcodes-0.6.0.dist-info/RECORD +77 -0
- structuralcodes/geometry/_steel_sections.py +0 -2155
- structuralcodes-0.4.0.dist-info/RECORD +0 -63
- /structuralcodes/{sections/section_integrators → core}/_marin_integration.py +0 -0
- {structuralcodes-0.4.0.dist-info → structuralcodes-0.6.0.dist-info}/WHEEL +0 -0
- {structuralcodes-0.4.0.dist-info → structuralcodes-0.6.0.dist-info}/licenses/LICENSE +0 -0
structuralcodes/core/base.py
CHANGED
|
@@ -15,21 +15,48 @@ class Material(abc.ABC):
|
|
|
15
15
|
"""Abstract base class for materials."""
|
|
16
16
|
|
|
17
17
|
_constitutive_law = None
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
_initial_strain: t.Optional[float] = None
|
|
19
|
+
_initial_stress: t.Optional[float] = None
|
|
20
|
+
_strain_compatibility: t.Optional[bool] = None
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
density: float,
|
|
25
|
+
initial_strain: t.Optional[float] = None,
|
|
26
|
+
initial_stress: t.Optional[float] = None,
|
|
27
|
+
strain_compatibility: t.Optional[bool] = None,
|
|
28
|
+
name: t.Optional[str] = None,
|
|
29
|
+
) -> None:
|
|
20
30
|
"""Initializes an instance of a new material.
|
|
21
31
|
|
|
22
32
|
Args:
|
|
23
|
-
density (float):
|
|
33
|
+
density (float): Density of the material in kg/m3.
|
|
24
34
|
|
|
25
35
|
Keyword Args:
|
|
36
|
+
initial_strain (Optional[float]): Initial strain of the material.
|
|
37
|
+
initial_stress (Optional[float]): Initial stress of the material.
|
|
38
|
+
strain_compatibility (Optional[bool]): Only relevant if
|
|
39
|
+
initial_strain or initial_stress are different from zero. If
|
|
40
|
+
True, the material deforms with the geometry. If False, the
|
|
41
|
+
stress in the material upon loading is kept constant
|
|
42
|
+
corresponding to the initial strain.
|
|
26
43
|
name (Optional[str]): descriptive name of the material
|
|
44
|
+
|
|
45
|
+
Raise:
|
|
46
|
+
ValueError: if both initial_strain and initial_stress are provided
|
|
27
47
|
"""
|
|
28
48
|
self._density = abs(density)
|
|
49
|
+
if initial_strain is not None and initial_stress is not None:
|
|
50
|
+
raise ValueError(
|
|
51
|
+
'Both initial_strain and initial_stress cannot be provided.'
|
|
52
|
+
)
|
|
53
|
+
self._initial_strain = initial_strain
|
|
54
|
+
self._initial_stress = initial_stress
|
|
55
|
+
self._strain_compatibility = strain_compatibility
|
|
29
56
|
self._name = name if name is not None else 'Material'
|
|
30
57
|
|
|
31
58
|
@property
|
|
32
|
-
def constitutive_law(self):
|
|
59
|
+
def constitutive_law(self) -> ConstitutiveLaw:
|
|
33
60
|
"""Returns the ConstitutiveLaw of the object."""
|
|
34
61
|
return self._constitutive_law
|
|
35
62
|
|
|
@@ -43,6 +70,88 @@ class Material(abc.ABC):
|
|
|
43
70
|
"""Returns the density of the material in kg/m3."""
|
|
44
71
|
return self._density
|
|
45
72
|
|
|
73
|
+
@property
|
|
74
|
+
def initial_strain(self):
|
|
75
|
+
"""Returns the initial strain of the material."""
|
|
76
|
+
return self._initial_strain
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def initial_stress(self):
|
|
80
|
+
"""Returns the initial stress of the material."""
|
|
81
|
+
return self._initial_stress
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def strain_compatibility(self):
|
|
85
|
+
"""Returns the strain compatibility of the material.
|
|
86
|
+
|
|
87
|
+
If true (default), the strain compatibility is enforced
|
|
88
|
+
haveing the same strain as in all other materials of the
|
|
89
|
+
section at the same point. If false, the strain compatibility
|
|
90
|
+
is not enforced and the initial strain is applied to the section
|
|
91
|
+
independently.
|
|
92
|
+
"""
|
|
93
|
+
return self._strain_compatibility
|
|
94
|
+
|
|
95
|
+
def _apply_initial_strain(self):
|
|
96
|
+
"""Wraps the current constitutive law to apply initial strain."""
|
|
97
|
+
strain_compatibility = (
|
|
98
|
+
self._strain_compatibility
|
|
99
|
+
if self._strain_compatibility is not None
|
|
100
|
+
else True
|
|
101
|
+
)
|
|
102
|
+
if self._initial_stress is not None:
|
|
103
|
+
# Specified a stress, compute the strain from it
|
|
104
|
+
self._initial_strain_from_stress()
|
|
105
|
+
if self._initial_strain is not None:
|
|
106
|
+
# Lazy import to avoid circular dependency
|
|
107
|
+
from structuralcodes.materials.constitutive_laws import ( # noqa: PLC0415
|
|
108
|
+
InitialStrain,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if self._initial_stress is None:
|
|
112
|
+
# Compute the stress from the strain
|
|
113
|
+
self._initial_stress = self._constitutive_law.get_stress(
|
|
114
|
+
self._initial_strain
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
self._constitutive_law = InitialStrain(
|
|
118
|
+
self._constitutive_law,
|
|
119
|
+
self._initial_strain,
|
|
120
|
+
strain_compatibility,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
def _initial_strain_from_stress(self):
|
|
124
|
+
"""Computes the initial strain from the initial stress.
|
|
125
|
+
|
|
126
|
+
This function is called internally so it assumes that the
|
|
127
|
+
initial stress is not None
|
|
128
|
+
"""
|
|
129
|
+
# Iteratively compute the initial strain that gives the desired
|
|
130
|
+
# initial stress. Note that the wrapped law can be nonlinear
|
|
131
|
+
tol = 1e-12
|
|
132
|
+
max_iter = 100
|
|
133
|
+
target_stress = self._initial_stress
|
|
134
|
+
strain = 0.0
|
|
135
|
+
stress = self._constitutive_law.get_stress(strain)
|
|
136
|
+
d_stress = target_stress - stress
|
|
137
|
+
num_iter = 0
|
|
138
|
+
while abs(d_stress) > tol and num_iter < max_iter:
|
|
139
|
+
tangent = self._constitutive_law.get_tangent(strain)
|
|
140
|
+
if tangent == 0:
|
|
141
|
+
raise ValueError(
|
|
142
|
+
'Tangent modulus = 0 during initial strain computation.'
|
|
143
|
+
)
|
|
144
|
+
d_strain = d_stress / tangent
|
|
145
|
+
strain += d_strain
|
|
146
|
+
stress = self._constitutive_law.get_stress(strain)
|
|
147
|
+
d_stress = target_stress - stress
|
|
148
|
+
num_iter += 1
|
|
149
|
+
|
|
150
|
+
if abs(d_stress) > tol:
|
|
151
|
+
raise RuntimeError('Failed to converge for given initial stress.')
|
|
152
|
+
|
|
153
|
+
self._initial_strain = strain
|
|
154
|
+
|
|
46
155
|
|
|
47
156
|
class ConstitutiveLaw(abc.ABC):
|
|
48
157
|
"""Abstract base class for constitutive laws."""
|
|
@@ -150,7 +259,9 @@ class ConstitutiveLaw(abc.ABC):
|
|
|
150
259
|
|
|
151
260
|
eps = np.concatenate((eps_neg, eps_pos))
|
|
152
261
|
sig = self.get_stress(eps)
|
|
153
|
-
from structuralcodes.materials.constitutive_laws import
|
|
262
|
+
from structuralcodes.materials.constitutive_laws import ( # noqa: PLC0415
|
|
263
|
+
UserDefined,
|
|
264
|
+
)
|
|
154
265
|
|
|
155
266
|
return UserDefined(eps, sig)
|
|
156
267
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Main entry point for geometry."""
|
|
2
2
|
|
|
3
|
+
from . import profiles
|
|
3
4
|
from ._circular import CircularGeometry
|
|
4
5
|
from ._geometry import (
|
|
5
6
|
CompoundGeometry,
|
|
@@ -14,7 +15,6 @@ from ._reinforcement import (
|
|
|
14
15
|
add_reinforcement_circle,
|
|
15
16
|
add_reinforcement_line,
|
|
16
17
|
)
|
|
17
|
-
from ._steel_sections import HE, IPE, IPN, UB, UBP, UC, UPN
|
|
18
18
|
|
|
19
19
|
__all__ = [
|
|
20
20
|
'Geometry',
|
|
@@ -22,13 +22,7 @@ __all__ = [
|
|
|
22
22
|
'SurfaceGeometry',
|
|
23
23
|
'CompoundGeometry',
|
|
24
24
|
'create_line_point_angle',
|
|
25
|
-
'
|
|
26
|
-
'HE',
|
|
27
|
-
'UB',
|
|
28
|
-
'UC',
|
|
29
|
-
'UBP',
|
|
30
|
-
'IPN',
|
|
31
|
-
'UPN',
|
|
25
|
+
'profiles',
|
|
32
26
|
'add_reinforcement',
|
|
33
27
|
'add_reinforcement_line',
|
|
34
28
|
'CircularGeometry',
|
|
@@ -12,7 +12,7 @@ import numpy as np
|
|
|
12
12
|
from numpy.typing import ArrayLike
|
|
13
13
|
from shapely import Polygon
|
|
14
14
|
|
|
15
|
-
from structuralcodes.core.base import
|
|
15
|
+
from structuralcodes.core.base import Material
|
|
16
16
|
|
|
17
17
|
from ._geometry import SurfaceGeometry
|
|
18
18
|
|
|
@@ -37,9 +37,8 @@ class CircularGeometry(SurfaceGeometry):
|
|
|
37
37
|
def __init__(
|
|
38
38
|
self,
|
|
39
39
|
diameter: float,
|
|
40
|
-
material:
|
|
40
|
+
material: Material,
|
|
41
41
|
n_points: int = 20,
|
|
42
|
-
density: t.Optional[float] = None,
|
|
43
42
|
concrete: bool = False,
|
|
44
43
|
origin: t.Optional[ArrayLike] = None,
|
|
45
44
|
name: t.Optional[str] = None,
|
|
@@ -49,14 +48,9 @@ class CircularGeometry(SurfaceGeometry):
|
|
|
49
48
|
|
|
50
49
|
Arguments:
|
|
51
50
|
diameter (float): The diameter of the geometry.
|
|
52
|
-
material (
|
|
53
|
-
ConsitutiveLaw class applied to the geometry.
|
|
51
|
+
material (Material): A Material class applied to the geometry.
|
|
54
52
|
n_points (int): The number of points used to discretize the
|
|
55
53
|
circle as a shapely `Polygon` (default = 20).
|
|
56
|
-
density (Optional(float)): When a ConstitutiveLaw is passed as
|
|
57
|
-
material, the density can be provided by this argument. When
|
|
58
|
-
material is a Material object the density is taken from the
|
|
59
|
-
material.
|
|
60
54
|
concrete (bool): Flag to indicate if the geometry is concrete.
|
|
61
55
|
origin (Optional(ArrayLike)): The center point of the circle.
|
|
62
56
|
(0.0, 0.0) is used as default.
|
|
@@ -84,7 +78,6 @@ class CircularGeometry(SurfaceGeometry):
|
|
|
84
78
|
super().__init__(
|
|
85
79
|
poly=polygon,
|
|
86
80
|
material=material,
|
|
87
|
-
density=density,
|
|
88
81
|
concrete=concrete,
|
|
89
82
|
name=name,
|
|
90
83
|
group_label=group_label,
|
|
@@ -18,9 +18,9 @@ from shapely.geometry import (
|
|
|
18
18
|
)
|
|
19
19
|
from shapely.ops import split
|
|
20
20
|
|
|
21
|
-
from structuralcodes.core.base import
|
|
21
|
+
from structuralcodes.core.base import Material
|
|
22
|
+
from structuralcodes.materials.basic import ElasticMaterial
|
|
22
23
|
from structuralcodes.materials.concrete import Concrete
|
|
23
|
-
from structuralcodes.materials.constitutive_laws import Elastic
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class Geometry:
|
|
@@ -72,13 +72,24 @@ class Geometry:
|
|
|
72
72
|
@staticmethod
|
|
73
73
|
def from_geometry(
|
|
74
74
|
geo: Geometry,
|
|
75
|
-
new_material: t.Optional[
|
|
75
|
+
new_material: t.Optional[Material] = None,
|
|
76
76
|
) -> Geometry:
|
|
77
77
|
"""Create a new geometry with a different material."""
|
|
78
78
|
raise NotImplementedError(
|
|
79
79
|
'This method should be implemented by subclasses'
|
|
80
80
|
)
|
|
81
81
|
|
|
82
|
+
def __add__(self, other: Geometry) -> CompoundGeometry:
|
|
83
|
+
"""Add operator "+" for geometries.
|
|
84
|
+
|
|
85
|
+
Arguments:
|
|
86
|
+
other (Geometry): The other geometry to add.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
CompoundGeometry: A new CompoundGeometry.
|
|
90
|
+
"""
|
|
91
|
+
return CompoundGeometry([self, other])
|
|
92
|
+
|
|
82
93
|
|
|
83
94
|
class PointGeometry(Geometry):
|
|
84
95
|
"""Class for a point geometry with material.
|
|
@@ -91,8 +102,7 @@ class PointGeometry(Geometry):
|
|
|
91
102
|
self,
|
|
92
103
|
point: t.Union[Point, ArrayLike],
|
|
93
104
|
diameter: float,
|
|
94
|
-
material:
|
|
95
|
-
density: t.Optional[float] = None,
|
|
105
|
+
material: Material,
|
|
96
106
|
name: t.Optional[str] = None,
|
|
97
107
|
group_label: t.Optional[str] = None,
|
|
98
108
|
):
|
|
@@ -105,12 +115,7 @@ class PointGeometry(Geometry):
|
|
|
105
115
|
point (Union(Point, ArrayLike)): A couple of coordinates or a
|
|
106
116
|
shapely Point object.
|
|
107
117
|
diameter (float): The diameter of the point.
|
|
108
|
-
material (
|
|
109
|
-
point (this can be a Material or a ConstitutiveLaw).
|
|
110
|
-
density (Optional(float)): When a ConstitutiveLaw is passed as
|
|
111
|
-
material, the density can be providen by this argument. When
|
|
112
|
-
the material is a Material object the density is taken from the
|
|
113
|
-
material.
|
|
118
|
+
material (Material): The material for the point.
|
|
114
119
|
name (Optional(str)): The name to be given to the object.
|
|
115
120
|
group_label (Optional(str)): A label for grouping several objects
|
|
116
121
|
(default is None).
|
|
@@ -131,22 +136,12 @@ class PointGeometry(Geometry):
|
|
|
131
136
|
warn_str += ' discarded'
|
|
132
137
|
warnings.warn(warn_str)
|
|
133
138
|
point = Point(coords)
|
|
134
|
-
if not isinstance(material, Material)
|
|
135
|
-
material, ConstitutiveLaw
|
|
136
|
-
):
|
|
139
|
+
if not isinstance(material, Material):
|
|
137
140
|
raise TypeError(
|
|
138
|
-
f'mat should be a valid structuralcodes.base.Material \
|
|
139
|
-
or structuralcodes.base.ConstitutiveLaw object. \
|
|
141
|
+
f'mat should be a valid structuralcodes.base.Material object. \
|
|
140
142
|
{repr(material)}'
|
|
141
143
|
)
|
|
142
|
-
|
|
143
|
-
self._density = density
|
|
144
|
-
if isinstance(material, Material):
|
|
145
|
-
self._density = material.density
|
|
146
|
-
self._material = material.constitutive_law
|
|
147
|
-
elif isinstance(material, ConstitutiveLaw):
|
|
148
|
-
self._material = material
|
|
149
|
-
|
|
144
|
+
self._material = material
|
|
150
145
|
self._point = point
|
|
151
146
|
self._diameter = diameter
|
|
152
147
|
self._area = np.pi * diameter**2 / 4.0
|
|
@@ -162,14 +157,14 @@ class PointGeometry(Geometry):
|
|
|
162
157
|
return self._area
|
|
163
158
|
|
|
164
159
|
@property
|
|
165
|
-
def material(self) ->
|
|
160
|
+
def material(self) -> Material:
|
|
166
161
|
"""Returns the point material."""
|
|
167
162
|
return self._material
|
|
168
163
|
|
|
169
164
|
@property
|
|
170
165
|
def density(self) -> float:
|
|
171
166
|
"""Returns the density."""
|
|
172
|
-
return self.
|
|
167
|
+
return self.material.density
|
|
173
168
|
|
|
174
169
|
@property
|
|
175
170
|
def x(self) -> float:
|
|
@@ -204,7 +199,6 @@ class PointGeometry(Geometry):
|
|
|
204
199
|
point=affinity.translate(self._point, dx, dy),
|
|
205
200
|
diameter=self._diameter,
|
|
206
201
|
material=self._material,
|
|
207
|
-
density=self._density,
|
|
208
202
|
name=self._name,
|
|
209
203
|
group_label=self._group_label,
|
|
210
204
|
)
|
|
@@ -231,7 +225,6 @@ class PointGeometry(Geometry):
|
|
|
231
225
|
),
|
|
232
226
|
diameter=self._diameter,
|
|
233
227
|
material=self._material,
|
|
234
|
-
density=self._density,
|
|
235
228
|
name=self._name,
|
|
236
229
|
group_label=self._group_label,
|
|
237
230
|
)
|
|
@@ -239,16 +232,15 @@ class PointGeometry(Geometry):
|
|
|
239
232
|
@staticmethod
|
|
240
233
|
def from_geometry(
|
|
241
234
|
geo: PointGeometry,
|
|
242
|
-
new_material: t.Optional[
|
|
235
|
+
new_material: t.Optional[Material] = None,
|
|
243
236
|
) -> PointGeometry:
|
|
244
237
|
"""Create a new PointGeometry with a different material.
|
|
245
238
|
|
|
246
239
|
Arguments:
|
|
247
240
|
geo (PointGeometry): The geometry.
|
|
248
|
-
new_material (Optional(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
material is created.
|
|
241
|
+
new_material (Optional(Material)): A new material to be applied to
|
|
242
|
+
the geometry. If new_material is None an Elastic material with
|
|
243
|
+
same stiffness as the original material is created.
|
|
252
244
|
|
|
253
245
|
Returns:
|
|
254
246
|
PointGeometry: The new PointGeometry.
|
|
@@ -261,24 +253,21 @@ class PointGeometry(Geometry):
|
|
|
261
253
|
raise TypeError('geo should be a PointGeometry')
|
|
262
254
|
if new_material is not None:
|
|
263
255
|
# provided a new_material
|
|
264
|
-
if not isinstance(new_material, Material)
|
|
265
|
-
new_material, ConstitutiveLaw
|
|
266
|
-
):
|
|
256
|
+
if not isinstance(new_material, Material):
|
|
267
257
|
raise TypeError(
|
|
268
258
|
f'new_material should be a valid structuralcodes.base.\
|
|
269
|
-
Material
|
|
259
|
+
Material object. \
|
|
270
260
|
{repr(new_material)}'
|
|
271
261
|
)
|
|
272
262
|
else:
|
|
273
263
|
# new_material not provided, assume elastic material with same
|
|
274
264
|
# elastic modulus
|
|
275
|
-
new_material =
|
|
265
|
+
new_material = ElasticMaterial.from_material(geo.material)
|
|
276
266
|
|
|
277
267
|
return PointGeometry(
|
|
278
268
|
point=geo._point,
|
|
279
269
|
diameter=geo._diameter,
|
|
280
270
|
material=new_material,
|
|
281
|
-
density=geo._density,
|
|
282
271
|
name=geo._name,
|
|
283
272
|
group_label=geo._group_label,
|
|
284
273
|
)
|
|
@@ -331,13 +320,12 @@ class SurfaceGeometry(Geometry):
|
|
|
331
320
|
holes.
|
|
332
321
|
"""
|
|
333
322
|
|
|
334
|
-
_material:
|
|
323
|
+
_material: Material
|
|
335
324
|
|
|
336
325
|
def __init__(
|
|
337
326
|
self,
|
|
338
327
|
poly: Polygon,
|
|
339
|
-
material:
|
|
340
|
-
density: t.Optional[float] = None,
|
|
328
|
+
material: Material,
|
|
341
329
|
concrete: bool = False,
|
|
342
330
|
name: t.Optional[str] = None,
|
|
343
331
|
group_label: t.Optional[str] = None,
|
|
@@ -346,11 +334,7 @@ class SurfaceGeometry(Geometry):
|
|
|
346
334
|
|
|
347
335
|
Arguments:
|
|
348
336
|
poly (shapely.Polygon): A Shapely polygon.
|
|
349
|
-
material (
|
|
350
|
-
ConsitutiveLaw class applied to the geometry.
|
|
351
|
-
density (Optional(float)): When a ConstitutiveLaw is passed as mat,
|
|
352
|
-
the density can be provided by this argument. When mat is a
|
|
353
|
-
Material object the density is taken from the material.
|
|
337
|
+
material (Material): A Material applied to the geometry.
|
|
354
338
|
concrete (bool): Flag to indicate if the geometry is concrete.
|
|
355
339
|
name (Optional(str)): The name to be given to the object.
|
|
356
340
|
group_label (Optional(str)): A label for grouping several objects.
|
|
@@ -362,24 +346,15 @@ class SurfaceGeometry(Geometry):
|
|
|
362
346
|
f'poly need to be a valid shapely.geometry.Polygon object. \
|
|
363
347
|
{repr(poly)}'
|
|
364
348
|
)
|
|
365
|
-
if not isinstance(material, Material)
|
|
366
|
-
material, ConstitutiveLaw
|
|
367
|
-
):
|
|
349
|
+
if not isinstance(material, Material):
|
|
368
350
|
raise TypeError(
|
|
369
|
-
f'mat should be a valid structuralcodes.base.Material \
|
|
370
|
-
or structuralcodes.base.ConstitutiveLaw object. \
|
|
351
|
+
f'mat should be a valid structuralcodes.base.Material object. \
|
|
371
352
|
{repr(material)}'
|
|
372
353
|
)
|
|
373
354
|
self._polygon = poly
|
|
374
|
-
# Pass a constitutive law to the SurfaceGeometry
|
|
375
|
-
self._density = density
|
|
376
|
-
if isinstance(material, Material):
|
|
377
|
-
self._density = material.density
|
|
378
|
-
if isinstance(material, Concrete):
|
|
379
|
-
concrete = True
|
|
380
|
-
material = material.constitutive_law
|
|
381
|
-
|
|
382
355
|
self._material = material
|
|
356
|
+
if isinstance(material, Concrete):
|
|
357
|
+
concrete = True
|
|
383
358
|
self._concrete = concrete
|
|
384
359
|
|
|
385
360
|
@property
|
|
@@ -403,11 +378,11 @@ class SurfaceGeometry(Geometry):
|
|
|
403
378
|
@property
|
|
404
379
|
def density(self) -> float:
|
|
405
380
|
"""Returns the density."""
|
|
406
|
-
return self.
|
|
381
|
+
return self.material.density
|
|
407
382
|
|
|
408
383
|
@property
|
|
409
|
-
def material(self) ->
|
|
410
|
-
"""Returns the
|
|
384
|
+
def material(self) -> Material:
|
|
385
|
+
"""Returns the material."""
|
|
411
386
|
return self._material
|
|
412
387
|
|
|
413
388
|
@property
|
|
@@ -506,17 +481,6 @@ class SurfaceGeometry(Geometry):
|
|
|
506
481
|
# get the intersection
|
|
507
482
|
return self.polygon.intersection(lines_polygon)
|
|
508
483
|
|
|
509
|
-
def __add__(self, other: Geometry) -> CompoundGeometry:
|
|
510
|
-
"""Add operator "+" for geometries.
|
|
511
|
-
|
|
512
|
-
Arguments:
|
|
513
|
-
other (Geometry): The other geometry to add.
|
|
514
|
-
|
|
515
|
-
Returns:
|
|
516
|
-
CompoundGeometry: A new CompoundGeometry.
|
|
517
|
-
"""
|
|
518
|
-
return CompoundGeometry([self, other])
|
|
519
|
-
|
|
520
484
|
def __sub__(self, other: Geometry) -> SurfaceGeometry:
|
|
521
485
|
"""Add operator "-" for geometries.
|
|
522
486
|
|
|
@@ -527,7 +491,6 @@ class SurfaceGeometry(Geometry):
|
|
|
527
491
|
SurfaceGeometry: The resulting SurfaceGeometry.
|
|
528
492
|
"""
|
|
529
493
|
material = self.material
|
|
530
|
-
density = self._density
|
|
531
494
|
|
|
532
495
|
# if we subtract a point from a surface we obtain the same surface
|
|
533
496
|
sub_polygon = self.polygon
|
|
@@ -540,9 +503,7 @@ class SurfaceGeometry(Geometry):
|
|
|
540
503
|
for g in other.geometries:
|
|
541
504
|
sub_polygon = sub_polygon - g.polygon
|
|
542
505
|
|
|
543
|
-
return SurfaceGeometry(
|
|
544
|
-
poly=sub_polygon, material=material, density=density
|
|
545
|
-
)
|
|
506
|
+
return SurfaceGeometry(poly=sub_polygon, material=material)
|
|
546
507
|
|
|
547
508
|
def _repr_svg_(self) -> str:
|
|
548
509
|
"""Returns the svg representation."""
|
|
@@ -561,7 +522,6 @@ class SurfaceGeometry(Geometry):
|
|
|
561
522
|
return SurfaceGeometry(
|
|
562
523
|
poly=affinity.translate(self.polygon, dx, dy),
|
|
563
524
|
material=self.material,
|
|
564
|
-
density=self._density,
|
|
565
525
|
concrete=self.concrete,
|
|
566
526
|
)
|
|
567
527
|
|
|
@@ -589,23 +549,21 @@ class SurfaceGeometry(Geometry):
|
|
|
589
549
|
self.polygon, angle, origin=point, use_radians=use_radians
|
|
590
550
|
),
|
|
591
551
|
material=self.material,
|
|
592
|
-
density=self._density,
|
|
593
552
|
concrete=self.concrete,
|
|
594
553
|
)
|
|
595
554
|
|
|
596
555
|
@staticmethod
|
|
597
556
|
def from_geometry(
|
|
598
557
|
geo: SurfaceGeometry,
|
|
599
|
-
new_material: t.Optional[
|
|
558
|
+
new_material: t.Optional[Material] = None,
|
|
600
559
|
) -> SurfaceGeometry:
|
|
601
560
|
"""Create a new SurfaceGeometry with a different material.
|
|
602
561
|
|
|
603
562
|
Arguments:
|
|
604
563
|
geo (SurfaceGeometry): The geometry.
|
|
605
|
-
new_material: (Optional(
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
material is created.
|
|
564
|
+
new_material: (Optional(Material)): A new material to be applied to
|
|
565
|
+
the geometry. If new_material is None an Elastic material with
|
|
566
|
+
same stiffness of the original material is created.
|
|
609
567
|
|
|
610
568
|
Returns:
|
|
611
569
|
SurfaceGeometry: The new SurfaceGeometry.
|
|
@@ -618,22 +576,18 @@ class SurfaceGeometry(Geometry):
|
|
|
618
576
|
raise TypeError('geo should be a SurfaceGeometry')
|
|
619
577
|
if new_material is not None:
|
|
620
578
|
# provided a new_material
|
|
621
|
-
if not isinstance(new_material, Material)
|
|
622
|
-
new_material, ConstitutiveLaw
|
|
623
|
-
):
|
|
579
|
+
if not isinstance(new_material, Material):
|
|
624
580
|
raise TypeError(
|
|
625
581
|
f'new_material should be a valid structuralcodes.base.\
|
|
626
|
-
Material
|
|
582
|
+
Material object. \
|
|
627
583
|
{repr(new_material)}'
|
|
628
584
|
)
|
|
629
585
|
else:
|
|
630
586
|
# new_material not provided, assume elastic material with same
|
|
631
587
|
# elastic modulus
|
|
632
|
-
new_material =
|
|
588
|
+
new_material = ElasticMaterial.from_material(geo.material)
|
|
633
589
|
|
|
634
|
-
return SurfaceGeometry(
|
|
635
|
-
poly=geo.polygon, material=new_material, density=geo._density
|
|
636
|
-
)
|
|
590
|
+
return SurfaceGeometry(poly=geo.polygon, material=new_material)
|
|
637
591
|
|
|
638
592
|
# here we can also add static methods like:
|
|
639
593
|
# from_points
|
|
@@ -648,14 +602,12 @@ class SurfaceGeometry(Geometry):
|
|
|
648
602
|
|
|
649
603
|
def _process_geometries_multipolygon(
|
|
650
604
|
geometries: MultiPolygon,
|
|
651
|
-
materials: t.Optional[
|
|
652
|
-
t.Union[t.List[Material], Material, ConstitutiveLaw]
|
|
653
|
-
],
|
|
605
|
+
materials: t.Optional[t.Union[t.List[Material], Material]],
|
|
654
606
|
) -> list[Geometry]:
|
|
655
607
|
"""Process geometries for initialization."""
|
|
656
608
|
checked_geometries = []
|
|
657
609
|
# a MultiPolygon is provided
|
|
658
|
-
if isinstance(materials,
|
|
610
|
+
if isinstance(materials, Material):
|
|
659
611
|
for g in geometries.geoms:
|
|
660
612
|
checked_geometries.append(
|
|
661
613
|
SurfaceGeometry(poly=g, material=materials)
|
|
@@ -698,20 +650,23 @@ class CompoundGeometry(Geometry):
|
|
|
698
650
|
properties.
|
|
699
651
|
"""
|
|
700
652
|
|
|
701
|
-
geometries: t.List[
|
|
653
|
+
geometries: t.List[t.Union[SurfaceGeometry, PointGeometry]]
|
|
702
654
|
|
|
703
655
|
def __init__(
|
|
704
656
|
self,
|
|
705
|
-
geometries: t.Union[
|
|
657
|
+
geometries: t.Union[
|
|
658
|
+
t.List[t.Union[SurfaceGeometry, PointGeometry, CompoundGeometry]],
|
|
659
|
+
MultiPolygon,
|
|
660
|
+
],
|
|
706
661
|
materials: t.Optional[t.Union[t.List[Material], Material]] = None,
|
|
707
662
|
) -> None:
|
|
708
663
|
"""Creates a compound geometry.
|
|
709
664
|
|
|
710
665
|
Arguments:
|
|
711
666
|
geometries (Union(List(Geometry), MultiPolygon)): A list of
|
|
712
|
-
Geometry objects (i.e. PointGeometry
|
|
713
|
-
shapely MultiPolygon object (in this
|
|
714
|
-
materials should be given).
|
|
667
|
+
Geometry objects (i.e. PointGeometry, SurfaceGeometry or
|
|
668
|
+
CompoundGeometry) or a shapely MultiPolygon object (in this
|
|
669
|
+
latter case also a list of materials should be given).
|
|
715
670
|
materials (Optional(List(Material), Material)): A material (applied
|
|
716
671
|
to all polygons) or a list of materials. In this case the
|
|
717
672
|
number of polygons should match the number of materials.
|
|
@@ -834,17 +789,6 @@ class CompoundGeometry(Geometry):
|
|
|
834
789
|
processed_geoms.append(pg.rotate(angle, point, use_radians))
|
|
835
790
|
return CompoundGeometry(geometries=processed_geoms)
|
|
836
791
|
|
|
837
|
-
def __add__(self, other: Geometry) -> CompoundGeometry:
|
|
838
|
-
"""Add operator "+" for geometries.
|
|
839
|
-
|
|
840
|
-
Arguments:
|
|
841
|
-
other (Geometry): The other geometry to add.
|
|
842
|
-
|
|
843
|
-
Returns:
|
|
844
|
-
CompoundGeometry: A new CompoundGeometry.
|
|
845
|
-
"""
|
|
846
|
-
return CompoundGeometry([self, other])
|
|
847
|
-
|
|
848
792
|
def __sub__(self, other: Geometry) -> CompoundGeometry:
|
|
849
793
|
"""Add operator "-" for geometries.
|
|
850
794
|
|
|
@@ -868,7 +812,7 @@ class CompoundGeometry(Geometry):
|
|
|
868
812
|
@staticmethod
|
|
869
813
|
def from_geometry(
|
|
870
814
|
geo: CompoundGeometry,
|
|
871
|
-
new_material: t.Optional[
|
|
815
|
+
new_material: t.Optional[Material] = None,
|
|
872
816
|
) -> CompoundGeometry:
|
|
873
817
|
"""Create a new CompoundGeometry with a different material.
|
|
874
818
|
|
|
@@ -11,7 +11,7 @@ import typing as t
|
|
|
11
11
|
from numpy.typing import ArrayLike
|
|
12
12
|
from shapely import Polygon
|
|
13
13
|
|
|
14
|
-
from structuralcodes.core.base import
|
|
14
|
+
from structuralcodes.core.base import Material
|
|
15
15
|
|
|
16
16
|
from ._geometry import SurfaceGeometry
|
|
17
17
|
|
|
@@ -28,8 +28,7 @@ class RectangularGeometry(SurfaceGeometry):
|
|
|
28
28
|
self,
|
|
29
29
|
width: float,
|
|
30
30
|
height: float,
|
|
31
|
-
material:
|
|
32
|
-
density: t.Optional[float] = None,
|
|
31
|
+
material: Material,
|
|
33
32
|
concrete: bool = False,
|
|
34
33
|
origin: t.Optional[ArrayLike] = None,
|
|
35
34
|
name: t.Optional[str] = None,
|
|
@@ -40,12 +39,7 @@ class RectangularGeometry(SurfaceGeometry):
|
|
|
40
39
|
Arguments:
|
|
41
40
|
width (float): The width of the geometry.
|
|
42
41
|
height (float): The height of the geometry.
|
|
43
|
-
material (
|
|
44
|
-
ConsitutiveLaw class applied to the geometry.
|
|
45
|
-
density (Optional(float)): When a ConstitutiveLaw is passed as
|
|
46
|
-
material, the density can be provided by this argument. When
|
|
47
|
-
material is a Material object the density is taken from the
|
|
48
|
-
material.
|
|
42
|
+
material (Material): A Material class applied to the geometry.
|
|
49
43
|
concrete (bool): Flag to indicate if the geometry is concrete. When
|
|
50
44
|
passing a Material as material, this is automatically inferred.
|
|
51
45
|
origin (Optional(ArrayLike)): The center point of the rectangle.
|
|
@@ -84,7 +78,6 @@ class RectangularGeometry(SurfaceGeometry):
|
|
|
84
78
|
super().__init__(
|
|
85
79
|
poly=polygon,
|
|
86
80
|
material=material,
|
|
87
|
-
density=density,
|
|
88
81
|
concrete=concrete,
|
|
89
82
|
name=name,
|
|
90
83
|
group_label=group_label,
|