structuralcodes 0.2.0__py3-none-any.whl → 0.3.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.2.0'
6
+ __version__ = '0.3.1'
7
7
 
8
8
  __all__ = [
9
9
  'set_design_code',
@@ -62,7 +62,7 @@ def eps_cd(
62
62
  return beta_ds * k_h * eps_cd_0
63
63
 
64
64
 
65
- def beta_ds(t: npt.ArrayLike, t_s: float, h_0: float):
65
+ def beta_ds(t: npt.ArrayLike, t_s: float, h_0: float) -> npt.ArrayLike:
66
66
  """Calculate the coefficient taking into account the time of drying.
67
67
 
68
68
  EN 1992-1-1:2004, Eq. (3.10).
@@ -180,41 +180,52 @@ def _check_env_temp(T: float) -> None:
180
180
 
181
181
 
182
182
  def t_T(
183
- t0: npt.ArrayLike, T_cur: npt.ArrayLike, dt: npt.ArrayLike = None
184
- ) -> np.ndarray:
185
- """Calculate the temperature corrected concrete age in days at t0.
183
+ T_cur: t.Union[npt.ArrayLike, float],
184
+ dt: t.Union[npt.ArrayLike, float],
185
+ ) -> float:
186
+ """Calculate the temperature corrected concrete age in days.
186
187
 
187
- Defined in fib Model Code 2010 (2013). Eq. 5.1-85 (only for a single time
188
- value input, as required in Eq. 5.1-73).
188
+ Defined in fib Model Code 2010 (2013). Eq. 5.1-85.
189
189
 
190
190
  Args:
191
- t0 (np.typing.ArrayLike): The age of the concrete in days at which the
192
- loading is applied.
193
- T_cur (np.typing.ArrayLike): The temperature of the environment during
194
- curing in degrees Celcius.
195
-
196
- Keyword Args:
197
- dt (np.typing.ArrayLike): Number of days at which T_cur prevails.
198
- Required when providing a list for T_cur.
191
+ T_cur (Union(ArrayLike, float)): The temperature of the environment
192
+ during curing in degrees Celcius.
193
+ dt (Union(ArrayLike, float)): Number of days at which T_cur
194
+ prevails.
199
195
 
200
196
  Returns:
201
- np.ndarray: The temperature corrected age of the concrete in days at
197
+ float: The temperature corrected age of the concrete in days at
202
198
  loading.
203
199
  """
204
- _check_age_at_loading(t0)
205
- if dt is None:
206
- dt = t0
207
- else:
208
- T_cur = np.asarray(T_cur)
209
- dt = np.asarray(dt)
210
- if T_cur.size != dt.size:
211
- raise ValueError('Dimensions of T_cur and dt do not match.')
212
- if np.sum(dt) != t0:
213
- raise ValueError(
214
- f'Curing time {np.sum(dt)} and time of loading {t0} do not'
215
- ' match.'
200
+ # Prepare the input
201
+ T_cur = T_cur if np.isscalar(T_cur) else np.atleast_1d(T_cur)
202
+ dt = dt if np.isscalar(dt) else np.atleast_1d(dt)
203
+
204
+ # Check that both are scalar or both are arrays
205
+ if any(np.isscalar(this_check) for this_check in (T_cur, dt)) and any(
206
+ not np.isscalar(this_check) for this_check in (T_cur, dt)
207
+ ):
208
+ raise ValueError(
209
+ (
210
+ f'T ({type(T_cur)}) and dt ({type(dt)}) should either both be '
211
+ 'ArrayLike or scalars.'
216
212
  )
217
- return np.sum(dt * np.exp(13.65 - (4000 / (273 + T_cur))))
213
+ )
214
+
215
+ # Check the shape of the input arrays
216
+ if (
217
+ not all((np.isscalar(T_cur), np.isscalar(dt)))
218
+ and T_cur.shape != dt.shape
219
+ ):
220
+ raise ValueError(
221
+ f'T_cur {T_cur.shape} and dt {dt.shape} should have the same '
222
+ 'shape.'
223
+ )
224
+
225
+ # Return the sum of the temperature adjusted time increments
226
+ if not all((np.isscalar(T_cur), np.isscalar(dt))):
227
+ return float(np.sum(np.exp(13.65 - 4000 / (273 + T_cur)) * dt))
228
+ return np.exp(13.65 - 4000 / (273 + T_cur)) * dt
218
229
 
219
230
 
220
231
  def t0_adj(
@@ -274,25 +285,29 @@ def eps_cds0(
274
285
 
275
286
 
276
287
  def beta_ds(
277
- time: npt.ArrayLike, ts: float, notional_size: float
278
- ) -> np.ndarray:
288
+ time: t.Union[npt.ArrayLike, float], ts: float, notional_size: float
289
+ ) -> t.Union[npt.ArrayLike, float]:
279
290
  """Calculate the multiplication factor beta_ds.
280
291
 
281
292
  Defined in fib Model Code 2010 (2013), Eq. 5.1-82.
282
293
 
283
294
  Args:
284
- time (numpy.typing.ArrayLike): The different times in days at which the
285
- shrinkage strain is determined.
295
+ time (Union(ArrayLike, float)): The different times in days at which
296
+ the shrinkage strain is determined.
286
297
  ts (float): Age of the concrete when exposed to the environment.
287
298
  notional_size (float): The notional size of the considered element in
288
299
  mm, defined as 2A/u.
289
300
 
290
301
  Returns:
291
- numpy.ndarray: Multiplication factor used for calculating the drying
292
- shrinkage as a function of time.
302
+ Union(ArrayLike, float): Multiplication factor used for calculating the
303
+ drying shrinkage as a function of time.
293
304
  """
294
- time_drying = np.atleast_1d(time - ts)
295
- time_drying[time_drying < 0.0] = 0.0
305
+ time = time if np.isscalar(time) else np.atleast_1d(time)
306
+ time_drying = time - ts
307
+ if np.isscalar(time_drying):
308
+ time_drying = max(time_drying, 0.0)
309
+ else:
310
+ time_drying[time_drying < 0.0] = 0.0
296
311
  return np.sqrt(time_drying / (0.035 * (notional_size) ** 2 + time_drying))
297
312
 
298
313
 
@@ -341,9 +356,9 @@ def beta_RH(rh: float, beta_s1: float) -> float:
341
356
 
342
357
  def eps_cds(
343
358
  eps_cds0: float,
344
- beta_ds: npt.ArrayLike,
359
+ beta_ds: t.Union[npt.ArrayLike, float],
345
360
  beta_rh: float,
346
- ) -> np.ndarray:
361
+ ) -> t.Union[npt.ArrayLike, float]:
347
362
  """Calculate the drying shrinkage of the concrete element.
348
363
 
349
364
  Defined in fib Model Code 2010 (2013), Eqs. 5.1-77.
@@ -351,15 +366,15 @@ def eps_cds(
351
366
  Args:
352
367
  eps_cds0 (float): The notional drying shrinkage, no units, as defined
353
368
  in fib Model Code 2010 (2013), Eq. 5.1-80.
354
- beta_ds (numpy.typing.ArrayLike): Multiplication factor used for
369
+ beta_ds (Union(ArrayLike, float)): Multiplication factor used for
355
370
  calculating the drying shrinkage as a function of time, as defined
356
371
  in fib Model Code 2010 (2013), Eq. 5.1-82.
357
372
  beta_rh (float): Multiplication factor used when calculating the
358
373
  drying shrinkage.
359
374
 
360
375
  Returns:
361
- numpy.ndarray: The drying shrinkage strains for the given times, no
362
- units.
376
+ Union(ArrayLike, float): The drying shrinkage strains for the given
377
+ times, no units.
363
378
  """
364
379
  return eps_cds0 * beta_rh * beta_ds
365
380
 
@@ -386,24 +401,28 @@ def eps_cbs0(
386
401
  return -ALPHA_BS[cem_class] * ((0.1 * fcm) / (6 + 0.1 * fcm)) ** 2.5 * 1e-6
387
402
 
388
403
 
389
- def beta_bs(time: npt.ArrayLike) -> np.ndarray:
404
+ def beta_bs(
405
+ time: t.Union[npt.ArrayLike, float],
406
+ ) -> t.Union[npt.ArrayLike, float]:
390
407
  """Calculate multiplication factor beta_bs which is used to determine the
391
408
  basic shrinkage.
392
409
 
393
410
  Defined in fib Model Code 2010 (2013), Eq. 5.1-79.
394
411
 
395
412
  Args:
396
- time (numpy.typing.ArrayLike): The different times in days at which the
397
- basic strain is determined.
413
+ time (Union(ArrayLike, float)): The different times in days at which
414
+ the basic strain is determined.
398
415
 
399
416
  Returns:
400
- numpy.ndarray: Multiplication factor that is used to determine the
401
- basic shrinkage.
417
+ Union(ArrayLike, float): Multiplication factor that is used to
418
+ determine the basic shrinkage.
402
419
  """
403
420
  return 1 - np.exp(-0.2 * np.sqrt(time))
404
421
 
405
422
 
406
- def eps_cbs(eps_cbs0: float, beta_bs: npt.ArrayLike) -> np.ndarray:
423
+ def eps_cbs(
424
+ eps_cbs0: float, beta_bs: t.Union[npt.ArrayLike, float]
425
+ ) -> t.Union[npt.ArrayLike, float]:
407
426
  """Calculate the basic shrinkage.
408
427
 
409
428
  Defined in fib Model Code 2010 (2013), Eqs. 5.1-76.
@@ -411,11 +430,12 @@ def eps_cbs(eps_cbs0: float, beta_bs: npt.ArrayLike) -> np.ndarray:
411
430
  Args:
412
431
  eps_cbs0 (float): Notional basic shrinkage, as defined in fib Model
413
432
  Code 2010 (2013), Eq. 5.1-78.
414
- beta_bs (numpy.typing.ArrayLike): Time function for basic shrinkage,
433
+ beta_bs (Union(ArrayLike, float)): Time function for basic shrinkage,
415
434
  as defined in fib Model Code 2010 (2013), Eq. 5.1-79.
416
435
 
417
436
  Returns:
418
- numpy.ndarray: The basic shrinkage strains for the given times.
437
+ Union(ArrayLike, float): The basic shrinkage strains for the given
438
+ times.
419
439
  """
420
440
  return eps_cbs0 * beta_bs
421
441
 
@@ -436,15 +456,17 @@ def beta_bc_fcm(fcm: float) -> float:
436
456
  return 1.8 / fcm**0.7
437
457
 
438
458
 
439
- def beta_bc_t(time: npt.ArrayLike, t0: float, t0_adj: float) -> np.ndarray:
459
+ def beta_bc_t(
460
+ time: t.Union[npt.ArrayLike, float], t0: float, t0_adj: float
461
+ ) -> t.Union[npt.ArrayLike, float]:
440
462
  """Calculate multiplication factor that accounts for the effect of the age
441
463
  of the of the concrete to calculate the basic creep coefficient.
442
464
 
443
465
  Defined in fib Model Code 2010 (2013), Eq. 5.1-66.
444
466
 
445
467
  Args:
446
- time (numpy.typing.ArrayLike): The different times in days at which the
447
- basic creep coefficient is determined.
468
+ time (Union(ArrayLike, float)): The different times in days at which
469
+ the basic creep coefficient is determined.
448
470
  t0 (float): The age of the concrete in days at which the loading is
449
471
  applied.
450
472
  t0_adj (float): The temperature corrected age of the concrete when the
@@ -452,12 +474,14 @@ def beta_bc_t(time: npt.ArrayLike, t0: float, t0_adj: float) -> np.ndarray:
452
474
  (2013). Eq. 5.1-85.
453
475
 
454
476
  Returns:
455
- numpy.ndarray: Multiplication factors beta_bc_t.
477
+ Union(ArrayLike, float): Multiplication factors beta_bc_t.
456
478
  """
457
479
  return np.log(((30 / t0_adj + 0.035) ** 2) * (time - t0) + 1)
458
480
 
459
481
 
460
- def phi_bc(beta_bc_fcm: float, beta_bc_t: npt.ArrayLike) -> np.ndarray:
482
+ def phi_bc(
483
+ beta_bc_fcm: float, beta_bc_t: t.Union[npt.ArrayLike, float]
484
+ ) -> t.Union[npt.ArrayLike, float]:
461
485
  """Calculate the basic creep coefficient.
462
486
 
463
487
  Defined in fib Model Code 2010 (2013), Eq. 5.1-64.
@@ -466,12 +490,12 @@ def phi_bc(beta_bc_fcm: float, beta_bc_t: npt.ArrayLike) -> np.ndarray:
466
490
  beta_bc_fcm (float): Multiplication factor that accounts for the
467
491
  influence of the concrete strength of the creep behaviour, as
468
492
  defined in fib Model Code 2010 (2013), Eq. 5.1-65.
469
- beta_bc_t (numpy.typing.ArrayLike): Multiplication factor that
493
+ beta_bc_t (Union(ArrayLike, float)): Multiplication factor that
470
494
  accounts for the influence of the age of the concrete of the creep
471
495
  behaviour, as defined in fib Model Code 2010 (2013), Eq. 5.1-66.
472
496
 
473
497
  Returns:
474
- numpy.ndarray: The basic creep coefficient.
498
+ Union(ArrayLike, float): The basic creep coefficient.
475
499
  """
476
500
  return beta_bc_fcm * beta_bc_t
477
501
 
@@ -583,16 +607,19 @@ def gamma_t0(t0_adj: float) -> float:
583
607
 
584
608
 
585
609
  def beta_dc_t(
586
- time: npt.ArrayLike, t0: float, beta_h: float, gamma_t0: float
587
- ) -> np.ndarray:
610
+ time: t.Union[npt.ArrayLike, float],
611
+ t0: float,
612
+ beta_h: float,
613
+ gamma_t0: float,
614
+ ) -> t.Union[npt.ArrayLike, float]:
588
615
  """Calculate multiplication factor that accounts for the different
589
616
  considered values of time. Used to calculate the drying creep coefficient.
590
617
 
591
618
  Defined in fib Model Code 2010 (2013), Eq. 5.1-71a.
592
619
 
593
620
  Args:
594
- time (numpy.typing.ArrayLike): The different times in days at which the
595
- drying creep coefficient is determined.
621
+ time (Union(ArrayLike, float)): The different times in days at which
622
+ the drying creep coefficient is determined.
596
623
  t0 (float): The age of the concrete concrete when the loading is
597
624
  applied in days.
598
625
  beta_h (float): Multiplication factor that accounts for the effect of
@@ -602,8 +629,8 @@ def beta_dc_t(
602
629
  calculated by Eq. 5.1-71b.
603
630
 
604
631
  Returns:
605
- numpy.ndarray: Multiplcation factor beta_dc_t for the considered values
606
- of time.
632
+ Union(ArrayLike, float): Multiplcation factor beta_dc_t for the
633
+ considered values of time.
607
634
  """
608
635
  return ((time - t0) / (beta_h + (time - t0))) ** gamma_t0
609
636
 
@@ -612,8 +639,8 @@ def phi_dc(
612
639
  beta_dc_fcm: float,
613
640
  beta_dc_RH: float,
614
641
  beta_dc_t0: float,
615
- beta_dc_t: npt.ArrayLike,
616
- ) -> np.ndarray:
642
+ beta_dc_t: t.Union[npt.ArrayLike, float],
643
+ ) -> t.Union[npt.ArrayLike, float]:
617
644
  """Calculate drying creep coefficient.
618
645
 
619
646
  Defined in fib Model Code 2010 (2013), Eq. 5.1-67.
@@ -628,12 +655,12 @@ def phi_dc(
628
655
  beta_dc_t0 (float): multiplication factor that accounts for the effect
629
656
  of the (temperature corrected) age of the concrete when loading is
630
657
  applied, as calculated by Eq. 5.1-70.
631
- beta_dc_t (numpy.typing.ArrayLike): multiplication factor that
658
+ beta_dc_t (Union(ArrayLike, float)): multiplication factor that
632
659
  accounts for the different considered values of time, as calculated
633
660
  by Eq. 5.1-71a.
634
661
 
635
662
  Returns:
636
- numpy.ndarray: Drying creep coeffcient.
663
+ Union(ArrayLike, float): Drying creep coeffcient.
637
664
  """
638
665
  return beta_dc_fcm * beta_dc_RH * beta_dc_t0 * beta_dc_t
639
666
 
@@ -658,8 +685,11 @@ def k_sigma(sigma: float, fcm: float) -> float:
658
685
 
659
686
 
660
687
  def phi(
661
- phi_bc: npt.ArrayLike, phi_dc: npt.ArrayLike, sigma: float, fcm: float
662
- ) -> np.ndarray:
688
+ phi_bc: t.Union[npt.ArrayLike, float],
689
+ phi_dc: t.Union[npt.ArrayLike, float],
690
+ sigma: float,
691
+ fcm: float,
692
+ ) -> t.Union[npt.ArrayLike, float]:
663
693
  """Calculate the creep coefficient distinguishing between linear and
664
694
  non-linear creep for compressive stresses sigma <= 0.4fcm, and 0.4fcm <
665
695
  sigma <= 0.6fcm, respectively.
@@ -667,16 +697,16 @@ def phi(
667
697
  Defined in fib Model Code 2010, Eqs. 5.1-63 and 5.1-74.
668
698
 
669
699
  Args:
670
- phi_bc (numpy.typing.ArrayLike): Basic creep coefficient, as defined
700
+ phi_bc (Union(ArrayLike, float)): Basic creep coefficient, as defined
671
701
  in fib Model Code 2010 (2013), Eq. 5.1-64.
672
- phi_dc (numpy.typing.ArrayLike): Drying creep coefficient, as defined
702
+ phi_dc (Union(ArrayLike, float)): Drying creep coefficient, as defined
673
703
  in fib Model Code 2010 (2013), Eq. 5.1-67.
674
704
  sigma (float): The compressive stress applied to the concrete at ts in
675
705
  MPa.
676
706
  fcm (float): The mean compressive strength of the concrete in MPa.
677
707
 
678
708
  Returns:
679
- numpy.ndarray: The creep coefficient.
709
+ Union(ArrayLike, float): The creep coefficient.
680
710
  """
