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

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

Potentially problematic release.


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

Files changed (26) hide show
  1. structuralcodes/__init__.py +1 -1
  2. structuralcodes/codes/ec2_2004/__init__.py +2 -0
  3. structuralcodes/codes/ec2_2004/shear.py +44 -4
  4. structuralcodes/codes/mc2010/__init__.py +18 -0
  5. structuralcodes/codes/mc2010/_concrete_punching.py +300 -388
  6. structuralcodes/core/base.py +1 -1
  7. structuralcodes/geometry/_circular.py +3 -10
  8. structuralcodes/geometry/_geometry.py +47 -92
  9. structuralcodes/geometry/_rectangular.py +3 -10
  10. structuralcodes/geometry/_reinforcement.py +8 -11
  11. structuralcodes/materials/__init__.py +2 -1
  12. structuralcodes/materials/basic/__init__.py +11 -0
  13. structuralcodes/materials/basic/_elastic.py +52 -0
  14. structuralcodes/materials/basic/_elasticplastic.py +75 -0
  15. structuralcodes/materials/basic/_generic.py +26 -0
  16. structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py +1 -1
  17. structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py +1 -1
  18. structuralcodes/materials/reinforcement/_reinforcementMC2010.py +1 -1
  19. structuralcodes/sections/_generic.py +53 -14
  20. structuralcodes/sections/_rc_utils.py +15 -5
  21. structuralcodes/sections/section_integrators/_fiber_integrator.py +19 -11
  22. structuralcodes/sections/section_integrators/_marin_integrator.py +24 -19
  23. {structuralcodes-0.4.0.dist-info → structuralcodes-0.5.0.dist-info}/METADATA +1 -1
  24. {structuralcodes-0.4.0.dist-info → structuralcodes-0.5.0.dist-info}/RECORD +26 -22
  25. {structuralcodes-0.4.0.dist-info → structuralcodes-0.5.0.dist-info}/WHEEL +0 -0
  26. {structuralcodes-0.4.0.dist-info → structuralcodes-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -29,7 +29,7 @@ class Material(abc.ABC):
29
29
  self._name = name if name is not None else 'Material'
30
30
 
31
31
  @property
32
- def constitutive_law(self):
32
+ def constitutive_law(self) -> ConstitutiveLaw:
33
33
  """Returns the ConstitutiveLaw of the object."""
34
34
  return self._constitutive_law
35
35
 
@@ -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 ConstitutiveLaw, Material
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: t.Union[Material, ConstitutiveLaw],
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 (Union(Material, ConstitutiveLaw)): A Material or
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 ConstitutiveLaw, Material
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,7 +72,7 @@ class Geometry:
72
72
  @staticmethod
73
73
  def from_geometry(
74
74
  geo: Geometry,
75
- new_material: t.Optional[t.Union[Material, ConstitutiveLaw]] = None,
75
+ new_material: t.Optional[Material] = None,
76
76
  ) -> Geometry:
77
77
  """Create a new geometry with a different material."""
78
78
  raise NotImplementedError(
@@ -91,8 +91,7 @@ class PointGeometry(Geometry):
91
91
  self,
92
92
  point: t.Union[Point, ArrayLike],
93
93
  diameter: float,
94
- material: t.Union[Material, ConstitutiveLaw],
95
- density: t.Optional[float] = None,
94
+ material: Material,
96
95
  name: t.Optional[str] = None,
97
96
  group_label: t.Optional[str] = None,
98
97
  ):
@@ -105,12 +104,7 @@ class PointGeometry(Geometry):
105
104
  point (Union(Point, ArrayLike)): A couple of coordinates or a
106
105
  shapely Point object.
107
106
  diameter (float): The diameter of the point.
108
- material (Union(Material, ConstitutiveLaw)): The material for the
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.
107
+ material (Material): The material for the point.
114
108
  name (Optional(str)): The name to be given to the object.
115
109
  group_label (Optional(str)): A label for grouping several objects
116
110
  (default is None).
@@ -131,22 +125,12 @@ class PointGeometry(Geometry):
131
125
  warn_str += ' discarded'
132
126
  warnings.warn(warn_str)
133
127
  point = Point(coords)
134
- if not isinstance(material, Material) and not isinstance(
135
- material, ConstitutiveLaw
136
- ):
128
+ if not isinstance(material, Material):
137
129
  raise TypeError(
138
- f'mat should be a valid structuralcodes.base.Material \
139
- or structuralcodes.base.ConstitutiveLaw object. \
130
+ f'mat should be a valid structuralcodes.base.Material object. \
140
131
  {repr(material)}'
141
132
  )
142
- # Pass a constitutive law to the PointGeometry
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
-
133
+ self._material = material
150
134
  self._point = point
151
135
  self._diameter = diameter
152
136
  self._area = np.pi * diameter**2 / 4.0
@@ -162,14 +146,14 @@ class PointGeometry(Geometry):
162
146
  return self._area
163
147
 
164
148
  @property
165
- def material(self) -> ConstitutiveLaw:
149
+ def material(self) -> Material:
166
150
  """Returns the point material."""
167
151
  return self._material
168
152
 
169
153
  @property
170
154
  def density(self) -> float:
171
155
  """Returns the density."""
172
- return self._density
156
+ return self.material.density
173
157
 
174
158
  @property
175
159
  def x(self) -> float:
@@ -204,7 +188,6 @@ class PointGeometry(Geometry):
204
188
  point=affinity.translate(self._point, dx, dy),
205
189
  diameter=self._diameter,
206
190
  material=self._material,
207
- density=self._density,
208
191
  name=self._name,
209
192
  group_label=self._group_label,
210
193
  )
