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_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:])])
Exemple #3
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()
Exemple #4
0
    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
Exemple #5
0
    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
Exemple #6
0
    def test_adding_elements(self):
        conn = RigidConnection('conn')
        body = RigidBody('body', mass=1.235)
        s = System()
        s.add_leaf(conn)
        conn.add_leaf(body)
        s.setup()

        # Should have dict of elements
        self.assertEqual(s.elements, {'conn': conn, 'body': body})

        # Number of states:
        #   6 ground
        # + 6 constraints on conn
        # + 6 <node-0>   between conn and body
        # ---
        #  18
        self.assertEqual(s.lhs.shape, (18, 18))
        for vec in (s.rhs, s.qd, s.qdd):
            self.assertEqual(len(vec), 18)

        # Check there are no dofs
        self.assertEqual(len(s.q.dofs), 0)
        self.assertEqual(len(s.qd.dofs), 0)
        self.assertEqual(len(s.qdd.dofs), 0)
    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):
        # 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 setUp(self):
        # Parameters
        mass = 11.234
        length = 2.54
        gravity = 9.81

        # Build model
        hinge = Hinge('hinge', [0, 1, 0])
        link = RigidConnection('link', [length, 0, 0])
        body = RigidBody('body', mass)

        system = System(gravity=gravity)
        system.add_leaf(hinge)
        hinge.add_leaf(link)
        link.add_leaf(body)
        system.setup()

        # Custom outputs to calculate correct answer
        def force_body_prox_local(s):
            theta = s.q[hinge.istrain][0]
            thetadot = s.qd[hinge.istrain][0]
            thetadotdot = s.qdd[hinge.istrain][0]
            Fx = mass * (-gravity*np.sin(theta) - length*thetadot**2)
            Fz = mass * (+gravity*np.cos(theta) - length*thetadotdot)
            return [Fx, 0, Fz, 0, 0, 0]

        def force_hinge_prox(s):
            theta = s.q[hinge.istrain][0]
            thetadot = s.qd[hinge.istrain][0]
            thetadotdot = s.qdd[hinge.istrain][0]
            A = np.array([[+np.cos(theta), np.sin(theta)],
                          [-np.sin(theta), np.cos(theta)]])
            Fxz = -mass * length * np.dot(A, [thetadot**2, thetadotdot])
            return [Fxz[0], 0, Fxz[1] + gravity*mass, 0, 0, 0]

        # Solver
        integ = Integrator(system, ('pos', 'vel', 'acc'))
        integ.add_output(LoadOutput(hinge.iprox))
        integ.add_output(LoadOutput(link.iprox))
        integ.add_output(LoadOutput(body.iprox))
        integ.add_output(LoadOutput(body.iprox, local=True))
        integ.add_output(CustomOutput(force_hinge_prox, "correct ground"))
        integ.add_output(CustomOutput(force_body_prox_local,
                                      "correct link distal local"))

        self.system = system
        self.integ = integ
Exemple #10
0
    def setUp(self):
        # Parameters
        mass = 11.234
        length = 2.54
        gravity = 9.81

        # Build model
        hinge = Hinge('hinge', [0, 1, 0])
        link = RigidConnection('link', [length, 0, 0])
        body = RigidBody('body', mass)

        system = System(gravity=gravity)
        system.add_leaf(hinge)
        hinge.add_leaf(link)
        link.add_leaf(body)
        system.setup()

        # Custom outputs to calculate correct answer
        def force_body_prox_local(s):
            theta = s.q[hinge.istrain][0]
            thetadot = s.qd[hinge.istrain][0]
            thetadotdot = s.qdd[hinge.istrain][0]
            Fx = mass * (-gravity * np.sin(theta) - length * thetadot**2)
            Fz = mass * (+gravity * np.cos(theta) - length * thetadotdot)
            return [Fx, 0, Fz, 0, 0, 0]

        def force_hinge_prox(s):
            theta = s.q[hinge.istrain][0]
            thetadot = s.qd[hinge.istrain][0]
            thetadotdot = s.qdd[hinge.istrain][0]
            A = np.array([[+np.cos(theta), np.sin(theta)],
                          [-np.sin(theta), np.cos(theta)]])
            Fxz = -mass * length * np.dot(A, [thetadot**2, thetadotdot])
            return [Fxz[0], 0, Fxz[1] + gravity * mass, 0, 0, 0]

        # Solver
        integ = Integrator(system, ('pos', 'vel', 'acc'))
        integ.add_output(LoadOutput(hinge.iprox))
        integ.add_output(LoadOutput(link.iprox))
        integ.add_output(LoadOutput(body.iprox))
        integ.add_output(LoadOutput(body.iprox, local=True))
        integ.add_output(CustomOutput(force_hinge_prox, "correct ground"))
        integ.add_output(
            CustomOutput(force_body_prox_local, "correct link distal local"))

        self.system = system
        self.integ = integ
