使用 scipy.ivp() 在自由落体中实现球弹跳
Implement ball bouncing in free fall using scipy.ivp()
我想使用球的 scipy_ivp() 求解常微分方程,球在 x 方向的初始速度为 1,在 y 方向的初始速度为 0。重力加速度为g = 9.82,当球撞击地面时,它的速度应该改变符号并乘以0.9。但是,使用事件参数,我发现它不能正常工作。这是我的代码和结果:
from scipy.integrate import solve_ivp
def f_derivs_ivp(t, vars, g = 9.82):
dxdt = vars[2]
dydt = vars[3]
dvxdt = 0
dvydt = -g
return dxdt, dydt, dvxdt, dvydt
def bounce(t, y, g = 9.82):
if y[1] <= 0:
y[3] = -0.9*y[3]
#print(y[1])
return y[1]
#bounce.terminal = True
#bounce.direction = -1
vars0 = np.array([0, 10, 1, 0])
sol = solve_ivp(f_derivs_ivp, [0, 7], vars0, max_step=0.01, events = bounce)
plt.plot(sol.y[0], sol.y[1], "ko")
print(sol.y_events)
print(sol.t_events)
使用 scipy.ivp() 以外的其他方法,结果应如下所示:
我做错了什么,events 参数如何工作?另请注意,如果我在弹跳函数中写入 return y[1] - 10
,则不会发生任何变化。例如,如果我在 bounce 函数的 if 语句中写入 y[3] = 10
,它会上下弹跳,但不是它应该的那样。
scipy ODE 求解器不具备具有用户可定义操作的事件操作机制。事件函数只是轨迹上的标量值函数,其零点(如果设置了交叉方向)是事件。这意味着事件函数用于搜索事件(首先检测符号变化,然后使用布伦特方法进行细化)。如果时间步包含事件,它将在每个时间步被调用多次。
内置操作是“注册”(默认)和“终止”。
您必须在反弹时中断积分,并以反射状态作为初始条件重新开始。分别绘制这些片段或使用串联来获得一个大的解决方案数组。
我想使用球的 scipy_ivp() 求解常微分方程,球在 x 方向的初始速度为 1,在 y 方向的初始速度为 0。重力加速度为g = 9.82,当球撞击地面时,它的速度应该改变符号并乘以0.9。但是,使用事件参数,我发现它不能正常工作。这是我的代码和结果:
from scipy.integrate import solve_ivp
def f_derivs_ivp(t, vars, g = 9.82):
dxdt = vars[2]
dydt = vars[3]
dvxdt = 0
dvydt = -g
return dxdt, dydt, dvxdt, dvydt
def bounce(t, y, g = 9.82):
if y[1] <= 0:
y[3] = -0.9*y[3]
#print(y[1])
return y[1]
#bounce.terminal = True
#bounce.direction = -1
vars0 = np.array([0, 10, 1, 0])
sol = solve_ivp(f_derivs_ivp, [0, 7], vars0, max_step=0.01, events = bounce)
plt.plot(sol.y[0], sol.y[1], "ko")
print(sol.y_events)
print(sol.t_events)
使用 scipy.ivp() 以外的其他方法,结果应如下所示:
我做错了什么,events 参数如何工作?另请注意,如果我在弹跳函数中写入 return y[1] - 10
,则不会发生任何变化。例如,如果我在 bounce 函数的 if 语句中写入 y[3] = 10
,它会上下弹跳,但不是它应该的那样。
scipy ODE 求解器不具备具有用户可定义操作的事件操作机制。事件函数只是轨迹上的标量值函数,其零点(如果设置了交叉方向)是事件。这意味着事件函数用于搜索事件(首先检测符号变化,然后使用布伦特方法进行细化)。如果时间步包含事件,它将在每个时间步被调用多次。
内置操作是“注册”(默认)和“终止”。
您必须在反弹时中断积分,并以反射状态作为初始条件重新开始。分别绘制这些片段或使用串联来获得一个大的解决方案数组。