From 839d7061f851b9c0a0053d7b5be091647b6b6881 Mon Sep 17 00:00:00 2001 From: Ivan Tomac Date: Fri, 24 Oct 2025 19:59:11 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Added=20functinon=20=C2=B4s=5Feqa=5Fasme()?= =?UTF-8?q?=C2=B4=20and=20file=20for=20test=20functions=20=C2=B4test=5Fdam?= =?UTF-8?q?=5Fparams.py=C2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/stress_life/demage_parameters.py | 62 +++++++++++++++++++ tests/stress_life/test_dam_params.py | 19 ++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/stress_life/test_dam_params.py diff --git a/src/fatpy/core/stress_life/demage_parameters.py b/src/fatpy/core/stress_life/demage_parameters.py index 46f87a9..d65e570 100644 --- a/src/fatpy/core/stress_life/demage_parameters.py +++ b/src/fatpy/core/stress_life/demage_parameters.py @@ -1 +1,63 @@ """Damage parameters calculation methods for the stress-life.""" +import inspect +import warnings +import numpy as np +from numpy.typing import NDArray + +def s_eqa_asme(fat_strength_coef: NDArray[np.float64], + fat_strength_exp: NDArray[np.float64], + yilel_stress: NDArray[np.float64], + stress_amp: NDArray[np.float64], + mean_stress: NDArray[np.float64] + ) -> NDArray[np.uint64]: + """ + Uniaxial high-cycle fatigue criterion using the equivalent stress amplitude + based on ASME + + References + ---------- + [1] J. Papuga, I. Vízková, M. Lutovinov, M. Nesládek: Mean stress effect in + stress-life fatigue prediction re-evaluated, MATEC Web of Conferences 165, + 10018, 2018. + + Parameters + ---------- + :param fat_strength_coef : NDArray[np.float64] Manson-Coffin and Basquin + equation fatigue strength coefficient in [MPa] + :param fat_strength_exp : NDArray[np.float64] Manson-Coffin and Basquin + equation fatigue strength exponent + :param yilel_stress : NDArray[np.float64] Tensile yield strength in [MPa] + :param stress_amp : NDArray[np.float64] Stress amplitude in [MPa] + :param mean_stress : NDArray[np.float64] Mean stress in [MPa] + + :return: NDArray[np.uint64] Estimated repetitions N of a given load cycle + to failure + """ + signature = inspect.signature(s_eqa_asme) + for param in signature.parameters.values(): + if param.name not in locals(): + raise ValueError(f"Missing argument: {param.name}") + if not isinstance(locals()[param.name], np.ndarray): + raise TypeError(f"{param.name} must be a numpy ndarray.") + + if np.any(fat_strength_coef <= 0): + raise ValueError("fat_strength_coef must be positive values.") + if np.any(fat_strength_exp >= 0): + raise ValueError("fat_strength_exp must be negative values.") + if np.any(yilel_stress <= 0): + raise ValueError("yilel_stress must be positive values.") + if np.any(stress_amp < 0): + raise ValueError("stress_amp must be non-negative values.") + if np.any(mean_stress/yilel_stress >= 1): + raise ValueError("mean_stress/yilel_stress must be less than 1.") + + stress_aeq = stress_amp / np.sqrt(1 - (mean_stress/yilel_stress)**2) + + if np.any(stress_aeq >= fat_strength_coef): + warnings.warn("excessive loading detected resulting in N < 1.", UserWarning) + + N = 0.5 * (stress_aeq / fat_strength_coef)**(1/fat_strength_exp) + + return N.astype(np.uint64) + + diff --git a/tests/stress_life/test_dam_params.py b/tests/stress_life/test_dam_params.py new file mode 100644 index 0000000..fdb1361 --- /dev/null +++ b/tests/stress_life/test_dam_params.py @@ -0,0 +1,19 @@ +"""Damage parameters calculation methods for the stress-life. + +""" + +import numpy as np +import pytest +from numpy.typing import NDArray +from fatpy.core.stress_life.demage_parameters import s_eqa_asme + +def test_s_eqa_asme() -> None: + fat_strength_coef = np.array([475.4]) + fat_strength_exp = np.array([-0.078]) + yilel_stress = np.array([500.0]) + stress_amp = np.array([180.0]) + mean_stress = np.array([100.0]) + + N = s_eqa_asme(fat_strength_coef, fat_strength_exp, yilel_stress, stress_amp, mean_stress) + print(N) + assert N == np.array([98366]) \ No newline at end of file From 69b0d5d84328c6e685965f518bc0c14b5d62aece Mon Sep 17 00:00:00 2001 From: Ivan Tomac Date: Fri, 24 Oct 2025 20:13:59 +0200 Subject: [PATCH 2/3] minor correction --- tests/stress_life/test_dam_params.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/stress_life/test_dam_params.py b/tests/stress_life/test_dam_params.py index fdb1361..1d5552f 100644 --- a/tests/stress_life/test_dam_params.py +++ b/tests/stress_life/test_dam_params.py @@ -15,5 +15,4 @@ def test_s_eqa_asme() -> None: mean_stress = np.array([100.0]) N = s_eqa_asme(fat_strength_coef, fat_strength_exp, yilel_stress, stress_amp, mean_stress) - print(N) assert N == np.array([98366]) \ No newline at end of file From d8a311f929b880962e9874a8cb4e9e1f4255459c Mon Sep 17 00:00:00 2001 From: Ivan Tomac Date: Fri, 24 Oct 2025 20:13:59 +0200 Subject: [PATCH 3/3] Code corrected according to reviewer comments. --- .../core/stress_life/demage_parameters.py | 83 +++++++------------ tests/stress_life/test_dam_params.py | 23 ++--- 2 files changed, 38 insertions(+), 68 deletions(-) diff --git a/src/fatpy/core/stress_life/demage_parameters.py b/src/fatpy/core/stress_life/demage_parameters.py index d65e570..6b599cf 100644 --- a/src/fatpy/core/stress_life/demage_parameters.py +++ b/src/fatpy/core/stress_life/demage_parameters.py @@ -1,63 +1,38 @@ """Damage parameters calculation methods for the stress-life.""" -import inspect -import warnings + import numpy as np from numpy.typing import NDArray -def s_eqa_asme(fat_strength_coef: NDArray[np.float64], - fat_strength_exp: NDArray[np.float64], - yilel_stress: NDArray[np.float64], - stress_amp: NDArray[np.float64], - mean_stress: NDArray[np.float64] - ) -> NDArray[np.uint64]: - """ - Uniaxial high-cycle fatigue criterion using the equivalent stress amplitude - based on ASME - References - ---------- - [1] J. Papuga, I. Vízková, M. Lutovinov, M. Nesládek: Mean stress effect in +def calc_stress_eq_amp_asme( + yield_stress: NDArray[np.float64], + stress_amp: NDArray[np.float64], + mean_stress: NDArray[np.float64], +) -> NDArray[np.float64]: + r"""Stress-life prediction function based on the ASME mean-stress correction. + + Commputes the value of equivalent stress amplitude, :math:`\sigma_{aeq}` in MPa + for given stress values :math:`\sigma_a` and :math:`\sigma_m` representing a + single load cycle, using the ASME mean stress correction. + + ### Mathematical formulation: + + $$ \displaystyle\sigma_{aeq}=\frac{\sigma_a}{\left[1-\left(\frac{\sigma_m}{R_e} + \right)^2\right]^{1/2} } $$ + + Args: + yield_stress: :math:`R_e` - Tensile yield strength in [MPa]. + stress_amp: :math:`\\sigma_a` - Stress amplitude in [MPa]. + mean_stress: :math:`\\sigma_m` - Mean stress in [MPa]. + + Returns: + Equivalent stress amplitude by ASME + + References: + [1] J. Papuga, I. Vízková, M. Lutovinov, M. Nesládek: Mean stress effect in stress-life fatigue prediction re-evaluated, MATEC Web of Conferences 165, 10018, 2018. - - Parameters - ---------- - :param fat_strength_coef : NDArray[np.float64] Manson-Coffin and Basquin - equation fatigue strength coefficient in [MPa] - :param fat_strength_exp : NDArray[np.float64] Manson-Coffin and Basquin - equation fatigue strength exponent - :param yilel_stress : NDArray[np.float64] Tensile yield strength in [MPa] - :param stress_amp : NDArray[np.float64] Stress amplitude in [MPa] - :param mean_stress : NDArray[np.float64] Mean stress in [MPa] - - :return: NDArray[np.uint64] Estimated repetitions N of a given load cycle - to failure """ - signature = inspect.signature(s_eqa_asme) - for param in signature.parameters.values(): - if param.name not in locals(): - raise ValueError(f"Missing argument: {param.name}") - if not isinstance(locals()[param.name], np.ndarray): - raise TypeError(f"{param.name} must be a numpy ndarray.") - - if np.any(fat_strength_coef <= 0): - raise ValueError("fat_strength_coef must be positive values.") - if np.any(fat_strength_exp >= 0): - raise ValueError("fat_strength_exp must be negative values.") - if np.any(yilel_stress <= 0): - raise ValueError("yilel_stress must be positive values.") - if np.any(stress_amp < 0): - raise ValueError("stress_amp must be non-negative values.") - if np.any(mean_stress/yilel_stress >= 1): - raise ValueError("mean_stress/yilel_stress must be less than 1.") - - stress_aeq = stress_amp / np.sqrt(1 - (mean_stress/yilel_stress)**2) - - if np.any(stress_aeq >= fat_strength_coef): - warnings.warn("excessive loading detected resulting in N < 1.", UserWarning) - - N = 0.5 * (stress_aeq / fat_strength_coef)**(1/fat_strength_exp) - - return N.astype(np.uint64) - + stress_aeq = stress_amp / np.sqrt(1 - (mean_stress / yield_stress) ** 2) + return stress_aeq diff --git a/tests/stress_life/test_dam_params.py b/tests/stress_life/test_dam_params.py index 1d5552f..a8073cf 100644 --- a/tests/stress_life/test_dam_params.py +++ b/tests/stress_life/test_dam_params.py @@ -1,18 +1,13 @@ -"""Damage parameters calculation methods for the stress-life. - -""" +"""Damage parameters calculation methods for the stress-life.""" import numpy as np -import pytest -from numpy.typing import NDArray -from fatpy.core.stress_life.demage_parameters import s_eqa_asme +from fatpy.core.stress_life.demage_parameters import calc_stress_eq_amp_asme + -def test_s_eqa_asme() -> None: - fat_strength_coef = np.array([475.4]) - fat_strength_exp = np.array([-0.078]) - yilel_stress = np.array([500.0]) - stress_amp = np.array([180.0]) - mean_stress = np.array([100.0]) +def test_calc_stress_eq_amp_asme() -> None: + yield_stress = 500.0 + stress_amp = 180.0 + mean_stress = 100.0 - N = s_eqa_asme(fat_strength_coef, fat_strength_exp, yilel_stress, stress_amp, mean_stress) - assert N == np.array([98366]) \ No newline at end of file + sigma_aeq = calc_stress_eq_amp_asme(yield_stress, stress_amp, mean_stress) + assert np.around(sigma_aeq, 1) == 183.7