Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New model for fatigue capacity and methods for calculating fatigue damage #91

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,31 @@ Compare the cycle range and range-mean distribution from several time series usi
Calculate fatigue damage in mooring lines
*****************************************

Using a traditional S-N curve with constant slope and intercept.

.. literalinclude:: examples/mooring_fatigue.py
:language: python
:linenos:
:lines: 1-

Using a novel S-N curve with mean load and corrosion dependent intercept parameter as described in OMAE2021-62775.

.. literalinclude:: examples/mooring_fatigue_mean_load.py
:language: python
:linenos:
:lines: 1-

.. figure:: img/damage-contribution-single.png
:figclass: align-center
:target: _images/damage-contribution-single.png

Note that this figure is based on cycles from a single time series. The figure below illustrates more clearly how this
can look like when using cycles aggregated from years of history.

.. figure:: img/damage-contribution-aggregated.png
:figclass: align-center
:target: _images/damage-contribution-aggregated.png


Apply low-pass and high-pass filters to time series
***************************************************
Expand Down
13 changes: 7 additions & 6 deletions docs/source/examples/mooring_fatigue.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
"""
Calculate mooring line fatigue.
Calculate mooring line fatigue using Rainflow counting and a traditional S-N curve.
"""
import os
from math import pi
from qats import TsDB
from qats.fatigue.sn import SNCurve, minersum
from qats.fatigue.sn import SNCurve


# load time series
db = TsDB.fromfile(os.path.join("..", "..", "..", "data", "simo_p_out.ts"))

# initiate SN-curve: DNVGL-OS-E301 curve for studless chain
sncurve = SNCurve(name="Studless chain OS-E301", m1=3.0, a1=6e10)
sncurve = SNCurve(name="Studless chain OS-E301", m=3.0, b0=10.778)

# Calculate fatigue damage for all mooring line tension time series (kN)
for ts in db.getl(names='tension_*_qs'):
Expand All @@ -21,11 +22,11 @@
ranges, _, counts = cycles.T

# calculate cross section stress cycles (shown here: 118mm studless chain, with unit [kN] for tension cycles)
area = 2. * pi * (118. / 2.) ** 2. # mm^2
ranges = [r * 1e3 / area for r in ranges] # MPa
area = 2. * pi * (118. / 2.) ** 2. # mm^2
ranges = 1e3 * ranges / area # MPa

# calculate fatigue damage from Palmgren-Miner rule (SCF=1, no thickness correction)
damage = minersum(ranges, counts, sncurve)
damage, _ = sncurve.minersum(ranges, counts)

# print summary
print(f"{ts.name}:")
Expand Down
54 changes: 54 additions & 0 deletions docs/source/examples/mooring_fatigue_mean_load.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""
Calculate fatigue damage using a mean load and corrosion dependent S-N curve.
Plot cycle amplitude and mean versus contribution to total damage.
"""
import numpy as np
import matplotlib.pyplot as plt
from qats import TsDB
from qats.fatigue.rainflow import mesh
from qats.fatigue.sn import SNCurve


# mooring chain properties
mbl = 10000. # minimum breaking load
diameter = 110. # mm
grade = 3 # corrosion grade
area = 2. * np.pi * (diameter / 2) ** 2. # mm^2

# S-N curve (mean load and corrosion dependent fatigue capacity, ref. OMAE2021-62775)
sn = SNCurve(
m=3, # inverse slope
b0=11.873, # Constant in equation to calculate intercept parameter
b1=-0.0519, # Mean load coefficient in equation to calculate the intercept parameter
b2=-0.109, # Corrosion coefficient in equation to calculate the intercept parameter
default_g1=20., # default mean load / MBL ratio (%)
default_g2=1., # default corrosion grade (1=new)
)

# tension history
db = TsDB.fromfile("../../../data/mooring.ts")
ts = db.get("Mooring line 1")

# rainflow counting and meshing the cycle distribution (for plotting)
cycles = ts.rfc()
ranges, means, count = mesh(cycles, nr=25, nm=25)
count *= 31556926. / ts.duration # scale annual cycle count
stress_ranges = 1000. * ranges / area # MPa
total_damage, damage_per_bin = sn.minersum(stress_ranges, count, g1=means / mbl * 100., g2=float(grade))

# plotting cycle amplitude and mean versus damage contribution
# cycle mean and amplitude (half the range) normalized on MBL in %
a = 100. * 0.5 * ranges / mbl
m = 100. * means / mbl
d = 100. * damage_per_bin / total_damage
cbar_min, cbar_max = np.floor(np.min(d)), np.ceil(np.max(d))
cbar_labels = np.linspace(cbar_min, cbar_max, 6)
fig1, ax1 = plt.subplots()
contour_ = ax1.contourf(a, m, d, 400)
ax1.set_xlabel("Cycle amplitude [%MBL]")
ax1.set_ylabel("Cycle mean [%MBL]")
cbar = fig1.colorbar(contour_)
cbar.set_ticks(cbar_labels)
cbar.set_ticklabels(cbar_labels)
cbar.set_label("Damage [%]")
plt.show()
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/img/damage-contribution-single.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading