The meanstress module#

Provide mean stress transformations for load collectives and histograms.

Mean stress transformations convert a cyclic load with stress amplitude S_a and mean stress S_m to an equivalent amplitude at a target stress ratio R_goal. The equivalent cycle is intended to produce the same fatigue assessment result in an S-N curve calculation.

The module represents mean stress sensitivity by a Haigh diagram: each stress ratio interval R = S_min / S_max is assigned a slope M. Convenience constructors implement the FKM-Goodman and five-segment diagrams, while pandas accessors apply the transformation to load collectives and rainflow histograms.

See also

pylife.strength.meanstress.HaighDiagram

Store piecewise mean stress sensitivities.

pylife.strength.meanstress.MeanstressTransformCollective

Transform load collectives.

pylife.strength.meanstress.MeanstressTransformMatrix

Transform load histograms.

class pylife.strength.meanstress.HaighDiagram(pandas_obj)[source]#

Represent a piecewise Haigh diagram for mean stress correction.

A Haigh diagram assigns a mean stress sensitivity M to intervals of the stress ratio R. In pyLife it is stored as a pandas.Series whose values are dimensionless sensitivities and whose R index level is a pandas.IntervalIndex. The diagram is used to transform stress cycles from their actual R value to a target R_goal.

Parameters:

pandas_obj (pandas.Series) – Series containing mean stress sensitivities M indexed by the supplied R intervals. Additional index levels may identify several diagrams.

Notes

For one segment with sensitivity M the transformation keeps the damage equivalent quantity S_a + M S_m constant. With

\[S_m = S_a\,\frac{1 + R}{1 - R},\]

an amplitude transformed to R_goal is obtained from

\[S_{a,goal} = \frac{(1 - R_{goal})(S_a + M S_m)} {1 - R_{goal} + M(1 + R_{goal})}.\]

For R_goal = -\infty the implemented limiting form is

\[S_{a,goal} = \frac{S_a + M S_m}{1 - M}.\]
classmethod five_segment(five_segment_haigh_diagram)[source]#

Create a five-segment Haigh diagram.

Parameters:

five_segment_haigh_diagram (pandas.Series or pandas.DataFrame) – Five-segment mean stress data containing dimensionless sensitivities M0 through M4 and transition stress ratios R12 and R23.

Returns:

Haigh diagram with five stress-ratio segments.

Return type:

pylife.strength.meanstress.HaighDiagram

Notes

The five-segment diagram defines

\[\begin{split}M(R) = \begin{cases} M_4, & 1 < R \\ M_0, & -\infty < R \le 0 \\ M_1, & 0 < R \le R_{12} \\ M_2, & R_{12} < R \le R_{23} \\ M_3, & R_{23} < R \le 1. \end{cases}\end{split}\]

R12 and R23 are dimensionless transition ratios and must satisfy the physical ordering used by the selected material model.

Examples

>>> from pylife.strength.meanstress import HaighDiagram
>>> haigh = HaighDiagram.five_segment(
...    pd.Series(
...        {"M0": 0.5, "M1": 0.25, "M2": 0.125, "M3": 1.0, "M4": -2.0, "R12": 0.2, "R23": 0.8}
...    )
... )
>>> haigh.to_pandas()
R
(1.0, inf]    -2.000
(-inf, 0.0]    0.500
(0.0, 0.2]     0.250
(0.2, 0.8]     0.125
(0.8, 1.0]     1.000
dtype: float64
>>> from pylife.strength.meanstress import HaighDiagram
>>> collective = pd.DataFrame(
...     {
...         "range": [600.0, 300.0, 500.0],
...         "mean": [400.0, -150.0, 0.0],
...         "cycles": [1.0, 10.0, 100.0],
...     }
... )
>>> haigh = HaighDiagram.five_segment(
...    pd.Series(
...        {"M0": 0.5, "M1": 0.25, "M2": 0.125, "M3": 1.0, "M4": -2.0, "R12": 0.2, "R23": 0.8}
...    )
... )
>>> haigh.transform(collective, 0.0)
        range        mean  cycles
