Mean stress correction methods

Studies have shown that the mean stress effect plays a critical role in fatigue damage accumulation. The mean value of the fatigue stress response varies under different mean stress levels. In general, fatigue damage increases with the superimposition of static stress to the applied cyclic stress. The mean stress correction is to transform the stress cycle to an equivalent stress cycle with zero mean stress.

For a stress range \([\sigma_{lower}, \sigma_{upper}]\), the mean stress \(\sigma_{mean}\) is calculated with

\[\sigma_{m} = \frac{\sigma_{lower} + \sigma_{upper}}{2}\]

and the alternating stress, also refered to as stress amplitude, \(\sigma_a\) is calculated with

\[\sigma_{a} = \frac{\sigma_{upper} - \sigma_{lower}}{2}\]

Reference:

[1]:
# Import auxiliary libraries for demonstration

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

plt.rcParams[ "figure.figsize" ] = [ 5, 4 ]

plt.rcParams[ "figure.dpi" ] = 80
plt.rcParams[ "font.family" ] = "Times New Roman"
plt.rcParams[ "font.size" ] = '14'

Goodman correction method

Function goodmanCorrection implements the Goodman correction method.

The Goodman diagram, originally proposed in 1890, is a graphical representation of this effect. The Goodman correction could be expressed as

\[\frac{\sigma_a}{\sigma_{FL}} + \frac{\sigma_{m}}{\sigma_{u}} = 1\]

where \(\sigma_{u}\) is the ultimate strength; \(\sigma_{mean}\) is the mean stress of the stress range; \(\sigma_a\) is the alternating stress; \(\sigma_{FL}\) is the fatigue limit.

If a safty factor \(n\) is considered, the equation becomes

\[\frac{\sigma_a}{\sigma_{FL}} + \frac{\sigma_{m}}{\sigma_{u}} = \frac{1}{n}\]

Function help

[2]:
from ffpack.lcc import goodmanCorrection

help( goodmanCorrection )
Help on function goodmanCorrection in module ffpack.lcc.meanStressCorrection:

goodmanCorrection(stressRange, ultimateStrength, n=1.0)
    The Goodman correction in this implementation is applicable to cases with stress
    ratio no less than -1.

    Parameters
    ----------
    stressRange: 1d array
        Stress range, e.g., [ lowerStress, upperStress ].
    ultimateStrength: scalar
        Ultimate tensile strength.
    n: scalar, optional
        Safety factor, default to 1.0.

    Returns
    -------
    rst: scalar
        Fatigue limit.

    Raises
    ------
    ValueError
        If the stressRange dimension is not 1, or stressRange length is not 2.
        If stressRange[ 1 ] <= 0 or stressRange[ 0 ] >= stressRange[ 1 ].
        If ultimateStrength is not a scalar or ultimateStrength <= 0.
        If ultimateStrength is smaller than the mean stress.
        If n < 1.0.

    Examples
    --------
    >>> from ffpack.lcc import goodmanCorrection
    >>> stressRange = [ 1.0, 2.0 ]
    >>> ultimateStrength = 4.0
    >>> rst = goodmanCorrection( stressRange, ultimateStrength )

Example with default values

[3]:
stressRangeData = [ 1.0, 2.0 ]
ultimateStrength = 4.0

goodmanResult = goodmanCorrection( stressRangeData, ultimateStrength )
[4]:
print( goodmanResult )
0.8
[5]:
fig, ax = plt.subplots()

x = [0, ultimateStrength]
y = [goodmanResult, 0]
ax.plot( x, y, "-" )
ax.tick_params( axis='x', direction="in", length=5 )
ax.tick_params( axis='y', direction="in", length=5 )
plt.xlim( left=0, right=5 )
plt.ylim( bottom=0, top=1 )

sigmaMean = np.mean(stressRangeData)
sigmaAlt = (stressRangeData[1] - stressRangeData[0]) / 2
point = ( sigmaMean, sigmaAlt )
ax.plot( point[0], point[1], "o" )
ax.axvline( point[0], ymin=0, ymax=point[1]/1, linestyle='--', color='gray') # plot vertical line
ax.axhline( point[1], xmin=0, xmax=point[0]/5, linestyle='--', color='gray') # plot horizontal line

ax.set_xlabel( "Mean stress" )
ax.set_ylabel( "Alternating stress" )
ax.set_title( "Goodman correction" )

