二阶pde数值求解算法

二阶偏微分方程分类

AUxx+2BUxy+CUyy+DUx+EUy+FU=0

  • B2AC<0,椭圆型;
  • B2AC=0,抛物线型;
  • B2AC>0,双曲型;

边界条件

  • 第一类边界条件,给定边界 Γ上的函数值 ϕ|Γ;
  • 第二类边界条件,给定边界 Γ上的函数导数值 ϕn|Γ;
  • 第三类边界条件,给定边界 Γ上的函数值与导数值线性组合 aϕ+bϕn|Γ;

椭圆形偏微分方程

主要考虑Poisson方程和Laplace方程:

[2x2+2y2]ϕ=S(x,y)

区域离散化:

[ϕi+1,j+ϕi1,j+ϕi,j+1+ϕi,j14ϕij]=h2Sij

或表示为:

[(δi2ϕ)ij+(δj2ϕ)ij]=h2Sij

(δi2ϕ)ijϕi+1,j+ϕi1,j2ϕij (δj2ϕ)ijϕi,j+1+ϕi,j12ϕij

正方形边界代码示例:

% 边值条件与初值选取
xa=0;xb=pi;
ya=0;yb=pi;
N=100;
M=100;
h1=(xb-xa)/N;
h2=(yb-ya)/M;
xinit=xa:h1:xb;
yinit=ya:h2:yb;
u=zeros(N+1,M+1);
u(:,M+1)=sin(xinit);
uold=u;
u(2:N,2:M)=1/(2*pi);% 边界平均值为1/(2*pi)以初始化内点

Jacobi迭代法

φijn+1=14[φi1,jn+φi+1,jn+φi,j1n+φi,j+1n+h2Sijn]

% 正方形边界问题下的jacobi迭代法实现
function usolve=jacobi_iteration(u,s,h,uold,N,M,err)
if nargin <5         
    err = 10^-6;
end  
iter_num=0;
while max(max(abs(u-uold)))>=err
      uold=u;
      u(2:N,2:M)=0.25*(u(3:N+1,2:M)+u(1:N-1,2:M)+u(2:N,3:M+1)+u(2:N,1:M-1)+h^2*s(2:N,2:M));
      iter_num=iter_num+1;
end
usolve=u;
% fprintf("The error of Jacobi method is %f\n",max(max(abs(u-uold))))
fprintf("The iteration number of Jacobi method is%d\n",iter_num)
end

Gauss-Seidal法

φijn+1=(1ω)φijn+ω4[φi1,jn+1+φi+1,jn+φi,j1n+1+φi,j+1n+h2Sijn]

其中 0<ω<2,最佳值需要依据情况确定。

% 正方形边界问题下的Gauss_Seidel迭代法实现
function usolve=Gauss_Seidel(u,S,h,w,N,M,err)
if nargin <5         
    err = 10^-8;
end    
iter_num=0;
merr=err+1;
while merr>err
    iter_num= iter_num+1;
    merr=0;
        for i=2:N
            for j=2:M
                %Gauss-Seidel迭代法
                relax=w/4*(u(i,j+1)+u(i,j-1)+u(i+1,j)+u(i-1,j)-4*u(i,j)+h^2*S(i,j));
                u(i,j)=u(i,j)+relax;
                if abs(relax)>merr
                    merr=abs(relax);
                end
            end
        end
end
 usolve=u;       
%  fprintf("The error of Gauss-Seidel method is%f\n",abs(merr))
 fprintf("The iteration number of Gauss-Seidel method is%d\n",iter_num)
end  

抛物线形偏微分方程

主要以扩散方程和含时薛定谔方程为主:

一维扩散方程:

Φt=2Φx2+S(x,t)

一维扩散问题边界示例

%格点化条件
L=1;
t0=1;
a=1;%u_t=a^2u_xx
dx=0.05;x=0:dx:L;N=length(x);
dt=0.001;t=0:dt:t0;M=length(t);
[X,T]=meshgrid(x,t);
y=zeros(N,M);
y(1:(N+1)/2,1) = 2*x(1:(N+1)/2); % 边界条件
y((N+1)/2:N,1) = 2*(1-x((N+1)/2:N));

显式差分

Φin+1=rΦi+1n+(12r)Φin+rΦi1n+SinΔt,r=Δth2

只有当 r<12时算法才稳定。

若记

(δ2Φn)i=Φi+1n2Φin+Φi1n

则显式差分也可写成:

Φn+1=(1HΔt)Φn+SnΔt

其中 :

HΦi1h2(δ2Φ)i

%----显式差分-------
function  uforward=forward(y,dx,dt,M,N,a)
rr=dt/dx^2*a;
for j=1:M-1    %时间上的步数
    for i=2:N-1   %空间上的点
        y(i,j+1)=rr*y(i+1,j)+(1-2*rr)*y(i,j)+rr*y(i-1,j);
    end
end
uforward=y';
end

直接隐式差分

