Tutorial: reproduce a published strain-life analysis¶
This walkthrough reproduces the SAE 1137 steel analysis of Williams, Lee, Rilly, "A practical method for statistical analysis of strain-life fatigue data", International Journal of Fatigue 25 (2003) 427-436, from the six re-tabulated tests bundled with the library. The same numbers anchor the golden regression tests in the suite, so what this page shows is enforced, not aspirational.
The data¶
from lcf import datasets
df = datasets.sae1137_reduced()
print(df)
Six strain-controlled tests, half-life total strain amplitude, stress
amplitude in MPa, and reversals to failure. Elastic modulus 208000 MPa.
The same records ship in the open
seed collection as validated test-record@1 documents.
Fit the strain-life constants¶
The paper drops plastic strain amplitudes below 0.0005, they sit at
measurement-noise level. min_plastic_strain applies the same rule.
import lcf
fit = lcf.fit_strain_life(
total_strain_amp=df.total_strain_amp,
stress_amp=df.stress_amp,
reversals=df.reversals,
E=datasets.SAE1137_E,
min_plastic_strain=5e-4,
)
Output, validated against the published reduction in the test suite:
| Constant | This fit | Meaning |
|---|---|---|
| eps_f | 1.106 | Fatigue ductility coefficient |
| c | -0.620 | Fatigue ductility exponent |
| sigma_f | 1072.8 MPa | Fatigue strength coefficient |
| b | -0.0836 | Fatigue strength exponent |
| transition | 22362 reversals | Elastic and plastic branches cross |
Predict a life¶
two_nf = lcf.predict_reversals(fit, 0.004) # 30902 reversals
Median and design life at a strain amplitude¶
from lcf import stats
ll = stats.fit_log_life(df.total_strain_amp, df.reversals)
median = stats.predict_life(ll, 0.005) # 23342
design = stats.design_life(ll, 0.005,
reliability=0.90, confidence=0.90) # 3541
The median at 0.005, about 23300 reversals from these six bundled tests, sits close to the 23700 the paper reports from its own eight-specimen reduction. The R90C90 design value here is far below the paper's because it comes from this six-point total-strain regression and its scatter, not from the paper's branch-wise reduction, a reminder that a design value belongs to a fit, not to a material. The paper's own reduction formula is reproduced exactly in the test suite as a golden case.
The same analysis through the MCP server¶
An agent produces the identical numbers with two tool calls:
fit_strain_life(total_strain_amp=[...], stress_amp=[...],
reversals=[...], E=208000, min_plastic_strain=0.0005)
fit_design_curve(amplitude=[...], life_values=[...],
design_amplitude=0.005)
Both persist their results for later recall_result calls.
If some tests had been runouts¶
Real campaigns suspend tests. Flag them instead of deleting them:
ml = stats.fit_log_life_censored(amplitude, life, censored)
bound = stats.design_life_ml(amplitude, life, censored,
at_amplitude=0.005)
The statistics page covers the censored layer.