0  640.000000  320.000000     1.0
1  100.000000   50.000000    10.0
2  333.333333  166.666667   100.0
classmethod fkm_goodman(haigh_fkm_goodman)[source]#

Create an FKM-Goodman Haigh diagram.

Parameters:

haigh_fkm_goodman (pandas.Series or pandas.DataFrame) – Mean stress sensitivity data. It must contain M for -inf < R <= 0 and may contain M2 for 0 < R <= 1. If M2 is missing, M / 3 is used.

Returns:

Haigh diagram with segments (1, inf], (-inf, 0] and (0, 1].

Return type:

pylife.strength.meanstress.HaighDiagram

Limitations

The FKM-Goodman correction implemented here assumes the FKM linear guideline piecewise slopes: M for alternating to pulsating compression/tension cycles, M2 for tensile mean stresses up to R = 1, and 0 beyond R = 1. Use five_segment() when material-specific transition ratios R12 and R23 are available.

Notes

The implemented slopes are

\[\begin{split}M(R) = \begin{cases} 0, & 1 < R \\ M, & -\infty < R \le 0 \\ M_2, & 0 < R \le 1. \end{cases}\end{split}\]

Examples

Create a diagram with default M2.

>>> from pylife.strength.meanstress import HaighDiagram
>>> HaighDiagram.fkm_goodman(pd.Series({"M": 0.5})).to_pandas()
R
(1.0, inf]     0.000000
(-inf, 0.0]    0.500000
(0.0, 1.0]     0.166667
dtype: float64

Create a diagram with a manual M2.

>>> from pylife.strength.meanstress import HaighDiagram
>>> HaighDiagram.fkm_goodman(pd.Series({"M": 0.5, "M2": 0.2})).to_pandas()
R
(1.0, inf]     0.0
(-inf, 0.0]    0.5
(0.0, 1.0]     0.2
dtype: float64
>>> from pylife.strength.meanstress import HaighDiagram
>>> collective = pd.DataFrame(
...     {
...         "range": [600.0, 300.0, 500.0],
...         "mean": [100.0, 50.0, 80.0],
...         "cycles": [1.0, 10.0, 100.0],
...     }
... )
>>> HaighDiagram.fkm_goodman(pd.Series({"M": 0.5})).transform(collective, -1.0)
   range  mean  cycles
0  700.0   0.0     1.0
1  350.0   0.0    10.0
2  580.0   0.0   100.0
classmethod from_dict(segments_dict)[source]#

Create a Haigh diagram from interval boundaries and sensitivities.

Parameters:

segments_dict (dict) – Mapping from (left, right) stress-ratio interval tuples to dimensionless mean stress sensitivities M.

Returns:

Haigh diagram accessor wrapping a pandas.Series indexed by the supplied R intervals.

Return type:

pylife.strength.meanstress.HaighDiagram

Examples

>>> from pylife.strength.meanstress import HaighDiagram
>>> HaighDiagram.from_dict({
...    (1.0, np.inf): 0.0,
...    (-np.inf, 0.0): 0.5,
...    (0.0, 1.0): 0.167
... }).to_pandas()
R
(1.0, inf]     0.000
(-inf, 0.0]    0.500
(0.0, 1.0]     0.167
dtype: float64
transform(collective, R_goal)[source]#

Transform a load collective to a target stress ratio.

Parameters:
  • collective (pandas.DataFrame) – Load collective to transform. It must contain either range and mean columns or from and to columns. Ranges are stress ranges in MPa or another consistent stress unit; means are mean stresses in the same unit. Additional columns, for example cycles, are copied.

  • R_goal (float) – Target stress ratio R = S_min / S_max, dimensionless.

Returns:

Transformed collective with columns range for stress range, mean for mean stress, and all non-load columns copied from the input.

Return type:

pandas.DataFrame

Notes

Each cycle is moved segment by segment across the Haigh diagram until it reaches R_goal. The result uses stress ranges, so the transformed range is 2 * S_a.

Examples