Exemple #11
0
    def test_iter_elements(self):
        #     /-- c2
        #  c1-|
        #     \-- c3 --- c4
        s = System()
        c1 = RigidConnection('c1')
        c2 = RigidConnection('c2')
        c3 = RigidConnection('c3')
        c4 = RigidConnection('c4')
        s.add_leaf(c1)
        c1.add_leaf(c2)
        c1.add_leaf(c3)
        c3.add_leaf(c4)
        s.setup()

        # Should iter elements depth-first
        self.assertEqual(list(s.iter_elements()),
                         [c1, c2, c3, c4])
Exemple #12
0
    def test_assemble(self):
        # Test system:
        #
        #                   /-- m2
        #  m1 -----conn----|
        #                   \-- m3
        s = System()
        m1 = RigidBody('m1', 1.3)
        m2 = RigidBody('m2', 3.4)
        m3 = RigidBody('m3', 7.5)
        conn = RigidConnection('conn')
        s.add_leaf(conn)
        s.add_leaf(m1)
        conn.add_leaf(m2)
        conn.add_leaf(m3)
        s.setup()

        # Check starting mass matrices of elements are as expected
        assert_aae(np.diag(m1.mass_vv[:3, :3]), 1.3)
        assert_aae(np.diag(m2.mass_vv[:3, :3]), 3.4)
        assert_aae(np.diag(m3.mass_vv[:3, :3]), 7.5)

        # Initially make system matrix empty for testing
        s.lhs[:, :] = 0
        assert_aae(s.lhs, 0)

        # After assembly, the mass matrices are put in the correct places:
        #   0:6  -> m1 node
        #   6:12 -> conn constraints
        #  12:18 -> m2 node
        #  12:18 -> m3 node
        s.assemble()
        M = s.lhs.copy()
        # Subtract expected mass
        M[0:6, 0:6] -= m1.mass_vv
        M[12:18, 12:18] -= m2.mass_vv + m3.mass_vv
        # Subtract expected constraints
        M[0:6, 6:12] -= conn.F_vp
        M[6:12, 0:6] -= conn.F_vp
        M[12:18, 6:12] -= conn.F_vd
        M[6:12, 12:18] -= conn.F_vd
        assert_aae(M, 0)
Exemple #13
0
def build_system():
    # Calculate inertia, stiffness and damping
    I2 = mass * length**2
    k = (2 * np.pi * natfreq)**2 * I2
    c = 2 * damping_factor * I2 * (2 * np.pi * natfreq)

    # Build model
    hinge = Hinge('hinge', [0, 0, 1])
    hinge.stiffness = k
    hinge.damping = c
    link = RigidConnection('link', [length, 0, 0])
    body = RigidBody('body', mass)

    system = System()
    system.add_leaf(hinge)
    hinge.add_leaf(link)
    link.add_leaf(body)
    system.setup()

    return system
Exemple #14
0
def build_system():
    # Calculate inertia, stiffness and damping
    I2 = mass * length**2
    k = (2*np.pi*natfreq)**2 * I2
    c = 2 * damping_factor * I2 * (2*np.pi*natfreq)

    # Build model
    hinge = Hinge('hinge', [0,0,1])
    hinge.stiffness = k
    hinge.damping = c
    link = RigidConnection('link', [length, 0, 0])
    body = RigidBody('body', mass)

    system = System()
    system.add_leaf(hinge)
    hinge.add_leaf(link)
    link.add_leaf(body)
    system.setup()

    return system
