@rfhongyi
2016-11-21T02:29:03.000000Z
字数 11493
阅读 1373





import matplotlib.pyplot as pltimport numpy as npclass billiard_rectangular:def __init__(self,x_0,y_0,vx_0,vy_0,N,dt):self.x_0 = x_0self.y_0 = y_0self.vx_0 = vx_0self.vy_0 = vy_0self.N = Nself.dt = dtdef motion_calculate(self):self.x = []self.y = []self.vx = []self.vy = []self.t = [0]self.x.append(self.x_0)self.y.append(self.y_0)self.vx.append(self.vx_0)self.vy.append(self.vy_0)for i in range(1,self.N):self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)self.vx.append(self.vx[i - 1])self.vy.append(self.vy[i - 1])if (self.x[i] < -1.0):self.x[i],self.y[i] = self.correct('x>-1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i] = - self.vx[i]elif(self.x[i] > 1.0):self.x[i],self.y[i] = self.correct('x<1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i] = - self.vx[i]elif(self.y[i] < -1.0):self.x[i],self.y[i] = self.correct('y>-1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vy[i] = -self.vy[i]elif(self.y[i] > 1.0):self.x[i],self.y[i] = self.correct('y<1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vy[i] = -self.vy[i]else:passself.t.append(self.t[i - 1] + self.dt)return self.x, self.ydef correct(self,condition,x,y,vx,vy):vx_c = vx/100.0vy_c = vy/100.0while eval(condition):x = x + vx_c*self.dty = y + vy_c*self.dtreturn x-vx_c*self.dt,y-vy_c*self.dtdef reflect(self):passdef plot(self):plt.figure(figsize = (8,8))plt.xlim(-1,1)plt.ylim(-1,1)plt.xlabel('x')plt.ylabel('y')plt.plot(self.x,self.y,'g')plt.show()

from visual import *side = 4.0thk = 0.3s2 = 2*side - thks3 = 2*side + thkwallR = box (pos=( side, 0, 0), size=(thk, s2, s3), color = color.green)wallL = box (pos=(-side, 0, 0), size=(thk, s2, s3), color = color.green)wallB = box (pos=(0, -side, 0), size=(s3, thk, s3), color = color.green)wallT = box (pos=(0, side, 0), size=(s3, thk, s3), color = color.green)wallG = box (pos=(0,0,-2*side),size=(s3,s3,s3),color=color.green)ball = sphere(pos=(0.2,0,0), color=color.white, radius = 0.5, make_trail=True, retain=200)ball.trail_object.radius = 0.07ball.v = vector(0.5,0.3,0.4)side = side - thk*0.5 - ball.radiusdt = 0.5t=0.0while True:rate(100)t = t + dtball.pos = ball.pos + ball.v*dtif not (side > ball.x > -side):ball.v.x = -ball.v.xif not (side > ball.y > -side):ball.v.y = -ball.v.yif not (side>ball.z>-side):ball.v.z=-ball.v.z


class billiard_circle(billiard_rectangular):def motion_calculate(self):self.x = []self.y = []self.vx = []self.vy = []self.t = [0]self.x.append(self.x_0)self.y.append(self.y_0)self.vx.append(self.vx_0)self.vy.append(self.vy_0)for i in range(1,self.N):self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)self.vx.append(self.vx[i - 1])self.vy.append(self.vy[i - 1])if (np.sqrt( self.x[i]**2+self.y[i]**2 ) > 1.0):self.x[i],self.y[i] = self.correct('np.sqrt(x**2+y**2) < 1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i],self.vy[i] = self.reflect(self.x[i],self.y[i],self.vx[i - 1], self.vy[i - 1])self.t.append(self.t[i - 1] + self.dt)return self.x, self.ydef reflect(self,x,y,vx,vy):module = np.sqrt(x**2+y**2) ### normalizationx = x/moduley = y/modulev = np.sqrt(vx**2+vy**2)cos1 = (vx*x+vy*y)/vcos2 = (vx*y-vy*x)/vvt = -v*cos1vc = v*cos2vx_n = vt*x+vc*yvy_n = vt*y-vc*xreturn vx_n,vy_ndef plot(self):plt.figure(figsize = (8,8))plt.xlim(-1,1)plt.ylim(-1,1)plt.xlabel('x')plt.ylabel('y')self.plot_boundary()plt.plot(self.x,self.y,'b')plt.show()def phase_space_plot(self):plt.figure(figsize = (16,8))plt.subplot(121)plt.xlabel('x')plt.ylabel(r'$v_x$')plt.scatter(self.x,self.vx, s=1)plt.subplot(122)plt.xlabel('y')plt.ylabel(r'$v_x$')plt.scatter(self.y,self.vx, s=1)plt.show()def phase_plot(self):plt.figure(figsize = (8,8))record_x = []record_vx = []for i in range(len(self.x)):if (abs(self.y[i] - 0)<0.001):record_vx.append(self.vx[i])record_x.append(self.x[i])plt.xlabel('x')plt.ylabel(r'$v_x$')plt.scatter(record_x,record_vx,s=1)plt.show()def plot_boundary(self):theta = 0x = []y = []while theta < 2*np.pi:x.append(np.cos(theta))y.append(np.sin(theta))theta+= 0.01plt.plot(x,y)


This is the phase diagram of and

class billiard_ellipse(billiard_circle): ### x^2/3+y^2/2 = 1def motion_calculate(self):self.x = []self.y = []self.vx = []self.vy = []self.t = [0]self.x.append(self.x_0)self.y.append(self.y_0)self.vx.append(self.vx_0)self.vy.append(self.vy_0)for i in range(1,self.N):self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)self.vx.append(self.vx[i - 1])self.vy.append(self.vy[i - 1])if (self.x[i]**2/3+self.y[i]**2/2 > 1.0):self.x[i],self.y[i] = self.correct('x**2/3+y**2/2 < 1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i],self.vy[i] = self.reflect((2./3)*self.x[i],self.y[i],self.vx[i - 1], self.vy[i - 1])self.t.append(self.t[i - 1] + self.dt)return self.x, self.ydef plot(self):plt.figure(figsize = (8,6))plt.xlim(-2.2,2.2)plt.ylim(-2,2)plt.xlabel('x')plt.ylabel('y')self.plot_boundary()plt.plot(self.x,self.y,'b')plt.show()def plot_boundary(self):theta = 0x = []y = []while theta < 2*np.pi:x.append(np.sqrt(3)*np.cos(theta))y.append(np.sqrt(2)*np.sin(theta))theta+= 0.01plt.title(r'Elliptical stadium $\frac{x^2}{4}+\frac{y^2}{3} = 3$')plt.plot(x,y)



class billiard_innercircle(billiard_circle):def motion_calculate(self):self.x = []self.y = []self.vx = []self.vy = []self.t = [0]self.x.append(self.x_0)self.y.append(self.y_0)self.vx.append(self.vx_0)self.vy.append(self.vy_0)for i in range(1,self.N):self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)self.vx.append(self.vx[i - 1])self.vy.append(self.vy[i - 1])if (self.x[i] < -1.0):self.x[i],self.y[i] = self.correct('x>-1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i] = - self.vx[i]elif(self.x[i] > 1.0):self.x[i],self.y[i] = self.correct('x<1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i] = - self.vx[i]elif(self.y[i] < -1.0):self.x[i],self.y[i] = self.correct('y>-1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vy[i] = -self.vy[i]elif(self.y[i] > 1.0):self.x[i],self.y[i] = self.correct('y<1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vy[i] = -self.vy[i]elif(self.x[i]**2+self.y[i]**2<0.01):self.x[i],self.y[i] = self.correct('x**2+y**2 > 0.01',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i],self.vy[i] = self.reflect(self.x[i],self.y[i],self.vx[i - 1], self.vy[i - 1])self.t.append(self.t[i - 1] + self.dt)return self.x, self.ydef plot_boundary(self):theta = 0x = []y = []while theta < 2*np.pi:x.append(0.1*np.cos(theta))y.append(0.1*np.sin(theta))theta+= 0.01plt.plot(x,y)




class billiard_innercircle2(billiard_circle):def motion_calculate(self):self.x = []self.y = []self.vx = []self.vy = []self.t = [0]self.x.append(self.x_0)self.y.append(self.y_0)self.vx.append(self.vx_0)self.vy.append(self.vy_0)for i in range(1,self.N):self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)self.vx.append(self.vx[i - 1])self.vy.append(self.vy[i - 1])if (self.x[i] < -1.0):self.x[i],self.y[i] = self.correct('x>-1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i] = - self.vx[i]elif(self.x[i] > 1.0):self.x[i],self.y[i] = self.correct('x<1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i] = - self.vx[i]elif(self.y[i] < -1.0):self.x[i],self.y[i] = self.correct('y>-1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vy[i] = -self.vy[i]elif(self.y[i] > 1.0):self.x[i],self.y[i] = self.correct('y<1.0',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vy[i] = -self.vy[i]elif((self.x[i] - 0.05)**2+self.y[i]**2<0.01):self.x[i],self.y[i] = self.correct('(x - 0.05)**2+y**2 > 0.01',self.x[i - 1], self.y[i - 1], self.vx[i - 1], self.vy[i - 1])self.vx[i],self.vy[i] = self.reflect(self.x[i]-0.05,self.y[i],self.vx[i - 1], self.vy[i - 1])self.t.append(self.t[i - 1] + self.dt)return self.x, self.ydef plot_boundary(self):theta = 0x = []y = []plt.title(r'$(x-0.5)^2+y^2 = 0.01$')while theta < 2*np.pi:x.append(0.1*np.cos(theta)+0.5)y.append(0.1*np.sin(theta))theta+= 0.01plt.plot(x,y)


