导数近似之差分矩阵算法

                     

贡献者: 零穹; addis

  • 缺参考文献
预备知识 有限差分

   本节介绍利用已知函数点近似函数导数的方法,以及相应的计算机处理,它们将给出所谓的差分矩阵。这一内容将使我们能够更快过渡到谱方法。

   我们从这样的问题开始:给定一组点 {xi} 和对应的函数值 u(xi),我们如何使用这些数据近似 u 的导数呢?

1. 差分近似

   最直接的想法就是进行有限差分。考虑点 {xi} 是均匀分布的,并记 xi+1xi=h,则该式对每一 i 都成立。

   记 wiu(xi) 的近似值。那么标准的二阶有限差分近似为

(1)wi=ui+1ui12h. 
所谓的几阶近似公式是指

定义 1 n 阶近似

   称函数 u(x)f(x)(关于 h)的n 阶近似,是指对任一点 xi|f(xi)u(xi)| 是关于 hn 的高阶无穷小,即 limh0|f(xi)u(xi)|hn=01

   让我们证明式 1 的差分公式确实是 u 关于 h 的二阶近似。

   证明:利用该泰勒展开

(2)f(xi+h)=f(xi)+f(xi)h+12f(xi)h2+16f(xi)h3+o(h3),f(xih)=f(xi)f(xi)h+12f(xi)h216f(xi)h3+o(h3). 
因此
(3)f(xi+h)f(xih)=2hf(xi)+13h3f(xi)+o(h3). 
(4)f(xi)=f(xi+h)f(xih)2h13h3f(xi)o(h3)=f(xi+h)f(xih)2h+o(h2). 
因此,式 1 表明
(5)|uiwi|=|uiui+1ui12h|=|o(h2)|. 

   证毕!

2. 差分矩阵

   式 1 告诉我们,已知点 {xi} 处的函数值 {ui},我们可以得到函数 u 在这些点的导数近似 {wi}。但是,这一公式仅仅给我们非端点 i=0,i=NNi 的最大取值)处的导数近似。也就是说,若我们通过已知点逐次近似函数的高阶导数,则能通过式 1 近似函数高阶导数的点数会依次减少端点处的 2 个。

   然而,若认为 u 关于 x 是周期性的,即 u0=uN,ui=uN+i,那么端点处的导数近似公式就为

(6)w0=u1u12h=u1uN12h=wN. 
这样就不会使得能近似高阶导数的点数减少2。在函数的周期性假设下,结合式 1 式 6 就有
(7)(w1wN)=h1(01/21/21/2001/21/21/20)(u1uN). 
注意式 1 表明 ui 的系数矩阵在第 i 行的非零元只有 i+1i1 处的。即对角元的两边,并且符号相反。因此非零元刚好在对角线两边的 “对角线”,左下角和右上角的数值来源于式 6 。明显的,该矩阵是一个 Toeplitz 矩阵。由于它来源于差分公式,因此也被称为差分矩阵

3. 从多项式插值角度看差分公式

   差分公式式 1 还可以从二阶多项式插值法3获得。这一角度使我们能够推广到一般的高阶多项式内插公式。

   该思路是这样的:设函数 un 次多项式,则每一点的导数自然可以通过多项式求导得到。通过多项式插值法可以得到过已知数据点的多项式,接着多项式的导数在已知点的取值就得到数据点处的函数导数的多项式近似值。

   对于二阶多项式近似,函数在点 {xi} 取值 {ui} 的二次多项式(多项式近似通过的 3 个点取 xi1,xi,xi+1)为

(8)pi(x)=ui1(xxi)(xxi+1)/2h2ui(xxi1)(xxi+1)/h2+ui+1(xxi)(xxi1)/2h2=ui1a1(x)+uia0(x)+ui+1a1(x). 
其中
(9)a1(x):=(xxi)(xxi+1)/2h2,a0(x):=(xxi1)(xxi+1)/h2,a1(x):=(xxi)(xxi1)/2h2. 
带入 xi1,xi,xi+1 可知,pi(xi1)=ui1,pixi=ui,p(xi+1)=ui+1。通过求导数 pi(x) 并令 x=xi 取值,可得式 1