>>> from pylife.strength.meanstress import HaighDiagram
>>> collective = pd.DataFrame(
...     {
...         "from": [300.0, -150.0, -250.0],
...         "to": [-300.0, 150.0, 250.0],
...         "cycles": [1.0, 10.0, 100.0],
...     }
... )
>>> HaighDiagram.from_dict({(-np.inf, np.inf): 0.5}).transform(collective, 0.0)
        range        mean  cycles
0  400.000000  200.000000     1.0
1  200.000000  100.000000    10.0
2  333.333333  166.666667   100.0
>>> from pylife.strength.meanstress import HaighDiagram
>>> collective = pd.DataFrame(
...     {
...         "range": [600.0, 300.0, 500.0],
...         "mean": [100.0, 50.0, 80.0],
...         "cycles": [1.0, 10.0, 100.0],
...     }
... )
>>> HaighDiagram.from_dict({(-np.inf, np.inf): 0.5}).transform(collective, -1.0)
   range  mean  cycles
0  700.0   0.0     1.0
1  350.0   0.0    10.0
2  580.0   0.0   100.0
class pylife.strength.meanstress.MeanstressTransformCollective(pandas_obj)[source]#

Transform counted load collectives to a target stress ratio.

The accessor is registered as .meanstress_transform on pandas.DataFrame load collectives. The input data must satisfy the pylife.stress.collective load collective contract and provide either range and mean columns or from and to columns.

Parameters:

pandas_obj (pandas.DataFrame) – Load collective data passed by the pandas accessor machinery.

See also

pylife.strength.meanstress.HaighDiagram

Represent the correction diagram.

pylife.strength.meanstress.MeanstressTransformMatrix

Transform rainflow histograms.

five_segment(five_segment, R_goal)[source]#

Apply the five-segment transformation to a load collective.

Parameters:
  • five_segment (pandas.Series or pandas.DataFrame) – Mean stress sensitivities M0 through M4 and transition ratios R12 and R23.

  • R_goal (float) – Target stress ratio R = S_min / S_max, dimensionless.

Returns:

The transformed load collective. After the meanstress transformation, the resulting (range, mean) interval bins may no longer be continuous.

Return type:

pylife.stress.collective.LoadCollective

See also

pylife.strength.meanstress.HaighDiagram.five_segment

Create the underlying diagram.

Examples

>>> collective = pd.DataFrame(
...     {
...         "range": [600.0, 300.0, 500.0],
...         "mean": [400.0, -150.0, 0.0],
...         "cycles": [1.0, 10.0, 100.0],
...     }
... )
>>> haigh = pd.Series(
...    {"M0": 0.5, "M1": 0.25, "M2": 0.125, "M3": 1.0, "M4": -2.0, "R12": 0.2, "R23": 0.8}
... )
>>> transformed = collective.meanstress_transform.five_segment(haigh, 0.0)
>>> transformed.amplitude
0    320.000000
1     50.000000
2    166.666667
Name: amplitude, dtype: float64
>>> transformed.meanstress
0    320.000000
1     50.000000
2    166.666667
Name: meanstress, dtype: float64
fkm_goodman(goodman, R_goal)[source]#

Apply the FKM-Goodman transformation to a load collective.

Parameters:
  • goodman (pandas.Series or pandas.DataFrame) – Mean stress sensitivity data containing M and optionally M2.

  • R_goal (float) – Target stress ratio R = S_min / S_max, dimensionless.

Returns:

Transformed load collective accessor. Stress amplitudes and mean stresses use the same unit as the input.

Return type:

pylife.stress.collective.LoadCollective

See also

pylife.strength.meanstress.HaighDiagram.fkm_goodman

Create the underlying diagram.

Examples

>>> collective = pd.DataFrame(
...     {
...         "from": [300.0, -150.0, -250.0],
...         "to": [-300.0, 150.0, 250.0],
...         "cycles": [1.0, 10.0, 100.0],
...     }
... )
>>> collective.meanstress_transform.fkm_goodman(pd.Series({"M": 0.5}), 0.0).amplitude
0    200.000000
1    100.000000
2    166.666667
Name: amplitude, dtype: float64
class pylife.strength.meanstress.MeanstressTransformMatrix(pandas_obj)[source]#

