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

Exercise_09 : The Billiard Problem

台球.png

Problem 3.31

冉峰 弘毅班 2014301020064


录制_2016_11_20_22_02_14_448.gif9.199.gif9.120.gif


Abstract

Background

The moving

The collision

The Chaos Theory

The Lorenz Attractor

Lorenz_Attractor.gif


The Main Body

Code for the trajectory of the billiard ball in the case of square boundary

  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. class billiard_rectangular:
  4. def __init__(self,x_0,y_0,vx_0,vy_0,N,dt):
  5. self.x_0 = x_0
  6. self.y_0 = y_0
  7. self.vx_0 = vx_0
  8. self.vy_0 = vy_0
  9. self.N = N
  10. self.dt = dt
  11. def motion_calculate(self):
  12. self.x = []
  13. self.y = []
  14. self.vx = []
  15. self.vy = []
  16. self.t = [0]
  17. self.x.append(self.x_0)
  18. self.y.append(self.y_0)
  19. self.vx.append(self.vx_0)
  20. self.vy.append(self.vy_0)
  21. for i in range(1,self.N):
  22. self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)
  23. self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)
  24. self.vx.append(self.vx[i - 1])
  25. self.vy.append(self.vy[i - 1])
  26. if (self.x[i] < -1.0):
  27. 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])
  28. self.vx[i] = - self.vx[i]
  29. elif(self.x[i] > 1.0):
  30. 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])
  31. self.vx[i] = - self.vx[i]
  32. elif(self.y[i] < -1.0):
  33. 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])
  34. self.vy[i] = -self.vy[i]
  35. elif(self.y[i] > 1.0):
  36. 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])
  37. self.vy[i] = -self.vy[i]
  38. else:
  39. pass
  40. self.t.append(self.t[i - 1] + self.dt)
  41. return self.x, self.y
  42. def correct(self,condition,x,y,vx,vy):
  43. vx_c = vx/100.0
  44. vy_c = vy/100.0
  45. while eval(condition):
  46. x = x + vx_c*self.dt
  47. y = y + vy_c*self.dt
  48. return x-vx_c*self.dt,y-vy_c*self.dt
  49. def reflect(self):
  50. pass
  51. def plot(self):
  52. plt.figure(figsize = (8,8))
  53. plt.xlim(-1,1)
  54. plt.ylim(-1,1)
  55. plt.xlabel('x')
  56. plt.ylabel('y')
  57. plt.plot(self.x,self.y,'g')
  58. plt.show()

Result



Vpython code

  1. from visual import *
  2. side = 4.0
  3. thk = 0.3
  4. s2 = 2*side - thk
  5. s3 = 2*side + thk
  6. wallR = box (pos=( side, 0, 0), size=(thk, s2, s3), color = color.green)
  7. wallL = box (pos=(-side, 0, 0), size=(thk, s2, s3), color = color.green)
  8. wallB = box (pos=(0, -side, 0), size=(s3, thk, s3), color = color.green)
  9. wallT = box (pos=(0, side, 0), size=(s3, thk, s3), color = color.green)
  10. wallG = box (pos=(0,0,-2*side),size=(s3,s3,s3),color=color.green)
  11. ball = sphere(pos=(0.2,0,0), color=color.white, radius = 0.5, make_trail=True, retain=200)
  12. ball.trail_object.radius = 0.07
  13. ball.v = vector(0.5,0.3,0.4)
  14. side = side - thk*0.5 - ball.radius
  15. dt = 0.5
  16. t=0.0
  17. while True:
  18. rate(100)
  19. t = t + dt
  20. ball.pos = ball.pos + ball.v*dt
  21. if not (side > ball.x > -side):
  22. ball.v.x = -ball.v.x
  23. if not (side > ball.y > -side):
  24. ball.v.y = -ball.v.y
  25. if not (side>ball.z>-side):
  26. ball.v.z=-ball.v.z

Result


