0%

wavenumber的模拟计算(二)

上一篇使用了MATLAB模拟二维波动网格,使用GMT做谱分析和绘图。本文进一步简化模拟代码,仅使用GMT一种语言可完成波数谱的模拟,并展示一维和二维波数谱的差异。

GMT有几种计算波数谱的程序

GMT有spectrum1D和grdfft可以计算波数谱。

  • spectrum1D:一维谱分析。
  • grdfft:二维谱分析,含x,y和径向三个方向的计算。

模拟代码

下面利用完全GMT工具进行波数谱的模拟,首先利用grdmath模拟出一个规范的正弦波二维矩阵,形成网格文件。然后使用grdfft计算三个方向的谱,使用spectrum1D计算X方向的一维波数谱。

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
#!/usr/bin/env bash
ps=testgrd.ps

# gmt grdmath -R-50/50/-50/50 -I0.2 X Y ADD SIN = x.nc
gmt grdmath -R-50/50/-50/50 -I0.2 X SIN = x.nc

gmt makecpt -Crainbow -T-1/1/0.1 > t.cpt
gmt grdimage x.nc -R-30/30/-30/30 -JX3i -Ct.cpt -Bxa -Bya -BWSne -P -K -Y7i > $ps

gmt grd2xyz x.nc | awk '{if ($2 == 0) print $0}' > x.txt
gmt psxy -R -J -O -K x.txt -Sc0.03i -Gblack >> $ps
# Do grdfft
gmt grdfft x.nc -Er+w+n -Gfft.txt
gmt grdfft x.nc -Ex+w+n -Gfftx.txt
gmt grdfft x.nc -Ey+w+n -Gffty.txt
gmt math fftx.txt -C1 SQR ffty.txt SQR ADD SQRT = fftrr.txt

# Plot specrum result from grdfft
gmt psbasemap -R1/20/1e-14/1e-2 -JX-2.8il/3il -Bxa1pf2g3+l"Wavelength" -Bya1pg+l"power spectrum" -BwNsE -K -X3.2i -O >> $ps
gmt psxy -R fft.txt -J -W0.5p,red, -O -K >> $ps
gmt psxy -R fftx.txt -J -W0.5p,blue, -O -K >> $ps
gmt psxy -R ffty.txt -J -W0.5p,green, -O -K >> $ps
gmt psxy -R fftrr.txt -J -W0.5p,black, -O -K >> $ps

gmt psbasemap -R0.05/1e0/1e-14/1e-2 -JX2.8il/3il -BSE -Bxa1p+l"wavenumber/cycle" -O -K>> $ps

gmt pslegend -D+w1.2i+jBL+o0.1i/0.1i -R -J -O -K -F+p1p+glightgray --FONT_ANNOT_PRIMARY=10p,1,black << EOF >> $ps
S 0.2i - 0.5i - 1p,red, 0.5i r
S 0.2i - 0.5i - 1p,blue 0.5i x
S 0.2i - 0.5i - 1p,green, 0.5i y
EOF

# Do spectrum1D
gmt psxy -R-30/30/-1/1 -JX3i/3i x.txt -i0,2 -Bxaf -Byaf -BWSne -O -K -X-3.2i -Y-4.5i >> $ps
gmt psxy -R -J x.txt -i0,2 -Sc0.03i -Gred -O -K >> $ps

awk '{print $1,$3}' x.txt | gmt spectrum1d -S256 -W --GMT_FFT=brenner -N -i1 -D0.2 > fft_spec.txt
gmt psbasemap -R1/20/1e-12/1e2 -JX-2.8il/3il -Bxa1pf2g3+l"Wavelength" -Bya1pg+l"power spectrum" -BwNsE -K -X3.2i -O >> $ps
gmt psxy -R fft_spec.txt -J -W0.5p,red, -O -K >> $ps
gmt psbasemap -R0.05/1e0/1e-12/1e2 -JX2.8il/3il -BSE -Bxa1p+l"wavenumber/cycle" -O >> $ps

awk '{print $3}' x.txt| gmt gmtmath STDIN -Sl STD SQR =

gmt psconvert $ps -P -Tg -A

结果

z=sin(x)

上为二维FFT在三个方向的谱分析结果,黑色曲线为sqrt(x^2+y^2),径向的能量谱不与一维的平方和(开根号)相等。下为一维(彩图中横线的采样)谱分析结果(形状与二维FFT的X方向一致,但能量大小不一样)。

z=sin(x+y)

上图把函数改变,数据x和y方向周期依然是2pi,但是r方向是2pi*cos(pi/2),即4.44。这样可以帮助理解r方向是什么方向。运行时,把下面的代码取消注释。

1
# gmt grdmath -R-50/50/-50/50 -I0.2 X Y ADD SIN = x.nc

注意的问题

  • spectrum1D得到的波数谱符合能量守恒定律,即输入信号的方差等于功率谱密度的积分,也就是谱和X轴围起来的面积。例如正弦波的方差为0.5,而功率密度的积分也恰好为0.5。
  • grdfft得到的波数谱不是密度谱,所以不遵循能量守恒。
  • grdfft的三个方向的谱的关系是什么?r^2=x^2+y^2?

参考

wavenumber的模拟计算