예제 #1
0
    def __call__(self, t, y, ms, N):
        rs = y[:int(len(y) / 2)].reshape((N, p.num_dimensions))

        disp = rs[self.i] - rs[self.j]
        dist = np.linalg.norm(disp)

        radius1 = find_particle_radius(ms[self.i])
        radius2 = find_particle_radius(ms[self.j])
        collision_radius = radius1 + radius2

        return dist - collision_radius
예제 #2
0
def find_acc_cpp_wrapper(rs, ms):
    rs_tuple = tuple(map(tuple, rs))
    ms_tuple = tuple(ms)
    radii_tuple = tuple(find_particle_radius(ms))
    As = find_acc_cpp(rs_tuple, ms_tuple, radii_tuple, (p.qt, p.G))
    As = np.array(As)
    return As
예제 #3
0
    def update_screen(i):
        """update function for FuncAnimation"""
        i = i * p.display_rate
        N = int(whole_solution.Ns[i])
        for j in range(N):
            circles_top[j].set_center(whole_solution.rs[i, j, (0, 1)])
            circles_top[j].set_radius(
                find_particle_radius(whole_solution.ms[i, j]))
            circles_side[j].set_center(whole_solution.rs[i, j, (0, 2)])
            circles_side[j].set_radius(
                find_particle_radius(whole_solution.ms[i, j]))

        # remove particles that no longer exist
        for j in range(N, p.num_particles):
            circles_top[j].set_center((max_x + 1000, max_y + 1000))
            circles_side[j].set_center((max_x + 1000, max_z + 1000))

        return circles_top, circles_side
예제 #4
0
def plot_snapshot(rs, ms):
    circles = [
        plt.Circle(rs[i, (0, 1)], find_particle_radius(ms[i]))
        for i in range(len(ms))
    ]
    ax = plt.axes()
    ax.axis('scaled')
    ax.set_xlim(np.min(rs[:, 0]) - 1, np.max(rs[:, 0]) + 1)
    ax.set_ylim(np.min(rs[:, 1]) - 1, np.max(rs[:, 1]) + 1)
    for circle in circles:
        ax.add_artist(circle)
    plt.show()
예제 #5
0
def combine_overlapping_particles(rs, vs, ms):
    """Useful for generating initial conditions, and making sure no overlaps occur after a coalesce"""
    def find_first_overlapping_pair(rs, radii):
        for i in range(len(rs)):
            for j in range(i + 1, len(rs)):
                dist = np.linalg.norm(rs[i] - rs[j])
                min_dist = radii[i] + radii[j]
                if dist < min_dist:
                    return i, j
        return None

    while True:
        overlapping_pair = find_first_overlapping_pair(
            rs, find_particle_radius(ms))
        if overlapping_pair is None:
            break
        print('there is a collision')
        rs, vs, ms = coalesce(overlapping_pair, rs, vs, ms)

    return rs, vs, ms
예제 #6
0
def animate_top_side(
    whole_solution,
    filename='',
):
    """takes the objects and animates them using funcanimation"""

    # defined quantities
    num_of_frames = int(p.snapshots / p.display_rate)
    frame_interval = 1000 / p.fps

    # fig = plt.figure(figsize=(12, 12))
    # ax = plt.axes()
    fig, (ax_top, ax_side) = plt.subplots(1, 2)
    fig.set_figwidth(12)
    ax_top.axis('scaled')
    ax_side.axis('scaled')
    ax_top.set_title('Top view')
    ax_side.set_title('Side view')
    ax_top.set_xlabel('x'), ax_top.set_ylabel('y')
    ax_side.set_xlabel('x'), ax_side.set_ylabel('z')

    min_x = np.nanmin(whole_solution.rs[:, :, 0])
    max_x = np.nanmax(whole_solution.rs[:, :, 0])
    min_y = np.nanmin(whole_solution.rs[:, :, 1])
    max_y = np.nanmax(whole_solution.rs[:, :, 1])
    min_z = np.nanmin(whole_solution.rs[:, :, 2])
    max_z = np.nanmax(whole_solution.rs[:, :, 2])

    if p.display_size:
        ax_top.set_xlim(-p.display_size, p.display_size)
        ax_top.set_ylim(-p.display_size, p.display_size)
        ax_side.set_xlim(-p.display_size, p.display_size)
        ax_side.set_ylim(-p.display_size, p.display_size)
    else:
        ax_top.set_xlim(min_x, max_x)
        ax_top.set_ylim(min_y, max_y)
        ax_side.set_xlim(min_x, max_x)
        ax_side.set_ylim(min_z, max_z)

    circles_top = [
        plt.Circle((0, 0), find_particle_radius(1))
        for _ in range(p.num_particles)
    ]
    circles_side = [
        plt.Circle((0, 0), find_particle_radius(1))
        for _ in range(p.num_particles)
    ]
    for circle in circles_top:
        ax_top.add_artist(circle)
    for circle in circles_side:
        ax_side.add_artist(circle)

    def init():
        """initialisation function for FuncAnimation"""
        for i in range(len(circles_top)):
            circles_top[i].set_center((0, 0))
            circles_top[i].set_color('b')
            circles_top[i].set_radius(1)
        for i in range(len(circles_side)):
            circles_side[i].set_center((0, 0))
            circles_side[i].set_color('b')
            circles_side[i].set_radius(1)

        return circles_top, circles_side

    def update_screen(i):
        """update function for FuncAnimation"""
        i = i * p.display_rate
        N = int(whole_solution.Ns[i])
        for j in range(N):
            circles_top[j].set_center(whole_solution.rs[i, j, (0, 1)])
            circles_top[j].set_radius(
                find_particle_radius(whole_solution.ms[i, j]))
            circles_side[j].set_center(whole_solution.rs[i, j, (0, 2)])
            circles_side[j].set_radius(
                find_particle_radius(whole_solution.ms[i, j]))

        # remove particles that no longer exist
        for j in range(N, p.num_particles):
            circles_top[j].set_center((max_x + 1000, max_y + 1000))
            circles_side[j].set_center((max_x + 1000, max_z + 1000))

        return circles_top, circles_side

    ani = FuncAnimation(fig,
                        update_screen,
                        num_of_frames,
                        init_func=init,
                        blit=False,
                        interval=frame_interval)

    if filename:
        print("saving animation to {}".format(filename))
        if filename[-4:] == ".gif":
            writer = PillowWriter(fps=p.fps)
        elif filename[-4:] == ".mp4":
            writer = FFMpegWriter(fps=p.fps)
        else:
            raise Exception("Animation file format not allowed")
        ani.save(filename, writer=writer)

    plt.show()