Transform rainflow histograms to a target stress ratio.

The accessor is registered as .meanstress_transform on pandas.Series load histograms. Histograms may be indexed by from and to interval bins or by range and mean interval bins.

Parameters:

pandas_obj (pandas.Series) – Load histogram data passed by the pandas accessor machinery.

See also

pylife.strength.meanstress.HaighDiagram

Represent the correction diagram.

pylife.strength.meanstress.MeanstressTransformCollective

Transform load collectives.

five_segment(five_segment, R_goal)[source]#

Apply the five-segment transformation to a load histogram.

Parameters:
  • five_segment (pandas.Series or pandas.DataFrame) – Mean stress sensitivities M0 through M4 and transition ratios R12 and R23.

  • R_goal (float) – Target stress ratio R = S_min / S_max, dimensionless.

Returns:

Transformed load histogram accessor. The resulting range and mean interval bins may no longer be continuous.

Return type:

pylife.stress.collective.LoadHistogram

Warning

The transformed interval bins are geometrically correct for the transformed corner points. Rebin only as a later visualization step because rebinning may change the numerical damage result.

See also

pylife.strength.meanstress.HaighDiagram.five_segment

Create the underlying diagram.

Examples

>>> histogram = pd.Series(
...     [10, 90, 900, 9000, 90000, 900000],
...     index=pd.MultiIndex.from_arrays(
...         [
...             pd.IntervalIndex.from_arrays(
...                 [650, 550, 450, 350, 250, 150], [750, 650, 550, 450, 350, 250]
...             ),
...             pd.IntervalIndex.from_arrays([0, 0, 0, 0 ,0, 0], [0, 0, 0, 0, 0, 0]),
...         ],
...         names=["range", "mean"],
...     ),
...     name="cycles"
... )
>>> five_segments = pd.Series(
...     {
...         "M0": 0.5,
...         "M1": 0.2,
...         "M2": 0.1,
...         "M3": 1.0,
...         "M4": 2.0,
...         "R12": 0.2,
...         "R23": 0.8,
...     }
... )
>>> transformed = histogram.meanstress_transform.five_segment(five_segments, 0)
>>> transformed.amplitude
range                                     mean
(433.3333333333333, 500.0]                (216.66666666666666, 250.0]                 233.333333
(366.6666666666667, 433.3333333333333]    (183.33333333333334, 216.66666666666666]    200.000000
(300.0, 366.6666666666667]                (150.0, 183.33333333333334]                 166.666667
(233.33333333333334, 300.0]               (116.66666666666667, 150.0]                 133.333333
(166.66666666666669, 233.33333333333334]  (83.33333333333334, 116.66666666666667]     100.000000
(100.0, 166.66666666666669]               (50.0, 83.33333333333334]                    66.666667
Name: amplitude, dtype: float64
fkm_goodman(goodman, R_goal)[source]#

Apply the FKM-Goodman transformation to a load histogram.

Parameters:
  • goodman (pandas.Series or pandas.DataFrame) – Mean stress sensitivity data containing M and optionally M2.

  • R_goal (float) – Target stress ratio R = S_min / S_max, dimensionless.

Returns:

Transformed load histogram accessor. The resulting range and mean interval bins may no longer be continuous.

Return type:

pylife.stress.collective.LoadHistogram

Warning

The transformed interval bins are geometrically correct for the transformed corner points. Rebin only as a later visualization step because rebinning may change the numerical damage result.

See also

pylife.strength.meanstress.HaighDiagram.fkm_goodman

Create the underlying diagram.

Examples

