## Reliability

The application of reliability concepts to offshore structures began as an American story. In 1979, under the direction of Dr. Fred Moses, the American Petroleum Institute began a series of studies to implement reliability design procedures for fixed offshore platforms. This would (a) offer greater uniformity in platform component reliability; (b) enable a more effective material utilisation; (c) directly account for randomness and uncertainties in engineering parameters; (d) be capable of consistent modifications to account for different location, platform type, and life; (e) offer a logical basis for incorporating new information; and (f) help to focus on research activities to emphasise areas of greatest uncertainty and have results impact reliability factors.

PRAC 79-22 Project recommended that API RP-2A standard should change its current method of checking component safety known as working stress design (WSD) format to a multiple safety factor format. This concept came to be known as the Load Resistance Factor Design or LRFD.

To illustrate this, in WSD, a component is checked with an equation of the form:

```
Nominal Strength / Safety factor > Sum of Nominal Loads
```

Notice only one safety factor is used in the above, and hence the reliability would depend on the range of design application. Whereas, in the LRFD approach, partial safety factors are used in the format:

```
Component factor * Nominal Strength > Sum of Factored Loads
```

The research that went into producing this method included the following steps:

- Gather statistical data on load effects and component strengths.
- Review present performance criteria and experience.
- Establish target reliability level for each component type, based on performance experience.
- Calibrate load and resistance factors for tabulation in the standard.

PRAC 80-22 Project defined the reliability model for a structure as one that should incorporate safety margins and uncertainties in evaluating risk to a component or system.

```
Risk = 1 - Reliability = P[failure] = [Strength < Load]
```

The probability of component failure is as shown in Figure below.

The (extreme) load frequency curve overlapping the strength curve represents the risk. The model is viewed as a situation in which the probabilities correspond to the worst loading case — annual or lifetime, as appropriate. This overlap (i.e., probability of failure) would decrease if either (i) the mean margin of safety increases, or (ii) the uncertainty (σ) in load or resistance reduces.

The analysis of reliability is carried out by defining a failure function, *g*, such that *g < 0* denotes failure, or:

\begin{aligned} g = R - E \end{aligned}

where, *R* is the resistance or capacity, and *E* is the load effect. An exact solution for the probability of failure, *Pf*, could be obtained if *R* and *E* are both assumed as normal distributions with respective mean values, R and E, and coefficients of variations (cov),^{1} V_{R}, and V_{E}. Using these assumptions, *Pf* can be written as:

\begin{align} P_f &= \Phi\left( \frac{-\overline{g}}{\sigma_g} \right) \newline &= \Phi(-\beta) \end{align}

where,

\begin{aligned} \Phi(x) = \int_{-\infty}^{\infty} {\frac{1}{2\pi}}e^{\left({\frac{-1}{2}}z^2\right)dz} \end{aligned}

However, normal distributions are not always applicable to both load and strength variables, and both *R* and *E* in turn depend on several other random variables, such as load type (gravity, wave), beam-column stability, combined hydrostatic, axial and bending strengths, etc. Therefore, a generalisation is needed to carry out realistic reliability analyses. These results are often described in terms of a safety index, $\beta = \bar{g} / \sigma_g$, i.e., the ratio of mean safety margin to uncertainty level. In other words, $\beta$ is the distance in terms of standard deviations ($\sigma_g$) from the mean ($\bar{g}$) of the safety margin to the failure region (g < 0). When expanded, the expression becomes:

\begin{aligned} \beta = \frac{\ln\left({\frac{R_m}{E_m} \cdot \sqrt{\frac{1 + V_E^2}{1 + V_R^2}} } \right)}{\sqrt{\ln\left[ (1 + V_R^2) \cdot (1 + V_E^2) \right]}} \newline \end{aligned}

The LRFD method caught-on. Shell engineers extended the concept to numerous geographical areas^{2} to develop the following table:

Area | MPM (E_{20)} |
Mean (E_{20m)} |
$\sigma$_{E} |
COV (V_{20m}) |
---|---|---|---|---|

CNS, SNS | 0.80 | 0.84 | 0.18 | 0.212 |

NNS | 0.75 | 0.81 | 0.21 | 0.265 |

GoM | 0.68 | 0.79 | 0.25 | 0.32 |

AUS | 0.67 | 0.78 | 0.26 | 0.33 |

where, E_{20} is the most probable value, and E_{20m} is the mean value. In addition to $V_E$ provided above, uncertainty in hydrodynamic areas, volumes and marine growth, must be accounted for. This effect is covered by using COV = 8% and a bias factor of 1.0 (= ratio of mean value to characteristic value). This COV must be combined with COV values in table above.

Based on the GoM database, the following were derived, viz.,

\begin{aligned} R_m &= 1.85 \newline \gamma_E &= 1.35 \newline cov_R &= 0.05 \end{aligned}