Code for the trajectory of the billiard ball in the case of circular boundary

  1. class billiard_circle(billiard_rectangular):
  2. def motion_calculate(self):
  3. self.x = []
  4. self.y = []
  5. self.vx = []
  6. self.vy = []
  7. self.t = [0]
  8. self.x.append(self.x_0)
  9. self.y.append(self.y_0)
  10. self.vx.append(self.vx_0)
  11. self.vy.append(self.vy_0)
  12. for i in range(1,self.N):
  13. self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)
  14. self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)
  15. self.vx.append(self.vx[i - 1])
  16. self.vy.append(self.vy[i - 1])
  17. if (np.sqrt( self.x[i]**2+self.y[i]**2 ) > 1.0):
  18. 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])
  19. self.vx[i],self.vy[i] = self.reflect(self.x[i],self.y[i],self.vx[i - 1], self.vy[i - 1])
  20. self.t.append(self.t[i - 1] + self.dt)
  21. return self.x, self.y
  22. def reflect(self,x,y,vx,vy):
  23. module = np.sqrt(x**2+y**2) ### normalization
  24. x = x/module
  25. y = y/module
  26. v = np.sqrt(vx**2+vy**2)
  27. cos1 = (vx*x+vy*y)/v
  28. cos2 = (vx*y-vy*x)/v
  29. vt = -v*cos1
  30. vc = v*cos2
  31. vx_n = vt*x+vc*y
  32. vy_n = vt*y-vc*x
  33. return vx_n,vy_n
  34. def plot(self):
  35. plt.figure(figsize = (8,8))
  36. plt.xlim(-1,1)
  37. plt.ylim(-1,1)
  38. plt.xlabel('x')
  39. plt.ylabel('y')
  40. self.plot_boundary()
  41. plt.plot(self.x,self.y,'b')
  42. plt.show()
  43. def phase_space_plot(self):
  44. plt.figure(figsize = (16,8))
  45. plt.subplot(121)
  46. plt.xlabel('x')
  47. plt.ylabel(r'$v_x$')
  48. plt.scatter(self.x,self.vx, s=1)
  49. plt.subplot(122)
  50. plt.xlabel('y')
  51. plt.ylabel(r'$v_x$')
  52. plt.scatter(self.y,self.vx, s=1)
  53. plt.show()
  54. def phase_plot(self):
  55. plt.figure(figsize = (8,8))
  56. record_x = []
  57. record_vx = []
  58. for i in range(len(self.x)):
  59. if (abs(self.y[i] - 0)<0.001):
  60. record_vx.append(self.vx[i])
  61. record_x.append(self.x[i])
  62. plt.xlabel('x')
  63. plt.ylabel(r'$v_x$')
  64. plt.scatter(record_x,record_vx,s=1)
  65. plt.show()
  66. def plot_boundary(self):
  67. theta = 0
  68. x = []
  69. y = []
  70. while theta < 2*np.pi:
  71. x.append(np.cos(theta))
  72. y.append(np.sin(theta))
  73. theta+= 0.01
  74. plt.plot(x,y)

Result

9.120.gif

9.5.png
9.8.png
9.6.png
9.7.png



This is the phase diagram of and
9.9.png
9.12.png
9.11.png
9.16.png
9.14.png


Code for the trajectory of the billiard ball in the case of elliptical boundary

  1. class billiard_ellipse(billiard_circle): ### x^2/3+y^2/2 = 1
  2. def motion_calculate(self):
  3. self.x = []
  4. self.y = []
  5. self.vx = []
  6. self.vy = []
  7. self.t = [0]
  8. self.x.append(self.x_0)
  9. self.y.append(self.y_0)
  10. self.vx.append(self.vx_0)
  11. self.vy.append(self.vy_0)
  12. for i in range(1,self.N):
  13. self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)
  14. self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)
  15. self.vx.append(self.vx[i - 1])
  16. self.vy.append(self.vy[i - 1])
  17. if (self.x[i]**2/3+self.y[i]**2/2 > 1.0):
  18. 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])
  19. self.vx[i],self.vy[i] = self.reflect((2./3)*self.x[i],self.y[i],self.vx[i - 1], self.vy[i - 1])
  20. self.t.append(self.t[i - 1] + self.dt)
  21. return self.x, self.y
  22. def plot(self):
  23. plt.figure(figsize = (8,6))
  24. plt.xlim(-2.2,2.2)
  25. plt.ylim(-2,2)
  26. plt.xlabel('x')
  27. plt.ylabel('y')
  28. self.plot_boundary()
  29. plt.plot(self.x,self.y,'b')
  30. plt.show()
  31. def plot_boundary(self):
  32. theta = 0
  33. x = []
  34. y = []
  35. while theta < 2*np.pi:
  36. x.append(np.sqrt(3)*np.cos(theta))
  37. y.append(np.sqrt(2)*np.sin(theta))
  38. theta+= 0.01
  39. plt.title(r'Elliptical stadium $\frac{x^2}{4}+\frac{y^2}{3} = 3$')
  40. plt.plot(x,y)

