structuralcodes 0.0.2__py3-none-any.whl → 0.1.1__py3-none-any.whl

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

Potentially problematic release.


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

@@ -3,7 +3,7 @@
3
3
  from . import codes, core, geometry, materials, sections
4
4
  from .codes import get_design_codes, set_design_code, set_national_annex
5
5
 
6
- __version__ = '0.0.2'
6
+ __version__ = '0.1.1'
7
7
 
8
8
  __all__ = [
9
9
  'set_design_code',
@@ -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(design_code: t.Optional[str] = None) -> None:
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 not None:
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
- _CODE = None
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
- return _DESIGN_CODES.get(design_code.lower())
99
+
100
+ # Set design code before returning
101
+ set_design_code(design_code)
102
+ return _CODE
@@ -191,7 +191,7 @@ def eps_cs(
191
191
  ValueError: Checks if the cement class equals R, N or S.
192
192
  """
193
193
  _cement_class = cement_class.upper().strip()
194
- beta_ds = (t - t_S) / (t - t_S + 0.04 * h_0 ** (1 / 3)) # (3.10)
194
+ beta_ds = (t - t_S) / (t - t_S + 0.04 * h_0 ** (3 / 2)) # (3.10)
195
195
  beta_as = 1 - math.exp(-0.2 * t**0.5) # (3.13)
196
196
 
197
197
  # k_h is defined in Table 3.3 under (3.9)
@@ -1,6 +1,7 @@
1
1
  """Design rules according to EN 1992-1-1 regarding shear."""
2
2
 
3
3
  import math
4
+ import typing as t
4
5
 
5
6
  # General functions
6
7
 
@@ -171,6 +172,7 @@ def VRdc(
171
172
  fcd: float,
172
173
  k1: float = 0.15,
173
174
  gamma_c: float = 1.5,
175
+ CRdc: t.Optional[float] = None,
174
176
  ) -> float:
175
177
  """Compute the design strength of the shear resistance.
176
178
 
@@ -194,11 +196,13 @@ def VRdc(
194
196
  value might differ between National Annexes.
195
197
  gamma_c (float): Partial factor for concrete. Default value = 1.5,
196
198
  value might differ between National Annexes.
199
+ CRdc (Optional[float]): Scaling factor for the shear resistance.
200
+ Default value is 0.18 / gamma_c.
197
201
 
198
202
  Returns:
199
203
  float: The concrete shear resistance in MPa.
200
204
  """
201
- CRdc = 0.18 / gamma_c
205
+ CRdc = CRdc or 0.18 / gamma_c
202
206
  return (
203
207
  max(
204
208
  CRdc * _k(d) * (100 * _rho_L(Asl, bw, d) * fck) ** (1.0 / 3.0)
@@ -291,7 +291,9 @@ def beta_ds(
291
291
  numpy.ndarray: Multiplication factor used for calculating the drying
292
292
  shrinkage as a function of time.
293
293
  """
294
- return np.sqrt((time - ts) / (0.035 * (notional_size) ** 2 + (time - ts)))
294
+ time_drying = np.atleast_1d(time - ts)
295
+ time_drying[time_drying < 0.0] = 0.0
296
+ return np.sqrt(time_drying / (0.035 * (notional_size) ** 2 + time_drying))
295
297
 
296
298
 
297
299
  def beta_s1(fcm: float) -> float:
@@ -0,0 +1,7 @@
1
+ """The fib Model Code 2020."""
2
+
3
+ import typing as t
4
+
5
+ __title__: str = 'fib Model Code 2020'
6
+ __year__: str = '2024'
7
+ __materials__: t.Tuple[str] = ('concrete', 'reinforcement')
@@ -175,37 +175,87 @@ class UltimateBendingMomentResults:
175
175
 
176
176
 
177
177
  @dataclass
178
- class NMMInteractionDomain:
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
- n: float = 0 # axial load
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 (positive and negative).
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
- eps_max, eps_min = self.get_ultimate_strain()
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
- eps_max, eps_min = self.get_ultimate_strain()
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
- material = material.constitutive_law
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) -> Material:
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
- mat: t.Union[Material, ConstitutiveLaw],
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
- mat (Union(Material, ConstitutiveLaw)): A Material or
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(mat, Material) and not isinstance(
369
- mat, ConstitutiveLaw
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(mat)}'
366
+ {repr(material)}'
375
367
  )
376
- self.polygon = poly
368
+ self._polygon = poly
377
369
  # Pass a constitutive law to the SurfaceGeometry
378
370
  self._density = density
379
- if isinstance(mat, Material):
380
- self._density = mat.density
381
- if isinstance(mat, Concrete):
371
+ if isinstance(material, Material):
372
+ self._density = material.density
373
+ if isinstance(material, Concrete):
382
374
  concrete = True
383
- mat = mat.constitutive_law
375
+ material = material.constitutive_law
384
376
 
385
- self.material = mat
386
- self.concrete = concrete
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(poly=sub_polygon, mat=material, density=density)
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
- mat=self.material,
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
- mat=self.material,
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, mat=new_material, density=geo._density
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(SurfaceGeometry(poly=g, mat=materials))
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, mat=m))
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
- SurfaceGeometry objects or a shapely MultiPolygon object
693
- (in this case also a list of materials should be given).
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._point.buffer(pg._diameter / 2)
729
+ pg.point.buffer(pg.diameter / 2)
716
730
  for pg in self.point_geometries
