fftw3の使い方について

留意点

使用時に留意するのは3つ

  • include ファイルの言及

  • コンパイルオプションの指定

  • ファイル中のsubroutine呼び出し

include ファイルの言及

fortran ファイル中に以下を言及

include 'fftw3'

コンパイルオプション

gfortran test.f90 -I/usr/local/include -lfftw3

が必要.-Iオプションはincludeファイルの存在場所を指定する.-lfftw3はライブラリの指定を行っている.

subroutine 呼び出し(fftw3の使い方)

integer, parameter :: N=256
integer(8) :: plan
complex(kind(0d0)) :: y(N), fft(N)

call dfftw_plan_dft_1d( plan, N, y, fft, FFTW_FORWARD, FFTW_ESTIMATE )
call dfftw_execute_dft( plan, y, fft )
call dfftw_destroy_plan( plan )

よくわからんのはFFTW_FORWARDとFFTW_ESTIMATEだけど,これは特に何か変数を用意する必要はなさそうで,指定すれば事足りるみたい.

使うべき関数の注意点

fftw3には複数のsubroutineが含まれているけど,そのうち,幾つかは危険な香りがするみたい.例えば,fftw3のreferenceには次のような文言がある.

call dfftw_execute(plan)

However, we have had reports that this causes problems with some recent optimizing Fortran compilers. The problem is, because the input/output arrays are not passed as explicit arguments to dfftw_execute, the semantics of Fortran (unlike C) allow the compiler to assume that the input/output arrays are not changed by dfftw_execute. As a consequence, certain compilers end up optimizing out or repositioning the call to dfftw_execute, assuming incorrectly that it does nothing.

dfftw_execute(plan)ではなく,別の,それぞれ用途にフィットした関数を使うのがよろしいようです.

You must use the correct type of execute function, matching the way the plan was created. Complex DFT plans should use dfftw_execute_dft, Real-input (r2c) DFT plans should use use dfftw_execute_dft_r2c, and real-output (c2r) DFT plans should use dfftw_execute_dft_c2r. The various r2r plans should use dfftw_execute_r2r.

複素Fourier変換(最もgeneral)が欲しければ,

call dfftw_execute_dft( plan, in, out )

を使いましょう.

fftw3 in fortran の作法

  • planにはinteger(8) を使いましょう.

integer(8) :: plan

ref. 8.1 Fortran-interface routines( http://www.fftw.org/doc/Fortran_002dinterface-routines.html#Fortran_002dinterface-routines )

fortran fftw3のサンプル

抜粋 :

In Fortran, you would use the following to accomplish the same thing:

double complex in, out
dimension in(N), out(N)
integer*8 plan

call dfftw_plan_dft_1d(plan,N,in,out,FFTW_FORWARD,FFTW_ESTIMATE)
call dfftw_execute_dft(plan, in, out)
call dfftw_destroy_plan(plan)

To transform a three-dimensional array in-place .... In Fortran, you would use this instead:

double complex arr
dimension arr(L,M,N)
integer*8 plan

call dfftw_plan_dft_3d(plan, L,M,N, arr,arr &
             & ,FFTW_FORWARD, FFTW_ESTIMATE)
call dfftw_execute_dft(plan, arr, arr)
call dfftw_destroy_plan(plan)

Note that we pass the array dimensions in the “natural” order in both C and Fortran.

fortranでの"natural"な配列の渡し方 == (L,M,N)で良いみたい.

自作サンプル結果

正弦波(モード数=2)の波を入力してFFTする.

 1program main
 2
 3
 4
 5  implicit none
 6
 7  integer, parameter :: N=256
 8  double precision, parameter :: pi   = 4.d0 * atan( 1.d0 )
 9  double precision, parameter :: xmax = 2.d0 * pi, xmin = 0.d0
10  double precision, parameter :: amp  = 1.d0
11  double precision, parameter :: k    = 2.d0
12
13  integer(8) :: plan
14
15  integer :: i, j
16  double precision :: dx
17  double precision :: x(N)
18  complex(kind(0d0)) :: y(N), fft(N)
19  double precision :: power(N), theta(N)
20
21  ! data preparation
22
23  include 'fftw3.f'
24
25  do i=1, N
26     dx = ( xmax - xmin ) / dble(N)
27     x(i) = dx * dble( i - 1 )
28     y(i) = amp * sin( k * x(i) )
29  enddo
30
31  open( 50, file='x.dat', form='formatted' )
32  do i=1, N
33     write(50,*) x(i), y(i)
34  enddo
35  close(50)
36
37  ! FFT
38
39  call dfftw_plan_dft_1d( plan, N, y, fft, FFTW_FORWARD, FFTW_ESTIMATE )
40  call dfftw_execute_dft( plan, y, fft )
41  call dfftw_destroy_plan( plan )
42
43  power = abs( fft ) / dble(N)
44  theta = atan2( aimag(fft), real(fft) )
45
46  ! write
47
48  open( 50, file='fft.dat', form='formatted' )
49  do i=1, N
50     write(50,*) i, power(i), theta(i)
51  enddo
52  close(50)
53
54
55end program main

結果は以下.

../../_images/fftw3_test.jpg

multi-threaded での注意点もあるみたいだ.