ipyvolume
import numpy as np
import ipyvolume as ipv
class Particle():
def __init__ (self, pos_vec, vel_vec, box_size, time_step, grav):
self.pos = pos_vec
self.vec = vel_vec
self.grav = grav
self.box_size = box_size
def pos_update(self, time_step):
for i in range(3):
if self.pos[i] > self.box_size:
self.vec[i] = self.vec[i]*-1
self.pos[i] += -(self.pos[i]-self.box_size)
if self.pos[i]<0:
self.vec[i] = self.vec[i]*-1
self.pos[i] += -self.pos[i]
if self.grav == True:
if i==2:
self.vec = self.vec*0.8
if self.grav == True:
self.vec[2]= self.vec[2]-time_step*1
self.pos[0] += self.vec[0]*time_step
self.pos[1] += self.vec[1]*time_step
self.pos[2] += self.vec[2]*time_step
def initialize_particles(number_of_particles,box_size,time_step, grav = False):
velocities = np.random.randn(number_of_particles,3)
mean_vel = np.full([number_of_particles,3], np.mean(velocities, axis=0))
velocities = np.subtract(velocities,mean_vel)
velocities[:,2] = 0
pos_vec = np.random.random([number_of_particles,3])*box_size #Generate random positions
particle_list = []
for i in range(number_of_particles):
particle_list.append(Particle(pos_vec[i,:], velocities[i,:], box_size,time_step, grav))
return particle_list
def bounce(particle1,particle2, particle_radius, time_step):
a = particle1.pos - particle2.pos
b = (a[0]**2 + a[1]**2 + a[2]**2)**(1/2)
n = np.divide(a,b,out=np.zeros_like(a), where=b!=0)
v_rel = particle1.vec - particle2.vec
v_norm = np.dot(v_rel,n)*n
particle1.vec += -v_norm
particle2.vec += +v_norm
while particledist(particle1, particle2)<(2*particle_radius):
particle1.pos_update(time_step)
particle2.pos_update(time_step)
def particledist(particle1, particle2):
r_x = particle1.pos[0] - particle2.pos[0]
r_y = particle1.pos[1] - particle2.pos[1]
r_z = particle1.pos[2] - particle2.pos[2]
r = (r_x**2 + r_y**2 + r_z**2)**(1/2)
return r
def isbounce(particle_list, particle_radius, time_step):
for particle1 in particle_list:
for particle2 in particle_list:
if particledist(particle1,particle2)<2*particle_radius and particledist(particle1,particle2)!=0:
bounce(particle1, particle2, particle_radius, time_step) #Call bounce function
def avgvel(particle_list):
vel_vec = np.array([0,0,0])
for particle in particle_list:
vel_vec =vel_vec + particle.vec
avg_vec = vel_vec/len(particle_list)
return avg_vec
def tot_eng(particle_list):
tot_eng = 0
for particle in particle_list:
tot_eng = tot_eng + particle.vec[0]**2 + particle.vec[1]**2 + particle.vec[2]**2
return tot_eng
def particleSimulate(num_particles, box_size, total_time, time_step, particle_radius,
grav = False, save = False):
particle_list = initialize_particles(num_particles, box_size, time_step, grav) #Generate starting points
x=np.zeros([total_time,num_particles,1])
y=np.zeros([total_time,num_particles,1])
z=np.zeros([total_time,num_particles,1])
time = 0
while time < total_time:
isbounce(particle_list, particle_radius, time_step)
for i in range(len(particle_list)):
particle_list[i].pos_update(time_step) #Update position
x[time,i] = particle_list[i].pos[0]
y[time,i] = particle_list[i].pos[1]
z[time,i] = particle_list[i].pos[2]
time += 1
if (time/total_time)*100%10==0:
print(str(time/total_time*100) + "% complete")
colors = []
for i in range(num_particles):
colors.append([0,0,1])
ipv.figure()
s = ipv.scatter(x, z, y, color = colors , size=7, marker="sphere")
ipv.animation_control(s, interval=1)
ipv.xlim(-1,box_size+1)
ipv.ylim(-1,box_size+1)
ipv.zlim(-1,box_size+1)
ipv.style.axes_off()
ipv.save('./particle_sim.html')
num_particles = 30
box_size = 10
total_time = 1000
time_step = 0.02
particle_radius = 0.5
particleSimulate(num_particles, box_size, total_time, time_step, particle_radius)
Yukarı