五点差分格式求解边值问题


文章目录

1 数学理论
1.1 问题
1.2 问题解答

2 程序

3 结果分析说明
3.1 初步验证迭代程序的正确性
3.2 解答题目内容
3.2.1 比较三种迭代法的次数
3.2.2 差分解与精确解的精度
4 遇到的问题与解决

附录




1 数学理论.

1.1 问题

在这里插入图片描述

1.2 问题解答

在这里插入图片描述

2 程序.

见附录

3 结果分析说明

3.1 初步验证迭代程序的正确性

  • 取 h = k = 1/2, 1/4, 1/8,验证各个迭代法是否随着区间划分的增多,然后近似解与精确解的误差减小,结果如下:
    在这里插入图片描述
    在这里插入图片描述
  • 结果分析:由上面的图表可以知道,随着分点数的增加,误差是减小的,也就是说所给程序,初步验证是可以和理论相结合的。

3.2 解答题目内容.

3.2.1 比较三种迭代法的次数
  • h= k= 1/ 64
    在这里插入图片描述
    结果分析:在 h= k= 1/64 时,Jacobi 方法的迭代次数是 7811 次,SOR 方法的迭代次数是 192 次,Gauss-Seidel 方法的迭代次数是 4211 次。由理论上可以知道 Gauss-Seidel 方法的迭代速度为 Jacobi 方法迭代次数的两倍,而选择恰当的松弛因子时,SOR 可以大大的加快迭代速度。从实验结果来看,无疑是证明了理论的正确性。
  • h= k= 1/128
    在这里插入图片描述
    结果分析:在 h= k= 1/64 时,Jacobi 方法的迭代次数是 28951 次,SOR 方法的迭代次数是 383 次,Gauss-Seidel 方法的迭代次数是 15660 次。由理论上可以知道 Gauss-Seidel 方法的迭代速度为 Jacobi 方法迭代次数的两倍,而选择恰当的松弛因子时,SOR 可以大大的加快迭代速度。从实验结果来看,无疑是证明了理论的正确性。
  • 两种步长的比较
    从比较结果来看,随着步长的减小,迭代次数明显增加。
    在这里插入图片描述
3.2.2 差分解与精确解的精度
  1. h= k= 1/64
    这里求出了误差矩阵的分布
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    结果分析:这里由误差矩阵的分布来看,各个迭代方法的误差矩阵的分布是相似的,很难比较出结果。为了简单起见,求出各个误差矩阵的最大值,利用最大值来比较,整理出结果如下图。可以知道max误差最大的是 Jacobi 迭代法 ,为 0.9374。其次是 Gauss-Seidel,为 0.8974。最后max误差最小为 SOR 法,为 0.8588。从实验结果来看,这也验证了理论上,当选取合适的迭代松弛因子时,SOR 的精度较高,而 Gauss-Seidel 次之,Jacobi 最小。
    在这里插入图片描述
  2. h= k= 1/128
    这里求出了误差矩阵的分布
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    结果分析:这里由误差矩阵的分布来看,各个迭代方法的误差矩阵的分布是相似的,很难比较出结果。为了简单起见,求出各个误差矩阵的最大值,利用最大值来比较,整理出结果如下图。可以知道max误差最大的是 Jacobi 迭代法 ,为 0.7517。其次是 Gauss-Seidel,为 0.5887。最后max误差最小为 SOR 法,为 0.4303。从实验结果来看,这也验证了理论上,当选取合适的迭代松弛因子时,SOR 的精度较高,而 Gauss-Seidel 次之,Jacobi 最小。
    在这里插入图片描述
  3. 两种步长的比较
    从下图结果可以知道,当减小步长时,各个迭代法的最大误差也是减小的
    在这里插入图片描述