>>> histogram = pd.Series(
...     [10, 90, 900, 9000, 90000, 900000],
...     index=pd.MultiIndex.from_arrays(
...         [
...             pd.IntervalIndex.from_arrays(
...                 [650, 550, 450, 350, 250, 150], [750, 650, 550, 450, 350, 250]
...             ),
...             pd.IntervalIndex.from_arrays([0, 0, 0, 0 ,0, 0], [0, 0, 0, 0, 0, 0]),
...         ],
...         names=["range", "mean"],
...     ),
...     name="cycles"
... )
>>> transformed = histogram.meanstress_transform.fkm_goodman(pd.Series({"M": 0.0}), 0)
>>> transformed.amplitude
range           mean
(650.0, 750.0]  (325.0, 375.0]    350.0
(550.0, 650.0]  (275.0, 325.0]    300.0
(450.0, 550.0]  (225.0, 275.0]    250.0
(350.0, 450.0]  (175.0, 225.0]    200.0
(250.0, 350.0]  (125.0, 175.0]    150.0
(150.0, 250.0]  (75.0, 125.0]     100.0
Name: amplitude, dtype: float64
pylife.strength.meanstress.experimental_mean_stress_sensitivity(sn_curve_R0, sn_curve_Rn1, N_c=inf)[source]#

Estimate mean stress sensitivity from two S-N curves.

Parameters:
  • sn_curve_R0 (pylife.materiallaws.WoehlerCurve) – Wöhler curve accessor for stress ratio R = 0.

  • sn_curve_Rn1 (pylife.materiallaws.WoehlerCurve) – Wöhler curve accessor for stress ratio R = -1.

  • N_c (float, optional) – Number of cycles at which the amplitudes are compared. If N_c is greater than or equal to the knee point ND of a curve, its SD value is used. Default is numpy.inf.

Returns:

Mean stress sensitivity M_sigma, dimensionless.

Return type:

float

Raises:

ValueError – Raised if the resulting sensitivity is outside the physically plausible interval [0, 1].

Notes

Following Haibach [Haibach-Meanstress], the sensitivity is estimated as

\[M_{\sigma} = \frac{S_a^{R=-1}(N_c)}{S_a^{R=0}(N_c)} - 1.\]

References

[Haibach-Meanstress]

E. Haibach, “Betriebsfestigkeit”, Springer-Verlag, 2006, p. 21.

pylife.strength.meanstress.five_segment_correction(amplitude, meanstress, M0, M1, M2, M3, M4, R12, R23, R_goal)[source]#

Transform amplitudes with the five-segment mean stress correction.

Parameters:
  • amplitude (array_like) – Stress amplitudes in MPa or another consistent stress unit.

  • meanstress (array_like) – Mean stresses in the same unit as amplitude.

  • M0 (float) – Mean stress sensitivity for -inf < R <= 0, dimensionless.

  • M1 (float) – Mean stress sensitivity for 0 < R <= R12, dimensionless.

  • M2 (float) – Mean stress sensitivity for R12 < R <= R23, dimensionless.

  • M3 (float) – Mean stress sensitivity for R23 < R <= 1, dimensionless.

  • M4 (float) – Mean stress sensitivity for 1 < R, dimensionless.

  • R12 (float) – Transition stress ratio between M1 and M2, dimensionless.

  • R23 (float) – Transition stress ratio between M2 and M3, dimensionless.

  • R_goal (float) – Target stress ratio R = S_min / S_max, dimensionless.

Returns:

Transformed stress amplitudes in the same unit as amplitude.

Return type:

numpy.ndarray

See also

pylife.strength.meanstress.HaighDiagram.five_segment

Create a five-segment diagram.

pylife.strength.meanstress.fkm_goodman(amplitude, meanstress, M, M2, R_goal)[source]#

Transform amplitudes with the FKM-Goodman mean stress correction.

Parameters:
  • amplitude (array_like) – Stress amplitudes in MPa or another consistent stress unit.

  • meanstress (array_like) – Mean stresses in the same unit as amplitude.

  • M (float) – Mean stress sensitivity for -inf < R <= 0, dimensionless.

  • M2 (float) – Mean stress sensitivity for 0 < R <= 1, dimensionless.

  • R_goal (float) – Target stress ratio R = S_min / S_max, dimensionless.

Returns:

Transformed stress amplitudes in the same unit as amplitude.

Return type:

numpy.ndarray

See also

pylife.strength.meanstress.HaighDiagram.fkm_goodman

Create an FKM-Goodman diagram.