实验:不同频率对迭代法收敛速度的影响(Multigrid)

Multigrid方法的核心思想就是不同频率的收敛速度是不同的。

让我们来用实验说明不同的频率对迭代法收敛速度的影响

本实验来自A Multigrid Tutotrial(ppt p.23)

Home Page for "A Multigrid Tutorial," 2nd edition

首先, 我们要求解的问题是

Au=0

离散形式为

-u_{i-1} + 2u_i - u_{i+1} = 0\\ 1\leq i \leq N-1

边界值为

u_0 = u_{N} = 0

(我们用u代表真值,v代表近似解)

我们将Fourier modes作为初始值, 其中N=64, 即

\overrightarrow{v_k}=\left(v_i\right)_k=\sin \left(\frac{i k \pi}{N}\right)
1 \leq i \leq N-1, \quad 1 \leq k \leq N-1

其中i代表component, k代表mode

我们绘制出k=1,3,6的图像

import matplotlib.pyplot as plt
import numpy as np

N = 64
v = np.zeros((N+1,N+1),dtype=np.float64)

for i in range(1,N):
    for k in range(1,N):
        v[i,k] = np.sin(i*k*np.pi/N)
v1 = v[:,1]
v3 = v[:,2]
v6 = v[:,6]

plt.plot(v1, label="k=1")
plt.plot(v3, label="k=3")
plt.plot(v6, label="k=6")
plt.legend()

可见k=1,3,6频率越来越高。

可见k=1,3,6频率越来越高。

然后我们利用weighted Jacobi迭代法进行迭代, 其中omega=2/3

它的迭代公式为:

v_i^{(new)}=(1-\omega)v_{i}^{(old)} + (\omega/ 2) \left(v_{i-1}^{(old)}+v_{i+1}^{(old)} +h^2 f_i \right)

在我们的例子中,omega=2/3, f=0, h=1/N
我们设定初始值为

v_0=\frac{1}{3}\left(\sin \left(\frac{j \pi}{N}\right)+\sin \left(\frac{6 j \pi}{N}\right)+\sin \left(\frac{32 j \pi}{N}\right)\right)
# 首先我们绘制v的误差下降曲线
v0 = np.zeros((N+1),dtype=np.float64)
for j in range(1,N):
    v0[j] = 1/3 * (np.sin(j*np.pi/N) + np.sin(6*j*np.pi/N) + np.sin(32*j*np.pi/N))
v_new = np.zeros((N+1),dtype=np.float64)
v_old = np.zeros((N+1),dtype=np.float64)
num_iters = 100
v_old = v0
error = []
for i in range(num_iters):
    v_new[1:N] = 1./3 * v_old[1:N] + 1./3 * (v_old[2:N+1] + v_old[0:N-1])
    error.append(np.linalg.norm((v_new[1:N] - v_old[1:N]),np.inf) )
    v_old[:] = v_new[:]
plt.plot(error/error[0])

# 然后我们分别绘制v1,v3,v6的误差下降曲线
# 迭代公式完全一样,只有初始值不一样

def weighted_jacobian(v0, label):
    v_new = np.zeros((N+1),dtype=np.float64)
    v_old = np.zeros((N+1),dtype=np.float64)
    num_iters = 100
    v_old = v0
    error = []
    for i in range(num_iters):
        v_new[1:N] = 1./3 * v_old[1:N] + 1./3 * (v_old[2:N+1] + v_old[0:N-1])
        error.append(np.linalg.norm((v_new[1:N] - v_old[1:N]),np.inf) )
        v_old[:] = v_new[:]
    plt.plot(error/error[0], label=label)

# v1
v01 = np.zeros((N+1),dtype=np.float64)
for j in range(1,N):
    v01[j] = 1/3 * (np.sin(j*np.pi/N))
weighted_jacobian(v01,'v1')

# v3
v03 = np.zeros((N+1),dtype=np.float64)
for j in range(1,N):
    v03[j] = 1/3 * (np.sin(3*j*np.pi/N))
weighted_jacobian(v03,'v3')

# v6
v06 = np.zeros((N+1),dtype=np.float64)
for j in range(1,N):
    v06[j] = 1/3 * (np.sin(6*j*np.pi/N))
weighted_jacobian(v06,'v6')

plt.legend()

可见,v1的收敛速度最慢,v3的收敛速度次之,v6的收敛速度最快。

所以,频率越高,收敛速度越快。

完毕。

2 个赞