Моделирование простого сценария, связанного с физикой

#python #physics

#python #физика

Вопрос:

Я полный новичок в обоих симуляциях, поэтому этот вопрос может показаться глупым. Если да, пожалуйста, не стесняйтесь редактировать его. Я пытаюсь смоделировать следующий сценарий на Python. Я случайным образом помещаю несколько маленьких частиц в 2D-поле с фиксированными размерами. Каждая частица имеет радиус воздействия r . Если первая частица имеет вторую в радиусе своего действия, то к обеим частицам должна быть применена сила (эффект, который первая оказывает на вторую, и наоборот), и моя функция силы определяется как:

f(i,j)_n = (r - |pi_n - pj_n|)((pj_n - pi_n)/|pi_n - pj_n|)

где n — текущий временной шаг, pi_n представляет положение i на временном шаге n и || представляет вычисление величины и (pj_n - pi_n) представляет вычитание вектора.

Мне было интересно, есть ли какие-либо библиотеки, которые упрощают этот материал для меня. Все, что мне нужно, это в основном следующее:

 time-step particle position(x,y)
  

У кого-нибудь есть какие-нибудь предложения для меня, пожалуйста?

Комментарии:

1. Если вы абсолютный новичок в симуляциях, я бы рекомендовал попробовать написать это самостоятельно. Эти библиотеки могут немного сбить с толку новичков. Кроме того, вы сможете изучить материал.

Ответ №1:

Поиск в Google для python library vector 2d возвращенных http://www.supereffective.org/pages/Vector-2d-Vector-Library в качестве главного хита, который кажется компетентной библиотекой (содержащей проекцию и перпендикуляризацию, нормализацию, вращение, масштабирование и т.д.)

Пока количество частиц не слишком велико, это должно отлично работать в сочетании со схемой интеграции. например, вы отслеживаете векторы каждой частицы (pos, vel) и, возможно, также ускорения и используете:

F = m a

-> F = m dv/dt

-> dv/dt = F/m

и таким образом

dv ~= dt*F/m

-> v' - v ~= dt*F/m

-> ball.vel = timeStep*sum(ball.force(n) for n in ball.neighbors())/ball.mass

Это интеграция Эйлера, которая обладает довольно плохими свойствами, но подходит для игры.

Ответ №2:

Мне действительно нравится библиотека физики pymunk, оболочка для библиотеки физики бурундука.

Прежде всего, необходимо инициализировать библиотеку:

 import pymunk
pymunk.init_pymunk()
space = pymunk.Space()
space.gravity = (0.0, -100.0)
  

Чтобы достичь чего-то подобного, что вы просили, вам нужно создать Body и Circle форму для каждой частицы, которую вы хотите создать.

 mass = 1
radius = 14
inertia = pymunk.moment_for_circle(mass, 0, radius, (0,0))
body = pymunk.Body(mass, inertia)
x, y = random.randint(0, 200), random.randint(0, 200)
body.position = x, 550
shape = pymunk.Circle(body, radius, (0,0))
shape.sensor = True
space.add(body, shape)
  

Частицы не будут сталкиваться друг с другом, потому что sensor флаг установлен на True . Радиус теперь является чем-то вроде области влияния.

Теперь мы создаем функцию обратного вызова для частиц, которые имеют перекрывающуюся область влияния:

 def near_callback(space, arbiter, *args, **kwargs):
    body_i = arbiter.shapes[0].body
    body_j = arbiter.shapes[1].body

    # calculate the forces force_i and force_j with your formula
    ...

    body_i.apply_force(force_i)
    body_j.apply_force(force_j)
  

Обратный вызов задается в space :

 space.set_default_collision_handler(near_callback, near_callback, None, None, None)
  

Конечно, space должно быть «пошаговым» для каждого временного интервала:

 space.step(dt)
  

Я надеюсь, что это было несколько понятно и полезно.

Комментарии:

1. Я знаю, что это довольно поздно, но я возвращаюсь к этому вопросу и проверяю ваш ответ. Не могли бы вы указать мне на какой-либо полезный материал, связанный с pymunk? Я устанавливал dt=1 и выполнял space.step(dt) почти 100 раз, но обратный вызов так и не был вызван. Может быть, я делаю что-то тривиально неправильное. Не могли бы вы показать рабочий пример, с которым я могу поиграть?