Skip to content

Commit d690172

Browse files
Merge pull request #519 from Blueprints-org/233-feature-request-add-formula-58-from-nen_en_1993_1_1_c2_a1_2016
233 Formula 5.8 from NEN-EN 1993-1-1
2 parents f7b2969 + ef70833 commit d690172

File tree

9 files changed

+217
-10
lines changed

9 files changed

+217
-10
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Module containing all formulas from EN 1993-1-1:2005: Chapter 5 - Structural analysis."""
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""Formula 5.8 from EN 1993-1-1:2005: Chapter 5 - Structural Analysis."""
2+
3+
import numpy as np
4+
5+
from blueprints.codes.eurocode.en_1993_1_1_2005 import EN_1993_1_1_2005
6+
from blueprints.codes.formula import ComparisonFormula
7+
from blueprints.codes.latex_formula import LatexFormula, latex_replace_symbols
8+
from blueprints.type_alias import DIMENSIONLESS, MM2, MPA, N
9+
from blueprints.validations import raise_if_less_or_equal_to_zero, raise_if_negative
10+
11+
12+
class Form5Dot8CheckSlenderness(ComparisonFormula):
13+
r"""Class representing formula 5.8 for check of slenderness."""
14+
15+
label = "5.8"
16+
source_document = EN_1993_1_1_2005
17+
18+
def __init__(
19+
self,
20+
lambda_bar: DIMENSIONLESS,
21+
a: MM2,
22+
f_y: MPA,
23+
n_ed: N,
24+
) -> None:
25+
r"""Check the slenderness ratio.
26+
27+
EN 1993-1-1:2005 art.5.3.2(6) - Formula (5.8)
28+
29+
Parameters
30+
----------
31+
lambda_bar : DIMENSIONLESS
32+
[$\overline{\lambda}$] In-plane non-dimensional slenderness calculated for the member
33+
considered as hinged at its ends [-].
34+
a : MM2
35+
[$A$] Cross-sectional area [$mm^2$].
36+
f_y : MPA
37+
[$f_y$] Yield strength [$MPa$].
38+
n_ed : N
39+
[$N_{Ed}$] Design value of the compression force [$N$].
40+
"""
41+
super().__init__()
42+
self.lambda_bar = lambda_bar
43+
self.a = a
44+
self.f_y = f_y
45+
self.n_ed = n_ed
46+
47+
@staticmethod
48+
def _evaluate_lhs(lambda_bar: DIMENSIONLESS, *_args, **_kwargs) -> float:
49+
"""Evaluates the left-hand side of the comparison. See __init__ for details."""
50+
raise_if_negative(lambda_bar=lambda_bar)
51+
return lambda_bar
52+
53+
@staticmethod
54+
def _evaluate_rhs(a: MM2, f_y: MPA, n_ed: N, *_args, **_kwargs) -> float:
55+
"""Evaluates the right-hand side of the comparison. See __init__ for details."""
56+
raise_if_less_or_equal_to_zero(n_ed=n_ed)
57+
raise_if_negative(a=a, f_y=f_y)
58+
return 0.5 * np.sqrt(a * f_y / n_ed)
59+
60+
@property
61+
def unity_check(self) -> float:
62+
"""Returns the unity check value."""
63+
return self.lhs / self.rhs
64+
65+
@staticmethod
66+
def _evaluate(
67+
lambda_bar: DIMENSIONLESS,
68+
a: MM2,
69+
f_y: MPA,
70+
n_ed: N,
71+
) -> bool:
72+
"""Evaluates the formula, for more information see the __init__ method."""
73+
lhs = Form5Dot8CheckSlenderness._evaluate_lhs(lambda_bar=lambda_bar)
74+
rhs = Form5Dot8CheckSlenderness._evaluate_rhs(a=a, f_y=f_y, n_ed=n_ed)
75+
return lhs > rhs
76+
77+
def __bool__(self) -> bool:
78+
"""Allow truth-checking of the check object itself."""
79+
return self._evaluate(
80+
lambda_bar=self.lambda_bar,
81+
a=self.a,
82+
f_y=self.f_y,
83+
n_ed=self.n_ed,
84+
)
85+
86+
def latex(self) -> LatexFormula:
87+
"""Returns LatexFormula object for formula 5.8."""
88+
n = 2
89+
_equation: str = r"\left( \overline{\lambda} > 0.5 \sqrt{\frac{A \cdot f_{y}}{N_{Ed}}} \right)"
90+
_numeric_equation: str = latex_replace_symbols(
91+
_equation,
92+
{
93+
r"\lambda": f"{self.lambda_bar:.{n}f}",
94+
"A": f"{self.a:.{n}f}",
95+
"f_{y}": f"{self.f_y:.{n}f}",
96+
"N_{Ed}": f"{self.n_ed:.{n}f}",
97+
},
98+
unique_symbol_check=False,
99+
)
100+
return LatexFormula(
101+
return_symbol=r"CHECK",
102+
result="OK" if self.__bool__() else "\\text{Not OK}",
103+
equation=_equation,
104+
numeric_equation=_numeric_equation,
105+
comparison_operator_label="\\to",
106+
unit="",
107+
)