plt.tight_layout()
plt.show()
../_images/moduleCookbook_lccMeanStressCorrection_10_0.png

Soderberg correction method

Function soderbergCorrection implements the Goodman correction method.

The Soderberg diagram, originally proposed in 1890, is a graphical representation of this effect. The Goodman correction could be expressed as

\[\frac{\sigma_a}{\sigma_{FL}} + \frac{\sigma_{m}}{\sigma_{y}} = 1\]

where \(\sigma_{y}\) is the yield strength; \(\sigma_{mean}\) is the mean stress of the stress range; \(\sigma_a\) is the alternating stress; \(\sigma_{FL}\) is the fatigue limit.

If a safty factor \(n\) is considered, the equation becomes

\[\frac{\sigma_a}{\sigma_{FL}} + \frac{\sigma_{m}}{\sigma_{y}} = \frac{1}{n}\]

Function help

[6]:
from ffpack.lcc import soderbergCorrection

help( soderbergCorrection )
Help on function soderbergCorrection in module ffpack.lcc.meanStressCorrection:

soderbergCorrection(stressRange, yieldStrength, n=1.0)
    The Soderberg correction in this implementation is applicable to cases with stress
    ratio no less than -1.

    Parameters
    ----------
    stressRange: 1d array
        Stress range, e.g., [ lowerStress, upperStress ].
    yieldStrength: scalar
        Yield strength.
    n: scalar, optional
        Safety factor, default to 1.0.

    Returns
    -------
    rst: scalar
        Fatigue limit.

    Raises
    ------
    ValueError
        If the stressRange dimension is not 1, or stressRange length is not 2.
        If stressRange[ 1 ] <= 0 or stressRange[ 0 ] >= stressRange[ 1 ].
        If yieldStrength is not a scalar or yieldStrength <= 0.
        If yieldStrength is smaller than the mean stress.
        If safety factor n < 1.0.

    Examples
    --------
    >>> from ffpack.lcc import soderbergCorrection
    >>> stressRange = [ 1.0, 2.0 ]
    >>> yieldStrength = 3.0
    >>> rst = soderbergCorrection( stressRange, yieldStrength )

Example with default values

[7]:
stressRangeData = [ 1.0, 2.0 ]
yieldStrength = 3.0

soderbergResult = soderbergCorrection( stressRangeData, yieldStrength )
[8]:
print( soderbergResult )
1.0
[9]:
fig, ax = plt.subplots()

x = [0, yieldStrength]
y = [soderbergResult, 0]
ax.plot( x, y, "-" )
ax.tick_params( axis='x', direction="in", length=5 )
ax.tick_params( axis='y', direction="in", length=5 )
plt.xlim( left=0, right=4 )
plt.ylim( bottom=0, top=1.5 )

sigmaMean = np.mean(stressRangeData)
sigmaAlt = (stressRangeData[1] - stressRangeData[0]) / 2
point = ( sigmaMean, sigmaAlt )
ax.plot( point[0], point[1], "o" )
ax.axvline( point[0], ymin=0, ymax=point[1]/1.5, linestyle='--', color='gray') # plot vertical line
ax.axhline( point[1], xmin=0, xmax=point[0]/4, linestyle='--', color='gray') # plot horizontal line

ax.set_xlabel( "Mean stress" )
ax.set_ylabel( "Alternating stress" )
ax.set_title( "Soderberg correction" )

plt.tight_layout()
plt.show()
../_images/moduleCookbook_lccMeanStressCorrection_18_0.png

Gerber correction method

Function gerberCorrection implements the Goodman correction method.

The Goodman diagram, originally proposed in 1890, is a graphical representation of this effect. The Goodman correction could be expressed as

\[\frac{\sigma_a}{\sigma_{FL}} + \left( \frac{\sigma_{m}}{\sigma_{u}} \right)^{2} = 1\]

where \(\sigma_{u}\) is the ultimate strength; \(\sigma_{mean}\) is the mean stress of the stress range; \(\sigma_a\) is the alternating stress; \(\sigma_{FL}\) is the fatigue limit.

If a safty factor \(n\) is considered, the equation becomes

\[\frac{n\sigma_a}{\sigma_{FL}} + \left( \frac{n\sigma_{m}}{\sigma_{u}} \right)^{2} = 1\]

Function help

[10]:
from ffpack.lcc import gerberCorrection

