Skip to content

Commit 0c2cbd0

Browse files
Merge pull request #27 from robbievanleeuwen/interaction_generalisation
Generalise moment interaction diagram
2 parents 62c1cca + a29d935 commit 0c2cbd0

15 files changed

+422
-439
lines changed

concreteproperties/analysis_section.py

+39-38
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
from dataclasses import dataclass
4+
from math import isinf
45
from typing import TYPE_CHECKING, List, Optional, Tuple
56

67
import numpy as np
@@ -161,7 +162,7 @@ def service_stress_analysis(
161162
theta: float,
162163
kappa: float,
163164
centroid: Tuple[float, float],
164-
) -> Tuple[float, float, float, float, float]:
165+
) -> Tuple[float, float, float, float]:
165166
r"""Performs a service stress analysis on the section.
166167
167168
:param point_na: Point on the neutral axis
@@ -176,13 +177,12 @@ def service_stress_analysis(
176177

177178
# initialise section actions
178179
n = 0
179-
max_strain = 0
180180
m_x = 0
181181
m_y = 0
182-
m_v = 0
182+
max_strain = 0
183183

184184
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(
186186
point_na=point_na,
187187
d_n=d_n,
188188
theta=theta,
@@ -194,9 +194,8 @@ def service_stress_analysis(
194194
n += el_n
195195
m_x += el_m_x
196196
m_y += el_m_y
197-
m_v += el_m_v
198197

199-
return n, m_x, m_y, m_v, max_strain
198+
return n, m_x, m_y, max_strain
200199

201200
def get_service_stress(
202201
self,
@@ -239,7 +238,7 @@ def get_service_stress(
239238
)
240239

241240
# calculate total force
242-
n, m_x, m_y, _, _ = self.service_stress_analysis(
241+
n, m_x, m_y, _ = self.service_stress_analysis(
243242
point_na=point_na,
244243
d_n=d_n,
245244
theta=theta,
@@ -263,7 +262,7 @@ def ultimate_stress_analysis(
263262
d_n: float,
264263
theta: float,
265264
ultimate_strain: float,
266-
pc: Tuple[float, float],
265+
centroid: Tuple[float, float],
267266
) -> Tuple[float, float, float]:
268267
r"""Performs an ultimate stress analysis on the section.
269268
@@ -272,7 +271,7 @@ def ultimate_stress_analysis(
272271
:param theta: Angle (in radians) the neutral axis makes with the
273272
horizontal axis (:math:`-\pi \leq \theta \leq \pi`)
274273
:param ultimate_strain: Concrete strain at failure
275-
:param pc: Location of the plastic centroid
274+
:param centroid: Centroid about which to take moments
276275
277276
:return: Axial force and resultant moments about the global axes
278277
"""
@@ -288,7 +287,7 @@ def ultimate_stress_analysis(
288287
d_n=d_n,
289288
theta=theta,
290289
ultimate_strain=ultimate_strain,
291-
pc=pc,
290+
centroid=centroid,
292291
)
293292

294293
n += el_n
@@ -303,7 +302,7 @@ def get_ultimate_stress(
303302
point_na: Tuple[float, float],
304303
theta: float,
305304
ultimate_strain: float,
306-
pc: Tuple[float, float],
305+
centroid: Tuple[float, float],
307306
) -> Tuple[np.ndarray, float, float, float]:
308307
r"""Given the neutral axis depth `d_n` and ultimate strain, determines the
309308
ultimate stresses with the section.
@@ -313,7 +312,7 @@ def get_ultimate_stress(
313312
:param theta: Angle (in radians) the neutral axis makes with the
314313
horizontal axis (:math:`-\pi \leq \theta \leq \pi`)
315314
:param ultimate_strain: Concrete strain at failure
316-
:param pc: Location of the plastic centroid
315+
:param centroid: Centroid about which to take moments
317316
318317
:return: Ultimate stresses net force and distance from neutral axis to point of
319318
force action
@@ -325,13 +324,16 @@ def get_ultimate_stress(
325324
# loop through nodes
326325
for idx, node in enumerate(self.mesh_nodes):
327326
# 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+
)
335337

336338
# get stress at gauss point
337339
sig[idx] = self.geometry.material.ultimate_stress_strain_profile.get_stress( # type: ignore
@@ -344,7 +346,7 @@ def get_ultimate_stress(
344346
d_n=d_n,
345347
theta=theta,
346348
ultimate_strain=ultimate_strain,
347-
pc=pc,
349+
centroid=centroid,
348350
)
349351

350352
# calculate point of action
@@ -575,7 +577,7 @@ def calculate_service_actions(
575577
theta: float,
576578
kappa: float,
577579
centroid: Tuple[float, float],
578-
) -> Tuple[float, float, float, float, float]:
580+
) -> Tuple[float, float, float, float]:
579581
r"""Calculates service actions for the current finite element.
580582
581583
:param point_na: Point on the neutral axis
@@ -590,10 +592,9 @@ def calculate_service_actions(
590592

591593
# initialise element results
592594
force_e = 0
593-
max_strain_e = 0
594595
m_x_e = 0
595596
m_y_e = 0
596-
m_v_e = 0
597+
max_strain_e = 0
597598

598599
# get points for 1 point Gaussian integration
599600
gps = utils.gauss_points(n=1)
@@ -622,23 +623,20 @@ def calculate_service_actions(
622623
# calculate force (stress * area)
623624
force_gp = gp[0] * stress * j
624625

625-
# convert gauss point to local coordinates
626-
u, _ = utils.global_to_local(theta=theta, x=x, y=y)
627626
# add force and moment
628627
force_e += force_gp
629628
m_x_e += force_e * (y - centroid[1])
630629
m_y_e += force_e * (x - centroid[0])
631-
m_v_e += force_gp * u
632630

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
634632

635633
def calculate_ultimate_actions(
636634
self,
637635
point_na: Tuple[float, float],
638636
d_n: float,
639637
theta: float,
640638
ultimate_strain: float,
641-
pc: Tuple[float, float],
639+
centroid: Tuple[float, float],
642640
) -> Tuple[float, float, float]:
643641
r"""Calculates ultimate actions for the current finite element.
644642
@@ -647,7 +645,7 @@ def calculate_ultimate_actions(
647645
:param theta: Angle (in radians) the neutral axis makes with the
648646
horizontal axis (:math:`-\pi \leq \theta \leq \pi`)
649647
:param ultimate_strain: Concrete strain at failure
650-
:param pc: Location of the plastic centroid
648+
:param centroid: Centroid about which to take moments
651649
652650
:return: Axial force and resultant moments about the global axes
653651
"""
@@ -670,13 +668,16 @@ def calculate_ultimate_actions(
670668
y = np.dot(N, np.transpose(self.coords[1, :]))
671669

672670
# 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+
)
680681

681682
# get stress at gauss point
682683
stress = self.conc_material.ultimate_stress_strain_profile.get_stress(
@@ -688,7 +689,7 @@ def calculate_ultimate_actions(
688689

689690
# add force and moment
690691
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])
693694

694695
return force_e, m_x_e, m_y_e

0 commit comments

Comments
 (0)