如何在重力,浮力和空气阻力的作用下绘制弹丸的运动?

时间:2019-01-02 02:06:16

标签: python numpy matplotlib physics

我正在尝试绘制在重力,浮力和阻力作用下的质点的抛物线运动。基本上,我想显示浮力和阻力对飞行距离,飞行时间和速度变化对绘图的影响。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!--script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script-->

在此之后,我无法弄清楚如何在这种力下绘制弹丸运动。换句话说,我正在尝试比较三种情况下质量的弹丸运动

  1. 仅在重力作用下的质量
  2. 在重力和空气阻力作用下的质量
  3. 在重力,空气阻力和浮力作用下的质量

2 个答案:

答案 0 :(得分:2)

您必须根据给定时间的力总和来计算每个位置。为此,最好从随时计算净力开始,然后使用它来计算加速度,速度和位置。对于以下计算,假定浮力和重力是恒定的(实际上并不正确,但在这种情况下其可变性的影响可忽略不计),还假定初始位置为(0,0)可以简单地更改为任何初始位置。

F_x = tau_x 
F_y = tau_y + bouyancy + gravity

其中tau_xtau_y分别是在xy方向上的拖曳力。然后由

给出速度v_xv_y
v_x = v_x + (F_x / (2 * m)) * dt
v_y = v_y + (F_y / (2 * m)) * dt

因此,x在任何时间y的{​​{1}}和r_x位置r_y都是

的总和
t

在两种情况下,对于某些r_x = r_x + v_x * dt r_y = r_y + v_y * dt ,必须从0t进行评估,如果dt是求和的步数,则其中dt * n = t。 / p>

n

整个计算实际上可以分两行完成

r_x = r_x + V_i * np.cos(theta) * dt + (F_x / (2 * m)) * dt**2
r_y = r_y + V_i * np.sin(theta) * dt + (F_y / (2 * m)) * dt**2

除了r_x = r_x + V_i * np.cos(theta) * dt + (tau_x / (2 * m)) * dt**2 r_y = r_y + V_i * np.sin(theta) * dt + ((tau_y + bouyancy + gravity) / (2 * m)) * dt**2 v_x需要在每个时间步进行更新。要对此进行循环并计算一段时间内的v_yx位置,您可以简单地遵循以下示例(已编辑)。

以下代码包含一些纠正措施,以防止出现y负位置,因为y的给定值适用于表面或火星,我认为这是适当的-当您命中零g并尝试继续时您可能会像我们物理学家所说的那样快速进行计划外的拆卸。

修改

为响应已编辑的问题,对以下示例进行了修改,以绘制请求的所有三种情况-重力,重力加阻力以及重力加阻力和浮力。情节设置代码也已添加

完整示例(已编辑)

y

请注意,这会保留并返回变量import numpy as np import matplotlib.pyplot as plt def projectile(V_initial, theta, bouyancy=True, drag=True): g = 9.81 m = 1 C = 0.47 r = 0.5 S = np.pi*pow(r, 2) ro_mars = 0.0175 time = np.linspace(0, 100, 10000) tof = 0.0 dt = time[1] - time[0] bouy = ro_mars*g*(4/3*np.pi*pow(r, 3)) gravity = -g * m V_ix = V_initial * np.cos(theta) V_iy = V_initial * np.sin(theta) v_x = V_ix v_y = V_iy r_x = 0.0 r_y = 0.0 r_xs = list() r_ys = list() r_xs.append(r_x) r_ys.append(r_y) # This gets a bit 'hand-wavy' but as dt -> 0 it approaches the analytical solution. # Just make sure you use sufficiently small dt (dt is change in time between steps) for t in time: F_x = 0.0 F_y = 0.0 if (bouyancy == True): F_y = F_y + bouy if (drag == True): F_y = F_y - 0.5*C*S*ro_mars*pow(v_y, 2) F_x = F_x - 0.5*C*S*ro_mars*pow(v_x, 2) * np.sign(v_y) F_y = F_y + gravity r_x = r_x + v_x * dt + (F_x / (2 * m)) * dt**2 r_y = r_y + v_y * dt + (F_y / (2 * m)) * dt**2 v_x = v_x + (F_x / m) * dt v_y = v_y + (F_y / m) * dt if (r_y >= 0.0): r_xs.append(r_x) r_ys.append(r_y) else: tof = t r_xs.append(r_x) r_ys.append(r_y) break return r_xs, r_ys, tof v = 30 theta = np.pi/4 fig = plt.figure(figsize=(8,4), dpi=300) r_xs, r_ys, tof = projectile(v, theta, True, True) plt.plot(r_xs, r_ys, 'g:', label="Gravity, Buoyancy, and Drag") r_xs, r_ys, tof = projectile(v, theta, False, True) plt.plot(r_xs, r_ys, 'b:', label="Gravity and Drag") r_xs, r_ys, tof = projectile(v, theta, False, False) plt.plot(r_xs, r_ys, 'k:', label="Gravity") plt.title("Trajectory", fontsize=14) plt.xlabel("Displacement in x-direction (m)") plt.ylabel("Displacement in y-direction (m)") plt.ylim(bottom=0.0) plt.legend() plt.show() 中的运行时间。

答案 1 :(得分:0)

使用向量符号和<div class="title-button"></div> If(document.querySelector(".title-button").className == "hidden"){ //Your statement goes here }

odeint

请注意,我已纠正了拖动力以使用实际(而非初始)速度,不知道这是您的错误还是故意的。

也请查看import numpy as np from scipy.integrate import odeint import scipy.constants as SPC import matplotlib.pyplot as plt V_initial = 30 # m/s theta = np.pi/6 # 30 g = 3.711 m = 1 # I assume this is your mass C = 0.47 r = 0.5 ro_mars = 0.0175 t_flight = 2*(V_initial*np.sin(theta)/g) t = np.linspace(0, t_flight, 200) pos0 = [0, 0] v0 = [np.cos(theta) * V_initial, np.sin(theta) * V_initial] def f(vector, t, C, r, ro_mars, apply_bouyancy=True, apply_resistance=True): x, y, x_prime, y_prime = vector # volume and surface V = np.pi * 4/3 * r**3 S = np.pi*pow(r, 2) # net weight bouyancy if apply_bouyancy: Fb = (ro_mars * V - m) * g *np.array([0,1]) else: Fb = -m * g * np.array([0,1]) # velocity vector v = np.array([x_prime, y_prime]) # drag force - corrected to be updated based on current velocity # Ft = -0.5*C*S*ro_mars*pow(V_initial, 2) if apply_resistance: Ft = -0.5*C*S*ro_mars* v *np.linalg.norm(v) else: Ft = np.array([0, 0]) # resulting acceleration x_prime2, y_prime2 = (Fb + Ft) / m return x_prime, y_prime, x_prime2, y_prime2 sol = odeint(f, pos0 + v0 , t, args=(C, r, ro_mars)) plt.plot(sol[:,0], sol[:, 1], 'g', label='tray') plt.legend(loc='best') plt.xlabel('x') plt.ylabel('y') plt.grid() plt.show() 的文档,以更好地了解如何将二阶ODE(如问题中的一个)转换为一阶向量ODE。

要消除空气阻力或弹性,请将odeintapply_bouyancy设置为apply_resistanceTrue并将其添加到False