一维有限元方法

模型问题

我们考虑如下一维 Poisson 方程的线性有限元求解算法 其中真解为

程序实现

测试模型数据

function pde = sin4pidata( )
%% SINDATA
%
%  u = sin(4*pi*x)
%  f = 16*pi*pi*sin(4*pi*x)
%  Du = 4*pi*cos(4*pi*x)
%

pde = struct(...
    'source', @source, ...
    'solution', @solution, ...
    'dirichlet', @dirichlet, ...
    'grad_solution', @grad_solution);

% right hand side function
function z = source(p)
    x = p;
    z = 16*pi*pi*sin(4*pi*x);
end

function z = solution(p)
    x = p;
    z = sin(4*pi*x);
end

% Dirichlet boundary condition
function z = dirichlet(p)
    x = p;
    z = solution(p);
end

% Derivative of the exact solution
function z = grad_solution(p)
    x = p;
    z = 4*pi*cos(4*pi*x);
end

end

数值积分公式

function [lambda, weight] = quadpts1d(order)
%% QUADPTS1 quadrature points in 1-D.
%

numPts = ceil((order+1)/2);

if numPts > 10
   numPts = 10; 
end

switch numPts
    case 1
        A = [0      2.0000000000000000000000000];

    case 2
        A = [0.5773502691896257645091488     1.0000000000000000000000000
            -0.5773502691896257645091488     1.0000000000000000000000000];

    case 3
        A = [0     0.8888888888888888888888889
            0.7745966692414833770358531     0.5555555555555555555555556
            -0.7745966692414833770358531     0.5555555555555555555555556];

    case 4
        A = [0.3399810435848562648026658     0.6521451548625461426269361
            0.8611363115940525752239465     0.3478548451374538573730639
            -0.3399810435848562648026658     0.6521451548625461426269361
            -0.8611363115940525752239465     0.3478548451374538573730639];

    case 5
        A = [0                                 0.5688888888888888888888889
            0.5384693101056830910363144     0.4786286704993664680412915
            0.9061798459386639927976269     0.2369268850561890875142640
            -0.5384693101056830910363144     0.4786286704993664680412915
            -0.9061798459386639927976269     0.2369268850561890875142640];

    case 6
        A = [0.2386191860831969086305017     0.4679139345726910473898703
            0.6612093864662645136613996     0.3607615730481386075698335
            0.9324695142031520278123016     0.1713244923791703450402961
            -0.2386191860831969086305017     0.4679139345726910473898703
            -0.6612093864662645136613996     0.3607615730481386075698335
            -0.9324695142031520278123016     0.1713244923791703450402961];

    case 7
        A = [0                                 0.4179591836734693877551020
            0.4058451513773971669066064     0.3818300505051189449503698
            0.7415311855993944398638648     0.2797053914892766679014678
            0.9491079123427585245261897     0.1294849661688696932706114
            -0.4058451513773971669066064     0.3818300505051189449503698
            -0.7415311855993944398638648     0.2797053914892766679014678
            -0.9491079123427585245261897     0.1294849661688696932706114];

    case 8
        A = [0.1834346424956498049394761     0.3626837833783619829651504
            0.5255324099163289858177390     0.3137066458778872873379622
            0.7966664774136267395915539     0.2223810344533744705443560
            0.9602898564975362316835609     0.1012285362903762591525314
            -0.1834346424956498049394761     0.3626837833783619829651504
            -0.5255324099163289858177390     0.3137066458778872873379622
            -0.7966664774136267395915539     0.2223810344533744705443560
            -0.9602898564975362316835609     0.1012285362903762591525314];

    case 9
        A = [0                                 0.3302393550012597631645251
            0.3242534234038089290385380     0.3123470770400028400686304
            0.6133714327005903973087020     0.2606106964029354623187429
            0.8360311073266357942994298     0.1806481606948574040584720
            0.9681602395076260898355762     0.0812743883615744119718922
            -0.3242534234038089290385380     0.3123470770400028400686304
            -0.6133714327005903973087020     0.2606106964029354623187429
            -0.8360311073266357942994298     0.1806481606948574040584720
            -0.9681602395076260898355762     0.0812743883615744119718922];

    case 10
        A = [0.1488743389816312108848260     0.2955242247147528701738930
            0.4333953941292471907992659     0.2692667193099963550912269
            0.6794095682990244062343274     0.2190863625159820439955349
            0.8650633666889845107320967     0.1494513491505805931457763
            0.9739065285171717200779640     0.0666713443086881375935688
            -0.1488743389816312108848260     0.2955242247147528701738930
            -0.4333953941292471907992659     0.2692667193099963550912269
            -0.6794095682990244062343274     0.2190863625159820439955349
            -0.8650633666889845107320967     0.1494513491505805931457763
            -0.9739065285171717200779640     0.0666713443086881375935688];
end
lambda1 = (A(:,1)+1)/2;
lambda2 = 1 - lambda1;
lambda = [lambda1, lambda2];
weight = A(:,2)/2;

网格生成

