具有牛顿法的有限差分的近似雅可比方程会引起不稳定性吗?


13

我已经在python 3中实现了向后欧拉求解器(使用numpy)。为了我自己的方便和练习,我还编写了一个小函数来计算梯度的有限差分近似值,这样我就不必总是解析地确定雅可比矩阵(如果可能的话!)。

使用Ascher和Petzold 1998中提供的描述,我编写了此函数来确定给定点x处的梯度:

def jacobian(f,x,d=4):
    '''computes the gradient (Jacobian) at a point for a multivariate function.

    f: function for which the gradient is to be computed
    x: position vector of the point for which the gradient is to be computed
    d: parameter to determine perturbation value eps, where eps = 10^(-d).
        See Ascher und Petzold 1998 p.54'''

    x = x.astype(np.float64,copy=False)
    n = np.size(x)
    t = 1 # Placeholder for the time step
    jac = np.zeros([n,n])
    eps = 10**(-d)
    for j in np.arange(0,n):
        yhat = x.copy()
        ytilde = x.copy()
        yhat[j] = yhat[j]+eps
        ytilde[j] = ytilde[j]-eps
        jac[:,j] = 1/(2*eps)*(f(t,yhat)-f(t,ytilde))
    return jac

我通过对摆采用多元函数并对符号点的雅可比行列式与数字确定的梯度进行比较来测试此函数。我对测试结果感到满意,错误约为1e-10。当我使用近似雅可比矩阵求解摆的ODE时,它也工作得很好。我无法检测到两者之间的任何区别。

然后,我尝试使用以下PDE(一维费舍尔方程)对其进行测试:

tu=x(kxu)+λ(u(Cu))

使用有限差分离散化。

现在,牛顿的方法在第一步就爆炸了:

/home/sfbosch/Fisher-Equation.py:40: RuntimeWarning: overflow encountered in multiply
  du = (k/(h**2))*np.dot(K,u) + lmbda*(u*(C-u))
./newton.py:31: RuntimeWarning: invalid value encountered in subtract
  jac[:,j] = 1/(2*eps)*(f(t,yhut)-f(t,yschlange))
Traceback (most recent call last):
  File "/home/sfbosch/Fisher-Equation.py", line 104, in <module>
    fisher1d(ts,dt,h,L,k,C,lmbda)
  File "/home/sfbosch/Fisher-Equation.py", line 64, in fisher1d
    t,xl = euler.implizit(fisherode,ts,u0,dt)
  File "./euler.py", line 47, in implizit
    yi = nt.newton(g,y,maxiter,tol,Jg)
  File "./newton.py", line 54, in newton
    dx = la.solve(A,b)
  File "/usr/lib64/python3.3/site-packages/scipy/linalg/basic.py", line 73, in solve
    a1, b1 = map(np.asarray_chkfinite,(a,b))
  File "/usr/lib64/python3.3/site-packages/numpy/lib/function_base.py", line 613, in asarray_chkfinite
    "array must not contain infs or NaNs")
ValueError: array must not contain infs or NaNs

对于各种eps值,都会发生这种情况,但是奇怪的是,只有设置了PDE空间步长和时间步长,以使不满足Courant–Friedrichs–Lewy条件。否则它将起作用。(如果与前锋欧拉解决,这是您期望的行为!)

为了完整起见,这是牛顿法的函数:

def newton(f,x0,maxiter=160,tol=1e-4,jac=jacobian):
    '''Newton's Method.

    f: function to be evaluated
    x0: initial value for the iteration
    maxiter: maximum number of iterations (default 160)
    tol: error tolerance (default 1e-4)
    jac: the gradient function (Jacobian) where jac(fun,x)'''

    x = x0
    err = tol + 1
    k = 0
    t = 1 # Placeholder for the time step
    while err > tol and k < maxiter:
        A = jac(f,x)
        b = -f(t,x)
        dx = la.solve(A,b)
        x = x + dx
        k = k + 1
        err = np.linalg.norm(dx)
    if k >= maxiter:
        print("Maxiter reached. Result may be inaccurate.")
        print("k = %d" % k)
    return x

(函数la.solve是scipy.linalg.solve。)

我有信心我的向后Euler实现是正确的,因为我已经使用Jacobian函数对它进行了测试,并获得了稳定的结果。

