[关闭]
@computationalphysics-2014301020090 2016-10-16T16:48:44.000000Z 字数 12640 阅读 243

The 5th homework

Chapter 2.2 problem 2.9:The trajectory of a cannon shell


在此输入正文

●Abstract

problem 2.9

Calculate the trajectory of our cannon shell including both air drag and the reduced air density at high altitudes so that you can reproduce the results in Figure2.5 . Perform your calculation for different firing angles and determine the value of angle the gives the maximum range.


●background

We investigate the effects of both air drag and the reduced air density at high altitudes in order to reproduce the results in textbook for L1. We generalize it to cover targets of different altitude and use Python to design the programs, which can realize the purpose of this assignment. This article deals with the ideas for these problems, the programs ,and the results.
Without air drag, the trajectory of a cannon shell would be a perfect parabola, and the maximum range occurs for a firing angle of 45°. However, when the air drag is considered, things are distinctly different: the maximum range would be a smaller one.
Since the cannon shell could reach considerable high altitudes, we must be aware of the reduced air density. In this problem, we solved both the isothermal and adiabatic cases, and generalize the problem to cover targets at different altitudes.
On top of that, we can use several numerical approaches including the simple Euler method and the Runge-Kutta method to yield the numerical solutions to these problems.


●Content

●Idea

●we assumed that the drag force for cannon shell is given by


●according to Newton's second law,


●We also take the reduced air density at high altitudes into account. There are two mainstream models regard of this problem in statistical mechanics: isothermal ideal gas, and adiabatic approximation.
For isothermal ideal gas, the pressure p depends on altitudes according to

●For an ideal gas the pressure is proportional to the destiny,so this leads to

where and is the density at sea level≈1.225.
●For adiabatic approximation, the density depends on altitudes according to

where a≈ for air. Here is the sea level temperature (in K)≈300K.
●Since the drag force due to air resistance is proportional to the density, so for both models we have

●Now we can get for isothermal ideal gas, the equations of motion become


●Also, for adiabatic approximation, the equations of motion become


●On top of that, we can use several numerical approaches including the simple Euler method and the Runge-Kutta method to yield the numerical solutions to these problems.

