SciPyRK45(solve_ivp)函数计算次数是否准确?

Does SciPy RK45 (solve_ivp) count the number of function evaluations accurately?

我想根据 SciPy RK45 衡量我自己的 ODE 积分器的性能。因此,我需要确切地知道 RK45 使用的右侧函数计算的数量。

有谁知道sol.nfev这个数字是否准确,即没有重复?比如RK45拒绝一个步长,重复该步,那么该步的初始评价f(t,x)是不是算了多次?
此外,RK45 使用的 Dormand-Prince RK method 有 7 个阶段,但由于“First Same As Last”属性(最后一个阶段在与下一步的第一阶段)。 sol.nfev 中是否考虑到了这一点?

经过一些实验,我可以确认 RK45 计数准确,即不评估也不计算重复次数。对于任何想知道如何解释数字 sol.nfev 的人:
将 RK45 报告的 RK 步数表示为 num_steps = len(sol.t) - 1,将拒绝的步数表示为 num_rej。然后它成立

sol.nfev = (num_steps + num_rej) * 6 + 2

因为每一步都需要 6 次函数评估,除了第一个需要 7 次。此外,开始时有一个欧拉步来生成初始步长(因此 +2)。感谢@LutzLehmann 指出这一点。

这是一个例子:

class Fun:
def __init__(self):
    self.t = []
    self.x = []

def __call__(self, t, x):
    self.t.append(t)
    self.x.append(x)
    if t <= 1:
        return - x ** 2
    return 10  # discontinuity to provoke step rejection

t0 = 0
t1 = 1.01
x0 = [1]
sol = solve_ivp(Fun(), (t0, t1), x0)

print(sol.nfev)
print(len(f.t))
num_steps = len(sol.t) - 1
print(num_steps)
print(num_steps * 6 + 2)

从输出

56
56
7
44

我们可以看到最终解决方案中有 7 个 RK 步骤 sol 但由于函数的不连续性,也有 2 个被拒绝的步骤 (44 + 2 * 6 = 56)。