Nek5000
SEM for Incompressible NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
fft_fftw_mod.F90
Go to the documentation of this file.
1 
12 module fft
13  use, intrinsic :: iso_c_binding
14  use fftw3, only : fftw_r2hc, fftw_hc2r, fftw_redft00, fftw_redft10, fftw_redft01
15  implicit none
16 
18  public :: w_forward, w_backward, p_forward, p_backward
19 
20  private
21 
22  integer, parameter :: nplans = 10
23  integer :: n_r2r_plans = 0
24  type(c_ptr) :: r2r_plans(nplans)
25  integer :: r2r_plan_lengths(nplans)
26  integer :: r2r_plan_nums(nplans)
27  integer(C_INT) :: r2r_plan_kinds(nplans)
28 
29  integer, parameter :: w_forward = fftw_redft10
30  integer, parameter :: w_backward = fftw_redft01
31  integer, parameter :: p_forward = fftw_r2hc
32  integer, parameter :: p_backward = fftw_hc2r
33 
34 contains
35 
41 subroutine fft_r2r(u, length, num, kind, rescale)
42  use kinds, only : dp
43  use fftw3, only : fftw_exhaustive, fftw_estimate
44  use fftw3, only : fftw_plan_many_r2r
45  use fftw3, only : fftw_execute_r2r
46  use parallel, only : nid
47 
48  real(DP), intent(inout) :: u(:,:,:) !>
49  integer, intent(in) :: length !>
50  integer, intent(in) :: num !>
51  integer(C_INT) :: kind !>
52  real(DP), intent(inout) :: rescale !>
53 
54  integer :: i, plan_idx
55  real(DP), allocatable :: proxy(:)
56 
57  ! Look for an existing plan
58  plan_idx = -1
59  do i = 1, n_r2r_plans
60  if ( &
61  length == r2r_plan_lengths(i) .and. &
62  num == r2r_plan_nums(i) .and. &
63  kind == r2r_plan_kinds(i) &
64  ) then
65  plan_idx = i
66  exit
67  endif
68  enddo
69 
70  ! If there's no plan, make a new one
71  if (plan_idx < 0) then
72  if (n_r2r_plans == nplans) then
73  write(*,*) "Ran out of plans!"
74  endif
75 
76  n_r2r_plans = n_r2r_plans + 1
77  plan_idx = n_r2r_plans
78  allocate(proxy(num*length))
79  r2r_plans(plan_idx) = fftw_plan_many_r2r(1, &
80  (/length/), num, &
81  proxy, (/length/), 1, length, &
82  proxy, (/length/), 1, length, &
83  (/kind/), fftw_exhaustive)
84  deallocate(proxy)
85  r2r_plan_lengths(plan_idx) = length
86  r2r_plan_nums(plan_idx) = num
87  r2r_plan_kinds(plan_idx) = kind
88  endif
89 
90  ! execute the plan
91  call fftw_execute_r2r(r2r_plans(plan_idx), u, u)
92 
93  ! rescale the normalization factor
94  if (kind == fftw_redft00) then
95  rescale = rescale * sqrt(2.*real(length-1, kind=dp))
96  else if (kind == w_forward .or. kind == w_backward) then
97  rescale = rescale * sqrt(2.*real(length, kind=dp))
98  else if (kind == fftw_r2hc .or. kind == fftw_hc2r) then
99  rescale = rescale * sqrt(real(length, kind=dp))
100  else
101  write(*,*) "Don't know how to deal with FFT kind", kind
102  endif
103 
104 end subroutine fft_r2r
105 
107 real(DP) function wavenumber(i, N, L, kind)
108  use kinds, only : dp
109  implicit none
110  integer, intent(in) :: i !>
111  integer, intent(in) :: N !>
112  real(DP), intent(in) :: L !>
113  integer, intent(in) :: kind !>
114 
115  real(DP), parameter :: pi = 4.*atan(1.)
116 
117  if (kind == p_forward) then
118  if (i <= n / 2) then
119  wavenumber = 2*pi*i/(l)
120  else
121  wavenumber = 2*pi*(n - i)/(l)
122  endif
123  else if (kind == w_forward) then
124  wavenumber = pi*i/(l)
125  else
126  write(*,*) "Don't know how to deal with FFT kind", kind
127  endif
128 
129 end function wavenumber
130 
132 subroutine transpose_grid(grid, grid_t, shape_x, idx, idx_t, comm)
133  use kinds, only : dp
134  use fftw3, only : fftw_exhaustive, fftw_estimate
135  use parallel, only : nid, nekreal
136 
137  real(DP), intent(inout) :: grid(0:,0:,0:)
138  real(DP), intent(out) :: grid_t(0:,0:,0:)
139  integer, intent(in) :: shape_x(3)
140  integer, intent(in) :: idx
141  integer, intent(in) :: idx_t
142  integer, intent(in) :: comm
143 
144  real(DP), allocatable :: tmp(:,:)
145  real(DP), allocatable :: tmp_t(:,:)
146  integer :: block0, block1, num
147  integer :: i, j, k, ierr, comm_size
148 
149 
150  if (size(grid) < 1) return
151 
152  call mpi_comm_size(comm, comm_size, ierr)
153 
154  if (idx == 1 .or. idx_t == 1) then
155  block0 = size(grid,2)
156  block1 = size(grid,1) / comm_size
157  num = size(grid,3)
158  else if (idx == 3 .or. idx_t == 3) then
159  block0 = size(grid,3)
160  block1 = size(grid,1) / comm_size
161  num = size(grid,2)
162  endif
163  allocate(tmp(0:block0-1, 0:size(grid,1)-1))
164  allocate(tmp_t(0:block0-1, 0:size(grid,1)-1))
165 
166  if (idx == 1 .or. idx_t == 1) then
167  do i = 0, num - 1
168  tmp = transpose(grid(:,:,i))
169  call mpi_alltoall(tmp, block0*block1, nekreal, &
170  tmp_t, block0*block1, nekreal, comm, ierr)
171  if (ierr /= 0) write(*,*) "alltoall errored", ierr, nid
172  do j = 0, size(grid_t,1) - 1
173  do k = 0, size(grid_t,2) - 1
174  grid_t(j,k,i) = tmp_t( mod(j,int(block0)), (j / block0) * block1 + k )
175  enddo
176  enddo
177  enddo
178  else if (idx == 3 .or. idx_t == 3) then
179  do i = 0, num - 1
180  tmp = transpose(grid(:,i,:))
181  call mpi_alltoall(tmp, block0*block1, nekreal, &
182  tmp_t, block0*block1, nekreal, comm, ierr)
183  if (ierr /= 0) write(*,*) "alltoall errored", ierr, nid
184  do j = 0, size(grid_t,1) - 1
185  do k = 0, size(grid_t,3) - 1
186  grid_t(j,i,k) = tmp_t( mod(j,int(block0)), (j / block0) * block1 + k )
187  enddo
188  enddo
189  enddo
190  else
191  write(*,*) "Something went wrong in transpose", nid
192  endif
193 
194 end subroutine transpose_grid
195 
196 end module
Definition: comm.h:85
Definition: fftw3.F90:1
subroutine, public transpose_grid(grid, grid_t, shape_x, idx, idx_t, comm)
Global (parallel) transform of grid data.
cleaned
Definition: parallel_mod.F90:2
subroutine, public fft_r2r(u, length, num, kind, rescale)
Compute a number of 1D FFTs or DCTs.
subroutine mpi_comm_size(comm, nprocs, ierror)
Definition: mpi_dummy.F90:409
real(dp) function, public wavenumber(i, N, L, kind)
Get the wavenumber of the ith mode.