Я пытаюсь создать (очень) простое N-body
моделирование и анимировать его в 3D
.Вот мой код:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
G=6.67408e-11
msol=1.989e40
mter=5.972e24
au=1.496e11
dt=.0007
N=30
positions=np.random.rand(N,3)
velocities=np.random.randn(N,3)
acc=np.zeros_like(positions)
masses=np.random.rand(N)
def gravforce(m0,m1,pos0,pos1):
global G
dx=pos1[0]-pos0[0]
dy=pos1[1]-pos0[1]
dz=pos1[2]-pos0[2]
r=np.sqrt(dx**2+dy**2+dz**2)
f=-G*m0*m1/r**2
ratio=f/r
fx=dx*ratio
fy=dy*ratio
fz=dz*ratio
return fx, fy, fz
fig,ax=plt.subplots(subplot_kw=dict(projection='3d'))
planets=ax.scatter(positions[:,0],positions[:,1],positions[:,2],c='b',marker='o')
def animate(i):
acc[:,0]=[sum([gravforce(masses[i],masses[j],positions[i],positions[j])[0]/masses[j] for j in range(1,N) if j != i]) for i in range(len(acc))]
acc[:,1]=[sum([gravforce(masses[i],masses[j],positions[i],positions[j])[1]/masses[j] for j in range(1,N) if j != i]) for i in range(len(acc))]
acc[:,2]=[sum([gravforce(masses[i],masses[j],positions[i],positions[j])[2]/masses[j] for j in range(1,N) if j != i]) for i in range(len(acc))]
velocities[:,0]=velocities[:,0]+acc[:,0]*dt
velocities[:,1]=velocities[:,1]+acc[:,1]*dt
velocities[:,2]=velocities[:,2]+acc[:,2]*dt
positions[:,0]=positions[:,0]+velocities[:,0]*dt
positions[:,1]=positions[:,1]+velocities[:,1]*dt
positions[:,2]=positions[:,2]+velocities[:,2]*dt
planets.set_sizes(masses[:]*20)
planets._offsets3d(positions[:,0],positions[:,1],positions[:2])
ani=FuncAnimation(fig,animate,frames=1000,interval=1,blit=False)
Когда я запускаю его, я получаю следующее сообщение об ошибке:
Traceback (most recent call last):
File "<ipython-input-30-b2a4f400dbe9>", line 1, in <module>
runfile('C:/Program Files (x86)/WinPython-64bit-3.3.5.9/python-3.3.5.amd64/Scripts/orbit/3dnbody_2dprojection.py', wdir='C:/Program Files (x86)/WinPython-64bit-3.3.5.9/python-3.3.5.amd64/Scripts/orbit')
File "C:\Program Files (x86)\WinPython-64bit-3.3.5.9\python-3.3.5.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 685, in runfile
execfile(filename, namespace)
File "C:\Program Files (x86)\WinPython-64bit-3.3.5.9\python-3.3.5.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 85, in execfile
exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)
File "C:/Program Files (x86)/WinPython-64bit-3.3.5.9/python-3.3.5.amd64/Scripts/orbit/3dnbody_2dprojection.py", line 56, in <module>
ani=FuncAnimation(fig,animate,frames=1000,interval=1,blit=False)
File "C:\Program Files (x86)\WinPython-64bit-3.3.5.9\python-3.3.5.amd64\lib\site-packages\matplotlib\animation.py", line 1067, in __init__
TimedAnimation.__init__(self, fig, **kwargs)
File "C:\Program Files (x86)\WinPython-64bit-3.3.5.9\python-3.3.5.amd64\lib\site-packages\matplotlib\animation.py", line 913, in __init__
*args, **kwargs)
File "C:\Program Files (x86)\WinPython-64bit-3.3.5.9\python-3.3.5.amd64\lib\site-packages\matplotlib\animation.py", line 591, in __init__
self._init_draw()
File "C:\Program Files (x86)\WinPython-64bit-3.3.5.9\python-3.3.5.amd64\lib\site-packages\matplotlib\animation.py", line 1092, in _init_draw
self._draw_frame(next(self.new_frame_seq()))
File "C:\Program Files (x86)\WinPython-64bit-3.3.5.9\python-3.3.5.amd64\lib\site-packages\matplotlib\animation.py", line 1106, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "C:/Program Files (x86)/WinPython-64bit-3.3.5.9/python-3.3.5.amd64/Scripts/orbit/3dnbody_2dprojection.py", line 54, in animate
planets._offsets3d(positions[:,0],positions[:,1],positions[:2])
TypeError: 'tuple' object is not callable
Насколько я могу судить, я не вызываю кортеж (изВ моем понимании это было бы попыткой сделать, например, F(2)
вместо F[2]
, где F
- это кортеж), поэтому это сбивает меня с толку и расстраивает.
Я также приветствую любые горячиесоветы, как сделать этот код более элегантным / эффективным.