Exemple #15
0
    def test_applied_force(self):
        # Set up a hinge with a mass offset on a rigid body. The
        # reduced system should have 1 DOF -- the hinge rotation --
        # with the associated mass being the inertia of the mass about
        # the hinge, and the associated generalised force being the
        # applied moment.
        mass = 36.2
        zforce = -30
        L = 3.2
        s = System()
        h = Hinge('hinge', [0, 1, 0])
        c = RigidConnection('conn', [L, 0, 0])
        b = RigidBody('body', mass, nodal_load=[0, 0, zforce])
        s.add_leaf(h)
        h.add_leaf(c)
        c.add_leaf(b)
        s.setup()

        rsys = ReducedSystem(s)
        self.assertEqual(rsys.M.shape, (1, 1))
        self.assertEqual(rsys.Q.shape, (1, ))
        self.assertEqual(rsys.M[0, 0], mass * L**2)  # inertial about hinge
        self.assertEqual(rsys.Q[0], -zforce * L)  # moment about hinge
Exemple #16
0
    def test_applied_force(self):
        # Set up a hinge with a mass offset on a rigid body. The
        # reduced system should have 1 DOF -- the hinge rotation --
        # with the associated mass being the inertia of the mass about
        # the hinge, and the associated generalised force being the
        # applied moment.
        mass = 36.2
        zforce = -30
        L = 3.2
        s = System()
        h = Hinge('hinge', [0, 1, 0])
        c = RigidConnection('conn', [L, 0, 0])
        b = RigidBody('body', mass, nodal_load=[0, 0, zforce])
        s.add_leaf(h)
        h.add_leaf(c)
        c.add_leaf(b)
        s.setup()

        rsys = ReducedSystem(s)
        self.assertEqual(rsys.M.shape, (1, 1))
        self.assertEqual(rsys.Q.shape, (1,))
        self.assertEqual(rsys.M[0, 0], mass * L**2)  # inertial about hinge
        self.assertEqual(rsys.Q[0], -zforce * L)  # moment about hinge
Exemple #17
0
    def test_adding_elements_with_strains(self):
        slider = PrismaticJoint('slider', [1, 0, 0])
        conn = RigidConnection('conn')
        body = RigidBody('body', mass=1.235)
        s = System()
        s.add_leaf(slider)
        slider.add_leaf(conn)
        conn.add_leaf(body)
        s.setup()

        # Should have dict of elements
        self.assertEqual(s.elements,
                         {'slider': slider, 'conn': conn, 'body': body})

        # Number of states:
        #   6 ground
        # + 6 constraints on slider
        # + 1 strain in slider
        # + 6 <node-0>   between slider and conn
        # + 6 constraints on conn
        # + 6 <node-1>   between conn and body
        # ---
        #  31
        self.assertEqual(s.lhs.shape, (31, 31))
        for vec in (s.rhs, s.qd, s.qdd):
            self.assertEqual(len(vec), 31)

        # Check there is the one slider dof
        self.assertEqual(len(s.q.dofs), 1)
        self.assertEqual(len(s.qd.dofs), 1)
        self.assertEqual(len(s.qdd.dofs), 1)

        # After prescribing the slider, there should be no dofs
        s.prescribe(slider)
        self.assertEqual(len(s.q.dofs), 0)
        self.assertEqual(len(s.qd.dofs), 0)
        self.assertEqual(len(s.qdd.dofs), 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])
Exemple #19
0
    def setUp(self):
        # Parameters
        mass = 11.234
        length = 2.54
        gravity = 9.81

        # Build model
        slider = PrismaticJoint('slider', [1, 0, 0])
        link = RigidConnection('link', [0, 0, length])
        body = RigidBody('body', mass)

        system = System(gravity=gravity)
        system.add_leaf(slider)
        slider.add_leaf(link)
        link.add_leaf(body)
        system.setup()

        # Prescribe motion -- sinusoidal acceleration
        motion_frequency = 1  # Hz
        motion_amplitude = 2.3  # m

        # x =  motion_amplitude * np.cos(w*t)
        # v = -motion_amplitude * np.sin(w*t) * w
        # a = -motion_amplitude * np.cos(w*t) * w**2
        def prescribed_acceleration(t):
            w = 2 * np.pi * motion_frequency
            return -w**2 * motion_amplitude * np.cos(w * t)

        system.prescribe(slider, prescribed_acceleration)

        # Set the correct initial condition
        system.q[slider.istrain][0] = motion_amplitude
        system.qd[slider.istrain][0] = 0.0

        # Custom outputs to calculate correct answer
        def force_body_prox(s):
            a = prescribed_acceleration(s.time)
            Fx = mass * a
            Fz = mass * gravity
            return [Fx, 0, Fz, 0, 0, 0]

        def force_link_prox(s):
            a = prescribed_acceleration(s.time)
            Fx = mass * a
            Fz = mass * gravity
            My = length * Fx
            return [Fx, 0, Fz, 0, My, 0]

        def force_slider_prox(s):
            a = prescribed_acceleration(s.time)
            x = -a / (2 * np.pi * motion_frequency)**2
            Fx = mass * a
            Fz = mass * gravity
            My = length * Fx - x * Fz
            return [Fx, 0, Fz, 0, My, 0]

        # Solver
        integ = Integrator(system, ('pos', 'vel', 'acc'))
        integ.add_output(LoadOutput(slider.iprox))
        integ.add_output(LoadOutput(link.iprox))
        integ.add_output(LoadOutput(body.iprox))
        integ.add_output(CustomOutput(force_slider_prox, "correct ground"))
        integ.add_output(CustomOutput(force_link_prox, "correct slider dist"))
        integ.add_output(CustomOutput(force_body_prox, "correct link dist"))

        self.system = system
        self.integ = integ