4 遇到的问题与解决.

  • 对于公式的不理解,通过反复向老师请教,得到了相对正确的理解,非常感谢老师的指导和帮助。
  • 对数据和分析不够,比如对误差矩阵的分布,如果能够动态的展示不同迭代方法的误差分布,以及不同步长的误差分布,那么可以有效的利用误差分布来进行问题的分析,在本文中仅仅利用最大误差说服力是不够的
  • 对下面题目的理解
    在这里插入图片描述
    第一行是一个差分方程,左边是一个拉普拉斯算子,右边可以称之为右端函数。当右端函数为零,即 Δu = 0 时,那么,这个差分方程称为 拉普拉斯方程;当右端函数不为零时,这个差分方程称为 泊松方程。
    在本题中注意一点,标准的拉普拉斯方程是 -Δu = 0 ,本题中 泊松方程对应的标准方程应该为 Δu = -f。我对问题的解答时,也就是进行数学迭代公式的演算时,并未将拉普拉斯方程化为标准型来计算。
    这里有点儿绕哈,相差一个负号,会导致不同的结果。不过在程序运行时,通过观察变量的结果可以很容易看出自己是否符号搞反了。
  • 高斯塞德尔迭代法这里比较难理解
    在这里插入图片描述
    因为 高斯塞德尔法提前生成了点,所以下面这样写程序是正确的
    在这里插入图片描述

附录.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
1,main 函数
% %% 主函数
clc;
clear;
 
matrixH = [1/64];
errorArray=[]; % 和精确解比较,观察随着 h 的减小,error 是否减小
for iterator = 1: length(matrixH)
    h = matrixH(iterator);
    %h = 1/ 64;  % 步长
    % h = 1/ 128;
 
    n = 1/ h;  % 矩阵最大维度
 
    e = 0.0001; % 精度,重合到小数点后四位
 
    maxIterator = 100000;
 
    right_value = Right(h, n, e);   % 精确解
 
 
   
    [ja_value, timesJacobi,errorJacobi, errorRightJacobi] = Jacobi(h, n, e,right_value, maxIterator);    % 雅可比
    [sor_value, timesSOR,errorSOR, errorRightSOR] = SOR(h, n, e,right_value,maxIterator);  % 逐次超松弛
    [gauss_value, timesGauss,errorGauss, errorRightGauss] = GaussSider(h, n, e,right_value,maxIterator);     % 高斯赛德尔
    errorArrayGauss(iterator) = errorGauss;
    errorArrayJacobi(iterator) = errorJacobi;
    errorArraySOR(iterator) = errorSOR;
end
 
%% 画图
plotResult(1, 'Gauss', matrixH, errorArrayGauss, errorRightGauss);
 
plotResult(2, 'Jacobi',matrixH, errorArrayJacobi, errorRightJacobi);
 
plotResult(3, 'SOR', matrixH, errorArraySOR, errorRightSOR);
 
figure(4)
times = [timesJacobi, timesSOR, timesGauss];
bar(times);
 
xlabel('名称');
ylabel('迭代总次数');
title('Jacobi, SOR, Gauss 的迭代次数对比');
set(gca, 'XTickLabel', {'Jacobi', 'SOR', 'Gauss'});
 
for i= 1: length(times)
    str = sprintf('%d', times(i));
    text(i-0.1, times(i)+3,str);
end
 
 
 
 
 
 
 

2,绘图函数
%% 绘图函数
function result = plotResult(figureNum, name, matrixH, errorArray, errorRight)
    figure(figureNum);
    subplot(2,2,1);
    plot(fliplr(matrixH), errorArray);
    xlabel('h');
    ylabel('errorNorm_2');
    title(strcat(name, ': 随着分点数的增加,即 h 的减小,error矩阵的二范数减小'));
    box off;
 
    subplot(2,2,2);
    x = 0: matrixH(length(matrixH)): 1;
    y = 0: matrixH(length(matrixH)): 1;
    plotArray = errorRight.^2;
    %plotArrayGauss = sqrt(plotArrayGauss);
    surf(x, y, plotArray(:,:));
    xlabel('x');
    ylabel('y');
    zlabel('z');
    title(strcat(name, ': 精确解和近似解相减后得到的平方'));
    box off;
end