●Code1

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sun Oct 16 16:57:48 2016
  4. @author: 胡胜勇
  5. """
  6. import math
  7. import matplotlib.pyplot as plt
  8. # import modules
  9. g=9.8
  10. B2m=0.00004
  11. y_zero=10000
  12. a=0.0065
  13. T0=300
  14. alpha=2.5
  15. # set constants
  16. class cannon0:
  17. "the simplest model with no air drag, no air density variance, no probability distribution"
  18. # initialize variables
  19. def __init__(self,v0,theta,yFinal=0):
  20. self.x0=0
  21. self.y0=0
  22. self.yFinal=yFinal
  23. self.v0=v0
  24. self.Theta=theta
  25. self.theta=theta*math.pi/180
  26. self.vx0=self.v0*math.cos(self.theta)
  27. self.vy0=self.v0*math.sin(self.theta)
  28. self.dt=0.01
  29. return None
  30. # external force other than gravity, no force in simplest case
  31. def F(self,vx,vy,y=1):
  32. return 0,0
  33. # calculate the flying trajactory
  34. def fly(self):
  35. self.X=[self.x0]
  36. self.Y=[self.y0]
  37. self.Vx=[self.vx0]
  38. self.Vy=[self.vy0]
  39. self.T=[0]
  40. while not (self.Y[-1]<self.yFinal and self.Vy[-1]<0):
  41. newVx=self.Vx[-1]+self.F(vx=self.Vx[-1],vy=self.Vy[-1],y=self.Y[-1])[0]*self.dt
  42. newVy=self.Vy[-1]-g*self.dt+self.F(self.Vx[-1],self.Vy[-1])[1]*self.dt
  43. self.Vx.append(newVx)
  44. self.Vy.append(newVy)
  45. meanVx=0.5*(self.Vx[-1]+self.Vx[-2])
  46. meanVy=0.5*(self.Vy[-1]+self.Vy[-2])
  47. # meanV=math.sqrt(meanVx**2+meanVy**2) # not used in Cannon0 because there is no air drag
  48. newX=self.X[-1]+meanVx*self.dt
  49. newY=self.Y[-1]+meanVy*self.dt
  50. self.X.append(newX)
  51. self.Y.append(newY)
  52. # fix the final landing coordinate
  53. # r=-self.Y[-2]/self.Y[-1]
  54. self.X[-1]=((self.Y[-2]-self.yFinal)*self.X[-1]+(self.yFinal-self.Y[-1])*self.X[-2])/(self.Y[-2]-self.Y[-1])
  55. self.Y[-1]=self.yFinal
  56. return 0
  57. # get the final distance shells can reach
  58. def distance(self):
  59. return self.X[-1]
  60. def height(self):
  61. return max(self.Y)
  62. # represent trajectory
  63. def plot(self, color):
  64. plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, no air drag"%(self.v0,self.Theta))
  65. return 0
  66. class cannon1(cannon0):
  67. "the second simplest model with no air drag under constant air density, no probability distribution"
  68. # external force other than gravity
  69. def F(self,vx,vy,y=1):
  70. vl=math.sqrt(vx**2+vy**2)
  71. self.Fx=-B2m*vx*vl
  72. self.Fy=-B2m*vy*vl
  73. return self.Fx,self.Fy
  74. def plot(self, color):
  75. plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, uniform air drag"%(self.v0,self.Theta))
  76. return 0
  77. class cannon2(cannon0):
  78. "the model concerning ISOTHERMAL air density variance but no probability distribution"
  79. def F(self,vx,vy,x=1,y=1):
  80. vl=math.sqrt(vx**2+vy**2)
  81. self.Fx=-B2m*vx*vl*math.exp(-y/y_zero)
  82. self.Fy=-B2m*vy*vl*math.exp(-y/y_zero)
  83. return self.Fx,self.Fy
  84. def plot(self, color):
  85. plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, isothermal air drag"%(self.v0,self.Theta))
  86. return 0
  87. class cannon3(cannon0):
  88. "the model concerning ADIABATIC air density variance but no probability distribution"
  89. def F(self,vx,vy,y=1):
  90. vl=math.sqrt(vx**2+vy**2)
  91. self.Fx=-B2m*vx*vl*(1-a*y/T0)**alpha
  92. self.Fy=-B2m*vy*vl*(1-a*y/T0)**alpha
  93. return self.Fx,self.Fy
  94. def plot(self, color):
  95. plt.plot(self.X,self.Y,color,label="$%dm/s$,$%d\degree$, adiabatic air drag"%(self.v0,self.Theta))
  96. return 0
  97. # select the angle casting the largest distance
  98. Distance=[]
  99. for i in range(90):
  100. A=cannon1(600,i)
  101. A.fly()
  102. newDistance=A.distance()
  103. Distance.append(newDistance)
  104. maxDistance=max(Distance)
  105. maxAngle=Distance.index(maxDistance)
  106. print maxAngle
  107. sub1=plt.subplot(221)
  108. A=cannon0(600,45)
  109. A.fly()
  110. sub1.plot(A.X,A.Y,'r-',label='$45\degree$')
  111. A1=cannon0(600,35)
  112. A1.fly()
  113. sub1.plot(A1.X,A1.Y,'r--',label='$35\degree$')
  114. A2=cannon0(600,55)
  115. A2.fly()
  116. sub1.plot(A2.X,A2.Y,'r:',label='$55\degree$')
  117. sub1.set_title('No air drag')
  118. sub1.legend(loc="upper right",frameon=False)
  119. plt.xlabel("Distance [m]")
  120. plt.ylabel("Hieght [m]")
  121. sub2=plt.subplot(222)
  122. B=cannon1(600,40)
  123. B.fly()
  124. sub2.plot(B.X,B.Y,'g-',label='$40\degree$')
  125. B1=cannon1(600,30)
  126. B1.fly()
  127. sub2.plot(B1.X,B1.Y,'g--',label='$30\degree$')
  128. B2=cannon1(600,50)
  129. B2.fly()
  130. sub2.plot(B2.X,B2.Y,'g:',label='$50\degree$')
  131. sub2.set_title('Uniform Air Drag')
  132. sub2.legend(loc="upper right",frameon=False)
  133. plt.xlabel("Distance [m]")
  134. plt.ylabel("Hieght [m]")
  135. sub3=plt.subplot(223)
  136. C=cannon2(600,45)
  137. C.fly()
  138. sub3.plot(C.X,C.Y,'b-',label='$45\degree$')
  139. C1=cannon2(600,35)
  140. C1.fly()
  141. sub3.plot(C1.X,C1.Y,'b--',label='$35\degree$')
  142. C2=cannon2(600,55)
  143. C2.fly()
  144. sub3.plot(C2.X,C2.Y,'b:',label='$55\degree$')
  145. sub3.set_title('Isothermal Air Drag')
  146. sub3.legend(loc="upper right",frameon=False)
  147. plt.xlabel("Distance [m]")
  148. plt.ylabel("Hieght [m]")
  149. sub4=plt.subplot(224)
  150. D=cannon3(600,42)
  151. D.fly()
  152. sub4.plot(D.X,D.Y,'y-',label='$42\degree$')
  153. D1=cannon3(600,32)
  154. D1.fly()
  155. sub4.plot(D1.X,D1.Y,'y--',label='$32\degree$')
  156. D2=cannon3(600,52)
  157. D2.fly()
  158. sub4.plot(D2.X,D2.Y,'y:',label='$52\degree$')
  159. sub4.set_title('Adiabatic Air Drag')
  160. sub4.legend(loc="upper right",frameon=False)
  161. plt.xlabel("Distance [m]")
  162. plt.ylabel("Hieght [m]")
  163. plt.show()
  164. #print A.distance()
  165. #print B.distance()
  166. #print C.distance()
  167. #print D.distance()

●fifure

●For more intuitive observation about the relation between the and the angle,We introduce another list of code

●Code2

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sun Oct 16 20:11:38 2016
  4. @author: 胡胜勇
  5. """
  6. # -*- coding: utf-8 -*-
  7. import math
  8. import numpy as np
  9. from matplotlib import pyplot as plt
  10. from matplotlib import animation
  11. g = 9.8
  12. b2m = 4e-5
  13. r = []
  14. X = []
  15. Y = []
  16. class flight_state:
  17. def __init__(self, _x = 0, _y = 0, _vx = 0, _vy = 0, _t = 0):
  18. self.x = _x
  19. self.y = _y
  20. self.vx = _vx
  21. self.vy = _vy
  22. self.t = _t
  23. class cannon:
  24. def __init__(self, _fs = flight_state(0, 0, 0, 0, 0), _dt = 0.01):
  25. self.cannon_flight_state = []
  26. self.cannon_flight_state.append(_fs)
  27. self.dt = _dt
  28. def next_state(self, current_state):
  29. global g
  30. next_x = current_state.x + current_state.vx * self.dt
  31. next_vx = current_state.vx
  32. next_y = current_state.y + current_state.vy * self.dt
  33. next_vy = current_state.vy - g * self.dt
  34. #print next_x, next_y
  35. return flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)
  36. def shoot(self):
  37. while not(self.cannon_flight_state[-1].y < 0):
  38. self.cannon_flight_state.append(self.next_state(self.cannon_flight_state[-1]))
  39. r = - self.cannon_flight_state[-2].y / self.cannon_flight_state[-1].y
  40. self.cannon_flight_state[-1].x = (self.cannon_flight_state[-2].x + r * self.cannon_flight_state[-1].x) / (r + 1)
  41. self.cannon_flight_state[-1].y = 0
  42. def show_trajectory(self):
  43. x = []
  44. y = []
  45. for fs in self.cannon_flight_state:
  46. x.append(fs.x)
  47. y.append(fs.y)
  48. X.append(x)
  49. Y.append(y)
  50. # if n == 1:
  51. # plt.subplot(111)
  52. # line, = plot(x,y, label = labe)
  53. # xlabel(r'$x(m)$', fontsize=16)
  54. # ylabel(r'$y(m)$', fontsize=16)
  55. # text(40767, 14500, 'initial speed: 700m/s\n' + 'firing angle: 45' + r'$^{\circ}$', color='black')
  56. # title('Trajectory of cannon shell')#
  57. # ax = gca()
  58. # ax.spines['right'].set_color('none')
  59. # ax.spines['top'].set_color('none')
  60. # ax.xaxis.set_ticks_position('bottom')
  61. # ax.yaxis.set_ticks_position('left')
  62. # ax.set_xlim(0, 60000)
  63. # ax.set_ylim(0, 18000)
  64. # #show()
  65. class drag_cannon(cannon):
  66. def next_state(self, current_state):
  67. global g, b2m
  68. v = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)
  69. next_x = current_state.x + current_state.vx * self.dt
  70. next_vx = current_state.vx - b2m * v * current_state.vx * self.dt
  71. next_y = current_state.y + current_state.vy * self.dt
  72. next_vy = current_state.vy - g * self.dt - b2m * v * current_state.vy * self.dt
  73. #print next_x, next_y
  74. return flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)
  75. class adiabatic_drag_cannon(cannon):
  76. def next_state(self, current_state):
  77. global g, b2m
  78. factor = (1 - 6.5e-3 * current_state.y / 288.15) ** 2.5
  79. v = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)
  80. next_x = current_state.x + current_state.vx * self.dt
  81. next_vx = current_state.vx - factor * b2m * v * current_state.vx * self.dt
  82. next_y = current_state.y + current_state.vy * self.dt
  83. next_vy = current_state.vy - g * self.dt - factor * b2m * v * current_state.vy * self.dt
  84. #print next_x, next_y
  85. return flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)
  86. class isothermal_drag_cannon(cannon):
  87. def next_state(self, current_state):
  88. global g, b2m
  89. factor = math.exp(-current_state.y / 1e4)
  90. v = math.sqrt(current_state.vx * current_state.vx + current_state.vy * current_state.vy)
  91. next_x = current_state.x + current_state.vx * self.dt
  92. next_vx = current_state.vx - factor * b2m * v * current_state.vx * self.dt
  93. next_y = current_state.y + current_state.vy * self.dt
  94. next_vy = current_state.vy - g * self.dt - factor * b2m * v * current_state.vy * self.dt
  95. #print next_x, next_y
  96. return flight_state(next_x, next_y, next_vx, next_vy, current_state.t + self.dt)
  97. speed = 700
  98. theta = np.arange(30., 56., 0.1)
  99. v_x = [speed * math.cos(i * math.pi / 180) for i in theta]
  100. v_y = [speed * math.sin(i * math.pi / 180) for i in theta]
  101. def wahaha():
  102. b = []
  103. for i in range(len(theta)):
  104. b.append(adiabatic_drag_cannon(flight_state(0, 0, v_x[i], v_y[i], 0)))
  105. #labe2 = str(theta[i]) + r'$^{\circ}$'
  106. b[i].shoot()
  107. # xx = [b[i].cannon_flight_state[j].x for j in range(len(b[i].cannon_flight_state))]
  108. # yy = [b[i].cannon_flight_state[j].y for j in range(len(b[i].cannon_flight_state))]
  109. # X.append(xx)
  110. # Y.append(yy)
  111. r.append(b[i].cannon_flight_state[-1].x)
  112. b[i].show_trajectory()
  113. #legend(loc='upper left', frameon=False)
  114. wahaha()
  115. p = r.index(max(r))
  116. print theta[p], max(r),type(max(r))
  117. fig = plt.figure()
  118. ax = plt.axes(xlim=(0, 40000), ylim=(0, 18000))
  119. #labe = str(theta[i]) + r'$^{\circ}$'
  120. line, = ax.plot([], [],lw = 2,label = 'adiabatic model' ,color = 'red')
  121. angle_text = ax.text(24167, 14400, '')
  122. maxrange_text = ax.text(24167, 12400, '')
  123. plt.xlabel(r'$x(m)$', fontsize=16)
  124. plt.ylabel(r'$y(m)$', fontsize=16)
  125. plt.title('Trajectory of cannon shell')
  126. plt.legend(loc='upper left', frameon=False)
  127. # initialization function: plot the background of each frame
  128. def init():
  129. line.set_data([], [])
  130. angle_text.set_text('')
  131. maxrange_text.set_text('')
  132. return line, angle_text, maxrange_text
  133. # animation function. This is called sequentially
  134. # note: i is framenumber
  135. def animate(i):
  136. x = X[i]
  137. y = Y[i]
  138. line.set_data(x, y)
  139. pct = float(X[i][-1])/float(max(r))*100
  140. angle_text.set_text('initial speed: 700m/s\n' + 'firing angle: %s' % theta[i] + r'$^{\circ}$' + '\nrange: %f %%' % pct)
  141. if i > p:
  142. maxrange_text.set_text('max range: %s' % max(r))
  143. maxrange_text.set_color(color='red')
  144. return line, angle_text, maxrange_text
  145. fram = len(theta)
  146. # call the animator. blit=True means only re-draw the parts that have changed.
  147. anim=animation.FuncAnimation(fig, animate, init_func=init, frames=fram, interval=30, blit=True)
  148. #anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
  149. plt.show()
  150. #show()

● Result


● Conclusion

Approximately,relations between the and the angle are as follows:

Condition Max Angle Max Range
no drag 50004.950 m
uniform air drag 22070.050 m
isothermal air drag 26621.572 m
adiabatic air drag 24641.195m

Pytion is really interesting as well as powerful,I need to learn more about it.


●Acknowledgments

Thanks to Yue Shaosheng,Wang Shibing

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