예제 #1
0
    def test_case_compute_all_dilatations(self, n_elem, dilatation):
        """
        This test case, tests compute_all_dilatations
        function by comparing with analytical solution.
        :param n_elem:
        :param dilatation:
        :return:
        """

        initial, test_rod = constructor(n_elem)

        (
            dilatation_collection,
            voronoi_dilatation,
            lengths,
            rest_voronoi_lengths,
        ) = compute_all_dilatations_analytically(n_elem, dilatation)

        test_rod.position_collection *= dilatation
        # Compute dilatation using compute_all_dilatations
        # Compute geometry again because node positions changed.
        # But compute geometry will be done inside compute_all_dilatations.
        _compute_all_dilatations(
            test_rod.position_collection,
            test_rod.volume,
            test_rod.lengths,
            test_rod.tangents,
            test_rod.radius,
            test_rod.dilatation,
            test_rod.rest_lengths,
            test_rod.rest_voronoi_lengths,
            test_rod.voronoi_dilatation,
        )

        assert_allclose(test_rod.lengths, lengths, atol=Tolerance.atol())
        assert_allclose(test_rod.rest_voronoi_lengths,
                        rest_voronoi_lengths,
                        atol=Tolerance.atol())
        assert_allclose(test_rod.dilatation,
                        dilatation_collection,
                        atol=Tolerance.atol())
        assert_allclose(test_rod.voronoi_dilatation,
                        voronoi_dilatation,
                        atol=Tolerance.atol())
예제 #2
0
    def test_case_compute_rotational_energy(self, n_elem, nu=0):
        """
        This function tests compute rotational energy function. We
        take an initial input energy for the rod and compute the angular velocity and
        set the angular velocity of rod elements. We call compute_rotational_energy
        function and compare the result with output energy. Here we are using mass
        moment of inertia corresponding to z velocity.
        Note here we are only setting the z velocity of the rod, y and x velocity
        are zero.
        Parameters
        ----------
        n_elem
        nu

        Returns
        -------

        """

        initial, test_rod = constructor(n_elem, nu)
        input_energy = 10
        omega = np.sqrt(
            2 * input_energy /
            (test_rod.mass_second_moment_of_inertia[2, 2, 0] * n_elem))

        test_rod.omega_collection[..., :] = np.array([0.0, 0.0,
                                                      omega]).reshape(3, 1)
        _compute_all_dilatations(
            test_rod.position_collection,
            test_rod.volume,
            test_rod.lengths,
            test_rod.tangents,
            test_rod.radius,
            test_rod.dilatation,
            test_rod.rest_lengths,
            test_rod.rest_voronoi_lengths,
            test_rod.voronoi_dilatation,
        )

        output_energy = test_rod.compute_rotational_energy()

        assert_allclose(output_energy, input_energy, atol=Tolerance.atol())
예제 #3
0
    def test_case_compute_dilatation_rate(self, n_elem, dilatation):
        """
        This test case tests compute_dilatation_rate
        function by comparing with analytical calculation.
        This function depends on the compute_all_dilatations.
        :param n_elem:
        :param dilatation:
        :return:
        """
        initial, test_rod = constructor(n_elem)

        dilatation_rate, velocity = compute_dilatation_rate_analytically(
            n_elem, dilatation)
        # Set velocity vector in test_rod to the computed velocity vector above,
        # since we need to initialize velocity for dilatation_rate
        test_rod.velocity_collection = velocity

        _compute_all_dilatations(
            test_rod.position_collection,
            test_rod.volume,
            test_rod.lengths,
            test_rod.tangents,
            test_rod.radius,
            test_rod.dilatation,
            test_rod.rest_lengths,
            test_rod.rest_voronoi_lengths,
            test_rod.voronoi_dilatation,
        )

        _compute_dilatation_rate(
            test_rod.position_collection,
            test_rod.velocity_collection,
            test_rod.lengths,
            test_rod.rest_lengths,
            test_rod.dilatation_rate,
        )

        assert_allclose(test_rod.dilatation_rate,
                        dilatation_rate,
                        atol=Tolerance.atol())
