"""
A program that generates orbits of random particles and plots them using matplot3d. You can specify the number of particles in this simulation by the first argument and the mass of the center object (~100~500) by the second. Standard call: python orbit.py [number of particles] [mass of center object]
"""
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
import sys
def Gen_Orbits(length, dims=3, particles=3) :
"""
Create orbits using Euler method
length is the number of points for the line.
dims is the number of dimensions the line has.
"""
lineData = np.empty((particles, dims, length))
velocity = np.empty((particles, dims, length))
lineData[:, :, 0] = np.random.rand(particles, dims)*20-10
velocity[:, :, 0] = np.random.rand(particles, dims)*20-10
#velocity[:,:,0]=np.empty((particles, dims))
m = np.random.rand(particles)*30
m[0] = 100
if len(sys.argv) > 2:
m[0] = int(sys.argv[2])
velocity[0, :, 0] = [0,0,0]
t=0.001
for index in range(1, length) :
step = determine_step(lineData[:, :, index-1],m)/10000
velocity[:, :, index] = velocity[:,:,index-1] + step
lineData[:, :, index] = lineData[:, :, index-1] + velocity[:, :, index-1]*t + (step[:,:]**2)/2*t**2
return lineData
def determine_step(lineData,m):
step = np.empty((np.size(lineData,0),np.size(lineData,1)))
particles = np.arange(np.size(lineData,0))
x = lineData[:,0]
y = lineData[:,1]
z = lineData[:,2]
for p1 in particles:
for p2 in particles:
if (p1 == 0):
step[p1,:] = [0, 0, 0]
continue
if (p1==p2):
continue
dx = (x[p2]-x[p1])
dy = (y[p2]-y[p1])
dz = (z[p2]-z[p1])
r=(dx**2+dy**2+dz**2)**(1/2)
f=m[p1]*m[p2]/r**2
step[p1,:] = step[p1,:] + f*np.array([dx,dy,dz])/r/m[p1]
return step
def update_lines(num, dataLines, lines) :
for line, data in zip(lines, dataLines) :
# NOTE: there is no .set_data() for 3 dim data...
line.set_data(data[0:2, :num])
line.set_3d_properties(data[2,:num])
return lines
# Attaching 3D axis to the figure
fig = plt.figure()
ax = p3.Axes3D(fig)
# Calculating the data
N_PARTICLES = 3
if len(sys.argv) > 1:
N_PARTICLES = int(sys.argv[1])
data = Gen_Orbits(10000, 3, N_PARTICLES)
# Reducing plotting data by 10
rdata = np.empty((N_PARTICLES, 3, 1000))
for i in range(0,10000,10):
rdata[:,:,i/10] = data[:,:,i]
# Creating fifty line objects.
# NOTE: Can't pass empty arrays into 3d version of plot()
lines = [ax.plot(dat[0, 0:1], dat[1, 0:1], dat[2, 0:1])[0] for dat in rdata]
# Setting the axes properties
ax.set_xlim3d([-30.0, 30.0])
ax.set_xlabel('X')
ax.set_ylim3d([-30.0, 30.0])
ax.set_ylabel('Y')
ax.set_zlim3d([-30.0, 30.0])
ax.set_zlabel('Z')
ax.set_title('Orbits')
# Creating the Animation object
line_ani = animation.FuncAnimation(fig, update_lines, 1000, fargs=(rdata, lines),
interval=10, blit=False)
plt.show()