717
731
  ]
718
732
  self.geom = MultiPolygon(geoms_representation)
@@ -18,6 +18,7 @@ def add_reinforcement(
18
18
  coords: t.Tuple[float, float],
19
19
  diameter: float,
20
20
  material: t.Union[Material, ConstitutiveLaw],
21
+ group_label: t.Optional[str] = None,
21
22
  ) -> CompoundGeometry:
22
23
  """Add a single bar given coordinate.
23
24
 
@@ -28,12 +29,16 @@ def add_reinforcement(
28
29
  diameter (float): The diameter of the reinforcement.
29
30
  material (Union(Material, ConstitutiveLaw)): A material or a
30
31
  constitutive law for the behavior of the reinforcement.
32
+ group_label (Optional(str)): A label for grouping several objects
33
+ (default is None).
31
34
 
32
35
  Returns:
33
36
  CompoundGeometry: A compound geometry with the original geometry and
34
37
  the reinforcement.
35
38
  """
36
- bar = PointGeometry(Point(coords), diameter, material)
39
+ bar = PointGeometry(
40
+ Point(coords), diameter, material, group_label=group_label
41
+ )
37
42
  return geo + bar
38
43
 
39
44
 
@@ -47,6 +52,7 @@ def add_reinforcement_line(
47
52
  s: float = 0.0,
48
53
  first: bool = True,
49
54
  last: bool = True,
55
+ group_label: t.Optional[str] = None,
50
56
  ) -> CompoundGeometry:
51
57
  """Adds a set of bars distributed in a line.
52
58
 
@@ -66,6 +72,8 @@ def add_reinforcement_line(
66
72
  True).
67
73
  last (bool): Boolean indicating if placing the last bar (default =
68
74
  True).
75
+ group_label (Optional(str)): A label for grouping several objects
76
+ (default is None).
69
77
 
70
78
  Note:
71
79
  At least n or s should be greater than zero.
@@ -110,6 +118,10 @@ def add_reinforcement_line(
110
118
  continue
111
119
  coords = p1 + v * s * i
112
120
  geo = add_reinforcement(
113
- geo, (coords[0], coords[1]), diameter, material
121
+ geo,
122
+ (coords[0], coords[1]),
123
+ diameter,
124
+ material,
125
+ group_label=group_label,
114
126
  )
115
127
  return geo
@@ -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._Iy / ymax
232
- self._Welz = self._Iz / xmax
231
+ self._Wely = self.Iy / ymax
232
+ self._Welz = self.Iz / xmax
233
233
 
234
234
  @property
235
235
  def Wely(self) -> float:
@@ -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 (positive and negative)."""
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, -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 if a
80
- single value is provided the same is adopted for both positive
81
- and negative strains.
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), -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
- eps_su_p = eps_su[0]
91
- eps_su_n = eps_su[1]
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 = (eps_su_p, eps_su_n)
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
- eps_sy_p, eps_sy_n = self.get_ultimate_strain(yielding=True)
189
- eps_su_p, eps_su_n = self.get_ultimate_strain()
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 (positive and negative)."""
237
+ """Return the ultimate strain (negative and positive)."""
237
238
  if yielding:
238
- return (self._eps_sy, -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, -self._eps_sy * 2)
242
- return (self._eps_su, -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 (positive and negative)."""
403
+ """Return the ultimate strain (negative and positive)."""
403
404
  if yielding:
404
- return (100, self._eps_0)
405
- return (100, self._eps_u)
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 (positive and negative)."""
513
+ """Return the ultimate strain (negative and positive)."""
513
514
  if yielding:
514
- return (100, self._eps_c)
515
- return (100, self._eps_cu)
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 (positive and negative)."""
606
+ """Return the ultimate strain (negative and positive)."""
606
607
  if yielding:
607
- return (100, self._eps_c1)
608
- return (100, self._eps_cu1)
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 (positive and negative)."""
717
+ """Return the ultimate strain (negative and positive)."""
717
718
  if yielding:
718
- return (100, self._eps_c)
719
- return (100, self._eps_cu)
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 (positive and negative)."""
879
+ """Return the ultimate strain (negative and positive)."""
879
880
  del kwargs
880
- return (self._ultimate_strain_p, self._ultimate_strain_n)
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 if a
889
- single value is provided the same is adopted for both positive
890
- and negative strains.
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
- eps_su_p = eps_su[0]
901
- eps_su_n = eps_su[1]
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',
@@ -2,9 +2,9 @@
2
2
 
3
3
  from __future__ import annotations # To have clean hints of ArrayLike in docs
4
4
 
5
+ import math
5
6
  import typing as t
6
7
  import warnings
7
- from math import cos, sin
8
8
 
9
9
  import numpy as np
10
10
  from numpy.typing import ArrayLike
@@ -208,7 +208,13 @@ class GenericSectionCalculator(SectionCalculator):
208
208
  )
209
209
  # Change sign due to moment sign convention
210
210
  izz *= -1
211
- if abs(abs(izy) - abs(iyz)) > 10:
211
+
212
+ # Compute reasonable value for absolute tolerance for checking iyz
213
+ rel_tol = 1e-9
214
+ abs_tol = 0.5 * (iyy + izz) * rel_tol
215
+
216
+ # Check calculated cross moment
217
+ if not math.isclose(iyz, izy, rel_tol=rel_tol, abs_tol=abs_tol):
212
218
  error_str = 'Something went wrong with computation of '
213
219
  error_str += f'moments of area: iyz = {iyz}, izy = {izy}.\n'
214
220
  error_str += 'They should be equal but are not!'
@@ -291,14 +297,14 @@ class GenericSectionCalculator(SectionCalculator):
291
297
  for g in geom.geometries + geom.point_geometries:
292
298
  for other_g in geom.geometries + geom.point_geometries:
293
299
  # if g != other_g:
294
- eps_p = g.material.get_ultimate_strain(yielding=yielding)[0]
300
+ eps_p = g.material.get_ultimate_strain(yielding=yielding)[1]
295
301
  if isinstance(g, SurfaceGeometry):
296
302
  y_p = g.polygon.bounds[1]
297
303
  elif isinstance(g, PointGeometry):
298
304
  y_p = g._point.coords[0][1]
299
305
  eps_n = other_g.material.get_ultimate_strain(
300
306
  yielding=yielding
301
- )[1]
307
+ )[0]
302
308
  if isinstance(other_g, SurfaceGeometry):
303
309
  y_n = other_g.polygon.bounds[3]
304
310
  elif isinstance(other_g, PointGeometry):
@@ -574,7 +580,12 @@ class GenericSectionCalculator(SectionCalculator):
574
580
  """Rotate triangulated data of angle theta."""
575
581
  rotated_triangulated_data = []
576
582
  for tr in self.triangulated_data:
577
- T = np.array([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]])
583
+ T = np.array(
584
+ [
585
+ [np.cos(theta), -np.sin(theta)],
586
+ [np.sin(theta), np.cos(theta)],
587
+ ]
588
+ )
578
589
  coords = np.vstack((tr[0], tr[1]))
