You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1441 lines
42 KiB
Python
1441 lines
42 KiB
Python
from __future__ import division
|
|
import numpy as np
|
|
|
|
|
|
def nt2fr(nt, kind=0):
|
|
"""
|
|
NT2FR Calculates the frequency matrix given the counting distribution matrix.
|
|
|
|
Parameters
|
|
----------
|
|
nt = the counting distribution matrix,
|
|
kind = 0,1
|
|
|
|
Returns
|
|
-------
|
|
fr = the frequency matrix,
|
|
|
|
If kind=0 function computes the inverse to
|
|
|
|
N_T(u,v) = #{ (M_i,m_i); M_i>u, m_i<v }
|
|
|
|
and if def=1 the inverse to
|
|
|
|
N_T(u,v) = #{ (M_i,m_i); M_i>=u, m_i=<v }
|
|
|
|
where (M_i,m_i) are cycles and v,u are in the discretization grid.
|
|
"""
|
|
|
|
n = len(nt)
|
|
fr_raw = (nt[:n - 1, :][:, n - 1] + nt[1:, :][:, 1:] -
|
|
nt[:n - 1, :][:, 1:] - nt[1:, :][:, :n - 1])
|
|
|
|
fr = np.zeros(np.shape(nt))
|
|
if kind == 0:
|
|
fr[:n - 1, :n - 1] = fr_raw
|
|
else:
|
|
fr[1:, 1:] = fr_raw
|
|
return fr
|
|
|
|
|
|
def fr2nt(fr):
|
|
"""
|
|
FR2NT Calculates the counting distribution given the frequency matrix.
|
|
|
|
Parameters
|
|
----------
|
|
fr = a square frequency matrix for a cycle count.
|
|
|
|
Returns
|
|
---------
|
|
nt = a square counting distribution matrix for a cycle count,
|
|
|
|
Copyright 1993, Mats Frendahl, Dept. of Math. Stat., University of Lund.
|
|
"""
|
|
|
|
n, m = np.shape(fr)
|
|
if n < 3:
|
|
raise ValueError('The dimension must be 3 or larger!')
|
|
if n != m:
|
|
raise ValueError('The matrix is not square!')
|
|
|
|
m1 = np.cumsum(np.cumsum(fr, axis=1) - fr)
|
|
m2 = np.zeros((n, n))
|
|
m2[1:, 1:] = m1[:n - 2, :][:, 1:]
|
|
nt = np.fliplr(np.triu(np.fliplr(m2), 0))
|
|
|
|
return nt
|
|
|
|
|
|
def iter_(frfc, fmM_0=None, k=1, epsilon=1e-5):
|
|
"""
|
|
ITER Calculates a Markov matrix given a rainflow matrix
|
|
|
|
CALL: [fmM_k frfc_k] = iter_(frfc, fmM_0, k, eps)
|
|
|
|
Parameters
|
|
----------
|
|
frfc = the rainflow matrix to be inverted,
|
|
fmM_0 = the first approximation to the Markov matrix, if not
|
|
specified fmM_0=frfc,
|
|
k = number of iterations, if not specified, k=1.
|
|
eps = a convergence treshold, default value; eps=0.00001
|
|
|
|
Return
|
|
------
|
|
fmM_k = the solution to the equation frfc = fmM + F(fmM),
|
|
frfc_k = the rainflow matrix; frfc_k = fmM_k + F(fmM_k).
|
|
|
|
|
|
See also
|
|
--------
|
|
iter_mc, spec2cmat, mctp2rfm, mc2rfm
|
|
|
|
References
|
|
----------
|
|
Rychlik, I. (1996)
|
|
'Simulation of load sequences from Rainflow matrices: Markov method'
|
|
Int. J. Fatigue, Vol 18, pp 429-438
|
|
"""
|
|
return _raw_iter(mctp2rfc, frfc, fmM_0, k, epsilon)
|
|
|
|
|
|
def _raw_iter(fun2rfc, frfc, fmM_0=None, k=1, epsilon=1e-5):
|
|
if fmM_0 is None:
|
|
fmM_0 = frfc
|
|
|
|
frfc0 = np.fliplr(frfc)
|
|
fmM = np.fliplr(fmM_0)
|
|
for _i in range(k):
|
|
fmM_old = fmM
|
|
frfc = fun2rfc(fmM)
|
|
fmM = fmM_old + (frfc0 - frfc)
|
|
fmM = np.maximum(0, fmM)
|
|
# check = [k-i+1, sum(sum(abs(fmM_old-fmM))), sum(sum(frfc0))/sum(sum(fmM))];
|
|
# disp(['iteration step, accuracy ', num2str(check(1:2))])
|
|
converged = not np.sum(np.abs(fmM_old - fmM)) > epsilon
|
|
if converged:
|
|
break
|
|
|
|
F = np.fliplr(fmM)
|
|
frfc = np.fliplr(fun2rfc(fmM))
|
|
|
|
return F, frfc
|
|
|
|
|
|
def iter_mc(frfc, fmM_0=None, k=1, epsilon=1e-5):
|
|
"""
|
|
ITER_MC Calculates a kernel of a MC given a rainflow matrix
|
|
|
|
Solves f_rfc = f_xy + F_mc(f_xy) for f_xy.
|
|
|
|
Call: [fmM_k frfc_k]=iter_mc(frfc,fmM_0,k,eps)
|
|
|
|
fmM_k = the solution to the equation frfc = fmM + F(fmM),
|
|
frfc_k = the rainflow matrix; frfc_k = fmM_k + F(fmM_k).
|
|
|
|
|
|
frfc = the rainflow matrix to be inverted,
|
|
fmM_0 = the first approximation to the Markov matrix, if not
|
|
specified fmM_0=frfc,
|
|
k = number of iterations, if not specified, k=1.
|
|
eps = a convergence treshold, default value; eps=0.00001
|
|
|
|
See also
|
|
--------
|
|
iter_, spec2cmat, mctp2rfm, mc2rfm
|
|
|
|
References
|
|
----------
|
|
Rychlik, I. (1996)
|
|
'Simulation of load sequences from Rainflow matrices: Markov method'
|
|
Int. J. Fatigue, Vol 18, pp 429-438
|
|
"""
|
|
return _raw_iter(mc2rfc, frfc, fmM_0, k, epsilon)
|
|
|
|
|
|
def _raise_kind_error(kind):
|
|
if kind in (-1, 0):
|
|
raise NotImplementedError('kind = {} not yet implemented'.format(kind))
|
|
else:
|
|
raise ValueError('kind = {}: not a valid value of kind'.format(kind))
|
|
|
|
|
|
def nt2cmat(nt, kind=1):
|
|
"""
|
|
Return cycle matrix from a counting distribution.
|
|
|
|
Parameters
|
|
----------
|
|
NT: 2D array
|
|
Counting distribution. [nxn]
|
|
kind = 1: causes peaks to be projected upwards and troughs
|
|
downwards to the closest discrete level (default).
|
|
= 0: causes peaks and troughs to be projected to
|
|
the closest discrete level.
|
|
= -1: causes peaks to be projected downwards and the
|
|
troughs upwards to the closest discrete level.
|
|
|
|
Returns
|
|
-------
|
|
cmat = Cycle matrix. [nxn]
|
|
|
|
Example
|
|
--------
|
|
>>> import numpy as np
|
|
>>> cmat0 = np.round(np.triu(np.random.rand(4, 4), 1)*10)
|
|
>>> cmat0 = np.array([[ 0., 5., 6., 9.],
|
|
... [ 0., 0., 1., 7.],
|
|
... [ 0., 0., 0., 4.],
|
|
... [ 0., 0., 0., 0.]])
|
|
|
|
>>> nt = cmat2nt(cmat0)
|
|
>>> np.allclose(nt,
|
|
... [[ 0., 0., 0., 0.],
|
|
... [ 20., 15., 9., 0.],
|
|
... [ 28., 23., 16., 0.],
|
|
... [ 32., 27., 20., 0.]])
|
|
True
|
|
>>> cmat = nt2cmat(nt)
|
|
>>> np.allclose(cmat, [[ 0., 5., 6., 9.],
|
|
... [ 0., 0., 1., 7.],
|
|
... [ 0., 0., 0., 4.],
|
|
... [ 0., 0., 0., 0.]])
|
|
True
|
|
|
|
See also
|
|
--------
|
|
cmat2nt
|
|
"""
|
|
n = len(nt) # Number of discrete levels
|
|
if kind == 1:
|
|
I = np.r_[0:n - 1]
|
|
J = np.r_[1:n]
|
|
c = nt[I + 1][:, J - 1] - nt[I][:, J - 1] - nt[I + 1][:, J] + nt[I][:, J]
|
|
c2 = np.vstack((c, np.zeros((n - 1))))
|
|
cmat = np.hstack((np.zeros((n, 1)), c2))
|
|
elif kind == 11: # same as def=1 but using for-loop
|
|
cmat = np.zeros((n, n))
|
|
j = np.r_[1:n]
|
|
for i in range(n - 1):
|
|
cmat[i, j] = nt[i + 1, j - 1] - nt[i, j - 1] - nt[i + 1, j] + nt[i, j]
|
|
else:
|
|
_raise_kind_error(kind)
|
|
return cmat
|
|
|
|
|
|
def cmat2nt(cmat, kind=1):
|
|
"""
|
|
CMAT2NT Calculates a counting distribution from a cycle matrix.
|
|
|
|
Parameters
|
|
----------
|
|
cmat = Cycle matrix. [nxn]
|
|
kind = 1: causes peaks to be projected upwards and troughs
|
|
downwards to the closest discrete level (default).
|
|
= 0: causes peaks and troughs to be projected to
|
|
the closest discrete level.
|
|
= -1: causes peaks to be projected downwards and the
|
|
troughs upwards to the closest discrete level.
|
|
Returns
|
|
-------
|
|
NT: n x n array
|
|
Counting distribution.
|
|
|
|
Example
|
|
-------
|
|
>>> import numpy as np
|
|
>>> cmat0 = np.round(np.triu(np.random.rand(4, 4), 1)*10)
|
|
>>> cmat0 = np.array([[ 0., 5., 6., 9.],
|
|
... [ 0., 0., 1., 7.],
|
|
... [ 0., 0., 0., 4.],
|
|
... [ 0., 0., 0., 0.]])
|
|
|
|
>>> nt = cmat2nt(cmat0, kind=11)
|
|
>>> np.allclose(nt,
|
|
... [[ 0., 0., 0., 0.],
|
|
... [ 20., 15., 9., 0.],
|
|
... [ 28., 23., 16., 0.],
|
|
... [ 32., 27., 20., 0.]])
|
|
True
|
|
|
|
>>> cmat = nt2cmat(nt, kind=11)
|
|
>>> np.allclose(cmat, [[ 0., 5., 6., 9.],
|
|
... [ 0., 0., 1., 7.],
|
|
... [ 0., 0., 0., 4.],
|
|
... [ 0., 0., 0., 0.]])
|
|
True
|
|
|
|
See also
|
|
--------
|
|
nt2cmat
|
|
"""
|
|
n = len(cmat) # Number of discrete levels
|
|
nt = np.zeros((n, n))
|
|
|
|
if kind == 1:
|
|
csum = np.cumsum
|
|
flip = np.fliplr
|
|
nt[1:n, :n - 1] = flip(csum(flip(csum(cmat[:-1, 1:], axis=0)), axis=1))
|
|
elif kind == 11: # same as def=1 but using for-loop
|
|
# j = np.r_[1:n]
|
|
for i in range(1, n):
|
|
for j in range(n - 1):
|
|
nt[i, j] = np.sum(cmat[:i, j + 1:n])
|
|
else:
|
|
_raise_kind_error(kind)
|
|
return nt
|
|
|
|
|
|
def mctp2tc(f_Mm, utc, param, f_mM=None):
|
|
"""
|
|
MCTP2TC Calculates frequencies for the upcrossing troughs and crests
|
|
using Markov chain of turning points.
|
|
|
|
Parameters
|
|
----------
|
|
f_Mm = the frequency matrix for the Max2min cycles,
|
|
utc = the reference level,
|
|
param = a vector defining the discretization used to compute f_Mm,
|
|
note that f_mM has to be computed on the same grid as f_mM.
|
|
f_mM = the frequency matrix for the min2Max cycles.
|
|
|
|
Returns
|
|
-------
|
|
f_tc = the matrix with frequences of upcrossing troughs and crests,
|
|
|
|
Example
|
|
-------
|
|
>>> fmM = np.array([[ 0.0183, 0.0160, 0.0002, 0.0000, 0],
|
|
... [0.0178, 0.5405, 0.0952, 0, 0],
|
|
... [0.0002, 0.0813, 0, 0, 0],
|
|
... [0.0000, 0, 0, 0, 0],
|
|
... [ 0, 0, 0, 0, 0]])
|
|
>>> param = (-1, 1, len(fmM))
|
|
>>> utc = 0
|
|
>>> f_tc = mctp2tc(fmM, utc, param)
|
|
>>> np.allclose(f_tc,
|
|
... [[ 0.0, 1.59878359e-02, -1.87345256e-04, 0.0, 0.0],
|
|
... [ 0.0, 5.40312726e-01, 3.86782958e-04, 0.0, 0.0],
|
|
... [ 0.0, 0.0, 0.0, 0.0, 0.0],
|
|
... [ 0.0, 0.0, 0.0, 0.0, 0.0],
|
|
... [ 0.0, 0.0, 0.0, 0.0, 0.0]])
|
|
True
|
|
"""
|
|
def _check_ntc(ntc, n):
|
|
if ntc > n - 1:
|
|
raise IndexError('index for mean-level out of range, stop')
|
|
|
|
def _check_discretization(param, ntc):
|
|
if not (1 < ntc < param[2]):
|
|
raise ValueError('the reference level out of range, stop')
|
|
|
|
def _normalize_rows(arr):
|
|
n = len(arr)
|
|
for i in range(n):
|
|
rowsum = np.sum(arr[i])
|
|
if rowsum != 0:
|
|
arr[i] = arr[i] / rowsum
|
|
return arr
|
|
|
|
def _make_tempp(P, Ph, i, ntc):
|
|
Ap = P[i:ntc - 1, i + 1:ntc]
|
|
Bp = Ph[i + 1:ntc, i:ntc - 1]
|
|
dim_p = ntc - 1 - i
|
|
tempp = np.zeros((dim_p, 1))
|
|
I = np.eye(len(Ap))
|
|
if i == 1:
|
|
e = Ph[i + 1:ntc, 0]
|
|
else:
|
|
e = np.sum(Ph[i + 1:ntc, :i - 1], axis=1)
|
|
|
|
if max(abs(e)) > 1e-10:
|
|
if dim_p == 1:
|
|
tempp[0] = (Ap / (1 - Bp * Ap) * e)
|
|
else:
|
|
rh = I - np.dot(Bp, Ap)
|
|
tempp = np.dot(Ap, np.linalg.solve(rh, e))
|
|
|
|
# end
|
|
# end
|
|
return tempp
|
|
|
|
def _make_tempm(P, Ph, j, ntc, n):
|
|
Am = P[ntc - 1:j, ntc:j + 1]
|
|
Bm = Ph[ntc:j + 1, ntc - 1:j]
|
|
dim_m = j - ntc + 1
|
|
tempm = np.zeros((dim_m, 1))
|
|
Im = np.eye(len(Am))
|
|
if j == n - 1:
|
|
em = P[ntc - 1:j, n]
|
|
else:
|
|
em = np.sum(P[ntc - 1:j, j + 1:n], axis=1)
|
|
# end
|
|
if max(abs(em)) > 1e-10:
|
|
if dim_m == 1:
|
|
tempm[0] = (Bm / (1 - Am * Bm) * em)
|
|
else:
|
|
rh = Im - np.dot(Am, Bm)
|
|
tempm = np.dot(Bm, np.linalg.lstsq(rh, em)[0])
|
|
# end
|
|
# end
|
|
return tempm
|
|
|
|
if f_mM is None:
|
|
f_mM = np.copy(f_Mm) * 1.0
|
|
|
|
u = np.linspace(*param)
|
|
udisc = u[::-1] # np.fliplr(u)
|
|
ntc = np.sum(udisc >= utc)
|
|
n = len(f_Mm)
|
|
_check_ntc(ntc, n)
|
|
_check_discretization(param, ntc)
|
|
|
|
# normalization of frequency matrices
|
|
f_Mm = _normalize_rows(f_Mm)
|
|
P = np.fliplr(f_Mm)
|
|
Ph = np.rot90(np.fliplr(f_mM * 1.0), -1)
|
|
Ph = _normalize_rows(Ph)
|
|
Ph = np.fliplr(Ph)
|
|
|
|
F = np.zeros((n, n))
|
|
F[:ntc - 1, :(n - ntc)] = f_mM[:ntc - 1, :(n - ntc)]
|
|
F = cmat2nt(F)
|
|
|
|
for i in range(1, ntc):
|
|
for j in range(ntc - 1, n - 1):
|
|
if i < ntc - 1:
|
|
tempp = _make_tempp(P, Ph, i, ntc)
|
|
b = np.dot(np.dot(tempp.T, f_mM[i:ntc - 1, n - j - 2::-1]),
|
|
np.ones((n - j - 1, 1)))
|
|
# end
|
|
if j > ntc - 1:
|
|
tempm = _make_tempm(P, Ph, j, ntc, n)
|
|
c = np.dot(np.dot(np.ones((1, i)),
|
|
f_mM[:i, n - ntc - 1:n - j - 2:-1]),
|
|
tempm)
|
|
# end
|
|
if (j > ntc - 1) and (i < ntc - 1):
|
|
a = np.dot(np.dot(tempp.T,
|
|
f_mM[i:ntc - 1, n - ntc - 1:-1:n - j + 1]),
|
|
tempm)
|
|
F[i, n - j - 1] = F[i, n - j - 1] + a + b + c
|
|
# end
|
|
if (j == ntc - 1) and (i < ntc - 1):
|
|
F[i, n - ntc] = F[i, n - ntc] + b
|
|
for k in range(ntc):
|
|
F[i, n - k - 1] = F[i, n - ntc]
|
|
# end
|
|
# end
|
|
if (j > ntc - 1) and (i == ntc - 1):
|
|
F[i, n - j - 1] = F[i, n - j - 1] + c
|
|
for k in range(ntc - 1, n):
|
|
F[k, n - j - 1] = F[ntc - 1, n - j - 1]
|
|
# end
|
|
# end
|
|
# end
|
|
# end
|
|
|
|
# fmax=max(max(F));
|
|
# contour (u,u,flipud(F),...
|
|
# fmax*[0.005 0.01 0.02 0.05 0.1 0.2 0.4 0.6 0.8])
|
|
# axis([param(1) param(2) param(1) param(2)])
|
|
# title('Crest-trough density')
|
|
# ylabel('crest'), xlabel('trough')
|
|
# axis('square')
|
|
# if mlver>1, commers, end
|
|
return nt2cmat(F)
|
|
|
|
|
|
def mctp2rfc(fmM, fMm=None):
|
|
"""
|
|
Return Rainflow matrix given a Markov chain of turning points
|
|
|
|
computes f_rfc = f_mM + F_mct(f_mM).
|
|
|
|
Parameters
|
|
----------
|
|
fmM = the min2max Markov matrix,
|
|
fMm = the max2min Markov matrix,
|
|
|
|
Returns
|
|
-------
|
|
f_rfc = the rainflow matrix,
|
|
|
|
Example:
|
|
-------
|
|
>>> fmM = np.array([[ 0.0183, 0.0160, 0.0002, 0.0000, 0],
|
|
... [0.0178, 0.5405, 0.0952, 0, 0],
|
|
... [0.0002, 0.0813, 0, 0, 0],
|
|
... [0.0000, 0, 0, 0, 0],
|
|
... [ 0, 0, 0, 0, 0]])
|
|
|
|
>>> np.allclose(mctp2rfc(fmM),
|
|
... [[ 2.669981e-02, 7.799700e-03, 4.906077e-07, 0.0, 0.0],
|
|
... [ 9.599629e-03, 5.485009e-01, 9.539951e-02, 0.0, 0.0],
|
|
... [ 5.622974e-07, 8.149944e-02, 0.0, 0.0, 0.0],
|
|
... [ 0.0, 0.0, 0.0, 0.0, 0.0],
|
|
... [ 0.0, 0.0, 0.0, 0.0, 0.0]], 1.e-7)
|
|
True
|
|
"""
|
|
def _get_PMm(AA1, MA, nA):
|
|
PMm = AA1.copy()
|
|
for j in range(nA):
|
|
norm = MA[j]
|
|
if norm != 0:
|
|
PMm[j, :] = PMm[j, :] / norm
|
|
PMm = np.fliplr(PMm)
|
|
return PMm
|
|
|
|
if fMm is None:
|
|
fmM = np.atleast_1d(fmM)
|
|
fMm = fmM
|
|
else:
|
|
fmM, fMm = np.atleast_1d(fmM, fMm)
|
|
f_mM, f_Mm = fmM.copy(), fMm.copy()
|
|
N = max(f_mM.shape)
|
|
f_max = np.sum(f_mM, axis=1)
|
|
f_min = np.sum(f_mM, axis=0)
|
|
f_rfc = np.zeros((N, N))
|
|
f_rfc[N - 2, 0] = f_max[N - 2]
|
|
f_rfc[0, N - 2] = f_min[N - 2]
|
|
for k in range(2, N - 1):
|
|
for i in range(1, k):
|
|
AA = f_mM[N - 1 - k:N - 1 - k + i, k - i:k]
|
|
AA1 = f_Mm[N - 1 - k:N - 1 - k + i, k - i:k]
|
|
RAA = f_rfc[N - 1 - k:N - 1 - k + i, k - i:k]
|
|
nA = max(AA.shape)
|
|
MA = f_max[N - 1 - k:N - 1 - k + i]
|
|
mA = f_min[k - i:k]
|
|
SA = AA.sum()
|
|
SRA = RAA.sum()
|
|
|
|
DRFC = SA - SRA
|
|
NT = min(mA[0] - sum(RAA[:, 0]), MA[0] - sum(RAA[0, :])) # check!
|
|
NT = max(NT, 0) # ??check
|
|
|
|
if NT > 1e-6 * max(MA[0], mA[0]):
|
|
NN = MA - np.sum(AA, axis=1) # T
|
|
e = (mA - np.sum(AA, axis=0)) # T
|
|
e = np.flipud(e)
|
|
PmM = np.rot90(AA.copy())
|
|
for j in range(nA):
|
|
norm = mA[nA - 1 - j]
|
|
if norm != 0:
|
|
PmM[j, :] = PmM[j, :] / norm
|
|
e[j] = e[j] / norm
|
|
# end
|
|
# end
|
|
fx = 0.0
|
|
if (max(np.abs(e)) > 1e-6 and
|
|
max(np.abs(NN)) > 1e-6 * max(MA[0], mA[0])):
|
|
PMm = _get_PMm(AA1, MA, nA)
|
|
|
|
A = PMm
|
|
B = PmM
|
|
|
|
if nA == 1:
|
|
fx = NN * (A / (1 - B * A) * e)
|
|
else:
|
|
rh = np.eye(A.shape[0]) - np.dot(B, A)
|
|
# least squares
|
|
fx = np.dot(NN, np.dot(A, np.linalg.solve(rh, e)))
|
|
# end
|
|
# end
|
|
f_rfc[N - 1 - k, k - i] = fx + DRFC
|
|
|
|
# check2=[ DRFC fx]
|
|
# pause
|
|
else:
|
|
f_rfc[N - 1 - k, k - i] = 0.0
|
|
# end
|
|
# end
|
|
m0 = max(0, f_min[0] - np.sum(f_rfc[N - k + 1:N, 0]))
|
|
M0 = max(0, f_max[N - 1 - k] - np.sum(f_rfc[N - 1 - k, 1:k]))
|
|
f_rfc[N - 1 - k, 0] = min(m0, M0)
|
|
# n_loops_left=N-k+1
|
|
# end
|
|
|
|
for k in range(1, N):
|
|
M0 = max(0, f_max[0] - np.sum(f_rfc[0, N - k:N]))
|
|
m0 = max(0, f_min[N - 1 - k] - np.sum(f_rfc[1:k + 1, N - 1 - k]))
|
|
f_rfc[0, N - 1 - k] = min(m0, M0)
|
|
# end
|
|
|
|
# clf
|
|
# subplot(1,2,2)
|
|
# pcolor(levels(paramm),levels(paramM),flipud(f_mM))
|
|
# title('Markov matrix')
|
|
# ylabel('max'), xlabel('min')
|
|
# axis([paramm(1) paramm(2) paramM(1) paramM(2)])
|
|
# axis('square')
|
|
#
|
|
# subplot(1,2,1)
|
|
# pcolor(levels(paramm),levels(paramM),flipud(f_rfc))
|
|
# title('Rainflow matrix')
|
|
# ylabel('max'), xlabel('rfc-min')
|
|
# axis([paramm(1) paramm(2) paramM(1) paramM(2)])
|
|
# axis('square')
|
|
|
|
return f_rfc
|
|
|
|
|
|
def mc2rfc(f_xy, paramv=None, paramu=None):
|
|
"""
|
|
MC2RFC Calculates a rainflow matrix given a Markov chain with kernel f_xy;
|
|
f_rfc = f_xy + F_mc(f_xy).
|
|
|
|
CALL: f_rfc = mc2rfc(f_xy);
|
|
|
|
where
|
|
|
|
f_rfc = the rainflow matrix,
|
|
f_xy = the frequency matrix of Markov chain (X0,X1)
|
|
but only the triangular part for X1>X0.
|
|
|
|
Further optional input arguments;
|
|
|
|
CALL: f_rfc = mc2rfc(f_xy,paramx,paramy);
|
|
|
|
paramx = the parameter matrix defining discretization of x-values,
|
|
paramy = the parameter matrix defining discretization of y-values,
|
|
"""
|
|
N = len(f_xy)
|
|
if paramv is None:
|
|
paramv = (-1, 1, N)
|
|
|
|
if paramu is None:
|
|
paramu = paramv
|
|
|
|
dd = np.diag(np.rot90(f_xy))
|
|
Splus = np.sum(f_xy, axis=1).T
|
|
Sminus = np.fliplr(sum(f_xy))
|
|
Max_rfc = np.zeros((N, 1))
|
|
Min_rfc = np.zeros((N, 1))
|
|
norm = np.zeros((N, 1))
|
|
for i in range(N):
|
|
Spm = Sminus[i] + Splus[i] - dd[i]
|
|
if Spm > 0:
|
|
Max_rfc[i] = (Splus[i] - dd[i]) * \
|
|
(Splus[i] - dd[i]) / (1 - dd[i] / Spm) / Spm
|
|
Min_rfc[i] = (Sminus[i] - dd[i]) * \
|
|
(Sminus[i] - dd[i]) / (1 - dd[i] / Spm) / Spm
|
|
norm[i] = Spm
|
|
# end if
|
|
# end for
|
|
|
|
# cross=zeros(N,1)
|
|
# for i=2:N
|
|
# cross(N-i+1)=cross(N-i+2)+Sminus(N-i+2)-Splus(N-i+2)
|
|
# end
|
|
|
|
f_rfc = np.zeros((N, N))
|
|
f_rfc[N - 1, 1] = Max_rfc[N - 1]
|
|
f_rfc[1, N - 1] = Min_rfc[2]
|
|
|
|
for k in range(2, N - 1):
|
|
for i in range(1, k - 1):
|
|
|
|
# AAe= f_xy(1:N-k,1:k-i)
|
|
# SAAe=sum(sum(AAe))
|
|
AA = f_xy[N - k:N - k + i, :][:, k - i:k]
|
|
# RAA = f_rfc(N-k+1:N-k+i,k-i+1:k)
|
|
RAA = f_rfc[N - k:N - k + i, :][:, k - i:k]
|
|
nA = len(AA)
|
|
# MA = Splus(N-k+1:N-k+i)
|
|
MA = Splus[N - k:N - k + i]
|
|
mA = Sminus[N - k:N - k + i]
|
|
normA = norm[N - k:N - k + i]
|
|
MA_rfc = Max_rfc[N - k:N - k + i]
|
|
# mA_rfc=Min_rfc(k-i+1:k)
|
|
SA = np.sum(AA)
|
|
SRA = np.sum(RAA)
|
|
SMA_rfc = sum(MA_rfc)
|
|
SMA = np.sum(MA)
|
|
DRFC = SA - SMA - SRA + SMA_rfc
|
|
|
|
NT = MA_rfc[0] - np.sum(RAA[0, :])
|
|
|
|
# if k==35
|
|
# check=[MA_rfc(1) sum(RAA(1,:))]
|
|
# pause
|
|
# end
|
|
|
|
NT = np.maximum(NT, 0)
|
|
|
|
if NT > 1e-6 * MA_rfc[0]:
|
|
|
|
NN = MA - np.sum(AA, axis=1).T
|
|
e = (np.fliplr(mA) - np.sum(AA)).T
|
|
e = np.flipud(e)
|
|
AA = AA + np.flipud(np.rot90(AA, -1))
|
|
AA = np.rot90(AA)
|
|
AA = AA - 0.5 * np.diag(np.diag(AA))
|
|
|
|
for j in range(nA):
|
|
if normA[j] != 0:
|
|
AA[j, :] = AA[j, :] / normA[j]
|
|
e[j] = e[j] / normA[j]
|
|
# end if
|
|
# end for
|
|
fx = 0.
|
|
|
|
if np.max(
|
|
np.abs(e)) > 1e-7 and np.max(np.abs(NN)) > 1e-7 * MA_rfc[0]:
|
|
I = np.eye(np.shape(AA))
|
|
|
|
if nA == 1:
|
|
fx = NN / (1 - AA) * e
|
|
else:
|
|
# TODO CHECK this
|
|
fx = NN * np.linalg.solve((I - AA), e)[0] # (I-AA)\e
|
|
# end
|
|
# end
|
|
|
|
f_rfc[N - k, k - i] = DRFC + fx
|
|
# end
|
|
# end
|
|
m0 = np.maximum(0, Min_rfc[N] - sum(f_rfc[N - k + 1:N, 0]))
|
|
M0 = np.maximum(0, Max_rfc[N - k] - sum(f_rfc[N - k, 1:k]))
|
|
f_rfc[N - k, 0] = min(m0, M0)
|
|
# n_loops_left=N-k+1
|
|
# end for
|
|
|
|
for k in range(1, N):
|
|
M0 = max(0, Max_rfc[0] - sum(f_rfc[0, N - k + 1:N]))
|
|
m0 = max(0, Min_rfc[k] - sum(f_rfc[1:k, N - k]))
|
|
f_rfc[0, N - k] = min(m0, M0)
|
|
# end for
|
|
f_rfc = f_rfc + np.rot90(np.diag(dd), -1)
|
|
|
|
# clf
|
|
# subplot(1,2,2)
|
|
# pcolor(levels(paramv),levels(paramu),flipud(f_xy+flipud(rot90(f_xy,-1))))
|
|
# axis([paramv(1), paramv(2), paramu(1), paramu(2)])
|
|
# title('MC-kernel f(x,y)')
|
|
# ylabel('y'), xlabel('x')
|
|
# axis('square')
|
|
#
|
|
# subplot(1,2,1)
|
|
# pcolor(levels(paramv),levels(paramu),flipud(f_rfc))
|
|
# axis([paramv(1), paramv(2), paramu(1), paramu(2)])
|
|
# title('Rainflow matrix')
|
|
# ylabel('max'), xlabel('rfc-min')
|
|
# axis('square')
|
|
|
|
return f_rfc
|
|
|
|
|
|
def mktestmat(param=(-1, 1, 32), x0=None, s=None, lam=1, numsubzero=0):
|
|
"""
|
|
|
|
MKTESTMAT Makes test matrices for min-max (and max-min) matrices.
|
|
|
|
Parameters
|
|
----------
|
|
param = Parameter vector, [a b n], defines discretization.
|
|
x0 = Center of ellipse. [min Max] [1x2]
|
|
s = Standard deviation. (0<s<infinity) [1x1]
|
|
lam = Orientation of ellipse. (0<lam<infinity) [1x1]
|
|
lam=1 gives circles.
|
|
numsubzero = Number of subdiagonals that are set to zero
|
|
(-Inf: no subdiagonals that are set to zero)
|
|
(Optional, Default = 0, only the diagonal is zero)
|
|
|
|
Returns
|
|
-------
|
|
F = min-max matrix. [nxn]
|
|
Fh = max-min matrix. [nxn]
|
|
|
|
Makes a Normal kernel (Iso-lines are ellipses).
|
|
Each element in F =(F(i,j)) is
|
|
F[i,j] = exp(-1/2*(x-x0)*inv(S)*(x-x0));
|
|
where
|
|
S = 1/2*s**2*[lam**2+1 lam**2-1; lam**2-1 lam**2+1]
|
|
|
|
The matrix Fh is obtained by assuming a time-reversible process.
|
|
These matrices can be used for testing.
|
|
|
|
Example
|
|
-------
|
|
>>> import numpy as np
|
|
>>> param = [-1, 1, 32]
|
|
>>> F, Fh = mktestmat(param, x0=[-0.2, 0.2], s=0.25, lam=0.5)
|
|
>>> np.allclose(F[0,:4],
|
|
... [ 8.45677332e-29, 5.94193456e-27, 3.53462989e-25, 1.78013497e-23])
|
|
True
|
|
|
|
>>> u = np.linspace(*param)
|
|
|
|
cmatplot(u,u,F,3)
|
|
axis('square')
|
|
>>> F, Fh = mktestmat(param, x0=[-0.2, 0.2], s=0.25, lam=0.5, numsubzero=-np.inf)
|
|
>>> np.allclose(F[0,:4],
|
|
... [ 8.45677332e-29, 5.94193456e-27, 3.53462989e-25, 1.78013497e-23])
|
|
True
|
|
|
|
cmatplot(u,u,F,3); axis('square');
|
|
|
|
close all;
|
|
"""
|
|
# History:
|
|
# Revised by PJ 23-Nov-1999
|
|
# updated for WAFO
|
|
# Created by PJ (Paer Johannesson) 1997
|
|
# Copyright (c) 1997 by Paer Johannesson
|
|
# Toolbox: Rainflow Cycles for Switching Processes V.1.0, 2-Oct-1997
|
|
|
|
if x0 is None:
|
|
x0 = np.ones((2,)) * (param[1] + param[0]) / 2
|
|
if s is None:
|
|
s = (param[1] - param[0]) / 4
|
|
|
|
if np.isinf(numsubzero):
|
|
numsubzero = -(param[2] + 1)
|
|
|
|
u = np.linspace(*param)
|
|
n = param[2]
|
|
|
|
# F - min-Max matrix
|
|
|
|
F = np.zeros((n, n))
|
|
S = 1 / 2 * s**2 * np.array([[lam**2 + 1, lam**2 - 1],
|
|
[lam**2 - 1, lam**2 + 1]])
|
|
Sm1 = np.linalg.pinv(S)
|
|
for i in range(min(n - 1 - numsubzero, n)):
|
|
for j in range(max(i + numsubzero, 0), n):
|
|
dx = np.array([u[i], u[j]]) - x0
|
|
F[i, j] = np.exp(-1 / 2 * np.dot(np.dot(dx, Sm1), dx))
|
|
|
|
Fh = F.T # Time-reversible Max-min matrix
|
|
return F, Fh
|
|
|
|
|
|
def cmatplot(cmat, ux=None, uy=None, method=1, clevels=None):
|
|
"""
|
|
CMATPLOT Plots a cycle matrix, e.g. a rainflow matrix.
|
|
|
|
CALL: cmatplot(F)
|
|
cmatplot(F,method)
|
|
cmatplot(ux,uy,F)
|
|
cmatplot(ux,uy,F,method)
|
|
|
|
F = Cycle matrix (e.g. rainflow matrix) [nxm]
|
|
method = 1: mesh-plot (default)
|
|
2: surf-plot
|
|
3: pcolor-plot [axis('square')]
|
|
4: contour-plot [axis('square')]
|
|
5: TechMath-plot [axis('square')]
|
|
11: From-To, mesh-plot
|
|
12: From-To, surf-plot
|
|
13: From-To, pcolor-plot [axis('square')]
|
|
14: From-To, contour-plot [axis('square')]
|
|
15: From-To, TechMath-plot [axis('square')]
|
|
ux = x-axis (default: 1:m)
|
|
uy = y-axis (default: 1:n)
|
|
|
|
Examples:
|
|
param = [-1 1 64]; u=levels(param);
|
|
F = mktestmat(param,[-0.2 0.2],0.25,1/2);
|
|
cmatplot(F,method=1);
|
|
cmatplot(u,u,F,method=2); colorbar;
|
|
cmatplot(u,u,F,method=3); colorbar;
|
|
cmatplot(u,u,F,method=4);
|
|
|
|
close all;
|
|
|
|
See also
|
|
--------
|
|
cocc, plotcc
|
|
"""
|
|
|
|
F = cmat
|
|
shape = np.shape(F)
|
|
if ux is None:
|
|
ux = np.arange(shape[1]) # Antalet kolumner
|
|
|
|
if uy is None:
|
|
uy = np.arange(shape[0]) # Antalet rader
|
|
|
|
if clevels is None:
|
|
Fmax = np.max(F)
|
|
if method in [5, 15]:
|
|
clevels = Fmax * np.r_[0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0]
|
|
else: # 4, 14
|
|
clevels = Fmax * np.r_[0.005,
|
|
0.01,
|
|
0.02,
|
|
0.05,
|
|
0.1,
|
|
0.2,
|
|
0.4,
|
|
0.6,
|
|
0.8]
|
|
|
|
# Make sure ux and uy are row vectors
|
|
ux = ux.ravel()
|
|
uy = uy.ravel()
|
|
|
|
n = len(F)
|
|
|
|
from matplotlib import pyplot as plt
|
|
if method == 1: # mesh
|
|
F = np.flipud(F.T) # Vrid cykelmatrisen for att plotta rett
|
|
plt.mesh(ux, np.fliplr(uy), F)
|
|
plt.xlabel('min')
|
|
plt.ylabel('Max')
|
|
# view(-37.5-90,30);
|
|
# v = axis;
|
|
# plt.axis([min(ux) max(ux) min(uy) max(uy) v[5:6]]);
|
|
elif method == 2: # surf
|
|
F = np.flipud(F.T) # Vrid cykelmatrisen for att plotta rett
|
|
plt.surf(ux, np.fliplr(uy), F)
|
|
plt.xlabel('min')
|
|
plt.ylabel('Max')
|
|
# view(-37.5-90,30);
|
|
# v = axis;
|
|
# plt.axis([min(ux) max(ux) min(uy) max(uy) v(5:6)]);
|
|
# elseif method == 3 # pcolor
|
|
# F = flipud(F');
|
|
# F1 = [F zeros(length(uy),1); zeros(1,length(ux)+1)];
|
|
# F2 = F1; F2(F2==0)=NaN;
|
|
# F1 = F2;
|
|
# dx=ux(2)-ux(1); dy=uy(2)-uy(1);
|
|
# ux1 = [ux ux(length(ux))+dx] - dx/2;
|
|
# uy1 = [uy uy(length(uy))+dy] - dy/2;
|
|
# pcolor(ux1,fliplr(uy1),F1);
|
|
# xlabel('min');
|
|
# ylabel('Max');
|
|
# v = axis; axis([min(ux1) max(ux1) min(uy1) max(uy1)]);
|
|
# axis('square')
|
|
# elseif method == 4 # contour
|
|
# F = flipud(F');
|
|
# if isempty(clevels)
|
|
# Fmax=max(max(F));
|
|
# clevels=Fmax*[0.005 0.01 0.02 0.05 0.1 0.2 0.4 0.6 0.8];
|
|
# end
|
|
# contour(ux,fliplr(uy),F,clevels);
|
|
# xlabel('min');
|
|
# ylabel('Max');
|
|
# v = axis; axis([min(ux) max(ux) min(uy) max(uy)]);
|
|
# axis('square');
|
|
#
|
|
# # Cstr=num2str(clevels(1),4);
|
|
# # for i=2:length(clevels)
|
|
# # Cstr=[Cstr ',' num2str(clevels(i),4)];
|
|
# # end
|
|
# # title(['ISO-lines: ' Cstr])
|
|
#
|
|
# if 1==2
|
|
# clevels=sort(clevels);
|
|
# n_clevels=length(clevels);
|
|
# if n_clevels>12
|
|
# disp(' Only the first 12 levels will be listed in table.')
|
|
# n_clevels=12;
|
|
# end
|
|
#
|
|
# textstart_x=0.65;
|
|
# textstart_y=0.45;
|
|
# delta_y=1/33;
|
|
# h=figtext(textstart_x,textstart_y,'Level curves at:','normalized');
|
|
# set(h,'FontWeight','Bold')
|
|
#
|
|
# textstart_y=textstart_y-delta_y;
|
|
#
|
|
# for i=1:n_clevels
|
|
# textstart_y=textstart_y-delta_y;
|
|
# figtext(textstart_x,textstart_y,num2str(clevels(i)),'normalized')
|
|
# end
|
|
# end # 1==2
|
|
#
|
|
# elseif method == 5 | method == 15 # TechMath-typ
|
|
#
|
|
# if isempty(clevels)
|
|
# Fmax=max(max(F));
|
|
# clevels=Fmax*[0.001 0.005 0.01 0.05 0.1 0.5 1.0];
|
|
# end
|
|
# v=clevels;
|
|
# # axis('ij');
|
|
# sym = '...x+***';
|
|
# sz = [6 20 24 8 8 8 12 16];
|
|
#
|
|
# # plot(-1,-1,sym(1),'markersize',1),hold on
|
|
# for i = 1:length(v)
|
|
# plot(-1,-1,sym(i),'markersize',sz(i));hold on;
|
|
# end
|
|
#
|
|
# for i = 1:length(v)-1
|
|
# Ind = (F>v(i)) & (F<=v(i+1));
|
|
# [I,J] = find(Ind);
|
|
# # axis('ij');
|
|
# plot(I,J,sym(i),'markersize',sz(i));hold on;
|
|
# end
|
|
# plot([1 n],[1 n],'--'); grid;
|
|
# hold off;
|
|
#
|
|
# axis([0.5 n+0.5 0.5 n+0.5]);
|
|
#
|
|
# #legendText = sprintf('#6g < f <= %6g\n',[v(1:nv-1); v(2:nv)])
|
|
# #legendText = sprintf('<= %g\n',v(2:end))
|
|
#
|
|
# legendText=num2str(v(1:end)');
|
|
#
|
|
# legend(legendText,-1);
|
|
#
|
|
# title('From-To plot');
|
|
# xlabel('To / Standing');
|
|
# ylabel('From / Hanging');
|
|
#
|
|
# if method == 15
|
|
# axis('ij');
|
|
# end
|
|
#
|
|
# elseif method == 11 # mesh
|
|
#
|
|
# mesh(ux,uy,F);
|
|
# axis('ij');
|
|
# xlabel('To');
|
|
# ylabel('From');
|
|
# view(-37.5-90,30);
|
|
# v = axis; axis([min(ux) max(ux) min(uy) max(uy) v(5:6)]);
|
|
#
|
|
# elseif method == 12 # surf
|
|
#
|
|
# surf(ux,uy,F);
|
|
# axis('ij');
|
|
# xlabel('To');
|
|
# ylabel('From');
|
|
# view(-37.5-90,30);
|
|
# v = axis; axis([min(ux) max(ux) min(uy) max(uy) v(5:6)]);
|
|
#
|
|
# elseif method == 13 # From-To-Matrix - pcolor
|
|
#
|
|
# F1 = [F zeros(length(uy),1); zeros(1,length(ux)+1)];
|
|
# F2 = F1; F2(F2==0)=NaN;
|
|
# F1 = F2;
|
|
# dx=ux(2)-ux(1); dy=uy(2)-uy(1);
|
|
# ux1 = [ux ux(length(ux))+dx] - dx/2;
|
|
# uy1 = [uy uy(length(uy))+dy] - dy/2;
|
|
# axis('ij');
|
|
# pcolor(ux1,uy1,F1)
|
|
# axis('ij');
|
|
# xlabel('To');
|
|
# ylabel('From');
|
|
# v = axis; axis([min(ux1) max(ux1) min(uy1) max(uy1)]);
|
|
# axis('square')
|
|
#
|
|
# elseif method == 14 # contour
|
|
# if isempty(clevels)
|
|
# Fmax=max(max(F));
|
|
# clevels=Fmax*[0.005 0.01 0.02 0.05 0.1 0.2 0.4 0.6 0.8];
|
|
# end
|
|
# contour(ux,uy,F,clevels);
|
|
# axis('ij');
|
|
# xlabel('To');
|
|
# ylabel('From');
|
|
# v = axis; axis([min(ux) max(ux) min(uy) max(uy)]);
|
|
# axis('square');
|
|
|
|
# # Cstr=num2str(clevels(1),4);
|
|
# # for i=2:length(clevels)
|
|
# # Cstr=[Cstr ',' num2str(clevels(i),4)];
|
|
# # end
|
|
# # title(['ISO-lines: ' Cstr])
|
|
#
|
|
# if 1==1
|
|
# clevels=sort(clevels);
|
|
# n_clevels=length(clevels);
|
|
# if n_clevels>12
|
|
# disp(' Only the first 12 levels will be listed in table.');
|
|
# n_clevels=12;
|
|
# end
|
|
#
|
|
# textstart_x=0.10;
|
|
# textstart_y=0.45;
|
|
# delta_y=1/33;
|
|
# h=figtext(textstart_x,textstart_y,'Level curves at:','normalized');
|
|
# set(h,'FontWeight','Bold')
|
|
#
|
|
# textstart_y=textstart_y-delta_y;
|
|
#
|
|
# for i=1:n_clevels
|
|
# textstart_y=textstart_y-delta_y;
|
|
# figtext(textstart_x,textstart_y,num2str(clevels(i)),'normalized')
|
|
# end
|
|
# end
|
|
#
|
|
# elseif method == 15 # TechMath-typ
|
|
# # See: 'method == 5'
|
|
#
|
|
# # if isempty(clevels)
|
|
# # Fmax=max(max(F));
|
|
# # clevels=Fmax*[0.005 0.01 0.05 0.1 0.4 0.8];
|
|
# # end
|
|
# # v=clevels;
|
|
# # axis('ij');
|
|
# # sym = '...***';
|
|
# # sz = [8 12 16 8 12 16]
|
|
# # for i = 1:length(v)-1
|
|
# # Ind = (F>v(i)) & (F<=v(i+1));
|
|
# # [I,J] = find(Ind);
|
|
# # axis('ij');
|
|
# # plot(J,I,sym(i),'markersize',sz(i)),hold on
|
|
# # end
|
|
# # hold off
|
|
# #
|
|
# # axis([0.5 n+0.5 0.5 n+0.5])
|
|
# #
|
|
# # %legendText = sprintf('%6g < f <= %6g\n',[v(1:nv-1); v(2:nv)])
|
|
# # legendText = sprintf('<= %g\n',v(2:nv))
|
|
# #
|
|
# # %legendText=num2str(v(2:nv)')
|
|
# #
|
|
# # legend(legendText,-1)
|
|
#
|
|
# end
|
|
#
|
|
# end % _cmatplot
|
|
|
|
|
|
def arfm2mctp(Frfc):
|
|
"""
|
|
ARFM2MCTP Calculates the markov matrix given an asymmetric rainflow matrix.
|
|
|
|
CALL: F = arfm2mctp(Frfc);
|
|
|
|
F = Markov matrix (from-to-matrix) [n,n]
|
|
Frfc = Rainflow Matrix [n,n]
|
|
|
|
Examples
|
|
--------
|
|
param = [-1 1 32];
|
|
u = levels(param);
|
|
F = mktestmat(param,[-0.2 0.2],0.15,2);
|
|
F = F/sum(sum(F));
|
|
Farfc = mctp2arfm({F []});
|
|
F1 = arfm2mctp(Farfc);
|
|
cmatplot(u,u,{F+F' F1},3);
|
|
assert(F1(20,21:25), [0.00209800691364310, 0.00266223402503216,...
|
|
0.00300934711658560, 0.00303029619424592,...
|
|
0.00271822008031848], 1e-10);
|
|
assert(sum(sum(abs(F1-(F+F')))), 0, 1e-10) should be zero
|
|
|
|
close all;
|
|
|
|
See also
|
|
--------
|
|
rfm2mctp, mctp2arfm, smctp2arfm, cmatplot
|
|
|
|
References
|
|
----------
|
|
P. Johannesson (1999):
|
|
Rainflow Analysis of Switching Markov Loads.
|
|
PhD thesis, Mathematical Statistics, Centre for Mathematical Sciences,
|
|
Lund Institute of Technology.
|
|
"""
|
|
# Tested on Matlab 5.3
|
|
#
|
|
# History:
|
|
# Revised by PJ 09-Apr-2001
|
|
# updated for WAFO
|
|
|
|
# Copyright (c) 1997-1998 by Pear Johannesson
|
|
# Toolbox: Rainflow Cycles for Switching Processes V.1.1, 22-Jan-1998
|
|
|
|
# Recursive formulation a'la Igor
|
|
#
|
|
# This program used the formulation where the probabilities
|
|
# of the events are calculated using "elementary" events for
|
|
# the MCTP.
|
|
#
|
|
# Standing
|
|
# pS = Max*pS1*pS2*pS3;
|
|
# F_rfc(i,j) = pS;
|
|
# Hanging
|
|
# pH = Min*pH1*pH2*pH3;
|
|
# F_rfc(j,i) = pH;
|
|
#
|
|
# The cond. prob. pS1, pS2, pS3, pH1, pH2, pH3 are calculated using
|
|
# the elementary cond. prob. C, E, R, D, E3, Ch, Eh, Rh, Dh, E3h.
|
|
|
|
# T(1,:)=clock;
|
|
|
|
N = np.sum(Frfc)
|
|
Frfc = Frfc / N
|
|
|
|
n = len(Frfc) # Number of levels
|
|
|
|
# T(7,:)=clock;
|
|
# Transition matrices for MC
|
|
|
|
Q = np.zeros((n, n))
|
|
Qh = np.zeros((n, n))
|
|
|
|
# Transition matrices for time-reversed MC
|
|
|
|
Qr = np.zeros((n, n))
|
|
Qrh = np.zeros((n, n))
|
|
|
|
# Probability of minimum and of maximun
|
|
|
|
MIN = np.sum(np.triu(Frfc).T, axis=0) + np.sum(np.tril(Frfc), axis=0)
|
|
MAX = np.sum(np.triu(Frfc), axis=0) + np.sum(np.tril(Frfc).T, axis=0)
|
|
|
|
# Calculate rainflow matrix
|
|
|
|
F = np.zeros((n, n))
|
|
EYE = np.eye((n, n))
|
|
|
|
# fprintf(1,'Calculating row ');
|
|
for k in range(n - 1): # k = subdiagonal
|
|
# fprintf(1,'-%1d',i);
|
|
|
|
for i in range(n - k): # i = minimum
|
|
|
|
j = i + k + 1 # maximum;
|
|
|
|
# pS = Frfc(i,j); # Standing cycle
|
|
# pH = Frfc(j,i); # Hanging cycle
|
|
#
|
|
# Min = MIN[i]
|
|
# Max = MAX[j]
|
|
#
|
|
# # fprintf(1,'Min=%f, Max=%f\n',Min,Max);
|
|
#
|
|
#
|
|
# if j - i == 2: # Second subdiagonal
|
|
#
|
|
# # For Part 1 & 2 of cycle
|
|
#
|
|
# #C = y/Min;
|
|
# c0 = 0;
|
|
# c1 = 1/Min;
|
|
# #Ch = x/Max;
|
|
# c0h = 0;
|
|
# c1h = 1/Max;
|
|
# d1 = Qr(i,i+1)*(1-Qrh(i+1,i));
|
|
# D = d1;
|
|
# d1h = Qrh(j,j-1)*(1-Qr(j-1,j));
|
|
# Dh = d1h;
|
|
# d0 = sum(Qr(i,i+1:j-1));
|
|
# #E = 1-d0-y/Min;
|
|
# e0 = 1-d0;
|
|
# e1 = -1/Min;
|
|
# d0h = sum(Qrh(j,i+1:j-1));
|
|
# #Eh = 1-d0h-x/Max;
|
|
# e0h = 1-d0h;
|
|
# e1h = -1/Max;
|
|
# r1 = Qr(i,i+1)*Qrh(i+1,i);
|
|
# R = r1;
|
|
# r1h = Qrh(j,j-1)*Qr(j-1,j);
|
|
# Rh = r1h;
|
|
#
|
|
# # For Part 3 of cycle
|
|
#
|
|
# d3h = sum(Qh(j,i+1:j-1));
|
|
# E3h = 1-d3h;
|
|
# d3 = sum(Q(i,i+1:j-1));
|
|
# E3 = 1-d3;
|
|
#
|
|
# # Define coeficients for equation system
|
|
# a0 = -pS+2*pS*Rh-pS*Rh^2+pS*R-2*pS*Rh*R+pS*Rh^2*R;
|
|
# a1 = -E3h*Max*c1h*e0*Rh+E3h*Max*c1h*e0;
|
|
# a3 = -E3h*Max*c1h*e1*Rh+E3h*Max*c1h*Dh*c1+E3h*Max*c1h*e1+pS*c1h*c1-pS*c1h*c1*Rh;
|
|
#
|
|
# b0 = -pH+2*pH*R+pH*Rh-2*pH*Rh*R-pH*R^2+pH*Rh*R^2;
|
|
# b2 = -Min*E3*e0h*R*c1+Min*E3*e0h*c1;
|
|
# b3 = Min*E3*e1h*c1+Min*E3*D*c1h*c1-pH*c1h*c1*R-Min*E3*e1h*R*c1+pH*c1h*c1;
|
|
#
|
|
# C2 = a3*b2;
|
|
# C1 = (-a0*b3+a1*b2+a3*b0);
|
|
# C0 = a1*b0;
|
|
# # Solve: C2*z^2 + C1*z + C0 = 0
|
|
# z1 = -C1/2/C2 + sqrt((C1/2/C2)^2-C0/C2);
|
|
# z2 = -C1/2/C2 - sqrt((C1/2/C2)^2-C0/C2);
|
|
#
|
|
# # Solution 1
|
|
# x1 = -(b0+b2*z1)/(b3*z1);
|
|
# y1 = z1;
|
|
# # Solution 2
|
|
# x2 = -(b0+b2*z2)/(b3*z2);
|
|
# y2 = z2;
|
|
#
|
|
# x = x2;
|
|
# y = y2;
|
|
#
|
|
# # fprintf(1,'2nd: i=%d, j=%d: x1=%f, y1=%f, x2=%f, y2=%f\n',i,j,x1,y1,x2,y2);
|
|
#
|
|
# # Test Standing cycle: assume x=y
|
|
#
|
|
# C0 = a0; C1 = a1; C2 = a3;
|
|
# z1S = -C1/2/C2 + sqrt((C1/2/C2)^2-C0/C2);
|
|
# z2S = -C1/2/C2 - sqrt((C1/2/C2)^2-C0/C2);
|
|
#
|
|
# # Test Hanging cycle: assume x=y
|
|
#
|
|
# C0 = b0; C1 = b2; C2 = b3;
|
|
# z1H = -C1/2/C2 + sqrt((C1/2/C2)^2-C0/C2);
|
|
# z2H = -C1/2/C2 - sqrt((C1/2/C2)^2-C0/C2);
|
|
#
|
|
# # fprintf(1,'2nd: i=%d, j=%d: z1S=%f,: z2S=%f, z1H=%f, z2H=%f\n',i,j,z1S,z2S,z1H,z2H);
|
|
#
|
|
# else
|
|
#
|
|
# Eye = EYE(1:j-i-2,1:j-i-2);
|
|
#
|
|
# # For Part 1 & 2 of cycle
|
|
#
|
|
# I = i+1:j-2;
|
|
# J = i+2:j-1;
|
|
# A = Qr(I,J);
|
|
# Ah = Qrh(J,I);
|
|
# a = Qr(i,J);
|
|
# ah = Qrh(j,I);
|
|
# b = Qr(I,j);
|
|
# bh = Qrh(J,i);
|
|
#
|
|
# e = 1 - sum(Qr(I,i+2:j),2);
|
|
# eh = 1 - sum(Qrh(J,i:j-2),2);
|
|
#
|
|
# Inv = inv(Eye-A*Ah);
|
|
# #C = y/Min + a*Ah*Inv*b;
|
|
# c0 = a*Ah*Inv*b;
|
|
# c1 = 1/Min;
|
|
# #Ch = x/Max + ah*Inv*A*bh;
|
|
# c0h = ah*Inv*A*bh;
|
|
# c1h = 1/Max;
|
|
# d1 = Qr(i,i+1)*(1-Qrh(i+1,i));
|
|
# D = d1+a*eh+a*Ah*Inv*A*eh;
|
|
# d1h = Qrh(j,j-1)*(1-Qr(j-1,j));
|
|
# Dh = d1h+ah*Inv*e;
|
|
# d0 = sum(Qr(i,i+1:j-1));
|
|
# #E = 1-d0-y/Min+a*Ah*Inv*e;
|
|
# e0 = 1-d0+a*Ah*Inv*e;
|
|
# e1 = -1/Min;
|
|
# d0h = sum(Qrh(j,i+1:j-1));
|
|
# #Eh = 1-d0h-x/Max+ah*Inv*A*eh;
|
|
# e0h = 1-d0h+ah*Inv*A*eh;
|
|
# e1h = -1/Max;
|
|
# r1 = Qr(i,i+1)*Qrh(i+1,i);
|
|
# R = r1+a*bh+a*Ah*Inv*A*bh;
|
|
# r1h = Qrh(j,j-1)*Qr(j-1,j);
|
|
# Rh = r1h+ah*Inv*b;
|
|
#
|
|
# # For Part 3 of cycle
|
|
#
|
|
# A3 = Q(I,J);
|
|
# A3h = Qh(J,I);
|
|
# Inv3 = inv(Eye-A3*A3h);
|
|
#
|
|
# # For Standing cycle
|
|
# d3h = sum(Qh(j,i+1:j-1));
|
|
# c3h = Qh(j,I);
|
|
# e3h = 1 - sum(Qh(J,i+1:j-2),2);
|
|
# E3h = 1-d3h + c3h*Inv3*A3*e3h;
|
|
#
|
|
# # For Hanging cycle
|
|
# d3 = sum(Q(i,i+1:j-1));
|
|
# c3 = Q(i,J);
|
|
# e3 = 1 - sum(Q(I,i+2:j-1),2);
|
|
# E3 = 1-d3 + c3*A3h*Inv3*e3;
|
|
#
|
|
# end
|
|
#
|
|
# if j-i == 1 # First subdiagonal
|
|
#
|
|
# if i == 1
|
|
# x = Max;
|
|
# y = Max;
|
|
# elseif j == n
|
|
# x = Min;
|
|
# y = Min;
|
|
# else
|
|
# if pS == 0
|
|
# x = 0;
|
|
# y = pH;
|
|
# elseif pH == 0
|
|
# x = pS;
|
|
# y = 0;
|
|
# else
|
|
# x = Min*pS/(Min-pH);
|
|
# y = Max*pH/(Max-pS);
|
|
# end
|
|
# end
|
|
#
|
|
# elseif j-i >= 2
|
|
# if i == 1
|
|
# x = Max*(1-sum(Qh(j,2:j-1)));
|
|
# y = Max*(1-sum(Qrh(j,2:j-1)));
|
|
# elseif j == n
|
|
# x = Min*(1-sum(Q(i,i+1:n-1)));
|
|
# y = Min*(1-sum(Qr(i,i+1:n-1)));
|
|
# else
|
|
# if pS == 0
|
|
# x = 0;
|
|
# y = pH;
|
|
# elseif pH == 0
|
|
# x = pS;
|
|
# y = 0;
|
|
# else
|
|
# # Define coeficients for equation system
|
|
# a0 = pS*c0h*c0+pS*Rh^2*R-2*pS*Rh*R-E3h*Max*c0h*e0*Rh+E3h*Max*c0h*e0+2*pS*Rh+pS*R-pS*c0h*c0*Rh-pS-pS*Rh^2+E3h*Max*c0h*Dh*c0;
|
|
# a1 = pS*c1h*c0+E3h*Max*c1h*Dh*c0-E3h*Max*c1h*e0*Rh-pS*c1h*c0*Rh+E3h*Max*c1h*e0;
|
|
# a2 = pS*c0h*c1+E3h*Max*c0h*e1-pS*c0h*c1*Rh+E3h*Max*c0h*Dh*c1-E3h*Max*c0h*e1*Rh;
|
|
# a3 = -E3h*Max*c1h*e1*Rh+E3h*Max*c1h*Dh*c1+E3h*Max*c1h*e1+pS*c1h*c1-pS*c1h*c1*Rh;
|
|
#
|
|
# b0 = pH*c0h*c0+pH*Rh*R^2-pH+pH*Rh-2*pH*Rh*R-pH*c0h*c0*R+Min*E3*e0h*c0-Min*E3*e0h*R*c0+Min*E3*D*c0h*c0+2*pH*R-pH*R^2;
|
|
# b1 = Min*E3*D*c1h*c0+Min*E3*e1h*c0+pH*c1h*c0-Min*E3*e1h*R*c0-pH*c1h*c0*R;
|
|
# b2 = -pH*c0h*c1*R-Min*E3*e0h*R*c1+Min*E3*D*c0h*c1+Min*E3*e0h*c1+pH*c0h*c1;
|
|
# b3 = Min*E3*e1h*c1+Min*E3*D*c1h*c1-pH*c1h*c1*R-Min*E3*e1h*R*c1+pH*c1h*c1;
|
|
#
|
|
# C2 = a2*b3-a3*b2;
|
|
# C1 = a0*b3-a1*b2+a2*b1-a3*b0;
|
|
# C0 = a0*b1-a1*b0;
|
|
# #fprintf(1,'i=%d, j=%d, C0/C2=%f,C1/C2=%f,C2=%f\n',i,j,C0/C2,C1/C2,C2);
|
|
# # Solve: C2*z^2 + C1*z + C0 = 0
|
|
# z1 = -C1/2/C2 + sqrt((C1/2/C2)^2-C0/C2);
|
|
# z2 = -C1/2/C2 - sqrt((C1/2/C2)^2-C0/C2);
|
|
#
|
|
# # Solution 1
|
|
# x1 = -(b0+b2*z1)/(b1+b3*z1);
|
|
# y1 = z1;
|
|
# # Solution 2
|
|
# x2 = -(b0+b2*z2)/(b1+b3*z2);
|
|
# y2 = z2;
|
|
#
|
|
# x = x2;
|
|
# y = y2;
|
|
#
|
|
# # fprintf(1,'End: i=%d, j=%d: x1=%f, y1=%f, x2=%f, y2=%f\n',i,j,x1,y1,x2,y2);
|
|
# end
|
|
# end
|
|
# end
|
|
#
|
|
# # fprintf(1,'i=%d, j=%d: x=%f, y=%f\n',i,j,x,y);
|
|
#
|
|
# # min-max
|
|
# F(i,j) = x;
|
|
#
|
|
# # max-min
|
|
# F(j,i) = y;
|
|
#
|
|
# # Fill the transitions matrices
|
|
# Q(i,j) = x/Min;
|
|
# Qh(j,i) = y/Max;
|
|
# Qr(i,j) = y/Min;
|
|
# Qrh(j,i) = x/Max;
|
|
#
|
|
# end
|
|
# end
|
|
# #fprintf(1,'\n');
|
|
#
|
|
#
|
|
# T(8,:)=clock;
|
|
#
|
|
# return F,T
|
|
|
|
|
|
if __name__ == "__main__":
|
|
from wafo.testing import test_docstrings
|
|
test_docstrings(__file__)
|