应用配景
有限差分数值仿真技术是声波或弹性波场数值模拟中最为流行的方法之一,然而传统的有 限差分方法在求解颠簸方程时,会产生不期望的数值频散或称网格频散,导致了数值模拟结果 分辨率的降低。究其根源,是因为基于颠簸方程的有限差分求解过程,通常是利用一离散化的 有限差分方程去迫近颠簸方程,从而使得相速度酿成了离散空间间隔的函数。因此,当每一波长内空间采样太少(即空间网格太粗)时,就会产生数值频散。
所谓数值频散实质上是一种因离散化求解颠簸方程而产生的伪颠簸。这种频散既差别于颠簸方程自己引起的频散,也差别于因波流传的速度、频率和角度而引起的频散,它是有限差分 方法求解颠簸方程时所固有的本质特征,无法制止。
为了消除这种数值频散,人们进行了大量的研究[1][2][3],他们的结论是基本一致的,即 为了消除数值频散,在使用二阶有限差分方法时,每个二分之一功率对应的波长至少必须使用 nn个网格点,而四阶有限差分则可用二阶差分网格点数的一半。王才经 (1990) 也得到了基本 一致的结论[4]。从他们的研究结论中,我们似乎可以得出,提高有限差分格式的精度,可充实 减少每一个波长内的采样点。但事实上并非如此,因为再提高差分格式的精度,将会大大增加 计算量。因此,通过提高有限差分格式的精度以便在粗网格计算条件下消除网格频散的方法并 不可取。
在流体动力学连续方程的求解中,Boris和Book (1973)[5]、Book等 (1975)[6]发展了一种通量校正传输方法 (FCT),并将他们的FCT方法应用于声波方程的求解中,有效地压制了在粗网格情况下差分计算产生的数值频散。杨顶辉和滕吉文(1997)将这种FCT技术与求解各向异性颠簸方程组的有限差分方法结合,获得了一种适用于求解各向异性介质中二阶声波和弹性波方程的FCT有限差分算法。其过程主要包罗三步:有限差分计算、平滑方程的解和反漫射处置惩罚。
正如上面所述,在使用有限差分求解颠簸方程时,如果每一波长的采样点太少,会产生 数值频散。因此,为了消除差分计算引起的频散,必须作漫射通量的计算,通过漫射通量来 修改差分方程的解 ( 即平滑方程的解 )。由于这种平滑处置惩罚是对计算区域内的每一个网格点实施的,从而一定水平地压制了真实的颠簸,造成振幅精度的部门损失。固然这种精度的损失并 不影响FCT技术的推广,因为损失是不明显的。漫射是以守恒方式实现的,即任何时候在任一 点去掉一部门波场时,就必须有相同数量加回到某一地方。因此,一旦解发生漫射,就必须在 任何不需要漫射的地方引入反漫射以抵消漫射,以使真实波场得以恢复。因此对解作反漫射修正,比漫射计算更复杂,通常是通过一非线性局部搜索来实现。
研究进展
1975 Book等
[7]首次将流体动力学中的通量校正传输方法应用于声波方程求解。1997 杨顶辉等
[8]将通量校正传输方法与正演模拟相结合,应用到弹性波方程正演模拟。均取得了较好的效果。2012 张省等
[9] 在VTI介质中将
通例交错网格与FCT技术相结合进行了数值模拟,有效压制了数值频散。2017 王婷等
[10]将通量传输校正技术与旋转交错网格相结合,实现了弹性波方程旋转交错网格高阶有限差分数值模拟,提高了数值模拟稳定性,并利用FCT技术有效压制了粗网格情况下造成的数值频散,提高了数值模拟精度。
基本理论
通量传输校正技术虽然能有效的压制数值频散,但存在较难选取合适参数的问题,从而影响校正效果。王婷等[10]将接纳改进后的FCT与旋转交错网格相结合,借助旋转交错网格来实现对弹性波方程的有限差分数值模拟,在增加少量计算机内存的情况下有效压制粗网格造成的数值频散。
FCT校正[9]是在假设所有的极值点都是由数值频散引起的前提下,对到场计算的所有网格点进行扩散通量校正处置惩罚,再对非局部极值点进行逆扩散通量校正来赔偿损耗。FCT旋转交错网格有限差分方法的实现分两个阶段:旋转交错网格有限差分阶段和通量校正阶段。通量校正阶段又分为两步:平滑方程的解和反漫射矫正。
其具体步调如下:
(1)用旋转交错网格有限差分格式表现弹性波颠簸方程。求解 n+1n+1 时刻和 nn时刻的速度分量。
首先建立应力-速度方程的旋转交错网格有限差分格式,进行计算得到 n+1n+1 时刻的速度分量 vxn+1(i,j),vzn+1(i,j)v_{x}^{n+1}(i, j),v_{z}^{n+1}(i, j) 和各应力分量 τxxn+1(i,j),τzzn+1(i,j),τxzn+1(i,j)\tau_{x x}^{n+1}(i, j),\tau_{zz}^{n+1}(i, j),\tau_{xz}^{n+1}(i, j) 的值。为了节省时间,提高计算效率,通量校正运算都是只针对速度分量 vx,vzv_{x},v_{z}进行计算,而无须校正应力分量,因为一旦速度分量被校正完毕,对应力分量的校正可通过弹性波方程来完成。
(2)以速度vxv_{x}为例,计算 nn 时刻的弥散通量 PP 和 QQ 。
以速度分量 vxn+1(i,j)v_{x}^{n+1}(i, j) 为例,计算 n−1n-1 时刻的漫射通量
,Pi+1/2,jn−1=η1((vx)i+1,jn−1−(vx)i,jn−1)Qi,j+1/2n−1=η1((vx)i,j+1n−1−(vx)i,jn−1),(1)\begin{aligned} P_{i+1 / 2, j}^{n-1} &=\eta_{1}\left((v_{x})_{i+1, j}^{n-1}-(v_{x})_{i, j}^{n-1}\right) \\ Q_{i, j+1 / 2}^{n-1} &=\eta_{1}\left((v_{x})_{i, j+1}^{n-1}-(v_{x})_{i, j}^{n-1}\right) \end{aligned},(1)
其中,参数 η1\eta_{1} 为漫射因子, 0⩽η⩽10 \leqslant \eta \leqslant 1 ,其巨细取决于有限差分阶段频散误差的巨细,可以通过简单数值实验来确定,它可以为一个常数,根据实际计算情况而差别。
(3)运用n+1n+1 时刻计算得到的弥散通量对所有网格点(包罗非局部极值点)上的速度 vxv_{x} 进行修正。
这一步是对波形进行平滑处置惩罚,在压制网格频散的同时,也会造成一定的振幅损失。
,(vx)i,jn~+1=(vx)i,jn+1+(Pi+1/2,jn−1−Pi−1/2,jn−1)+(Qi,j+1/2n−1−Qi,j−1/2n−1),(2)\begin{aligned}(v_{x})_{i, j}^{\tilde{n}+1} &=(v_{x})_{i, j}^{n+1}+\left(P_{i+1 / 2, j}^{n-1}-P_{i-1 / 2, j}^{n-1}\right) \\ &+\left(Q_{i, j+1 / 2}^{n-1}-Q_{i, j-1 / 2}^{n-1}\right) \end{aligned},(2)
(4)反弥散通量的计算
1)计算 k+1k+1 时刻的弥散通量 PP 和 QQ ;
,Pi+1/2,jn+1=η2((vx)i+1,jn+1−(vx)i,jn+1)Qi,j+1/2n+1=η2((vx)i,j+1n+1−(vx)i,jn+1),(3)\begin{aligned} P_{i+1 / 2, j}^{n+1} &=\eta_{2}\left((v_{x})_{i+1, j}^{n+1}-(v_{x})_{i, j}^{n+1}\right) \\ Q_{i, j+1 / 2}^{n+1} &=\eta_{2}\left((v_{x})_{i, j+1}^{n+1}-(v_{x})_{i, j}^{n+1}\right) \end{aligned},(3)
其中,参数 η2\eta_{2} 的选取与 η1\eta_{1} 类似,但其值要略大于 η1\eta_{1} ,这是因为反漫射运算不但要赔偿认为加入的漫反射的损失,还要赔偿传统有限差分运算带来的振幅损失。
2)计算散射后的 vxv_{x} 差别值,得到反漫射通量:
,Xi+1/2,j=(vx)i+1,jn~+1−(vx)i,jn~+1Zi,j+1/2=(vx)i,j+1n~+1−(vx)i,jn~+1,(4)\begin{aligned} X_{i+1 / 2, j} &=(v_{x})_{i+1, j}^{\tilde{n}+1}-(v_{x})_{i, j}^{\tilde{n}+1} \\ Z_{i, j+1 / 2} &=(v_{x})_{i, j+1}^{\tilde{n}+1}-(v_{x})_{i, j}^{\tilde{n}+1} \end{aligned},(4)
3)利用反漫射通量修正平滑解 (vx)i+1,jn~+1(v_{x})_{i+1, j}^{\tilde{n}+1} 即可得到消除数值频散后的正确波场值。
,(vx)i,jn+1=(vx)i,jm~+1+(Xi+1/2,jc−Xi−1/2,jc)+(Zi,j+1/2c−Zi,j−1/2c),(5)(v_{x})_{i, j}^{n+1}=(v_{x})_{i, j}^{\widetilde{m}+1}+\left(X_{i+1 / 2, j}^{c}-X_{i-1 / 2, j}^{c}\right)+\left(Z_{i, j+1 / 2}^{c}-Z_{i, j-1 / 2}^{c}\right),(5)
其中,
Xi+1/2,jc=sx1⋅max{0.0,min[sx1⋅Xi−1/2,j,abs(Pi+1/2,jn+1),sx1⋅Xi+3/2,j}\begin{aligned} X_{i+1/2, j}^{c} =s_{x}^{1} \cdot \max \left\{0.0,\min \left[s_{x}^{1} \cdot X_{i-1 / 2, j},\right.\right. \left.\operatorname{abs}\left(P_{i+1 / 2, j}^{n+1}\right) , s_{x}^{1} \cdot X_{i+3/2, j} \right\} \end{aligned}
,Zi,j+1/2C=sx2⋅max{0.0,min[sz2⋅Zi,j−1/2,abs(Qi+1/2,jn+1,sz2⋅Zi,j+3/2]}\begin{aligned} Z_{i, j+1 / 2}^{C} &=s_{x}^{2} \cdot \max \left\{0.0, \min \left[s_{z}^{2} \cdot Z_{i, j-1 / 2},\right.\right.\\ &\left.\operatorname{abs}\left(Q_{i+1 / 2, j}^{n+1}, s_{z}^{2} \cdot Z_{i, j+3 / 2}\right]\right\} \end{aligned}
sx1=sign(Pi+1/2,jn+1)sz2=sign(Qi,j+1/2n+1)\begin{aligned} s_{x}^{1} &=\operatorname{sign}\left(P_{i+1 / 2, j}^{n+1}\right) \\ s_{z}^{2} &=\operatorname{sign}\left(Q_{i, j+1 / 2}^{n+1}\right) \end{aligned}
反弥散通量的计算不是对所有的网格点进行处置惩罚,仅针对进行漫射通量校正前未产生频散的网格点(即非局部极值点),通过修正被平滑过的非局部极值点方程的解,恢复不需要进行漫反射位置(未产生数值频散位置)的真实波场。
步伐实现(MATLAB)
% FCT.m
% 参考步伐 wangzhi 2009.7.10 【Fortran】
% http://www.pudn.com/Download/item/id/2861815.html
functionOUTPUT =FCT(p_last,p_next,nz,nx,mu1,mu2)% p_last:上一时刻场分量值
% p_next:下一时刻场分量值
p_smoothing = zeros(nz,nx); % p_smoothing:平滑解
P_last = zeros(nz,nx); % 上一时刻漫射通量
Q_last = zeros(nz,nx);
P_next = zeros(nz,nx); % 下一时刻漫射通量
Q_next = zeros(nz,nx);
Z = zeros(nz,nx); % 反漫射通量
X = zeros(nz,nx); % 反漫射通量
fct_result = zeros(nz,nx);
sx0 = 0; sx1 = 0;
sz0 = 0; sz1 = 0;
Xc0 = 0; Xc1 = 0;
Zc0 = 0; Zc1 = 0;
% mu1 = 0.04; % 漫射因子
% mu2 = 0.05; % 反漫射因子
for i = 1:nz-1
for j = 1:nx-1
P_last(i,j) = mu1*(p1(i+1,j)-p1(i,j));
Q_last(i,j) = mu1*(p1(i,j+1)-p1(i,j));
P_next(i,j) = mu2*(p(i+1,j)-p(i,j));
Q_next(i,j) = mu2*(p(i,j+1)-p(i,j));
end
end
for i = 2:nz
for j = 2:nx
p_smoothing(i,j)=p_next(i,j)+(P_last(i,j)-P_last(i-1,j))+(Q_last(i,j)-Q_last(i,j-1));
end
end
for i = 1:nz-1
for j = 1:nx-1
X(i,j) = p_smoothing(i+1,j)-p_smoothing(i,j);
Z(i,j) = p_smoothing(i,j+1)-p_smoothing(i,j);
end
end
for i = 3:nz-2
for j = 3:nx-2
sx0 = mysign(P_next(i-1,j));
sx1 = mysign(P_next(i,j));
sz0 = mysign(Q_next(i-1,j));
sz1 = mysign(Q_next(i,j));
Xc0 = sx0*max(0,min([sx0*X(i-2,j) abs(P_next(i-1,j)) sx0*X(i,j)]));
Xc1 = sx1*max(0,min([sx1*X(i-1,j) abs(P_next(i,j)),sx1*X(i+1,j)]));
Zc0 = sz0*max(0,min([sz0*Z(i,j-2),abs(Q_next(i,j-1)),sz0*Z(i,j)]));
Zc1 = sz1*max(0,min([sz1*Z(i,j-1),abs(Q_next(i,j)),sz1*Z(i,j+1)]));
fct_result(i,j) = p_smoothing(i,j) - (Xc1 - Xc0) - (Zc1 - Zc0);
end
end
OUTPUT = fct_result;
end
步伐实现(C++)
// 参考步伐
// http://www.pudn.com/Download/item/id/3221579.html#include <math.h>#include <stdio.h>#include <stdlib.h>#define Xn 300
#define Zn 300
#define Tn 1000#define dt 0.0005
#define dh 8.0
#define N 6
#define R 0.001
#define pml 40
#define socx 150
#define socz 150#define y1 0.002 // 漫射因子
#define y2 0.0026 // 反漫射因子
void fct1(float *v_x,float *Pn1,float *Qn1)
{
int i,j;
for(i=1;i<Xn;i++)
{
for(j=0;j<Zn-1;j++)
{
Pn1[i*Zn+j]=y1*(v_x[i*Zn+j]-v_x[(i-1)*Zn+j]);
Qn1[i*Zn+j]=y1*(v_x[i*Zn+j+1]-v_x[i*Zn+j]);
}
}
void fct1z(float *v_z,float *Pn1z,float *Qn1z)
{
int i,j;
for(i=0;i<Xn-1;i++)
{
for(j=1;j<Zn;j++)
{
Pn1z[i*Zn+j]=y1*(v_z[(i+1)*Zn+j]-v_z[i*Zn+j]);
Qn1z[i*Zn+j]=y1*(v_z[i*Zn+j]-v_z[i*Zn+j-1]);
}
}
}
int sign(float tmp)
{
if(tmp>0)
return 1;
else if(tmp==0)
return 0;
else
return -1;
}
float max(float tmp)
{
if(tmp>0)
return tmp;
else
return 0.0;
}
float min(float tmp1,float tmp2,float tmp3,float tmp4,float tmp5)
{
float tmp6=0.0;
if(tmp1>tmp2)
tmp6=tmp2;
else
tmp6=tmp1;
if(tmp6>tmp3)
tmp6=tmp3;
if(tmp6>tmp4)
tmp6=tmp4;
if(tmp6>tmp5)
tmp6=tmp5;
return tmp6;
}
void fct2(float *v_x,float *Pn1,float *Qn1,float *Pn2,float *Qn2,float *X,float *Z,float *X1,float *Z1)
{
int i,j;
float *tmp1=(float *)malloc(sizeof(float)*Xn*Zn);
for(i=0;i<Xn*Zn;i++)
tmp1[i]=0.0;
for(i=1;i<Xn;i++)
for(j=0;j<Zn-1;j++)
{
Pn2[i*Zn+j]=y2*(v_x[i*Zn+j]-v_x[(i-1)*Zn+j]);
Qn2[i*Zn+j]=y2*(v_x[i*Zn+j+1]-v_x[i*Zn+j]);
}
for(i=0;i<Xn-1;i++)
for(j=1;j<Zn;j++)
{
tmp1[i*Zn+j]=v_x[i*Zn+j]+(Pn1[(i+1)*Zn+j]-Pn1[i*Zn+j])+(Qn1[i*Zn+j]-Qn1[i*Zn+j-1]);
}
for(i=1;i<Xn;i++)
for(j=0;j<Zn-1;j++)
{
X[i*Zn+j]=tmp1[i*Zn+j]-tmp1[(i-1)*Zn+j];
Z[i*Zn+j]=tmp1[i*Zn+j+1]-tmp1[i*Zn+j];
}
int tmp3=0,tmp4=0;
for(i=2;i<Xn-2;i++)
for(j=2;j<Zn-2;j++)
{
tmp3=sign(Pn2[i*Zn+j]);
tmp4=sign(Qn2[i*Zn+j]);
X1[i*Zn+j]=tmp3*max(min(tmp3*X[(i+1)*Zn+j],tmp3*X[(i+2)*Zn+j],tmp3*X[(i-1)*Zn+j],tmp3*X[(i-2)*Zn+j],abs(Pn2[i*Zn+j])));
Z1[i*Zn+j]=tmp4*max(min(tmp4*Z[i*Zn+j+1],tmp4*Z[i*Zn+j+2],tmp4*Z[i*Zn+j-1],tmp4*Z[i*Zn+j-2],abs(Qn2[i*Zn+j])));
}
for(i=0;i<Xn-1;i++)
for(j=1;j<Zn;j++)
{
v_x[i*Zn+j]=tmp1[i*Zn+j]+(X1[(i+1)*Zn+j]-X1[i*Zn+j])+(Z1[i*Zn+j]-Z1[i*Zn+j-1]);
}
free(tmp1);
}
void fct2z(float *v_z,float *Pn1z,float *Qn1z,float *Pn2z,float *Qn2z,float *Xz,float *Zz,float *X1z,float *Z1z)
{
int i,j;
float *tmp1=(float *)malloc(sizeof(float)*Xn*Zn);
for(i=0;i<Xn*Zn;i++)
tmp1[i]=0.0;
for(i=0;i<Xn-1;i++)
for(j=1;j<Zn;j++)
{
Pn2z[i*Zn+j]=y2*(v_z[(i+1)*Zn+j]-v_z[i*Zn+j]);
Qn2z[i*Zn+j]=y2*(v_z[i*Zn+j]-v_z[i*Zn+j-1]);
}
for(i=1;i<Xn;i++)
for(j=0;j<Zn-1;j++)
{
tmp1[i*Zn+j]=v_z[i*Zn+j]+(Pn1z[i*Zn+j]-Pn1z[(i-1)*Zn+j])+(Qn1z[i*Zn+j+1]-Qn1z[i*Zn+j]);
}
for(i=0;i<Xn-1;i++)
for(j=1;j<Zn;j++)
{
Xz[i*Zn+j]=tmp1[(i+1)*Zn+j]-tmp1[i*Zn+j];
Zz[i*Zn+j]=tmp1[i*Zn+j]-tmp1[i*Zn+j-1];
}
int tmp3=0,tmp4=0;
for(i=2;i<Xn-2;i++)
for(j=2;j<Zn-2;j++)
{
tmp3=sign(Pn2z[i*Zn+j]);
tmp4=sign(Qn2z[i*Zn+j]);
X1z[i*Zn+j]=tmp3*max(min(tmp3*Xz[(i+1)*Zn+j],tmp3*Xz[(i+2)*Zn+j],tmp3*Xz[(i-1)*Zn+j],tmp3*Xz[(i-2)*Zn+j],abs(Pn2z[i*Zn+j])));
Z1z[i*Zn+j]=tmp4*max(min(tmp4*Zz[i*Zn+j+1],tmp4*Zz[i*Zn+j+2],tmp4*Zz[i*Zn+j-1],tmp4*Zz[i*Zn+j-2],abs(Qn2z[i*Zn+j])));
}
for(i=1;i<Xn;i++)
for(j=0;j<Zn-1;j++)
{
v_z[i*Zn+j]=tmp1[i*Zn+j]+(X1z[i*Zn+j]-X1z[(i-1)*Zn+j])+(Z1z[i*Zn+j+1]-Z1z[i*Zn+j]);
}
free(tmp1);
}
}
当空间采样变得很粗时,FCT方法无法完全恢复数值频散造成的分辨率损失(Fei and Larner, 1995; Yang et al., 2002)
参考
^Alford R,Kelly K and Boore D. Accuracy of finite-difference modelling of the acoustic wave equation.Geophysics,1974,39(6):834-842.^Kelly K,Ward K,Treitel R and Alford R.Synthetic seismograms:A finite-difference approach.Geophysics,1976,41(1):2~27.^Dablain M A. The application of high-order differencing to the scalar wave equation. Geophysics, 1986,51(1):54~66.^王才经.颠簸方程模拟和偏移的频散分析.计算地球物理研究文集,1990,33:521~528.^Boris J P and Book D L. Flux-corrected transport, I. SHASTA, A fluid transport algorithm that works. J Comput Phys, 1973,11:38~69^Book D L. Boris J P and Hain K. Flux-corrected transport II, generalization of the method. J Comput Phys, 1975,18,248~283^Book D L,Boris J P,Hain K.Flux-corrected transport II:Generalizations of the method[J].Journal of Computational Physics,1975(18): 248-283.^杨顶辉,滕吉文.各向异性介质中三分量地震记录的FCT有限差分模拟[J].石油地球物理勘探,1997(02):181-190+304.^ab张省,何兵寿,王玉凤.VTI介质交错网格FCT有限差分数值模拟[J].工程地球物理学报,2012(5):565-571.^ab王婷,段焱文,蔡伟祥,易院平,汪勇.基于旋转交错网格和FCT技术的高精度数值模拟[J].中国锰业,2017,35(06):157-163.