示例#1
0
    def load_collection(self):
        sc = GenericSimulatorClass()
        from elastica.rod.cosserat_rod import CosseratRod

        # rod = RodBase()
        rod_list = []
        for _ in range(5):
            rod = CosseratRod.straight_rod(
                n_elements=10,
                start=np.zeros((3)),
                direction=np.array([0, 1, 0.0]),
                normal=np.array([1, 0, 0.0]),
                base_length=1,
                base_radius=1,
                density=1,
                nu=1,
                youngs_modulus=1,
            )
            # Bypass check, but its fine for testing
            sc._systems.append(rod)

            # Also add rods to a separate list
            rod_list.append(rod)

        return sc, rod_list
示例#2
0
def constructor(n_elem, nu=0.0):

    cls = BaseClass(n_elem, nu)
    rod = CosseratRod.straight_rod(
        cls.n_elem,
        cls.start,
        cls.direction,
        cls.normal,
        cls.base_length,
        cls.base_radius,
        cls.density,
        cls.nu,
        cls.E,
        cls.poisson_ratio,
    )
    return cls, rod
示例#3
0
def constructor(n_elem, nu=0.0):

    cls = BaseClass(n_elem, nu)
    rod = CosseratRod.straight_rod(
        cls.n_elem,
        cls.start,
        cls.direction,
        cls.normal,
        cls.base_length,
        cls.base_radius,
        cls.density,
        cls.nu,
        cls.E,
        shear_modulus=cls.shear_modulus,
    )

    # Ghost needed for Cosserat rod functions adapted for block structure.
    rod.ghost_elems_idx = np.empty((0), dtype=int)
    rod.ghost_voronoi_idx = np.empty((0), dtype=int)

    return cls, rod
示例#4
0
def simulate_rolling_friction_torque_with(C_s=0.0):

    rolling_friction_torque_sim = RollingFrictionTorqueSimulator()

    # setting up test params
    n_elem = 50
    start = np.zeros((3, ))
    direction = np.array([0.0, 0.0, 1.0])
    normal = np.array([0.0, 1.0, 0.0])
    base_length = 1.0
    base_radius = 0.025
    base_area = np.pi * base_radius**2
    mass = 1.0
    density = mass / (base_length * base_area)
    nu = 1e-6
    E = 1e9
    # For shear modulus of 2E/3
    poisson_ratio = 0.5

    # Set shear matrix
    shear_matrix = np.repeat(1e4 * np.identity((3))[:, :, np.newaxis],
                             n_elem,
                             axis=2)

    shearable_rod = CosseratRod.straight_rod(
        n_elem,
        start,
        direction,
        normal,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )

    # TODO: CosseratRod has to be able to take shear matrix as input, we should change it as done below
    shearable_rod.shear_matrix = shear_matrix

    rolling_friction_torque_sim.append(shearable_rod)
    rolling_friction_torque_sim.constrain(shearable_rod).using(FreeRod)

    # Add gravitational forces
    gravitational_acc = -9.80665
    rolling_friction_torque_sim.add_forcing_to(shearable_rod).using(
        GravityForces, acc_gravity=np.array([0.0, gravitational_acc, 0.0]))

    # Add Uniform torque on the rod
    rolling_friction_torque_sim.add_forcing_to(shearable_rod).using(
        UniformTorques, torque=1.0 * C_s, direction=direction)

    # Add friction forces
    origin_plane = np.array([0.0, -base_radius, 0.0])
    normal_plane = np.array([0.0, 1.0, 0.0])
    slip_velocity_tol = 1e-4
    static_mu_array = np.array([0.4, 0.4,
                                0.4])  # [forward, backward, sideways]
    kinetic_mu_array = np.array([0.2, 0.2,
                                 0.2])  # [forward, backward, sideways]

    rolling_friction_torque_sim.add_forcing_to(shearable_rod).using(
        AnisotropicFrictionalPlane,
        k=10.0,
        nu=1e-4,
        plane_origin=origin_plane,
        plane_normal=normal_plane,
        slip_velocity_tol=slip_velocity_tol,
        static_mu_array=static_mu_array,
        kinetic_mu_array=kinetic_mu_array,
    )

    rolling_friction_torque_sim.finalize()
    timestepper = PositionVerlet()

    final_time = 1.0
    dt = 1e-6
    total_steps = int(final_time / dt)
    print("Total steps", total_steps)
    integrate(timestepper, rolling_friction_torque_sim, final_time,
              total_steps)

    # compute translational and rotational energy
    translational_energy = shearable_rod.compute_translational_energy()
    rotational_energy = shearable_rod.compute_rotational_energy()

    # compute translational and rotational energy using analytical equations
    force_slip = static_mu_array[2] * mass * gravitational_acc
    force_noslip = 2.0 * C_s / (3.0 * base_radius)

    mass_moment_of_inertia = 0.5 * mass * base_radius**2

    if np.abs(force_noslip) <= np.abs(force_slip):
        analytical_translational_energy = (2.0 / mass *
                                           (final_time * C_s /
                                            (3.0 * base_radius))**2)
        analytical_rotational_energy = (2.0 * mass_moment_of_inertia *
                                        (final_time * C_s /
                                         (3.0 * base_radius**2 * mass))**2)
    else:
        analytical_translational_energy = (
            mass * (kinetic_mu_array[2] * gravitational_acc * final_time)**2 /
            2.0)
        analytical_rotational_energy = (
            (C_s - kinetic_mu_array[2] * mass * np.abs(gravitational_acc) *
             base_radius)**2 * final_time**2 / (2.0 * mass_moment_of_inertia))

    return {
        "rod": shearable_rod,
        "sweep": C_s,
        "translational_energy": translational_energy,
        "rotational_energy": rotational_energy,
        "analytical_translational_energy": analytical_translational_energy,
        "analytical_rotational_energy": analytical_rotational_energy,
    }
示例#5
0
def simulate_axial_friction_with(force=0.0):

    axial_friction_sim = AxialFrictionSimulator()

    # setting up test params
    n_elem = 50
    start = np.zeros((3, ))
    direction = np.array([0.0, 0.0, 1.0])
    normal = np.array([0.0, 1.0, 0.0])
    base_length = 1.0
    base_radius = 0.025
    base_area = np.pi * base_radius**2
    mass = 1.0
    density = mass / (base_length * base_area)
    nu = 1e-6
    E = 1e5
    # For shear modulus of 2E/3
    poisson_ratio = 0.5

    # Set shear matrix
    shear_matrix = np.repeat(1e4 * np.identity((3))[:, :, np.newaxis],
                             n_elem,
                             axis=2)

    shearable_rod = CosseratRod.straight_rod(
        n_elem,
        start,
        direction,
        normal,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )

    # TODO: CosseratRod has to be able to take shear matrix as input, we should change it as done below
    shearable_rod.shear_matrix = shear_matrix

    axial_friction_sim.append(shearable_rod)
    axial_friction_sim.constrain(shearable_rod).using(FreeRod)

    # Add gravitational forces
    gravitational_acc = -9.80665
    axial_friction_sim.add_forcing_to(shearable_rod).using(
        GravityForces, acc_gravity=np.array([0.0, gravitational_acc, 0.0]))

    # Add Uniform force on the rod
    axial_friction_sim.add_forcing_to(shearable_rod).using(UniformForces,
                                                           force=1.0 * force,
                                                           direction=direction)

    # Add friction forces
    origin_plane = np.array([0.0, -base_radius, 0.0])
    normal_plane = np.array([0.0, 1.0, 0.0])
    slip_velocity_tol = 1e-4
    static_mu_array = np.array([0.8, 0.4,
                                0.4])  # [forward, backward, sideways]
    kinetic_mu_array = np.array([0.4, 0.2,
                                 0.2])  # [forward, backward, sideways]

    axial_friction_sim.add_forcing_to(shearable_rod).using(
        AnisotropicFrictionalPlane,
        k=10.0,
        nu=1e-4,
        plane_origin=origin_plane,
        plane_normal=normal_plane,
        slip_velocity_tol=slip_velocity_tol,
        static_mu_array=static_mu_array,
        kinetic_mu_array=kinetic_mu_array,
    )

    axial_friction_sim.finalize()
    timestepper = PositionVerlet()

    final_time = 0.25
    dt = 1e-5
    total_steps = int(final_time / dt)
    print("Total steps", total_steps)
    integrate(timestepper, axial_friction_sim, final_time, total_steps)

    # compute translational and rotational energy
    translational_energy = shearable_rod.compute_translational_energy()
    rotational_energy = shearable_rod.compute_rotational_energy()

    # compute translational and rotational energy using analytical equations

    if force >= 0.0:  # forward friction force
        if np.abs(force) <= np.abs(
                static_mu_array[0] * mass * gravitational_acc):
            analytical_translational_energy = 0.0
        else:
            analytical_translational_energy = (
                final_time**2 / (2.0 * mass) *
                (np.abs(force) -
                 kinetic_mu_array[0] * mass * np.abs(gravitational_acc))**2)

    else:  # backward friction force
        if np.abs(force) <= np.abs(
                static_mu_array[1] * mass * gravitational_acc):
            analytical_translational_energy = 0.0
        else:
            analytical_translational_energy = (
                final_time**2 / (2.0 * mass) *
                (np.abs(force) -
                 kinetic_mu_array[1] * mass * np.abs(gravitational_acc))**2)

    analytical_rotational_energy = 0.0

    return {
        "rod": shearable_rod,
        "sweep": force,
        "translational_energy": translational_energy,
        "rotational_energy": rotational_energy,
        "analytical_translational_energy": analytical_translational_energy,
        "analytical_rotational_energy": analytical_rotational_energy,
    }