[1+2rrr1+2rrr1+2rrr1+2r][Φ1n+1Φ2n+1ΦN2n+1ΦN1n+1]=[Φ1n+S1nΔt+rΦ0n+1Φ2n+S2nΔt...ΦN2n+SN2nΔtΦN1n+SN1nΔt+rΦNn+1]

用算符表示为:

Φn+1=11+HΔt[Φn+SnΔt]

%----直接隐式差分----
function  uback=back(y,dx,dt,M,N,a)
rr=dt/dx^2*a;
A=diag((1+2*rr)*ones(N-2,1),0) + diag(-rr*ones(N-3,1),-1) + diag(-rr*ones(N-3,1),1);
for j=1:M-1    %时间上的步数
    for i=2:N-1   %空间上的点
        b = y(2:N-1,j);
        b(1) = b(1) + rr*y(1,j+1);
        b(N-2) = b(N-2) + rr*y(N,j+1);
        y(2:N-1,j+1) = soldiag(A,b);
    end
end
uback=y';
end
%--soldiag---
function x = soldiag(A,d)
%求解Ax=d,A为系数矩阵
    n = length(d);
    x = zeros(n,1);
    for i = 2:n
        w = A(i,i-1)/A(i-1,i-1);
        A(i,i) = A(i,i)-w*A(i-1,i);
        d(i) = d(i)-w*d(i-1);
    end
    x(n) = d(n)/A(n,n);
    for i = (n-1):(-1):1
        x(i) = (d(i)-A(i,i+1)*x(i+1))/A(i,i);
    end
end

平均隐式差分

[1+rr/2r/21+rr/2r/21+rr/2r/21+r][Φ1n+1Φ2n+1ΦN2n+1ΦN1n+1]=[r2Φ2n+(1r)Φ1n+r2Φ0n+S0nΔt+r2Φ0n+1r2Φ3n+(1r)Φ2n+r2Φ1n+S1nΔt...r2ΦN1n+(1r)ΦN2n+r2ΦN3n+SN2nΔtr2ΦNn+(1r)ΦN1n+r2ΦN2n+SN1nΔt+r2ΦNn+1]

用算符表示为:

Φn+1=11+12HΔt[(112HΔt)Φn+SnΔt]

%---------平均隐式差分-----
function uck=Crank_Nicolson(y,dx,dt,M,N,a)
rr=dt/dx^2*a;
A = diag((1+rr)*ones(N-2,1),0) + diag(-rr/2*ones(N-3,1),-1) + diag(-rr/2*ones(N-3,1),1);
for j = 1:M-1
    b = (1-rr)*y(2:N-1,j) + rr/2*y(1:N-2,j) + rr/2*y(3:N,j);
    b(1) = b(1) + rr/2*y(1,j+1);
    b(N-2) = b(N-2) + rr/2*y(N,j+1);
    y(2:N-1,j+1) = soldiag(A,b);
end
uck = y';
end

一维薛定谔方程的平均隐式差分

iϕt=22m2ϕ+Vϕ

平均隐式差分为:

ϕn+1=(1i12HΔt1+i12HΔt)ϕn,H=2x2+V

实际计算时:

ϕn+1=(21+i12HΔt1)ϕnχϕn

其中 χ满足:

χj1+[2+2ih2Δth2Vj]χj+χj+1=4ih2Δtϕjn,j=1,,N1

或矩阵形式:

令 :

r=2+2ih2Δth2Vj

[r11r11r11r][χ1χ2χN2χN1]=[4ih2Δtϕ1nχ04ih2Δtϕ2n...4ih2ΔtϕN2n4ih2ΔtϕN1n+χN]

一维高斯波包初值边界值示例

%设定条件
xa=-30;xb=30;dx=0.1;
x=xa:dx:xb;
ta=0;tb=5;dt=0.01;t=ta:dt:tb;
N = length(x);
M = length(t);
V = transpose(arrayfun(@v,x));
sigma=3;k0=2.5;%Gauss波包参数
x0=-10;              %Gauss波包参数

psi0 = exp(k0*1i.*x).*exp(-(x-x0).^2*log10(2)/(2*sigma^2)); 
psi0(1) = 0; psi0(N) = 0; % 波函数边界条件
psi0 = transpose(psi0);

平均隐式差分

%平均隐式差分
psi=zeros(N,M);
psi(:,1)=psi0;
chi = zeros(N,M-1);
r = 1i*dt/(dx^2);
A = diag((1+r)*ones(N-2,1)+1i/2*dt*V(2:N-1)) + diag(-r/2*ones(N-3,1),-1) + diag(-r/2*ones(N-3,1),1);
for j = 1:M-1
    b = 2*psi(2:N-1,j);
    b(1) = b(1) + r/2*chi(1,j);
    b(N-2) = b(N-2) + r/2*chi(N,j);
    chi(2:N-1,j) = inv(A)b;
    psi(2:N-1,j+1) = chi(2:N-1,j)-psi(2:N-1,j);
end
Orbifold
Orbifold
Undergraduated Student

I am an undergraduated students majoring in physics.