def test_solve_accelerations_coupling(self): # Further to test above, check that coupling between prescribed # accelerations and other dofs is correct. For example, if there # is a rigid body vertically offset from the joint, then a # prescribed horizontal acceleration should cause an angular # acceleration as well as the translational acceleration. s = System() j = FreeJoint('joint') c = RigidConnection('conn', [0, 0, 1.7]) b = RigidBody('body', mass=23.54, inertia=74.1 * np.eye(3)) s.add_leaf(j) j.add_leaf(c) c.add_leaf(b) s.setup() # Prescribe horizontal acceleration, solve other accelerations s.prescribe(j, 2.3, part=[0]) # x acceleration s.update_kinematics() # update system to show prescribed acc s.solve_accelerations() # solve free accelerations s.update_kinematics() # update system to show solution # Ground shouldn't move assert_aae(j.ap, 0) # Need angular acceleration = (m a_x L) / I0 I0 = 74.1 + (23.54 * 1.7**2) expected_angular_acc = -(23.54 * 2.3 * 1.7) / I0 assert_aae(j.ad, [2.3, 0, 0, 0, expected_angular_acc, 0]) assert_aae(j.astrain, j.ad) # not always true, but works for FreeJoint
def test_call(self): s = System() c = RigidConnection('conn', [1, 0, 0]) h = Hinge('hinge', [0, 1, 0]) b = RigidBody('body', 1) s.add_leaf(h) h.add_leaf(c) c.add_leaf(b) s.setup() # Set hinge angle h.xstrain[0] = 0.82 h.vstrain[0] = 1.2 h.astrain[0] = -0.3 s.update_kinematics() s.solve_reactions() # Test load outputs out = LoadOutput('node-1') assert_array_equal(out(s), s.joint_reactions['node-1']) out = LoadOutput('node-1', local=True) F = s.joint_reactions['node-1'] assert_array_equal(out(s), np.r_[np.dot(b.Rp.T, F[:3]), np.dot(b.Rp.T, F[3:])])
def test_solve_accelerations(self): # solve_accelerations() should find: # (a) response of system to forces (here, gravity) # (b) include any prescribed accelerations in qdd vector g = 9.81 s = System(gravity=g) j = FreeJoint('joint') b = RigidBody('body', mass=23.54, inertia=52.1 * np.eye(3)) s.add_leaf(j) j.add_leaf(b) s.setup() # Prescribe horizontal acceleration. Vertical acceleration # should result from gravity. s.prescribe(j, 2.3, part=[0]) # x acceleration # Initially accelerations are zero assert_aae(j.ap, 0) assert_aae(j.ad, 0) assert_aae(j.astrain, 0) # Solve accelerations & check s.solve_accelerations() s.update_kinematics() assert_aae(j.ap, 0) # ground assert_aae(j.ad, [2.3, 0, -g, 0, 0, 0]) assert_aae(j.astrain, j.ad) # not always true, but works for FreeJoint
def rigid_body_mass_matrix(element): joint = FreeJoint('joint') system = System() system.add_leaf(joint) joint.add_leaf(element) system.setup() for el in joint.iter_leaves(): system.prescribe(el, 0, 0) system.update_kinematics() rsys = ReducedSystem(system) return rsys.M
def rigid_body_mass_matrix(element): joint = FreeJoint('joint') system = System() system.add_leaf(joint) joint.add_leaf(element) system.setup() for el in joint.iter_leaves(): system.prescribe(el, 0, 0) system.update_kinematics() rsys = ReducedSystem(system) return rsys.M
def test_call(self): s = System() c = RigidConnection('conn', [1, 0, 0]) h = Hinge('hinge', [0, 1, 0]) b = RigidBody('body', 1) s.add_leaf(h) h.add_leaf(c) c.add_leaf(b) s.setup() # Set hinge angle h.xstrain[0] = 0.82 h.vstrain[0] = 1.2 h.astrain[0] = -0.3 s.update_kinematics() # Test node outputs out = StateOutput('node-1') assert_array_equal(out(s), np.r_[b.rp, b.Rp.flatten()]) out = StateOutput('node-1', deriv=1) assert_array_equal(out(s), b.vp) out = StateOutput('node-1', deriv=2) assert_array_equal(out(s), b.ap) out = StateOutput('node-1', local=True) assert_array_equal(out(s), np.r_[np.dot(b.Rp.T, b.rp), np.eye(3).flatten()]) out = StateOutput('node-1', deriv=1, local=True) assert_array_equal(out(s), np.r_[np.dot(b.Rp.T, b.vp[:3]), np.dot(b.Rp.T, b.vp[3:])]) out = StateOutput('node-1', deriv=2, local=True) assert_array_equal(out(s), np.r_[np.dot(b.Rp.T, b.ap[:3]), np.dot(b.Rp.T, b.ap[3:])]) # Test strain outputs out = StateOutput('hinge-strains') assert_array_equal(out(s), 0.82) out = StateOutput('hinge-strains', deriv=1) assert_array_equal(out(s), 1.2) out = StateOutput('hinge-strains', deriv=2) assert_array_equal(out(s), -0.3) # Strains cannot be transformed to local coordinates with self.assertRaises(RuntimeError): out = StateOutput('hinge-strains', local=True) out(s)
def setUp(self): joint = PrismaticJoint('joint', [0, 0, 1]) joint.stiffness = self.K joint.damping = 2 * self.damping_coeff * (self.K * self.M)**0.5 body = RigidBody('body', self.M) system = System() system.add_leaf(joint) joint.add_leaf(body) system.setup() system.update_kinematics() self.joint, self.body, self.system = joint, body, system
def setUp(self): joint = PrismaticJoint('joint', [0, 0, 1]) joint.stiffness = self.K joint.damping = 2 * self.damping_coeff * (self.K * self.M) ** 0.5 body = RigidBody('body', self.M) system = System() system.add_leaf(joint) joint.add_leaf(body) system.setup() system.update_kinematics() self.joint, self.body, self.system = joint, body, system
def setUp(self): x = linspace(0, self.L, 15) fe = BeamFE(x, density=self.m, EA=0, EIy=self.EI, EIz=0) fe.set_boundary_conditions('C', 'C') fe.set_dofs([False, False, True, False, True, False]) beam = DistalModalElementFromFE('beam', fe, num_modes=1, damping=self.damping_coeff) system = System() system.add_leaf(beam) system.setup() system.update_kinematics() self.beam, self.system = beam, system
def test_distal_forces_cause_acceleration(self): j = FreeJoint('joint') b = RigidBody('body', mass=3, inertia=np.diag([7, 7, 7])) s = System() s.add_leaf(j) j.add_leaf(b) s.setup() # Constant loading j.distal_forces = np.array([2, 0, 0, 0, 0, 0]) s.update_kinematics() s.update_matrices() s.solve_accelerations() s.update_kinematics() assert_array_equal(j.ad, [2. / 3, 0, 0, 0, 0, 0])
def setUp(self): x = linspace(0, self.L, 15) fe = BeamFE(x, density=self.m, EA=0, EIy=self.EI, EIz=0) fe.set_boundary_conditions('C', 'C') fe.set_dofs([False, False, True, False, True, False]) beam = DistalModalElementFromFE('beam', fe, num_modes=1, damping=self.damping_coeff) system = System() system.add_leaf(beam) system.setup() system.update_kinematics() self.beam, self.system = beam, system
class TestReactionForcesForCentrifugalForce(unittest.TestCase): """ System ------ A rigid body with offset mass, attached to a spinning hinge. Tests ----- Check centrifugal force reaction on hinge is in correct direction. """ mass = 5.0 # kg offset = 3.2 # m def setUp(self): # Rigid body with offset centre of mass self.body = RigidBody("body", self.mass, Xc=[self.offset, 0, 0]) # Hinge with axis along Z axis self.hinge = Hinge("hinge", [0, 0, 1]) # Build system self.system = System() self.system.add_leaf(self.hinge) self.hinge.add_leaf(self.body) self.system.setup() self.system.update_kinematics() # Set up nodal values initially self.system.update_matrices() def test_reactions(self): # Set angular acceleration w = 5.21 # rad/s self.hinge.vstrain[0] = w self.system.update_kinematics() # Update nodal values based on DOFs self.system.update_matrices() self.system.solve_reactions() # Solve reactions incl d'Alembert # Some parameters L = self.offset m = self.mass # Check reactions at beam root Pg = self.system.joint_reactions["ground"] P0 = self.system.joint_reactions["node-0"] Fx_expected = -m * L * w ** 2 assert_aae(P0, [Fx_expected, 0, 0, 0, 0, 0]) assert_aae(Pg, P0)
class TestReactionForcesForCentrifugalForce(unittest.TestCase): """ System ------ A rigid body with offset mass, attached to a spinning hinge. Tests ----- Check centrifugal force reaction on hinge is in correct direction. """ mass = 5.0 # kg offset = 3.2 # m def setUp(self): # Rigid body with offset centre of mass self.body = RigidBody('body', self.mass, Xc=[self.offset, 0, 0]) # Hinge with axis along Z axis self.hinge = Hinge('hinge', [0, 0, 1]) # Build system self.system = System() self.system.add_leaf(self.hinge) self.hinge.add_leaf(self.body) self.system.setup() self.system.update_kinematics() # Set up nodal values initially self.system.update_matrices() def test_reactions(self): # Set angular acceleration w = 5.21 # rad/s self.hinge.vstrain[0] = w self.system.update_kinematics() # Update nodal values based on DOFs self.system.update_matrices() self.system.solve_reactions() # Solve reactions incl d'Alembert # Some parameters L = self.offset m = self.mass # Check reactions at beam root Pg = self.system.joint_reactions['ground'] P0 = self.system.joint_reactions['node-0'] Fx_expected = -m * L * w**2 assert_aae(P0, [Fx_expected, 0, 0, 0, 0, 0]) assert_aae(Pg, P0)
class hinged_beam_tests(unittest.TestCase): density = 5.0 length = 20.0 force = 34.2 # N/m hinge_torque = 0.0 free_beam = False def setUp(self): # FE model for beam x = linspace(0, self.length, 20) fe = BeamFE(x, density=self.density, EA=0, EIy=1, EIz=0) fe.set_boundary_conditions('C', 'F') self.beam = ModalElementFromFE('beam', fe, 0) # Set loading - in negative Z direction load = np.zeros((len(x), 3)) load[:, 2] = -self.force self.beam.loading = load # Hinge with axis along Y axis self.hinge = Hinge('hinge', [0, 1, 0]) self.hinge.internal_torque = self.hinge_torque # Build system self.system = System() self.system.add_leaf(self.hinge) self.hinge.add_leaf(self.beam) self.system.setup() if not self.free_beam: # Prescribe hinge to be fixed self.system.prescribe(self.hinge) # Initial calculations self.recalc() def recalc(self): self.system.update_kinematics() # Set up nodal values initially self.system.update_matrices() self.system.solve_accelerations() # Calculate accelerations of DOFs self.system.update_kinematics() # Update nodal values based on DOFs self.system.update_matrices() self.system.solve_reactions() # Solve reactions incl d'Alembert
class TestReactionForcesWithRotatedBeam(unittest.TestCase): """Intended to check the transformation from blade loading to rotor loading in a wind turbine rotor: the loads are applied to the beam in the local rotated coordinate system, check they work through to the ground reactions correctly. """ force = 24.1 length = 4.3 root_length = 0.0 def setUp(self): # FE model for beam - no modes, i.e. rigid self.x = x = linspace(0, self.length, 20) fe = BeamFE(x, density=2, EA=0, EIy=0, EIz=0) # Build the elements self.shaft = Hinge('shaft', [1, 0, 0]) self.roots = [] self.blades = [] self.pitch_bearings = [] for ib in range(1): R = rotations(('x', ib * 2 * pi / 3), ('y', -pi / 2)) root_offset = dot(R, [self.root_length, 0, 0]) root = RigidConnection('root%d' % (ib + 1), root_offset, R) bearing = Hinge('pitch%d' % (ib + 1), [1, 0, 0]) blade = ModalElementFromFE('blade%d' % (ib + 1), fe, 0) self.shaft.add_leaf(root) root.add_leaf(bearing) bearing.add_leaf(blade) self.roots.append(root) self.blades.append(blade) self.pitch_bearings.append(bearing) # Build system self.system = System() self.system.add_leaf(self.shaft) self.system.setup() self.system.update_kinematics() # Set up nodal values initially self.system.update_matrices() def test_reactions(self): # Some parameters L = self.length F = self.length * self.force # Set loading - in local z direction load = np.zeros((len(self.x), 3)) load[:, 2] = self.force self.blades[0].loading = load self.system.update_kinematics() self.system.update_matrices() self.system.solve_reactions() # Check reactions at ground (0, 0, 0) P = -self.system.joint_reactions['ground'] F_expected = [-F, 0, 0] M_expected = [0, -F * (L + self.root_length) / 2, 0] assert_aae(P, np.r_[F_expected, M_expected]) # Reactions on other side of hinge P2 = -self.system.joint_reactions['node-0'] assert_aae(P, P2) # Now set pitch angle to 45deg # NB: hinge rotation is opposite to wind turbine pitch convention self.pitch_bearings[0].xstrain[0] = -pi / 4 self.system.update_kinematics() self.system.update_matrices() self.system.solve_reactions() # Check reactions at ground (0, 0, 0) P = -self.system.joint_reactions['ground'] F_expected = [-F / sqrt(2), F / sqrt(2), 0] M_expected = [-F / sqrt(2) * L / 2, -F / sqrt(2) * L / 2, 0] assert_aae(P, np.r_[F_expected, M_expected]) # Reactions on other side of hinge P2 = -self.system.joint_reactions['node-0'] assert_aae(P, P2)
class TestReactionForcesOnModalElementFromFE(unittest.TestCase): """ System ------ A triangular rigid beam, offset by a rigid link from a hinge. Tests ----- Set the angular acceleration of the hinge. Check the reaction forces at the centre and at the root of the beam. """ mass = 5.0 # kg length = 20.0 # m offset = 3.2 # m force = -34.2 # N / m def setUp(self): # FE model for beam - no modes, i.e. rigid x = linspace(0, self.length, 20) density = (2 * self.mass / self.length) * (1 - x / self.length) fe = BeamFE(x, density=density, EA=0, EIy=1, EIz=0) fe.set_boundary_conditions('C', 'F') self.beam = ModalElementFromFE('beam', fe, 0) # Set loading - in Z direction load = np.zeros((len(x), 3)) load[:, 2] = self.force self.beam.loading = load # Offset from hinge axis self.conn = RigidConnection('offset', [self.offset, 0, 0]) # Hinge with axis along Y axis self.hinge = Hinge('hinge', [0, 1, 0]) # Build system self.system = System() self.system.add_leaf(self.hinge) self.hinge.add_leaf(self.conn) self.conn.add_leaf(self.beam) self.system.setup() self.system.update_kinematics() # Set up nodal values initially def test_reactions(self): # Set angular acceleration alpha = 1.235 # rad/s2 self.hinge.astrain[0] = alpha self.system.update_kinematics() # Update nodal values based on DOFs self.system.solve_reactions() # Solve reactions incl d'Alembert # Some parameters L = self.length m = self.mass Ro = self.offset Rg = L / 3 # distance to CoM along beam IG = m * L**2 / 18 assert_aae(m, self.beam.mass_vv[0, 0]) # Check reactions at beam root P = self.system.joint_reactions['node-1'] Fz_expected = (-m * (Ro + Rg) * alpha - self.force * L) My_expected = ((IG + m * Rg * (Ro + Rg)) * alpha + self.force * L**2 / 2) assert_aae(P, [0, 0, Fz_expected, 0, My_expected, 0])
class TestReactionForcesOnModalElementFromFE(unittest.TestCase): """ System ------ A triangular rigid beam, offset by a rigid link from a hinge. Tests ----- Set the angular acceleration of the hinge. Check the reaction forces at the centre and at the root of the beam. """ mass = 5.0 # kg length = 20.0 # m offset = 3.2 # m force = -34.2 # N / m def setUp(self): # FE model for beam - no modes, i.e. rigid x = linspace(0, self.length, 20) density = (2 * self.mass / self.length) * (1 - x / self.length) fe = BeamFE(x, density=density, EA=0, EIy=1, EIz=0) fe.set_boundary_conditions('C', 'F') self.beam = ModalElementFromFE('beam', fe, 0) # Set loading - in Z direction load = np.zeros((len(x), 3)) load[:, 2] = self.force self.beam.loading = load # Offset from hinge axis self.conn = RigidConnection('offset', [self.offset, 0, 0]) # Hinge with axis along Y axis self.hinge = Hinge('hinge', [0, 1, 0]) # Build system self.system = System() self.system.add_leaf(self.hinge) self.hinge.add_leaf(self.conn) self.conn.add_leaf(self.beam) self.system.setup() self.system.update_kinematics() # Set up nodal values initially def test_reactions(self): # Set angular acceleration alpha = 1.235 # rad/s2 self.hinge.astrain[0] = alpha self.system.update_kinematics() # Update nodal values based on DOFs self.system.solve_reactions() # Solve reactions incl d'Alembert # Some parameters L = self.length m = self.mass Ro = self.offset Rg = L / 3 # distance to CoM along beam IG = m * L ** 2 / 18 assert_aae(m, self.beam.mass_vv[0, 0]) # Check reactions at beam root P = self.system.joint_reactions['node-1'] Fz_expected = (-m * (Ro + Rg) * alpha - self.force * L) My_expected = ((IG + m * Rg * (Ro + Rg)) * alpha + self.force * L ** 2 / 2) assert_aae(P, [0, 0, Fz_expected, 0, My_expected, 0])
class TestReactionForcesWithRotatedBeam(unittest.TestCase): """Intended to check the transformation from blade loading to rotor loading in a wind turbine rotor: the loads are applied to the beam in the local rotated coordinate system, check they work through to the ground reactions correctly. """ force = 24.1 length = 4.3 root_length = 0.0 def setUp(self): # FE model for beam - no modes, i.e. rigid self.x = x = linspace(0, self.length, 20) fe = BeamFE(x, density=2, EA=0, EIy=0, EIz=0) # Build the elements self.shaft = Hinge('shaft', [1, 0, 0]) self.roots = [] self.blades = [] self.pitch_bearings = [] for ib in range(1): R = rotations(('x', ib*2*pi/3), ('y', -pi/2)) root_offset = dot(R, [self.root_length, 0, 0]) root = RigidConnection('root%d' % (ib+1), root_offset, R) bearing = Hinge('pitch%d' % (ib+1), [1, 0, 0]) blade = ModalElementFromFE('blade%d' % (ib+1), fe, 0) self.shaft.add_leaf(root) root.add_leaf(bearing) bearing.add_leaf(blade) self.roots.append(root) self.blades.append(blade) self.pitch_bearings.append(bearing) # Build system self.system = System() self.system.add_leaf(self.shaft) self.system.setup() self.system.update_kinematics() # Set up nodal values initially self.system.update_matrices() def test_reactions(self): # Some parameters L = self.length F = self.length * self.force # Set loading - in local z direction load = np.zeros((len(self.x), 3)) load[:, 2] = self.force self.blades[0].loading = load self.system.update_kinematics() self.system.update_matrices() self.system.solve_reactions() # Check reactions at ground (0, 0, 0) P = -self.system.joint_reactions['ground'] F_expected = [-F, 0, 0] M_expected = [0, -F*(L+self.root_length)/2, 0] assert_aae(P, np.r_[F_expected, M_expected]) # Reactions on other side of hinge P2 = -self.system.joint_reactions['node-0'] assert_aae(P, P2) # Now set pitch angle to 45deg # NB: hinge rotation is opposite to wind turbine pitch convention self.pitch_bearings[0].xstrain[0] = -pi / 4 self.system.update_kinematics() self.system.update_matrices() self.system.solve_reactions() # Check reactions at ground (0, 0, 0) P = -self.system.joint_reactions['ground'] F_expected = [-F/sqrt(2), F/sqrt(2), 0] M_expected = [-F/sqrt(2)*L/2, -F/sqrt(2)*L/2, 0] assert_aae(P, np.r_[F_expected, M_expected]) # Reactions on other side of hinge P2 = -self.system.joint_reactions['node-0'] assert_aae(P, P2)
def test_update_kinematics_results(self): # Test system: (all rigid connections of length 1) # # [hinge] # (gnd)---c1---(0) # (1)---c2---(2) # | # y c3 # | | # |--> x (3) # s = System() c1 = RigidConnection('c1', [1, 0, 0]) c2 = RigidConnection('c2', [1, 0, 0]) c3 = RigidConnection('c3', [0, -1, 0]) hinge = Hinge('hinge', [0, 0, 1]) s.add_leaf(c1) c1.add_leaf(hinge) hinge.add_leaf(c2) c2.add_leaf(c3) s.setup() # All velocities and accelerations should be zero for el in [c1, c2, c3, hinge]: assert_aae(el.vp, 0) assert_aae(el.vd, 0) assert_aae(el.ap, 0) assert_aae(el.ad, 0) # (gnd) assert_aae(c1.rp, 0) assert_aae(c1.Rp, np.eye(3)) # (0) assert_aae(c1.rd, [1, 0, 0]) assert_aae(c1.Rd, np.eye(3)) # (1) assert_aae(c2.rp, [1, 0, 0]) assert_aae(c2.Rp, np.eye(3)) # (2) assert_aae(c3.rp, [2, 0, 0]) assert_aae(c3.Rp, np.eye(3)) # (3) assert_aae(c3.rd, [2, -1, 0]) assert_aae(c3.Rd, np.eye(3)) ##### now set angular velocity of hinge ##### hinge.vstrain[0] = 1.0 s.update_kinematics() # (gnd) assert_aae(c1.vp, 0) assert_aae(c1.ap, 0) # (0) assert_aae(c1.vd, 0) assert_aae(c1.ad, 0) # (1) assert_aae(c2.vp, [0, 0, 0, 0, 0, 1.0]) assert_aae(c2.ap, 0) # (2) assert_aae(c3.vp, [0, 1, 0, 0, 0, 1.0]) assert_aae(c3.ap, [-1, 0, 0, 0, 0, 0]) # centripetal acceleration # (3) assert_aae(c3.vd, [1, 1, 0, 0, 0, 1.0]) assert_aae(c3.ad, [-1, 1, 0, 0, 0, 0]) # centripetal acceleration