我可以在调试器中看到newton()在错误发生之前管理35次迭代。我尝试过的每个eps这个数字都相同。

另一个观察结果:当我使用FDA和使用初始条件作为输入的函数计算梯度并在改变ε大小的同时比较两者时,误差随着ε的缩小而增大。我希望它会先变大,然后变小,然后随着epsilon的缩小而变大。因此,在实现Jacobian时出现错误是一个合理的假设,但是如果是这样,它是如此微妙,以至于我看不到它。编辑:我修改了jacobian()以使用正向而不是中央差异,现在我观察到错误的预期发展。但是,newton()仍然无法收敛。在牛顿迭代中观察dx,我发现它只是增长,甚至没有波动:每一步它几乎翻倍(系数1.9),并且系数逐渐变大。

Ascher和Petzold确实提到,雅可比行列式的差分近似并不总是能很好地起作用。具有牛顿法的有限差分的近似雅可比方程会引起不稳定性吗?还是原因在别的地方?我还能如何解决这个问题?


1
“我有信心向后执行Euler,因为我已经使用Jacobian函数对它进行了测试,并获得了稳定的结果。” 请说清楚。您是在说用精确的Jacobian方程运行相同的问题,并且解收敛到PDE的精确解吗?那是重要的信息。
大卫·凯奇森

@DavidKetcheson是的,这就是我的意思。抱歉,如果我的术语不正确或不完整。(我想我也应该说“我会获得稳定和预期的结果。”)
史蒂芬·博世

Answers:


3

最重要的是评论:

使用Ascher and Petzold 1998中提供的描述,我编写了此函数来确定给定点x处的梯度:

查看SUNDIALS的差商近似的代码,以更好地了解实现中应该执行的操作。Ascher和Petzold是入门的好书,但SUNDIALS实际上用于生产工作,因此已经过更好的测试。(此外,SUNDIALS与Petzold从事的DASPK有关。)

Ascher和Petzold确实提到,雅可比行列式的差分近似并不总是能很好地起作用。具有牛顿法的有限差分的近似雅可比方程会引起不稳定性吗?

根据经验,近似的雅可比行列式可以导致牛顿法的收敛失败。我不知道我会把它们描述为“不稳定”。在某些情况下,无法在终止标准中达到所需的错误容忍度。在其他情况下,它可能表现为不稳定。我几乎可以肯定,在Higham的数值方法书中,或者在Hairer和Wanner对W方法的讨论中,对于这种现象会有更定量的结果。

还是原因在别的地方?我还能如何解决这个问题?

这取决于您认为错误可能在哪里。如果您对后向Euler的实现非常有信心,那么我不会从这里开始。经验使我对数值方法的实现抱有偏执的想法,因此,如果是我,我将首先编写一些非常基本的测试问题(几个非刚性和刚性线性问题,具有中心有限差分近似的热方程,这样的事情),我将使用制造好的解决方案的方法来向自己保证,我知道解决方案将是什么,应该与之进行比较。

但是,您已经完成了一些工作:

我有信心我的向后Euler实现是正确的,因为我已经使用Jacobian函数对它进行了测试,并获得了稳定的结果。

那将是我要测试的下一件事:使用解析雅可比行列式。在那之后,您还可能在处于后向欧拉的不稳定区域的偶然机会上查看有限差分Jacobian的极值特征值。将分析雅可比矩阵的极值特征值作为比较的基础可能会给您一些启示。假设所有这些都签出,问题可能出在牛顿解决。


感谢您进行周到的分析(以及SUNDIALS提示和其他来源)。我的教授建议将lambda设置为0,认为PDE的FDA随后变为线性,因此我们希望FDA雅可比行列式等于解析雅可比行列式。当我执行此操作时,它将管理三个时间步,每次newton()每次都达到最大值时,才像以前一样炸毁。
斯蒂芬·博世

他还说,使用近似雅可比矩阵求解PDE是不常见的做法,并建议由于多种自由度而可能会遇到麻烦(尽管提供了解释,尽管只是看了Hairer和Wanner对W方法的讨论,我可以看到它可能并不简单。
斯蒂芬·博世

1
鉴于有关该主题的文献数量众多,例如Knoll和Keyes的著名评论,您的教授的说法有些令人惊讶。我可能应该在回答中引用本文,因为参考书目中的资料也可能有助于诊断您的问题。
Geoff Oxberry 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.