def Morison_added_mass(w, draft, radius, Cm=2.0): """Calculate added mass and damping from Morison strip model of uniform cylinder""" from whales.viscous_drag import ViscousDragModel Morison_model = ViscousDragModel({ 'inertia coefficient': Cm, 'members': [{ 'end1': [0, 0, 0], 'end2': [0, 0, -draft], 'diameter': 2 * radius, 'strip width': 1.0, }] }) A1 = Morison_model.Morison_added_mass() A = np.tile(A1, (len(w), 1, 1)) return LinearSystem(A, zeros_like(A), zeros_like(A))
def added_mass(w, z1, z2, diameter, Cm=2): """Calculate the added mass/damping. Specific for now to vertical cylinders of varying diameter. ``z1``, ``z2``: coordinates of ends of element ``diameter``: array (2 x Npoints) diameter at each z value """ config = { 'end1': [0, 0, z1], 'end2': [0, 0, z2], 'diameter': diameter, 'strip width': 1.0, } Morison_model = ViscousDragModel({ 'inertia coefficient': Cm, 'members': [config], }) A1 = Morison_model.Morison_added_mass() A = np.tile(A1, (len(w), 1, 1)) return LinearSystem(A, zeros_like(A), zeros_like(A))
class CylinderTestCase(MyTestCase): """Test simple model with vertical cylinder""" def setUp(self): config = { 'drag coefficient': 0.7, 'inertia coefficient': 2.0, 'members': [{ 'end1': [0, 0, 0], 'end2': [0, 0, -10], 'diameter': 2.3, 'strip width': 1, }], } self.model = ViscousDragModel(config) def test_model_elements(self): """Check element strips setup correctly""" m = self.model self.assertArraysEqual(m.element_lengths, np.ones(10)) # Centres of strips centres = np.zeros((10, 3)) centres[:,2] = -np.arange(0.5, 10, 1) self.assertArraysEqual(m.element_centres, centres) # Element diameters self.assertArraysEqual(m.element_diameters, 2.3) # Element axes self.assertArraysEqual(m.element_axes, np.array([np.eye(3)] * 10)) def test_wave_velocity_transfer_func(self): """Test wave velocity transfer function""" w = np.array([1,2]) # frequencies to test H_uf = self.model.wave_velocity_transfer_function(w) # With waves in x-direction, sideways velocity should be zero self.assertArraysEqual(H_uf[:,:,1], 0) # Check variation in depth: exp(kz) iz1 = 3 iz2 = 8 z = self.model.element_centres[:,2] for i in range(2): assert_array_almost_equal_nulp(H_uf[i,iz1,:] / np.exp(w[i]**2/9.81*z[iz1]), H_uf[i,iz2,:] / np.exp(w[i]**2/9.81*z[iz2])) # Check all x velocities are in-phase and real, all z are imaginary self.assertTrue(np.isreal( H_uf[:,:,0]).all()) self.assertTrue(np.isreal(1j * H_uf[:,:,2]).all()) def test_structural_velocity_transfer_func(self): """Test structural velocity with special cases""" w = np.array([1,2]) # frequencies to test # Case 1: pure surge motion H1 = np.zeros((2, 6)) # shape (freq, xyzXYZ) H1[:,0] = 1 # maximum surge at maximum datum wave height H_us = self.model.structural_velocity_transfer_function(w, H1) # all elements should have same surge velocity; all other velocities zero # at t=0, velocity is zero and becoming negative 90 deg later self.assertArraysEqual(H_us[1,:,0], 2j) self.assertArraysEqual(H_us[0,:,0], 1j) self.assertArraysEqual(H_us[:,:,1:], 0) # Case 2: pure roll motion H2 = np.zeros((2, 6)) # shape (freq, xyzXYZ) H2[:,3] = 1 # maximum roll at maximum datum wave height H_us = self.model.structural_velocity_transfer_function(w, H2) # x & z velocity should be zero self.assertArraysEqual(H_us[:,:,[0,2]], 0) # y velocity corresponding to rotation about origin (check bottom) # at t=0, ang. velocity is zero and becoming negative 90 deg later # Velocity of bottom element = 9.5 * ang vel self.assertArraysEqual(H_us[0,-1,1], 9.5 * 1j) self.assertArraysEqual(H_us[1,-1,1], 9.5 * 2j) def test_added_mass(self): """Test added mass calculation from Morison elements""" A = self.model.Morison_added_mass() # Expected surge added mass: (Cm-1) * rho * V self.assertEqual(A[0,0], 1 * 1025 * 10 * np.pi * 2.3**2 / 4)