blueprints/codes/eurocode/en_1993_1_1_2005/chapter_6_ultimate_limit_state/formula_6_3.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Formula 6.3 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate limit state."""
1+
"""Formula 6.3 from EN 1993-1-1:2005: Chapter 6 - Ultimate limit state."""
22

33
from collections.abc import Sequence
44

@@ -25,7 +25,7 @@ def __init__(
2525
) -> None:
2626
"""[$A_{deduction}$] Calculation of the area deduction for staggered fastener holes [$mm^2$].
2727
28-
NEN-EN 1993-1-1+C2+A1:2016 art.6.2.2.2 (4) b) - Formula (6.3)
28+
EN 1993-1-1:2005 art.6.2.2.2 (4) b) - Formula (6.3)
2929
section (4) a) should be handled separately.
3030
3131
Parameters

blueprints/codes/eurocode/en_1993_1_1_2005/chapter_6_ultimate_limit_state/formula_6_4.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Formula 6.4 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate Limit State."""
1+
"""Formula 6.4 from EN 1993-1-1:2005: Chapter 6 - Ultimate Limit State."""
22

33
from blueprints.codes.eurocode.en_1993_1_1_2005 import EN_1993_1_1_2005
44
from blueprints.codes.formula import Formula
@@ -20,7 +20,7 @@ def __init__(
2020
) -> None:
2121
r"""[$\Delta M_{Ed}$] Calculation of the additional moment [$Nmm$].
2222
23-
NEN-EN 1993-1-1+C2+A1:2016 art.6.2.2.5(4) - Formula (6.4)
23+
EN 1993-1-1:2005 art.6.2.2.5(4) - Formula (6.4)
2424
Where a class 4 cross section is subjected to an axial compression force, the method given in EN 1993-1-5 should be used to
2525
determine the possible shift [$e_{N}$] of the centroid of the effective area [$A_{eff}$] relative to the centre of gravity
2626
of the gross cross section and the resulting additional moment according to this formula.

blueprints/codes/eurocode/en_1993_1_1_2005/chapter_6_ultimate_limit_state/formula_6_6.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Formula 6.6 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate Limit State."""
1+
"""Formula 6.6 from EN 1993-1-1:2005: Chapter 6 - Ultimate Limit State."""
22

33
from blueprints.codes.eurocode.en_1993_1_1_2005 import EN_1993_1_1_2005
44
from blueprints.codes.formula import Formula
@@ -21,7 +21,7 @@ def __init__(
2121
) -> None:
2222
r"""[$N_{pl,Rd}$] Calculation of the design plastic resistance of the gross cross-section [$N$].
2323
24-
NEN-EN 1993-1-1+C2+A1:2016 art.6.2.3(2) - Formula (6.6)
24+
EN 1993-1-1:2005 art.6.2.3(2) - Formula (6.6)
2525
2626
Parameters
2727
----------

blueprints/codes/eurocode/en_1993_1_1_2005/chapter_6_ultimate_limit_state/formula_6_7.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Formula 6.7 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate Limit State."""
1+
"""Formula 6.7 from EN 1993-1-1:2005: Chapter 6 - Ultimate Limit State."""
22

33
from blueprints.codes.eurocode.en_1993_1_1_2005 import EN_1993_1_1_2005
44
from blueprints.codes.formula import Formula
@@ -21,7 +21,7 @@ def __init__(
2121
) -> None:
2222
r"""[$N_{u,Rd}$] Calculation of the design tension resistance [$N$].
2323
24-
NEN-EN 1993-1-1+C2+A1:2016 art.6.2.3(2) - Formula (6.7)
24+
EN 1993-1-1:2005 art.6.2.3(2) - Formula (6.7)
2525
2626
Parameters
2727
----------