Using these above together with $E_m$ and $V_E$ = (0.32^{2} + 0.08^{2})^{0.5}, the safety index, $\beta$ (GOM) was computed to be 2.77, for a reference period of 20 years — based on a characteristic 100-y design event. (From $\beta$, *Pf* could be determined as 4E-4/annum for the GoM database.)

Further, it was noted that the mean RSR is proportional to $\gamma_E$, which resulted in the expression:

\begin{aligned} R_m = \frac{1.85}{1.35} \cdot \gamma_E = 1.37 \cdot \gamma_E \end{aligned}

Once this was done, calibrating other locations to Gulf of Mexico safety level became easier. To extend this to a target probability of failure, first a target needed to be defined for the platform type. The industry now generally recognises it to be 3E-5/annum for a manned new installation, which would be 6E-4 for 20 years (= 20 * 3E-5/year).

For the target Pf = 3E-5/year (which corresponds to $P_{f20}$ = 6E-4, for 20 years), $\beta_{20}$ could be determined as equal to 3.239. Using this safety index, probability density function plots could be generated for all tabulated regions — as I’ve done below. (See plot code.)

### For exposure level L1 ($P_f=3\cdot10^{-5}/y$)

### For exposure level L2 ($P_f=5\cdot10^{-4}/y$)

Also, using this new safety index and the table above, the ISO 19902 has tabulated the mean RSR (Rm) and $\gamma_E$ for the Australian Northwest Shelf and the North Sea in A.9.9.3.

So, in a gist, that’s the general theory to develop mean RSR and $\gamma_E$, which could be applied to new locations, if E_{mean} and V_{E} could be determined from Metocean and Structural response studies like Shell did in the 90s for its NS and AU assets, and later for its Southeast Asian assets. Of course, statistically extending a dataset of one region’s safety index entirely to another depends very much on how well the means and covs are computed for the new region — and in general feels both like a novel idea as well as a hack. But for our generation, this will do.

Probability density plot code, now updated to include exposure levels L1 as well as L2, is as follows:

