Scipy solve_ivp:在运行期间更改max_step可能吗?

mzsu5hc0  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(152)

我正在求解弹性物体落在弹性表面上的运动方程。通过反复试验,我发现,只有当我选择solve_ivp在0.0001附近时,我才能得到合理的结果。即使是像Radau这样的通常很好的方法,如果没有这个,似乎也不会给予结果。我相信,只有当我的任何物体靠近表面时,这才是必要的,这些距离在积分过程中是已知的。我的问题是:我可以在积分过程中改变max_step的值吗?
感谢您的任何帮助!

vdzxcuhz

vdzxcuhz1#

solve_ivp不能处理动态变化的步长,但是solve_ivp是一个执行ODESolver类型的求解器的 Package 器。使用ODESolver(如Radau),可以更改max_step属性。请参阅scipy文档,尽管很少有关于如何使用基于类的低级求解器的示例。希望下面的示例能有所帮助。
例如,此代码将步长限制为不大于0.1。

from scipy.integrate import solve_ivp, Radau
import numpy as np
def fun(t, y):
    return [1]
        
sol = solve_ivp(fun, [0, 1], [0], method="Radau", max_step=0.1)
print(np.diff(sol.t))

字符串
产量[1.00e-04 1.00e-03 1.00e-02 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 8.89e-02]
下面的代码是等效的:

rad = Radau(fun, t0=0, y0=[0], t_bound=1, max_step=0.1)
step_size = []
while rad.status == "running":
    rad.step()
    step_size.append(rad.step_size)
print(np.array(step_size))


得到[1.00e-04 1.00e-03 1.00e-02 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 8.89e-02],结果相同。
但是现在,我们可以在计算过程中修改ODESolver对象,以在计算过程中更改最大步长。

rad = Radau(fun, t0=0, y0=[0], t_bound=1, max_step=0.1)
step_size = []
while rad.t < 0.5 and rad.status == "running":
    rad.step()
    step_size.append(rad.step_size)
rad.max_step = 0.05  # modify max_step
while rad.status == "running":
    rad.step()
    step_size.append(rad.step_size)
print(np.array(step_size))


产量[1.00e-04 1.00e-03 1.00e-02 1.00e-01 1.00e-01 1.00e-01 1.00e-01 1.00e-01 5.00e-02 5.00e-02 5.00e-02 5.00e-02 5.00e-02 5.00e-02 5.00e-02 5.00e-02 5.00e-02 3.89e-02]

相关问题