Sheng Wang

PML边界-一阶声波方程有线差分模拟在二维下的实现

本文介绍了二维下声波方程PML吸收边界的有限差分实现。

PML区域控制方程

二维下不考虑输出源,二阶声波方程为:

对应的一阶压强-速度方程可以写成:

针对PML区域:

$d(x)$的选择

$R$推荐取0.001,$\delta$为PML层厚[Collino and Tsogka 2001]。

交错网格

构建二维下的交错网格。

对于交错节点,$p$,$q_x$,$q_z$递推关系如下图:

二阶精度有现差分实现

$q_x$递推

$q_z$递推

$p_x$递推

$p_z$递推

递推汇总

故而,波场递推关系为:

Implementation

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
%Matlab
close all;clear;clc;
%Parameters
n_pml = 10;
nx = 320; nz = 320; dx = 5.0; dz = 5.0;
x = (-n_pml:nx-1-n_pml) *dx; %(1:11) and (310:320) are PML zone
z = (-n_pml:nx-1-n_pml) *dz;
dt = 1.0e-3; nt = 2000; t = (0:nt-1)*dt;
v = zeros(nx,nz) + 800.0; rho = 1000.0;
R = 0.001; delta = n_pml * dx; d_const = (3.0/2.0/delta)*log(1.0/R) /(delta* delta);

%d(x) and d(z)
d_pxLeft = ( (-n_pml:0)*dx ).^2 * d_const;
d_pxRight = ( (0:n_pml)*dx ).^2 * d_const;
d_qxLeft = ( (-n_pml:-1)*dx +dx/2 ).^2 * d_const;
d_qxRight = ( (1:n_pml)*dx -dx/2 ).^2 * d_const;
d_px = [d_pxLeft zeros(1,nx-2*n_pml-2) d_pxRight];
d_qx = [d_qxLeft zeros(1,nx-2*n_pml-1) d_qxRight];
d_pzLeft = ( (-n_pml:0)*dz ) .^2 * d_const;
d_pzRight = ( (0:n_pml)*dz ) .^2 * d_const;
d_qzLeft = ( (-n_pml:-1)*dz +dz/2 ) .^2 * d_const;
d_qzRight = ( (1:n_pml)*dz -dz/2 ) .^2 * d_const;
d_pz = [d_pzLeft zeros(1,nx-2*n_pml-2) d_pzRight];
d_qz = [d_qzLeft zeros(1,nx-2*n_pml-1) d_qzRight];
p = zeros(nx,nz); p_x = zeros(nx,nz); p_z = zeros(nx,nz);
q_x = zeros(nx-1,nz); q_z = zeros(nx,nz-1);

$Source
src = [ 2.0*mexihat(-5,5,200) zeros(1,nt)];
ix_src = 161; iz_src = 161;

%Main loop
figure
for it = 1:nt
%
% 1 2 3 4 5
% --q---q---q---q---q--...
% p---p---p---p---p---p...
% 1 2 3 4 5 6
%

p_x(ix_src, iz_src) = p_x(ix_src,iz_src) + src(it)/2.0;
p_z(ix_src, iz_src) = p_z(ix_src,iz_src) + src(it)/2.0;
p( ix_src, iz_src) = p( ix_src,iz_src) + src(it)/2.0;
%q_x
for ix = 1:nx-1
for iz = 1:nz
deno = (2.0 + dt * d_qx(ix)*v(ix,iz));
c_qx1 = (2.0 - dt * d_qx(ix)*v(ix,iz) ) / deno;
c_qx2 = -2.0*dt / rho / dx / deno;
q_x(ix,iz) = c_qx1 * q_x(ix,iz) + c_qx2 *( p(ix+1,iz) - p(ix,iz) );
end
end
%q_z
for iz = 1:nz-1
for ix = 1:nx
deno = (2.0 + dt * d_qz(iz)*v(ix,iz) );
c_qz1 = (2.0 - dt * d_qz(iz)*v(ix,iz) )/ deno;
c_qz2 = -2.0*dt/rho/ dz / deno;
q_z(ix,iz) = c_qz1 * q_z(ix,iz) + c_qz2 *( p(ix,iz+1) - p(ix,iz) );
end
end

%p_x
for ix = 2:nx-1
for iz = 2:nz-1
deno = (2.0 + dt * d_px(ix)*v(ix,iz) );
c_px1 = (2.0 - dt * d_px(ix)*v(ix,iz) ) / deno;
c_px2 = -2.0*rho*v2(ix,iz)*dt/dx / deno;
deno = (2.0 + dt * d_pz(iz)*v(ix,iz) );
c_pz1 = (2.0 - dt * d_pz(iz)*v(ix,iz) ) / deno;
c_pz2 = -2.0*rho*v2(ix,iz)*dt/dz /deno;
p_x(ix,iz) = c_px1 * p_x(ix,iz) + c_px2 * ( q_x(ix,iz) - q_x(ix- 1,iz) );
p_z(ix,iz) = c_pz1 * p_z(ix,iz) + c_pz2 * ( q_z(ix,iz) - q_z(ix,iz- 1) );
p(ix,iz) = p_x(ix,iz) + p_z(ix,iz);
end
end

pmax = max(max( abs(p) ));
imagesc(x, z, p/pmax );
colormap('gray');
axis square;
pause(0.001);
end