简述有限元: 逼近函数 II程序实例(I)
逼近函数 I 中介绍了逼近函数的数学推导, 这一次用程序实现它.
例题回顾
给定一个二次(抛物型)函数 f(x)=10(x−1)2−1,x∈Ω=[1,2], 在线性函数空间 V 中寻找最佳逼近向量 u
V=span{1,x}.\bf 解: 设 ψ0=1,ψ1=x, 则
u=c0ψ0(x)+c1ψ1(x)=c0+c1x.所以系数矩阵
A11=(ψ0,ψ0)=∫121⋅1dx=1,A12=(ψ1,ψ0)=∫12x⋅1dx=23,A21=A12=23,A22=(ψ1,ψ1)=∫12x⋅xdx=37.所有系数矩阵是
A=1232337右端项为:
b1=(ψ0,f)=∫121⋅(10(x−1)2−1)dx=37,b2=(ψ1,f)=∫12x⋅(10(x−1)2−1)dx=313.所以 b=[37,313]T, 解线性方程组就可以得到
c=−38/310.因此
u=10x−38/3.程序实现
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
| close all
clear
clc
format rat % 以分式显示结果
% 基本变量
xx = [1, 2];
syms x
f = (10 * (x-1)^2 -1);
F = inline(vectorize(f), 'x'); % 符号向量化
% 基函数
N = 3;
for i = 1 : N
V(i) = x^(i-1);
end
% 组装系数矩阵
A = assemble_stiffness_matrix(V, xx);
% 载入右端向量
b = assemble_load_vector(f, V, xx);
% 线性方程组求解
c = A\b;
u =V*c;
% 可视化
X = xx(1) : 0.01 : xx(2);
U = inline(vectorize(u), 'x');
Plot(X, F, U)
% 结果展示
result(A, b, c, u)
|
V = {1, x}
V = {1, x}程序计算结果与手算的是一样的.
当 V=span{1,x,x2} 时, 逼近解等于真解, 如下图所示
V = {1, x}
V = {1, x}本程序其他函数可点击原文链接下载, GitHub.
选取更好的基函数
上一节的基函数空间为 V=span{xj},j∈Is,Is={0,1,…,N}, 在上一节的例子中, 函数逼近的很好, 在用此基函数逼近多项式时, 理论上可以得到原多项式. ..但是.., 当 N 过大时, 形成的系数矩阵 A 是奇异的, 是病态的, 即线性方程组系统不可解.
病态缘由选择..正交..(或者几乎正交)的基函数是数值计算中经常使用的, 其原因是可以使得 Aij=0,i=j, 从而矩阵几乎是对角化的.
傅立叶级数
Fourier series
令
V=span{sin(πx),sin(2πx),…,sin(N+1)πx}.那么基函数为
ψi(x)=sin(i+1)πx,i∈Is.将基函数带入上文的主程序中, 得到 N=3 和 N=11 时的拟合图
N=3
N=11以上结果似乎拟合得很好, ..但是..可以发现, 无论当 N 如何增大, 始终得到 u(0)=u(1)=1. 肯定是哪里出错了:
u(x)=j∈Is∑cjsin(j+1)πx.上式显示: u(0)=u(1)≡0. 因此需要修正算法:
令 u(0)=f(0),u(1)=f(1), 以加入边界信息, 再加上 u(x)=∑j∈Iscjψj(x), 可设
u~(x)=(1−x)f(0)+xf(1)+j∈Is∑cjψj(x).设 B(x)=(1−x)f(0)+xf(1), 此时的线性方程组系统为
j∈Is∑(ψj,ψi)cj=(f−B,ψi),i∈Is.针对该基函数修正后的主函数为
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
| close all
clear
clc
format rat % 以分式显示结果
% format long
% 基本变量
xx = [0, 1];
syms x
f = (10 * (x-1/2)^5 -1);
F = inline(vectorize(f), 'x');
f_0 = F(xx(1));
f_N = F(xx(end));
n = 6;
for i = 1:n
V(i) = sin(i*pi*x);
end
B = f_0*(xx(end)-x) + f_N*(x-xx(1));
% 组装系数矩阵
A = assemble_stiffness_matrix(V, xx);
% 载入右端向量
b = assemble_load_vector(f-B, V, xx);
% 线性方程组求解
c = A\b;
u = B + V*c;
% 可视化
X = xx(1) : 0.01 : xx(2);
U = inline(vectorize(u), 'x');
Plot(X, F, U)
% 结果展示
result(A, b, c, u)
|
如下图所示, 使用修正后的算法, N=3 时, 已经可以逼近的很好了.
N=3
结果展示 N=3计算结果展示: 矩阵 A=21I, 这是巧合吗? 不是的! 因为在区间 [0,1] 上
∫01sin2(jπx)dx=21.所以
c=A−1b=2b.即
ci=2(f−B,ψi).这样程序就更简单了.
程序实例(II)
通过正弦函数逼近 f(x)=tanh(s(x−π)),s=20, 即在空间 V=span{sin(2i+1)x} ,i∈[0,1,…,N] 中找到 u(x) 最佳逼近于 f(x).
N=1
N=3
N=7
N=15程序参考之前小节. 该现象称为吉布斯现象.
下节预告
讨论逼近函数的最后一种方法 – 插值法 🤘