681
711
  # Calculate the creep coefficient (phi) (see Eq. 5.1-63)
682
712
  _phi = phi_bc + phi_dc
@@ -687,7 +717,9 @@ def phi(
687
717
  return _phi
688
718
 
689
719
 
690
- def calc_J(E_ci_t0: float, phi: npt.ArrayLike, E_ci: float) -> np.ndarray:
720
+ def calc_J(
721
+ E_ci_t0: float, phi: t.Union[npt.ArrayLike, float], E_ci: float
722
+ ) -> t.Union[npt.ArrayLike, float]:
691
723
  """Calculate the creep compliance function.
692
724
 
693
725
  Defined in fib Model Code 2010, Eq. 5.1-61.
@@ -695,12 +727,12 @@ def calc_J(E_ci_t0: float, phi: npt.ArrayLike, E_ci: float) -> np.ndarray:
695
727
  Args:
696
728
  E_ci_t0 (float): Modulus of elasticity at time of loading t0, as
697
729
  defined in fib Model Code 2010 (2013), Eq. 5.1-56.
698
- phi (numpy.typing.ArrayLike): Creep coefficient, as defined in fib
730
+ phi (Union(ArrayLike, float)): Creep coefficient, as defined in fib
699
731
  Model Code 2010 (2013), Eq. 5.1-63.
700
732
  E_ci (float) Modulus of elasticity of the concrete at 28 days, as
701
733
  defined in fib Model Code 2010 (2013), Eq. 5.1-21.
702
734
 
703
735
  Returns:
704
- numpy.ndarray: The creep compliance function.
736
+ Union(ArrayLike, float): The creep compliance function.
705
737
  """
706
738
  return (1 / E_ci_t0) + (phi / E_ci)
@@ -8,8 +8,8 @@ from numpy.typing import ArrayLike
8
8
 
9
9
 
10
10
  @dataclass
11
- class GrossProperties:
12
- """Simple dataclass for storing gross section properties."""
11
+ class SectionProperties:
12
+ """Simple dataclass for storing section properties."""
13
13
 
14
14
  # section areas
15
15
  area: float = field(default=0, metadata={'description': 'Total area'})
@@ -108,7 +108,7 @@ class GrossProperties:
108
108
  Arguments:
109
109
  spec (str): The string specifying the format.
110
110
  """
111
- output_string = 'Gross Concrete Section Properties:\n'
111
+ output_string = 'Section Properties:\n'
112
112
  for f in fields(self):
113
113
  value = getattr(self, f.name)
114
114
  description = f.metadata.get(
@@ -120,26 +120,12 @@ class GrossProperties:
120
120
  return output_string
121
121
 
122
122
  def __str__(self) -> str:
123
- """Returns the informal string representation of the gross concrete
124
- section properties.
123
+ """Returns the informal string representation of the section
124
+ properties.
125
125
  """
126
126
  return f'{self}'
127
127
 
128
128
 
129
- @dataclass
130
- class CrackedProperties:
131
- """Simple dataclass for storing cracked section properties."""
132
-
133
- # second moments of area
134
- i_yy: float = 0
135
- i_zz: float = 0
136
- i_yz: float = 0
137
-
138
- # section cracked flexural rigidity
139
- ei_yy: float = 0
140
- ei_zz: float = 0
141
-
142
-
143
129
  @dataclass
144
130
  class MomentCurvatureResults:
145
131
  """Class for storing moment curvature results.
@@ -130,14 +130,8 @@ class ConstitutiveLaw(abc.ABC):
130
130
 
131
131
  return eps
132
132
 
133
- def __marin__(self, **kwargs):
134
- """Function for getting the strain limits and coefficients
135
- for marin integration.
136
-
137
- By default the law is discretized as a piecewise linear
138
- function. Then marin coefficients are computed based on this
139
- discretization.
140
- """
133
+ def _discretize_law(self) -> ConstitutiveLaw:
134
+ """Discretize the law as a piecewise linear function."""
141
135
 
142
136
  # Discretize the constitutive law in a "smart way"
143
137
  def find_x_lim(x, y):
@@ -179,8 +173,29 @@ class ConstitutiveLaw(abc.ABC):
179
173
  sig = self.get_stress(eps)
180
174
  from structuralcodes.materials.constitutive_laws import UserDefined
181
175
 
182
- # Return Marin coefficients for linearized version
183
- return UserDefined(eps, sig).__marin__(**kwargs)
176
+ return UserDefined(eps, sig)
177
+
178
+ def __marin__(self, **kwargs):
179
+ """Function for getting the strain limits and coefficients
180
+ for marin integration.
181
+
182
+ By default the law is discretized as a piecewise linear
183
+ function. Then marin coefficients are computed based on this
184
+ discretization.
185
+ """
186
+ piecewise_law = self._discretize_law()
187
+ return piecewise_law.__marin__(**kwargs)
188
+
189
+ def __marin_tangent__(self, **kwargs):
190
+ """Function for getting the strain limits and coefficients
191
+ for marin integration of tangent modulus.
192
+
193
+ By default the law is discretized as a piecewise linear
194
+ function. Then marin coefficients are computed based on this
195
+ discretization.
196
+ """
197
+ piecewise_law = self._discretize_law()
198
+ return piecewise_law.__marin_tangent__(**kwargs)
184
199
 
185
200
  def get_secant(self, eps: float) -> float:
186
201
  """Method to return the
@@ -228,7 +243,7 @@ class SectionCalculator(abc.ABC):
228
243
  self.section = section
229
244
 
230
245
  @abc.abstractmethod
231
- def _calculate_gross_section_properties(self) -> s_res.GrossProperties:
246
+ def _calculate_gross_section_properties(self) -> s_res.SectionProperties:
232
247
  """Calculates the gross section properties of the section
233
248
  This function is private and called when the section is created
234
249
  It stores the result into the result object.
@@ -1,5 +1,6 @@
1
1
  """Main entry point for geometry."""
2
2
 
3
+ from ._circular import CircularGeometry
3
4
  from ._geometry import (
4
5
  CompoundGeometry,
5
6
  Geometry,
@@ -7,7 +8,12 @@ from ._geometry import (
7
8
  SurfaceGeometry,
8
9
  create_line_point_angle,
9
10
  )
10
- from ._reinforcement import add_reinforcement, add_reinforcement_line
11
+ from ._rectangular import RectangularGeometry
12
+ from ._reinforcement import (
13
+ add_reinforcement,
14
+ add_reinforcement_circle,
15
+ add_reinforcement_line,
16
+ )
11
17
  from ._steel_sections import HE, IPE, IPN, UB, UBP, UC, UPN
12
18
 
13
19
  __all__ = [
@@ -25,4 +31,7 @@ __all__ = [
25
31
  'UPN',
26
32
  'add_reinforcement',
27
33
  'add_reinforcement_line',
34
+ 'CircularGeometry',
35
+ 'add_reinforcement_circle',
36
+ 'RectangularGeometry',
28
37
  ]
@@ -0,0 +1,101 @@
1
+ """Classes for circular geometries.
2
+
3
+ The class `CircularGeometry` represents a circular SurfaceGeometry with
4
+ homogenous material.
5
+ This class is simply a wrapper of `SurfaceGeometry` class and permits an easy
6
+ input by the user.
7
+ """
8
+
9
+ import typing as t
10
+
11
+ import numpy as np
12
+ from numpy.typing import ArrayLike
13
+ from shapely import Polygon
14
+
15
+ from structuralcodes.core.base import ConstitutiveLaw, Material
16
+
17
+ from ._geometry import SurfaceGeometry
18
+
19
+
20
+ def _create_circle(radius, npoints=20, origin: t.Optional[ArrayLike] = None):
21
+ """Create a circle with a given radius."""
22
+ origin = origin if origin is not None else (0.0, 0.0)
23
+ phi = np.linspace(0, 2 * np.pi, npoints + 1)
24
+ x = radius * np.cos(phi) + origin[0]
25
+ y = radius * np.sin(phi) + origin[1]
26
+ points = np.transpose(np.array([x, y]))
27
+ return Polygon(points)
28
+
29
+
30
+ class CircularGeometry(SurfaceGeometry):
31
+ """This is a wrapper class for defining a `SurfaceGeometry` of circular
32
+ shape with a homogeneous material.
33
+ """
34
+
35
+ _radius: float
36
+
37
+ def __init__(
38
+ self,
39
+ diameter: float,
40
+ material: t.Union[Material, ConstitutiveLaw],
41
+ n_points: int = 20,
42
+ density: t.Optional[float] = None,
43
+ concrete: bool = False,
44
+ origin: t.Optional[ArrayLike] = None,
45
+ name: t.Optional[str] = None,
46
+ group_label: t.Optional[str] = None,
47
+ ) -> None:
48
+ """Initialize a CircularGeometry.
49
+
50
+ Arguments:
51
+ diameter (float): The diameter of the geometry.
52
+ material (Union(Material, ConstitutiveLaw)): A Material or
53
+ ConsitutiveLaw class applied to the geometry.
54
+ n_points (int): The number of points used to discretize the
55
+ 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
+ concrete (bool): Flag to indicate if the geometry is concrete.
61
+ origin (Optional(ArrayLike)): The center point of the circle.
62
+ (0.0, 0.0) is used as default.
63
+ name (Optional(str)): The name to be given to the object.
64
+ group_label (Optional(str)): A label for grouping several objects.
65
+
66
+ Note:
67
+ The CircularGeometry is simply a wrapper for a SurfaceGeometry
68
+ object.
69
+ """
70
+ # Check that size is strictly positive
71
+ if diameter <= 0:
72
+ raise ValueError('Diameter must be a positive number.')
73
+ # Manage size as radius or diameter (default)
74
+ self._radius = diameter / 2.0
75
+ # Parse origin
76
+ if origin is not None and len(origin) != 2:
77
+ raise ValueError('origin must be an ArrayLike with len == 2')
78
+ origin = origin if origin is not None else (0.0, 0.0)
79
+ # Create the shapely polygon
80
+ polygon = _create_circle(
81
+ radius=self._radius, npoints=n_points, origin=origin
82
+ )
83
+ # Pass everything to the base class
84
+ super().__init__(
85
+ poly=polygon,
86
+ material=material,
87
+ density=density,
88
+ concrete=concrete,
89
+ name=name,
90
+ group_label=group_label,
91
+ )
92
+
93
+ @property
94
+ def radius(self):
95
+ """Returns the radius of the circle."""
96
+ return self._radius
97
+
98
+ @property
99
+ def diameter(self):
100
+ """Return diameter of the circle."""
101
+ return 2 * self._radius
@@ -323,7 +323,7 @@ def create_line_point_angle(
323
323
  return LineString([(x1, y1), (x2, y2)])
324
324
 
325
325
 
326
- class SurfaceGeometry:
326
+ class SurfaceGeometry(Geometry):
327
327
  """Class for a surface geometry with material.
328
328
 
329
329
  Basically it is a wrapper for shapely polygon including the material (and
@@ -339,6 +339,8 @@ class SurfaceGeometry:
339
339
  material: t.Union[Material, ConstitutiveLaw],
340
340
  density: t.Optional[float] = None,
341
341
  concrete: bool = False,
342
+ name: t.Optional[str] = None,
343
+ group_label: t.Optional[str] = None,
342
344
  ) -> None:
343
345
  """Initializes a SurfaceGeometry object.
344
346
 
@@ -350,7 +352,10 @@ class SurfaceGeometry:
350
352
  the density can be provided by this argument. When mat is a
351
353
  Material object the density is taken from the material.
352
354
  concrete (bool): Flag to indicate if the geometry is concrete.
355
+ name (Optional(str)): The name to be given to the object.
356
+ group_label (Optional(str)): A label for grouping several objects.
353
357
  """
358
+ super().__init__(name=name, group_label=group_label)
354
359
  # Check if inputs are of the correct type, otherwise return error
355
360
  if not isinstance(poly, Polygon):
356
361
  raise TypeError(
@@ -557,7 +562,7 @@ class SurfaceGeometry:
557
562
  poly=affinity.translate(self.polygon, dx, dy),
558
563
  material=self.material,
559
564
  density=self._density,
560
- concrete=self.concrete
565
+ concrete=self.concrete,
561
566
  )
562
567
 
563
568
  def rotate(