用法

代码中包含了如下几个重要的命令/脚本:

  • fk:用于计算格林函数的主程序;

  • st_fk:用于计算静态格林函数的主程序;

  • trav:用于计算 P、S 初至到时的辅助程序;

  • sachd:用于修改 SAC 头段的辅助程序;

  • fk.pl:对 fkst_fktravsachd 的封装,一般情况下直接使用 fk.pl 脚本即可;

  • syn:用于将格林函数合成为理论地震图三分量的程序;

  • fk2mt:将FK生成的格林函数转换为另一种Moment Tensor格式的格林函数,即Moment Tensor的每个分量分别对应3个格林函数;

因而,实际操作的时候,只需要调用 fk.pl 生成格林函数,再调用 syn 将格林函数合成为三分量地震图即可。

基础原理

这里不涉及算法的细节,只介绍一些基础的东西。

根据 Zhu and Rivera (2002),在定义了柱坐标系之后,位移可以表示为:

公式中涉及到了一个求和与两个积分:

  • 对频率的积分,本质上就是一个反傅里叶变换,技术上很成熟了,可以不管

  • 对 m 的求和,其实是对方位角模数的求和,理论上是要从零求和到无穷的。但是由于震源的简单性,只需要对几项做求和即可,具体的求和数目由震源类型决定:

    • 爆炸源:m=0

    • 单力源:m=0, 1

    • 双力偶:m=0, 1, 2

  • 对 k 的积分是一个难点,只能进行数值积分,由于积分核 \(U_z R_m^k + U_r S_m^k + U_{\theta} T_m^k\) 比较复杂,在做数值积分的时候就需要更多的考虑。

积分核 \(U_z R_m^k + U_r S_m^k + U_{\theta} T_m^k\) 中 R、S、T 是柱坐标下的基矢量,由一堆 Bessel 函数组成,已知。该算法中的一大堆数学推导以及细节都是为了求出 Uz、Ur 和 Ut。具体 Uz、Ur 和 Ut 怎么求,不是本文的重点,需要了解的只能自己推公式。

参数说明

先把用法贴在这里作为参考:

fk.pl -Mmodel/depth[/f_or_k] [-D] [-Hf1/f2] [-Nnt/dt/smth/dk/taper]
    [-Ppmin/pmax[/kmax]] [-Rrdep] [-SsrcType] [-Uupdn] [-Xcmd] distances

速度模型

-Mmodel/depth/k_or_f 中的 model 为模型文件名, kf 的作用在下面会解释。

格式

fk 的输入速度模型是一维水平分层速度模型,其格式为:

thickness vs vp/vs [rho Qs Qp]

或:

thickness vs vp [rho Qs Qp]

其中

  • 列 1:该层的厚度(km) 注意是厚度不是深度

  • 列 2:S 波速度(km/s)

  • 列 3:波速比或 P 波速度

  • 列 4:密度( \(g/cm^3\)

  • 列 5:S 波的 Q 值

  • 列 6:P 波的 Q 值

其中前三列是必须的,若未指定密度,则使用经验公式 rho=0.77+0.32*vp;若未指定 Qs,则取 Qs=500;若未指定 Qp,则取 Qp=2*Qs。

关于 k 和 f

  • 若命令行中使用 -Mmodel/depth ,则表示输入模型为第二种格式;

  • 若命令行中使用 -Mmodel/depth/k,则表示输入模型使用第一种格式,即第三列是波速比;

  • 若命令行中使用 -Mmodel/depth/f,则表示需要对速度模型做展平变换,当震中距较大时需要这样做;

备注

  • fk.pl 的输入模型是先 Vs 再 Vp,而 fk.pl 在调用 fk 时使用的模型是先 Vp 后 Vs,注意不要搞混;

  • 若第一层的厚度为零,则该行指定了上半空间的参数;

  • 若第一层的厚度不为零,则上半空间为真空,该层给出了地表下方第一层的参数;

  • 最后一层会被自动当做下半无限半空间,并修改其厚度为 0;

  • 对于液态层(如海水和外核):

    • S 波速度可以用零表示,程序中用自动用 0.0001 替换零值;

    • Qs 值不可以取为零,应取某小值;

震源

震源深度

震源深度由 -Mmodel/depth/[f_or_k] 中的 depth 指定,单位为 km。

需要注意,震源深度不能位于速度模型的分界面上,即震源的深度必须位于模型某层的内部。fk 在做展平变换时,震源和速度模型的分界面的深度所用的转换公式不同,所以,当使用了展平变换,即便震源深度和界面深度相同,程序也不会报错。这一点实际使用时要注意(尽管没有报错,也不能让震源在界面上)。

大多数计算理论地震图的方法都会有这样的限制,因为在计算过程中会用到震源所在层的速度或密度,若震源位于速度模型的分界面上,则会出现参数的间断。

震源类型

fk 中用 -SsrcType 指定震源类型,其中 srcType 可以取如下三个值:

  • 0:爆炸源;

  • 1:单力源;

  • 2:双力偶源;

台站

台站深度

-Rrdeprdep 用于设置 receiver 的深度(单位为 km),默认值为零,即台站位于地表。

需要注意,fk 中要求震源和台站不能位于同一深度。代码中,会计算震源和台站之间的深度差 hs,并将其作为分母。但这一限制的本质原因尚不清楚。

台站震中距

fk.pl 命令行中可以指定多个震中距,震中距的默认单位为 km。

当震中距较大时,以 km 做单位很不方便,此时可以使用 -D 选项,表明震中距的单位为度。同时,由于震中距比较大,此时可能还需要对速度模型做展平变换。震中距可以是 0。

时间序列

说说 -Nnt/dt/smth/dk/taper 中的 nt、dt 和 smth。

采样间隔

dt 即生成的格林函数的采样间隔。与此同时,dt 决定了 fk 要计算的最高频率,其公式为

\[f_{max} = \frac{1}{2 dt}\]

即 fk 生成的格林函数的最高频率是由 dt 决定的 Nyquist 采样率。

因而,一般来说,要首先根据自己的实际需求,确定所需要的最高频率,进而决定 dt

数据点数

nt 即数据点数,nt 的选择有一些需要注意的地方:

  • nt 必须为 2 的 n 次方,即可以取 1、2、256、512、1024 等。程序中限制了 nt*smth 不得超过 8192。若想要突破数据点数的限制,可以增大源码 model.hnt=8192 的值。

    • nt=1,则调用 st_fk 直接计算静态位移解;

    • nt=2,则调用 fk 计算零频位移,等效于静态位移解;

    • nt 必须为 2 的 n 次方是因为在 FFT 时数据点为 2 的 n 次方时有快速算法;

  • \(T=nt*dt\) 确定了最终数据的总长度

smooth 因子

由于 dt 决定了 fk 计算的最高频率,所以 dt 是不能随便取的。比如需要最高频率为 2.5Hz,则 dt 应取 0.2s,但是若希望最终生成的数据的采样间隔为 0.05s,则需要 smth 这个参数。

在程序中,smth 做了两件事情:

  1. 将 dt 除以 smth;

  2. 将总数据点数乘以 smth;

总的效果应该相当于对计算结果做了一个插值,这也可以通过 SAC 的插值命令来完成。在程序实现时,实际上就是在反傅里叶变换之前,给数据的高频部分补上更多的零值。

同样由于快速傅里叶算法的限制, smth 也必须取 2 的 n 次方。

频率

最高频率

前面已经说到,fk 所计算的最高频率由 dt 决定:

\[f_{max} = \frac{1}{2 dt}\]

频率间隔

频率域的采样间隔(分辨率)为 \(df=\frac{1}{T}=\frac{1}{nt*dt}\)

高通滤波

fk 会从零频开始,以 df 为频率间隔,一直到最高频率 fmax,计算每个离散频率处的值。

比如,给定参数 dt=0.1,npts=1024,则 fk 计算的最高频率为 5 Hz,频率间隔 df 约等于 0.01Hz。因而 fk 会计算 0 Hz、0.01 Hz、0.02 Hz 一直到 5 Hz 的值,共计循环 512 次。

有些情况下,比较低频的信息是没有用的,所以可以不必计算,这样循环可以进一步减小,以加速计算。

-Hf1/f2 中, f1 限定了循环过程中频率的下限,即对频率的循环会从 f1 开始计算到 fmax 而不是从零开始,这本质上是一个高通滤波器。

这样一来,fk 会计算频率在 f1 和 fmax 之间的值,对于小于 f1 以及大于 fmax 的频率段,其值直接设为零。这实际上是在频率域直接截断,似乎会出现一些问题,所以一般都会对频率的两端做尖灭处理,即 f2 和 taper。程序会在 f1 和 f2 之间以及 (1-taper)*fmax 和 fmax 之间分别加上余弦窗。

taper 的默认值为 0.3,所以当 dt=0.1s 时,fmax=5Hz,则在 3.5Hz 到 5Hz 之间会加上余弦窗,此时数据的频段上限是 5Hz 还是 3.5Hz 呢?这是个疑问。

k 积分

k 是什么

这里的 k 不是波数,而是水平波数:

\[k = k_x = \vec{k}\cdot \vec{x} = \frac{\omega}{v} \sin \theta = \omega p\]

其中, \(\theta\) 是射线与垂直方向的夹角, \(p=\frac{\sin \theta}{v}\) 是水平慢度,也就是射线参数。

下限和上限

-Ppmin/pmax[/kmax] 可以限定 k 积分的上下限。其中 pmin 确定了 k 积分的下限:

\[k_{min} = \omega pmin\]

pmaxkmax 决定了 k 积分的上限:

\[k_{max} = \sqrt{kmax^2+\omega pmax}\]

说明:

  1. pmin 和 pmax 的取值范围是 0 到 1,代码中会将 pmin 和 pmax 都除以震源处的 S 波速度。

  2. 程序中 kmax=kmax/hs,其中 hs 是震源与台站的深度差;由于积分核在零频处以 exp(-k*hs) 的速度随着 k 衰减,因而要求 kmax>10,以保证求和足够多。

  3. 指定了 pmin 和 pmax,就相当于指定了射线参数的范围,或射线出射角度的范围,似乎可以用于筛选中特定射线参数范围的射线;

  4. 为什么 pmin 和 pmax 在程序中都要除以 S 波速度呢?这样当给定 \(pmin=\sin 30=0.5\) 时,以 30 度角出射的 S 波会被计算,而以 30 度角出射的 P 波则不会被计算?这样对吗?

  5. pmin 和 pmax 的取值为 0 到 1,为什么不是 - 1 到 1?也许正负号是由 updn 决定的。

上行和下行

-Uupdn 选项可以指定是计算全波场还是只计算上行波或下行波。updn 可以取值如下:

  • 0:计算全波场;也是默认值;

  • 1:仅计算下传波场;

  • -1:仅计算上传波场;

该参数取不同的值,会影响到程序内部的一些公式。具体的原理可能需要推公式才能理解。

dk

dk 用于控制 k 积分的积分间隔。程序中 \(dk=dk*PI/max(x,hs)\),其中 hs 为震源与台站的深度差, x 为震中距,因而 k 积分间隔实际上是与要计算的最大震中距有关的。

由于积分核中 J(kx) 在大震中距时按 2pi/x 的周期震荡,因而要求 dk 小于 0.5,以保证每个周期内至少有四个采样点。官方建议取值为 0.1 到 0.4。dk 理论上越小越好,当然 dk 越小计算就会越慢。

振幅压制

这个参数在 fk.pl 脚本内部可以修改,但是在命令行里没法修改。

对于实序列 \(f(t)\) ,其傅里叶变换为:

\[F(\omega) = \int f(t) e^{-i\omega t} dt\]

若将该实序列 f(t) 乘以 \(e^{-\sigma t/T}\),即 \(g(t)=f(t)e^{-\sigma t/T}\) 的傅里叶变换为:

\[G(\omega) = \int g(t) e^{-i\omega t} dt = \int f(t) e^{-\sigma t/T} e^{-i\omega t} dt = \int f(t) e^{-i(\omega-i\sigma/T)} dt = F(\omega-i\sigma/T)\]

因而,在频率域将 \(\omega\) 减去 \(i\sigma/T\) ,相当于对实序列乘以 \(e^{-\sigma t/T}\)

其中 T 为实序列的总时间长度,sigma 称为压制因子,用于降低数据尾部的振幅值,而最终反傅里叶变换得到的实序列,会再次乘以 \(e^{+\sigma t/T}\),以消除压制因子对振幅的影响。所以,理论上看,sigma 没什么实际用途,这样处理的具体目的还不清楚,似乎是出于频率域的稳定性考虑的。

DEBUG

fk 提供了 -X 选项用于 debug,最常见的用法是 -Xcat,此时 fk.pl 中 cmd 被替换成 cat 命令,即将所有的输入都传递给 cat 命令,这样可以很清楚地知道要传递的数据是否正确,方便 debug。

格林函数

fk 将生成的格林函数以 SAC 格式写到磁盘中。

爆炸源

生成三个分量,命名为 xxxx.grn.[a-c] ,分别是 Z、R、T 向的格林函数。其单位为 10^-20 cm/(dyne cm)

单力源

生成六个分量,其中:

  • xxxx.grn.[0-2]:m=0 对应的 ZRT 格林函数,等效于 垂直向上 的单位单力产生的位移三分量;

  • xxxx.grn.[3-6]:m=1 对应的 ZRT 格林函数,等效于水平单力产生的位移三分量;

格林函数的单位为 10^-15 cm/dyne

双力偶

生成九个分量,其中

  • xxx.grn.[0-2]:m=0 阶源生成的 ZRT 格林函数,相当于 45-down-dip(DD) 双力偶源在 45 度方位角处产生的位移,并乘以(-2,-2,0)

  • xxx.grn.[3-5]:m=1 阶源生成的 ZRT 格林函数,相当于 vertical dip-slip(DS) 双力偶源在 45 度方位角处产生的位移,并乘以 \(-\sqrt 2\)

  • xxx.grn.[6-8]:m=2 阶源生成的 ZRT 格林函数,相当于 vertical strike-slip(SS) 双力偶源在 22.5 度方位角处产生的位移,并乘以 \(-\sqrt 2\)

格林函数的单位为 10^-20 cm/(dyne cm)

说明

在大多数教程以及文献中,任意一个双力偶源可以表示为三个基本断层的线性迭加。这三个基本断层分别为 DD、DS 和 SS。有些计算格林函数的代码会计算出三种基本断层的位移解,然后根据文献中给出的辐射花样系数进行合成。而 fk 计算出的是 m=0、1、2 时的位移解,虽然这三者分别与 DD、DS、SS 在某个特定方位角的位移解有关系。因而在对 fk 生成的格林函数进行合成时,有专门的辐射花样系数,参见 Zhu and Rivera(2002) 的附录 B10-B12。

syn 用法说明

fk.pl 只是算出了格林函数, syn 的作用在于将格林函数组合起来得到RTZ三个方向的理论地震图。

syn 的用法相对比较简单,此处作简单介绍:

  • -M 选项指定震源机制信息,有四种用法:

    • 对于爆炸源:-Mmag 其中 mag 的单位是 dyne-cm

    • 对于单力源:-Mmag/strike/dip 其中 mag 的单位是 dyne,dip为力的方向相对于水平方向的夹角

      • dip=0: 水平单力

      • dip=90: 垂直向下单力

      • dip=-90: 垂直向上单力

    • 对于双力偶源: -Mmag/strike/dip/rake 其中 mag 是矩震级Mw,strike/dip/rake 的定义参照 Aki&Richards(1980)

    • 对于地震矩源: -Mmag/Mxx/Mxy/Mxz/Myy/Myz/Mzz 其中 mag 的单位是 dyne-cm。此处有大坑,见后面的详细说明。

  • -Aazimuth 选项指定台站方位角,定义为相对于北方向顺时针旋转的角度

  • -Ddura/rise 指定一个梯形作为震源时间函数。其中 dura 是梯形震源时间函数的总持续时间,rise 代表了梯形中上升段所占据的时间比例,取值范围为0到0.5,若取值为0.5,则梯形退化为三角形

  • -SsrcFunctionName 除了使用 -D 选项之外,也可以使用将一个SAC文件作为震源时间函数。-S 选项后直接跟SAC文件名。

    用SAC文件作为震源时间函数时需要注意两点:

    1. SAC文件的采样间隔要与格林函数的采样间隔相等。如果不等也没关系,但要注意 syn 是直接把数据点卷积格林函数的,并没有考虑采样间隔的问题,因而若采样间隔不等可能会一些易忽略的错误;

    2. 严格的震源时间函数应该满足积分之后最大值等于1,只有这种情况下,震级或震源强度的定义才是准确的。当然,若无需考虑绝对振幅是否正确的问题,震源时间函数可以不满足这一要求。

  • -Ff1/f2/n 对理论地震图进行滤波

  • -GFirstCompOfGreen 指定第一个FK格林函数的文件名

  • -TFirstCompOfGreen 指定第一个MT格林函数的文件名。MT格林函数是指矩张量的每个分量所对应的格林函数,共计6*3=18个。程序 fk2mt 可以将FK生成的FK格林函数转换为这里所需的MT格林函数

  • 其他选项都很简单,就不介绍了

关于地震矩源 -Mmag/Mxx/Mxy/Mxz/Myy/Myz/Mzz,需要注意:

  1. 此处x=North、y=East、z=Down,即地震矩张量使用的是NED坐标系

  2. GCMT网站上给出的地震矩张量是RTP坐标系,二者之间的转换公式见 Aki&Richards(1980)P117 Box4.4

  3. GCMT网站中地震矩张量的6个分量的顺序是 Mrr Mtt Mpp Mrt Mrp Mtp,而本程序中的顺序是 Mxx Mxy Mxz Myy Myz Mzz,因而若使用GCMT的震源机制解,则需要对6个分量进行坐标转换并修改其先后顺序

输出类型

fk 计算得到的格林函数究竟是什么物理量呢?是位移还是速度?

在 Zhu and Rivera(2002) 的文章中、代码中的注释以及说明文档等多个地方都提到 fk 计算出的是位移量,而实际上利用 fksyn 计算出来的合成地震图是速度场。

Zhu and Rivera(2002) 的附录 B 中给出了不同震源类型以及不同 m 值所对应的 source term,这里的 source term 代表了震源引起的位移-应力不连续。source term 是一个与频率无关的常数,所以 fk 中所使用的 source term 在时间域上的脉冲源。(时间域上的脉冲函数,在频率域是一个常数,所以 fk 中在频率域加了一个常数的 source term,实际上相当于在时间域上加上脉冲源。)

因而,fk 实际上计算的是脉冲源对应的位移场,其等效于阶跃函数所产生的速度场。(阶跃函数的偏导即脉冲函数。)

对于一个真实的小震级的简单地震而言,其震源时间函数可以认为是一个阶跃函数,震源时间函数的偏导就是脉冲函数。因而 fk 计算出的格林函数实际上是速度场,在使用 syn 合成真实数据时,如果使用 -D 选项指定了一个三角震源函数(近似的脉冲函数),得到的合成数据都是速度场。

其他说明

  1. 对于 PREM 模型,震源深度取 15km,震中距为 5 度,做不做展平变换,震相的走时差大概在 0.8s 左右

  2. 将 PREM 模型离散成每层 20km 或 50km,计算出的结果差异不大

  3. 若台站深度大于震源深度,则会对模型做翻转,程序中的部分参数乘以 - 1;

  4. fk.f 中输入的 src_layer 表示震源位于第 src_layer 层的顶部, rcv_layer 同理;而 travsrc_layer 表示震源位于第 src_layer 的底部;

  5. 输出的格林函数文件中 xxx.grn.0xxx.grn.5 会包含 P 波和 S 波的到时。如果 syn 合成的是 Double Couple,则合成的理论地震图里会包含 P 波和 S 波的到时。如果 syn 合成的是 ISO,则合成的理论地震图里没有到时。

疑问

  1. 在考虑衰减时,Aki and Richard(1980)的公式 (5.88) 中给出的公式中虚数前为负号,而 fk 代码中为正号。Why?

  2. 如何从数学或物理上详细解释 sigma 的含义?