Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_fft_fftpack.F90
Go to the documentation of this file.
1 !**************************************************************
2 ! Copyright INRIA
3 ! Authors :
4 ! CALVI project team
5 !
6 ! This code SeLaLib (for Semi-Lagrangian-Library)
7 ! is a parallel library for simulating the plasma turbulence
8 ! in a tokamak.
9 !
10 ! This software is governed by the CeCILL-B license
11 ! under French law and abiding by the rules of distribution
12 ! of free software. You can use, modify and redistribute
13 ! the software under the terms of the CeCILL-B license as
14 ! circulated by CEA, CNRS and INRIA at the following URL
15 ! "http://www.cecill.info".
16 !**************************************************************
17 #ifndef DOXYGEN_SHOULD_SKIP_THIS
18 module sll_m_fft
19 #include "sll_working_precision.h"
20 #include "sll_assert.h"
21 #include "sll_memory.h"
22 
23  use sll_m_fft_utils
24 
25  implicit none
26 
27  type sll_fft_plan
28  sll_real64, dimension(:), pointer :: twiddles => null() ! twiddles factors
29  sll_int32 :: style
30  sll_int32 :: library
31  sll_int32 :: direction
32  sll_int32 :: problem_rank
33  sll_int32, dimension(:), pointer :: problem_shape
34  end type sll_fft_plan
35 
36  interface fft_new_plan
37  module procedure fftpack_new_plan_c2c_1d, fftpack_new_plan_r2r_1d, &
38  fftpack_new_plan_r2c_1d, fftpack_new_plan_c2r_1d, &
39  fftpack_new_plan_c2r_2d, fftpack_new_plan_r2c_2d, &
40  fftpack_new_plan_c2c_2d
41  end interface
42 
43  interface fft_apply_plan
44  module procedure fftpack_apply_plan_c2c_1d, fftpack_apply_plan_r2r_1d, &
45  fftpack_apply_plan_r2c_1d, fftpack_apply_plan_c2r_1d, &
46  fftpack_apply_plan_c2r_2d, fftpack_apply_plan_r2c_2d, &
47  fftpack_apply_plan_c2c_2d
48  end interface
49 
50  integer, parameter :: FFT_FORWARD = -1
51  integer, parameter :: FFT_BACKWARD = 1
52 
53 ! Flags to pass when we create a new plan
54 ! We can define 31 different flags.
55 ! The value assigned to the flag can only be a power of two.
56 ! See section "How-to manipulate flags ?" for more information.
57  integer, parameter :: FFT_NORMALIZE_FORWARD = 2**0
58  integer, parameter :: FFT_NORMALIZE_INVERSE = 2**0
59  integer, parameter :: FFT_NORMALIZE = 2**0
60 
61  integer, parameter :: FFTPACK_MOD = 100
62 
63  interface fft_get_mode
64  module procedure fft_get_mode_complx_1d, fft_get_mode_real_1d
65  end interface
66 
67  interface fft_set_mode
68  module procedure fft_set_mode_complx_1d, fft_set_mode_real_1d
69  end interface
70 
71 contains
72 
73  subroutine print_defaultfftlib()
74  print *, 'The library used is FFTPACK'
75  end subroutine
76 
77  function fft_get_mode_complx_1d(plan, array, k) result(mode)
78  type(sll_fft_plan), pointer :: plan
79  sll_comp64, dimension(0:) :: array
80  sll_int32 :: k
81  sll_comp64 :: mode
82  mode = array(k)
83  end function
84 
85  function fft_get_mode_real_1d(plan, data, k) result(mode)
86  type(sll_fft_plan), pointer :: plan
87  sll_real64, dimension(0:) :: data
88  sll_int32 :: k, n_2, n
89  sll_comp64 :: mode
90 
91  n = plan%problem_shape(1)
92  n_2 = n/2 !ishft(n,-1)
93 
94  if (k .eq. 0) then
95  mode = cmplx(data(0), 0.0_f64, kind=f64)
96  else if (k .eq. n_2) then
97  mode = cmplx(data(n - 1), 0.0_f64, kind=f64)
98  else if (k .gt. n_2) then
99  mode = cmplx(data(2*(n - k) - 1), -data(2*(n - k)), kind=f64)
100  else
101  mode = cmplx(data(2*k - 1), data(2*k), kind=f64)
102  end if
103  end function
104 
105  subroutine fft_set_mode_complx_1d(plan, array, new_value, k)
106  type(sll_fft_plan), pointer :: plan
107  sll_comp64, dimension(0:) :: array
108  sll_int32 :: k
109  sll_comp64 :: new_value
110  array(k) = new_value
111  end subroutine
112 
113  subroutine fft_set_mode_real_1d(plan, data, new_value, k)
114  type(sll_fft_plan), pointer :: plan
115  sll_real64, dimension(0:) :: data
116  sll_int32 :: k, n_2, n, index_mode
117  sll_comp64 :: new_value
118 
119  n = plan%problem_shape(1)
120  n_2 = n/2 !ishft(n,-1)
121 
122  if (k .eq. 0) then
123  data(0) = real(new_value, kind=f64)
124  else if (k .eq. n_2) then
125  data(n - 1) = real(new_value, kind=f64)
126  else if (k .gt. n_2) then
127  data(2*(n - k) - 1) = real(new_value, kind=f64)
128  data(2*(n - k)) = -aimag(new_value)
129  else
130  data(2*k - 1) = real(new_value, kind=f64)
131  data(2*k) = aimag(new_value)
132  end if
133  end subroutine
134 
135  ! return the index mode of ith stored mode
136  ! In the complex output case the mode are stored in the natural order
137  ! X_0,X_1,...,X_N-1
138  ! In the real output case the order is
139  ! r_o,r_1,i_1,r_2,i_2,...,r_N/2-1,i_N/2-1,r_N/2
140  ! where X_k is the complex number (r_k,i_k).
141  ! X_o and X_N/2 are purely real.
142  function fft_ith_stored_mode(plan, i)
143  type(sll_fft_plan), pointer :: plan
144  sll_int32 :: i, fft_ith_stored_mode
145  fft_ith_stored_mode = i
146  end function fft_ith_stored_mode
147 
148 ! FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK
149 ! FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK
150 ! FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK
151 ! COMPLEX
152  function fftpack_new_plan_c2c_1d(nx, array_in, array_out, direction, flags) result(plan)
153  sll_int32, intent(in) :: nx
154  sll_comp64, dimension(:) :: array_in, array_out
155  sll_int32, intent(in) :: direction
156  sll_int32, optional, intent(in) :: flags
157  type(sll_fft_plan), pointer :: plan
158  sll_int32 :: ierr
159 
160  sll_allocate(plan, ierr)
161  plan%library = fftpack_mod
162  plan%direction = direction
163  if (present(flags)) then
164  plan%style = flags
165  else
166  plan%style = 0_f32
167  end if
168  plan%problem_rank = 1
169  sll_allocate(plan%problem_shape(1), ierr)
170  plan%problem_shape = (/nx/)
171  allocate (plan%twiddles(4*nx + 15))
172  call zffti(nx, plan%twiddles)
173  end function
174 
175  subroutine fftpack_apply_plan_c2c_1d(plan, array_in, array_out)
176  type(sll_fft_plan), pointer, intent(in) :: plan
177  sll_comp64, dimension(:), intent(inout) :: array_in, array_out
178  sll_int32 :: nx
179  sll_real64 :: factor
180 
181  if (loc(array_in) .ne. loc(array_out)) then ! out-place transform
182  array_out = array_in
183  end if
184 
185  nx = plan%problem_shape(1)
186 
187  if (plan%direction .eq. fft_forward) then
188  call zfftf(nx, array_out, plan%twiddles)
189  else if (plan%direction .eq. fft_backward) then
190  call zfftb(nx, array_out, plan%twiddles)
191  end if
192 
193  if (fft_is_present_flag(plan%style, fft_normalize)) then
194  factor = 1.0_f64/real(nx, kind=f64)
195  array_out = factor*array_out
196  end if
197  end subroutine
198 ! END COMPLEX
199 
200 ! REAL
201  function fftpack_new_plan_r2r_1d(nx, array_in, array_out, direction, flags) result(plan)
202  sll_int32, intent(in) :: nx
203  sll_real64, dimension(:) :: array_in, array_out
204  sll_int32, intent(in) :: direction
205  sll_int32, optional, intent(in) :: flags
206  type(sll_fft_plan), pointer :: plan
207  sll_int32 :: ierr
208 
209  sll_allocate(plan, ierr)
210  plan%library = fftpack_mod
211  plan%direction = direction
212  if (present(flags)) then
213  plan%style = flags
214  else
215  plan%style = 0_f32
216  end if
217  plan%problem_rank = 1
218  sll_allocate(plan%problem_shape(1), ierr)
219  plan%problem_shape = (/nx/)
220 
221  sll_allocate(plan%twiddles(2*nx + 15), ierr)
222  call dffti(nx, plan%twiddles)
223  end function
224 
225  subroutine fftpack_apply_plan_r2r_1d(plan, array_in, array_out)
226  type(sll_fft_plan), pointer, intent(in) :: plan
227  sll_real64, dimension(:), intent(inout) :: array_in, array_out
228  sll_int32 :: nx
229  sll_real64 :: factor
230 
231  if (loc(array_in) .ne. loc(array_out)) then ! out-place transform
232  array_out = array_in
233  end if
234 
235  nx = plan%problem_shape(1)
236 
237  if (plan%direction .eq. fft_forward) then
238  call dfftf(nx, array_out, plan%twiddles)
239  else if (plan%direction .eq. fft_backward) then
240  call dfftb(nx, array_out, plan%twiddles)
241  end if
242 
243  if (fft_is_present_flag(plan%style, fft_normalize)) then
244  factor = 1.0_f64/real(nx, kind=f64)
245  array_out = factor*array_out
246  end if
247  end subroutine
248 ! END REAL
249 
250  function fftpack_new_plan_r2c_1d(nx, array_in, array_out, flags) result(plan)
251  sll_int32, intent(in) :: nx
252  sll_real64, dimension(:) :: array_in
253  sll_comp64, dimension(:) :: array_out
254  sll_int32, optional, intent(in) :: flags
255  type(sll_fft_plan), pointer :: plan
256  sll_int32 :: ierr
257 
258  print *, "function fftpack_new_plan_r2c_1d is not implemented"
259  end function
260 
261  subroutine fftpack_apply_plan_r2c_1d(plan, array_in, array_out)
262  type(sll_fft_plan), pointer :: plan
263  sll_real64, dimension(0:), intent(inout) :: array_in
264  sll_comp64, dimension(0:), intent(out) :: array_out
265  sll_int32 :: nx, i
266  sll_real64 :: factor
267 
268  print *, "subroutine fftpack_apply_plan_r2c_1d is not implemented"
269  end subroutine
270 
271  function fftpack_new_plan_c2r_1d(nx, array_in, array_out, flags) result(plan)
272  sll_int32, intent(in) :: nx
273  sll_real64, dimension(:) :: array_out
274  sll_comp64, dimension(:) :: array_in
275  sll_int32, optional, intent(in) :: flags
276  type(sll_fft_plan), pointer :: plan
277  sll_int32 :: ierr
278 
279  print *, "function fftpack_new_plan_c2r_1d is not implemented"
280  end function
281 
282  subroutine fftpack_apply_plan_c2r_1d(plan, array_in, array_out)
283  type(sll_fft_plan), pointer :: plan
284  sll_real64, dimension(0:), intent(inout) :: array_out
285  sll_comp64, dimension(0:), intent(out) :: array_in
286  sll_int32 :: nx, i
287  sll_real64 :: factor
288 
289  print *, "subroutine fftpack_apply_plan_c2r_1d is not implemented"
290  end subroutine
291 
292  function fftpack_new_plan_c2c_2d(NX, NY, array_in, array_out, direction, flags) &
293  result(plan)
294 
295  sll_int32, intent(in) :: nx, ny
296  sll_comp64, dimension(0:, 0:), target, intent(in) :: array_in, array_out
297  sll_int32, intent(in) :: direction
298  sll_int32, optional, intent(in) :: flags
299  type(sll_fft_plan), pointer :: plan
300  sll_int32 :: ierr
301  !true if dft in the two directions, false otherwise.
302  logical :: two_direction
303 
304  print *, "function fftpack_new_plan_c2c_2d is not implemented"
305  end function fftpack_new_plan_c2c_2d
306 
307  subroutine fftpack_apply_plan_c2c_2d(plan, array_in, array_out)
308  type(sll_fft_plan), pointer :: plan
309  sll_comp64, dimension(0:, 0:), intent(inout) :: array_in, array_out
310  sll_int32 :: i, nx, ny
311  sll_int32, dimension(2) :: fft_shape
312  logical :: two_direction
313 
314  print *, "subroutine fftpack_apply_plan_c2c_2d is not implemented"
315  end subroutine fftpack_apply_plan_c2c_2d
316 
317  function fftpack_new_plan_c2r_2d(nx, ny, array_in, array_out, flags) result(plan)
318  sll_int32, intent(in) :: nx, ny
319  sll_comp64, dimension(:, :), intent(in) :: array_in
320  sll_real64, dimension(:, :), intent(in) :: array_out
321  sll_int32, optional, intent(in) :: flags
322  type(sll_fft_plan), pointer :: plan
323  sll_int32 :: ierr
324 
325  print *, "function fftpack_new_plan_c2r_2d is no implemented"
326  end function fftpack_new_plan_c2r_2d
327 
328  subroutine fftpack_apply_plan_c2r_2d(plan, array_in, array_out)
329  type(sll_fft_plan), pointer :: plan
330  sll_comp64, dimension(0:, 0:), intent(inout) :: array_in
331  sll_real64, dimension(0:, 0:), intent(out) :: array_out
332  sll_int32 :: nx, i, ny, k, j
333  sll_real64 :: factor
334 
335  print *, "subroutine fftpack_apply_plan_c2r_2d is not implemented"
336  end subroutine fftpack_apply_plan_c2r_2d
337 
338  function fftpack_new_plan_r2c_2d(nx, ny, array_in, array_out, flags) result(plan)
339  sll_int32, intent(in) :: nx, ny
340  sll_real64, dimension(:, :), intent(in) :: array_in
341  sll_comp64, dimension(:, :), intent(in) :: array_out
342  sll_int32, optional, intent(in) :: flags
343  type(sll_fft_plan), pointer :: plan
344  sll_int32 :: ierr
345 
346  print *, "function fftpack_new_plan_r2c_2d is not implemented"
347  end function
348 
349  subroutine fftpack_apply_plan_r2c_2d(plan, array_in, array_out)
350  type(sll_fft_plan), pointer :: plan
351  sll_real64, dimension(0:, 0:), intent(inout) :: array_in
352  sll_comp64, dimension(0:, 0:), intent(out) :: array_out
353  sll_int32 :: nx, i, ny, k
354  sll_real64 :: factor
355 
356  print *, "subroutine fftpack_apply_plan_r2c_2d is not implemented"
357  end subroutine fftpack_apply_plan_r2c_2d
358 
359 ! FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK
360 ! FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK
361 ! FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK FFTPACK
362 
363  subroutine fft_delete_plan(plan)
364  type(sll_fft_plan), pointer :: plan
365 
366  if (.not. associated(plan)) then
367  print *, ' Error in fft_delete_plan subroutine'
368  print *, ' you try to delete a plan not associated'
369  stop
370  end if
371 
372  if (associated(plan%twiddles)) then
373  deallocate (plan%twiddles)
374  plan%twiddles => null()
375  end if
376  plan => null()
377  end subroutine
378 
379 end module sll_m_fft
380 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
FFT interface for FFTW.
    Report Typos and Errors