示例#6
0
def test_fixedjoint():
    # Define the rod for testing
    # Some rod properties. We need them for constructer, they are not used.
    normal1 = np.array([0.0, 1.0, 0.0])
    direction = np.array([1.0, 0.0, 0.0])
    normal2 = np.array([0.0, 0.0, 1.0])
    direction2 = np.array([1.0 / np.sqrt(2), 1.0 / np.sqrt(2), 0.0])
    # direction2 = np.array([0.,1.0,0.])
    base_length = 1
    base_radius = 0.2
    density = 1
    nu = 0.1

    # Youngs Modulus [Pa]
    E = 1e6
    # poisson ratio
    poisson_ratio = 0.5

    # Origin of the rod
    origin1 = np.array([0.0, 0.0, 0.0])
    origin2 = np.array([1.0, 0.0, 0.0])

    # Number of elements
    n = 2

    # create rod classes
    rod1 = CosseratRod.straight_rod(
        n,
        origin1,
        direction,
        normal1,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )
    rod2 = CosseratRod.straight_rod(
        n,
        origin2,
        direction2,
        normal2,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )

    # Rod velocity
    v1 = np.array([-1, 0, 0]).reshape(3, 1)
    v2 = v1 * -1

    rod1.velocity_collection = np.tile(v1, (1, n + 1))
    rod2.velocity_collection = np.tile(v2, (1, n + 1))

    # Stiffness between points
    k = 1e8
    kt = 1e6
    # Damping between two points
    nu = 1

    # Rod indexes
    rod1_index = -1
    rod2_index = 0

    # Compute the free joint forces
    distance = (rod2.position_collection[..., rod2_index] -
                rod1.position_collection[..., rod1_index])
    end_distance = np.linalg.norm(distance)
    if end_distance == 0:
        end_distance = 1
    elasticforce = k * distance
    relative_vel = (rod2.velocity_collection[..., rod2_index] -
                    rod1.velocity_collection[..., rod1_index])
    normal_relative_vel = np.dot(relative_vel, distance) / end_distance
    dampingforce = nu * normal_relative_vel * distance / end_distance
    contactforce = elasticforce - dampingforce

    fxjt = FixedJoint(k, nu, kt)

    fxjt.apply_forces(rod1, rod1_index, rod2, rod2_index)
    fxjt.apply_torques(rod1, rod1_index, rod2, rod2_index)

    assert_allclose(rod1.external_forces[..., rod1_index],
                    contactforce,
                    atol=Tolerance.atol())
    assert_allclose(rod2.external_forces[..., rod2_index],
                    -1 * contactforce,
                    atol=Tolerance.atol())

    linkdirection = (rod2.position_collection[..., rod2_index + 1] -
                     rod2.position_collection[..., rod2_index])

    positiondiff = (rod1.position_collection[..., rod1_index] -
                    rod1.position_collection[..., rod1_index - 1])
    tangent = positiondiff / np.sqrt(np.dot(positiondiff, positiondiff))

    # rod 2 has to be alligned with rod 1
    check1 = (rod1.position_collection[..., rod1_index] +
              rod2.rest_lengths[rod2_index] * tangent)
    check2 = rod2.position_collection[..., rod2_index + 1]
    forcedirection = -kt * (check2 - check1)
    torque = np.cross(linkdirection, forcedirection)

    torque_rod1 = -rod1.director_collection[..., rod1_index] @ torque
    torque_rod2 = rod2.director_collection[..., rod2_index] @ torque

    assert_allclose(rod1.external_torques[..., rod1_index],
                    torque_rod1,
                    atol=Tolerance.atol())
    assert_allclose(rod2.external_torques[..., rod2_index],
                    torque_rod2,
                    atol=Tolerance.atol())