Result

9.17.png
9.20.png
9.18.png




Code for the trajectory of the billiard ball in the case of square with an inner circle boundary, and the circle is in the center

  1. class billiard_innercircle(billiard_circle):
  2. def motion_calculate(self):
  3. self.x = []
  4. self.y = []
  5. self.vx = []
  6. self.vy = []
  7. self.t = [0]
  8. self.x.append(self.x_0)
  9. self.y.append(self.y_0)
  10. self.vx.append(self.vx_0)
  11. self.vy.append(self.vy_0)
  12. for i in range(1,self.N):
  13. self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)
  14. self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)
  15. self.vx.append(self.vx[i - 1])
  16. self.vy.append(self.vy[i - 1])
  17. if (self.x[i] < -1.0):
  18. 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])
  19. self.vx[i] = - self.vx[i]
  20. elif(self.x[i] > 1.0):
  21. 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])
  22. self.vx[i] = - self.vx[i]
  23. elif(self.y[i] < -1.0):
  24. 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])
  25. self.vy[i] = -self.vy[i]
  26. elif(self.y[i] > 1.0):
  27. 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])
  28. self.vy[i] = -self.vy[i]
  29. elif(self.x[i]**2+self.y[i]**2<0.01):
  30. 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])
  31. self.vx[i],self.vy[i] = self.reflect(self.x[i],self.y[i],self.vx[i - 1], self.vy[i - 1])
  32. self.t.append(self.t[i - 1] + self.dt)
  33. return self.x, self.y
  34. def plot_boundary(self):
  35. theta = 0
  36. x = []
  37. y = []
  38. while theta < 2*np.pi:
  39. x.append(0.1*np.cos(theta))
  40. y.append(0.1*np.sin(theta))
  41. theta+= 0.01
  42. plt.plot(x,y)

Result

9.27.png

9.28.png



Code for the trajectory of the billiard ball in the case of square with an inner circle boundary and the circle is slightly off-center

  1. class billiard_innercircle2(billiard_circle):
  2. def motion_calculate(self):
  3. self.x = []
  4. self.y = []
  5. self.vx = []
  6. self.vy = []
  7. self.t = [0]
  8. self.x.append(self.x_0)
  9. self.y.append(self.y_0)
  10. self.vx.append(self.vx_0)
  11. self.vy.append(self.vy_0)
  12. for i in range(1,self.N):
  13. self.x.append(self.x[i - 1] + self.vx[i - 1]*self.dt)
  14. self.y.append(self.y[i - 1] + self.vy[i - 1]*self.dt)
  15. self.vx.append(self.vx[i - 1])
  16. self.vy.append(self.vy[i - 1])
  17. if (self.x[i] < -1.0):
  18. 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])
  19. self.vx[i] = - self.vx[i]
  20. elif(self.x[i] > 1.0):
  21. 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])
  22. self.vx[i] = - self.vx[i]
  23. elif(self.y[i] < -1.0):
  24. 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])
  25. self.vy[i] = -self.vy[i]
  26. elif(self.y[i] > 1.0):
  27. 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])
  28. self.vy[i] = -self.vy[i]
  29. elif((self.x[i] - 0.05)**2+self.y[i]**2<0.01):
  30. 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])
  31. self.vx[i],self.vy[i] = self.reflect(self.x[i]-0.05,self.y[i],self.vx[i - 1], self.vy[i - 1])
  32. self.t.append(self.t[i - 1] + self.dt)
  33. return self.x, self.y
  34. def plot_boundary(self):
  35. theta = 0
  36. x = []
  37. y = []
  38. plt.title(r'$(x-0.5)^2+y^2 = 0.01$')
  39. while theta < 2*np.pi:
  40. x.append(0.1*np.cos(theta)+0.5)
  41. y.append(0.1*np.sin(theta))
  42. theta+= 0.01
  43. plt.plot(x,y)

Result

9.25.png


9.41.png


Conclusion


Thanks For

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注