def test_shift(): A = np.arange(1, 5) assert np.allclose(utils.shift(A, 0), A) assert np.allclose(utils.shift(A, 2, fill=0), [3, 4, 0, 0]) assert np.allclose(utils.shift(A, -2, fill=0), [0, 0, 1, 2]) assert np.allclose(utils.shift(A, 2), [3, 4, 4, 4]) assert np.allclose(utils.shift(A, -2), [1, 1, 1, 2])
def second_order_force_spectrum(w, Tc, S_wave): """Calculate the 2nd order force spectrum defined by $$ S_i^{(2)}(\omega) = 8 \int S_{\eta\eta}(\mu) S_{\eta\eta}(\mu + \omega) \, \left| T_i^{\mathrm{c}}(\mu, \mu + \omega) \right|^2 \mathrm{d}\mu $$ but extended to give the cross-spectrum S_ij """ Ndof = Tc.shape[1] # First make the matrix SS_kl, where l is the freq and k is the offset # SS_kl = S(w_l) * S(w_l + w_k) SS = np.tile(S_wave, (len(w), 1)) for k in range(len(w)): SS[k, :] *= shift(S_wave, k, fill=0) # Next use the Newman approximation to make a similar matrix TTc TTc = np.tile(Tc, (len(w), 1, 1)) # copy downwards new 0 axis for k in range(len(w)): for i in range(Ndof): TTc[k, :, i] += shift(Tc[:, i], k) TTc /= 2 # average # Now loop through each DOF to make the 2nd order spectrum S2 = np.zeros((len(w), Ndof, Ndof)) for i in range(Ndof): for j in range(Ndof): integrand = SS * TTc[:, :, i] * TTc[:, :, j] S2[:, i, j] = 8 * integrate.simps(integrand, w, axis=1) return S2