接上一篇:杨超:fft海面模拟(二)

视频封面

00:15视频封面

00:13

本篇说如何用IFFT计算海面IDFT模型。

将海面IDFT模型

h(vec{x},t)=sum_{vec{k}}	ilde{h}(vec{k},t)e^{ivec k cdot vec x}

写成标量形式:

h(x,z,t)=sum_{m=-frac{N}{2}}^{frac{N}{2}-1}sum_{n=-frac{N}{2}}^{frac{N}{2}-1}	ilde{h}(k_x,k_z,t)e^{i(k_xx+k_zz)}

接下来将 kx和kz展开,因为:

k_x=frac{2 pi n}{L}, nin{{-frac{N}{2},-frac{N}{2}+1,...,frac{N}{2}-1}}

k_z=frac{2 pi m}{L}, min{{-frac{N}{2},-frac{N}{2}+1,...,frac{N}{2}-1}}

故:

h(x,z,t)=sum_{m=-frac{N}{2}}^{frac{N}{2}-1}sum_{n=-frac{N}{2}}^{frac{N}{2}-1}	ilde{h}(frac{2 pi n}{L},frac{2pi m}{L},t)e^{i(frac{2pi n}{L}x+frac{2 pi m}{L}z)}

为使下标从0开始,令m=m+N/2,n=n+N/2,则 m,nin{{0,1,..,N-1}} 。得:

h(x,z,t)=sum_{m=0}^{N-1}sum_{n=0}^{N-1}	ilde{h}(frac{2 pi (n-frac{N}{2})}{L},frac{2pi (m-frac{N}{2})}{L},t)e^{i(frac{2pi (n-frac{N}{2})}{L}x+frac{2 pi (m-frac{N}{2})}{L}z)}

	ilde{h}(n,m,t)=	ilde{h}(frac{2 pi (n-frac{N}{2})}{L},frac{2pi (m-frac{N}{2})}{L},t),并将 e^{ifrac{2pi(m-frac{N}{2})z}{L}} 由内层求和号中提出,得:

h(x,z,t)=sum_{m=0}^{N-1}e^{ifrac{2pi(m-frac{N}{2})z}{L}}sum_{n=0}^{N-1}	ilde{h}(n,m,t)e^{ifrac{2 pi(n-frac{N}{2})x}{L}}

上式可拆成:

h(x,z,t)=sum_{m=0}^{N-1}h(x,m,t)e^{ifrac{2pi(m-frac{N}{2})z}{L}}

	ilde h(x,m,t)=sum_{n=0}^{N-1}	ilde{h}(n,m,t)e^{ifrac{2 pi(n-frac{N}{2})x}{L}}

由于L长度可随意选取,为向IDFT形式靠拢,取L=N,得:

h(x,z,t)=(-1)^zsum_{m=0}^{N-1}	ilde h(x,m,t)e^{ifrac{2pi mz}{N}} ...(a)

	ilde h(x,m,t)=(-1)^xsum_{n=0}^{N-1}	ilde{h}(n,m,t)e^{ifrac{2 pi nx}{N}} ...(b)

接下来把x和z展开。因为:

x=frac{uL}{N},u in{{-frac{N}{2},-frac{N}{2}+1,...,frac{N}{2}-1}}

z=frac{vL}{N},v in{{-frac{N}{2},-frac{N}{2}+1,...,frac{N}{2}-1}}

又因为L=N,且为使下标变为从零开始,令u=u+N/2,v=v+N/2,得:

x=u-frac{N}{2},u in{{0,1,...,N-1}}

z=v-frac{N}{2},v in{{0,1,...,N-1}}

代入(a)、(b)得:

h(u-frac{N}{2},v-frac{N}{2},t)=(-1)^{v-frac{N}{2}}sum_{m=0}^{N-1}	ilde h(u-frac{N}{2},m,t)e^{ifrac{2pi mv}{N}}(-1)^{m} ...(c)

	ilde h(u-frac{N}{2},m,t)=(-1)^{u-frac{N}{2}}sum_{n=0}^{N-1}	ilde{h}(n,m,t)e^{ifrac{2 pi nu}{N}}(-1)^{n} ...(d)

令:

A(u,v,t)=h(u-frac{N}{2},v-frac{N}{2},t)/(-1)^{v-frac{N}{2}}

B(u,m,t)=	ilde h(u-frac{N}{2},m,t)(-1)^{m}

C(u,m,t)=	ilde{h}(u-frac{N}{2},m,t)/(-1)^{u-frac{N}{2}}

D(n,m,t)=	ilde{h}(n,m,t)(-1)^{n}

则(c)、(d)变为:

A(u,v,t)=sum_{m=0}^{N-1}B(u,m,t)e^{ifrac{2pi mv}{N}} ...(1)

C(u,m,t)=sum_{n=0}^{N-1}D(n,m,t)e^{ifrac{2 pi nu}{N}} ...(2)

至此,已化成非归一化的IDFT形式,可以套用IFFT了!

总结起来海面IFFT计算流程如下:

1,根据菲利普频谱公式得到各 	ilde{h}(k_x,k_z,t) 。(参见:杨超:fft海面模拟(一))。

2,根据 	ilde{h}(n,m,t)=	ilde{h}(k_x,k_z,t)得到各 	ilde{h}(n,m,t)

3,根据 D(n,m,t)=	ilde{h}(n,m,t)(-1)^{n} 得到各 D(n,m,t) 。(符号校正1)。

4,根据(2)式计算行IFFT,得到各 C(u,m,t)

5,根据 B(u,m,t)=C(u,m,t)(-1)^{m+u-frac{N}{2}} 得到各 B(u,m,t) 。(符号校正2)。

6,根据(1)式计算列IFFT,得到各 A(u,v,t)

7,根据 h(x,z,t)=A(u,v,t)(-1)^{v-frac{N}{2}} 得到各 h(x,z,t) 。(符号校正3)。

8,结束。

可见,计算量主要集中在1,4,6步,其余步骤均为简单转换。

以N=4为例:

假设1,2,3步已执行完,而后便是核心的计算行、列IFFT步骤(4~6步),图示如下:

图中IFFT(1)表示式(1)对应的IFFT,IFFT(2)表示式(2)对应的IFFT。

可见总共需要计算8个4 point IFFT。(一般情况需要计算2N个N point IFFT)。

最后再执行步骤7得到各h(x,z,t)即可。

如果是gpu实现,则那4个IFFT(2)可以并行,4个IFFT(1)也可以并行。故一般情况下gpu实现只相当于计算2个N point IFFT的量。飞起。

至此,FFT海面整个逻辑链条都理清了。

关于实现和优化细节也有一些技巧值得一说,例如「蝶形lut生成」、「stage乒乓」、「分帧插值」,或许以后再另写一篇。本系列重在原理,就先这样了。

参考文章:

citeseerx.ist.psu.edu/v

keithlantz.net/2011/10/

keithlantz.net/2011/11/

OpenStax CNX

推荐阅读:

相关文章