Exemple #20
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])
    def setUp(self):
        # Parameters
        mass = 11.234
        length = 2.54
        gravity = 9.81

        # Build model
        slider = PrismaticJoint('slider', [1, 0, 0])
        link = RigidConnection('link', [0, 0, length])
        body = RigidBody('body', mass)

        system = System(gravity=gravity)
        system.add_leaf(slider)
        slider.add_leaf(link)
        link.add_leaf(body)
        system.setup()

        # Prescribe motion -- sinusoidal acceleration
        motion_frequency = 1    # Hz
        motion_amplitude = 2.3  # m

        # x =  motion_amplitude * np.cos(w*t)
        # v = -motion_amplitude * np.sin(w*t) * w
        # a = -motion_amplitude * np.cos(w*t) * w**2
        def prescribed_acceleration(t):
            w = 2*np.pi*motion_frequency
            return -w**2 * motion_amplitude * np.cos(w*t)

        system.prescribe(slider, prescribed_acceleration)

        # Set the correct initial condition
        system.q[slider.istrain][0] = motion_amplitude
        system.qd[slider.istrain][0] = 0.0

        # Custom outputs to calculate correct answer
        def force_body_prox(s):
            a = prescribed_acceleration(s.time)
            Fx = mass * a
            Fz = mass * gravity
            return [Fx, 0, Fz, 0, 0, 0]

        def force_link_prox(s):
            a = prescribed_acceleration(s.time)
            Fx = mass * a
            Fz = mass * gravity
            My = length * Fx
            return [Fx, 0, Fz, 0, My, 0]

        def force_slider_prox(s):
            a = prescribed_acceleration(s.time)
            x = -a / (2*np.pi*motion_frequency)**2
            Fx = mass * a
            Fz = mass * gravity
            My = length*Fx - x*Fz
            return [Fx, 0, Fz, 0, My, 0]

        # Solver
        integ = Integrator(system, ('pos', 'vel', 'acc'))
        integ.add_output(LoadOutput(slider.iprox))
        integ.add_output(LoadOutput(link.iprox))
        integ.add_output(LoadOutput(body.iprox))
        integ.add_output(CustomOutput(force_slider_prox, "correct ground"))
        integ.add_output(CustomOutput(force_link_prox, "correct slider dist"))
        integ.add_output(CustomOutput(force_body_prox, "correct link dist"))

        self.system = system
        self.integ = integ
Exemple #22
0
    def test_solve_reactions(self):
        # Check it calls the Element method in the right order: down
        # the tree from leaves to base. It must also reset reactions.
        s = System()
        c0 = RigidConnection('c0')
        c1 = RigidConnection('c1')
        c2 = RigidConnection('c2')
        b1 = RigidBody('b1', 1)
        b2 = RigidBody('b2', 1)
        s.add_leaf(c0)
        c0.add_leaf(c1)
        c0.add_leaf(c2)
        c1.add_leaf(b1)
        c2.add_leaf(b2)
        s.setup()

        # Check elements' iter_reactions() are called
        def mock_iter_reactions(element):
            calls.append(element)
        calls = []
        import types
        for el in s.elements.values():
            el.iter_reactions = types.MethodType(mock_iter_reactions, el)

        # Test
        s.joint_reactions[:] = 3
        s.solve_reactions()
        self.assertEqual(calls, [b2, c2, b1, c1, c0])
        assert_aae(s.joint_reactions, 0)
Exemple #23
0
    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