示例#7
0
def test_freejoint():

    # Some rod properties. We need them for constructer, they are not used.
    normal = np.array([0.0, 1.0, 0.0])
    direction = np.array([0.0, 0.0, 1.0])
    base_length = 1
    base_radius = 0.2
    density = 1
    nu = 0.1

    # Youngs Modulus [Pa]
    E = 1e6
    # poisson ratio
    poisson_ratio = 0.5

    # Origin of the rod
    origin1 = np.array([0.0, 0.0, 0.0])
    origin2 = np.array([1.0, 0.0, 0.0])

    # Number of elements
    n = 4

    # create rod classes
    rod1 = CosseratRod.straight_rod(
        n,
        origin1,
        direction,
        normal,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )
    rod2 = CosseratRod.straight_rod(
        n,
        origin2,
        direction,
        normal,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )

    # Stiffness between points
    k = 1e8

    # Damping between two points
    nu = 1

    # Rod indexes
    rod1_index = -1
    rod2_index = 0

    # Rod velocity
    v1 = np.array([-1, 0, 0]).reshape(3, 1)
    v2 = v1 * -1

    rod1.velocity_collection = np.tile(v1, (1, n + 1))
    rod2.velocity_collection = np.tile(v2, (1, n + 1))

    # Compute the free joint forces
    distance = (rod2.position_collection[..., rod2_index] -
                rod1.position_collection[..., rod1_index])
    end_distance = np.linalg.norm(distance)
    if end_distance <= Tolerance.atol():
        end_distance = 1.0
    elasticforce = k * distance
    relative_vel = (rod2.velocity_collection[..., rod2_index] -
                    rod1.velocity_collection[..., rod1_index])
    normal_relative_vel = np.dot(relative_vel, distance) / end_distance
    dampingforce = nu * normal_relative_vel * distance / end_distance
    contactforce = elasticforce - dampingforce

    frjt = FreeJoint(k, nu)
    frjt.apply_forces(rod1, rod1_index, rod2, rod2_index)
    frjt.apply_torques(rod1, rod1_index, rod2, rod2_index)

    assert_allclose(rod1.external_forces[..., rod1_index],
                    contactforce,
                    atol=Tolerance.atol())
    assert_allclose(rod2.external_forces[..., rod2_index],
                    -1 * contactforce,
                    atol=Tolerance.atol())