@@ -231,7 +214,6 @@ class PointGeometry(Geometry):
231
214
  ),
232
215
  diameter=self._diameter,
233
216
  material=self._material,
234
- density=self._density,
235
217
  name=self._name,
236
218
  group_label=self._group_label,
237
219
  )
@@ -239,16 +221,15 @@ class PointGeometry(Geometry):
239
221
  @staticmethod
240
222
  def from_geometry(
241
223
  geo: PointGeometry,
242
- new_material: t.Optional[t.Union[Material, ConstitutiveLaw]] = None,
224
+ new_material: t.Optional[Material] = None,
243
225
  ) -> PointGeometry:
244
226
  """Create a new PointGeometry with a different material.
245
227
 
246
228
  Arguments:
247
229
  geo (PointGeometry): The geometry.
248
- new_material (Optional(Union(Material, ConstitutiveLaw))): A new
249
- material to be applied to the geometry. If new_material is
250
- None an Elastic material with same stiffness as the original
251
- material is created.
230
+ new_material (Optional(Material)): A new material to be applied to
231
+ the geometry. If new_material is None an Elastic material with
232
+ same stiffness as the original material is created.
252
233
 
253
234
  Returns:
254
235
  PointGeometry: The new PointGeometry.
@@ -261,24 +242,21 @@ class PointGeometry(Geometry):
261
242
  raise TypeError('geo should be a PointGeometry')
262
243
  if new_material is not None:
263
244
  # provided a new_material
264
- if not isinstance(new_material, Material) and not isinstance(
265
- new_material, ConstitutiveLaw
266
- ):
245
+ if not isinstance(new_material, Material):
267
246
  raise TypeError(
268
247
  f'new_material should be a valid structuralcodes.base.\
269
- Material or structuralcodes.base.ConstitutiveLaw object. \
248
+ Material object. \
270
249
  {repr(new_material)}'
271
250
  )
272
251
  else:
273
252
  # new_material not provided, assume elastic material with same
274
253
  # elastic modulus
275
- new_material = Elastic(E=geo.material.get_tangent(eps=0))
254
+ new_material = ElasticMaterial.from_material(geo.material)
276
255
 
277
256
  return PointGeometry(
278
257
  point=geo._point,
279
258
  diameter=geo._diameter,
280
259
  material=new_material,
281
- density=geo._density,
282
260
  name=geo._name,
283
261
  group_label=geo._group_label,
284
262
  )
@@ -331,13 +309,12 @@ class SurfaceGeometry(Geometry):
331
309
  holes.
332
310
  """