```
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""Load and Resistance probability density and Safety Margins per ISO 19902:2007
2018 ckunte
Usage: python pdf.py ( --gom | --nns | --cns | --aus ) [--exp=L]
python pdf.py --help
python pdf.py --version
Options:
-h, --help Show help screen
--gom Plot for Gulf of Mexico
--nns Plot for Northern North Sea
--cns Plot for Central North Sea (also applicable to SNS)
--aus Plot for Australian Northwest shelf
--exp=L Exposure level: 1 for L1, 2 for L2 [default: 1]
--version Show version
"""
from scipy.stats import norm
import numpy as np
import matplotlib.pyplot as plt
try:
from docopt import docopt
except ImportError:
raise ImportError('Requires docopt: run pip install docopt')
args = docopt(__doc__, version='Load and Resistance probability density and Safety Margins per ISO 19902:2007, ver:0.3')
cat = int(args['--exp'])
"""
Legend:
Em -- Mean load for a reference return period
Ve -- Load COV
Rm -- Mean resistance
Vr -- Resistance COV
COV = [0.212, 0.265, 0.32, 0.33] # For CNS & SNS, NNS, GOM, AUS
Ve = map(sqrt(x^2 + 0.08^2), COV) => [0.2266, 0.2768, 0.3298, 0.3396]
Rm = RSR_mean = [1.73, 1.92, 1.85, 2.18] for target Pf = 3E-5/annum (used in these plots)
Rm = RSR_mean = [1.40, 1.49, 1.60, 1.60] for target Pf = 5E-4/annum
"""
def ER(Em,Ve,Rm,Vr):
mu_e = np.log(Em / np.sqrt(1 + Ve**2)) # mean
mu_r = np.log(Rm / np.sqrt(1 + Vr**2)) # mean
sigma_e = np.sqrt(np.log(1 + Ve**2))
sigma_r = np.sqrt(np.log(1 + Vr**2))
#
s_e = np.random.lognormal(mu_e, sigma_e, 1000)
s_r = np.random.lognormal(mu_r, sigma_r, 1000)
count_e, bins_e, ignored_e = plt.hist(s_e, 100, normed=True, align='mid', alpha=0.09, color='r')
count_r, bins_r, ignored_r = plt.hist(s_r, 100, normed=True, align='mid', alpha=0.09, color='g')
x_e = np.linspace(min(bins_e), max(bins_e), 10000)
x_r = np.linspace(min(bins_r), max(bins_r), 10000)
#
pdf_E = (np.exp(-(np.log(x_e) - mu_e)**2 / (2 * sigma_e**2)) / (x_e * sigma_e * np.sqrt(2 * np.pi)))
pdf_R = (np.exp(-(np.log(x_r) - mu_r)**2 / (2 * sigma_r**2)) / (x_r * sigma_r * np.sqrt(2 * np.pi)))
#
plt.plot(x_e, pdf_E, linewidth=1, color='r')
plt.plot(x_r, pdf_R, linewidth=1, color='g')
plt.ylabel('Probability density')
misc()
pass
# Data: Em, Ve, Rm, Vr
d = [
0.79,0.3298,1.85,0.05, # L1: GOM
0.79,0.3298,1.60,0.05, # L2: GOM
0.81,0.2768,1.92,0.05, # L1: NNS
0.81,0.2768,1.49,0.05, # L2: NNS
0.84,0.2266,1.73,0.05, # L1: CNS and SNS
0.84,0.2266,1.40,0.05, # L2: CNS and SNS
0.78,0.3396,2.18,0.05, # L1: AUS
0.78,0.3396,1.60,0.05 # L2: AUS
]
def gom():
plt.title('Gulf of Mexico')
if cat == 1:
ER(d[0],d[1],d[2],d[3])
plt.xlabel('Load or resistance as times the nominal load, $x, E_{mean}(%.2f); x, R_{mean}(%.2f)$' %(d[0],d[2]))
plt.axvline(x=d[0],color='r',linestyle=':')
plt.axvline(x=d[2],color='g',linestyle=':')
plt.savefig('GoM_L1.png')
if cat == 2:
ER(d[4],d[5],d[6],d[7])
plt.xlabel('Load or resistance as times the nominal load, $x, E_{mean}(%.2f); x, R_{mean}(%.2f)$' %(d[4],d[6]))
plt.axvline(x=d[4],color='r',linestyle=':')
plt.axvline(x=d[6],color='g',linestyle=':')
plt.savefig('GoM_L2.png')
pass
def nns():
plt.title('Northern North Sea')
if cat == 1:
ER(d[8],d[9],d[10],d[11])
plt.xlabel('Load or resistance as times the nominal load, $x, E_{mean}(%.2f); x, R_{mean}(%.2f)$' %(d[8],d[10]))
plt.axvline(x=d[8],color='r',linestyle=':')
plt.axvline(x=d[10],color='g',linestyle=':')
plt.savefig('NNS_L1.png')
if cat == 2:
ER(d[12],d[13],d[14],d[15])
plt.xlabel('Load or resistance as times the nominal load, $x, E_{mean}(%.2f); x, R_{mean}(%.2f)$' %(d[12],d[14]))
plt.axvline(x=d[12],color='r',linestyle=':')
plt.axvline(x=d[14],color='g',linestyle=':')
plt.savefig('NNS_L2.png')
pass
def cns_sns():
plt.title('Central North Sea (also applicable to Southern North Sea)')
if cat == 1:
ER(d[16],d[17],d[18],d[19])
plt.xlabel('Load or resistance as times the nominal load, $x, E_{mean}(%.2f); x, R_{mean}(%.2f)$' %(d[16],d[18]))
plt.axvline(x=d[16],color='r',linestyle=':')
plt.axvline(x=d[18],color='g',linestyle=':')
plt.savefig('CNS-SNS_L1.png')
if cat == 2:
ER(d[20],d[21],d[22],d[23])
plt.xlabel('Load or resistance as times the nominal load, $x, E_{mean}(%.2f); x, R_{mean}(%.2f)$' %(d[20],d[22]))
plt.axvline(x=d[20],color='r',linestyle=':')
plt.axvline(x=d[22],color='g',linestyle=':')
plt.savefig('CNS-SNS_L2.png')
pass
def aus():
plt.title('Australian Northwest Shelf')
if cat == 1:
ER(d[24],d[25],d[26],d[27])
plt.xlabel('Load or resistance as times the nominal load, $x, E_{mean}(%.2f); x, R_{mean}(%.2f)$' %(d[24],d[26]))
plt.axvline(x=d[24],color='r',linestyle=':')
plt.axvline(x=d[26],color='g',linestyle=':')
plt.savefig('AUS_L1.png')
if cat == 2:
ER(d[28],d[29],d[30],d[31])
plt.xlabel('Load or resistance as times the nominal load, $x, E_{mean}(%.2f); x, R_{mean}(%.2f)$' %(d[28],d[30]))
plt.axvline(x=d[28],color='r',linestyle=':')
plt.axvline(x=d[30],color='g',linestyle=':')
plt.savefig('AUS_L2.png')
pass
def misc():
plt.rcParams['grid.linestyle'] = ':'
plt.rcParams['grid.linewidth'] = 0.5
plt.grid(True)
plt.xlim(0.25,2.75)
plt.ylim(0,5)
if __name__ == '__main__':
if args['--gom']:
gom()
elif args['--nns']:
nns()
elif args['--cns']:
cns_sns()
elif args['--aus']:
aus()
else:
print "No option was selected. For help, try: python pdf.py -h"
```