使用 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 求解器不具备具有用户可定义操作的事件操作机制。事件函数只是轨迹上的标量值函数,其零点(如果设置了交叉方向)是事件。这意味着事件函数用于搜索事件(首先检测符号变化,然后使用布伦特方法进行细化)。如果时间步包含事件,它将在每个时间步被调用多次。

内置操作是“注册”(默认)和“终止”。

您必须在反弹时中断积分,并以反射状态作为初始条件重新开始。分别绘制这些片段或使用串联来获得一个大的解决方案数组。