예제 #4
0
    def test_case_bend_straight_rod(self, alpha):
        """
        In this test case we initialize a straight rod with 2 elements
        and numerically bend the rod. We modify node positions and directors
        to make a isosceles triangle. Then first we compute curvature
        between two elements and compute the angle between them.
        Finally, we compute bend twist couples and compare with
        correct solution.
        This test function tests
            _compute_bending_twist_strains
            _compute_internal_torques
            only bend_twist_couple terms.
        """

        n_elem = 2
        initial, test_rod = constructor(n_elem, nu=0.0)
        base_length = initial.base_length
        # Change the coordinates of nodes, artificially bend the rod.
        #              /\
        # ------ ==>  /  \
        #            /    \
        # Here I chose a isosceles triangle.

        length = base_length / n_elem
        position = np.zeros((MaxDimension.value(), n_elem + 1))
        position[..., 0] = np.array([0.0, 0.0, 0.0])
        position[..., 1] = length * np.array(
            [0.0, np.sin(alpha), np.cos(alpha)])
        position[..., 2] = length * np.array([0.0, 0.0, 2 * np.cos(alpha)])
        test_rod.position_collection = position

        # Set the directors manually. This is easy since we have two elements.
        directors = np.zeros(
            (MaxDimension.value(), MaxDimension.value(), n_elem))
        directors[..., 0] = np.array((
            [1.0, 0.0, 0.0],
            [0.0, np.cos(alpha), -np.sin(alpha)],
            [0.0, np.sin(alpha), np.cos(alpha)],
        ))
        directors[..., -1] = np.array((
            [1.0, 0.0, 0.0],
            [0.0, np.cos(alpha), np.sin(alpha)],
            [0, -np.sin(alpha), np.cos(alpha)],
        ))
        test_rod.director_collection = directors

        # Compute voronoi rest length. Since elements lengths are equal
        # in this test case, rest voronoi length can be easily computed
        # dividing base length to number of elements.

        rest_voronoi_length = base_length / n_elem

        # Now compute geometry and dilatation, which we need for curvature calculations.
        _compute_all_dilatations(
            test_rod.position_collection,
            test_rod.volume,
            test_rod.lengths,
            test_rod.tangents,
            test_rod.radius,
            test_rod.dilatation,
            test_rod.rest_lengths,
            test_rod.rest_voronoi_lengths,
            test_rod.voronoi_dilatation,
        )

        _compute_dilatation_rate(
            test_rod.position_collection,
            test_rod.velocity_collection,
            test_rod.lengths,
            test_rod.rest_lengths,
            test_rod.dilatation_rate,
        )

        _compute_bending_twist_strains(test_rod.director_collection,
                                       test_rod.rest_voronoi_lengths,
                                       test_rod.kappa)

        # Generalized rotation per unit length is given by rest_D_i * Kappa_i.
        # Thus in order to get the angle between two elements, we need to multiply
        # kappa with rest_D_i .  But this will give the exterior vertex angle of the
        # triangle. Think as, we rotate element 1 clockwise direction and align with
        # the element 2.
        #
        #               \
        #     /\         \ 1
        #  1 /  \ 2  ==>  \
        #   /    \         \
        #                   \ 2
        #                    \
        #
        # So for this transformation we use exterior vertex angle of isosceles triangle.
        # Exterior vertex angle can be computed easily, it is the sum of base angles
        # , since this is isosceles triangle it is 2*base_angle

        correct_angle = np.degrees(
            np.array([2 * alpha, 0.0, 0.0]).reshape(3, 1))
        test_angle = np.degrees(test_rod.kappa * test_rod.rest_voronoi_lengths)
        assert_allclose(test_angle, correct_angle, atol=Tolerance.atol())

        # Now lets test bending stress terms in internal torques equation.
        # Here we will test bend twist couple 2D and bend twist couple 3D terms of the
        # internal torques equation. Set the bending matrix to identity matrix for simplification.
        test_rod.bend_matrix[:] = np.repeat(np.identity(3)[:, :, np.newaxis],
                                            n_elem - 1,
                                            axis=2)

        # We need to compute shear stress, for internal torque equation.
        # Shear stress is not used in this test case. In order to make sure shear
        # stress do not contribute to the total torque we use assert check.
        _compute_internal_bending_twist_stresses_from_model(
            test_rod.director_collection,
            test_rod.rest_voronoi_lengths,
            test_rod.internal_couple,
            test_rod.bend_matrix,
            test_rod.kappa,
            test_rod.rest_kappa,
        )
        assert_allclose(
            test_rod.internal_stress,
            np.zeros(3 * n_elem).reshape(3, n_elem),
            atol=Tolerance.atol(),
        )

        # Make sure voronoi dilatation is 1
        assert_allclose(test_rod.voronoi_dilatation,
                        np.array([1.0]),
                        atol=Tolerance.atol())

        # Compute correct torques, first compute correct kappa.
        correct_kappa = np.radians(correct_angle / rest_voronoi_length)
        # We only need to compute bend twist couple 2D term for comparison,
        # because bend twist couple 3D term is already zero, due to cross product.
        # TODO: Extended this test for multiple elements more than 2.
        correct_torques = np.zeros((MaxDimension.value(), n_elem))
        correct_torques[..., 0] = correct_kappa[..., 0]
        correct_torques[..., -1] = -1.0 * correct_kappa[..., -1]

        _compute_internal_torques(
            test_rod.position_collection,
            test_rod.velocity_collection,
            test_rod.tangents,
            test_rod.lengths,
            test_rod.rest_lengths,
            test_rod.director_collection,
            test_rod.rest_voronoi_lengths,
            test_rod.bend_matrix,
            test_rod.rest_kappa,
            test_rod.kappa,
            test_rod.voronoi_dilatation,
            test_rod.mass_second_moment_of_inertia,
            test_rod.omega_collection,
            test_rod.internal_stress,
            test_rod.internal_couple,
            test_rod.dilatation,
            test_rod.dilatation_rate,
            test_rod.dissipation_constant_for_torques,
            test_rod.damping_torques,
            test_rod.internal_torques,
            test_rod.ghost_voronoi_idx,
        )

        assert_allclose(test_rod.internal_torques,
                        correct_torques,
                        atol=Tolerance.atol())