2n 阶多项式插值的差分公式

   为方便起见,以偶数阶为例,即可设为 2n 阶多项式插值,其过 2n+1 个点 ui+j,j=n,n+1,,n 只需注意 pi(xij)=uij,ui=u,注意式 8 的规律,因此 2n 阶多项式插值公式为(设 xi+2n=xi

(10)pi(x)=j=nnui+jaj(x), 
其中
(11)aj(x)=(1)nj(xxin)(xxin+1)(xxi+j1)(xxi+j+1)(xxi+n)/((j+n)!(nj)!h2n). 
只要求出 p(xi) 即可得到对应的 n 阶差分方程。(建议读者只需明白具体的思路,无需大量的进行计算,因为计算量会随着 n 的增大而增大,实际上以下的具体实例都是由 Mathematica 辅助计算完成)例如,对 4 阶(n=2),就有
(12)wi=ui212h+2ui+13h2ui13hui+212h. 
对 6 阶(n=3),就有
(13)wi=ui360h+3ui220h+3ui+14h+ui+360h3ui14h3ui+220h. 
因此,若设有 8 个数据点,即 xi 的个数为 8。那么,对应 4 阶和 6 阶多项式插值的差分矩阵分别就是
(14)(023h112h000112h23h23h023h112h000112h112h23h023h112h0000112h23h023h112h0000112h23h023h112h0000112h23h023h112h112h000112h23h023h23h112h000112h23h0,) 
(15)(034h320h160h0160h320h34h34h034h320h160h0160h320h320h34h034h320h160h0160h160h320h34h034h320h160h00160h320h34h034h320h160h160h0160h320h34h034h320h320h160h0160h320h34h034h34h320h160h0160h320h34h0) 

4. Mathematica 实操

   以下通过 u(x)=esinx 产生 100 个数据点,并用 4 阶差分矩阵求数据点的导数,并和实际导数进行比较。

代码 1:Mathematica 利用四阶差分矩阵求导数,数据点由 u(x)=esinx 产生
(*For[i=1,i\[LessEqual]10,
AppendTo[nn,n];*)
n = 100;(*数据点个数*)
A1[n_] := 
  SparseArray[{1 -> 0, 2 -> -2/3, 3 -> 1/12, n - 1 -> -1/12, 
    n -> 2/3}, n];(*第一列*)
	A2[n_] := 
  SparseArray[{1 -> 0, 2 -> 2/3, 3 -> -1/12, n - 1 -> 1/12, 
    n -> -2/3}, n];(*第一行*)
	T4[n_] := ToeplitzMatrix[A1[n], A2[n]];(*四阶差分矩阵*)
	h = 2 Pi/n; xi = Table[N[-Pi + i h], {i, 1, n}]; u = 
 Exp[Sin[xi]];(*通过函数u=Exp[Sin[xi]]产生n个数据点u_i*)
w = T4[n].u/h;(*n个点的导数近似*)
Plot1 = ListPlot[Transpose[{xi, u}], PlotStyle -> Red, 
  PlotLegends -> {"数据点"}];(*数据点的图像*)
Plot2 = ListPlot[Transpose[{xi, w}], PlotStyle -> Blue, 
  PlotLegends -> {"四阶近似导数"}];(*四阶差分算法求得的导数*)
Plot3 = Plot[Cos[x] Exp[Sin[x]], {x, -5, 5}, PlotStyle -> Orange, 
  PlotLegends -> {"真实导数"}];(*实际导数*)
Show[Plot1, Plot2, Plot3, PlotRange -> All]
所得结果如下图

图
图 1:4 阶差分矩阵求导结果

   从图中可看出,模拟结果很好的符合真实值(差分矩阵得到的结果很好的落在了真实导数曲线上)。


1. ^ 在数学分析里,这被记作 |f(xi)u(xi)|=o(hn)
2. ^ 这并不是说这样的处理更合理,而只能让我们能求得 u 满周期性条件时每个点的高阶导数。倘若 u 是非周期的,那么所得的各阶近似就不可信,但是对于没有在求高阶导过程中消掉的 “中间点” 的值却仍然是合理的。
3. ^ n 阶插值法可理解为通过 n+1 个已知点的 n 次多项式近似

                     

© 小时科技 保留一切权利