scipy odeint:保守的 ode 方程之和在求解时不会保持为零 - 这是正常的吗?

计算科学 Python scipy
2021-12-04 11:26:45

假设我们有以下等式:

dy1/dt = f(y1, t)      [1]
dy2/dt = g(y2, t)      [2]

这些方程是这样的,它们是“保守的”,即以下条件应该成立:

dy1/dt + dy2/dt = 0    [3]

使用scipy.odeint,我发现对于简单的 ODE 系统,我可以很好地整合这样的保守方程。

但是,对于较大的,我得到以下问题。

假设这是我的导数函数:

def deriv_function(y0s, t):
    ...body defines equations 1, and 2...

    print np.sum(ode)
    return ode

注意打印语句。

我使用scipy.odeint如下deriv_function

odeint(deriv_fun, y0s, [0, 0.5])

由于 print 语句,打印出以下内容:

-1.38555833473e-13 <--- note, close to zero
-0.00679107743937
-0.0067907211796
-0.0135814423985
-0.0135810861584
-0.416522145214
-0.416523165887
-0.818209018574
-0.818211056221
-1.21864678558
-1.21864881584
-2.86735888212
-2.8673729885
-2.46855840934
-2.46856658088
-3.70632102566
-3.70631206163
-4.93200749506
-4.93200691488
-6.14577326158
-6.14577268283
-8.53799987128
-8.53799713959
-10.8839304356
-10.8839320212
-13.1845005689
-13.1845021725
-15.4406122011
-15.4406123927
-17.6531469917
-17.653147185
-24.6238415795
-24.6238498033
-31.1628867985
-31.1628947266
-37.2974784594
-37.2974547092
-35.463527103
-35.4635192949
-39.5777426955
-39.5777472677
-43.5137135424
-43.5137108017
-47.2791485087
-47.2791483993
-50.881424906
-50.8814244751
-54.3275507164
-54.3275502654    <--- note, not close to zero

对于较小的方程组(不相同),打印出以下内容:

-1.13686837722e-13
0.0
0.0
0.0
-1.13686837722e-13
1.13686837722e-13
0.0
0.0
0.0
0.0
0.0
0.0
0.0
-1.13686837722e-13
0.0
0.0
0.0
1.13686837722e-13
0.0
0.0
0.0
0.0
-1.13686837722e-13
0.0
0.0
-1.13686837722e-13
0.0
0.0
0.0
0.0
0.0
0.0
-1.13686837722e-13
0.0
0.0
5.68434188608e-14
-5.68434188608e-14
-5.68434188608e-14
0.0

我花了很多时间试图弄清楚这个问题是否与我定义方程式的方式有关,我现在相当确定情况并非如此。为了证实这一点,我想问一下:非保守方程组是否有可能首先打印一个接近于零的 ode 和,但随后打印不接近于零的值?

思考这个问题的另一种方式:在更大的方程组中,ode sum initial 在增加之前打印出近似为零。这个问题的发生在求解器的内部会发生什么?

2个回答

一般来说,数值方法不守恒在连续系统中可能守恒的量。离散系统通常是非保守的。较小的时间步长(相当于较小的误差容限)应该会有所帮助,但如果您有一个必须精确守恒的量,则必须使用一种旨在保存所需量的方法。辛积分器可能是这种情况下最广为人知和使用的例子。

例如,考虑一个简单的质量弹簧振荡器:

dxdt=v
dvdt=kmx

总能量E=12(mv2+kx2)是守恒的,因为

dEdt=mvdvdt+kxdxdt=kvx+kxv=0

但是,如果您使用 Runge-Kutta 类型方法集成此系统,则不会保存能量。使用 MATLAB 的ode45积分器进行的快速测试给出了以下能量图,它不像您的情况那样引人注目,但显示出能量的明显衰减:
能量衰减

这是一个带有哈密顿量的哈密顿系统H(x,v)=E(x,v)=12(mv2+kx2)并且将是应用辛积分器的一个很好的候选者,它可以保持总能量。

有两种可能:

  1. 你有一个错误。
  2. 您会看到离散化错误的累积。

如果没有更多细节,我们不可能告诉您模拟中实际发生的情况。