def test_skew(): assert np.allclose(utils.skew(np.zeros(3)), np.zeros((3,3))) assert np.allclose(utils.skew([1,2,3]), np.array([ [ 0, -3, 2], [ 3, 0, -1], [-2, 1, 0], ]))
def test_skew(): assert np.allclose(utils.skew(np.zeros(3)), np.zeros((3, 3))) assert np.allclose(utils.skew([1, 2, 3]), np.array([ [0, -3, 2], [3, 0, -1], [-2, 1, 0], ]))
def Morison_inertial_force(self, w): r"""Calculate the Morison inertial force """ # XXX rho = 1025 # Define the matrix which transforms the 6 rigid-body DOFs # into the acceleration at each element L = np.array([np.c_[np.eye(3), -skew(x)] for x in self.element_centres]) # For inertial force: calculate normal fluid acceleration for unit wave a_fluid = 1j * w[:,newaxis,newaxis] * self.wave_velocity_transfer_function(w) # Only normal accelerations count -- subtract the longitudinal # component at each element: at = (a . t) t t = self.element_axes[:,:,2] at = np.einsum('wei,ei,ej->wej', a_fluid, t, t) an = a_fluid - at # Added mass force for each element (Nel x 3 x 6) F_inertial = (self.Cm * rho * (pi*self.element_diameters[newaxis,:,newaxis]**2/4) * self.element_lengths[newaxis,:,newaxis] * an) # Sum up to get total resultant force and moment # A = sum [ L.T * F_added ] F = np.einsum('eix,wei->wx', L, F_inertial) return F
def structural_velocity_transfer_function(self, w, H): """Return the transfer functions from wave elevation to structure velocity. - H: array of transfer functions (RAOs) Returns: array (frequency, element, xyz) """ H_us = np.zeros((len(w), len(self.element_diameters), 3), dtype=np.complex) for iel in range(H_us.shape[1]): xs = skew(self.element_centres[iel]) for j in range(H_us.shape[0]): # H may have more than 6 DOFs if model is flexible H_us[j, iel, :] = (1j*w[j] * (H[j, 0:3] - dot(xs, H[j, 3:6]))) return H_us
def Morison_added_mass(self): """Calculate added mass matrix from Morison elements""" # Define the matrix which transforms the 6 rigid-body DOFs # into the acceleration at each element L = np.array([np.c_[np.eye(3), -skew(x)] for x in self.element_centres]) # Only normal accelerations count -- subtract the longitudinal # component at each element: at = (a . t) t t = self.element_axes[:,:,2] a = L at = np.einsum('eix,ei,ej->ejx', a, t, t) an = a - at # Added mass force for each element (Nel x 3 x 6) F_added = ((self.Cm - 1) * 1025 * (pi*self.element_diameters[:,newaxis,newaxis]**2/4) * self.element_lengths[:,newaxis,newaxis] * an) # Sum up to get total resultant force and moment # A = sum [ L.T * F_added ] A = np.einsum('eix,eiy->xy', L, F_added) return A
def total_drag(self, w, H_wave, S_wave, vc=None): r"""Calculate the linearised forces on each element then sum The total force and moment together are $$ \boldsymbol{F} = \sum \boldsymbol{L}_i \boldsymbol{F}^_i$$ with $$\boldsymbol{L}_i = \begin{bmatrix} \boldsymbol{I} \\ \boldsymbol{\tilde{X}_i} \end{bmatrix}$$ The drag force on each element is $$ \boldsymbol{F}_i = C \boldsymbol{A} ( \boldsymbol{u}_f - \boldsymbol{u}_s ) + C \boldsymbol{b} $$ where $C = \rho C_d D \mathrm{d}s / 2$ is a constant, and $\boldsymbol{A}$ is the transformed linearisation matrix. Using the fluid velocity transfer functions $\boldsymbol{H}_{uf \zeta}$, $\boldsymbol{u}_f(t) = \boldsymbol{H}_{uf \zeta}(\omega) \zeta_a e^{i\omega t}$, so this part goes on the RHS as a force $C \boldsymbol{A} \boldsymbol{H}_{u_f \zeta} \zeta_a e^{i\omega t} + C \boldsymbol{b}$. The structural response is given by $$ \boldsymbol{u}_s = i\omega \begin{bmatrix} \boldsymbol{I} & -\boldsymbol{\tilde{X}} \end{bmatrix} \boldsymbol{\Xi}(\omega) e^{i\omega t} $$ so the rest of the drag force goes on the LHS as a damping matrix $$\boldsymbol{B}_v = C \boldsymbol{A} \boldsymbol{L}^{\mathrm{T}}$$ This function returns Fvc = sum (C Li bi), the steady part of the force, and Fvv[freq] = sum (C Li Ai H_uf), which is the harmonic drag force for unit wave amplitude. NB this is very slow if w goes right to zero -- why? """ # XXX rho = 1025 H_uf = self.wave_velocity_transfer_function(w) A, b = self.linearised_drag_force(w, H_wave, S_wave, vc) Bv = np.zeros((6,6)) # viscous drag damping Fvc = np.zeros(6) # constant drag force Fvv = np.zeros((len(w), 6), dtype=complex) # time-varying drag force for iel in range(len(self.element_diameters)): # Drag constant for each element C = (0.5 * rho * self.Cd * self.element_diameters[iel] * self.element_lengths[iel]) # Force acts at centre of each element x = self.element_centres[iel] L = np.r_[ np.eye(3), skew(x) ] # forces and moments about origin # Damping effect of viscous drag force Bv += C * dot(L, dot(A[iel], L.T)) # Applied viscous drag force Fvc += C * dot(L, b[iel]) for iw in range(len(w)): Fvv[iw] += C * dot(L, dot(A[iel], H_uf[iw, iel, :])) return Bv, Fvc, Fvv