blueprints/codes/eurocode/en_1993_1_1_2005/chapter_6_ultimate_limit_state/formula_6_8.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Formula 6.8 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate Limit State."""
1+
"""Formula 6.8 from EN 1993-1-1:2005: Chapter 6 - Ultimate Limit State."""
22

33
from blueprints.codes.eurocode.en_1993_1_1_2005 import EN_1993_1_1_2005
44
from blueprints.codes.formula import Formula
@@ -21,7 +21,7 @@ def __init__(
2121
) -> None:
2222
r"""[$N_{net,Rd}$] Calculation of the design tension resistance [$N$].
2323
24-
NEN-EN 1993-1-1+C2+A1:2016 art.6.2.3(4) - Formula (6.8)
24+
EN 1993-1-1:2005 art.6.2.3(4) - Formula (6.8)
2525
2626
Parameters
2727
----------
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Tests for the module EN 1993-1-1:2005 .chapter_5_structural_analysis`."""
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""Testing formula 5.8 of EN 1993-1-1:2005."""
2+
3+
import numpy as np
4+
import pytest
5+
6+
from blueprints.codes.eurocode.en_1993_1_1_2005.chapter_5_structural_analysis.formula_5_8 import Form5Dot8CheckSlenderness
7+
from blueprints.validations import LessOrEqualToZeroError, NegativeValueError
8+
9+
10+
class TestForm5Dot8CheckSlenderness:
11+
"""Validation for formula 5.8 from EN 1993-1-1:2005."""
12+
13+
def test_evaluation(self) -> None:
14+
"""Tests the evaluation of the result."""
15+
# Example values
16+
lambda_bar = 1.0
17+
a = 1000.0
18+
f_y = 355.0
19+
n_ed = 100000.0
20+
21+
# Object to test
22+
formula = Form5Dot8CheckSlenderness(lambda_bar=lambda_bar, a=a, f_y=f_y, n_ed=n_ed)
23+
24+
# Expected result, manually calculated
25+
expected_result = True
26+
expected_unity_check = lambda_bar / (0.5 * np.sqrt(a * f_y / n_ed))
27+
28+
assert formula == expected_result
29+
assert formula.unity_check == expected_unity_check
30+
31+
@pytest.mark.parametrize(
32+
("lambda_bar", "a", "f_y", "n_ed"),
33+
[
34+
(1.0, 1000.0, 355.0, -100000.0), # n_ed is negative
35+
(1.0, 1000.0, 355.0, 0.0), # n_ed is zero
36+
],
37+
)
38+
def test_raise_error_when_invalid_values_less_or_equal_to_zero(self, lambda_bar: float, a: float, f_y: float, n_ed: float) -> None:
39+
"""Test invalid values."""
40+
with pytest.raises(LessOrEqualToZeroError):
41+
Form5Dot8CheckSlenderness(
42+
lambda_bar=lambda_bar,
43+
a=a,
44+
f_y=f_y,
45+
n_ed=n_ed,
46+
)
47+
48+
@pytest.mark.parametrize(
49+
("lambda_bar", "a", "f_y", "n_ed"),
50+
[
51+
(-1.0, 1000.0, 355.0, 100000.0), # lambda_bar is negative
52+
(1.0, -1000.0, 355.0, 100000.0), # a is negative
53+
(1.0, 1000.0, -355.0, 100000.0), # f_y is negative
54+
],
55+
)
56+
def test_raise_error_when_negative(self, lambda_bar: float, a: float, f_y: float, n_ed: float) -> None:
57+
"""Test invalid values."""
58+
with pytest.raises(NegativeValueError):
59+
Form5Dot8CheckSlenderness(
60+
lambda_bar=lambda_bar,
61+
a=a,
62+
f_y=f_y,
63+
n_ed=n_ed,
64+
)
65+
66+
@pytest.mark.parametrize(
67+
("representation", "expected"),
68+
[
69+
(
70+
"complete",
71+
r"CHECK \to \left( \overline{\lambda} > 0.5 \sqrt{\frac{A \cdot f_{y}}{N_{Ed}}} "
72+
r"\right) \to \left( \overline{1.00} > 0.5 \sqrt{\frac{1000.00 \cdot 355.00}{100000.00}} \right) \to OK",
73+
),
74+
("short", r"CHECK \to OK"),
75+
],
76+
)
77+
def test_latex(self, representation: str, expected: str) -> None:
78+
"""Test the latex representation of the formula."""
79+
# Example values
80+
lambda_bar = 1.0
81+
a = 1000.0
82+
f_y = 355.0
83+
n_ed = 100000.0
84+
85+
# Object to test
86+
latex = Form5Dot8CheckSlenderness(
87+
lambda_bar=lambda_bar,
88+
a=a,
89+
f_y=f_y,
90+
n_ed=n_ed,
91+
).latex()
92+
93+
actual = {
94+
"complete": latex.complete,
95+
"short": latex.short,
96+
}
97+
98+
assert expected == actual[representation], f"{representation} representation failed."

0 commit comments

Comments
 (0)