stress_life#
The module py_fatigue.damage.stress_life
contains all the
damage models related to the stress-life approach.
- class py_fatigue.damage.stress_life.PalmgrenMiner(pandas_obj)#
Accessor for the Palmgren-Miner damage model.
- damage(sn_curve: SNCurve)#
Calculate the damage of the samples.
- Parameters:
sn_curve (SNCurve) – The SNCurve object.
- Returns:
The DataFrame with the damage.
- Return type:
DataFrame
- des(slope: float, equivalent_cycles: float = 10000000.0) float #
Calculate the damage equivalent stress range (DES).
- Parameters:
- Returns:
The DES.
- Return type:
See also
- dem(outer_radius: float, inner_radius: float, slope: float, equivalent_cycles: float = 10000000.0) float #
Calculate the damage equivalent stress range (DES).
- Parameters:
- Returns:
The DES.
- Return type:
See also
- plot_histogram(fig: Figure | None = None, ax: Axes | None = None, dens_func: Callable | None = None, **kwargs) Tuple[Figure, Axes] #
Plot the damage.
- Parameters:
fig (matplotlib.figure.Figure, optional) – The figure to plot on, by default None
ax (matplotlib.collections.PathCollection, optional) – The axes to plot on, by default None
kwargs – Additional keyword arguments for the plot.
- Returns:
The figure and axes.
- Return type:
matplotlib.figure.Figure, matplotlib.collections.PathCollection
- class py_fatigue.damage.stress_life.Gassner(pandas_obj)#
Accessor for the Gassner shift factor for variable amplitude.
- g(sn_curve: SNCurve)#
Calculate the shift factor of the samples.
The shift factor is a spectrum-dependent factor that allows to shift a Wohler curve and avoids having to calculate the damage using the
PalmgrenMiner
ruleevery time.Once the shift factor has been calculated, it can be applied to the Wohler SN curve. Then, accssing the curve through the maximum amplitude value of the spectrum will return the expected life for said spectrum.
The shift factor for each cycle in the spectrum is:
\[G_j = \frac{n_j}{N_S} \, \left({\frac{\sigma_{{max}_j} \, \sigma_{{alt}_j}} {\max{\sigma_{alt}} ^ {2}}}\right)^{2}\]The shift factor then is:
\[G = \sum_{j=1}^{N_B} G_j\]- Parameters:
sn_curve (SNCurve) – The SNCurve object.
- Returns:
The DataFrame with the shift factor per sample.
- Return type:
DataFrame
- py_fatigue.damage.stress_life.calc_pm(stress_range: float | Series | ndarray, count_cycle: float | Series | ndarray, sn_curve: SNCurve) ndarray #
Calculates the damage using the Palmgren-Miner rule, i.e. the linear damage accumulation rule:
\[D = \sum_{j=1}^{N_{\text{blocks}}} \frac{n_j}{N_j} \leq 1\]- Parameters:
stress_range (Union[pd.Series, np.ndarray]) – The stress range
- count_cycleUnion[pd.Series, np.ndarray]
The number of cycles
- sn_curveSNCurve
The SNCurve object.
- Returns:
The damage according to the Palmgren-Miner rule.
- Return type:
Union[float, np.ndarray]
- py_fatigue.damage.stress_life.calc_des(stress_range: float | Series | ndarray, count_cycle: float | Series | ndarray, slope: float, equivalent_cycles: float = 10000000.0) float #
Calculate the damage equivalent stress range (DES).
- Parameters:
- Returns:
The DES.
- Return type:
- py_fatigue.damage.stress_life.calc_dem(outer_radius: float, inner_radius: float, stress_range: float | Series | ndarray, count_cycle: float | Series | ndarray, slope: float, equivalent_cycles: float = 10000000.0) float #
Calculate the damage equivalent moment (DEM) in Nm.
\[DEM = DES * I_c / r_o = DES * S\]with \(I_c\) the area moment of inertia and \(r_i\) the inner radius, or \(S\) the Section modulus. The Damage Equivalent Stress Range (DES) is calculated using
calc_des()
- Parameters:
outer_radius (float) – The outer radius to calculate the DEM. Must be provided in m
inner_radius (float) – The inner radius to calculate the DEM. Must be provided in m
stress_range (Union[float, pd.Series, np.ndarray]) – The stress range
count_cycle (Union[float, pd.Series, np.ndarray]) – The number of cycles
slope (float) – The SN curve slope
equivalent_cycles (float, optional) – The equivalent number of cycles, by default 1e7
- Raises:
ValueError – If the inner radius is larger than the outer radius.
- Returns:
The DEM in Nm.
- Return type:
- py_fatigue.damage.stress_life.get_pm(cycle_count: CycleCount, sn_curve: SNCurve) ndarray #
Calculates the damage using the Palmgren-Miner rule.
- Parameters:
cycle_count (CycleCount) – The CycleCount object.
sn_curve (SNCurve) – The SNCurve object.
- Returns:
The damage according to the Palmgren-Miner rule.
- Return type:
np.ndarray
- py_fatigue.damage.stress_life.get_des(cycle_count: CycleCount, slope: float, equivalent_cycles: float = 10000000.0) float #
Calculate the damage equivalent stress range (DES).
- Parameters:
cycle_count (CycleCount) – The CycleCount object.
slope (float) – The SN curve slope
equivalent_cycles (float, optional) – The equivalent number of cycles, by default 1e7
- Returns:
The DES.
- Return type:
- py_fatigue.damage.stress_life.get_dem(outer_radius: float, inner_radius: float, cycle_count: CycleCount, slope: float, equivalent_cycles: float = 10000000.0) float #
Calculate the damage equivalent moment (DEM) in Nm.
\[DEM = DES * I_c / r_o = DES * S\]with \(I_c\) the area moment of inertia and \(r_i\) the inner radius, or \(S\) the Section modulus. The Damage Equivalent Stress Range (DES) is calculated using
calc_des()
- Parameters:
outer_radius (float) – The outer radius to calculate the DEM. Must be provided in m
inner_radius (float) – The inner radius to calculate the DEM. Must be provided in m
stress_range (Union[pd.Series, np.ndarray]) – The stress range
count_cycle (Union[pd.Series, np.ndarray]) – The number of cycles
slope (float) – The SN curve slope
equivalent_cycles (float, optional) – The equivalent number of cycles, by default 1e7
- Returns:
The DEM in Nm.
- Return type:
- py_fatigue.damage.stress_life.calc_manson_halford_exponents(cycles_to_failure: ndarray, exponent: float = 0.4) ndarray #
Calculate the Mannson-Halford exponents \(e_{j, j+1}\).
\[e{j, j+1} = \left(\frac{N_{j}}{N_{j+1}}\right)^{exponent}\]- Parameters:
cycles_to_failure (np.ndarray) – The number of cycles to failure.
exponent (float, optional) – The exponent, by default 0.4
- Returns:
The Mannson-Halford exponents.
- Return type:
np.ndarray
- py_fatigue.damage.stress_life.calc_pavlou_exponents(stress_range: ndarray, ultimate_stress: float = 900, exponent: float = -0.75, use_dca: bool = False) ndarray #
Calculate the Pavlou exponents \(q(\sigma_j)=e_{j, j+1}\).
\[e_{j, j+1} = \left(\frac{\Delta \sigma_j / 2}{\sigma_U}\right) ^{exponent}\]where \(\Delta \sigma_j\) is the stress amplitude, \(\sigma_U\) is the ultimate stress, \(\Delta \sigma\) is the stress range and \(exponent\) is the exponent.
- py_fatigue.damage.stress_life.calc_si_jian_exponents(stress_range: ndarray) ndarray #
Calculate the Si-Jian et al. exponents as
\[e_{j, j+1} = \sigma_{j+1} / \sigma_{j}\]where \(\sigma_{j+1}\) is the stress amplitude for the \(j\)-th cycle.
- Parameters:
stress_range (np.ndarray) – The stress range.
- Returns:
The Si-Jian et al. exponents.
- Return type:
np.ndarray
- py_fatigue.damage.stress_life.calc_theil_weights(stress_range: ndarray, sn_curve: SNCurve) ndarray #
Calculate the Theil weights for the Damage Curve Approach (DCA).
\[w_j = \frac{\Delta\sigma_j}{N_{f,j}}\]- Parameters:
stress_range (np.ndarray) – The stress range.
sn_curve (SNCurve) – The py-fatigue SN Curve
- Returns:
Theil’s model weights
- Return type:
np.ndarray
- py_fatigue.damage.stress_life.calc_nonlinear_damage(damage_rule: str, stress_range: ndarray, count_cycle: ndarray, sn_curve: SNCurve, **kwargs) float #
Calculate the fatigue damage using a nonlinear damage rule among the allowed ones:
‘Pavlou’: Pavlou damage rule
‘Manson-Halford’: Mannson-Halford damage rule
‘Si-Jian’: Si-Jian et al damage rule
‘Leve’: Leve damage rule
Warning
This function is not suited for variable amplitude loading. For variable amplitude loading, use
calc_nonlinear_damage_with_dca()
, as the fluctiations of the nonlinear damage exponent are controlled by the Damage Curve.The generic form of a nonlinear damage rule is:
\[D = \left( \left( \dots \left( \left( \left(\frac{n_1}{N_1}\right)^{e_{1, 2}} + \frac{n_2}{N_2} \right)^{e_{2, 3}} + \frac{n_3}{N_3} \right)^{e_{3, 4}} + \dots + \frac{n_{M-1}}{N_{M-1}} \right)^{e_{M-1, M}} + \dots + \frac{n_M}{N_M} \right)^{e_M}\]where \(n_j\) is the number of cycles in the fatigue histogram at the \(j\)-th cycle, \(N_j\) is the number of cycles to failure at the \(j\)-th cycle, \(e_{j, j+1}\) is the exponent for the \(j\)-th and \(j+1\)-th cycles, \(M\) is the number of load blocks in the fatigue spectrum.
The formula is conveniently rewritten as pseudocode:
pseudocode for the nonlinear damage rule## retrieve N_j using the fatigue histogram and SN curve # retrieve the exponents e_{j, j+1} # calculate the damage D = 0 for j in range(1, M+1): D = (D + n_j / N_j) ^ e_{j, j+1}
- Parameters:
damage_rule (str) – The damage rule to use. Must be one of the following: ‘Pavlou’, ‘Manson-Halford’, ‘Si-Jian’, ‘Leve’.
stress_range (np.ndarray) – The stress range.
count_cycle (np.ndarray) – The number of cycles.
sn_curve (SNCurve) – The SN curve.
kwargs (dict) –
The keyword arguments for the damage rule. The following keyword arguments are allowed:
’base_exponent’: The exponent for the damage rule.
’ultimate_stress’: The ultimate stress.
- Returns:
The cumulated damage.
- Return type:
np.ndarray
- py_fatigue.damage.stress_life.calc_nonlinear_damage_with_dca(damage_rule: str, stress_range: ndarray, count_cycle: ndarray, sn_curve: SNCurve, damage_bands: ndarray = array([0., 0.025, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.]), limit_damage: float | int = 1, logger: Logger | None = None, plot: bool = False, **kwargs) tuple[ndarray, ndarray, Figure | None, Axes | None] #
Calculate the fatigue damage using a nonlinear damage rule based on the Damage Curve Approach (DCA) among the allowed ones:
‘Pavlou’: Pavlou damage rule
‘Theil’: Theil damage rule
The DCA discreties the damage curve in multiple Damage bands \(\Delta D_j\) and calculates the damage for each band, depending on the damage value at the previous cycle. The damage is calculated as:
\[D = \sum_{j=1}^{n_b} \Delta D_j\]where \(n_b\) is the number of damage bands. In each damage band, the damage follows a weighted Palmgren-Miner sum, i.e.:
\[\Delta D_j = \sum_{i=1}^{n_j} w_{i, j} \frac{n_i}{N_i}\]where \(n_j\) is the number of cycles in the fatigue histogram at the \(j\)-th cycle, \(N_j\) is the number of cycles to failure at the \(j\)-th cycle, \(w_{i, j}\) is the weight for the \(i\)-th cycle in the \(j\)-th damage band.
Using the generic nonlinear damage accumulation formula:
\[D(\sigma) = \left(\frac{n}{N(\sigma)}\right)^{e(\sigma)}\]and substituting it inside the weighted Palmgren-Miner sum, the equation of the weights can be extracted as:
\[w_{i, j} = \frac{D_j - D_{j-1}}{ D_{j}^{1/e_{i, i}} - D_{j-1}^{1/e_{i, i}} }\]In the case of Pavlou’s model, the exponents are:
\[e_{j, j} = \left(\frac{\Delta \sigma_j / 2} {\sigma_U}\right)^{exponent}\]While for Theil’s method, the weights can be directly approximated as:
\[w_j = 1 + \frac{\Delta\sigma_j}{N_{f,j}}\]Warning
If you want to use Theil’s method in a production environment, it is recommended to use the
calc_theil_cycles_to_failure()
function, as it adheres to the original SN Cuve-based method.The formula is conveniently rewritten as pseudocode:
pseudocode for the nonlinear damage rule## retrieve n_i, N_i using the fatigue histogram and SN curve # retrieve the exponents e_{j, j+1} # define the damage bands DB # calculate the damage D = 0 for j in range(1, M+1): DB_j = np.digitize(D, DB, right=False) for i in range(1, n_j+1): if damage_rule == 'Pavlou': w_ij = (DB[DB_j] - DB[DB_j - 1]) / ((DB[DB_j] ** (1 / e_i)) - (DB[DB_j - 1] ** (1 / e_i))) elif damage_rule == 'Theil': w_ij = stress_range_i / N_i + 1 D += w_ij * n_i / N_i
- Parameters:
damage_rule (str) – The damage rule to use. Must be one of the following: ‘Pavlou’, ‘Theil’.
stress_range (np.ndarray) – The stress range.
count_cycle (np.ndarray) – The number of cycles.
sn_curve (SNCurve) – The SN curve.
damage_bands (np.ndarray) – Damage bands for the Pavlou damage calculation, by default [0, 0.025, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1]
limit_damage (float, optional) – Limit damage value, by default 1
logger (logging.Logger, optional) – If a logger is defined, attach output to it
plot (bool, by default False) – Whether to plot or not the cumulated damage
kwargs (dict) –
The keyword arguments for the damage rule. The following keyword arguments are allowed:
’base_exponent’: The exponent for the damage rule.
’ultimate_stress’: The ultimate stress.
- Returns:
The cycle-to-cycle damage and the cumulated damage.
- Return type:
tuple[np.ndarray, np.ndarray, mpl.Figure | None, mpl.Axes | None]
- py_fatigue.damage.stress_life.get_nonlinear_damage(damage_rule: str, cycle_count: CycleCount, sn_curve: SNCurve, **kwargs) float #
Calculate the fatigue damage using a nonlinear damage rule.
- Parameters:
damage_rule (str) – The damage rule to use. Must be one of the following: ‘Pavlou’, ‘Manson-Halford’, ‘Si-Jian’, ‘Leve’.
cycle_count (CycleCount) – The cycle count object.
sn_curve (SNCurve) – The SN curve object.
kwargs (dict) –
The keyword arguments for the damage rule. The following keyword arguments are allowed:
’base_exponent’: The exponent for the damage rule.
’ultimate_stress’: The ultimate stress.
- Returns:
The cumulated damage.
- Return type:
- py_fatigue.damage.stress_life.get_nonlinear_damage_with_dca(damage_rule: str, cycle_count: CycleCount, sn_curve: SNCurve, damage_bands: ndarray, limit_damage: float | int = 1, logger: Logger | None = None, plot: bool = False, **kwargs) tuple[ndarray, ndarray, Figure | None, Axes | None] #
Calculate the fatigue damage using a nonlinear damage rule based on the Damage Curve Approach (DCA) among the allowed ones:
‘Pavlou’: Pavlou damage rule
‘Theil’: Theil damage rule
Refer to
calc_nonlinear_damage_with_dca()
for the complete documentation with mathematical details.- Parameters:
damage_rule (str) – The damage rule to use. Must be one of the following: ‘Pavlou’, ‘Theil’.
cycle_count (CycleCount) – The cycle count object.
sn_curve (SNCurve) – The SN curve object.
damage_bands (np.ndarray) – The damage bands.
limit_damage (Union[float, int], optional) – The limit damage, by default 1
logger (logging.Logger, optional) – The logger object, by default None
kwargs (dict) –
The keyword arguments for the damage rule. The following keyword arguments are allowed:
’base_exponent’: The exponent for the damage rule.
’ultimate_stress’: The ultimate stress.
- Returns:
The cycle-to-cycle damage and the cumulated damage.
- Return type:
tuple[np.ndarray, np.ndarray]
- py_fatigue.damage.stress_life.find_sn_curve_intersection(slope: ndarray, intercept: ndarray, endurance: float, weight: float, res_stress: float, n_min: float, n_max: float, tol=1e-06)#
Solve the following nonlinear equation:
\[\left(\frac{a}{N}\right)^{\frac{1}{m}} = w \cdot N + b\]where:
a is the intercept of the S-N curve,
m is the slope of the S-N curve,
w is the weight for the stress range,
b is the residual stress range,
N is the number of cycles to failure,
for N in the range [\(n_{min}\), \(n_{max}\)]. The equation is linked to the S-N curve definition, therefore it can be as complex as the S-N curve itself, i.e. log-linear, log-bilinear, etc.
- Parameters:
intercept (float) – The intercept of the S-N curve.
slope (float) – The slope of the S-N curve.
endurance (float) – The endurance limit.
weight (float) – The weight for the stress range.
res_stress (float) – The residual stress range.
n_min (float, optional) – The minimum number of cycles to failure, by default 1e0.
n_max (float, optional) – The maximum number of cycles to failure, by default 1e10.
tol (float, optional) – The tolerance for the bisection method, by default 1e-6.
- Returns:
The number of cycles to failure.
- Return type:
- Raises:
ValueError – If the bisection method fails to find a solution.
- py_fatigue.damage.stress_life.calc_theil_sn_damage(stress_range, count_cycle, sn_curve: SNCurve, to_failure: bool = False) tuple[tuple[str, Any, Any], ...] #
Calculate the cycles to failure using the Theil’s method for variable amplitude loading. Perform a fatigue life prediction under a sequence of stress range blocks, taking into account the interaction between different stress levels. It uses Theil’s method to determine the effective stress range and accumulated damage, and an S-N curve to predict the number of cycles to failure.
Mathematically, the method can be described as follows. Provided a sequence of stress range blocks \(\Delta\sigma_i\) and the corresponding number of cycles \(n_i\), after initializing all the cumulative variables to zero, the effective stress range is calculated as:
\[\begin{split}N_i & = \text{SN Curve}\left(\Delta\sigma_i \right) \\ w_i & = \frac{\Delta\sigma_i}{N_i} \\ \Delta\sigma_{eff,i} & = \Delta\sigma_{cumsum,i-1} - w_i \cdot n_{cumsum, i-1} \\ n_{cumsum,i} & = n_{cumsum,i-1} + n_i \\ \Delta\sigma_{cumsum,i} & = w_i \cdot n_{cumsum,i} + \Delta\sigma_{eff,i}\end{split}\]where:
\(\Delta\sigma_{eff}\) is the effective stress range,
\(\Delta\sigma_{cumsum}\) is the cumulative stress range,
\(w\) is the damage weight for the current cycle,
\(n_{cumsum}\) is the cumulative number of cycles,
\(n\) is the number of cycles for the current block.
The method is applied to each block in the sequence, and the cumulative number of cycles is updated at the end of each block. The process continues until the number of cycles to failure is determined. If failure does not occur until the end of the sequence, the number of cycles to failure is estimated by “extrapolating” the last block, i.e., by calculating the intersection of the S-N curve with the effective stress range of the last block through the bisection method.
- Parameters:
stress_range (np.ndarray) – A numpy array containing the stress range for each block (MPa).
count_cycle (np.ndarray) – A numpy array containing the number of cycles for each block.
sn_curve (SNCurve) – An object representing the S-N curve of the material. It must have attributes intercept (float) and slope (float).
- Returns:
A tuple containing:
n_to_failure (float): The number of cycles to failure. If failure occurs within a block, the cumulative number of cycles at the end of that block is returned.
history (list): A list of tuples, where each tuple contains:
n_segment (np.ndarray): An array of cycle numbers for the segment.
stress_range_segment (np.ndarray): An array of corresponding stress ranges for the segment.
label (str): A label for the segment, indicating the block number and stress range.
- Return type:
- Raises:
ValueError – If the fatigue life solver fails to find a solution within a block, indicating that failure has occurred within that block.
Notes
The function assumes that the stress range and count cycle arrays have the same length.
The Theil’s method is used to calculate the effective stress range, which takes into account the sequence of stress levels.
The S-N curve is used to relate the stress range to the number of cycles to failure.