示例#8
0
def run_snake(b_coeff, SAVE_RESULTS=False):

    snake_sim = SnakeSimulator()

    # setting up test params
    n_elem = 20
    start = np.zeros((3, ))
    direction = np.array([0.0, 0.0, 1.0])
    normal = np.array([0.0, 1.0, 0.0])
    base_length = 1.0
    base_radius = 0.025
    base_area = np.pi * base_radius**2
    density = 1000
    nu = 5.0
    E = 1e7
    poisson_ratio = 0.5

    shearable_rod = CosseratRod.straight_rod(
        n_elem,
        start,
        direction,
        normal,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )

    snake_sim.append(shearable_rod)

    # Add gravitational forces
    gravitational_acc = -9.80665
    snake_sim.add_forcing_to(shearable_rod).using(
        GravityForces, acc_gravity=np.array([0.0, gravitational_acc, 0.0]))

    period = 1.0
    wave_length = b_coeff[-1]
    snake_sim.add_forcing_to(shearable_rod).using(
        MuscleTorques,
        base_length=base_length,
        b_coeff=b_coeff[:-1],
        period=period,
        wave_number=2.0 * np.pi / (wave_length),
        phase_shift=0.0,
        direction=normal,
        rest_lengths=shearable_rod.rest_lengths,
        ramp_up_time=period,
        with_spline=True,
    )

    # Add friction forces
    origin_plane = np.array([0.0, -base_radius, 0.0])
    normal_plane = normal
    slip_velocity_tol = 1e-8
    froude = 0.1
    mu = base_length / (period * period * np.abs(gravitational_acc) * froude)
    kinetic_mu_array = np.array([mu, 1.5 * mu,
                                 2.0 * mu])  # [forward, backward, sideways]
    static_mu_array = 2 * kinetic_mu_array
    snake_sim.add_forcing_to(shearable_rod).using(
        AnisotropicFrictionalPlane,
        k=1.0,
        nu=1e-6,
        plane_origin=origin_plane,
        plane_normal=normal_plane,
        slip_velocity_tol=slip_velocity_tol,
        static_mu_array=static_mu_array,
        kinetic_mu_array=kinetic_mu_array,
    )

    # Add call backs
    class ContinuumSnakeCallBack(CallBackBaseClass):
        """
        Call back function for continuum snake
        """
        def __init__(self, step_skip: int, callback_params: dict):
            CallBackBaseClass.__init__(self)
            self.every = step_skip
            self.callback_params = callback_params

        def make_callback(self, system, time, current_step: int):

            if current_step % self.every == 0:

                self.callback_params["time"].append(time)
                self.callback_params["position"].append(
                    system.position_collection.copy())

                return

    pp_list = defaultdict(list)
    snake_sim.collect_diagnostics(shearable_rod).using(ContinuumSnakeCallBack,
                                                       step_skip=200,
                                                       callback_params=pp_list)

    snake_sim.finalize()
    timestepper = PositionVerlet()
    # timestepper = PEFRL()

    final_time = (11.0 + 0.01) * period
    dt = 5.0e-5 * period
    total_steps = int(final_time / dt)
    print("Total steps", total_steps)
    integrate(timestepper, snake_sim, final_time, total_steps)

    if SAVE_RESULTS:
        import pickle

        filename = "continuum_snake.dat"
        file = open(filename, "wb")
        pickle.dump(pp_list, file)
        file.close()

    return pp_list
示例#9
0
base_area = np.pi * base_radius**2
density = 1750
nu = 0.001
E = 3e7
poisson_ratio = 0.5

start_rod_1 = np.zeros((3, ))
start_rod_2 = start_rod_1 + direction * base_length

