from numba import njit import numpy as np @njit(cache=True) # jit faster than previous cython compiled extension def pair_range_amplitude(x): """ Returns a list of half-cycle-amplitudes x: Peak-Trough sequence (integer list of local minima and maxima) This routine is implemented according to "Recommended Practices for Wind Turbine Testing - 3. Fatigue Loads", 2. edition 1990, Appendix A except that a list of half-cycle-amplitudes are returned instead of a from_level-to_level-matrix """ x = x - np.min(x) k = np.max(x) n = x.shape[0] S = np.zeros(n + 1) #A = np.zeros(k+1) flow = [] S[1] = x[0] ptr = 1 p = 1 q = 1 f = 0 # phase 1 while True: p += 1 q += 1 # read S[p] = x[ptr] ptr += 1 if q == n: f = 1 while p >= 4: if (S[p - 2] > S[p - 3] and S[p - 1] >= S[p - 3] and S[p] >= S[p - 2]) \ or\ (S[p - 2] < S[p - 3] and S[p - 1] <= S[p - 3] and S[p] <= S[p - 2]): ampl = abs(S[p - 2] - S[p - 1]) # A[ampl]+=2 #Two half cycles flow.append(ampl) flow.append(ampl) S[p - 2] = S[p] p -= 2 else: break if f == 0: pass else: break # phase 2 q = 0 while True: q += 1 if p == q: break else: ampl = abs(S[q + 1] - S[q]) # A[ampl]+=1 flow.append(ampl) return flow @njit(cache=True) def pair_range_from_to(x): """ Returns a list of half-cycle-amplitudes x: Peak-Trough sequence (integer list of local minima and maxima) This routine is implemented according to "Recommended Practices for Wind Turbine Testing - 3. Fatigue Loads", 2. edition 1990, Appendix A except that a list of half-cycle-amplitudes are returned instead of a from_level-to_level-matrix """ x = x - np.min(x) k = np.max(x) n = x.shape[0] S = np.zeros(n + 1) A = np.zeros((k + 1, k + 1)) S[1] = x[0] ptr = 1 p = 1 q = 1 f = 0 # phase 1 while True: p += 1 q += 1 # read S[p] = x[ptr] ptr += 1 if q == n: f = 1 while p >= 4: # print S[p - 3:p + 1] # print S[p - 2], ">", S[p - 3], ", ", S[p - 1], ">=", S[p - 3], ", ", S[p], ">=", S[p - 2], (S[p - 2] > S[p - 3] and S[p - 1] >= S[p - 3] and S[p] >= S[p - 2]) # print S[p - 2], "<", S[p - 3], ", ", S[p - 1], "<=", S[p - 3], ", ", S[p], "<=", S[p - 2], (S[p - 2] < S[p - 3] and S[p - 1] <= S[p - 3] and S[p] <= S[p - 2]) #print (S[p - 2] > S[p - 3] and S[p - 1] >= S[p - 3] and S[p] >= S[p - 2]) or (S[p - 2] < S[p - 3] and S[p - 1] <= S[p - 3] and S[p] <= S[p - 2]) if (S[p - 2] > S[p - 3] and S[p - 1] >= S[p - 3] and S[p] >= S[p - 2]) or \ (S[p - 2] < S[p - 3] and S[p - 1] <= S[p - 3] and S[p] <= S[p - 2]): A[S[p - 2], S[p - 1]] += 1 A[S[p - 1], S[p - 2]] += 1 S[p - 2] = S[p] p -= 2 else: break if f == 1: break # q==n # phase 2 q = 0 while True: q += 1 if p == q: break else: # print S[q], "to", S[q + 1] A[S[q], S[q + 1]] += 1 return A @njit(cache=True) def pair_range_amplitude_mean(x): """ Returns a list of half-cycle-amplitudes x: Peak-Trough sequence (integer list of local minima and maxima) This routine is implemented according to "Recommended Practices for Wind Turbine Testing - 3. Fatigue Loads", 2. edition 1990, Appendix A except that a list of half-cycle-amplitudes are returned instead of a from_level-to_level-matrix """ x = x - np.min(x) k = np.max(x) n = x.shape[0] S = np.zeros(n + 1) ampl_mean = [] A = np.zeros((k + 1, k + 1)) S[1] = x[0] ptr = 1 p = 1 q = 1 f = 0 # phase 1 while True: p += 1 q += 1 # read S[p] = x[ptr] ptr += 1 if q == n: f = 1 while p >= 4: if (S[p - 2] > S[p - 3] and S[p - 1] >= S[p - 3] and S[p] >= S[p - 2]) \ or\ (S[p - 2] < S[p - 3] and S[p - 1] <= S[p - 3] and S[p] <= S[p - 2]): # Extract two intermediate half cycles ampl = abs(S[p - 2] - S[p - 1]) mean = (S[p - 2] + S[p - 1]) / 2 ampl_mean.append((ampl, mean)) ampl_mean.append((ampl, mean)) S[p - 2] = S[p] p -= 2 else: break if f == 0: pass else: break # phase 2 q = 0 while True: q += 1 if p == q: break else: ampl = abs(S[q + 1] - S[q]) mean = (S[q + 1] + S[q]) / 2 ampl_mean.append((ampl, mean)) return ampl_mean