class UniformCantileverWithLinearTwist_Test: """Values from R.H. MacNeal, R.L. Harder: "Proposed standard set of problems to test FE accuracy" """ length = 12.0 width = 1.1 depth = 0.32 E = 29.0e6 tip_twist = np.pi / 2 num_elements = 12 def setup(self): x = np.linspace(0, self.length, self.num_elements) twist = x * self.tip_twist / self.length EIy = self.E * self.width * self.depth**3 / 12 EIz = self.E * self.depth * self.width**3 / 12 self.fe = BeamFE(x, 0, 0, EIy, EIz, twist=twist) self.fe.set_boundary_conditions('C', 'F') def test_deflection_under_tip_load_y(self): Q = transverse_load(self.num_elements, magnitude=1, only_tip=True) defl, reactions = self.fe.static_deflection(Q=Q) assert_allclose(defl[-6:][1], 0.001754, atol=1e-5) def test_deflection_under_tip_load_z(self): Q = transverse_load(self.num_elements, magnitude=1, angle=(np.pi / 2), only_tip=True) defl, reactions = self.fe.static_deflection(Q=Q) assert_allclose(defl[-6:][2], 0.005424, atol=1e-5)
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 _mock_rigid_uniform_beam(density, length, name='beam'): """Return empty modal representation of 20m long rigid beam""" x = linspace(0, length, 20) fe = BeamFE(x, density=density, EA=0, EIy=1, EIz=0) fe.set_boundary_conditions('C', 'F') beam = ModalElementFromFE(name, fe, 0) return beam
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()
class UniformCantileverWithLinearTwist_Test: """Values from R.H. MacNeal, R.L. Harder: "Proposed standard set of problems to test FE accuracy" """ length = 12.0 width = 1.1 depth = 0.32 E = 29.0e6 tip_twist = np.pi / 2 num_elements = 12 def setup(self): x = np.linspace(0, self.length, self.num_elements) twist = x * self.tip_twist / self.length EIy = self.E * self.width * self.depth ** 3 / 12 EIz = self.E * self.depth * self.width ** 3 / 12 self.fe = BeamFE(x, 0, 0, EIy, EIz, twist=twist) self.fe.set_boundary_conditions('C', 'F') def test_deflection_under_tip_load_y(self): Q = transverse_load(self.num_elements, magnitude=1, only_tip=True) defl, reactions = self.fe.static_deflection(Q=Q) assert_allclose(defl[-6:][1], 0.001754, atol=1e-5) def test_deflection_under_tip_load_z(self): Q = transverse_load(self.num_elements, magnitude=1, angle=(np.pi / 2), only_tip=True) defl, reactions = self.fe.static_deflection(Q=Q) assert_allclose(defl[-6:][2], 0.005424, atol=1e-5)
def setup(self): x = np.linspace(0, self.length, self.num_elements) twist = x * self.tip_twist / self.length EIy = self.E * self.width * self.depth**3 / 12 EIz = self.E * self.depth * self.width**3 / 12 self.fe = BeamFE(x, 0, 0, EIy, EIz, twist=twist) self.fe.set_boundary_conditions('C', 'F')
def setUp(self): x = linspace(0, 1, 16) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=1, EA=0, EIy=1, EIz=0) self.fe.set_boundary_conditions('C', 'F') self.fe.set_dofs([False, False, True, False, True, False])
def setUp(self): data = np.loadtxt("tests/example_blade_data.txt") x, density, EA, EI_flap, EI_edge, twist = data.T # Twist has been saved in my convention (+ve X rotation), not Bladed self.fe = BeamFE(x, density, EA, EI_flap, EI_edge, twist=twist) self.fe.set_boundary_conditions('C', 'F') self.modal = ModalBeamFE(self.fe) self.answers = np.load("tests/example_blade_mode_results.npz")
def setUp(self): x = array([0.0, 10.0, 22.0, 28.0]) EI = array([[2e7, 2e7], [1e7, 1e7], [1e7, 1e7]]) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=0, EA=0, EIy=EI, EIz=0) self.fe.set_boundary_conditions('C', 'C') self.fe.set_dofs([False, False, True, False, True, False])
def setup(self): x = np.linspace(0, self.length, 10) self.fe = BeamFE(x, self.density, 0, self.EIy, self.EIz, twist=self.twist) self.fe.set_boundary_conditions('C', 'F')
def test_uniform_tension_increases_stiffness(self): x = np.linspace(0, self.length, 10) fe1 = BeamFE(x, self.density, 0, self.EI, self.EI) fe2 = BeamFE(x, self.density, 0, self.EI, self.EI, axial_force=20 * np.ones(10)) assert np.all(np.diag(fe2.Ks) >= np.diag(fe1.Ks))
def blade_fe(blade, root_length=0.0, spin=0.0): # positive blade twist is geometrically a negative x-rotation twist = -np.array(blade['twist']) x = blade['radii'] qn = interleave(root_length + np.array(x), 6) N = BeamFE.centrifugal_force_distribution(qn, blade['density']) fe = BeamFE(x, blade['density'], blade['EA'], blade['EIyy'], blade['EIzz'], twist=twist, axial_force=N * spin**2) fe.set_boundary_conditions('C', 'F') return fe
class UniformCantileverWithConstantTwist_Test: length = 3.2 density = 54.3 EIy = 494.2 EIz = 654.2 twist = np.radians(76.4) def setup(self): x = np.linspace(0, self.length, 10) self.fe = BeamFE(x, self.density, 0, self.EIy, self.EIz, twist=self.twist) self.fe.set_boundary_conditions('C', 'F') def test_mass(self): mass = self.length * self.density assert_allclose(self.fe.mass, mass, atol=0.5) def test_moment_of_mass(self): I = self.density * self.length**2 / 2 m = np.dot(self.fe.S1, self.fe.q0) assert_allclose(m[0], I, atol=0.5) def test_moment_of_inertia(self): Iyy = self.density * self.length**3 / 3 J = np.einsum('p, ijpq, q -> ij', self.fe.q0, self.fe.S2, self.fe.q0) assert_allclose(J[0, 0], Iyy, atol=0.5) assert_allclose(J[1:, 1:], 0) def test_deflection_under_uniform_load(self): w = 34.2 # N/m Q = self.fe.distribute_load(transverse_load(10, w)) defl, reactions = self.fe.static_deflection(Q) print(reactions) x, y, z = defl[0::6], defl[1::6], defl[2::6] # Resolve into local blade coordinates tw = self.twist wy = +w * np.cos(tw) wz = -w * np.sin(tw) local_y = wy * self.length**4 / (8 * self.EIz) # NB y defl -> EIzz local_z = wz * self.length**4 / (8 * self.EIy) assert_allclose(x, 0) assert_allclose(y[-1], local_y * np.cos(tw) - local_z * np.sin(tw)) assert_allclose(z[-1], local_z * np.cos(tw) + local_y * np.sin(tw)) assert_allclose(reactions[1], -w * self.length)
class TestBeamFE_Example62(unittest.TestCase): def setUp(self): x = linspace(0, 1, 16) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=1, EA=0, EIy=1, EIz=0) self.fe.set_boundary_conditions('C', 'F') self.fe.set_dofs([False, False, True, False, True, False]) def test_mode_frequencies(self): modal = self.fe.modal_matrices() assert_allclose(modal.w[:4], [3.5160, 22.0345, 61.6972, 120.9019], atol=1e-1)
class TestBeamFEAttachmentModes(unittest.TestCase): def setUp(self): x = array([0.0, 10.0, 22.0, 28.0]) EI = array([[2e7, 2e7], [1e7, 1e7], [1e7, 1e7]]) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=0, EA=0, EIy=EI, EIz=0) self.fe.set_boundary_conditions('C', 'C') self.fe.set_dofs([False, False, True, False, True, False]) def test_simple_model(self): am = self.fe.attachment_modes() self.assertEqual(am.shape, (4 * 6, 2 * 2))
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 ExampleBlade_Test(unittest.TestCase): def setUp(self): data = np.loadtxt("tests/example_blade_data.txt") x, density, EA, EI_flap, EI_edge, twist = data.T # Twist has been saved in my convention (+ve X rotation), not Bladed self.fe = BeamFE(x, density, EA, EI_flap, EI_edge, twist=twist) self.fe.set_boundary_conditions('C', 'F') self.modal = ModalBeamFE(self.fe) self.answers = np.load("tests/example_blade_mode_results.npz") def test_mass(self): assert_allclose(self.fe.mass, 6547, atol=0.5) def test_moment_of_mass(self): m = np.dot(self.fe.S1, self.fe.q0) assert_allclose(m[0], 84219, atol=0.5) def test_moment_of_inertia(self): J = np.einsum('p, ijpq, q -> ij', self.fe.q0, self.fe.S2, self.fe.q0) assert_allclose(J[0, 0], 1784881, atol=0.5) def test_first_four_modal_frequencies_match_saved_values(self): assert_allclose(self.modal.w[:4], self.answers['freqs'], atol=1e-3) def test_first_four_mode_shapes_match_saved_values(self): v = self.modal.shapes answer = self.answers['shapes'] for i in range(4): assert_allclose_ignoring_sign(v[:, i], answer[:, i], atol=1e-5) def test_mode_shapes_are_normalised(self): w = self.modal.w v = self.modal.shapes M = self.fe.M K = self.fe.K for i in range(v.shape[1]): assert_allclose(dot(v[:, i].T, dot(M, v[:, i])), 1.0) assert_allclose(dot(v[:, i].T, dot(K, v[:, i])), w[i]**2) def test_mode_are_sorted(self): w = list(self.modal.w) self.assertEqual(w, sorted(w)) def test_correct_number_of_modes_are_returned(self): w_all, v_all = self.fe.normal_modes() w, v = self.fe.normal_modes(4) assert_allclose(w, w_all[:4]) for i in range(4): assert_allclose_ignoring_sign(v[:, i], v_all[:, i])
class TestBeamFEAttachmentModes(unittest.TestCase): def setUp(self): x = array([0.0, 10.0, 22.0, 28.0]) EI = array([[2e7, 2e7], [1e7, 1e7], [1e7, 1e7]]) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=0, EA=0, EIy=EI, EIz=0) self.fe.set_boundary_conditions('C', 'C') self.fe.set_dofs([False, False, True, False, True, False]) def test_simple_model(self): am = self.fe.attachment_modes() self.assertEqual(am.shape, (4*6, 2*2))
def _make_random_element(rdm): # Choose some parameters randomly length = rdm.uniform(1, 10) density = rdm.uniform(0.1, 100) EA = rdm.uniform(1e1, 1e8) EIy = rdm.uniform(1e5, 1e8) EIz = rdm.uniform(1e5, 1e8) x = np.linspace(0, length, 20) fe = BeamFE(x, density, EA, EIy, EIz) fe.set_boundary_conditions('C', 'C') beam = DistalModalElementFromFE('el', fe, 5) beam._params = dict(length=length, density=density, EA=EA, EIy=EIy, EIz=EIz) return beam
def setup(self): x = np.linspace(0, self.length, self.num_elements) twist = x * self.tip_twist / self.length EIy = self.E * self.width * self.depth ** 3 / 12 EIz = self.E * self.depth * self.width ** 3 / 12 self.fe = BeamFE(x, 0, 0, EIy, EIz, twist=twist) self.fe.set_boundary_conditions('C', 'F')
def test_first_mode_frequency(self): # From Reddy1993, p. 160 x = np.linspace(0, 1, 16) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. fe = BeamFE(x, density=1, EA=0, EIy=1, EIz=0) fe.set_boundary_conditions('C', 'F') fe.set_dofs([False, False, True, False, True, False]) element = ModalElementFromFE('elem', fe) Mmodal = element.mass_ee Kmodal = element.K w = np.sqrt(np.diag(Kmodal) / np.diag(Mmodal)) assert_aae(w[0], 3.5160, decimal=4)
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()
class UniformCantileverWithConstantTwist_Test: length = 3.2 density = 54.3 EIy = 494.2 EIz = 654.2 twist = np.radians(76.4) def setup(self): x = np.linspace(0, self.length, 10) self.fe = BeamFE(x, self.density, 0, self.EIy, self.EIz, twist=self.twist) self.fe.set_boundary_conditions('C', 'F') def test_mass(self): mass = self.length * self.density assert_allclose(self.fe.mass, mass, atol=0.5) def test_moment_of_mass(self): I = self.density * self.length ** 2 / 2 m = np.dot(self.fe.S1, self.fe.q0) assert_allclose(m[0], I, atol=0.5) def test_moment_of_inertia(self): Iyy = self.density * self.length ** 3 / 3 J = np.einsum('p, ijpq, q -> ij', self.fe.q0, self.fe.S2, self.fe.q0) assert_allclose(J[0, 0], Iyy, atol=0.5) assert_allclose(J[1:, 1:], 0) def test_deflection_under_uniform_load(self): w = 34.2 # N/m Q = self.fe.distribute_load(transverse_load(10, w)) defl, reactions = self.fe.static_deflection(Q) print(reactions) x, y, z = defl[0::6], defl[1::6], defl[2::6] # Resolve into local blade coordinates tw = self.twist wy = +w * np.cos(tw) wz = -w * np.sin(tw) local_y = wy * self.length**4 / (8 * self.EIz) # NB y defl -> EIzz local_z = wz * self.length**4 / (8 * self.EIy) assert_allclose(x, 0) assert_allclose(y[-1], local_y * np.cos(tw) - local_z * np.sin(tw)) assert_allclose(z[-1], local_z * np.cos(tw) + local_y * np.sin(tw)) assert_allclose(reactions[1], -w * self.length)
def setUp(self): x = array([0.0, 10.0, 22.0, 28.0]) EI = array([[2e7, 2e7], [1e7, 1e7], [1e7, 1e7]]) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=0, EA=0, EIy=EI, EIz=0) self.fe.set_boundary_conditions('P', 'C') self.fe.set_dofs([False, False, True, False, True, False])
def test_rigid_element_reference_loading(self): # Make an element with no modes (rigid) fe = BeamFE(np.linspace(0, 1, 11), density=1, EA=0, EIy=1, EIz=0) fe.set_boundary_conditions('C', 'F') fe.set_dofs([False, False, True, False, True, False]) element = ModalElementFromFE('elem', fe, 0) # Distributed load, linearly interpolated load = np.zeros((11, 3)) load[:, 2] = -100 # Uniform load in z direction element.apply_distributed_loading(load) assert_aae(element.applied_stress, []) assert_aae(element.applied_forces[0:6], [0, 0, -100 * 1, 0, 50, 0]) assert_aae(element.applied_forces[6:12], 0) # Distributed load, triangle at tip load = np.zeros((11, 3)) load[-1, 2] = -100 # tapered load in z direction element.applied_forces[:] = 0 # reset element.apply_distributed_loading(load) F = -100 * 0.1 / 2 assert_aae(element.applied_forces[0:6], [0, 0, F, 0, -F * (0.9 + 0.1 * 2 / 3), 0]) assert_aae(element.applied_forces[6:12], 0)
class AppliedLoads_Tests: def setup(self): self.fe = BeamFE(linspace(0, 10, 11), density=0, EA=0, EIy=1, EIz=1) def test_uniform_load(self): f = array([3.4, 5.6, 7.2]) load = zeros(6 * 11) for i in range(3): load[i::6] = f[i] # Force F = dot(self.fe.F1, load) assert_allclose(F, f * 10) # Moment q = self.fe.q0 I = np.vstack(( dot(q.T, (self.fe.F2[1, 2] - self.fe.F2[2, 1])), dot(q.T, (self.fe.F2[2, 0] - self.fe.F2[0, 2])), dot(q.T, (self.fe.F2[0, 1] - self.fe.F2[1, 0])), )) Q = dot(I, load) assert_allclose(Q, [0, -f[2] * 10 * 5, f[1] * 10 * 5]) def test_linear_load(self): f = array([3.4, 5.6, 7.2]) load = zeros(6 * 11) for i in range(3): load[i::6] = linspace(0, f[i], 11) # Force F = dot(self.fe.F1, load) assert_allclose(F, f * 10 / 2) # Moment q = self.fe.q0 I = np.vstack(( dot(q.T, (self.fe.F2[1, 2] - self.fe.F2[2, 1])), dot(q.T, (self.fe.F2[2, 0] - self.fe.F2[0, 2])), dot(q.T, (self.fe.F2[0, 1] - self.fe.F2[1, 0])), )) Q = dot(I, load) assert_allclose( Q, [0, -f[2] * 10 / 2 * 10 * 2 / 3, f[1] * 10 / 2 * 10 * 2 / 3]) # Check stresses assert_allclose(dot(self.fe.F, load), self.fe.distribute_load(load))
class TestBeamFE_Example42(unittest.TestCase): def setUp(self): x = array([0.0, 4.0, 10.0]) EI = 144.0 # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=0, EA=0, EIy=EI, EIz=0) self.fe.set_boundary_conditions('C', 'F') self.fe.set_dofs([False, False, True, False, True, False]) def test_stiffness(self): # Reddy1993, p 164 expected = array([ [27, 0, 0, 0, 0, 0], [-54, 144, 0, 0, 0, 0], [-27, 54, 27 + 8, 0, 0, 0], [-54, 72, 54 - 24, 144 + 96, 0, 0], [0, 0, -8, 24, 8, 0], [0, 0, -24, 48, 24, 96], ]) expected += expected.T - np.diag(expected.diagonal()) # make symmetric expected_II = expected[2:6, 2:6] expected_IB = expected[2:6, 0:2] assert_allclose(self.fe.K_II, expected_II) assert_allclose(self.fe.K_IB, expected_IB) def test_distributed_load(self): # Distributed force on second element: load = array([0, 0, 0, 0, 0, 0, 0, 0, -100, 0, 0, 0]) Q = self.fe.distribute_load_on_element(1, load) Q = Q[[2, 4, 8, 10, 14, 16]] assert_allclose(Q, [0, 0, -90, 120, -210, -180]) def test_solution_without_spring(self): # Distributed force on first element: load = array([0, 0, 0, 0, 0, 0, 0, 0, -100, 0, 0, 0]) QF = self.fe.distribute_load_on_element(1, load) # Solve static deflection deflections, reactions = self.fe.static_deflection(QF) # Expected values from Reddy expected_deflections = zeros_like(deflections) expected_deflections[[ 8, 10, 14, 16 ]] = array([-1.6, 0.72, -7.108, 0.99]) * 1e4 / 143.0 assert_allclose(deflections, expected_deflections, atol=1e1)
class TestBeamFE_Example42(unittest.TestCase): def setUp(self): x = array([0.0, 4.0, 10.0]) EI = 144.0 # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=0, EA=0, EIy=EI, EIz=0) self.fe.set_boundary_conditions('C', 'F') self.fe.set_dofs([False, False, True, False, True, False]) def test_stiffness(self): # Reddy1993, p 164 expected = array([ [27, 0, 0, 0, 0, 0], [-54, 144, 0, 0, 0, 0], [-27, 54, 27+8, 0, 0, 0], [-54, 72, 54-24, 144+96, 0, 0], [0, 0, -8, 24, 8, 0], [0, 0, -24, 48, 24, 96], ]) expected += expected.T - np.diag(expected.diagonal()) # make symmetric expected_II = expected[2:6, 2:6] expected_IB = expected[2:6, 0:2] assert_allclose(self.fe.K_II, expected_II) assert_allclose(self.fe.K_IB, expected_IB) def test_distributed_load(self): # Distributed force on second element: load = array([0, 0, 0, 0, 0, 0, 0, 0, -100, 0, 0, 0]) Q = self.fe.distribute_load_on_element(1, load) Q = Q[[2, 4, 8, 10, 14, 16]] assert_allclose(Q, [0, 0, -90, 120, -210, -180]) def test_solution_without_spring(self): # Distributed force on first element: load = array([0, 0, 0, 0, 0, 0, 0, 0, -100, 0, 0, 0]) QF = self.fe.distribute_load_on_element(1, load) # Solve static deflection deflections, reactions = self.fe.static_deflection(QF) # Expected values from Reddy expected_deflections = zeros_like(deflections) expected_deflections[[8, 10, 14, 16]] = array( [-1.6, 0.72, -7.108, 0.99]) * 1e4 / 143.0 assert_allclose(deflections, expected_deflections, atol=1e1)
class AppliedLoads_Tests: def setup(self): self.fe = BeamFE(linspace(0, 10, 11), density=0, EA=0, EIy=1, EIz=1) def test_uniform_load(self): f = array([3.4, 5.6, 7.2]) load = zeros(6 * 11) for i in range(3): load[i::6] = f[i] # Force F = dot(self.fe.F1, load) assert_allclose(F, f * 10) # Moment q = self.fe.q0 I = np.vstack(( dot(q.T, (self.fe.F2[1, 2] - self.fe.F2[2, 1])), dot(q.T, (self.fe.F2[2, 0] - self.fe.F2[0, 2])), dot(q.T, (self.fe.F2[0, 1] - self.fe.F2[1, 0])), )) Q = dot(I, load) assert_allclose(Q, [0, -f[2]*10*5, f[1]*10*5]) def test_linear_load(self): f = array([3.4, 5.6, 7.2]) load = zeros(6 * 11) for i in range(3): load[i::6] = linspace(0, f[i], 11) # Force F = dot(self.fe.F1, load) assert_allclose(F, f * 10 / 2) # Moment q = self.fe.q0 I = np.vstack(( dot(q.T, (self.fe.F2[1, 2] - self.fe.F2[2, 1])), dot(q.T, (self.fe.F2[2, 0] - self.fe.F2[0, 2])), dot(q.T, (self.fe.F2[0, 1] - self.fe.F2[1, 0])), )) Q = dot(I, load) assert_allclose(Q, [0, -f[2]*10/2 * 10*2/3, f[1]*10/2 * 10*2/3]) # Check stresses assert_allclose(dot(self.fe.F, load), self.fe.distribute_load(load))
def test_static_deflection(self): x = array([0.0, 4.0, 10.0]) EI = 144.0 # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. fe = BeamFE(x, density=10, EA=0, EIy=EI, EIz=0) fe.set_boundary_conditions('C', 'F') fe.set_dofs([False, False, True, False, True, False]) element = ModalElementFromFE('elem', fe) # Distributed load, linearly interpolated load = np.zeros((3, 3)) load[-1, 2] = -100 # Load in z direction at tip element.apply_distributed_loading(load) defl = -element.applied_stress / np.diag(element.K) # Check against directly calculating static deflection from FE Q = fe.distribute_load(interleave(load, 6)) defl_fe, reactions_fe = fe.static_deflection(Q) assert_aae(dot(element.shapes, defl), defl_fe, decimal=2)
def setup(self): self.fe = BeamFE(linspace(0, 10, 11), density=0, EA=0, EIy=1, EIz=1)
class TestBeamFE_Example41(unittest.TestCase): def setUp(self): x = array([0.0, 10.0, 22.0, 28.0]) EI = array([[2e7, 2e7], [1e7, 1e7], [1e7, 1e7]]) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=0, EA=0, EIy=EI, EIz=0) self.fe.set_boundary_conditions('P', 'C') self.fe.set_dofs([False, False, True, False, True, False]) def test_stiffness(self): # Reddy1993, pp 161-162 expected = 1e7 * array([ [0.024, -0.12, -0.024, -0.12, 0, 0, 0, 0], [0, 0.80, 0.12, 0.40, 0, 0, 0, 0], [0, 0, 0.0309, 0.0783, -0.00694, -0.04167, 0, 0], [0, 0, 0, 1.133, 0.0417, 0.167, 0, 0], [0, 0, 0, 0, 0.0625, -0.125, -0.0556, -0.167], [0, 0, 0, 0, 0, 1, 0.1667, 0.333], [0, 0, 0, 0, 0, 0, 0.0556, 0.1667], [0, 0, 0, 0, 0, 0, 0, 0.6667], ]) expected += expected.T - np.diag(expected.diagonal()) # make symmetric expected_II = expected[1:6, 1:6] expected_IB = expected[1:6, [0, 6, 7]] assert_allclose(expected_II, self.fe.K_II, atol=1e-2 * 1e7) assert_allclose(expected_IB, self.fe.K_IB, atol=1e-3 * 1e7) def test_distributed_load(self): # Distributed force on first element: load = array([0, 0, -2400, 0, 0, 0, 0, 0, -2400, 0, 0, 0]) Q = self.fe.distribute_load_on_element(0, load) Q = Q[[2, 4, 8, 10, 14, 16, 20, 22]] assert_allclose(Q / 1e3, [-12, 20, -12, -20, 0, 0, 0, 0]) def test_solution(self): # Distributed force on first element: load = array([0, 0, -2400, 0, 0, 0, 0, 0, -2400, 0, 0, 0]) QF = self.fe.distribute_load_on_element(0, load) # Nodal forces: Q = np.zeros(self.fe.K.shape[0]) Q[14] = -10000 # z force at 3rd node # Solve static deflection deflections, reactions = self.fe.static_deflection(QF + Q) # Expected values from Reddy expected_deflections = zeros_like(deflections) expected_deflections[[4, 8, 10, 14, 16]] = [ 0.03856, -0.2808, 0.01214, -0.1103, -0.02752 ] assert_allclose(deflections, expected_deflections, atol=1e-4) expected_reactions = zeros_like(reactions) expected_reactions[[2, 20, 22]] = [18565.54, 15434.46, 92164.83] assert_allclose(reactions, expected_reactions, atol=1e-2) def test_load_matrix_gives_same_result_as_method(self): # Distributed force on all elements load = np.zeros(4 * 6) load[2::6] = [350, 324, 654, 54] # Z component Q1 = self.fe.distribute_load(load) Q2 = dot(self.fe.F, load) assert_allclose(Q1, Q2)
class UniformCantilever_Test: length = 3.2 density = 54.3 EI = 494.2 def setup(self): x = np.linspace(0, self.length, 10) self.fe = BeamFE(x, self.density, 0, self.EI, self.EI) self.fe.set_boundary_conditions('C', 'F') def test_mass(self): mass = self.length * self.density assert_allclose(self.fe.mass, mass, atol=0.5) def test_moment_of_mass(self): I = self.density * self.length**2 / 2 m = np.dot(self.fe.S1, self.fe.q0) assert_allclose(m[0], I, atol=0.5) def test_moment_of_inertia(self): Iyy = self.density * self.length**3 / 3 J = np.einsum('p, ijpq, q -> ij', self.fe.q0, self.fe.S2, self.fe.q0) assert_allclose(J[0, 0], Iyy, atol=0.5) assert_allclose(J[1:, 1:], 0) def test_deflection_with_tip_load(self): # Simple tip load should produce databook tip deflection W = 54.1 # N Q = transverse_load(10, W, only_tip=True) defl, reactions = self.fe.static_deflection(Q=Q) x, y, z = defl[0::6], defl[1::6], defl[2::6] assert_allclose(x, 0) assert_allclose(z, 0) assert_allclose(y[-1], W * self.length**3 / (3 * self.EI)) def test_deflection_under_uniform_load(self): # Simple uniform load should produce databook tip deflection w = 34.2 # N/m Q = self.fe.distribute_load(transverse_load(10, magnitude=w)) defl, reactions = self.fe.static_deflection(Q) x, y, z = defl[0::6], defl[1::6], defl[2::6] assert_allclose(x, 0) assert_allclose(z, 0) assert_allclose(y[-1], w * self.length**4 / (8 * self.EI)) def test_deflection_is_parallel_to_uniform_loading(self): w = 67.4 # distributed load (N/m) theta = np.radians(35.4) # angle from y axis of load Q = self.fe.distribute_load(transverse_load(10, w, theta)) defl, reactions = self.fe.static_deflection(Q) x, y, z = defl[0::6], defl[1::6], defl[2::6] assert_allclose(x, 0) load_angle = np.arctan2(z, y) assert_allclose(load_angle[1:], theta) def test_reaction_force(self): # Simple uniform load should produce databook tip deflection w = 34.2 # N/m F = transverse_load(10, w) # Reaction force is F1 * F R = np.dot(self.fe.F1, F) assert_allclose(R, [0, w * self.length, 0])
class UniformCantilever_Test: length = 3.2 density = 54.3 EI = 494.2 def setup(self): x = np.linspace(0, self.length, 10) self.fe = BeamFE(x, self.density, 0, self.EI, self.EI) self.fe.set_boundary_conditions('C', 'F') def test_mass(self): mass = self.length * self.density assert_allclose(self.fe.mass, mass, atol=0.5) def test_moment_of_mass(self): I = self.density * self.length ** 2 / 2 m = np.dot(self.fe.S1, self.fe.q0) assert_allclose(m[0], I, atol=0.5) def test_moment_of_inertia(self): Iyy = self.density * self.length ** 3 / 3 J = np.einsum('p, ijpq, q -> ij', self.fe.q0, self.fe.S2, self.fe.q0) assert_allclose(J[0, 0], Iyy, atol=0.5) assert_allclose(J[1:, 1:], 0) def test_deflection_with_tip_load(self): # Simple tip load should produce databook tip deflection W = 54.1 # N Q = transverse_load(10, W, only_tip=True) defl, reactions = self.fe.static_deflection(Q=Q) x, y, z = defl[0::6], defl[1::6], defl[2::6] assert_allclose(x, 0) assert_allclose(z, 0) assert_allclose(y[-1], W * self.length**3 / (3 * self.EI)) def test_deflection_under_uniform_load(self): # Simple uniform load should produce databook tip deflection w = 34.2 # N/m Q = self.fe.distribute_load(transverse_load(10, magnitude=w)) defl, reactions = self.fe.static_deflection(Q) x, y, z = defl[0::6], defl[1::6], defl[2::6] assert_allclose(x, 0) assert_allclose(z, 0) assert_allclose(y[-1], w * self.length**4 / (8 * self.EI)) def test_deflection_is_parallel_to_uniform_loading(self): w = 67.4 # distributed load (N/m) theta = np.radians(35.4) # angle from y axis of load Q = self.fe.distribute_load(transverse_load(10, w, theta)) defl, reactions = self.fe.static_deflection(Q) x, y, z = defl[0::6], defl[1::6], defl[2::6] assert_allclose(x, 0) load_angle = np.arctan2(z, y) assert_allclose(load_angle[1:], theta) def test_reaction_force(self): # Simple uniform load should produce databook tip deflection w = 34.2 # N/m F = transverse_load(10, w) # Reaction force is F1 * F R = np.dot(self.fe.F1, F) assert_allclose(R, [0, w * self.length, 0])
class TestBeamFE_Example41(unittest.TestCase): def setUp(self): x = array([0.0, 10.0, 22.0, 28.0]) EI = array([[2e7, 2e7], [1e7, 1e7], [1e7, 1e7]]) # Using the z axis as the transverse direction gives the same # sign convention as Reddy uses in 2D, namely that rotations # are positive clockwise. self.fe = BeamFE(x, density=0, EA=0, EIy=EI, EIz=0) self.fe.set_boundary_conditions('P', 'C') self.fe.set_dofs([False, False, True, False, True, False]) def test_stiffness(self): # Reddy1993, pp 161-162 expected = 1e7 * array([ [0.024, -0.12, -0.024, -0.12, 0, 0, 0, 0], [0, 0.80, 0.12, 0.40, 0, 0, 0, 0], [0, 0, 0.0309, 0.0783, -0.00694, -0.04167, 0, 0], [0, 0, 0, 1.133, 0.0417, 0.167, 0, 0], [0, 0, 0, 0, 0.0625, -0.125, -0.0556, -0.167], [0, 0, 0, 0, 0, 1, 0.1667, 0.333], [0, 0, 0, 0, 0, 0, 0.0556, 0.1667], [0, 0, 0, 0, 0, 0, 0, 0.6667], ]) expected += expected.T - np.diag(expected.diagonal()) # make symmetric expected_II = expected[1:6, 1:6] expected_IB = expected[1:6, [0, 6, 7]] assert_allclose(expected_II, self.fe.K_II, atol=1e-2 * 1e7) assert_allclose(expected_IB, self.fe.K_IB, atol=1e-3 * 1e7) def test_distributed_load(self): # Distributed force on first element: load = array([0, 0, -2400, 0, 0, 0, 0, 0, -2400, 0, 0, 0]) Q = self.fe.distribute_load_on_element(0, load) Q = Q[[2, 4, 8, 10, 14, 16, 20, 22]] assert_allclose(Q / 1e3, [-12, 20, -12, -20, 0, 0, 0, 0]) def test_solution(self): # Distributed force on first element: load = array([0, 0, -2400, 0, 0, 0, 0, 0, -2400, 0, 0, 0]) QF = self.fe.distribute_load_on_element(0, load) # Nodal forces: Q = np.zeros(self.fe.K.shape[0]) Q[14] = -10000 # z force at 3rd node # Solve static deflection deflections, reactions = self.fe.static_deflection(QF + Q) # Expected values from Reddy expected_deflections = zeros_like(deflections) expected_deflections[[4, 8, 10, 14, 16]] = [0.03856, -0.2808, 0.01214, -0.1103, -0.02752] assert_allclose(deflections, expected_deflections, atol=1e-4) expected_reactions = zeros_like(reactions) expected_reactions[[2, 20, 22]] = [18565.54, 15434.46, 92164.83] assert_allclose(reactions, expected_reactions, atol=1e-2) def test_load_matrix_gives_same_result_as_method(self): # Distributed force on all elements load = np.zeros(4 * 6) load[2::6] = [350, 324, 654, 54] # Z component Q1 = self.fe.distribute_load(load) Q2 = dot(self.fe.F, load) assert_allclose(Q1, Q2)