function [node, elem, bdFlag] = intervalmesh(a,b,h)
%% INTERVALMESH the uniform mesh on interval [a,b] with size h.
%
% node(1:N,1): node(i) is the coordinate of i-th
% mesh point.
%
% elem(1:NT,1:2): elem(j,1:2) are the indexes of the two end
% vertices of j-th elements.
%

node = a:h:b;
node = node';
N = length(node);
elem = [1:N-1;2:N];
elem = elem';
bdFlag = false(N,1);
bdFlag([1,N]) = true;

测试脚本

%% 一维有限元测试函数 

h = 0.1;
a = 0;
b = 1;
pde = sin4pidata();
option.fQuadOrder = 3;
option.errQuadOder = 3;


maxIt = 5;
errL2 = zeros(maxIt,1);
errH1 = zeros(maxIt,1);
N = zeros(maxIt,1);

for i = 1:maxIt
    [node, elem, bdFlag] = intervalmesh(a,b,h/2^(i-1));
    uh = Poisson1d(node, elem, pde, bdFlag, option);
    N(i) = size(elem,1);
    hold on
    showsolution1d(node, uh);

    name = ['solution' int2str(N(i))];
    errL2(i) = getL2error1d(node, elem, pde.solution, uh, option.errQuadOder);
    errH1(i) = getH1error1d(node, elem, pde.grad_solution, uh, option.errQuadOder);
end

disp('L2 error:');
disp(errL2);

disp('H1 error:');
disp(errH1);

有限元算法实现

function uh = Poisson1d(node, elem, pde, bdFlag,option)
%% POISSON1D solve 1d Poisson equation by P1 linear element.
%
%  uh = Poisson1d(node,elem,pde, bdFlag) produces linear 
%  finite element approximation of 1d Poisson equation.

N = size(node,1); NT = size(elem,1); Ndof = N;
%% Compute geometric quantities and gradient of local basis
lens = node(elem(:,2))-node(elem(:,1));
Dphi = [-1./lens,1./lens];

%% Assemble stiffness matrix
A = sparse(Ndof,Ndof);
for i = 1:2
    for j = i:2
        Aij = Dphi(:,i).*Dphi(:,j).*lens;
        if (j==i)
            A = A + sparse(elem(:,i), elem(:,j),Aij,Ndof,Ndof);
        else
            A = A + sparse([elem(:,i);elem(:,j)],[elem(:,j);elem(:,i)],...
                [Aij; Aij],Ndof,Ndof);
        end
    end
end

%% Assemble the right hand side
[lambda,weight] = quadpts1d(option.fQuadOrder);
nQuad = length(weight);
phi = lambda;
bt = zeros(NT,2);
for i = 1:nQuad
    px = node(elem(:,1))*phi(i,1) + node(elem(:,2))*phi(i,2);
    fp = pde.source(px);
    for k = 1:2
        bt(:,k) = bt(:,k) + weight(i)*fp.*phi(i,k);
    end
end
bt = bt.*repmat(lens,1,2);
b = accumarray(elem(:),bt(:),[Ndof 1]);
clear bt px;

%% modify left-hand vector
isFixed = bdFlag;
isFree = ~isFixed;
uh = zeros(Ndof,1);
uh(isFixed) = pde.dirichlet(node(isFixed));
b = b - A*uh;

%% solve 
uh(isFree) = A(isFree,isFree)\b(isFree);

误差计算

function err = getL2error1d(node, elem, solution, uh, quadOrder)
%% GETL2ERROR1D L2 norm of approximation of linear fintie
%% element
%
% compute L2 error element-wise using quadrature rule with order
% quadOrder

NT = size(elem,1);
err = zeros(NT,1);
[lambda,weight] = quadpts1d(quadOrder);

% basis function at quadrature points
phi = lambda;

nQuad = length(weight);
for i = 1:nQuad
    uhp = uh(elem(:,1))*phi(i,1) + uh(elem(:,2))*phi(i,2);
    px = node(elem(:,1))*phi(i,1) + node(elem(:,2))*phi(i,2);
    err = err + weight(i)*(solution(px) - uhp).^2;
end

lens = node(elem(:,2)) - node(elem(:,1));
err = err.*lens;
err = sqrt(sum(err));

function err = getH1error1d(node, elem, grad_solution, uh, quadOrder)
%% GETH1ERROR1D H1 norm of approximation error of linear finite
%% element
% 
% compute H1 error element-wise using quadrature rule 
% with order quadOrder

NT = size(elem,1);
err = zeros(NT,1);
[lambda,weight] = quadpts1d(quadOrder);
phi = lambda;
lens = node(elem(:,2))-node(elem(:,1));
Dphi = [-1./lens,1./lens];

nQuad = length(weight);
Duh = uh(elem(:,1)).*Dphi(:,1) + uh(elem(:,2)).*Dphi(:,2);

for i = 1:nQuad
    px = node(elem(:,1))*phi(i,1) + node(elem(:,2))*phi(i,2);
    err = err + weight(i)*(grad_solution(px)-Duh).^2;
end
err = err.*lens;
err = sqrt(sum(err));

实验报告

用线性有限元方法求边值问题:

其中真解为

网格单元长度分别取为 ,用线性有限元求解 ,计算有限元解与真解的 误差

误差。

results matching ""

    No results matching ""