1
1
from __future__ import annotations
2
2
3
3
from dataclasses import dataclass
4
+ from math import isinf
4
5
from typing import TYPE_CHECKING , List , Optional , Tuple
5
6
6
7
import numpy as np
@@ -161,7 +162,7 @@ def service_stress_analysis(
161
162
theta : float ,
162
163
kappa : float ,
163
164
centroid : Tuple [float , float ],
164
- ) -> Tuple [float , float , float , float , float ]:
165
+ ) -> Tuple [float , float , float , float ]:
165
166
r"""Performs a service stress analysis on the section.
166
167
167
168
:param point_na: Point on the neutral axis
@@ -176,13 +177,12 @@ def service_stress_analysis(
176
177
177
178
# initialise section actions
178
179
n = 0
179
- max_strain = 0
180
180
m_x = 0
181
181
m_y = 0
182
- m_v = 0
182
+ max_strain = 0
183
183
184
184
for el in self .elements :
185
- el_n , el_m_x , el_m_y , el_m_v , el_max_strain = el .calculate_service_actions (
185
+ el_n , el_m_x , el_m_y , el_max_strain = el .calculate_service_actions (
186
186
point_na = point_na ,
187
187
d_n = d_n ,
188
188
theta = theta ,
@@ -194,9 +194,8 @@ def service_stress_analysis(
194
194
n += el_n
195
195
m_x += el_m_x
196
196
m_y += el_m_y
197
- m_v += el_m_v
198
197
199
- return n , m_x , m_y , m_v , max_strain
198
+ return n , m_x , m_y , max_strain
200
199
201
200
def get_service_stress (
202
201
self ,
@@ -239,7 +238,7 @@ def get_service_stress(
239
238
)
240
239
241
240
# calculate total force
242
- n , m_x , m_y , _ , _ = self .service_stress_analysis (
241
+ n , m_x , m_y , _ = self .service_stress_analysis (
243
242
point_na = point_na ,
244
243
d_n = d_n ,
245
244
theta = theta ,
@@ -263,7 +262,7 @@ def ultimate_stress_analysis(
263
262
d_n : float ,
264
263
theta : float ,
265
264
ultimate_strain : float ,
266
- pc : Tuple [float , float ],
265
+ centroid : Tuple [float , float ],
267
266
) -> Tuple [float , float , float ]:
268
267
r"""Performs an ultimate stress analysis on the section.
269
268
@@ -272,7 +271,7 @@ def ultimate_stress_analysis(
272
271
:param theta: Angle (in radians) the neutral axis makes with the
273
272
horizontal axis (:math:`-\pi \leq \theta \leq \pi`)
274
273
:param ultimate_strain: Concrete strain at failure
275
- :param pc: Location of the plastic centroid
274
+ :param centroid: Centroid about which to take moments
276
275
277
276
:return: Axial force and resultant moments about the global axes
278
277
"""
@@ -288,7 +287,7 @@ def ultimate_stress_analysis(
288
287
d_n = d_n ,
289
288
theta = theta ,
290
289
ultimate_strain = ultimate_strain ,
291
- pc = pc ,
290
+ centroid = centroid ,
292
291
)
293
292
294
293
n += el_n
@@ -303,7 +302,7 @@ def get_ultimate_stress(
303
302
point_na : Tuple [float , float ],
304
303
theta : float ,
305
304
ultimate_strain : float ,
306
- pc : Tuple [float , float ],
305
+ centroid : Tuple [float , float ],
307
306
) -> Tuple [np .ndarray , float , float , float ]:
308
307
r"""Given the neutral axis depth `d_n` and ultimate strain, determines the
309
308
ultimate stresses with the section.
@@ -313,7 +312,7 @@ def get_ultimate_stress(
313
312
:param theta: Angle (in radians) the neutral axis makes with the
314
313
horizontal axis (:math:`-\pi \leq \theta \leq \pi`)
315
314
:param ultimate_strain: Concrete strain at failure
316
- :param pc: Location of the plastic centroid
315
+ :param centroid: Centroid about which to take moments
317
316
318
317
:return: Ultimate stresses net force and distance from neutral axis to point of
319
318
force action
@@ -325,13 +324,16 @@ def get_ultimate_stress(
325
324
# loop through nodes
326
325
for idx , node in enumerate (self .mesh_nodes ):
327
326
# get strain at node
328
- strain = utils .get_ultimate_strain (
329
- point = (node [0 ], node [1 ]),
330
- point_na = point_na ,
331
- d_n = d_n ,
332
- theta = theta ,
333
- ultimate_strain = ultimate_strain ,
334
- )
327
+ if isinf (d_n ):
328
+ strain = ultimate_strain
329
+ else :
330
+ strain = utils .get_ultimate_strain (
331
+ point = (node [0 ], node [1 ]),
332
+ point_na = point_na ,
333
+ d_n = d_n ,
334
+ theta = theta ,
335
+ ultimate_strain = ultimate_strain ,
336
+ )
335
337
336
338
# get stress at gauss point
337
339
sig [idx ] = self .geometry .material .ultimate_stress_strain_profile .get_stress ( # type: ignore
@@ -344,7 +346,7 @@ def get_ultimate_stress(
344
346
d_n = d_n ,
345
347
theta = theta ,
346
348
ultimate_strain = ultimate_strain ,
347
- pc = pc ,
349
+ centroid = centroid ,
348
350
)
349
351
350
352
# calculate point of action
@@ -575,7 +577,7 @@ def calculate_service_actions(
575
577
theta : float ,
576
578
kappa : float ,
577
579
centroid : Tuple [float , float ],
578
- ) -> Tuple [float , float , float , float , float ]:
580
+ ) -> Tuple [float , float , float , float ]:
579
581
r"""Calculates service actions for the current finite element.
580
582
581
583
:param point_na: Point on the neutral axis
@@ -590,10 +592,9 @@ def calculate_service_actions(
590
592
591
593
# initialise element results
592
594
force_e = 0
593
- max_strain_e = 0
594
595
m_x_e = 0
595
596
m_y_e = 0
596
- m_v_e = 0
597
+ max_strain_e = 0
597
598
598
599
# get points for 1 point Gaussian integration
599
600
gps = utils .gauss_points (n = 1 )
@@ -622,23 +623,20 @@ def calculate_service_actions(
622
623
# calculate force (stress * area)
623
624
force_gp = gp [0 ] * stress * j
624
625
625
- # convert gauss point to local coordinates
626
- u , _ = utils .global_to_local (theta = theta , x = x , y = y )
627
626
# add force and moment
628
627
force_e += force_gp
629
628
m_x_e += force_e * (y - centroid [1 ])
630
629
m_y_e += force_e * (x - centroid [0 ])
631
- m_v_e += force_gp * u
632
630
633
- return force_e , m_x_e , m_y_e , m_v_e , max_strain_e
631
+ return force_e , m_x_e , m_y_e , max_strain_e
634
632
635
633
def calculate_ultimate_actions (
636
634
self ,
637
635
point_na : Tuple [float , float ],
638
636
d_n : float ,
639
637
theta : float ,
640
638
ultimate_strain : float ,
641
- pc : Tuple [float , float ],
639
+ centroid : Tuple [float , float ],
642
640
) -> Tuple [float , float , float ]:
643
641
r"""Calculates ultimate actions for the current finite element.
644
642
@@ -647,7 +645,7 @@ def calculate_ultimate_actions(
647
645
:param theta: Angle (in radians) the neutral axis makes with the
648
646
horizontal axis (:math:`-\pi \leq \theta \leq \pi`)
649
647
:param ultimate_strain: Concrete strain at failure
650
- :param pc: Location of the plastic centroid
648
+ :param centroid: Centroid about which to take moments
651
649
652
650
:return: Axial force and resultant moments about the global axes
653
651
"""
@@ -670,13 +668,16 @@ def calculate_ultimate_actions(
670
668
y = np .dot (N , np .transpose (self .coords [1 , :]))
671
669
672
670
# get strain at gauss point
673
- strain = utils .get_ultimate_strain (
674
- point = (x , y ),
675
- point_na = point_na ,
676
- d_n = d_n ,
677
- theta = theta ,
678
- ultimate_strain = ultimate_strain ,
679
- )
671
+ if isinf (d_n ):
672
+ strain = ultimate_strain
673
+ else :
674
+ strain = utils .get_ultimate_strain (
675
+ point = (x , y ),
676
+ point_na = point_na ,
677
+ d_n = d_n ,
678
+ theta = theta ,
679
+ ultimate_strain = ultimate_strain ,
680
+ )
680
681
681
682
# get stress at gauss point
682
683
stress = self .conc_material .ultimate_stress_strain_profile .get_stress (
@@ -688,7 +689,7 @@ def calculate_ultimate_actions(
688
689
689
690
# add force and moment
690
691
force_e += force_gp
691
- m_x_e += force_gp * (y - pc [1 ])
692
- m_y_e += force_gp * (x - pc [0 ])
692
+ m_x_e += force_gp * (y - centroid [1 ])
693
+ m_y_e += force_gp * (x - centroid [0 ])
693
694
694
695
return force_e , m_x_e , m_y_e
0 commit comments