检查给定的微分方程是否是刚性的

计算科学 刚性
2021-12-22 18:01:37

我必须确定以下微分方程是否僵硬:

y(t)=201y200y2+2,t[0,20].

可悲的是,我没有任何解决方案。所以,我所做的是实现显式和隐式欧拉,并查看各种步长的结果。

from numpy import *
from scipy import optimize

rhs = lambda z: array([ z[1], -201*z[1] - 200*z[0]**2 + 2 ])

def explicit_euler(y0,t0,tEnd,N):
    y = zeros((2,N+1))
    t = zeros(N+1)

    y[:,0] = y0
    t[0] = t0

    h = float(tEnd-t0)/N

    for k in xrange(N):
        y[:,k+1] = y[:,k] + h*rhs(y[:,k])
        t[k+1] = t[k] + h

    return y, t


def implicit_euler(y0,t0,tEnd,N):
    y = zeros((2,N+1))
    t = zeros(N+1)

    y[:,0] = y0
    t[0] = t0

    h = float(tEnd-t0)/N

    for k in xrange(N):
        F = lambda a: -a + y[:,k] + h*rhs(0.5*(y[:,k]+a))
        startvalue = y[:,k] + h*rhs(y[:,k])
        y[:,k+1] = optimize.fsolve(F, startvalue)
        t[k+1] = t[k] + h

    return y, t


t0 = 0.
tEnd = 20.
y0 = array([1,0])
N = 100


ye, te = explicit_euler(y0,t0,tEnd,N)
print ye[0]
yi, ti= implicit_euler(y0,t0,tEnd,N)
print yi[0]

对于N=100步,如上面的代码,结果输出

is:

[  1.00000000e+000   1.00000000e+000  -6.92000000e+000   2.95624000e+002
  -1.19471120e+004  -2.31180176e+005  -1.13350513e+009  -3.84263356e+011
  ...
               nan               nan               nan               nan
               nan               nan               nan               nan
               nan]
[ 1.          0.84122674  0.7135129   0.63248909  0.55673461  0.50831417
  0.45792912  0.42604819  0.39009643  0.36765118  0.34076357  0.32415616
  ....
  0.10461852  0.10443526  0.10425726  0.1040885   0.10392479  0.10376937
  0.10361875  0.10347557  0.10333695  0.10320504  0.10307743]

所以我们看到,显式欧拉发散了。(所有的nans)但隐含的没有。通过设置,我们还看到两者都得到相同的结果。[当步长足够小时,我们期望刚性微分方程可以使用显式方法求解]N=100000

但这似乎有点容易。你说这样好吗?你会怎么做?

2个回答

刚性方程没有可靠的定义。我最喜欢 Shampine 的工作定义:如果显式方法的计算效率低于隐式方法,则微分方程是僵硬的。关于特征值的所有其他定义都是故意模糊的,因为它们无法捕捉到“重要的特征值”取决于方法的速度这一事实,因此在某些情况下,特征值看起来“僵硬”的东西是你不知道的t 实际上想被视为“僵硬”,因为显式方法可能会走得很好,以至于它们工作得更好。

请注意,这与您正在使用的程序有很大关系。由于您使用 NumPy 循环,这将是一个非常低效的实现。由于您的实现效率低下,因此内核fsolve有效这一事实可能意味着,对于这种比较,隐式方法由于实现而具有较少的劣势,因此您的刚度阈值将低于您使用高度优化的代码。

我鼓励您采用这个工作定义,并使用刚度和特征值估计的概念作为选择方法的指南,但要仔细检查与基准的直觉。

术语“僵硬”有很多定义,但通常理解的定义是“有两个或多个时间尺度与被建模的过程相关联,并且这些时间尺度非常不同”。

在您的情况下,您有一个 ODE,其解决方案是单个函数因此,它只有一个时间尺度,因此人们不会认为 ODE 是僵硬的。y(t)