# S-N curves

In order to set a suitable design criteria, I am looking to compare two classes of S-N curves for a fatigue design, viz., E and F2, and I cannot not find a handy plot to refer to, and it is frustrating when standards fail to include. So, I channel it to write some code to roll my own: The basic S-N curve equation is as follows, which one may know is from Paris-Erdogan law (fracture mechanics):

$$N = k_1 \cdot S^{-m}$$

The standard does describe it in its logarithmic form, which is as follows:

$$\log N = \log k_1 - m \cdot \log S$$

and then it goes on to furnish its two sets of key components that form parts of the equation — highlighted below.1 Code: sncurves.py for plotting hotspot stresses versus number of cycles:

#!/usr/bin/env python
# encoding: utf-8
"""
sncurves.py -- 2016 ckunte
May 7: Initial commit.
"""
import numpy as np
import matplotlib.pyplot as plt

a = [
12.18, 16.13, # TJ
14.61, 17.01, # B
13.23, 16.47, # C
11.78, 15.63, # D
11.62, 15.37, # E
11.40, 15.00, # F
11.23, 14.71, # F2
11.00, 14.33, # G
10.57, 13.62  # W1
]
m = [3.0, 3.5, 4.0, 5.0] # Slope
r = [1.8E6, 1.0E5, 4.68E5, 1.0E6] # Range limit for curves

fig, ax = plt.subplots()

def style():
plt.rcParams['grid.linestyle'] = ':'
plt.rcParams['grid.linewidth'] = 0.5
plt.grid(True)

def tj_curve():
# -- TJ (tubular joints) curve --
# Slope 1
n = np.arange(1, r, 1.0E5)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='black', linewidth=2.0, label="TJ curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='black', linewidth=2.0)
pass

def b_curve():
# -- B curve --
# Slope 1
n = np.arange(1, r, 1.0E4)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='magenta', linewidth=2.0, label="B curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='magenta', linewidth=2.0)
pass

def c_curve():
# -- C curve --
# Slope 1
n = np.arange(1, r, 1.0E4)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='blue', linewidth=2.0, label="C curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='blue', linewidth=2.0)
pass

def d_curve():
# -- D curve --
# Slope 1
n = np.arange(1, r, 1.0E4)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='orange', linewidth=2.0, label="D curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='orange', linewidth=2.0)
pass

def e_curve():
# -- E curve --
# Slope 1
n = np.arange(1, r, 1.0E4)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='green', linewidth=2.0, label="E curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='green', linewidth=2.0)
pass

def f_curve():
# -- F curve --
# Slope 1
n = np.arange(1, r, 1.0E4)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='olive', linewidth=2.0, label="F curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='olive', linewidth=2.0)
pass

def f2_curve():
# -- F2 curve --
# Slope 1
n = np.arange(1, r, 1.0E4)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='brown', linewidth=2.0, label="F2 curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='brown', linewidth=2.0)
pass

def g_curve():
# -- G curve --
# Slope 1
n = np.arange(1, r, 1.0E4)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='deeppink', linewidth=2.0, label="G curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='deeppink', linewidth=2.0)
pass

def w1_curve():
# -- W1 curve --
# Slope 1
n = np.arange(1, r, 1.0E4)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='olivedrab', linewidth=2.0, label="W1 curve")
# Slope 2
n = np.arange(r, 1.0E12, 1.0E9)
s = (n / 10**a)**(-1 / m)
ax.loglog(n, s, basex=10, color='olivedrab', linewidth=2.0)
pass

if __name__ == '__main__':
# Plot all
style()
tj_curve()
b_curve()
c_curve()
d_curve()
f_curve()
f2_curve()
g_curve()
w1_curve()
ax.legend(loc=0)
ax.set_xlabel('Number of cycles, N')
ax.set_ylabel('Hotspot stress $\sigma$, MPa')
plt.savefig("sncurves.png")
plt.show()


1. Playing with logarithms is fraught with error, as they are not the same as plain algebra — Leonhard Euler’s gift to the world, which reminds me I should jog my memory from high-school. There is a very nice podcast recording (mp3) on Euler’s e that also discusses the history of logarithms, which was in ancient days allowed to transform “complicated” multiplication into simple addition, which makes perfect sense in a world that had no computers, no calculators, and no slide rules.