3,高斯函数
%% 高斯赛德尔函数
function [r, times, error,errorRight] = GaussSider(h, n, e,right_value,maxIterator)
    u = zeros(n+1, n+1);  % 初边值条件简写
   
    old = zeros(n+1, n+1);
   
    x = zeros(n);
    y = zeros(n);
   
    for i = 2: n
        x(i) = (i-1)*h;
    end
   
    for j = 2: n
            y(j) = (j-1)*h;
    end
   
    k = 1;
    while(true)
        for i = 2:n
            for j = 2:n
                a1 = u(i+1, j);
                a2 = u(i-1, j);
                a3 = u(i, j+1);
                a4 = u(i, j-1);
               
                u(i, j) = (1/4)*(-h*h*f_u(x(i), y(j)) + a1 + a2 + a3 + a4);
            end
        end
        errorArray(k) = norm((u-old),2);
        if(errorArray(k)<e||k>maxIterator)
            break;
        else
            old = u;
            k = k+1;
        end
       
    end
   
   
   
   
    errorRight = u-right_value;
    error = norm(errorRight, 2);
    times = k;
    r = u;
   
 
   
end

4,雅可比函数
%% 雅可比函数,很难,要实现与节点编排顺序无关
function [r,times,error, errorRight] = Jacobi(h, n, e,right_value,maxIterator)
    u = zeros(n+1, n+1);  % 初边值条件简写
   
    old = zeros(n+1, n+1);  % 上一次迭代情况
    k = 1;
    x = zeros(n);
    y = zeros(n);
   
    for i = 2: n
        x(i) = (i-1)*h;
        for j = 2: n
            y(j) = (j-1)*h;
        end
    end
   
    while(true)
        for i = 2:n
            for j = 2:n
                a1 = old(i+1, j);
                a2 = old(i-1, j);
                a3 = old(i, j+1);
                a4 = old(i, j-1);
                u(i, j) = (1/4)*(-h*h*f_u(x(i), y(j)) + a1 + a2 + a3 + a4);  
               
            end
        end
       
        errorArray(k) = norm((u-old),2);
        if(errorArray(k)<e || k >maxIterator)
            break;
        else
            old = u;
            k = k+1;
        end
       
    end
   
    errorRight = u-right_value;
    error = norm(errorRight, 2);
    times = k;
    r = u;
 
   
end

5,SOR 函数
%% 雅可比函数,很难,要实现与节点编排顺序无关
function [r,times,error, errorRight] = Jacobi(h, n, e,right_value,maxIterator)
    u = zeros(n+1, n+1);  % 初边值条件简写
   
    old = zeros(n+1, n+1);  % 上一次迭代情况
    k = 1;
    x = zeros(n);
    y = zeros(n);
   
    for i = 2: n
        x(i) = (i-1)*h;
        for j = 2: n
            y(j) = (j-1)*h;
        end
    end
   
    while(true)
        for i = 2:n
            for j = 2:n
                a1 = old(i+1, j);
                a2 = old(i-1, j);
                a3 = old(i, j+1);
                a4 = old(i, j-1);
                u(i, j) = (1/4)*(-h*h*f_u(x(i), y(j)) + a1 + a2 + a3 + a4);  
               
            end
        end
       
        errorArray(k) = norm((u-old),2);
        if(errorArray(k)<e || k >maxIterator)
            break;
        else
            old = u;
            k = k+1;
        end
       
    end
   
    errorRight = u-right_value;
    error = norm(errorRight, 2);
    times = k;
    r = u;
 
   
end

6,求解精确解
%% 精确解
function r = Right(h, n, e)
 
    u = zeros(n+1, n+1);  % 初边值条件简写
   
   
    for i=2: n
        for j=2: n
            x = (i-1)*h;
            y = (j-1)*h;
            u(i,j)= f_R(x, y);
        end
    end
   
    r = u;
   
   
end

7,右端函数
%% fij 函数
function r = f_u(x, y)
    r1 = 2*pi*pi*exp(pi*(x+y));
    r2 = sin(pi*x)*cos(pi*y) + cos(pi*x)*sin(pi*y);
   
    r = r1 * r2;
end

8,精确解函数
%% 精确解函数
function r = f_R(x, y)
r = exp(pi*(x+y))*sin(pi*x)*sin(pi*y);
end