579
590
  coords_r = T @ coords
580
591
  rotated_triangulated_data.append(
@@ -610,8 +621,8 @@ class GenericSectionCalculator(SectionCalculator):
610
621
  axial load.
611
622
 
612
623
  Arguments:
613
- theta (float): Inclination of n.a. respect to section y axis,
614
- default = 0.
624
+ theta (float): Inclination of n.a. respect to section y axis in
625
+ radians, default = 0.
615
626
  n (float): Axial load applied to the section (+: tension, -:
616
627
  compression), default = 0.
617
628
 
@@ -636,7 +647,9 @@ class GenericSectionCalculator(SectionCalculator):
636
647
  )
637
648
 
638
649
  # Rotate back to section CRS TODO Check
639
- T = np.array([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]])
650
+ T = np.array(
651
+ [[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]
652
+ )
640
653
  M = T @ np.array([[My], [Mz]])
641
654
  if self.triangulated_data is not None:
642
655
  # Rotate back also triangulated data!
@@ -667,7 +680,8 @@ class GenericSectionCalculator(SectionCalculator):
667
680
  n.a. and axial load.
668
681
 
669
682
  Arguments:
670
- theta (float): Inclination of n.a. respect to y axis, default = 0.
683
+ theta (float): Inclination of n.a. respect to y axis in radians,
684
+ default = 0.
671
685
  n (float): Axial load applied to the section (+: tension, -:
672
686
  compression), default = 0.
673
687
  chi_first (float): The first value of the curvature, default =
@@ -770,7 +784,12 @@ class GenericSectionCalculator(SectionCalculator):
770
784
  geo=rotated_geom, strain=strain, tri=self.triangulated_data
771
785
  )
772
786
  # Rotate back to section CRS
773
- T = np.array([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]])
787
+ T = np.array(
788
+ [
789
+ [np.cos(theta), -np.sin(theta)],
790
+ [np.sin(theta), np.cos(theta)],
791
+ ]
792
+ )
774
793
  M = T @ np.array([[My], [Mz]])
775
794
  eps_a[i] = strain[0]
776
795
  my[i] = M[0, 0]