333
311
 
334
- _material: ConstitutiveLaw
312
+ _material: Material
335
313
 
336
314
  def __init__(
337
315
  self,
338
316
  poly: Polygon,
339
- material: t.Union[Material, ConstitutiveLaw],
340
- density: t.Optional[float] = None,
317
+ material: Material,
341
318
  concrete: bool = False,
342
319
  name: t.Optional[str] = None,
343
320
  group_label: t.Optional[str] = None,
@@ -346,11 +323,7 @@ class SurfaceGeometry(Geometry):
346
323
 
347
324
  Arguments:
348
325
  poly (shapely.Polygon): A Shapely polygon.
349
- material (Union(Material, ConstitutiveLaw)): A Material or
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.
326
+ material (Material): A Material applied to the geometry.
354
327
  concrete (bool): Flag to indicate if the geometry is concrete.
355
328
  name (Optional(str)): The name to be given to the object.
356
329
  group_label (Optional(str)): A label for grouping several objects.
@@ -362,24 +335,15 @@ class SurfaceGeometry(Geometry):
362
335
  f'poly need to be a valid shapely.geometry.Polygon object. \
363
336
  {repr(poly)}'
364
337
  )
365
- if not isinstance(material, Material) and not isinstance(
366
- material, ConstitutiveLaw
367
- ):
338
+ if not isinstance(material, Material):
368
339
  raise TypeError(
369
- f'mat should be a valid structuralcodes.base.Material \
370
- or structuralcodes.base.ConstitutiveLaw object. \
340
+ f'mat should be a valid structuralcodes.base.Material object. \
371
341
  {repr(material)}'
372
342
  )
373
343
  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
344
  self._material = material
345
+ if isinstance(material, Concrete):
346
+ concrete = True
383
347
  self._concrete = concrete
384
348
 
385
349
  @property
@@ -403,11 +367,11 @@ class SurfaceGeometry(Geometry):
403
367
  @property
404
368
  def density(self) -> float:
405
369
  """Returns the density."""
406
- return self._density
370
+ return self.material.density
407
371
 
408
372
  @property
409
- def material(self) -> ConstitutiveLaw:
410
- """Returns the Constitutive law."""
373
+ def material(self) -> Material:
374
+ """Returns the material."""
411
375
  return self._material
412
376
 
413
377
  @property
@@ -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[t.Union[Material, ConstitutiveLaw]] = None,
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(Union(Material, ConstitutiveLaw))): A new
606
- material to be applied to the geometry. If new_material is None
607
- an Elastic material with same stiffness of the original
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) and not isinstance(
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 or structuralcodes.base.ConstitutiveLaw object. \
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 = Elastic(E=geo.material.get_tangent(eps=0))
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, (ConstitutiveLaw, Material)):
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[Geometry]
653
+ geometries: t.List[t.Union[SurfaceGeometry, PointGeometry]]
702
654
 