help( gerberCorrection )
Help on function gerberCorrection in module ffpack.lcc.meanStressCorrection:

gerberCorrection(stressRange, ultimateStrength, n=1.0)
    The Gerber correction in this implementation is applicable to cases with stress
    ratio no less than -1.

    Parameters
    ----------
    stressRange: 1d array
        Stress range, e.g., [ lowerStress, upperStress ].
    ultimateStrength: scalar
        Ultimate strength.
    n: scalar, optional
        Safety factor, default to 1.0.

    Returns
    -------
    rst: scalar
        Fatigue limit.

    Raises
    ------
    ValueError
        If the stressRange dimension is not 1, or stressRange length is not 2.
        If stressRange[ 1 ] <= 0 or stressRange[ 0 ] >= stressRange[ 1 ].
        If ultimateStrength is not a scalar or ultimateStrength <= 0.
        If ultimateStrength is smaller than the mean stress.
        If safety factor n < 1.0.

    Examples
    --------
    >>> from ffpack.lcc import gerberCorrection
    >>> stressRange = [ 1.0, 2.0 ]
    >>> ultimateStrength = 3.0
    >>> rst = gerberCorrection( stressRange, ultimateStrength )

Example with default values

[11]:
stressRangeData = [ 1.0, 2.0 ]
ultimateStrength = 4.0

gerberResult = gerberCorrection( stressRangeData, ultimateStrength )
[12]:
print( gerberResult )
0.5818181818181818
[13]:
fig, ax = plt.subplots()

x = np.arange(0, ultimateStrength + 0.25, 0.25)

sigmaMean = np.mean(stressRangeData)
sigmaAlt = (stressRangeData[1] - stressRangeData[0]) / 2
def calculateSigmaAlt(mean):
    rst = 1 - (mean / ultimateStrength) ** 2
    return rst * gerberResult

y = [calculateSigmaAlt(mean) for mean in x]
ax.plot( x, y, "-" )

ax.tick_params( axis='x', direction="in", length=5 )
ax.tick_params( axis='y', direction="in", length=5 )
plt.xlim( left=0, right=5 )
plt.ylim( bottom=0, top=0.8 )

point = ( sigmaMean, sigmaAlt )
ax.plot( point[0], point[1], "o" )
ax.axvline( point[0], ymin=0, ymax=point[1]/0.8, linestyle='--', color='gray') # plot vertical line
ax.axhline( point[1], xmin=0, xmax=point[0]/5, linestyle='--', color='gray') # plot horizontal line

ax.set_xlabel( "Mean stress" )
ax.set_ylabel( "Alternating stress" )
ax.set_title( "Gerber correction" )

plt.tight_layout()
plt.show()
../_images/moduleCookbook_lccMeanStressCorrection_26_0.png

Comparison of the correction methods

[14]:
sigmaFL = 0.8            # assumed fatigue limit
yieldStrength = 3.0      # assumed yield strength
ultimateStrength = 4.0   # assumed ultimate strength
[15]:
fig, ax = plt.subplots()

xYield = np.arange(0, yieldStrength + 0.25, 0.25)
xUltimate = np.arange(0, ultimateStrength + 0.25, 0.25)

def calcGoodman(mean):
    rst = 1 - mean / ultimateStrength
    return rst * sigmaFL

def calcSoderberg(mean):
    rst = 1 - mean / yieldStrength
    return rst * sigmaFL

def calcGerber(mean):
    rst = 1 - (mean / ultimateStrength) ** 2
    return rst * sigmaFL

yGoodman = [calcGoodman(mean) for mean in xUltimate]
ySoderberg = [calcSoderberg(mean) for mean in xYield]
yGerber = [calcGerber(mean) for mean in xUltimate]
ax.plot( xUltimate, yGoodman, "-", label='Goodman' )
ax.plot( xYield, ySoderberg, "-", label='Soderberg' )
ax.plot( xUltimate, yGerber, "-", label='Gerber' )
plt.legend()

ax.tick_params( axis='x', direction="in", length=5 )
ax.tick_params( axis='y', direction="in", length=5 )
plt.xlim( left=0, right=4.5 )
plt.ylim( bottom=0, top=1 )

ax.set_xlabel( "Mean stress" )
ax.set_ylabel( "Alternating stress" )
ax.set_title( "Mean stress correction" )

plt.tight_layout()
plt.show()
../_images/moduleCookbook_lccMeanStressCorrection_29_0.png