Липкие блоки в 2D эласти c столкновений с VPython - PullRequest
0 голосов
/ 29 января 2020

Я пытаюсь реализовать известную проблему столкновения elasti c, представленную в этом видео .

Я использую V Python для имитации всего этого, однако мой по какой-то причине код работает неправильно; похоже, что когда происходит третье столкновение, блоки «бесконечно сталкиваются» (счетчик столкновений продолжает увеличиваться), и блоки затем склеиваются. Они даже проходят сквозь стену, а не подпрыгивают на ней, и я не могу понять, почему.

Вот мой код:

from vpython import *
import numpy as np
import time


def compute_pi(number_of_digits):
    scene = canvas(width=1280, height=720, range=3.8, center=vec(6, 0, 0))
    scene.title = 'Computing PI with collisions'

    # blocks
    small_block = box(
        pos=vec(2.0, -2.5, 0.0), 
        size=vec(1.0, 1.0, 0.01), 
        color=vec(0.5, 1.0, 0.3)
    )
    large_block = box(
        pos=vec(4.0, -2.0, 0.0), 
        size=vec(2.0, 2.0, 0.01), 
        color=vec(1.0, 0.5, 0.3)
    )

    # wall & ground
    wall = box(
        pos=vec(0.0, 0.0, 0.0), 
        size=vec(0.1, 6, 0.01), 
        color=vec(1.0, 1.0, 1.0)
    )
    ground = box(
        pos=vec(9.95, -3.0, 0.0), 
        size=vec(20, 0.1, 0.01), 
        color=vec(1.0, 1.0, 1.0)
    )

    # initial conditions
    small_block.m = 1.0
    large_block.m = 100 ** (number_of_digits - 1)
    small_block.vel = vec(0.0, 0.0, 0.0)
    large_block.vel = vec(-0.01, 0.0, 0.0)

    t = 0
    dt = 0.05
    collisions_counter = 0

    time.sleep(0.5)

    while True:
        rate(1000)
        large_block.pos += large_block.vel * dt
        small_block.pos += small_block.vel * dt

        # wall collision
        if (small_block.pos.x - small_block.size.x / 2 < wall.pos.x + wall.size.x / 2):
            small_block.vel *= -1
            collisions_counter += 1
            print ("Number of collisions: " + str(collisions_counter))

        # blocks collision
        if (small_block.pos.x + small_block.size.x / 2 > large_block.pos.x - large_block.size.x / 2):
            small_block.vel = ((small_block.m - large_block.m) / (small_block.m + large_block.m)) * small_block.vel + ((2 * large_block.m) / (small_block.m + large_block.m)) * large_block.vel
            large_block.vel = ((2 * small_block.m) / (small_block.m + large_block.m)) * small_block.vel + ((large_block.m - small_block.m) / (small_block.m + large_block.m)) * large_block.vel
            collisions_counter += 1
            print ("Number of collisions: " + str(collisions_counter))

        t += dt 

1 Ответ

0 голосов
/ 04 февраля 2020

Я не могу изучить всю вашу физику здесь, но я думаю, что вы, возможно, стали жертвой следующей проблемы: Когда происходит столкновение, которое обращает вспять компонент скорости x, кажется естественным просто установить vx = -vx. К сожалению, если последнее движение прошло достаточно глубоко за границей, вы можете получить колебательную фибрилляцию, если в следующем временном интервале вы все еще достаточно пройдете границу, чтобы снова перевернуть знак заряда. Более безопасный тест должен быть явным: если вы когда-нибудь найдете положение справа от границы, явно установите vx = -abs (vx), а если слева от границы, явно установите vx = abs (vx).

...