回顾泰勒展开:
泰勒展开(Taylor expansion)是将一个在某点可导的无穷次的函数表示为该点的导数的无穷级数。对于函数 $f(x)$ ,在点 $a$ 处的泰勒展开式为:
$$ f(x) = f(a) + f'(a)(x-a) + \frac{f''(a)}{2!}(x-a)^2 + \frac{f'''(a)}{3!}(x-a)^3 + \cdots + \frac{f^{(n)}(a)}{n!}(x-a)^n + \cdots $$
其中, $f^{(n)}(a)$ 表示函数 $f(x)$ 在点 $a$ 处的第 $n$ 阶导数, $n!$ 表示 $n$ 的阶乘。
如果点 $a = 0$,则泰勒展开式称为麦克劳林展开(Maclaurin expansion),其形式为:
$$ f(x) = f(0) + f'(0)x + \frac{f''(0)}{2!}x^2 + \frac{f'''(0)}{3!}x^3 + \cdots + \frac{f^{(n)}(0)}{n!}x^n + \cdots $$
泰勒展开与有限差分:
一、为什么用中心差分近似二阶导数?离散方程怎么来的?
1. 从物理直观理解导数
二阶导数 ( y''(x) ) 在物理上可以理解为“曲率”,即函数在某点的弯曲程度。想象一条曲线,如果在某点附近弯曲剧烈(曲率大),对应的二阶导数绝对值就大。
2. 如何用离散点近似曲率?
有限差分法的核心思想:用相邻点的函数值,构造导数的近似值。对于二阶导数,我们取当前点 ( x_i ) 及其左右两个邻居点 ( x_{i-1} ) 和 ( x_{i+1} ),构造一个“曲率”的近似公式。
3. 泰勒展开推导二阶导数公式
假设步长为 ( h ),对 ( y(x_{i+1}) ) 和 ( y(x_{i-1}) ) 做泰勒展开:
• 向右展开到二阶:
$$ y(x_{i+1}) = y(x_i) + h y'(x_i) + \frac{h^2}{2} y''(x_i) + O(h^3) $$
• 向左展开到二阶:
$$ y(x_{i-1}) = y(x_i) - h y'(x_i) + \frac{h^2}{2} y''(x_i) + O(h^3) $$
将两式相加,消去一阶导数项 ( y'(x_i) ):
$$ y(x_{i+1}) + y(x_{i-1}) = 2y(x_i) + h^2 y''(x_i) + O(h^4) $$
整理得到二阶导数的中心差分公式:
$$ y''(x_i) \approx \frac{y(x_{i+1}) - 2y(x_i) + y(x_{i-1})}{h^2} $$
这就是离散方程的来源! 将微分方程中的 ( y''(x) ) 替换为此近似,方程就变成了关于离散点 ( y_{i-1}, y_i, y_{i+1} ) 的代数方程。
二、为什么已经有解析解,还要用离散方程求解?
1. 例子中的解析解是“教学工具”
你提到的例子非常简单(( y''=2 )),解析解确实容易求得。但实际工程和科学问题中,微分方程往往复杂得多,例如:
• 非线性方程:如 ( y'' + y^3 = \sin(x) ),解析解可能不存在。
• 变系数方程:如 ( y'' + x y' = 0 ),解析解需要特殊函数。
• 复杂边界条件:如非均匀网格或混合边界条件。
数值方法(如有限差分法)的威力在于:无论方程多复杂,只要你能写出导数近似公式,就能求解。
2. 为什么要用这个简单例子?
• 验证方法正确性:已知解析解的情况下,可以验证数值解是否准确。
• 理解算法流程:通过简单问题,学习如何离散方程、建立线性方程组、编程实现。
• 推广到复杂问题:掌握了简单问题的解法后,才能处理更复杂的方程。
三、实例的完整推导(补充细节)
1. 离散方程的建立
原方程 ( y''=2 ) 在离散点 ( x_i ) 处变为:
$$ \frac{y_{i+1} - 2y_i + y_{i-1}}{h^2} = 2 $$
两边乘以 ( h^2 ) 后得到:
$$ y_{i+1} - 2y_i + y_{i-1} = 2h^2 $$
这就是离散方程,每个内部点 ( i=1,2,3 ) 对应一个方程。
2. 边界条件的处理
• ( y(0)=0 \Rightarrow y_0 = 0 )
• ( y(1)=0 \Rightarrow y_4 = 0 )
边界条件直接代入离散方程,例如:
• 对 ( i=1 ),方程变为 ( y_2 - 2y_1 + y_0 = 2h^2 ),代入 ( y_0=0 ) 后简化为 ( -2y_1 + y_2 = 2h^2 )。
• 同理处理 ( i=3 )。
四、有限差分法的意义
1. 从连续到离散的桥梁
• 连续问题:微分方程在无限多个点 ( x \in [0,1] ) 上定义。
• 离散问题:有限差分法将问题转化为有限个点 ( x_0, x_1, \dots, x_N ) 上的线性方程组。
2. 数值方法的普适性
无论方程是线性、非线性、齐次或非齐次,只要能用差分近似导数,就能求解。例如:
• 热传导方程 ( \frac{\partial u}{\partial t} = \alpha \frac{\partial^2 u}{\partial x^2} )
• 波动方程 ( \frac{\partial^2 u}{\partial t^2} = c^2 \frac{\partial^2 u}{\partial x^2} )
有限差分法常用于数值求解微分方程。以下是一个求解二阶常微分方程边值问题的例子:
问题描述:
求解方程 ( y''(x) = 2 ),边界条件为 ( y(0) = 0 ) 和 ( y(1) = 0 )。
步骤 1:解析解
首先求解析解,便于后续验证数值解:
- 
积分一次:( y'(x) = 2x + C_1 )
 - 
再次积分:( y(x) = x^2 + C_1 x + C_2 )
 - 
代入边界条件:
• ( y(0) = 0 \Rightarrow C_2 = 0 )• ( y(1) = 0 \Rightarrow 1 + C_1 = 0 \Rightarrow C_1 = -1 )
 - 
最终解析解:( y(x) = x^2 - x )
 
步骤 2:网格划分
将区间 ([0, 1]) 划分为 4 等份(步长 ( h = 0.25 )),得到内部节点:
• ( x_1 = 0.25 )
• ( x_2 = 0.5 )
• ( x_3 = 0.75 )
边界点 ( x_0 = 0 ) 和 ( x_4 = 1 ) 的值已知(均为 0)。
步骤 3:离散方程
用中心差分近似二阶导数:
$$ y''(x_i) \approx \frac{y_{i+1} - 2y_i + y_{i-1}}{h^2} $$
代入原方程 ( y'' = 2 ),得到离散方程:
$$ \frac{y_{i+1} - 2y_i + y_{i-1}}{h^2} = 2 \quad (i = 1, 2, 3) $$
整理后:
$$ y_{i+1} - 2y_i + y_{i-1} = 2h^2 $$
其中 ( h = 0.25 ),故 ( 2h^2 = 0.125 )。
步骤 4:建立线性方程组
- 对于 ( i = 1 ):
 
$$ y_2 - 2y_1 + y_0 = 0.125 \quad \text{(因 ( y_0 = 0 \))} \Rightarrow -2y_1 + y_2 = 0.125 $$
- 对于 ( i = 2 ):
 
$$ y_3 - 2y_2 + y_1 = 0.125 $$
- 对于 ( i = 3 ):
 
$$ y_4 - 2y_3 + y_2 = 0.125 \quad \text{(因 ( y_4 = 0 \))} \Rightarrow y_2 - 2y_3 = 0.125 $$
方程组为:
$$ \begin{cases} -2y_1 + y_2 = 0.125 \\ y_1 - 2y_2 + y_3 = 0.125 \\ y_2 - 2y_3 = 0.125 \end{cases} $$
步骤 5:求解线性方程组
写成矩阵形式 ( A\mathbf{y} = \mathbf{b} ):
$$
\begin{bmatrix}
-2 & 1 & 0 \
1 & -2 & 1 \
0 & 1 & -2
\end{bmatrix}
\begin{bmatrix}
y_1 \ y_2 \ y_3
\end{bmatrix}
\begin{bmatrix}
0.125 \ 0.125 \ 0.125
\end{bmatrix}
$$
通过高斯消元法或代入法解得:
$$ y_1 = -0.1875, \quad y_2 = -0.25, \quad y_3 = -0.1875 $$
步骤 6:对比数值解与解析解
在内部节点处的解析解为:
• ( y(0.25) = (0.25)^2 - 0.25 = -0.1875 )
• ( y(0.5) = (0.5)^2 - 0.5 = -0.25 )
• ( y(0.75) = (0.75)^2 - 0.75 = -0.1875 )
结果完全一致,验证了有限差分法的准确性。
结论
通过离散化二阶导数并建立线性方程组,有限差分法成功求解了微分方程。此方法适用于更复杂的方程和边界条件,是工程和科学计算中的重要工具。
# 验证代码(可选)
import numpy as np
A = np.array([[-2, 1, 0],
              [1, -2, 1],
              [0, 1, -2]])
b = np.array([0.125, 0.125, 0.125])
y = np.linalg.solve(A, b)
print("数值解:", y)
# 输出: [-0.1875 -0.25   -0.1875]