703
655
  def __init__(
704
656
  self,
705
- geometries: t.Union[t.List[Geometry], MultiPolygon],
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 or SurfaceGeometry) or a
713
- shapely MultiPolygon object (in this latter case also a list of
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.
@@ -868,7 +823,7 @@ class CompoundGeometry(Geometry):
868
823
  @staticmethod
869
824
  def from_geometry(
870
825
  geo: CompoundGeometry,
871
- new_material: t.Optional[t.Union[Material, ConstitutiveLaw]] = None,
826
+ new_material: t.Optional[Material] = None,
872
827
  ) -> CompoundGeometry:
873
828
  """Create a new CompoundGeometry with a different material.
874
829
 
@@ -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 ConstitutiveLaw, Material
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: t.Union[Material, ConstitutiveLaw],
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 (Union(Material, ConstitutiveLaw)): A Material or
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,
@@ -6,7 +6,7 @@ import typing as t
6
6
  import numpy as np
7
7
  from shapely import Point
8
8
 
9
- from structuralcodes.core.base import ConstitutiveLaw, Material
9
+ from structuralcodes.core.base import Material
10
10
 
11
11
  from ._geometry import CompoundGeometry, PointGeometry, SurfaceGeometry
12
12
 
@@ -15,7 +15,7 @@ def add_reinforcement(
15
15
  geo: t.Union[SurfaceGeometry, CompoundGeometry],
16
16
  coords: t.Tuple[float, float],
17
17
  diameter: float,
18
- material: t.Union[Material, ConstitutiveLaw],
18
+ material: Material,
19
19
  group_label: t.Optional[str] = None,
20
20
  ) -> CompoundGeometry:
21
21
  """Add a single bar given coordinate.
@@ -25,8 +25,7 @@ def add_reinforcement(
25
25
  reinforcement.
26
26
  coords (Tuple(float, float)): A tuple with cordinates of bar.
27
27
  diameter (float): The diameter of the reinforcement.
28
- material (Union(Material, ConstitutiveLaw)): A material or a
29
- constitutive law for the behavior of the reinforcement.
28
+ material (Material): A material for the reinforcement.
30
29
  group_label (Optional(str)): A label for grouping several objects
31
30
  (default is None).
32
31
 
@@ -45,7 +44,7 @@ def add_reinforcement_line(
45
44
  coords_i: t.Tuple[float, float],
46
45
  coords_j: t.Tuple[float, float],
47
46
  diameter: float,
48
- material: t.Union[Material, ConstitutiveLaw],
47
+ material: Material,
49
48
  n: int = 0,
50
49
  s: float = 0.0,
51
50
  first: bool = True,
@@ -60,9 +59,8 @@ def add_reinforcement_line(
60
59
  coords_i (Tuple(float, float)): Coordinates of the initial point of
61
60
  line.
62
61
  coords_j (Tuple(float, float)): Coordinates of the final point of line.
63
- diamter (float): The diameter of the bars.
64
- material (Union(Material, ConstitutiveLaw)): A valid material or
65
- constitutive law.
62
+ diameter (float): The diameter of the bars.
63
+ material (Material): A material for the reinforcement.
66
64
  n (int): The number of bars to be distributed inside the line (default
67
65
  = 0).
68
66
  s (float): The distance between the bars (default = 0).
@@ -130,7 +128,7 @@ def add_reinforcement_circle(
130
128
  center: t.Tuple[float, float],
131
129
  radius: float,
132
130
  diameter: float,
133
- material: t.Union[Material, ConstitutiveLaw],
131
+ material: Material,
134
132
  n: int = 0,
135
133
  s: float = 0.0,
136
134
  first: bool = True,
@@ -152,8 +150,7 @@ def add_reinforcement_circle(
152
150
  radius (float): Radius of the circle line where reinforcement will be
153
151
  added.
154
152
  diameter (float): The diameter of the bars.
155
- material (Union(Material, ConstitutiveLaw)): A valid material or
156
- constitutive law.
153
+ material (Material): A material for the reinforcement.
157
154
  n (int): The number of bars to be distributed inside the line (default
158
155
  = 0).
159
156
  s (float): The distance between the bars (default = 0).
@@ -1,9 +1,10 @@
1
1
  """Main entry point for materials."""
2
2
 
3
- from . import concrete, constitutive_laws, reinforcement
3
+ from . import basic, concrete, constitutive_laws, reinforcement
4
4
 
5
5
  __all__ = [
6
6
  'concrete',
7
7
  'constitutive_laws',
8
8
  'reinforcement',
9
+ 'basic',
9
10
  ]
@@ -0,0 +1,11 @@
1
+ """A collection of basic material classes."""
2
+
3
+ from ._elastic import ElasticMaterial
4
+ from ._elasticplastic import ElasticPlasticMaterial
5
+ from ._generic import GenericMaterial
6
+
7
+ __all__ = [
8
+ 'ElasticMaterial',
9
+ 'ElasticPlasticMaterial',
10
+ 'GenericMaterial',
11
+ ]
@@ -0,0 +1,52 @@
1
+ """A material class with elastic properties."""
2
+
3
+ import typing as t
4
+
5
+ from ...core.base import Material
6
+ from ..constitutive_laws import create_constitutive_law
7
+
8
+
9
+ class ElasticMaterial(Material):
10
+ """A material class with elastic properties."""
11
+
12
+ _E: float
13
+
14
+ def __init__(
15
+ self,
16
+ E: float,
17
+ density: float,
18
+ name: t.Optional[str] = None,
19
+ ):
20
+ """Initialize a material with an elastic plastic constitutive law.
21
+
22
+ Arguments:
23
+ E (float): The Young's modulus.
24
+ density (float): The density.
25
+ name (str, optional): The name of the material, default value None.
26
+ """
27
+ super().__init__(density=density, name=name)
28
+ self._E = E
29
+ self._constitutive_law = create_constitutive_law('elastic', self)
30
+
31
+ @property
32
+ def E(self) -> float:
33
+ """Returns the Young's modulus."""
34
+ return self._E
35
+
36
+ def __elastic__(self) -> dict:
37
+ """Returns kwargs for creating an elastic constitutive law."""
38
+ return {'E': self.E}
39
+
40
+ @classmethod
41
+ def from_material(cls, other_material: Material):
42
+ """Create an elastic material based on another material."""
43
+ # Create name of elastic material
44
+ name = other_material.name
45
+ if name is not None:
46
+ name += '_elastic'
47
+
48
+ return cls(
49
+ E=other_material.constitutive_law.get_tangent(eps=0),
50
+ density=other_material.density,
51
+ name=name,
52
+ )
@@ -0,0 +1,75 @@
1
+ """A material class with elastic plastic properties."""
2
+
3
+ import typing as t
4
+
5
+ from ...core.base import Material
6
+ from ..constitutive_laws import create_constitutive_law
7
+
8
+
9
+ class ElasticPlasticMaterial(Material):
10
+ """A material class with elastic plastic properties."""
11
+
12
+ _E: float
13
+ _fy: float
14
+ _Eh: float
15
+ _eps_su: float
16
+
17
+ def __init__(
18
+ self,
19
+ E: float,
20
+ fy: float,
21
+ density: float,
22
+ Eh: float = 0,
23
+ eps_su: t.Optional[float] = None,
24
+ name: t.Optional[str] = None,
25
+ ):
26
+ """Initialize a material with an elastic plastic constitutive law.
27
+
28
+ Arguments:
29
+ E (float): The Young's modulus.
30
+ fy (float): The yield stress.
31
+ density (float): The density.
32
+ Eh (float, optional): The hardening modulus, default value 0.
33
+ eps_su (float, optional): The ultimate strain, default value None.
34
+ name (str, optional): The name of the material, default value None.
35
+ """
36
+ super().__init__(density=density, name=name)
37
+ self._E = E
38
+ self._fy = fy
39
+ self._Eh = Eh
40
+ self._eps_su = eps_su
41
+
42
+ self._constitutive_law = create_constitutive_law(
43
+ 'elasticplastic', self
44
+ )
45
+
46
+ @property
47
+ def E(self) -> float:
48
+ """Returns the Young's modulus."""
49
+ return self._E
50
+
51
+ @property
52
+ def fy(self) -> float:
53
+ """Returns the yield stress."""
54
+ return self._fy
55
+
56
+ @property
57
+ def Eh(self) -> float:
58
+ """Returns the hardening modulus."""
59
+ return self._Eh
60
+
61
+ @property
62
+ def eps_su(self) -> float:
63
+ """Returns the ultimate strain."""
64
+ return self._eps_su
65
+
66
+ def __elasticplastic__(self) -> dict:
67
+ """Returns kwargs for ElasticPlastic constitutive law with strain
68
+ hardening.
69
+ """
70
+ return {
71
+ 'E': self.E,
72
+ 'fy': self.fy,
73
+ 'Eh': self.Eh,
74
+ 'eps_su': self.eps_su,
75
+ }