Реализация алгоритма Верле в Python
У меня проблема с реализацией алгоритма верлета в Python. Я попробовал этот код:
x[0] = 1
v[0] = 0
t[0] = 0
a[0] = 1
for i in range (0, 1000):
x[i+1] = x[i] - v[i] * dt + (a[i] * (dt**2) * 0.5)
v[i] = (x[i+1] - x[i-1]) * 0.5 * dt
t[i+1] = t[i] + dt
Но это не работает должным образом. Что случилось? Я ищу общий код для алгоритма Verlet.
2 ответа
Есть несколько проблем с вашей реализацией,
- На этапе
0
вы пытаетесь получить доступ к индексу-1
который не существует, и при этом индекс неi+1
для последнего индекса. - Ускорение определяется только на первом шаге, а не для других.
- При расчете следующей позиции есть ошибка знака.
Что-то вроде этого должно это исправить,
import numpy as np
N = 1000
dt = 0.1
x = np.zeros(N)
v = np.zeros(N)
t = np.arange(0,(N+0.5)*dt, dt)
a = np.ones(N)*1.0 # initial condition
x[[0,1]] = 1
v[1] = v[0]+a[0]*dt
for i in range (1,N-1):
x[i+1] = x[i]+v[i]*dt+(a[i]*(dt**2)*0.5)
v[i+1] = v[i] + a[i]*dt
Это не будет очень эффективно, хотя лучше использовать scipy.integrate.ode
решить базовое дифференциальное уравнение движения.
Ваш вопрос не очень понятен, но в вашем коде есть несколько источников ошибок.
Например, для i
> 0
x[i+1] = x[i]-v[i]*dt+(a[i]*(dt**2)*0.5)
пытается использовать значение v[i]
, но этот элемент еще не существует в v
список.
Чтобы привести конкретный пример, когда i
= 1, вам нужно v[1]
, но единственное в v
список на этом этапе v[0]
; v[1]
не вычисляется до следующей строки.
Эта ошибка должна заставить интерпретатор Python отображать сообщение об ошибке:
IndexError: list index out of range
При обращении за помощью в Stack Overflow, пожалуйста, публикуйте сообщения об ошибках вместе с вопросом, желательно начиная со строки:
Traceback (most recent call last):
Это облегчает людям, читающим ваш вопрос, отладку вашего кода.
FWIW, на первой итерации вашего for
цикл, когда i
== 0, x[i+1]
а также x[i-1]
оба ссылаются на один и тот же элемент, так как в x
список на этом этапе, так x[-1]
является x[1]
,
Кроме того, странно, что вы храните свои t
значения в списке. Вам не нужно это делать. Просто магазин t
как простой float
значение и увеличить его на dt
каждый раз через цикл; Обратите внимание, что t
Сам по себе не используется ни в одном из расчетов, но вы можете распечатать его.
Ваши формулы не соответствуют тем, которые приведены на странице Википедии, ни для Basic Störmer-Verlet, ни для Velocity Verlet. Например, в строке кода, которую я цитировал ранее, вы вычитаете v[i]*dt
но вы должны добавить это.
Возможно, вам следует подумать о реализации связанного метода интеграции Leapfrog. Синхронизированная версия Leapfrog проста в написании и довольно эффективна, IME.
Из ссылки на Википедию:
x[i+1] = x[i] + v[i] * dt + 0.5 * a[i] * dt * dt
v[i+1] = v[i] + 0.5 * (a[i] + a[i+1]) * dt
Как правило, нет необходимости хранить a
значения в списке, так как они будут рассчитываться по другим параметрам с использованием соответствующего уравнения силы.