Python:带有步进控制 ODE 求解器的网格

计算科学 Python 网格
2021-12-01 14:54:59

我有一个通过 ODE 制定的物理问题。现在我喜欢使用 Pythons scipy.integrate 和其中的 complex_ode 对其进行数值求解。我弄清楚了它是如何工作的,但现在我想优化我的代码,我遇到了一个问题:

我需要大量的网格点才能使解决方案收敛。所以我尝试使用步长控制(dop853)设置另一种积分器方法。我不太熟悉该功能,但它也能正常工作,而且比我的方法快得多。这是一个简单的 MWE,它不反映我复杂的 ODE,但设置的结构(复杂值等)是相同的:

from scipy import *
from scipy.integrate import *
from pylab import *

grid = linspace(0, 8, 10e3)
dgrid = (grid[1]-grid[0])*ones(100e3)

def RHS(t, x):
    return -x

y = zeros(len(grid), dtype=complex)
y[0] = 1.0

solver = complex_ode(RHS)
solver.set_initial_value(y[0], grid[0]).set_integrator('dop853')

for t in range(len(grid)):
    solver.integrate(solver.t+dgrid[t])
    y[t] = solver.y[0]

plot(grid, y.real)
show()

但现在的问题是:我现在当然想将时间网格与解决方案联系起来。什么电网现在连接到解决方案?它仍然是我引入的网格(网格)还是步长控件在不同的时间步长计算并且我需要另一个时间数组?

1个回答

在这种情况下,您需要一个具有密集输出的积分器,这意味着它能够在积分器所采取的时间步长之间的任何时间点计算 ODE 的解。dop853(来自 Hairer 和 Wanner 的八阶 Dormand-Prince 积分器)除了自适应时间步长外,还具有此功能。可能发生的情况是积分器在内部跟踪足够的时间步长,以便能够在中间时间插入解决方案——也就是说,积分器具有“内部离散化”。当您使用 调用积分器solver.integrate(solver.t + dt)时,它会调整内部离散化(如有必要),以便solver.t + dt可以从内部离散化中计算的解值对 处的解进行插值。如果您可以阅读原始 Fortran 源,围绕“保存第一个函数评估”的部分可能是说明该策略的相关代码。

因此,要回答您的问题,stepsize 控件通常会在不同的时间步长上进行计算,但您不需要另一个时间数组。只需dop853直接调用 SciPy 接口即可在您想要的时间点计算解,它会处理一切。