二阶微分方程的有限差分法(Python)
考虑如下的二阶微分方程
-U''(x) = f(x) = 9sin(3x)-6x, x\in(0, \pi)
给定如下的边值条件
U(0)=0, U(\pi)=\pi^3
我们可以得到解析解为:
U(x)=sin(3x)+x^3
在区间
[0, \pi]
离散,可以得到如下的二阶中心差分格式
-\frac{U_{i-1}-2U_i + U_{i+1}}{h^2} = f_i
将上式写成矩阵的形式,
AU=F
, 其中
A
为三对角占优矩阵,因此这个
AU=F
这个方程组可以通过追赶法求解。
追赶法英文文献中常被称为 Thomas' algorithm,详见维基百科
Tridiagonal matrix algor
首先引入 numpy 和 matplotlib
import numpy as np
import matplotlib.pyplot as plt
用 Python 中的 numpy 实现 Thomas 算法
def Thomas(La, Mb, Uc, b):
Arguments:
La -- [lower item for tri-diagonal matrix]
Mb -- [mian item for tri-diagonal matrix]
Uc -- [upper item for tri-diagonal matrix]
b -- [AX = b, where A is the tri-diagonal matrix]
n = len(Mb)
Uc[0] = Uc[0] / Mb[0]
for i in range(1, n-1):
Uc[i] = Uc[i] / (Mb[i] - La[i - 1] * Uc[i - 1])
b[0] = b[0] / Mb[0]
for i in range(1, n):
b[i] = (b[i] - La[i-1]*b[i-1]) / (Mb[i] - La[i-1] * Uc[i-1])
ls = list(range(n-1))[::-1]
# print(b)
for i in ls:
b[i] = b[i] - Uc[i]*b[i+1]
return b
而后,利用有限差分法进行数值计算并且通过二范数误差和最大范数误差,来对有限差分法的数值精度进行刻画
def Exact(X):
return np.sin(3*X) + np.power(X,3)
def f(X):
return 9.0*np.sin(3.*X) - 6.*(X)
def FDMode(n):
Xa = 0
Xb = np.pi
U0 = 0
Upi = np.pi**3
h = np.array((Xb-Xa)/n)
h2 = h**2
N = n+1 # all point
U_numerical = np.zeros((N,1))
U_numerical[0] = U0
U_numerical[-1] = Upi
X = np.linspace(Xa,Xb,N)
La = np.zeros((n-2,))
Mb = np.zeros((n-1,))
Uc = np.zeros((n-2,))
La[:] = -1.0/h2
Mb[:] = 2.0/h2
Uc[:] = -1.0/h2
b = f(X)[1:-1]
b[0] = b[0] + U0
b[-1] = b[-1] + Upi/h2
res = Thomas(La,Mb,Uc,b)
exact = Exact(X)
# errors
norm_max = np.max(np.abs(exact[1:-1]-res))
norm_2 = np.sqrt(np.sum(np.abs(exact[1:-1]-res)**2))
# print(n,norm_max, norm_2)
return norm_max, norm_2
对不同的网格剖分数(即不同的时间步长)下的两种误差进行计算,并且绘制图像对比
nlist = list(range(10,101,10))
NN = len(nlist)
Norm2 = np.zeros((NN,))
NormMax = np.zeros((NN,))
for i in range(NN):
norm_max, norm_2 = FDMode(nlist[i])
Norm2[i] = norm_2
NormMax[i] = norm_max
print("norm_2",Norm2)
print("norm_max",NormMax)
fig, ax = plt.subplots()