From 09ac6e23893440a8ddb23937b7f3a5741c20f7e2 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 08:29:34 +0100 Subject: [PATCH 01/11] Add formula 6.1 implementation and tests for NEN-EN 1993-1-1+C2+A1:2016 --- .../formula_6_1.py | 93 +++++++++++++++++ .../test_formula_6_1.py | 99 +++++++++++++++++++ .../test_formula_6_2.py | 2 +- 3 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_1.py create mode 100644 tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_1.py diff --git a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_1.py b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_1.py new file mode 100644 index 000000000..b0a601233 --- /dev/null +++ b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_1.py @@ -0,0 +1,93 @@ +"""Formula 6.1 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate limit state.""" + +from blueprints.codes.eurocode.nen_en_1992_1_1_c2_2011 import NEN_EN_1992_1_1_C2_2011 +from blueprints.codes.formula import Formula +from blueprints.codes.latex_formula import LatexFormula, latex_replace_symbols +from blueprints.type_alias import DIMENSIONLESS, MPA +from blueprints.validations import raise_if_negative + + +class Form6Dot1ElasticVerification(Formula): + r"""Class representing formula 6.1 for the elastic verification with the yield criterion.""" + + label = "6.1" + source_document = NEN_EN_1992_1_1_C2_2011 + + def __init__( + self, + sigma_x_ed: MPA, + sigma_z_ed: MPA, + tau_ed: MPA, + f_y: MPA, + gamma_m0: DIMENSIONLESS, + ) -> None: + r"""Elastic verification with the yield criterion. + + NEN-EN 1993-1-1+C2:2011 art.6.2.1(5) - Formula (6.1) + + Parameters + ---------- + sigma_x_ed : MPA + [$\sigma_{x,\text{Ed}}$] Design value of the longitudinal stress at the point of consideration [$MPa$]. + sigma_z_ed : MPA + [$\sigma_{z,\text{Ed}}$] Design value of the transverse stress at the point of consideration [$MPa$]. + tau_ed : MPA + [$\tau_{\text{Ed}}$] Design value of the shear stress at the point of consideration [$MPa$]. + f_y : MPA + [$f_y$] Yield strength of the material [$MPa$]. + gamma_m0 : DIMENSIONLESS + [$\gamma_{M0}$] Partial safety factor for the material [dimensionless]. + """ + super().__init__() + self.sigma_x_ed = sigma_x_ed + self.sigma_z_ed = sigma_z_ed + self.tau_ed = tau_ed + self.f_y = f_y + self.gamma_m0 = gamma_m0 + + @staticmethod + def _evaluate( + sigma_x_ed: MPA, + sigma_z_ed: MPA, + tau_ed: MPA, + f_y: MPA, + gamma_m0: DIMENSIONLESS, + ) -> bool: + """Evaluates the formula, for more information see the __init__ method.""" + raise_if_negative(sigma_x_ed=sigma_x_ed, sigma_z_ed=sigma_z_ed, tau_ed=tau_ed, f_y=f_y, gamma_m0=gamma_m0) + + term1 = (sigma_x_ed / (f_y / gamma_m0)) ** 2 + term2 = (sigma_z_ed / (f_y / gamma_m0)) ** 2 + term3 = (sigma_x_ed / (f_y / gamma_m0)) * (sigma_z_ed / (f_y / gamma_m0)) + term4 = 3 * (tau_ed / (f_y / gamma_m0)) ** 2 + + return term1 + term2 - term3 + term4 <= 1 + + def latex(self) -> LatexFormula: + """Returns LatexFormula object for formula 6.1.""" + _equation: str = ( + r"\left( \frac{\sigma_{x,\text{Ed}}}{f_y / \gamma_{M0}} \right)^2 " + r"+ \left( \frac{\sigma_{z,\text{Ed}}}{f_y / \gamma_{M0}} \right)^2 " + r"- \left( \frac{\sigma_{x,\text{Ed}}}{f_y / \gamma_{M0}} \right) " + r"\left( \frac{\sigma_{z,\text{Ed}}}{f_y / \gamma_{M0}} \right) " + r"+ 3 \left( \frac{\tau_{\text{Ed}}}{f_y / \gamma_{M0}} \right)^2 \leq 1" + ) + _numeric_equation: str = latex_replace_symbols( + _equation, + { + r"\sigma_{x,\text{Ed}}": f"{self.sigma_x_ed:.3f}", + r"\sigma_{z,\text{Ed}}": f"{self.sigma_z_ed:.3f}", + r"\tau_{\text{Ed}}": f"{self.tau_ed:.3f}", + r"f_y": f"{self.f_y:.3f}", + r"\gamma_{M0}": f"{self.gamma_m0:.3f}", + }, + False, + ) + return LatexFormula( + return_symbol=r"CHECK", + result="OK" if self.__bool__() else "\\text{Not OK}", + equation=_equation, + numeric_equation=_numeric_equation, + comparison_operator_label="\\to", + unit="", + ) diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_1.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_1.py new file mode 100644 index 000000000..affef39a1 --- /dev/null +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_1.py @@ -0,0 +1,99 @@ +"""Testing formula 6.1 of NEN-EN 1993-1-1+C2+A1:2016.""" + +import pytest + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016.chapter_6_ultimate_limit_state.formula_6_1 import Form6Dot1ElasticVerification +from blueprints.validations import LessOrEqualToZeroError, NegativeValueError + + +class TestForm6Dot1ElasticVerification: + """Validation for formula 6.1 from NEN-EN 1993-1-1+C2+A1:2016.""" + + def test_evaluation(self) -> None: + """Tests the evaluation of the result.""" + # Example values + sigma_x_ed = 100.0 # MPa + sigma_z_ed = 50.0 # MPa + tau_ed = 30.0 # MPa + f_y = 355.0 # MPa + gamma_m0 = 1.0 # dimensionless + + # Object to test + formula = Form6Dot1ElasticVerification( + sigma_x_ed=sigma_x_ed, + sigma_z_ed=sigma_z_ed, + tau_ed=tau_ed, + f_y=f_y, + gamma_m0=gamma_m0, + ) + + # Expected result, manually calculated + expected_result = True + + assert formula == expected_result + + @pytest.mark.parametrize( + ("sigma_x_ed", "sigma_z_ed", "tau_ed", "f_y", "gamma_m0"), + [ + (-100.0, 50.0, 30.0, 355.0, 1.0), # sigma_x_ed is negative + (100.0, -50.0, 30.0, 355.0, 1.0), # sigma_z_ed is negative + (100.0, 50.0, -30.0, 355.0, 1.0), # tau_ed is negative + (100.0, 50.0, 30.0, -355.0, 1.0), # f_y is negative + (100.0, 50.0, 30.0, 355.0, -1.0), # gamma_m0 is negative + ], + ) + def test_raise_error_when_invalid_values_are_given( + self, sigma_x_ed: float, sigma_z_ed: float, tau_ed: float, f_y: float, gamma_m0: float + ) -> None: + """Test invalid values.""" + with pytest.raises((NegativeValueError, LessOrEqualToZeroError)): + Form6Dot1ElasticVerification( + sigma_x_ed=sigma_x_ed, + sigma_z_ed=sigma_z_ed, + tau_ed=tau_ed, + f_y=f_y, + gamma_m0=gamma_m0, + ) + + @pytest.mark.parametrize( + ("representation", "expected"), + [ + ( + "complete", + r"CHECK \to \left( \frac{\sigma_{x,\text{Ed}}}{f_y / \gamma_{M0}} \right)^2 + " + r"\left( \frac{\sigma_{z,\text{Ed}}}{f_y / \gamma_{M0}} \right)^2 - " + r"\left( \frac{\sigma_{x,\text{Ed}}}{f_y / \gamma_{M0}} \right) " + r"\left( \frac{\sigma_{z,\text{Ed}}}{f_y / \gamma_{M0}} \right) " + r"+ 3 \left( \frac{\tau_{\text{Ed}}}{f_y / \gamma_{M0}} \right)^2 \leq 1 \to " + r"\left( \frac{100.000}{355.000 / 1.000} \right)^2 + " + r"\left( \frac{50.000}{355.000 / 1.000} \right)^2 - " + r"\left( \frac{100.000}{355.000 / 1.000} \right) \left( \frac{50.000}{355.000 / 1.000} \right) " + r"+ 3 \left( \frac{30.000}{355.000 / 1.000} \right)^2 \leq 1 \to OK", + ), + ("short", r"CHECK \to OK"), + ], + ) + def test_latex(self, representation: str, expected: str) -> None: + """Test the latex representation of the formula.""" + # Example values + sigma_x_ed = 100.0 # MPa + sigma_z_ed = 50.0 # MPa + tau_ed = 30.0 # MPa + f_y = 355.0 # MPa + gamma_m0 = 1.0 # dimensionless + + # Object to test + latex = Form6Dot1ElasticVerification( + sigma_x_ed=sigma_x_ed, + sigma_z_ed=sigma_z_ed, + tau_ed=tau_ed, + f_y=f_y, + gamma_m0=gamma_m0, + ).latex() + + actual = { + "complete": latex.complete, + "short": latex.short, + } + + assert expected == actual[representation], f"{representation} representation failed." diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_2.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_2.py index 265b3b87b..921bd4a4d 100644 --- a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_2.py +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_2.py @@ -1,4 +1,4 @@ -"""Testing formula 6.5 of NEN-EN 1993-1-1+C2+A1:2016.""" +"""Testing formula 6.2 of NEN-EN 1993-1-1+C2+A1:2016.""" import pytest From 3cb105300824a6af5a3775d6e59eaa7f5c2471f7 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 10:40:49 +0100 Subject: [PATCH 02/11] No code changes made. Just formatting --- .../eurocode/ec3_1993_1_1_2016/formulas.md | 227 +++++++++--------- 1 file changed, 113 insertions(+), 114 deletions(-) diff --git a/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md b/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md index a894a2269..be059ac82 100644 --- a/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md +++ b/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md @@ -1,119 +1,118 @@ -**NEN-EN 1993-1-1+C2+A1 - December 2016 -Eurocode 3: Design of steel structures +**NEN-EN 1993-1-1+C2+A1 - December 2016 +Eurocode 3: Design of steel structures Part 1-1: General rules and rules for buildings** -The table presents a list of formulas from the Eurocode 3 standards for steel structures, tracking their implementation status (:x: or : -heavy_check_mark:) and any pertinent remarks. The 'Object Name' column references the corresponding Python entities inside of Blueprints. +The table presents a list of formulas from the Eurocode 3 standards for steel structures, tracking their implementation status (:x: or :heavy_check_mark:) and any pertinent remarks. The 'Object Name' column references the corresponding Python entities inside of Blueprints. Total of 108 formulas present. -| Formula number | Done | Remarks | Object name | -|:---------------|:----:|:--------|:------------| -| 2.1 | :x: | | | -| 2.2 | :heavy_check_mark: | | Form2Dot2CharacteristicValueResistance | -| 5.1 | :x: | | | -| 5.2 | :x: | | | -| 5.3 | :x: | | | -| 5.4 | :x: | | | -| 5.5 | :x: | | | -| 5.6 | :x: | | | -| 5.7 | :x: | | | -| 5.8 | :x: | | | -| 5.9 | :x: | | | -| 5.10 | :x: | | | -| 5.11 | :x: | | | -| 5.12 | :x: | | | -| 5.13 | :x: | | | -| 5.14 | :x: | | | -| 6.1 | :x: | | | -| 6.2 | :heavy_check_mark: | | Form6Dot2UtilizationRatio | -| 6.3 | :x: | | | -| 6.4 | :x: | | | -| 6.5 | :heavy_check_mark: | | Form6Dot5UnityCheckTensileStrength | -| 6.6 | :x: | | | -| 6.7 | :x: | | | -| 6.8 | :x: | | | -| 6.9 | :x: | | | -| 6.10 | :x: | | | -| 6.11 | :x: | | | -| 6.12 | :x: | | | -| 6.13 | :x: | | | -| 6.14 | :x: | | | -| 6.15 | :x: | | | -| 6.16 | :x: | | | -| 6.17 | :x: | | | -| 6.18 | :x: | | | -| 6.19 | :x: | | | -| 6.20 | :x: | | | -| 6.21 | :x: | | | -| 6.22 | :x: | | | -| 6.23 | :x: | | | -| 6.24 | :x: | | | -| 6.25 | :x: | | | -| 6.26 | :x: | | | -| 6.27 | :x: | | | -| 6.28 | :x: | | | -| 6.29 | :x: | | | -| 6.30 | :x: | | | -| 6.31 | :x: | | | -| 6.32 | :x: | | | -| 6.33 | :x: | | | -| 6.34 | :x: | | | -| 6.35 | :x: | | | -| 6.36 | :x: | | | -| 6.37 | :x: | | | -| 6.38 | :x: | | | -| 6.39 | :x: | | | -| 6.40 | :x: | | | -| 6.41 | :x: | | | -| 6.42 | :x: | | | -| 6.43 | :x: | | | -| 6.44 | :x: | | | -| 6.45 | :x: | | | -| 6.46 | :x: | | | -| 6.47 | :x: | | | -| 6.48 | :x: | | | -| 6.49 | :x: | | | -| 6.50 | :x: | | | -| 6.51 | :x: | | | -| 6.52 | :x: | | | -| 6.53 | :x: | | | -| 6.54 | :x: | | | -| 6.55 | :x: | | | -| 6.56 | :x: | | | -| 6.57 | :x: | | | -| 6.58 | :x: | | | -| 6.59 | :x: | | | -| 6.60 | :x: | | | -| 6.61 | :x: | | | -| 6.62 | :x: | | | -| 6.63 | :x: | | | -| 6.64 | :x: | | | -| 6.65 | :x: | | | -| 6.66 | :x: | | | -| 6.67 | :x: | | | -| 6.68 | :x: | | | -| 6.69 | :x: | | | -| 6.70 | :x: | | | -| 6.71 | :heavy_check_mark: | | FormADot2CriteriaBasedOnStressRangeLHS and FormADot2CriteriaBasedOnStressRangeRHS | -| 6.72 | :x: | | | -| 6.73 | :x: | | | -| 6.74 | :x: | | | -| 6.75 | :x: | | | -| BB.1 | :x: | | | -| BB.2 | :x: | | | -| BB.3 | :x: | | | -| BB.4 | :x: | | | -| BB.5 | :x: | | | -| BB.6 | :x: | | | -| BB.7 | :x: | | | -| BB.8 | :x: | | | -| BB.9 | :x: | | | -| BB.10 | :x: | | | -| BB.11 | :x: | | | -| BB.12 | :x: | | | -| BB.13 | :x: | | | -| BB.14 | :x: | | | -| BB.15 | :x: | | | -| BB.16 | :x: | | | -| BB.17 | :x: | | | +| Formula number | Done | Remarks | Object name | +|:---------------|:-------------------:|:--------|:-------------------------------------------------| +| 2.1 | :x: | | | +| 2.2 | :heavy_check_mark: | | Form2Dot2CharacteristicValueResistance | +| 5.1 | :x: | | | +| 5.2 | :x: | | | +| 5.3 | :x: | | | +| 5.4 | :x: | | | +| 5.5 | :x: | | | +| 5.6 | :x: | | | +| 5.7 | :x: | | | +| 5.8 | :x: | | | +| 5.9 | :x: | | | +| 5.10 | :x: | | | +| 5.11 | :x: | | | +| 5.12 | :x: | | | +| 5.13 | :x: | | | +| 5.14 | :x: | | | +| 6.1 | :x: | | Form6Dot1ElasticVerification | +| 6.2 | :heavy_check_mark: | | Form6Dot2UtilizationRatio | +| 6.3 | :x: | | | +| 6.4 | :x: | | | +| 6.5 | :heavy_check_mark: | | Form6Dot5UnityCheckTensileStrength | +| 6.6 | :x: | | | +| 6.7 | :x: | | | +| 6.8 | :x: | | | +| 6.9 | :x: | | | +| 6.10 | :x: | | | +| 6.11 | :x: | | | +| 6.12 | :x: | | | +| 6.13 | :x: | | | +| 6.14 | :x: | | | +| 6.15 | :x: | | | +| 6.16 | :x: | | | +| 6.17 | :x: | | | +| 6.18 | :x: | | | +| 6.19 | :x: | | | +| 6.20 | :x: | | | +| 6.21 | :x: | | | +| 6.22 | :x: | | | +| 6.23 | :x: | | | +| 6.24 | :x: | | | +| 6.25 | :x: | | | +| 6.26 | :x: | | | +| 6.27 | :x: | | | +| 6.28 | :x: | | | +| 6.29 | :x: | | | +| 6.30 | :x: | | | +| 6.31 | :x: | | | +| 6.32 | :x: | | | +| 6.33 | :x: | | | +| 6.34 | :x: | | | +| 6.35 | :x: | | | +| 6.36 | :x: | | | +| 6.37 | :x: | | | +| 6.38 | :x: | | | +| 6.39 | :x: | | | +| 6.40 | :x: | | | +| 6.41 | :x: | | | +| 6.42 | :x: | | | +| 6.43 | :x: | | | +| 6.44 | :x: | | | +| 6.45 | :x: | | | +| 6.46 | :x: | | | +| 6.47 | :x: | | | +| 6.48 | :x: | | | +| 6.49 | :x: | | | +| 6.50 | :x: | | | +| 6.51 | :x: | | | +| 6.52 | :x: | | | +| 6.53 | :x: | | | +| 6.54 | :x: | | | +| 6.55 | :x: | | | +| 6.56 | :x: | | | +| 6.57 | :x: | | | +| 6.58 | :x: | | | +| 6.59 | :x: | | | +| 6.60 | :x: | | | +| 6.61 | :x: | | | +| 6.62 | :x: | | | +| 6.63 | :x: | | | +| 6.64 | :x: | | | +| 6.65 | :x: | | | +| 6.66 | :x: | | | +| 6.67 | :x: | | | +| 6.68 | :x: | | | +| 6.69 | :x: | | | +| 6.70 | :x: | | | +| 6.71 | :heavy_check_mark: | | FormADot2CriteriaBasedOnStressRangeLHS and FormADot2CriteriaBasedOnStressRangeRHS | +| 6.72 | :x: | | | +| 6.73 | :x: | | | +| 6.74 | :x: | | | +| 6.75 | :x: | | | +| BB.1 | :x: | | | +| BB.2 | :x: | | | +| BB.3 | :x: | | | +| BB.4 | :x: | | | +| BB.5 | :x: | | | +| BB.6 | :x: | | | +| BB.7 | :x: | | | +| BB.8 | :x: | | | +| BB.9 | :x: | | | +| BB.10 | :x: | | | +| BB.11 | :x: | | | +| BB.12 | :x: | | | +| BB.13 | :x: | | | +| BB.14 | :x: | | | +| BB.15 | :x: | | | +| BB.16 | :x: | | | +| BB.17 | :x: | | | From a275980f62a6241352c8dd594fd77b5e234b2671 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 11:10:25 +0100 Subject: [PATCH 03/11] Add implementation and tests for formula 6.3 from NEN-EN 1993-1-1+C2+A1:2016 --- .../formula_6_3.py | 85 +++++++++++++++++++ .../eurocode/ec3_1993_1_1_2016/formulas.md | 2 +- .../test_formula_6_3.py | 81 ++++++++++++++++++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_3.py create mode 100644 tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_3.py diff --git a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_3.py b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_3.py new file mode 100644 index 000000000..acd99f313 --- /dev/null +++ b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_3.py @@ -0,0 +1,85 @@ +"""Formula 6.3 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate limit state.""" + +# pylint: disable=arguments-differ +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016 import NEN_EN_1993_1_1_C2_A1_2016 +from blueprints.codes.formula import Formula +from blueprints.codes.latex_formula import LatexFormula +from blueprints.type_alias import MM +from blueprints.validations import raise_if_less_or_equal_to_zero, raise_if_lists_differ_in_length, raise_if_negative + + +class Form6Dot3ADeductionAreaStaggeredFastenerHoles(Formula): + """Class representing formula 6.3 for the calculation of the area deduction [$A_{deduction}$].""" + + label = "6.3" + source_document = NEN_EN_1993_1_1_C2_A1_2016 + + def __init__( + self, + t: MM, + n: MM, + d_0: MM, + s: list[MM], + p: list[MM], + ) -> None: + """[$A_{deduction}$] Calculation of the area deduction [$mm^2$]. + + NEN-EN 1993-1-1+C2+A1:2016 art.6.3 - Formula (6.3) + + Parameters + ---------- + t : MM + [$t$] Thickness [$mm$]. + n : MM + [$n$] Number of holes extending in any diagonal or zig-zag line progressively across the member [$mm$]. + d_0 : MM + [$d_0$] Diameter of hole [$mm$]. + s : list[MM] + [$s$] Staggered pitch, the spacing of the centres of two consecutive holes in the + chain measured parallel to the member axis [$mm$]. + p : list[MM] + [$p$] Spacing of the centres of the same two holes measured perpendicular to the member axis [$mm$]. + """ + super().__init__() + self.t = t + self.n = n + self.d_0 = d_0 + self.s = s + self.p = p + + @staticmethod + def _evaluate( + t: MM, + n: MM, + d_0: MM, + s: list[MM], + p: list[MM], + ) -> MM: + """Evaluates the formula, for more information see the __init__ method.""" + raise_if_negative(t=t, n=n, d_0=d_0) + raise_if_less_or_equal_to_zero(t=t, n=n, d_0=d_0) + raise_if_lists_differ_in_length(s=s, p=p) + for s_i, p_i in zip(s, p): + raise_if_negative(s=s_i, p=p_i) + raise_if_less_or_equal_to_zero(s=s_i, p=p_i) + + return t * (n * d_0 - sum((s_i**2) / (4 * p_i) for s_i, p_i in zip(s, p))) + + def latex(self) -> LatexFormula: + """Returns LatexFormula object for formula 6.3.""" + _equation: str = r"t \left( n \cdot d_0 - \sum \frac{s^2}{4 \cdot p} \right)" + _numeric_equation: str = ( + rf"{self.t:.3f} \left( {self.n:.3f} \cdot {self.d_0:.3f} - \left( \frac{{{self.s[0]:.3f}^2}}" + r"{{4 \cdot {self.p[0]:.3f}}}" + ) + for s_i, p_i in zip(self.s[1:], self.p[1:]): + _numeric_equation += rf" + \frac{{{s_i:.3f}^2}}{{4 \cdot {p_i:.3f}}}" + _numeric_equation += r" \right) \right)" + return LatexFormula( + return_symbol=r"A_{deduction}", + result=f"{self:.3f}", + equation=_equation, + numeric_equation=_numeric_equation, + comparison_operator_label="=", + unit="mm^2", + ) diff --git a/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md b/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md index be059ac82..fe860d7a4 100644 --- a/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md +++ b/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md @@ -26,7 +26,7 @@ Total of 108 formulas present. | 5.14 | :x: | | | | 6.1 | :x: | | Form6Dot1ElasticVerification | | 6.2 | :heavy_check_mark: | | Form6Dot2UtilizationRatio | -| 6.3 | :x: | | | +| 6.3 | :heavy_check_mark: | | Form6Dot3ADeductionAreaStaggeredFastenerHoles | | 6.4 | :x: | | | | 6.5 | :heavy_check_mark: | | Form6Dot5UnityCheckTensileStrength | | 6.6 | :x: | | | diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_3.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_3.py new file mode 100644 index 000000000..d77d52e47 --- /dev/null +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_3.py @@ -0,0 +1,81 @@ +"""Testing formula 6.3 of NEN-EN 1993-1-1+C2+A1:2016.""" + +import pytest + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016.chapter_6_ultimate_limit_state.formula_6_3 import ( + Form6Dot3ADeductionAreaStaggeredFastenerHoles, +) +from blueprints.validations import LessOrEqualToZeroError, ListsNotSameLengthError, NegativeValueError + + +class TestForm6Dot3ADeductionAreaStaggeredFastenerHoles: + """Validation for formula 6.3 from NEN-EN 1993-1-1+C2+A1:2016.""" + + def test_evaluation(self) -> None: + """Tests the evaluation of the result.""" + # Example values + t = 10.0 + n = 5.0 + d_0 = 20.0 + s = [50.0, 60.0] + p = [100.0, 120.0] + + # Object to test + formula = Form6Dot3ADeductionAreaStaggeredFastenerHoles(t=t, n=n, d_0=d_0, s=s, p=p) + + # Expected result, manually calculated + manually_calculated_result = 862.5 # mm^2 + + assert formula == pytest.approx(expected=manually_calculated_result, rel=1e-4) + + @pytest.mark.parametrize( + ("t", "n", "d_0", "s", "p"), + [ + (-10.0, 5.0, 20.0, [50.0, 60.0], [100.0, 120.0]), # t is negative + (10.0, -5.0, 20.0, [50.0, 60.0], [100.0, 120.0]), # n is negative + (10.0, 5.0, -20.0, [50.0, 60.0], [100.0, 120.0]), # d_0 is negative + (10.0, 5.0, 20.0, [-50.0, 60.0], [100.0, 120.0]), # s has a negative value + (10.0, 5.0, 20.0, [50.0, 60.0], [-100.0, 120.0]), # p has a negative value + (0.0, 5.0, 20.0, [50.0, 60.0], [100.0, 120.0]), # t is zero + (10.0, 0.0, 20.0, [50.0, 60.0], [100.0, 120.0]), # n is zero + (10.0, 5.0, 0.0, [50.0, 60.0], [100.0, 120.0]), # d_0 is zero + (10.0, 5.0, 20.0, [0.0, 60.0], [100.0, 120.0]), # s has a zero value + (10.0, 5.0, 20.0, [50.0, 60.0], [0.0, 120.0]), # p has a zero value + (10.0, 5.0, 20.0, [50.0, 60.0], [100.0, 120.0, 10.0]), # p has a zero value + ], + ) + def test_raise_error_when_invalid_values_are_given(self, t: float, n: float, d_0: float, s: list[float], p: list[float]) -> None: + """Test invalid values.""" + with pytest.raises((NegativeValueError, LessOrEqualToZeroError, ListsNotSameLengthError)): + Form6Dot3ADeductionAreaStaggeredFastenerHoles(t=t, n=n, d_0=d_0, s=s, p=p) + + @pytest.mark.parametrize( + ("representation", "expected"), + [ + ( + "complete", + r"A_{deduction} = t \left( n \cdot d_0 - \sum \frac{s^2}{4 \cdot p} \right) = " + r"10.000 \left( 5.000 \cdot 20.000 - \left( \frac{50.000^2}{4 \cdot 100.000} + " + r"\frac{60.000^2}{4 \cdot 120.000} \right) \right) = 862.500 mm^2", + ), + ("short", r"A_{deduction} = 862.500 mm^2"), + ], + ) + def test_latex(self, representation: str, expected: str) -> None: + """Test the latex representation of the formula.""" + # Example values + t = 10.0 + n = 5.0 + d_0 = 20.0 + s = [50.0, 60.0] + p = [100.0, 120.0] + + # Object to test + latex = Form6Dot3ADeductionAreaStaggeredFastenerHoles(t=t, n=n, d_0=d_0, s=s, p=p).latex() + + actual = { + "complete": latex.complete, + "short": latex.short, + } + + assert expected == actual[representation], f"{representation} representation failed." From 97f308186bf6232930e2b0005151eab631337731 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 16:29:38 +0100 Subject: [PATCH 04/11] Fix string formatting in numeric equation for formula 6.3 --- .../chapter_6_ultimate_limit_state/formula_6_3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_3.py b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_3.py index acd99f313..ed703cf72 100644 --- a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_3.py +++ b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_3.py @@ -70,7 +70,7 @@ def latex(self) -> LatexFormula: _equation: str = r"t \left( n \cdot d_0 - \sum \frac{s^2}{4 \cdot p} \right)" _numeric_equation: str = ( rf"{self.t:.3f} \left( {self.n:.3f} \cdot {self.d_0:.3f} - \left( \frac{{{self.s[0]:.3f}^2}}" - r"{{4 \cdot {self.p[0]:.3f}}}" + rf"{{4 \cdot {self.p[0]:.3f}}}" ) for s_i, p_i in zip(self.s[1:], self.p[1:]): _numeric_equation += rf" + \frac{{{s_i:.3f}^2}}{{4 \cdot {p_i:.3f}}}" From cb772c2303826069f8fdc172de7b2f26b2377741 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 16:29:46 +0100 Subject: [PATCH 05/11] Add implementation and tests for formula 6.4 from NEN-EN 1993-1-1+C2+A1:2016 --- .../formula_6_4.py | 64 +++++++++++++++++++ .../test_formula_6_4.py | 62 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_4.py create mode 100644 tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_4.py diff --git a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_4.py b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_4.py new file mode 100644 index 000000000..5c2bf85f5 --- /dev/null +++ b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_4.py @@ -0,0 +1,64 @@ +"""Formula 6.4 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate Limit State.""" + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016 import NEN_EN_1993_1_1_C2_A1_2016 +from blueprints.codes.formula import Formula +from blueprints.codes.latex_formula import LatexFormula, latex_replace_symbols +from blueprints.type_alias import MM, NMM, N +from blueprints.validations import raise_if_negative + + +class Form6Dot4AxialCompression(Formula): + r"""Class representing formula 6.4 for the calculation of additional moment [$\Delta M_{Ed}$].""" + + label = "6.4" + source_document = NEN_EN_1993_1_1_C2_A1_2016 + + def __init__( + self, + n_ed: N, + e_n: MM, + ) -> None: + r"""[$\Delta M_{Ed}$] Calculation of the additional moment [$Nmm$]. + + NEN-EN 1993-1-1+C2+A1:2016 art.6.2.2.5(4) - Formula (6.4) + + Parameters + ---------- + n_ed : N + [$N_{Ed}$] Axial compression force [$N$]. + e_n : MM + [$e_{N}$] Shift of the centroid of the effective area relative to the centre of gravity of the gross cross section [$mm$]. + """ + super().__init__() + self.n_ed = n_ed + self.e_n = e_n + + @staticmethod + def _evaluate( + n_ed: N, + e_n: MM, + ) -> NMM: + """Evaluates the formula, for more information see the __init__ method.""" + raise_if_negative(n_ed=n_ed, e_n=e_n) + + return n_ed * e_n + + def latex(self) -> LatexFormula: + """Returns LatexFormula object for formula 6.4.""" + _equation: str = r"N_{Ed} \cdot e_{N}" + _numeric_equation: str = latex_replace_symbols( + _equation, + { + r"N_{Ed}": f"{self.n_ed:.3f}", + r"e_{N}": f"{self.e_n:.3f}", + }, + False, + ) + return LatexFormula( + return_symbol=r"\Delta M_{Ed}", + result=f"{self:.3f}", + equation=_equation, + numeric_equation=_numeric_equation, + comparison_operator_label="=", + unit="Nmm", + ) diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_4.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_4.py new file mode 100644 index 000000000..2cd0831dc --- /dev/null +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_4.py @@ -0,0 +1,62 @@ +"""Testing formula 6.4 of NEN-EN 1993-1-1+C2+A1:2016.""" + +import pytest + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016.chapter_6_ultimate_limit_state.formula_6_4 import Form6Dot4AxialCompression +from blueprints.validations import NegativeValueError + + +class TestForm6Dot4AxialCompression: + """Validation for formula 6.4 from NEN-EN 1993-1-1+C2+A1:2016.""" + + def test_evaluation(self) -> None: + """Tests the evaluation of the result.""" + # Example values + n_ed = 1000.0 + e_n = 50.0 + + # Object to test + formula = Form6Dot4AxialCompression(n_ed=n_ed, e_n=e_n) + + # Expected result, manually calculated + manually_calculated_result = 50000.0 # Nmm + + assert formula == pytest.approx(expected=manually_calculated_result, rel=1e-4) + + @pytest.mark.parametrize( + ("n_ed", "e_n"), + [ + (-1000.0, 50.0), # n_ed is negative + (1000.0, -50.0), # e_n is negative + ], + ) + def test_raise_error_when_invalid_values_are_given(self, n_ed: float, e_n: float) -> None: + """Test invalid values.""" + with pytest.raises(NegativeValueError): + Form6Dot4AxialCompression(n_ed=n_ed, e_n=e_n) + + @pytest.mark.parametrize( + ("representation", "expected"), + [ + ( + "complete", + r"\Delta M_{Ed} = N_{Ed} \cdot e_{N} = 1000.000 \cdot 50.000 = 50000.000 Nmm", + ), + ("short", r"\Delta M_{Ed} = 50000.000 Nmm"), + ], + ) + def test_latex(self, representation: str, expected: str) -> None: + """Test the latex representation of the formula.""" + # Example values + n_ed = 1000.0 + e_n = 50.0 + + # Object to test + latex = Form6Dot4AxialCompression(n_ed=n_ed, e_n=e_n).latex() + + actual = { + "complete": latex.complete, + "short": latex.short, + } + + assert expected == actual[representation], f"{representation} representation failed." From ec42af9b2b2d870282d1faee60f494055279fb03 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 16:29:53 +0100 Subject: [PATCH 06/11] Add implementation and tests for formula 6.5 from NEN-EN 1993-1-1+C2+A1:2016 --- .../formula_6_5.py | 47 +++++++++++-------- .../test_formula_6_5.py | 22 +++++---- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_5.py b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_5.py index 89392e2ce..b7f305106 100644 --- a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_5.py +++ b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_5.py @@ -1,10 +1,9 @@ """Formula 6.5 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate limit state.""" -# pylint: disable=arguments-differ from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016 import NEN_EN_1993_1_1_C2_A1_2016 from blueprints.codes.formula import Formula -from blueprints.codes.latex_formula import LatexFormula -from blueprints.type_alias import KN, RATIO +from blueprints.codes.latex_formula import LatexFormula, latex_replace_symbols +from blueprints.type_alias import N from blueprints.validations import raise_if_less_or_equal_to_zero, raise_if_negative @@ -16,19 +15,19 @@ class Form6Dot5UnityCheckTensileStrength(Formula): def __init__( self, - n_ed: KN, - n_t_rd: KN, + n_ed: N, + n_t_rd: N, ) -> None: - r"""[$N_{Ed}/N_{t,Rd}$] Unity check for tensile strength of an element in tension. + r"""[$N_{Ed}/N_{t,Rd} \leq 1$] Unity check for tensile strength of an element in tension. NEN-EN 1993-1-1+C2+A1:2016 art.6.2.3(1) - Formula (6.5) Parameters ---------- - n_ed : KN - [$N_{Ed}$] Design value of the normal tensile force [kN]. - n_t_rd : KN - [$N_{t,Rd}$] Design value of the resistance against tensile force [kN]. + n_ed : N + [$N_{Ed}$] Design value of the normal tensile force [$N$]. + n_t_rd : N + [$N_{t,Rd}$] Design value of the resistance against tensile force [$N$]. """ super().__init__() self.n_ed = n_ed @@ -36,20 +35,30 @@ def __init__( @staticmethod def _evaluate( - n_ed: KN, - n_t_rd: KN, - ) -> RATIO: + n_ed: N, + n_t_rd: N, + ) -> bool: """Evaluates the formula, for more information see the __init__ method.""" raise_if_less_or_equal_to_zero(n_t_rd=n_t_rd) raise_if_negative(n_ed=n_ed) - return n_ed / n_t_rd + return (n_ed / n_t_rd) <= 1 def latex(self) -> LatexFormula: """Returns LatexFormula object for formula 6.5.""" + _equation: str = r"\left( \frac{N_{Ed}}{N_{t,Rd}} \leq 1 \right)" + _numeric_equation: str = latex_replace_symbols( + _equation, + { + "N_{Ed}": f"{self.n_ed:.3f}", + "N_{t,Rd}": f"{self.n_t_rd:.3f}", + }, + False, + ) return LatexFormula( - return_symbol=r"N_{Ed}/N_{t,Rd}", - result=f"{self:.2f}", - equation=r"N_{Ed} / N_{t,Rd}", - numeric_equation=rf"{self.n_ed:.2f} / {self.n_t_rd:.2f}", - comparison_operator_label="=", + return_symbol=r"CHECK", + result="OK" if self.__bool__() else "\\text{Not OK}", + equation=_equation, + numeric_equation=_numeric_equation, + comparison_operator_label="\\to", + unit="", ) diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_5.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_5.py index b2599ad15..313091f32 100644 --- a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_5.py +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_5.py @@ -17,9 +17,9 @@ def test_evaluation(self) -> None: form = Form6Dot5UnityCheckTensileStrength(n_ed=n_ed, n_t_rd=n_t_rd) # Expected result, manually calculated - expected = 0.7 + expected = True - assert form == pytest.approx(expected) + assert form == expected @pytest.mark.parametrize( ("n_ed", "n_t_rd"), @@ -35,12 +35,12 @@ def test_raise_error_when_negative_n_ed_is_given(self, n_ed: float, n_t_rd: floa @pytest.mark.parametrize( ("n_ed", "n_t_rd"), [ - (7, 0), # n_ed is negative + (7, 0), # n_t_rd is zero (7, -10), # n_t_rd is negative ], ) def test_raise_error_when_negative_or_zero_n_t_rd_is_given(self, n_ed: float, n_t_rd: float) -> None: - """Test a zero value for n_t_rd.""" + """Test a zero or negative value for n_t_rd.""" with pytest.raises(LessOrEqualToZeroError): Form6Dot5UnityCheckTensileStrength(n_ed=n_ed, n_t_rd=n_t_rd) @@ -49,9 +49,10 @@ def test_raise_error_when_negative_or_zero_n_t_rd_is_given(self, n_ed: float, n_ [ ( "complete", - r"N_{Ed}/N_{t,Rd} = N_{Ed} / N_{t,Rd} = 7.00 / 10.00 = 0.70", + r"CHECK \to \left( \frac{N_{Ed}}{N_{t,Rd}} \leq 1 \right) \to " + r"\left( \frac{7.000}{10.000} \leq 1 \right) \to OK", ), - ("short", r"N_{Ed}/N_{t,Rd} = 0.70"), + ("short", r"CHECK \to OK"), ], ) def test_latex(self, representation: str, expected: str) -> None: @@ -61,8 +62,11 @@ def test_latex(self, representation: str, expected: str) -> None: n_t_rd = 10 # kN # Object to test - form_6_5_latex = Form6Dot5UnityCheckTensileStrength(n_ed=n_ed, n_t_rd=n_t_rd).latex() + latex = Form6Dot5UnityCheckTensileStrength(n_ed=n_ed, n_t_rd=n_t_rd).latex() - actual = {"complete": form_6_5_latex.complete, "short": form_6_5_latex.short} + actual = { + "complete": latex.complete, + "short": latex.short, + } - assert actual[representation] == expected, f"{representation} representation failed." + assert expected == actual[representation], f"{representation} representation failed." From 3b01032244d3ed7a6917229c368171eaac352845 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 16:29:59 +0100 Subject: [PATCH 07/11] Add implementation and tests for formula 6.6 from NEN-EN 1993-1-1+C2+A1:2016 --- .../formula_6_6.py | 71 +++++++++++++++++ .../test_formula_6_6.py | 78 +++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_6.py create mode 100644 tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_6.py diff --git a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_6.py b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_6.py new file mode 100644 index 000000000..49b9bf189 --- /dev/null +++ b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_6.py @@ -0,0 +1,71 @@ +"""Formula 6.6 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate Limit State.""" + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016 import NEN_EN_1993_1_1_C2_A1_2016 +from blueprints.codes.formula import Formula +from blueprints.codes.latex_formula import LatexFormula, latex_replace_symbols +from blueprints.type_alias import DIMENSIONLESS, MM2, MPA, N +from blueprints.validations import raise_if_less_or_equal_to_zero, raise_if_negative + + +class Form6Dot6DesignPlasticRestistanceGrossCrossSection(Formula): + r"""Class representing formula 6.6 for the calculation of [$N_{pl,Rd}$].""" + + label = "6.6" + source_document = NEN_EN_1993_1_1_C2_A1_2016 + + def __init__( + self, + a: MM2, + f_y: MPA, + gamma_m0: DIMENSIONLESS, + ) -> None: + r"""[$N_{pl,Rd}$] Calculation of the design plastic resistance of the gross cross-section [$N$]. + + NEN-EN 1993-1-1+C2+A1:2016 art.6.2.3(2) - Formula (6.6) + + Parameters + ---------- + a : MM2 + [$A$] Gross cross-sectional area [$mm^2$]. + f_y : MPA + [$f_y$] Yield strength of the material [$MPa$]. + gamma_m0 : DIMENSIONLESS + [$\gamma_{M0}$] Partial safety factor for resistance of cross-sections whatever the class is. + """ + super().__init__() + self.a = a + self.f_y = f_y + self.gamma_m0 = gamma_m0 + + @staticmethod + def _evaluate( + a: MM2, + f_y: MPA, + gamma_m0: DIMENSIONLESS, + ) -> N: + """Evaluates the formula, for more information see the __init__ method.""" + raise_if_negative(a=a, f_y=f_y) + raise_if_less_or_equal_to_zero(gamma_m0=gamma_m0) + + return (a * f_y) / gamma_m0 + + def latex(self) -> LatexFormula: + """Returns LatexFormula object for formula 6.6.""" + _equation: str = r"\frac{A \cdot f_y}{\gamma_{M0}}" + _numeric_equation: str = latex_replace_symbols( + _equation, + { + r"A": f"{self.a:.3f}", + r"f_y": f"{self.f_y:.3f}", + r"\gamma_{M0}": f"{self.gamma_m0:.3f}", + }, + False, + ) + return LatexFormula( + return_symbol=r"N_{pl,Rd}", + result=f"{self:.3f}", + equation=_equation, + numeric_equation=_numeric_equation, + comparison_operator_label="=", + unit="N", + ) diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_6.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_6.py new file mode 100644 index 000000000..d762b0277 --- /dev/null +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_6.py @@ -0,0 +1,78 @@ +"""Testing formula 6.6 of NEN-EN 1993-1-1+C2+A1:2016.""" + +import pytest + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016.chapter_6_ultimate_limit_state.formula_6_6 import ( + Form6Dot6DesignPlasticRestistanceGrossCrossSection, +) +from blueprints.validations import LessOrEqualToZeroError, NegativeValueError + + +class TestForm6Dot6DesignPlasticRestistanceGrossCrossSection: + """Validation for formula 6.6 from NEN-EN 1993-1-1+C2+A1:2016.""" + + def test_evaluation(self) -> None: + """Tests the evaluation of the result.""" + # Example values + a = 5000.0 + f_y = 355.0 + gamma_m0 = 1.0 + + # Object to test + formula = Form6Dot6DesignPlasticRestistanceGrossCrossSection(a=a, f_y=f_y, gamma_m0=gamma_m0) + + # Expected result, manually calculated + manually_calculated_result = 1775000.0 # N + + assert formula == pytest.approx(expected=manually_calculated_result, rel=1e-4) + + @pytest.mark.parametrize( + ("a", "f_y", "gamma_m0"), + [ + (-5000.0, 355.0, 1.0), # a is negative + (5000.0, -355.0, 1.0), # f_y is negative + ], + ) + def test_raise_error_when_negative_values_are_given(self, a: float, f_y: float, gamma_m0: float) -> None: + """Test invalid values.""" + with pytest.raises(NegativeValueError): + Form6Dot6DesignPlasticRestistanceGrossCrossSection(a=a, f_y=f_y, gamma_m0=gamma_m0) + + @pytest.mark.parametrize( + ("a", "f_y", "gamma_m0"), + [ + (5000.0, 355.0, 0.0), # gamma_m0 is zero + (5000.0, 355.0, -1.0), # gamma_m0 is negative + ], + ) + def test_raise_error_when_less_or_equal_to_zero_values_are_given(self, a: float, f_y: float, gamma_m0: float) -> None: + """Test invalid values.""" + with pytest.raises(LessOrEqualToZeroError): + Form6Dot6DesignPlasticRestistanceGrossCrossSection(a=a, f_y=f_y, gamma_m0=gamma_m0) + + @pytest.mark.parametrize( + ("representation", "expected"), + [ + ( + "complete", + r"N_{pl,Rd} = \frac{A \cdot f_y}{\gamma_{M0}} = \frac{5000.000 \cdot 355.000}{1.000} = 1775000.000 N", + ), + ("short", r"N_{pl,Rd} = 1775000.000 N"), + ], + ) + def test_latex(self, representation: str, expected: str) -> None: + """Test the latex representation of the formula.""" + # Example values + a = 5000.0 + f_y = 355.0 + gamma_m0 = 1.0 + + # Object to test + latex = Form6Dot6DesignPlasticRestistanceGrossCrossSection(a=a, f_y=f_y, gamma_m0=gamma_m0).latex() + + actual = { + "complete": latex.complete, + "short": latex.short, + } + + assert expected == actual[representation], f"{representation} representation failed." From 6e727c911728c54a8c590d8582d1ee65ddac01c4 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 16:30:07 +0100 Subject: [PATCH 08/11] Add implementation and tests for formula 6.7 from NEN-EN 1993-1-1+C2+A1:2016 --- .../formula_6_7.py | 71 +++++++++++++++++++ .../test_formula_6_7.py | 69 ++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_7.py create mode 100644 tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_7.py diff --git a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_7.py b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_7.py new file mode 100644 index 000000000..e93182c3e --- /dev/null +++ b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_7.py @@ -0,0 +1,71 @@ +"""Formula 6.7 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate Limit State.""" + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016 import NEN_EN_1993_1_1_C2_A1_2016 +from blueprints.codes.formula import Formula +from blueprints.codes.latex_formula import LatexFormula, latex_replace_symbols +from blueprints.type_alias import DIMENSIONLESS, MM2, MPA, N +from blueprints.validations import raise_if_less_or_equal_to_zero, raise_if_negative + + +class Form6Dot7DesignUltimateResistanceNetCrossSection(Formula): + r"""Class representing formula 6.7 for the calculation of [$N_{t,Rd}$].""" + + label = "6.7" + source_document = NEN_EN_1993_1_1_C2_A1_2016 + + def __init__( + self, + a_net: MM2, + f_u: MPA, + gamma_m2: DIMENSIONLESS, + ) -> None: + r"""[$N_{u,Rd}$] Calculation of the design tension resistance [$N$]. + + NEN-EN 1993-1-1+C2+A1:2016 art.6.2.3(2) - Formula (6.7) + + Parameters + ---------- + a_net : MM2 + [$A_{net}$] Net cross-sectional area at holes for fasteners [$mm^2$]. + f_u : MPA + [$f_u$] Ultimate tensile strength of the material [$N/mm^2$]. + gamma_m2 : DIMENSIONLESS + [$\gamma_{M2}$] Partial safety factor for resistance of cross-sections in tension to fracture. + """ + super().__init__() + self.a_net = a_net + self.f_u = f_u + self.gamma_m2 = gamma_m2 + + @staticmethod + def _evaluate( + a_net: MM2, + f_u: MPA, + gamma_m2: DIMENSIONLESS, + ) -> N: + """Evaluates the formula, for more information see the __init__ method.""" + raise_if_negative(a_net=a_net, f_u=f_u) + raise_if_less_or_equal_to_zero(gamma_m2=gamma_m2) + + return 0.9 * a_net * f_u / gamma_m2 + + def latex(self) -> LatexFormula: + """Returns LatexFormula object for formula 6.7.""" + _equation: str = r"0.9 \cdot \frac{A_{net} \cdot f_u}{\gamma_{M2}}" + _numeric_equation: str = latex_replace_symbols( + _equation, + { + r"A_{net}": f"{self.a_net:.3f}", + r"f_u": f"{self.f_u:.3f}", + r"\gamma_{M2}": f"{self.gamma_m2:.3f}", + }, + False, + ) + return LatexFormula( + return_symbol=r"N_{u,Rd}", + result=f"{self:.3f}", + equation=_equation, + numeric_equation=_numeric_equation, + comparison_operator_label="=", + unit="N", + ) diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_7.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_7.py new file mode 100644 index 000000000..07b576cd6 --- /dev/null +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_7.py @@ -0,0 +1,69 @@ +"""Testing formula 6.7 of NEN-EN 1993-1-1+C2+A1:2016.""" + +import pytest + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016.chapter_6_ultimate_limit_state.formula_6_7 import ( + Form6Dot7DesignUltimateResistanceNetCrossSection, +) +from blueprints.validations import LessOrEqualToZeroError, NegativeValueError + + +class TestForm6Dot7DesignUltimateResistanceNetCrossSection: + """Validation for formula 6.7 from NEN-EN 1993-1-1+C2+A1:2016.""" + + def test_evaluation(self) -> None: + """Tests the evaluation of the result.""" + # Example values + a_net = 2000.0 + f_u = 400.0 + gamma_m2 = 1.1 + + # Object to test + formula = Form6Dot7DesignUltimateResistanceNetCrossSection(a_net=a_net, f_u=f_u, gamma_m2=gamma_m2) + + # Expected result, manually calculated + manually_calculated_result = 654545.454545454 # N + + assert formula == pytest.approx(manually_calculated_result, rel=1e-4) + + @pytest.mark.parametrize( + ("a_net", "f_u", "gamma_m2"), + [ + (2000.0, 400.0, 0.0), # gamma_m2 is zero + (-2000.0, 400.0, 1.1), # a_net is negative + (2000.0, -400.0, 1.1), # f_u is negative + (2000.0, 400.0, -1.1), # gamma_m2 is negative + ], + ) + def test_raise_error_when_invalid_values_are_given(self, a_net: float, f_u: float, gamma_m2: float) -> None: + """Test invalid values.""" + with pytest.raises((LessOrEqualToZeroError, NegativeValueError)): + Form6Dot7DesignUltimateResistanceNetCrossSection(a_net=a_net, f_u=f_u, gamma_m2=gamma_m2) + + @pytest.mark.parametrize( + ("representation", "expected"), + [ + ( + "complete", + r"N_{u,Rd} = 0.9 \cdot \frac{A_{net} \cdot f_u}{\gamma_{M2}} = " + r"0.9 \cdot \frac{2000.000 \cdot 400.000}{1.100} = 654545.455 N", + ), + ("short", r"N_{u,Rd} = 654545.455 N"), + ], + ) + def test_latex(self, representation: str, expected: str) -> None: + """Test the latex representation of the formula.""" + # Example values + a_net = 2000.0 + f_u = 400.0 + gamma_m2 = 1.1 + + # Object to test + latex = Form6Dot7DesignUltimateResistanceNetCrossSection(a_net=a_net, f_u=f_u, gamma_m2=gamma_m2).latex() + + actual = { + "complete": latex.complete, + "short": latex.short, + } + + assert expected == actual[representation], f"{representation} representation failed." From e3f142c31eb16ae5b6d42b342428a39c80de3271 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Fri, 21 Feb 2025 16:30:13 +0100 Subject: [PATCH 09/11] Add implementation and tests for formula 6.8 from NEN-EN 1993-1-1+C2+A1:2016 --- .../formula_6_8.py | 71 +++++++++++++++++++ .../test_formula_6_8.py | 67 +++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_8.py create mode 100644 tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_8.py diff --git a/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_8.py b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_8.py new file mode 100644 index 000000000..74c1187b5 --- /dev/null +++ b/blueprints/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/formula_6_8.py @@ -0,0 +1,71 @@ +"""Formula 6.8 from NEN-EN 1993-1-1+C2+A1:2016: Chapter 6 - Ultimate Limit State.""" + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016 import NEN_EN_1993_1_1_C2_A1_2016 +from blueprints.codes.formula import Formula +from blueprints.codes.latex_formula import LatexFormula, latex_replace_symbols +from blueprints.type_alias import DIMENSIONLESS, MM2, MPA, N +from blueprints.validations import raise_if_less_or_equal_to_zero, raise_if_negative + + +class Form6Dot8NetDesignTensionResistance(Formula): + r"""Class representing formula 6.8 for the calculation of [$N_{net,Rd}$].""" + + label = "6.8" + source_document = NEN_EN_1993_1_1_C2_A1_2016 + + def __init__( + self, + a_net: MM2, + f_y: MPA, + gamma_m0: DIMENSIONLESS, + ) -> None: + r"""[$N_{net,Rd}$] Calculation of the design tension resistance [$N$]. + + NEN-EN 1993-1-1+C2+A1:2016 art.6.2.3(4) - Formula (6.8) + + Parameters + ---------- + a_net : MM2 + [$A_{net}$] Net area at holes for fasteners [$mm^2$]. + f_y : MPA + [$f_y$] Yield strength of the material [$MPa$]. + gamma_m0 : DIMENSIONLESS + [$\gamma_{M0}$] Partial safety factor for resistance of cross-sections whatever the class is. + """ + super().__init__() + self.a_net = a_net + self.f_y = f_y + self.gamma_m0 = gamma_m0 + + @staticmethod + def _evaluate( + a_net: MM2, + f_y: MPA, + gamma_m0: DIMENSIONLESS, + ) -> N: + """Evaluates the formula, for more information see the __init__ method.""" + raise_if_negative(a_net=a_net, f_y=f_y) + raise_if_less_or_equal_to_zero(gamma_m0=gamma_m0) + + return (a_net * f_y) / gamma_m0 + + def latex(self) -> LatexFormula: + """Returns LatexFormula object for formula 6.8.""" + _equation: str = r"\frac{A_{net} \cdot f_y}{\gamma_{M0}}" + _numeric_equation: str = latex_replace_symbols( + _equation, + { + r"A_{net}": f"{self.a_net:.3f}", + r"f_y": f"{self.f_y:.3f}", + r"\gamma_{M0}": f"{self.gamma_m0:.3f}", + }, + False, + ) + return LatexFormula( + return_symbol=r"N_{net,Rd}", + result=f"{self:.3f}", + equation=_equation, + numeric_equation=_numeric_equation, + comparison_operator_label="=", + unit="N", + ) diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_8.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_8.py new file mode 100644 index 000000000..68d1fc7f5 --- /dev/null +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_8.py @@ -0,0 +1,67 @@ +"""Testing formula 6.8 of NEN-EN 1993-1-1+C2+A1:2016.""" + +import pytest + +from blueprints.codes.eurocode.nen_en_1993_1_1_c2_a1_2016.chapter_6_ultimate_limit_state.formula_6_8 import Form6Dot8NetDesignTensionResistance +from blueprints.validations import LessOrEqualToZeroError, NegativeValueError + + +class TestForm6Dot8NetDesignTensionResistance: + """Validation for formula 6.8 from NEN-EN 1993-1-1+C2+A1:2016.""" + + def test_evaluation(self) -> None: + """Tests the evaluation of the result.""" + # Example values + a_net = 5000.0 # mm^2 + f_y = 355.0 # MPa + gamma_m0 = 1.0 + + # Object to test + formula = Form6Dot8NetDesignTensionResistance(a_net=a_net, f_y=f_y, gamma_m0=gamma_m0) + + # Expected result, manually calculated + manually_calculated_result = 1775000.0 # N + + assert formula == pytest.approx(expected=manually_calculated_result, rel=1e-4) + + @pytest.mark.parametrize( + ("a_net", "f_y", "gamma_m0"), + [ + (-5000.0, 355.0, 1.0), # a_net is negative + (5000.0, -355.0, 1.0), # f_y is negative + (5000.0, 355.0, -1.0), # gamma_m0 is negative + (5000.0, 355.0, 0.0), # gamma_m0 is zero + ], + ) + def test_raise_error_when_invalid_values_are_given(self, a_net: float, f_y: float, gamma_m0: float) -> None: + """Test invalid values.""" + with pytest.raises((NegativeValueError, LessOrEqualToZeroError)): + Form6Dot8NetDesignTensionResistance(a_net=a_net, f_y=f_y, gamma_m0=gamma_m0) + + @pytest.mark.parametrize( + ("representation", "expected"), + [ + ( + "complete", + r"N_{net,Rd} = \frac{A_{net} \cdot f_y}{\gamma_{M0}} = " + r"\frac{5000.000 \cdot 355.000}{1.000} = 1775000.000 N", + ), + ("short", r"N_{net,Rd} = 1775000.000 N"), + ], + ) + def test_latex(self, representation: str, expected: str) -> None: + """Test the latex representation of the formula.""" + # Example values + a_net = 5000.0 # mm^2 + f_y = 355.0 # MPa + gamma_m0 = 1.0 + + # Object to test + latex = Form6Dot8NetDesignTensionResistance(a_net=a_net, f_y=f_y, gamma_m0=gamma_m0).latex() + + actual = { + "complete": latex.complete, + "short": latex.short, + } + + assert expected == actual[representation], f"{representation} representation failed." From e7108e5a83067129dc4ad497239fac00b2daffc2 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Mon, 28 Apr 2025 19:37:15 +0200 Subject: [PATCH 10/11] Fix LaTeX formatting in test formulas for NEN-EN 1993-1-1+C2+A1:2016 --- .../chapter_6_ultimate_limit_state/test_formula_6_3.py | 4 ++-- .../chapter_6_ultimate_limit_state/test_formula_6_4.py | 4 ++-- .../chapter_6_ultimate_limit_state/test_formula_6_6.py | 4 ++-- .../chapter_6_ultimate_limit_state/test_formula_6_7.py | 4 ++-- .../chapter_6_ultimate_limit_state/test_formula_6_8.py | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_3.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_3.py index d77d52e47..8d6417765 100644 --- a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_3.py +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_3.py @@ -56,9 +56,9 @@ def test_raise_error_when_invalid_values_are_given(self, t: float, n: float, d_0 "complete", r"A_{deduction} = t \left( n \cdot d_0 - \sum \frac{s^2}{4 \cdot p} \right) = " r"10.000 \left( 5.000 \cdot 20.000 - \left( \frac{50.000^2}{4 \cdot 100.000} + " - r"\frac{60.000^2}{4 \cdot 120.000} \right) \right) = 862.500 mm^2", + r"\frac{60.000^2}{4 \cdot 120.000} \right) \right) = 862.500 \ mm^2", ), - ("short", r"A_{deduction} = 862.500 mm^2"), + ("short", r"A_{deduction} = 862.500 \ mm^2"), ], ) def test_latex(self, representation: str, expected: str) -> None: diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_4.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_4.py index 2cd0831dc..13c351691 100644 --- a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_4.py +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_4.py @@ -40,9 +40,9 @@ def test_raise_error_when_invalid_values_are_given(self, n_ed: float, e_n: float [ ( "complete", - r"\Delta M_{Ed} = N_{Ed} \cdot e_{N} = 1000.000 \cdot 50.000 = 50000.000 Nmm", + r"\Delta M_{Ed} = N_{Ed} \cdot e_{N} = 1000.000 \cdot 50.000 = 50000.000 \ Nmm", ), - ("short", r"\Delta M_{Ed} = 50000.000 Nmm"), + ("short", r"\Delta M_{Ed} = 50000.000 \ Nmm"), ], ) def test_latex(self, representation: str, expected: str) -> None: diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_6.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_6.py index d762b0277..ddc57ac84 100644 --- a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_6.py +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_6.py @@ -55,9 +55,9 @@ def test_raise_error_when_less_or_equal_to_zero_values_are_given(self, a: float, [ ( "complete", - r"N_{pl,Rd} = \frac{A \cdot f_y}{\gamma_{M0}} = \frac{5000.000 \cdot 355.000}{1.000} = 1775000.000 N", + r"N_{pl,Rd} = \frac{A \cdot f_y}{\gamma_{M0}} = \frac{5000.000 \cdot 355.000}{1.000} = 1775000.000 \ N", ), - ("short", r"N_{pl,Rd} = 1775000.000 N"), + ("short", r"N_{pl,Rd} = 1775000.000 \ N"), ], ) def test_latex(self, representation: str, expected: str) -> None: diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_7.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_7.py index 07b576cd6..a7154e7b9 100644 --- a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_7.py +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_7.py @@ -46,9 +46,9 @@ def test_raise_error_when_invalid_values_are_given(self, a_net: float, f_u: floa ( "complete", r"N_{u,Rd} = 0.9 \cdot \frac{A_{net} \cdot f_u}{\gamma_{M2}} = " - r"0.9 \cdot \frac{2000.000 \cdot 400.000}{1.100} = 654545.455 N", + r"0.9 \cdot \frac{2000.000 \cdot 400.000}{1.100} = 654545.455 \ N", ), - ("short", r"N_{u,Rd} = 654545.455 N"), + ("short", r"N_{u,Rd} = 654545.455 \ N"), ], ) def test_latex(self, representation: str, expected: str) -> None: diff --git a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_8.py b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_8.py index 68d1fc7f5..66edb8b3b 100644 --- a/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_8.py +++ b/tests/codes/eurocode/nen_en_1993_1_1_c2_a1_2016/chapter_6_ultimate_limit_state/test_formula_6_8.py @@ -44,9 +44,9 @@ def test_raise_error_when_invalid_values_are_given(self, a_net: float, f_y: floa ( "complete", r"N_{net,Rd} = \frac{A_{net} \cdot f_y}{\gamma_{M0}} = " - r"\frac{5000.000 \cdot 355.000}{1.000} = 1775000.000 N", + r"\frac{5000.000 \cdot 355.000}{1.000} = 1775000.000 \ N", ), - ("short", r"N_{net,Rd} = 1775000.000 N"), + ("short", r"N_{net,Rd} = 1775000.000 \ N"), ], ) def test_latex(self, representation: str, expected: str) -> None: From cd8a7d8c9539c061e017694248edfa44cf436ba6 Mon Sep 17 00:00:00 2001 From: GerjanDorgelo Date: Mon, 28 Apr 2025 19:39:32 +0200 Subject: [PATCH 11/11] Update implementation status for formulas 6.9 to 6.16 in Eurocode 3 documentation --- .../eurocode/ec3_1993_1_1_2016/formulas.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md b/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md index 717df0126..f3b8a5da1 100644 --- a/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md +++ b/docs/objects_overview/eurocode/ec3_1993_1_1_2016/formulas.md @@ -33,14 +33,14 @@ Total of 108 formulas present. | 6.6 | :heavy_check_mark: | | Form6Dot6DesignPlasticRestistanceGrossCrossSection | | 6.7 | :heavy_check_mark: | | Form6Dot7DesignUltimateResistanceNetCrossSection | | 6.8 | :heavy_check_mark: | | Form6Dot8NetDesignTensionResistance | -| 6.9 | :x: | | Form6Dot9CheckCompressionForce | -| 6.10 | :x: | | Form6Dot10NcRdClass1And2And3 | -| 6.11 | :x: | | Form6Dot11NcRdClass4 | -| 6.12 | :x: | | Form6Dot12CheckBendingMoment | -| 6.13 | :x: | | Form6Dot13MCRdClass1And2 | -| 6.14 | :x: | | Form6Dot14MCRdClass3 | -| 6.15 | :x: | | Form6Dot15McRdClass4 | -| 6.16 | :x: | | Form6Dot16CheckFlangeWithFastenerHoles | +| 6.9 | :heavy_check_mark: | | Form6Dot9CheckCompressionForce | +| 6.10 | :heavy_check_mark: | | Form6Dot10NcRdClass1And2And3 | +| 6.11 | :heavy_check_mark: | | Form6Dot11NcRdClass4 | +| 6.12 | :heavy_check_mark: | | Form6Dot12CheckBendingMoment | +| 6.13 | :heavy_check_mark: | | Form6Dot13MCRdClass1And2 | +| 6.14 | :heavy_check_mark: | | Form6Dot14MCRdClass3 | +| 6.15 | :heavy_check_mark: | | Form6Dot15McRdClass4 | +| 6.16 | :heavy_check_mark: | | Form6Dot16CheckFlangeWithFastenerHoles | | 6.17 | :x: | | | | 6.18 | :x: | | | | 6.19 | :x: | | |