class ModalElement_AsRigidBody_Tests: def setup(self): self.density = 230.4 self.length = 20.0 self.modes = _mock_rigid_uniform_modes(self.density, self.length) self.element = ModalElement('element', self.modes) def test_element_mass_when_aligned_with_global_coordinates(self): self.element.calc_mass() # Expected values: rod along x axis m = self.density * self.length Iy = m * self.length**2 / 3 expected_mass = m * eye(3) expected_inertia = diag([0, Iy, Iy]) expected_offdiag = zeros((3, 3)) # Y accel -> positive moment about Z # Z accel -> negative moment about Y expected_offdiag[2, 1] = m * self.length / 2 expected_offdiag[1, 2] = -m * self.length / 2 elmass = self.element.mass_vv assert_aae(elmass[:3, :3], expected_mass) assert_aae(elmass[3:, 3:], expected_inertia) assert_aae(elmass[3:, :3], expected_offdiag) assert_aae(elmass[:3, 3:], expected_offdiag.T) def test_element_mass_when_rotated_and_offset(self): Rp = dot(rotmat_y(pi / 5), dot(rotmat_z(-pi / 7), rotmat_x(3 * pi / 4))) self.element.rp[:] = [304.3, 12.3, -402.0] self.element.Rp[:, :] = Rp self.element.calc_mass() # Expected values: rod along x axis m = self.density * self.length Iy = m * self.length**2 / 3 expected_mass = m * eye(3) expected_inertia = diag([0, Iy, Iy]) expected_offdiag = zeros((3, 3)) # Y accel -> positive moment about Z # Z accel -> negative moment about Y expected_offdiag[2, 1] = m * self.length / 2 expected_offdiag[1, 2] = -m * self.length / 2 transform = lambda A: dot(Rp, dot(A, Rp.T)) assert_aae(expected_mass, transform(expected_mass)) elmass = self.element.mass_vv assert_aae(elmass[:3, :3], transform(expected_mass)) assert_aae(elmass[3:, 3:], transform(expected_inertia)) assert_aae(elmass[3:, :3], transform(expected_offdiag)) assert_aae(elmass[:3, 3:], transform(expected_offdiag).T)
class ModalElement_AsRigidBody_Tests: def setup(self): self.density = 230.4 self.length = 20.0 self.modes = _mock_rigid_uniform_modes(self.density, self.length) self.element = ModalElement('element', self.modes) def test_element_mass_when_aligned_with_global_coordinates(self): self.element.calc_mass() # Expected values: rod along x axis m = self.density * self.length Iy = m * self.length**2 / 3 expected_mass = m * eye(3) expected_inertia = diag([0, Iy, Iy]) expected_offdiag = zeros((3, 3)) # Y accel -> positive moment about Z # Z accel -> negative moment about Y expected_offdiag[2, 1] = m * self.length / 2 expected_offdiag[1, 2] = -m * self.length / 2 elmass = self.element.mass_vv assert_aae(elmass[:3, :3], expected_mass) assert_aae(elmass[3:, 3:], expected_inertia) assert_aae(elmass[3:, :3], expected_offdiag) assert_aae(elmass[:3, 3:], expected_offdiag.T) def test_element_mass_when_rotated_and_offset(self): Rp = dot(rotmat_y(pi/5), dot(rotmat_z(-pi/7), rotmat_x(3*pi/4))) self.element.rp[:] = [304.3, 12.3, -402.0] self.element.Rp[:, :] = Rp self.element.calc_mass() # Expected values: rod along x axis m = self.density * self.length Iy = m * self.length**2 / 3 expected_mass = m * eye(3) expected_inertia = diag([0, Iy, Iy]) expected_offdiag = zeros((3, 3)) # Y accel -> positive moment about Z # Z accel -> negative moment about Y expected_offdiag[2, 1] = m * self.length / 2 expected_offdiag[1, 2] = -m * self.length / 2 transform = lambda A: dot(Rp, dot(A, Rp.T)) assert_aae(expected_mass, transform(expected_mass)) elmass = self.element.mass_vv assert_aae(elmass[:3, :3], transform(expected_mass)) assert_aae(elmass[3:, 3:], transform(expected_inertia)) assert_aae(elmass[3:, :3], transform(expected_offdiag)) assert_aae(elmass[:3, 3:], transform(expected_offdiag).T)
def setup(self): x = linspace(0, self.length, 50) density = self.mass / self.length # One mode shape: linear in z direction. shape = linspace(0, 1, 50) rotation = -np.ones(50) / self.length shapes = c_[0 * x, 0 * x, shape].reshape((len(x), 3, 1)) rotations = c_[0 * x, rotation, 0 * x].reshape((len(x), 3, 1)) # Natural frequency: w^2 = k/I I0 = self.mass * (self.length**2 / 3) # inertia about end freq = (self.stiffness / I0)**0.5 modes = ModalRepresentation(x, density, shapes, rotations, [freq]) self.beam = ModalElement('beam', modes)
def setup(self): self.density = 230.4 self.length = 20.0 self.modes = _mock_rigid_uniform_modes(self.density, self.length) self.element = ModalElement('element', self.modes)
def make_a_modal_beam(length, density=None, section_inertia=None): x = linspace(0, length, 10) modes = ModalRepresentation(x, density, section_inertia=section_inertia) beam = ModalElement('beam', modes) return beam
def __init__(self, structure_config): s = structure_config #### Load details of flexible elements #### if 'definition' in s['tower']: if 'mass' in s['tower']: raise ValueError("Both tower definition and explicit mass!") self.tower_definition = Tower(s['tower']['definition']) assert np.all(self.tower_definition.stn_pos[:, :2] == 0) # vert. z_tower = self.tower_definition.stn_pos[:, 2] self.tower_modes = ModesFromScratch( z_tower - z_tower[0], self.tower_definition.density, 1, self.tower_definition.EIy, self.tower_definition.EIz) else: self.tower_definition = None self.tower_modes = None if 'blade' in s: self.blade_modes = load_modes_from_Bladed(s['blade']['definition']) else: self.blade_modes = None #### Create the elements #### # Free joint represents the rigid-body motion of the platform free_joint = FreeJoint('base') # This is the rigid-body mass of the platform structure conn_platform = RigidConnection('conn-platform', offset=s['platform']['CoM']) platform = RigidBody('platform', mass=s['platform']['mass'], inertia=np.diag(s['platform']['inertia'])) free_joint.add_leaf(conn_platform) conn_platform.add_leaf(platform) # Make a rigid body to represent the added mass # (approximate to zero frequency) # XXX this is skipping the coupling matrix #A = whales_model.A(0) # added_mass = RigidBody('added-mass', mass=np.diag(A[:3, :3]), # inertia=A[3:, 3:]) # Flexible tower or equivalent rigid body if self.tower_modes: # move base of tower 10m up, and rotate so tower x-axis is vertical conn_tower = RigidConnection( 'conn-tower', offset=[0, 0, z_tower[0]], rotation=rotmat_y(-pi/2)) tower = DistalModalElementFromScratch( 'tower', self.tower_modes, s['tower']['number of normal modes']) else: # move tower to COG conn_tower = RigidConnection( 'conn-tower', offset=s['tower']['CoM']) tower = RigidBody('tower', s['tower']['mass'], np.diag(s['tower']['inertia'])) free_joint.add_leaf(conn_tower) conn_tower.add_leaf(tower) # The nacelle -- rigid body # rotate back so nacelle inertia is aligned with global coordinates if self.tower_modes: nacoff = s['nacelle']['offset from tower top'] conn_nacelle = RigidConnection('conn-nacelle', offset=dot(rotmat_y(pi/2), nacoff), rotation=rotmat_y(pi/2)) tower.add_leaf(conn_nacelle) else: conn_nacelle = RigidConnection( 'conn-nacelle', offset=np.array([0, 0, s['nacelle']['height']])) free_joint.add_leaf(conn_nacelle) nacelle = RigidBody( 'nacelle', mass=s['nacelle']['mass'], inertia=np.diag(s['nacelle'].get('inertia', np.zeros(3)))) conn_nacelle.add_leaf(nacelle) # The rotor hub -- currently just connections (no mass) # rotate so rotor centre is aligned with global coordinates if self.tower_modes: rotoff = s['rotor']['offset from tower top'] conn_rotor = RigidConnection('conn-rotor', offset=dot(rotmat_y(pi/2), rotoff), rotation=rotmat_y(pi/2)) tower.add_leaf(conn_rotor) else: conn_rotor = RigidConnection( 'conn-rotor', offset=np.array([0, 0, s['nacelle']['height']])) free_joint.add_leaf(conn_rotor) # The drive shaft rotation (rotation about x) shaft = Hinge('shaft', [1, 0, 0]) conn_rotor.add_leaf(shaft) # The blades if self.blade_modes: rtlen = s['rotor']['root length'] Ryx = dot(rotmat_y(-pi/2), rotmat_x(-pi/2)) # align blade modes for i in range(3): R = rotmat_x(i*2*pi/3) root = RigidConnection('root%d' % (i+1), offset=dot(R, [0, 0, rtlen]), rotation=dot(R, Ryx)) blade = ModalElement('blade%d' % (i+1), self.blade_modes) shaft.add_leaf(root) root.add_leaf(blade) else: rotor = RigidBody('rotor', s['rotor']['mass'], np.diag(s['rotor']['inertia'])) shaft.add_leaf(rotor) # Build system self.system = System(free_joint) # Constrain missing DOFs -- tower torsion & extension not complete if self.tower_modes: self.system.prescribe(tower, vel=0, part=[0, 3])