我在使用快速扫描法(Fast sweeping method)求解程函方程时,发现写出的程序虽然能够收敛,但是数值解与真解之间的误差很大,请各位帮忙看看,以下是我的代码。其中使用的算例的是
参考的文章为:Zhao, H, K., 2005. A Fast sweeping method for Eikonal equations
%fast sweeping for Eikonal
function [phi_new, phi_old] = Eikonal(Nx, Ny, r, x, y, dx, dy, center, ghost_point, phi,c)
%c=1
d = @(x, y) sqrt((x - center(1))^2 + (y - center(2))^2); % 距离函数
h = dx;
phi_old = phi;
phi_new = phi;
% 快速扫掠法求解Eikonal方程 |∇phi_0| = c(x,y,T_end)
for i = 1 : 1 : Nx
for j = 1 :1 : Ny
if i==1
min_x = min(ghost_point, phi(i+1,j));
elseif i==Nx
min_x = min(phi(i-1,j),ghost_point);
else
min_x = min(phi(i-1,j),phi(i+1,j));
end
if j==1
min_y = min(ghost_point, phi(i,j+1));
elseif j==Ny
min_y = min(phi(i,j-1),ghost_point);
else
min_y = min(phi(i,j+1), phi(i,j-1));
end
if abs(min_x-min_y)>=(c(i,j))*h
tmp = min(min_x,min_y) + (c(i,j)) * h;
else
tmp = 0.5*(min_x+min_y+sqrt(abs(2*(c(i,j)^2)*(h*h)-(min_x-min_y)*(min_x-min_y))));
end
phi(i,j) = min(tmp,phi(i,j));
phi_new(i,j) = phi(i,j);
if x(i)==0 && y(j) ==0
phi(i,j) = phi_old(i,j);
phi_new(i,j) = phi(i,j);
end
end
end
for i = Nx : -1 : 1
for j = 1 :1 : Ny
if i==1
min_x = min(ghost_point, phi(i+1,j));
elseif i==Nx
min_x = min(phi(i-1,j),ghost_point);
else
min_x = min(phi(i-1,j),phi(i+1,j));
end
if j==1
min_y = min(ghost_point, phi(i,j+1));
elseif j==Ny
min_y = min(phi(i,j-1),ghost_point);
else
min_y = min(phi(i,j+1), phi(i,j-1));
end
if abs(min_x-min_y)>=(c(i,j))*h
tmp = min(min_x,min_y) + (c(i,j)) * h;
else
tmp = 0.5*(min_x+min_y+sqrt(abs(2*(c(i,j)^2)*(h*h)-(min_x-min_y)*(min_x-min_y))));
end
phi(i,j) = min(phi(i,j),tmp);
if x(i)==0 && y(j) ==0
phi(i,j) = phi_old(i,j);
end
end
end
for i = Nx : -1 : 1
for j = Ny :-1 : 1
if i==1
min_x = min(ghost_point, phi(i+1,j));
elseif i==Nx
min_x = min(phi(i-1,j),ghost_point);
else
min_x = min(phi(i-1,j),phi(i+1,j));
end
if j==1
min_y = min(ghost_point, phi(i,j+1));
elseif j==Ny
min_y = min(phi(i,j-1),ghost_point);
else
min_y = min(phi(i,j+1), phi(i,j-1));
end
if abs(min_x-min_y)>=(c(i,j))*h
tmp = min(min_x,min_y) + (c(i,j)) * h;
else
tmp = 0.5*(min_x+min_y+sqrt(abs(2*(c(i,j)^2)*(h*h)-(min_x-min_y)*(min_x-min_y))));
end
phi(i,j) = min(tmp,phi(i,j));
if x(i)==0 && y(j) ==0
phi(i,j) = phi_old(i,j);
end
end
end
for i = 1 : 1 : Nx
for j = Ny :-1 : 1
if i==1
min_x = min(ghost_point, phi(i+1,j));
elseif i==Nx
min_x = min(phi(i-1,j),ghost_point);
else
min_x = min(phi(i-1,j),phi(i+1,j));
end
if j==1
min_y = min(ghost_point, phi(i,j+1));
elseif j==Ny
min_y = min(phi(i,j-1),ghost_point);
else
min_y = min(phi(i,j+1), phi(i,j-1));
end
if abs(min_x-min_y)>=(c(i,j))*h
tmp = min(min_x,min_y) + (c(i,j)) * h;
else
tmp = 0.5*(min_x+min_y+sqrt(abs(2*(c(i,j)^2)*(h*h)-(min_x-min_y)*(min_x-min_y))));
end
phi(i,j) = min(tmp,phi(i,j));
if x(i)==0 && y(j) ==0
phi(i,j) = phi_old(i,j);
end
end
end
end
clc; clear; close all;
h=[0.02,0.01,0.005,0.0025,0.002];
x = (-0.5:h(3):0.5);
y = (-0.5:h(3):0.5);
Nx = length(x);
Ny = length(y);
[X, Y] = meshgrid(x, y);
X = X';
Y = Y';
center = [0,0];
d = @(x, y) sqrt((x - center(1))^2 + (y - center(2))^2);
c = @(x,y) 1+exp(-40*((x+0.2)^2+(y+0.2)^2))-exp(-40*((x-0.2)^2+(y-0.2)^2)); %程函方程中的f
true_phi = @(x,y) abs(exp((sqrt(x^2+y^2)-0.2)*(0.01*x+x*y+y^2+0.4))-1);
ghost_point = 1e12;
phi = ones(Nx,Ny)*1e6;
c_used = zeros(Nx,Ny);
true_values = zeros(Nx,Ny);
r=0.015;
%初始化矩阵
for i = 1 : Nx
for j =1 : Ny
if x(i)==0 && y(j) ==0
phi(i,j) = 0;
end
c_used(i,j) = c(x(i),y(j));
true_values(i,j) = true_phi(x(i),y(j));
end
end
%c_used = c(X,Y);
delta = 1;
k=1;
while delta>1e-9
[phi_new,phi_old] = Eikonal(Nx,Ny, r,x,y,h(3),h(3),center,ghost_point,phi,c_used);
delta = max(max(phi_new - phi_old));
phi = phi_new;
k = k+1;
end
error = max(max(phi-true_values));
以下是我的求解结果
以下为原文中的算例结果