예제 #5
0
    def test_case_compute_bending_energy(self, alpha, nu=0.0):
        """
        Similar to the previous test case test_case_bend_straight_rod.
        In this test case we initialize a straight rod with 2 elements
        and numerically bend the rod. We modify node positions and directors
        to make a isosceles triangle. Then first we compute curvature
        between two elements and compute the angle between them.
        Finally, we compute the bending energy of rod and compare with
        correct solution.
        This test function tests
            compute_bending_energy
        Parameters
        ----------
        alpha
        nu

        Returns
        -------

        """
        n_elem = 2
        initial, test_rod = constructor(n_elem, nu=0.0)
        base_length = initial.base_length
        # Change the coordinates of nodes, artificially bend the rod.
        #              /\
        # ------ ==>  /  \
        #            /    \
        # Here I chose a isosceles triangle.

        length = base_length / n_elem
        position = np.zeros((MaxDimension.value(), n_elem + 1))
        position[..., 0] = np.array([0.0, 0.0, 0.0])
        position[..., 1] = length * np.array(
            [0.0, np.sin(alpha), np.cos(alpha)])
        position[..., 2] = length * np.array([0.0, 0.0, 2 * np.cos(alpha)])
        test_rod.position_collection = position

        # Set the directors manually. This is easy since we have two elements.
        directors = np.zeros(
            (MaxDimension.value(), MaxDimension.value(), n_elem))
        directors[..., 0] = np.array((
            [1.0, 0.0, 0.0],
            [0.0, np.cos(alpha), -np.sin(alpha)],
            [0.0, np.sin(alpha), np.cos(alpha)],
        ))
        directors[..., -1] = np.array((
            [1.0, 0.0, 0.0],
            [0.0, np.cos(alpha), np.sin(alpha)],
            [0, -np.sin(alpha), np.cos(alpha)],
        ))
        test_rod.director_collection = directors

        # Compute voronoi rest length. Since elements lengths are equal
        # in this test case, rest voronoi length can be easily computed
        # dividing base length to number of elements.

        rest_voronoi_length = base_length / n_elem

        # Now compute geometry and dilatation, which we need for curvature calculations.
        _compute_all_dilatations(
            test_rod.position_collection,
            test_rod.volume,
            test_rod.lengths,
            test_rod.tangents,
            test_rod.radius,
            test_rod.dilatation,
            test_rod.rest_lengths,
            test_rod.rest_voronoi_lengths,
            test_rod.voronoi_dilatation,
        )

        _compute_dilatation_rate(
            test_rod.position_collection,
            test_rod.velocity_collection,
            test_rod.lengths,
            test_rod.rest_lengths,
            test_rod.dilatation_rate,
        )

        _compute_bending_twist_strains(test_rod.director_collection,
                                       test_rod.rest_voronoi_lengths,
                                       test_rod.kappa)

        # Generalized rotation per unit length is given by rest_D_i * Kappa_i.
        # Thus in order to get the angle between two elements, we need to multiply
        # kappa with rest_D_i .  But this will give the exterior vertex angle of the
        # triangle. Think as, we rotate element 1 clockwise direction and align with
        # the element 2.
        #
        #               \
        #     /\         \ 1
        #  1 /  \ 2  ==>  \
        #   /    \         \
        #                   \ 2
        #                    \
        #
        # So for this transformation we use exterior vertex angle of isosceles triangle.
        # Exterior vertex angle can be computed easily, it is the sum of base angles
        # , since this is isosceles triangle it is 2*base_angle

        correct_angle = np.degrees(
            np.array([2 * alpha, 0.0, 0.0]).reshape(3, 1))
        test_angle = np.degrees(test_rod.kappa * test_rod.rest_voronoi_lengths)
        assert_allclose(test_angle, correct_angle, atol=Tolerance.atol())

        # Now lets test bending stress terms in internal torques equation.
        # Here we will test bend twist couple 2D and bend twist couple 3D terms of the
        # internal torques equation. Set the bending matrix to identity matrix for simplification.
        test_rod.bend_matrix[:] = np.repeat(np.identity(3)[:, :, np.newaxis],
                                            n_elem - 1,
                                            axis=2)

        # Compute bending energy
        correct_kappa = 2 * alpha / rest_voronoi_length
        correct_bending_energy = (0.5 * correct_kappa * correct_kappa *
                                  rest_voronoi_length)
        test_bending_energy = test_rod.compute_bending_energy()
        assert_allclose(test_bending_energy,
                        correct_bending_energy,
                        atol=Tolerance.atol())