# Create rod 1
rod1 = CosseratRod.straight_rod(
    n_elem,
    start_rod_1,
    direction,
    normal,
    base_length,
    base_radius,
    density,
    nu,
    E,
    poisson_ratio,
)
hinge_joint_sim.append(rod1)
# Create rod 2
rod2 = CosseratRod.straight_rod(
    n_elem,
    start_rod_2,
    direction,
    normal,
    base_length,
    base_radius,
    density,
示例#10
0
normal = np.array([0.0, 1.0, 0.0])
base_length = 3.0
base_radius = 0.25
base_area = np.pi * base_radius ** 2
density = 5000
nu = 0.1
E = 1e6
# For shear modulus of 1e4, nu is 99!
poisson_ratio = 99

shearable_rod = CosseratRod.straight_rod(
    n_elem,
    start,
    direction,
    normal,
    base_length,
    base_radius,
    density,
    nu,
    E,
    poisson_ratio,
)

timoshenko_sim.append(shearable_rod)
timoshenko_sim.constrain(shearable_rod).using(
    OneEndFixedRod, constrained_position_idx=(0,), constrained_director_idx=(0,)
)

end_force = np.array([-15.0, 0.0, 0.0])
timoshenko_sim.add_forcing_to(shearable_rod).using(
    EndpointForces, 0.0 * end_force, end_force, ramp_up_time=final_time / 2.0
)
示例#11
0
number_of_rotations = 27
# For shear modulus of 1e4, nu is 99!
poisson_ratio = 99
shear_matrix = np.repeat(1e5 * np.identity((3))[:, :, np.newaxis],
                         n_elem,
                         axis=2)
temp_bend_matrix = np.zeros((3, 3))
np.fill_diagonal(temp_bend_matrix, [1.345, 1.345, 0.789])
bend_matrix = np.repeat(temp_bend_matrix[:, :, np.newaxis], n_elem - 1, axis=2)

shearable_rod = CosseratRod.straight_rod(
    n_elem,
    start,
    direction,
    normal,
    base_length,
    base_radius,
    density,
    nu,
    E,
    poisson_ratio,
)
# TODO: CosseratRod has to be able to take shear matrix as input, we should change it as done below

shearable_rod.shear_matrix = shear_matrix
shearable_rod.bend_matrix = bend_matrix

helicalbuckling_sim.append(shearable_rod)
helicalbuckling_sim.constrain(shearable_rod).using(
    HelicalBucklingBC,
    constrained_position_idx=(0, -1),
    constrained_director_idx=(0, -1),
def simulate_timoshenko_beam_with(elements=10,
                                  PLOT_FIGURE=False,
                                  ADD_UNSHEARABLE_ROD=False):
    timoshenko_sim = TimoshenkoBeamSimulator()
    final_time = 5000
    # setting up test params
    n_elem = elements
    start = np.zeros((3, ))
    direction = np.array([0.0, 0.0, 1.0])
    normal = np.array([0.0, 1.0, 0.0])
    base_length = 3.0
    base_radius = 0.25
    base_area = np.pi * base_radius**2
    density = 5000
    nu = 0.1
    E = 1e6
    # For shear modulus of 1e4, nu is 99!
    poisson_ratio = 99

    shearable_rod = CosseratRod.straight_rod(
        n_elem,
        start,
        direction,
        normal,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )

    timoshenko_sim.append(shearable_rod)
    timoshenko_sim.constrain(shearable_rod).using(
        OneEndFixedRod,
        constrained_position_idx=(0, ),
        constrained_director_idx=(0, ))
    end_force = np.array([-15.0, 0.0, 0.0])
    timoshenko_sim.add_forcing_to(shearable_rod).using(
        EndpointForces,
        0.0 * end_force,
        end_force,
        ramp_up_time=final_time / 2)

    if ADD_UNSHEARABLE_ROD:
        # Start into the plane
        unshearable_start = np.array([0.0, -1.0, 0.0])
        unshearable_rod = CosseratRod.straight_rod(
            n_elem,
            unshearable_start,
            direction,
            normal,
            base_length,
            base_radius,
            density,
            nu,
            E,
            # Unshearable rod needs G -> inf, which is achievable with -ve poisson ratio
            poisson_ratio=-0.7,
        )

        timoshenko_sim.append(unshearable_rod)
        timoshenko_sim.constrain(unshearable_rod).using(
            OneEndFixedRod,
            constrained_position_idx=(0, ),
            constrained_director_idx=(0, ))
        timoshenko_sim.add_forcing_to(unshearable_rod).using(
            EndpointForces,
            0.0 * end_force,
            end_force,
            ramp_up_time=final_time / 2)

    timoshenko_sim.finalize()
    timestepper = PositionVerlet()
    # timestepper = PEFRL()

    dl = base_length / n_elem
    dt = 0.01 * dl
    total_steps = int(final_time / dt)
    print("Total steps", total_steps)
    integrate(timestepper, timoshenko_sim, final_time, total_steps)

    if PLOT_FIGURE:
        plot_timoshenko(shearable_rod, end_force, SAVE_FIGURE,
                        ADD_UNSHEARABLE_ROD)

    # calculate errors and norms
    # Since we need to evaluate analytical solution only on nodes, n_nodes = n_elems+1
    error, l1, l2, linf = calculate_error_norm(
        analytical_shearable(shearable_rod, end_force, n_elem + 1)[1],
        shearable_rod.position_collection[0, ...],
        n_elem,
    )
    return {
        "rod": shearable_rod,
        "error": error,
        "l1": l1,
        "l2": l2,
        "linf": linf
    }
def test_straight_rod():

    # setting up test params
    n = 30
    start = np.random.rand(3)
    direction = 5 * np.random.rand(3)
    direction_norm = np.linalg.norm(direction)
    direction /= direction_norm
    normal = np.array((direction[1], -direction[0], 0))
    base_length = 10
    base_radius = np.random.uniform(1, 10)
    density = np.random.uniform(1, 10)
    mass = density * np.pi * base_radius**2 * base_length / n

    nu = 0.1
    # Youngs Modulus [Pa]
    E = 1e6
    # poisson ratio
    poisson_ratio = 0.5
    # Shear Modulus [Pa]
    G = E / (1.0 + poisson_ratio)
    # alpha c, constant for circular cross-sections
    # Second moment of inertia
    A0 = np.pi * base_radius * base_radius
    I0_1 = A0 * A0 / (4.0 * np.pi)
    I0_2 = I0_1
    I0_3 = 2.0 * I0_2
    I0 = np.array([I0_1, I0_2, I0_3])
    # Mass second moment of inertia for disk cross-section
    mass_second_moment_of_inertia = np.zeros((3, 3), np.float64)
    np.fill_diagonal(mass_second_moment_of_inertia,
                     I0 * density * base_length / n)
    # Inverse mass second of inertia
    inv_mass_second_moment_of_inertia = np.linalg.inv(
        mass_second_moment_of_inertia)
    # Shear/Stretch matrix
    shear_matrix = np.zeros((3, 3), np.float64)
    np.fill_diagonal(shear_matrix,
                     [4.0 * G * A0 / 3.0, 4.0 * G * A0 / 3.0, E * A0])
    # Bend/Twist matrix
    bend_matrix = np.zeros((3, 3), np.float64)
    np.fill_diagonal(bend_matrix, [E * I0_1, E * I0_2, G * I0_3])

    test_rod = CosseratRod.straight_rod(
        n,
        start,
        direction,
        normal,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )
    # checking origin and length of rod
    assert_allclose(test_rod.position_collection[..., 0],
                    start,
                    atol=Tolerance.atol())
    rod_length = np.linalg.norm(test_rod.position_collection[..., -1] -
                                test_rod.position_collection[..., 0])
    rest_voronoi_lengths = 0.5 * (base_length / n + base_length / n
                                  )  # element lengths are equal for all rod.
    # checking velocities, omegas and rest strains
    # density and mass
    assert_allclose(rod_length, base_length, atol=Tolerance.atol())
    assert_allclose(test_rod.velocity_collection,
                    np.zeros((3, n + 1)),
                    atol=Tolerance.atol())
    assert_allclose(test_rod.omega_collection,
                    np.zeros((3, n)),
                    atol=Tolerance.atol())
    assert_allclose(test_rod.rest_sigma,
                    np.zeros((3, n)),
                    atol=Tolerance.atol())
    assert_allclose(test_rod.rest_kappa,
                    np.zeros((3, n - 1)),
                    atol=Tolerance.atol())
    assert_allclose(test_rod.density, density, atol=Tolerance.atol())
    assert_allclose(test_rod.nu, nu, atol=Tolerance.atol())
    assert_allclose(rest_voronoi_lengths,
                    test_rod.rest_voronoi_lengths,
                    atol=Tolerance.atol())
    # Check mass at each node. Note that, node masses is
    # half of element mass at the first and last node.
    for i in range(1, n):
        assert_allclose(test_rod.mass[i], mass, atol=Tolerance.atol())
    assert_allclose(test_rod.mass[0], 0.5 * mass, atol=Tolerance.atol())
    assert_allclose(test_rod.mass[-1], 0.5 * mass, atol=Tolerance.atol())
    # checking directors, rest length
    # and shear, bend matrices and moment of inertia
    for i in range(n):
        assert_allclose(test_rod.director_collection[0, :, i],
                        normal,
                        atol=Tolerance.atol())
        assert_allclose(
            test_rod.director_collection[1, :, i],
            np.cross(direction, normal),
            atol=Tolerance.atol(),
        )
        assert_allclose(test_rod.director_collection[2, :, i],
                        direction,
                        atol=Tolerance.atol())
        assert_allclose(test_rod.rest_lengths,
                        base_length / n,
                        atol=Tolerance.atol())
        assert_allclose(test_rod.shear_matrix[..., i],
                        shear_matrix,
                        atol=Tolerance.atol())
        assert_allclose(
            test_rod.mass_second_moment_of_inertia[..., i],
            mass_second_moment_of_inertia,
            atol=Tolerance.atol(),
        )
        assert_allclose(
            test_rod.inv_mass_second_moment_of_inertia[..., i],
            inv_mass_second_moment_of_inertia,
            atol=Tolerance.atol(),
        )
    for i in range(n - 1):
        assert_allclose(test_rod.bend_matrix[..., i],
                        bend_matrix,
                        atol=Tolerance.atol())
示例#14
0
def simulate_rolling_friction_initial_velocity_with(IFactor=0.0):

    rolling_friction_initial_velocity_sim = RollingFrictionInitialVelocitySimulator(
    )

    # setting up test params
    n_elem = 50
    start = np.zeros((3, ))
    direction = np.array([0.0, 0.0, 1.0])
    normal = np.array([0.0, 1.0, 0.0])
    base_length = 1.0
    base_radius = 0.025
    base_area = np.pi * base_radius**2
    mass = 1.0
    density = mass / (base_length * base_area)
    nu = 1e-6
    E = 1e9
    # For shear modulus of 2E/3
    poisson_ratio = 0.5

    # Set shear matrix
    shear_matrix = np.repeat(1e4 * np.identity((3))[:, :, np.newaxis],
                             n_elem,
                             axis=2)

    shearable_rod = CosseratRod.straight_rod(
        n_elem,
        start,
        direction,
        normal,
        base_length,
        base_radius,
        density,
        nu,
        E,
        poisson_ratio,
    )

    # TODO: CosseratRod has to be able to take shear matrix as input, we should change it as done below
    shearable_rod.shear_matrix = shear_matrix
    # change the mass moment of inertia matrix and its inverse
    shearable_rod.mass_second_moment_of_inertia *= IFactor
    shearable_rod.inv_mass_second_moment_of_inertia /= IFactor

    # set initial velocity of 1m/s to rod elements in the slip direction
    Vs = 1.0
    shearable_rod.velocity_collection[0, :] += Vs

    rolling_friction_initial_velocity_sim.append(shearable_rod)
    rolling_friction_initial_velocity_sim.constrain(shearable_rod).using(
        FreeRod)

    # Add gravitational forces
    gravitational_acc = -9.80665
    rolling_friction_initial_velocity_sim.add_forcing_to(shearable_rod).using(
        GravityForces, acc_gravity=np.array([0.0, gravitational_acc, 0.0]))

    # Add friction forces
    origin_plane = np.array([0.0, -base_radius, 0.0])
    normal_plane = np.array([0.0, 1.0, 0.0])
    slip_velocity_tol = 1e-6
    static_mu_array = np.array([0.4, 0.4,
                                0.4])  # [forward, backward, sideways]
    kinetic_mu_array = np.array([0.2, 0.2,
                                 0.2])  # [forward, backward, sideways]

    rolling_friction_initial_velocity_sim.add_forcing_to(shearable_rod).using(
        AnisotropicFrictionalPlane,
        k=10.0,
        nu=1e-4,
        plane_origin=origin_plane,
        plane_normal=normal_plane,
        slip_velocity_tol=slip_velocity_tol,
        static_mu_array=static_mu_array,
        kinetic_mu_array=kinetic_mu_array,
    )

    rolling_friction_initial_velocity_sim.finalize()
    timestepper = PositionVerlet()

    final_time = 2.0
    dt = 1e-6
    total_steps = int(final_time / dt)
    print("Total steps", total_steps)
    integrate(timestepper, rolling_friction_initial_velocity_sim, final_time,
              total_steps)

    # compute translational and rotational energy
    translational_energy = shearable_rod.compute_translational_energy()
    rotational_energy = shearable_rod.compute_rotational_energy()

    # compute translational and rotational energy using analytical equations
    analytical_translational_energy = 0.5 * mass * Vs**2 / (1.0 +
                                                            IFactor / 2)**2
    analytical_rotational_energy = (0.5 * mass * Vs**2 * (IFactor / 2.0) /
                                    (1.0 + IFactor / 2)**2)

    return {
        "rod": shearable_rod,
        "sweep": IFactor / 2.0,
        "translational_energy": translational_energy,
        "rotational_energy": rotational_energy,
        "analytical_translational_energy": analytical_translational_energy,
        "analytical_rotational_energy": analytical_rotational_energy,
    }