Code documentation#
Spectral data#
Frequency-domain fatigue life#
Narrowband#
- class FLife.freq_domain.Narrowband(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Miles [1] / Bendat and Piersol [2].
References
- [1] John W. Miles. On structural fatigue under random loading. Journal
of the Aeronautical Sciences, 21(11):753{762, 1954.
- [2] Julius S. Bendat and Allen G. Piersol. Measurement and Analysis of Random Data.
Wiley, 1966.
- [3] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD = es.get_psd(freq, 20, 60, variance = 5) # one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> nb = FLife.Narrowband(sd) >>> print(f'Fatigue life: {nb.get_life(C,k):.3e} s.')
Define stress vector and depict stress peak PDF
>>> s = np.arange(0,np.max(x),.01) >>> plt.plot(s,nb.get_PDF(s)) >>> plt.xlabel('Stress [MPa]') >>> plt.ylabel('PDF')
- __init__(spectral_data)[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
- get_PDF(s)[source]#
Returns cycle PDF(Probability Density Function) as a function of stress s.
- Parameters:
s – numpy.ndarray Stress vector.
- Returns:
function pdf(s)
- damage_intesity_NB(m0, nu, C, k)[source]#
Calculates narrowband damage intensity with parameters m0, nu, C, k, as defined in [2].
- Parameters:
m0 – [int,float] Zeroth spectral moment [MPa**2].
nu – [int,float] Frequency of positive slope zero crossing [Hz].
C – [int,float] Fatigue strength coefficient [MPa**k].
k – [int,float] Fatigue strength exponent [/].
- Returns:
Estimated damage intensity.
- Return type:
float
- get_life(C, k, integrate_pdf=False)[source]#
Calculate fatigue life with parameters C, k, as defined in [2].
- Parameters:
C – [int,float] S-N curve intercept [MPa**k].
k – [int,float] S-N curve inverse slope [/].
integrate_pdf – boolean If true the the fatigue life is estimated by integrating the PDF, Default is false which means that the theoretical equation is used
- Returns:
Estimated fatigue life in seconds.
- Return type:
float
Wirsching-Light#
- class FLife.freq_domain.WirschingLight(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Wirsching and Light [1].
References
- [1] Paul H. Wirsching and Mark C. Light. Fatigue under wide band random
stresses. Journal of the Structural Division, 106(7):1593-1607, 1980
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> wl = FLife.WirschingLight(sd) >>> print(f'Fatigue life: {wl.get_life(C,k):.3e} s.')
Ortiz-Chen#
- class FLife.freq_domain.OrtizChen(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Ortiz and Chen [1].
References
- [1] K. Ortiz and N.K. Chen. Fatigue damage prediction for stationary wideband processes.
Fifth international conference on applications of statistics and probability in soil and structural engineering, 1987
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> oc = FLife.OrtizChen(sd) >>> print(f'Fatigue life: {oc.get_life(C,k):.3e} s.')
Alpha075#
- class FLife.freq_domain.Alpha075(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Benasciutti and Tovo [1].
References
- [1] Denis Benasciutti and Robert Tovo. Rainflow cycle distribution and
fatigue damage in Gaussian random loadings. Technical report, Department of Engineering, University of Ferrara, 2004
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> alpha075 = FLife.Alpha075(sd) >>> print(f'Fatigue life: {alpha075.get_life(C,k):.3e} s.')
Tovo-Benasciutti#
- class FLife.freq_domain.TovoBenasciutti(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Tovo and Benasciutti[1, 2, 3].
References
- [1] Roberto Tovo. Cycle distribution and fatigue damage under broadband
random loading. International Journal of Fatigue, 24(11):1137{ 1147, 2002
- [2] Denis Benasciutti and Roberto Tovo. Spectral methods for lifetime
prediction under wide-band stationary random processes. International Journal of Fatigue, 27(8):867{877, 2005
- [3] Denis Benasciutti and Roberto Tovo. Comparison of spectral methods for fatigue
analysis of broad-band Gaussian random processes. Probabilistic Engineering Mechanics, 21(4), 287-299, 2006
- [4] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> tb = FLife.TovoBenasciutti(sd) >>> print(f'Fatigue life, method 1: {tb.get_life(C,k, method="method 1"):.3e} s.') >>> print(f'Fatigue life, method 2: {tb.get_life(C,k, method="method 2"):.3e} s.')
Define stress vector and depict stress peak PDF
>>> s = np.arange(0,np.max(x),.01) >>> plt.plot(s,tb.get_PDF(s, method='method 1'), lw=5, alpha=.5, label = 'method 1') >>> plt.plot(s,tb.get_PDF(s, method='method 2'), '--', label = 'method 2') >>> plt.xlabel('Stress [MPa]') >>> plt.ylabel('PDF') >>> plt.legend()
- __init__(spectral_data)[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
- get_PDF(s, method='method 2')[source]#
Returns cycle PDF(Probability Density Function) as a function of stress s.
- Parameters:
s – numpy.ndarray Stress vector.
method –
string
’method 1’: weighting parameter b is defined by Tovo[1].
’method 2’: weighting parameter b is defined by Tovo and Benasciutti [2].
’method 3’: weighting parameter b is defined by Tovo and Benasciutti [3].
- Returns:
function pdf(s)
- get_life(C, k, method='method 2', integrate_pdf=False)[source]#
Calculate fatigue life with parameters C, k, as defined in [4].
- Parameters:
C – [int,float] S-N curve intercept [MPa**k].
k – [int,float] S-N curve inverse slope [/].
method –
string
’method 1’: weighting parameter b is defined by Tovo[1].
’method 2’: weighting parameter b is defined by Tovo and Benasciutti [2].
’method 3’: weighting parameter b is defined by Tovo and Benasciutti [3].
integrate_pdf – boolean If true the the fatigue life is estimated by integrating the PDF, Default is false which means that the theoretical equation is used
- Returns:
Estimated fatigue life in seconds.
- Return type:
float
Dirlik#
- class FLife.freq_domain.Dirlik(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Dirlik [1].
References
- [1] Turan Dirlik. Application of computers in fatigue analysis. PhD thesis,
University of Warwick, 1985
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> dirlik = FLife.Dirlik(sd) # Dirlik's fatigue-life estimator >>> print(f'Dirlik: {dirlik.get_life(C,k):.3e} s.')
Define stress vector and depict peak stress PDF
>>> s = np.arange(0,np.max(x),.01) >>> plt.plot(s,dirlik.get_PDF(s)) >>> plt.xlabel('Stress [MPa]') >>> plt.ylabel('PDF')
- __init__(spectral_data)[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
- get_PDF(s)[source]#
Returns cycle PDF(Probability Density Function) as a function of stress s.
- Parameters:
s – numpy.ndarray Stress vector
- Returns:
function pdf(s)
- get_life(C, k, integrate_pdf=False)[source]#
Calculate fatigue life with parameters C, k, as defined in [2].
- Parameters:
C – [int,float] S-N curve intercept [MPa**k].
k – [int,float] S-N curve inverse slope [/].
integrate_pdf – boolean If true the the fatigue life is estimated by integrating the PDF. Default is false which means that the theoretical equation is used.
- Returns:
Estimated fatigue life in seconds.
- Return type:
float
Zhao-Baker#
- class FLife.freq_domain.ZhaoBaker(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Zhao and Baker[1].
References
- [1] Wangwen Zhao and Michael J. Baker. On the probability density function
of rainflow stress range for stationary Gaussian processes. International Journal of Fatigue, 14(2):121-135, 1992
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> tb = FLife.TovoBenasciutti(sd) >>> zb = FLife.ZhaoBaker(sd) >>> print(f'Fatigue life, method 1: {zb.get_life(C,k, method="method 1"):.3e} s.') >>> print(f'Fatigue life, method 2: {zb.get_life(C,k, method="method 2"):.3e} s.')
Define stress vector and depict stress peak PDF
>>> s = np.arange(0,np.max(x),.01) >>> plt.plot(s,zb.get_PDF(s, method='method 1'), lw=5, alpha=.5, label = 'method 1') >>> plt.plot(s,zb.get_PDF(s, method='method 1'), '--', label = 'method 2') >>> plt.xlabel('Stress [MPa]') >>> plt.ylabel('PDF') >>> plt.legend()
- __init__(spectral_data)[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
- get_PDF(s, method='method 1')[source]#
Returns cycle PDF(Probability Density Function) as a function of stress s.
- Parameters:
s – numpy.ndarray Stress vector.
method –
string
’method 1’ is tuned in simulations with material parameters in the range of 2 <= k <= 6, where k is S-N curve coefficient.
’method 2’ is derived for S-N curve coefficient k = 3.
- Returns:
function pdf(s)
- get_life(C, k, method='method 1', integrate_pdf=False)[source]#
Calculate fatigue life with parameters C and k, as defined in [2].
- Parameters:
C – [int,float] S-N curve intercept [MPa**k].
k – [int,float] S-N curve inverse slope [/].
method –
string
’method 1’ is tuned in simulations with material parameters in the range of 2 <= k <= 6, where k is S-N curve coefficient.
’method 2’ is derived for S-N curve coefficient k = 3.
integrate_pdf – boolean If true the the fatigue life is estimated by integrating the PDF, Default is false which means that the theoretical equation is used
- Returns:
Estimated fatigue life in seconds.
- Return type:
float
Park#
- class FLife.freq_domain.Park(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Park et al.[1].
References
- [1] Jun-Bum Park, Joonmo Choung and Kyung-Su Kim. A new fatigue prediction model for marine
structures subject to wide band stress process. Ocean Engineering, 76: 144-151, 2014
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> park = FLife.Park(sd) >>> print(f'Fatigue life: {park.get_life(C,k):.3e} s.')
Define stress vector and depict stress peak PDF
>>> s = np.arange(0,np.max(x),.01) >>> plt.plot(s,park.get_PDF(s)) >>> plt.xlabel('Stress [MPa]') >>> plt.ylabel('PDF')
- __init__(spectral_data)[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
Jun-Park#
- class FLife.freq_domain.JunPark(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Jun and Park[1].
References
- [1] Seock-Hee Jun and Jun-Bum Park. Development of a novel fatigue damage model for
Gaussian wide band stress responses using numerical approximation methods. International Journal of Naval Architecture and Ocean Engineering, 12: 755-767, 2020
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> jp = FLife.Jun(sd) >>> print(f'Fatigue life: {jp.get_life(C,k):.3e} s.')
Define stress vector and depict stress peak PDF
>>> s = np.arange(0,np.max(x),.01) >>> plt.plot(s,jp.get_PDF(s)) >>> plt.xlabel('Stress [MPa]') >>> plt.ylabel('PDF')
- __init__(spectral_data)[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
Jiao-Moan#
- class FLife.freq_domain.JiaoMoan(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Class for fatigue life estimation using frequency domain method by Jiao and Moan [1].
References
- [1] Guoyang Jiao and Torgeir Moan. Probabilistic analysis of fatigue due to Gaussian load processes.
Probabilistic Engineering Mechanics, 5(2):76-83, 1990
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> jm = FLife.JiaoMoan(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {jm.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in Jiao-Moan method
>>> lower_band_index, upper_band_index= jm.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,300) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 2).
- get_life(C, k, approximation=False)[source]#
Calculate fatigue life with parameters C, k, as defined in [1, 2].
- Parameters:
C – [int,float] S-N curve intercept [MPa**k].
k – [int,float] S-N curve inverse slope [/].
approximation – Boolean IF true, approximated PDF of large peaks is used for bimodal random process.
- Returns:
Estimated fatigue life in seconds.
- Return type:
float
Sakai-Okamura#
- class FLife.freq_domain.SakaiOkamura(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Class for fatigue life estimation using frequency domain method by Sakai and Okamura[1].
References
- [1] Shinsuke Sakai, Hiroyuki Okamura. On the distribution of rainflow range for Gaussian
random processes with bimodal PSD. JSME International Journal, Series A: Mechanics and Material Engineering, 38(4):440-445, 1995
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> so = FLife.SakaiOkamura(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {so.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in Sakai-Okamura method
>>> lower_band_index, upper_band_index= so.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,300) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 2).
Fu-Cebon#
- class FLife.freq_domain.FuCebon(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Class for fatigue life estimation using frequency domain method by Fu and Cebon [1].
References
- [1] Tsengti Fu, David Cebon. Predicting fatigue lives for bi-modal stress spectral densities.
International Journal of Fatigue, 22(1):11-21, 2000
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> fc = FLife.FuCebon(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {fc.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in Fu-Cebon method
>>> lower_band_index, upper_band_index= fc.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,300) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 2).
Modified Fu-Cebon#
- class FLife.freq_domain.ModifiedFuCebon(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Class for fatigue life estimation using frequency domain method by Benasciutti and Tovo[1].
References
- [1] Denis Benasciutti and Roberto Tovo. Comparison of spectral methods for fatigue damage
assessment in bimodal random processes. 9th International Conference on Structural Safety & Reliability (ICOSSAR), 230:3207-3214, 2005
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> mfc = FLife.ModifiedFuCebon(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {mfc.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in modified Fu-Cebon method
>>> lower_band_index, upper_band_index= mfc.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,300) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 2).
Low’s bimodal#
- class FLife.freq_domain.Low(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Class for fatigue life estimation using frequency domain method by Low[1].
Notes
Numerical implementation supports only integer values of S-N curve parameter k (inverse slope). Due to approximation of large stress cycles through McLaurin series, sufficient engineering precision is up to k=6 [1].
References
- [1] Y.M.Low. A method for accurate estimation of the fatigue damage
induced by bimodal processes. Probabilistic Engineering Mechanics, 25(1):75-85, 2010
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> low = FLife.Low(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {low.get_life(C,int(k)):.3e} s.')
Plot segmentated PSD, used in Low’s method
>>> lower_band_index, upper_band_index= low.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,300) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 2).
Low 2014#
- class FLife.freq_domain.Low2014(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Class for fatigue life estimation using frequency domain method by Low[1].
References
- [1] Ying Min Low. A simple surrogate model for the rainflow fatigue damage arising
from processes with bimodal spectra. Marine Structures, 38:72-88, 2014
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> low2014 = FLife.LowBimodal2014(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {low2014.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in LowBimodal2014 method
>>> lower_band_index, upper_band_index= low2014.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,300) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 2).
- get_life(C, k)[source]#
Calculate fatigue life with parameters C, k, as defined in [1, 2].
- Parameters:
C – [int,float] S-N curve intercept [MPa**k].
k – [int,float] S-N curve inverse slope [/].
approximation – Boolean IF true, approximated PDF of large peaks is used for bimodal random process.
- Returns:
Estimated fatigue life in seconds.
- Return type:
float
Lotsberg#
- class FLife.freq_domain.Lotsberg(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Class for fatigue life estimation using frequency domain method by Lotsberg[1].
References
- [1] Inge Lotsberg. Background for Revision of DNV-RP-C203 Fatigue Analysis of
Offshore Steel Structure. 24th International Conference on Offshore Mechanics and Arctic Engineering, Halkidiki, Greece, 2005. ASME, Paper No. OMAE2005–67549.
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> lb = FLife.Lotsberg(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {lb.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in Lotsberg method
>>> lower_band_index, upper_band_index= lb.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,300) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 2).
Huang-Moan#
- class FLife.freq_domain.HuangMoan(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Class for fatigue life estimation using frequency domain method by Huang and Moan[1].
References
- [1] Wenbo Huang and Torgeir Moan. Fatigue Under Combined High and Low Frequency Loads.
25th International Conference on Offshore Mechanics and Arctic Engineering, Hamburg, Germany, 2006. ASME, Paper No. OMAE2006–92247.
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> hm = FLife.HuangMoan(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {hm.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in HuangMoan method
>>> lower_band_index, upper_band_index= hm.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,300) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 2))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 2).
Gao-Moan#
- class FLife.freq_domain.GaoMoan(spectral_data, PSD_splitting=('equalAreaBands', 3))[source]#
Class for fatigue life estimation using frequency domain method by Gao and Moan [1].
References
- [1] Zhen Gao and Torgeir Moan. Frequency-domain fatigue analysis of
wide-band stationary Gaussian processes using a trimodal spectral formulation. International Journal of Fatigue, 30(10-11): 1944-1955, 2008
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_middle = es.get_psd(freq, 100, 120, variance = 1) # middle mode of random process >>> PSD_higher = es.get_psd(freq, 300, 350, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_middle + PSDb_higher # trimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> gm = FLife.GaoMoan(sd, PSD_splitting=('userDefinedBands', [80,150,400])) # fatigue-life estimator >>> print(f'Fatigue life: {gm.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in Gao-Moan method
>>> lower_band_index, middle_band_index, upper_band_index= gm.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> # lower band >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][middle_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> # middle band >>> plt.fill_between(sd.psd[lower_band_index:middle_band_index,0], sd.psd[lower_band_index:middle_band_index,1], 'o', label='middle band', alpha=.5, color ='orange') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> # upper band >>> plt.fill_between(sd.psd[middle_band_index:upper_band_index,0], sd.psd[middle_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='green') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,450) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 3))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 3).
Single moment#
- class FLife.freq_domain.SingleMoment(spectral_data)[source]#
Class for fatigue life estimation using frequency domain method by Lutes and Larsen[1, 2].
References
- [1] L.D. Lutes, C.E. Larsen. Improved spectral method for variable amplitude fatigue prediction,
Journal of Structural Engineering ASCE, 116(4):1149-1164, 1990
- [2] C.E. Larsen, L.D. Lutes. Predicting the Fatigue Life of Offshore Structures by the Single-Moment Spectral Method,
Probabilistic Engineering Mechanics, 6(2):96-108, 1991
- [3] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> sm = FLife.SingleMoment(sd) >>> print(f'Fatigue life: {sm.get_life(C,k):.3e} s.')
- __init__(spectral_data)[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
- damage_intesity_SM(m_2k, C, k)[source]#
Calculates damage intensity with parameters m_2k, nu, C, k, as defined in [1,2].
- Parameters:
m_2k – [int,float] 2/k-th spectral moment [MPa**2].
C – [int,float] Fatigue strength coefficient [MPa**k].
k – [int,float] Fatigue strength exponent [/].
- Returns:
Estimated damage intensity.
- Return type:
float
Bands method#
- class FLife.freq_domain.BandsMethod(spectral_data, PSD_splitting=('equalAreaBands', 1))[source]#
Class for fatigue life estimation using frequency domain method by Braccesi et al. [1].
References
- [1] Claudio Braccesi, Filippo Cianetti and Lorenzo Tomassini. Random fatigue. A new
frequency domain criterion for the damage evaluation of mechanical components. International Journal of Fatigue, 70:417-427, 2015
- [2] Aleš Zorman and Janko Slavič and Miha Boltežar.
Vibration fatigue by spectral methods—A review with open-source support, Mechanical Systems and Signal Processing, 2023, https://doi.org/10.1016/j.ymssp.2023.110149
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> bm = FLife.BandsMethod(sd, PSD_splitting=('userDefinedBands', [80,150])) >>> print(f'Fatigue life: {bm.get_life(C,k):.3e} s.')
Plot segmentated PSD, used in Bands method
>>> lower_band_index, upper_band_index= bm.band_stop_indexes >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.vlines(sd.psd[:,0][lower_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[:lower_band_index,0], sd.psd[:lower_band_index,1], 'o', label='lower band', alpha=.2, color='blue') >>> plt.vlines(sd.psd[:,0][upper_band_index], 0, np.max(sd.psd[:,1]), 'k', linestyles='dashed', alpha=.5) >>> plt.fill_between(sd.psd[lower_band_index:upper_band_index,0], sd.psd[lower_band_index:upper_band_index,1], 'o', label='upper band', alpha=.5, color ='orange') >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD') >>> plt.xlim(0,200) >>> plt.legend()
- __init__(spectral_data, PSD_splitting=('equalAreaBands', 1))[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of class SpectralData
PSD_splitting –
tuple PSD_splitting[0] is PSD spliting method, PSD_splitting[1] is method argument. Splitting methods:
’userDefinedBands’, PSD_splitting[1] must be of type list or tupple, with N elements specifying upper band frequencies of N random processes.
’equalAreaBands’, PSD_splitting[1] must be of type int, specifying N random processes.
Defaults to (‘equalAreaBands’, 1).
Time-domain fatigue life#
- class FLife.time_domain.Rainflow(spectral_data, **kwargs)[source]#
Class for fatigue life estimation using rainflow counting method [1, 2].
References
- [1] C. Amzallag et. al. Standardization of the rainflow counting method for
fatigue analysis. International Journal of Fatigue, 16 (1994) 287-293
[2] ASTM E1049-85
- [3] Janko Slavič, Matjaž Mršnik, Martin Česnik, Jaka Javh, Miha Boltežar.
Vibration Fatigue by Spectral Methods, From Structural Dynamics to Fatigue Damage – Theory and Experiments, ISBN: 9780128221907, Elsevier, 1st September 2020
Example
Import modules, define time- and frequency-domain data
>>> import FLife >>> import pyExSi as es >>> import numpy as np >>> from matplotlib import pyplot as plt >>> # time-domain data >>> N = 2 ** 16 # number of data points of time signal >>> fs = 2048 # sampling frequency [Hz] >>> t = np.arange(0, N) / fs # time vector >>> # frequency-domain data >>> M = N // 2 + 1 # number of data points of frequency vector >>> freq = np.arange(0, M, 1) * fs / N # frequency vector >>> PSD_lower = es.get_psd(freq, 20, 60, variance = 5) # lower mode of random process >>> PSD_higher = es.get_psd(freq, 100, 120, variance = 2) # higher mode of random process >>> PSD = PSD_lower + PSD_higher # bimodal one-sided flat-shaped PSD
Get Gaussian stationary signal, instantiate SpectralData object and plot PSD
>>> rg = np.random.default_rng(123) # random generator seed >>> x = es.random_gaussian(N, PSD, fs, rg) # Gaussian stationary signal >>> sd = FLife.SpectralData(input=x, dt=1/fs) # SpectralData instance >>> plt.plot(sd.psd[:,0], sd.psd[:,1]) >>> plt.xlabel('Frequency [Hz]') >>> plt.ylabel('PSD')
Define S-N curve parameters and get fatigue-life estimatate
>>> C = 1.8e+22 # S-N curve intercept [MPa**k] >>> k = 7.3 # S-N curve inverse slope [/] >>> rf = FLife.Rainflow(sd) >>> print(f'Fatigue life: {rf.get_life(C,k):.3e} s.')
- __init__(spectral_data, **kwargs)[source]#
Get needed values from reference object.
- Parameters:
spectral_data – Instance of object SpectralData
rg – Instance of numpy.random._generator.Generator Parameter rg cotrols phase of generated time history, if not already exist in spectral_data.
- get_life(C, k, algorithm='four-point', Su=False, range=False, nr_load_classes=512, **kwargs)[source]#
Calculate fatigue life with parameters C, k, as defined in [3]
- Parameters:
C – [int,float] S-N curve intercept [MPa**k].
k – [int,float] S-N curve inverse slope [/].
algorithm – str Cycle counting method. Options are ‘three-point’ and ‘four-point’. Defaults to ‘four-point’.
Su – [int,float] Ultimate tensile strength [MPa]. If specified, Goodman equivalent stress is used for fatigue life estimation. Defaults to False.
range – bool If True, ranges instead of amplitudes are used for fatigue life estimation. Defaults to False.
nr_load_classes – int The number of intervals to divide the min-max range of the dataseries into. Used with algorithm =’four-point’. Defaults to 512.
- Returns:
Estimated fatigue life in seconds.
- Return type:
float
Multiaxial fatigue life#
- class FLife.multiaxial.EquivalentStress(input=None, window='hann', nperseg=1280, noverlap=None, psd_trim_length=None, T=None, fs=None, rg=None, **kwargs)[source]#
EquivalentStress object contains multiaxial data, based on input power spectral density (PSD). It is used to convert multiaxial stress states into equivalent uniaxiail stress states, that can be used in fatigue life estimation.
EquivalentStress inherits from SpectralData class, so all methods from SpectralData are available for fatigue analysis. If instance of SpectralData is passed as input, the multiaxial PSD is inherited, otherwise it is created from input PSD.
The following multiaxial criteria are available for equivalent stress calculation: - max_normal: Maximum normal stress on critical plane - max_shear: Maximum shear stress on critical plane - max_normal_and_shear: Maximum normal and shear stress on critical plane - EVMS: Equivalent von Misses stress - cs: Carpinteri-Spagnoli criterion - multiaxial_rainflow: Frequency-based multiaxial rainflow criterion - thermoelastic: Thermoelasticity-based criterion - EVMS_out_of_phase: EVMS adaptation for out-of-phase components - Nieslony: Nieslony criterion, combining von Mises and hydrostatic stresses - Lemaitre: Equivalent Lemaitre stress - liwi: LiWI approach - coin_liwi: COIN-LiWI method
- __init__(input=None, window='hann', nperseg=1280, noverlap=None, psd_trim_length=None, T=None, fs=None, rg=None, **kwargs)[source]#
Class constructor for EquivalentStress object.
- Parameters:
input – dictionary or instance of SpectralData class. Input data for EquivalentStress object. If dictionary, it should contain keys: PSD and f or keys ‘amplitude_spectrum’ and ‘f’. PSD should be an array with shape (f,6,6) for 3D stress state or (f,3,3) for 2D stress state. If multi-point PSD is provided, the shape should be (N,f,6,6) or (N,f,3,3) respectively. Amplitude spectrum should be an array with shape (f,3) for 2D stress state or (f,6) for 3D stress state. If multi-point amplitude spectrum is provided, the shape should be (N,f,3) or (N,f,6) respectively. If instance of SpectralData class is passed, the multiaxial PSD is inherited.
window – str or tuple or array_like, optional Desired window to use. Defaults to ‘hann’.
nperseg – int, optional Length of each segment. Defaults to 1280.
noverlap – int, optional Number of points to overlap between segments. If None, noverlap = nperseg / 2. Defaults to None.
psd_trim_length – int, optional Number of frequency points to be used for PSD. Defaults to None.
T – int, float, optional Length of time history when random process is defined by input parameter ‘GUI’ or by PSD and frequency vector. If T and fs are provided, time histoy is generated. Defaults to None.
fs – int, float, optional Sampling frequency of time history when random process is defined by input parameter ‘GUI’ or by PSD and frequency vector. If T and fs are provided, time histoy is generated. Defaults to None.
rg – numpy.random._generator.Generator, optional Random generator controls phase of generated time history, when input is ‘GUI’ or (PSD, frequency vector). Defaults to None.
- loop_over_points(criterion, *args, **kwargs)[source]#
Loop the selected criterion over multiple points on the model
- set_eq_stress(eq_psd, f)[source]#
Set equivalent stress to the object. Also generate im ehistory if T and fs are provided
- select_critical_point(point_index)[source]#
Manually select a critical point from multipoint equivalent stress
- Parameters:
point_index – int Index of the critical point
- max_normal(search_method='local')[source]#
Converts the stress tensor at one node or multiple nodes to equivalent, scalar psd stress, using method of maximum normal stress.
- Parameters:
search_method – str, optional, default ‘local’ Search method for optimization. Options are ‘local’ or ‘global’. Local is prefered, unless the optimization fails.
- Nieslony, Adam and Macha, Ewald (2007);
Spectral method in multiaxial random fatigue
- max_shear(search_method='local')[source]#
Converts the stress tensor at one node or multiple nodes to equivalent, scalar psd stress, using method of maximum shear stress.
- Parameters:
search_method – str, optional, default ‘local’ Search method for optimization. Options are ‘local’ or ‘global’. Local is prefered, unless the optimization fails.
- Nieslony, Adam and Macha, Ewald (2007);
Spectral method in multiaxial random fatigue
- max_normal_and_shear(s_af, tau_af, search_method='local')[source]#
Converts the stress tensor at one node or multiple nodes to equivalent, scalar psd stress, using method of maximum normal and shear stress.
Critical plane is based on max variance of shear stress
- Parameters:
s_af – float Fully reversed bending-fatigue limit. Used for calculating material fatigue coefficient K [1].
tau_af – float Fully reversed torsion-fatigue limit. Used Used for calculating material fatigue coefficient K [1].
- Nieslony, Adam and Macha, Ewald (2007);
Spectral method in multiaxial random fatigue
- Matjaz Mrsnik, Janko Slavic and Miha Boltezar
Multiaxial Vibration Fatigue A Theoretical and Experimental Comparison. Mechanical Systems and Signal Processing, 2016
- EVMS()[source]#
Converts the stress tensor at one node or multiple nodes to equivalent, scalar psd stress, using ther equivalent von Misses stress in frequency domain (EVMS)
- Preumont, A., & Piéfort, V. (1994);
Predicting Random High-Cycle Fatigue Life With Finite Elements.
- cs(s_af, tau_af)[source]#
Converts the stress tensor at one node to equivalent, scalar psd stress, using the C-S criterion.
- Parameters:
s_af – float Fully reversed torsion-fatigue limit.
tau_af – float Fully reversed torsion-fatigue limit.
- Carpinteri A, Spagnoli A and Vantadori S;
Reformulation in the frequency domain of a critical plane-based multiaxial fatigue criterion, Int J Fat, 2014
- multiaxial_rainflow()[source]#
Converts the stress tensor at one node to equivalent, scalar psd stress, for use in frequency domain multiaxial rainflow.
ONLY WORKS FOR BIAXIAL STRESSES: PSD MATRIX (f,3,3) - single point or (N,f,3,3) - multiple points
- Pitoiset, Xavier, and André Preumont;
Spectral methods for multiaxial random fatigue analysis of metallic structures, International journal of fatigue, 2000
- thermoelastic()[source]#
Converts the stress tensor at one node to equivalent, scalar psd stress, using the thermoelasticity based criterion, simulating the equivalent stress, detected with the thermal camera
- Šonc J, Zaletelj K and Slavič J;
Application of thermoelasticity in the frequency-domain multiaxial vibration-fatigue criterion, Mechanical Systems and Signal Processsing, 2025
- liwi()[source]#
Converts the stress tensor at one node to equivalent stress, using the LiWI approach.
ONLY WORKS WITH BIAXIAL AMPLITUDE SPECTRUM (f,3) - single point or (N,f,3) - multiple points
- Alexander T. Schmidt, Nimish Pandiya,
Extension of the static equivalent stress hypotheses to linearly vibrating systems using wave interference – The LiWI approach, International Journal of Fatigue, 2021,
- coin_liwi(k_a, k_phi)[source]#
Converts the stress tensor at one node to equivalent stress, using the COIN-LiWI method.
ONLY WORKS WITH 3D AMPLITUDE SPECTRUM (f,6) - single point or (N,f,6) - multiple points
- Parameters:
k_a – float Tension shear strength ratio. (from article: 1.70 for aluminum alloy, 1.64 for structural steel, 1.43 for cast iron)
k_phi – float Phase influence factor (from article: 0.90 for aluminum alloy, 0.85 for structural steel, 1.10 for cast iron)
- Alexander T. Schmidt, Jan Kraft,
A new equivalent stress approach based on complex invariants: The COIN LiWI method, International Journal of Fatigue, 2023
- EVMS_out_of_phase()[source]#
Converts the stress tensor at one node to equivalent stress, using the phase-sensitive EVMS criterion, adjusted for out-of-phase components.
ONLY WORKS WITH BIAXIAL PSD (f,3,3) - single point or (N,f,3,3) - multiple points
- Bonte, Martijn HA and de Boer, Andries and Liebregts R
Determining the von Mises stress power spectral density for frequency domain fatigue analysis including out-of-phase stress components, Journal of Sound and Vibration, 2007
- Nieslony(s_af, tau_af, coefficient_load_type='tension')[source]#
Converts the stress tensor at one node to equivalent, scalar psd stress, using the Nieaslony criterion, combining von Mises and hydrostatic stresses.
- Parameters:
s_af – float Fully reversed torsion-fatigue limit.
tau_af – float Fully reversed torsion-fatigue limit.
coefficient_load_type – str Type of load with which the material fatigue properties were determined. Options are ‘tension’ for tension-compression load or ‘torsion’.
- Adam Niesłony, Michał Böhm, Robert Owsiński, Artur Dziura, Karol Czekaj,
Integrating von Mises and hydrostatic stresses in frequency domain multiaxial fatigue criteria for vibration fatigue analysis, Mechanical Systems and Signal Processing, 2025
- Lemaitre(poisson_ratio)[source]#
Converts the stress tensor at one node or multiple nodes to equivalent, scalar psd stress, using ther equivalent Lemaitre stress in frequency domain
- Jingran Ge, Yi Sun, Song Zhou;
Fatigue life estimation under multiaxial random loading by means of the equivalent Lemaitre stress and multiaxial S–N curve methods. International Journal of Fatigue, 2015