You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用scipy.integrate.solve_bvp求解抛体运动遇网格节点超限问题

scipy.integrate.solve_bvp求解带空气阻力的一维抛体运动时出现“最大节点数超出”错误

我是编程新手,尝试用scipy.integrate.solve_bvp求解受边界条件约束、考虑空气阻力的一维竖直抛体运动:已知发射角90°、落地时间,需要确定发射初速度和落地末速度。

我先通过忽略空气阻力的SUVAT公式得到初速度猜测值,编写了如下代码:

import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt

drag_coef = 0.47 # 高尔夫球平均阻力系数
air_density = 1.293
area = 1.45*10**-3 # 高尔夫球横截面积
mass = 45.9*10**-3 # 高尔夫球质量
g = -9.80665

def function(time, height):
    drag_factor = drag_coef * air_density * area / (2*mass)
    return height[1], (g - drag_factor*height[1]*np.abs(height[1]))

def boundary_conditions(height_0, height_end):
    return height_0[0], height_end[0]

time_scale = 10 # 落地时间
velocity_0_guess = 49 # 初速度猜测值

time = np.linspace(0, time_scale, time_scale*1000+1)
height_0 = np.zeros(len(time))
velocity_0 = velocity_0_guess * np.ones(len(time))
height = np.array((height_0, velocity_0))

res = integrate.solve_bvp(function, boundary_conditions, time, height, max_nodes = time_scale*1000+1)

print(res.y[1][0]) # 计算得到的初速度
print(res.y[1][time_scale*1000]) # 计算得到的落地末速度

print(res)

plt.plot(time, res.y[0], label="S_z")
plt.xlabel("time [s]")
plt.ylabel("displacement [m]")
plt.show()

plt.plot(time, res.y[1], label="V_z")
plt.xlabel("time [s]")
plt.ylabel("velocity [m/s]")
plt.show()

当time_scale=10、velocity_0_guess=49时,运行后返回success=False,错误信息为:

message: 'The maximum number of mesh nodes is exceeded.'

但将time_scale改为5、velocity_0_guess改为24.5时,算法可正常收敛,返回success=True。

我已查阅官方文档、Reddit、Stack Overflow并尝试使用ChatGPT,但问题仍未解决,现寻求技术帮助。


解决方案

1. 初始网格无需过密,让算法自适应调整

solve_bvp是自适应节点的边界值问题求解器,它会根据计算误差自动加密/稀疏网格。初始给过于密集的网格(比如10001个点)不仅没必要,还会让算法在迭代调整时容易触发max_nodes限制。建议初始用稀疏网格,比如10个点:

time = np.linspace(0, time_scale, 10)

2. 优化初始猜测值的分布

初始速度猜测不要用全常数,建议给一个更接近实际运动趋势的分布(比如从初速度猜测值线性过渡到落地时的负速度),帮助算法更快收敛:

# 初始速度从49线性降到-40(模拟落地时向下的速度)
velocity_0 = np.linspace(velocity_0_guess, -40, len(time))

3. 适当增大max_nodes参数

算法在自适应加密节点时可能需要更多节点,可适当调高max_nodes的值,比如设为20000:

res = integrate.solve_bvp(function, boundary_conditions, time, height, max_nodes=20000)

修改后的完整代码

import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt

drag_coef = 0.47
air_density = 1.293
area = 1.45*10**-3
mass = 45.9*10**-3
g = -9.80665

def function(time, height):
    drag_factor = drag_coef * air_density * area / (2*mass)
    return height[1], (g - drag_factor*height[1]*np.abs(height[1]))

def boundary_conditions(height_0, height_end):
    return height_0[0], height_end[0]

time_scale = 10
velocity_0_guess = 49

# 初始稀疏网格
time = np.linspace(0, time_scale, 10)
height_0 = np.zeros(len(time))
# 优化初始速度猜测分布
velocity_0 = np.linspace(velocity_0_guess, -40, len(time))
height = np.array((height_0, velocity_0))

# 增大max_nodes限制
res = integrate.solve_bvp(function, boundary_conditions, time, height, max_nodes=20000)

print("计算得到的初速度:", res.y[1][0])
print("计算得到的落地末速度:", res.y[1][-1])
print(res)

# 用求解结果的节点和值绘图
plt.plot(res.x, res.y[0], label="S_z")
plt.xlabel("time [s]")
plt.ylabel("displacement [m]")
plt.legend()
plt.show()

plt.plot(res.x, res.y[1], label="V_z")
plt.xlabel("time [s]")
plt.ylabel("velocity [m/s]")
plt.legend()
plt.show()

修改后运行,算法应该能正常收敛,返回success=True,同时得到正确的初速度和末速度。


内容的提问来源于stack exchange,提问作者programming noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:55:17