@@ -866,7 +885,7 @@ class GenericSectionCalculator(SectionCalculator):
866
885
  """Calculate the NM interaction domain.
867
886
 
868
887
  Arguments:
869
- theta (float): Inclination of n.a. respect to y axis
888
+ theta (float): Inclination of n.a. respect to y axis in radians
870
889
  (Optional, default = 0).
871
890
  num_1 (int): Number of strain profiles in field 1
872
891
  (Optional, default = 1).
@@ -913,7 +932,7 @@ class GenericSectionCalculator(SectionCalculator):
913
932
  )
914
933
 
915
934
  # Get ultimate strain profiles for theta angle
916
- strains = self._compute_ultimate_strain_profiles(
935
+ strains, field_num = self._compute_ultimate_strain_profiles(
917
936
  theta=theta,
918
937
  num_1=num_1,
919
938
  num_2=num_2,
@@ -948,9 +967,8 @@ class GenericSectionCalculator(SectionCalculator):
948
967
 
949
968
  # Save to results
950
969
  res.strains = strains
951
- res.m_z = forces[:, 2]
952
- res.m_y = forces[:, 1]
953
- res.n = forces[:, 0]
970
+ res.forces = forces
971
+ res.field_num = field_num
954
972
 
955
973
  return res
956
974
 
@@ -1047,6 +1065,9 @@ class GenericSectionCalculator(SectionCalculator):
1047
1065
  raise ValueError(f'Type of spacing not known: {type}')
1048
1066
 
1049
1067
  # For generation of fields 1 and 2 pivot on positive strain
1068
+ field_num = np.repeat(
1069
+ [1, 2, 3, 4, 5, 6], [num_1, num_2, num_3, num_4, num_5, num_6]
1070
+ )
1050
1071
  # Field 1: pivot on positive strain
1051
1072
  eps_n = _np_space(eps_p_b, 0, num_1, type_1, endpoint=False)
1052
1073
  eps_p = np.zeros_like(eps_n) + eps_p_b
@@ -1098,16 +1119,17 @@ class GenericSectionCalculator(SectionCalculator):
1098
1119
  eps_n = np.append(eps_n, eps_n_6)
1099
1120
  eps_p = np.append(eps_p, eps_p_6)
1100
1121
 
1101
- # rotate them
1122
+ # compute strain components
1102
1123
  kappa_y = (eps_n - eps_p) / (y_n - y_p)
1103
1124
  eps_a = eps_n - kappa_y * y_n
1104
- kappa_z = np.zeros_like(kappa_y)
1105
1125
 
1106
1126
  # rotate back components to work in section CRS
1107
- T = np.array([[cos(theta), -sin(theta)], [sin(theta), cos(theta)]])
1108
- components = np.vstack((kappa_y, kappa_z))
1127
+ T = np.array(
1128
+ [[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]
1129
+ )
1130
+ components = np.vstack((kappa_y, np.zeros_like(kappa_y)))
1109
1131
  rotated_components = T @ components
1110
- return np.column_stack((eps_a, rotated_components.T))
1132
+ return np.column_stack((eps_a, rotated_components.T)), field_num
1111
1133
 
1112
1134
  def calculate_nmm_interaction_domain(
1113
1135
  self,
@@ -1180,7 +1202,7 @@ class GenericSectionCalculator(SectionCalculator):
1180
1202
  strains = np.empty((0, 3))
1181
1203
  for theta in thetas:
1182
1204
  # Get ultimate strain profiles for theta angle
1183
- strain = self._compute_ultimate_strain_profiles(
1205
+ strain, field_num = self._compute_ultimate_strain_profiles(
1184
1206
  theta=theta,
1185
1207
  num_1=num_1,
1186
1208
  num_2=num_2,
@@ -1216,6 +1238,7 @@ class GenericSectionCalculator(SectionCalculator):
1216
1238
  # Save to results
1217
1239
  res.strains = strains
1218
1240
  res.forces = forces
1241
+ res.field_num = field_num
1219
1242
 
1220
1243
  return res
1221
1244
 
@@ -1234,16 +1257,21 @@ class GenericSectionCalculator(SectionCalculator):
1234
1257
  # Prepare the results
1235
1258
  res = s_res.MMInteractionDomain()
1236
1259
  res.num_theta = num_theta
1237
- res.n = n
1238
1260
  # Create array of thetas
1239
1261
  res.theta = np.linspace(0, np.pi * 2, num_theta)
1240
1262
  # Initialize the result's arrays
1241
- res.m_y = np.zeros_like(res.theta)
1242
- res.m_z = np.zeros_like(res.theta)
1263
+ res.forces = np.zeros((num_theta, 3))
1264
+ res.strains = np.zeros((num_theta, 3))
1243
1265
  # Compute strength for given angle of NA
1244
1266
  for i, th in enumerate(res.theta):
1245
1267
  res_bend_strength = self.calculate_bending_strength(theta=th, n=n)
1246
- res.m_y[i] = res_bend_strength.m_y
1247
- res.m_z[i] = res_bend_strength.m_z
1268
+ # Save forces
1269
+ res.forces[i, 0] = n
1270
+ res.forces[i, 1] = res_bend_strength.m_y
1271
+ res.forces[i, 2] = res_bend_strength.m_z
1272
+ # Save strains
1273
+ res.strains[i, 0] = res_bend_strength.eps_a
1274
+ res.strains[i, 1] = res_bend_strength.chi_y
1275
+ res.strains[i, 2] = res_bend_strength.chi_z
1248
1276
 
1249
1277
  return res
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: structuralcodes
3
- Version: 0.0.2
3
+ Version: 0.1.1
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
- [![Build](https://github.com/fib-international/structuralcodes/actions/workflows/build.yaml/badge.svg)](https://github.com/fib-international/structuralcodes/actions/workflows/build.yaml)
20
+ [![PyPI version](https://badge.fury.io/py/structuralcodes.svg)](https://badge.fury.io/py/structuralcodes)
21
21
  [![Code style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/format.json)](https://github.com/charliermarsh/ruff)
22
22
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/charliermarsh/ruff)
23
23
  [![Docs](https://img.shields.io/badge/%F0%9F%93%9A%20docs-fib--international.github.io%2Fstructuralcodes%2F-orange)](https://fib-international.github.io/structuralcodes/)
24
24
 
25
+ [![Tests](https://github.com/fib-international/structuralcodes/actions/workflows/build.yaml/badge.svg)](https://github.com/fib-international/structuralcodes/actions/workflows/build.yaml)
26
+ [![Publish](https://github.com/fib-international/structuralcodes/actions/workflows/create-release.yml/badge.svg)](https://github.com/fib-international/structuralcodes/actions/workflows/create-release.yml)
27
+ [![Docs](https://github.com/fib-international/structuralcodes/actions/workflows/sphinx.yml/badge.svg)](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
+
@@ -1,31 +1,33 @@
1
- structuralcodes/__init__.py,sha256=iRaPZQiBsPlIMdiaTPyWPg9WtJ6izQ200aKbu4WXQpA,390
2
- structuralcodes/codes/__init__.py,sha256=D2lYPJ2IOgughWugFWQaHjz90zIl7gLX2Rrz53TvstA,1917
1
+ structuralcodes/__init__.py,sha256=4WhcwbLVv6pNyZiQjaNHUXYs0YzQTVU0kkM9EMA9ZyE,390
2
+ structuralcodes/codes/__init__.py,sha256=g5xMAJ3jEZHFd0cypvZY6lMCi7XeVEntsO8zHzI2mWc,2803
3
3
  structuralcodes/codes/ec2_2004/__init__.py,sha256=_PdL9kX7qlfn9VBfqUCJQy6V9fWmIyugzIiSZczjNAA,1986
4
4
  structuralcodes/codes/ec2_2004/_concrete_material_properties.py,sha256=Ol51tzcVOHUvc2Vea24WQJ4FABxXc-9cB5RVu2N1pio,5964
5
5
  structuralcodes/codes/ec2_2004/_reinforcement_material_properties.py,sha256=_ZlvdHcOswu1Ge1XjSvt4j5ue-znDceMOlA0s528IqM,2779
6
6
  structuralcodes/codes/ec2_2004/_section_7_3_crack_control.py,sha256=a91tWQKNTxB2SpSKu0Wtm-P5GdmifRLggNlEHIQ3XMY,31981
7
- structuralcodes/codes/ec2_2004/annex_b_shrink_and_creep.py,sha256=Vht8VjmpHNRl7-AirTm2buJl1RzL76AbW6-XgdDK6Kg,7348
8
- structuralcodes/codes/ec2_2004/shear.py,sha256=uA9a5Po5X4ysp5pDI8HB0pBjI9Z9txxhPD_joLTM8O0,16910
7
+ structuralcodes/codes/ec2_2004/annex_b_shrink_and_creep.py,sha256=kaMXZ_Ufp-k1wYQDXB27Tt2BUmi_lGYYuNzQxGtC6SQ,7348
8
+ structuralcodes/codes/ec2_2004/shear.py,sha256=gzhgIa-EgoD9gLO_Hfa8VeCmjAxuPK0wZ0soDKC7W5w,17095
9
9
  structuralcodes/codes/ec2_2023/__init__.py,sha256=UohRxikCUqPAUpHj4uSWHw5drICjZm3zvJJw7clljo0,1618
10
10
  structuralcodes/codes/ec2_2023/_annexB_time_dependent.py,sha256=ykRAHBHzqtMSErkVA-rwTHBdUq8-L7q2AOaEd2YW5wc,472
11
11
  structuralcodes/codes/ec2_2023/_section5_materials.py,sha256=-vYowBVcebyPyuGvX3wLfxiePdM0OrBgRrYil71Vd88,32384
12
12
  structuralcodes/codes/ec2_2023/_section9_sls.py,sha256=l1d3xcALAweU9jAAf1d91TJaGB_0p-eMzbRGuhfKydQ,11252
13
13
  structuralcodes/codes/mc2010/__init__.py,sha256=g2J2GTIy9jbLTVq_yF4DXau4WLmAkpmMTgnD4QmW2vI,2844
14
- structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py,sha256=7VRzXGjGAM7JkfMcgWvntq4PC2n7VVtSS7CHQuxZaHM,23193
14
+ structuralcodes/codes/mc2010/_concrete_creep_and_shrinkage.py,sha256=wFTVHfJKIyt0jUGthd1gWKfr4JfoFo9YN6d3nL6Ouq4,23277
15
15
  structuralcodes/codes/mc2010/_concrete_interface_different_casting_times.py,sha256=x_n9Z9WEPY6DFf8Og5UIERPivNh-O_3RM4ZnGBy64cs,3570
16
16
  structuralcodes/codes/mc2010/_concrete_material_properties.py,sha256=MTz70-9iaN_s0Z8gJksCEzP0Yza4pPfZ-vOI30pzbw4,12362
17
17
  structuralcodes/codes/mc2010/_concrete_punching.py,sha256=ZG2P7WXIRcFh5sGlmHP20BsJbz0o44cFO51FCru2kXw,17431
18
18
  structuralcodes/codes/mc2010/_concrete_shear.py,sha256=HZhhpzQd-09NPrHpSK5fnPA1epVCQH8JfdSi6bpgiFg,21883
19
19
  structuralcodes/codes/mc2010/_concrete_torsion.py,sha256=QBFnCYTOnP6FjN0MgX9iBrXN1yuELxQVP2TeDXDB7PM,4523
20
20
  structuralcodes/codes/mc2010/_reinforcement_material_properties.py,sha256=FELmgMcCrHlajGwQNRRHb8nqKnMCsLso1OyjonsTAdk,2842
21
+ structuralcodes/codes/mc2020/__init__.py,sha256=5hrAfBtAeG69N_lroFpG10_ZKB1SuNlKBnuHug2DI3E,174
21
22
  structuralcodes/core/__init__.py,sha256=spnvZIm_w3jX_lV-v3bloDjgHh8lrH6UHpA1Nv1zeAI,55
22
- structuralcodes/core/_section_results.py,sha256=FCYivFY6e2JFF5Nl9dUZNytgTT_-UeDOEc79czX1Lxg,6978
23
- structuralcodes/core/base.py,sha256=0QcYgYtmU5fK039a8QxrPM4Fa-ZpMUp2ez0XmpaCT_0,8562
24
- structuralcodes/geometry/__init__.py,sha256=B6zKtPQy_OgsKz-fhbvZs7gSnADQPNTQwCMDF1yp-Lo,434
25
- structuralcodes/geometry/_geometry.py,sha256=PcSMaxlacEJ5jxURWaVFtL3AxOpzbykMtDtnEi04iAU,30818
26
- structuralcodes/geometry/_steel_sections.py,sha256=RjecVItWDjKT2rC2U6cvo0NtNHuUygY1pfybLUKJBUM,60227
23
+ structuralcodes/core/_section_results.py,sha256=hHXoS71TpSmWqw276pBeLiLrEEiMEWclOd28ArRW_Kk,8280
24
+ structuralcodes/core/base.py,sha256=TqgsXzIXITQmER3tKNjzjPrbSN5uT_PqCpG3PVMd3Yw,8562
25
+ structuralcodes/geometry/__init__.py,sha256=FwzywfyGKOk6v96ZyOfyBo5iVeuK_W0TQVz5llAkYW4,559
26
+ structuralcodes/geometry/_geometry.py,sha256=kmY7TER5yS-TVw0XY4EuwNviLuEhExtLoon8oO2TJbA,31175
27
+ structuralcodes/geometry/_reinforcement.py,sha256=N2wTH-NoZ1fG-_vRT9gGX2Kk3zlW7CbDtl1oqS_lMv0,4144
28
+ structuralcodes/geometry/_steel_sections.py,sha256=UdJmhhnK8r5gEfBzvWsMFHGs5gmuoOhFoduBanlRMQg,60225
27
29
  structuralcodes/materials/__init__.py,sha256=r5E5vsXVKB-BGZXTnEbsrYJbH6rr6Xlc_b4LlcUPIbc,173
28
- structuralcodes/materials/constitutive_laws.py,sha256=JSCbBvFbDQqDkqiOtmJykHgtKqxRZu8Fh0GMpQP4gSU,34285
30
+ structuralcodes/materials/constitutive_laws.py,sha256=DX_yuC4OpgDCl_g3sl0Hi2ee7lFD2fy3yO4PTINKBzE,34455
29
31
  structuralcodes/materials/concrete/__init__.py,sha256=GRD5WcbYrnE4iN-L7qVkhVTi7w_PUP7pnbGueOaVeFs,2576
30
32
  structuralcodes/materials/concrete/_concrete.py,sha256=3zMTFtaqFeUl7ne7-pe9wF4LryzqvGpUwThnHTidCZU,3774
31
33
  structuralcodes/materials/concrete/_concreteEC2_2004.py,sha256=gWG3O9yeGw3UeftCjYTajZco_XYDmBxPGqhAEpH3nY0,14666
@@ -36,15 +38,14 @@ structuralcodes/materials/reinforcement/_reinforcement.py,sha256=zrSdBvHKTYqOHpk
36
38
  structuralcodes/materials/reinforcement/_reinforcementEC2_2004.py,sha256=svLpubjaTH_DepwY68TQIA8fRwadoAE3Y3KsyViGQHk,3265
37
39
  structuralcodes/materials/reinforcement/_reinforcementEC2_2023.py,sha256=3tKpFcMNYK52s5K2K_PctRcuSgwZTe-QXX3xziHPUno,2887
38
40
  structuralcodes/materials/reinforcement/_reinforcementMC2010.py,sha256=az_IAQJNKSF6Vv9KMoXjWTdYkWI6xcEm7s8i8GETn3A,2939
39
- structuralcodes/sections/__init__.py,sha256=401eBeFFzG-Xvj26HUIT_SwuSsSz_nERrl9pj129oME,566
40
- structuralcodes/sections/_generic.py,sha256=f-F9yMIxByY18s6RnHExv2Pvhe_dsCInXiaS6Phb74E,49033
41
- structuralcodes/sections/_reinforcement.py,sha256=8Xes3N8zm85bJVu_bgVNzMs4zo2zPv17xadw2I9CnE0,3739
41
+ structuralcodes/sections/__init__.py,sha256=qPoD5eS31at-uveYtxtVkXGLNHPrIMRrxGYY3wOLQ4s,441
42
+ structuralcodes/sections/_generic.py,sha256=jpubO8wBsVWJajpOkUYzBpunf4ltse8rmiNFyiwDuoI,49968
42
43
  structuralcodes/sections/section_integrators/__init__.py,sha256=PK4ixV0XrfHXN-itIrB1r90npoWo3aIJqMcenqcaees,399
43
44
  structuralcodes/sections/section_integrators/_factory.py,sha256=MHp14hfWU-oXTiIutCKLJEC47LirYsHgEAAmHVtnFMY,1242
44
45
  structuralcodes/sections/section_integrators/_fiber_integrator.py,sha256=5sxcfbmxMJfy45Pfd84I4sAh6HpPc5B4r6ab0WpjSNI,9305
45
46
  structuralcodes/sections/section_integrators/_marin_integration.py,sha256=SZgya6d_Tequ3jez7UEBlYioZepW2IDKaAxn_6WrMbU,1563
46
47
  structuralcodes/sections/section_integrators/_marin_integrator.py,sha256=rtEtd1X0QYAWNcaH7Pjd_b6LEzVjHqD_fbIrX64p7fg,9121
47
48
  structuralcodes/sections/section_integrators/_section_integrator.py,sha256=O-jsG1Pu_doovgRJsFG1Sf0KlkN2wNfQdmgkJiSHNN0,1590
48
- structuralcodes-0.0.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
49
- structuralcodes-0.0.2.dist-info/METADATA,sha256=PCsKsfFf9xBbl9Ab2W0xumVRjJvNyFOHmhU96mSnS-E,1811
50
- structuralcodes-0.0.2.dist-info/RECORD,,
49
+ structuralcodes-0.1.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
50
+ structuralcodes-0.1.1.dist-info/METADATA,sha256=CDs31oS5sYYBt1hk-gRLTGPJtfa6SiM1H5QP3IlGecI,2444
51
+ structuralcodes-0.1.1.dist-info/RECORD,,