! @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !
! @@                                                                @@ !
! @@       PROGRAM  ASCOT 2014.440 (ver.4.53)                       @@ !
! @@     "Abinitio Simulation Code for Quantum Transport"           @@ !
! @@                                                                @@ !
! @@                                                                @@ !
! @@  AUTHOR(S): Naoki WATANABE, Nobutaka NISHIKAWA (Mizuho I.R.)   @@ !
! @@             Hisashi KONDO (Univ. Tokyo)                        @@ !
! @@                                                09/May/2014     @@ !
! @@                                                                @@ !
! @@  Contact address: Phase System Consortium                      @@ !
! @@                                                                @@ !
! @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !

subroutine ZFFT1D_forward( nx, data )
  use ac_mpi_module

  implicit none
  integer, intent(in) :: nx
  complex(8), intent(inout) :: data (nx)

  integer(8)         :: pf
  integer, parameter :: FFTW_ESTIMATE = 64 
  integer, parameter :: FFTW_FORWARD  = -1

  integer scount, ecount, rate, count_max

  call system_clock(scount, rate, count_max )

  call dfftw_plan_dft_1d( pf, nx, data, data, FFTW_FORWARD, FFTW_ESTIMATE )
  call dfftw_execute_dft( pf, data, data )
  call dfftw_destroy_plan(pf)

  call system_clock(ecount, rate, count_max )
  time_fft = time_fft + real(ecount-scount)/rate

  return
end subroutine ZFFT1D_forward

subroutine ZFFT1D_backward( nx, data )
  use ac_mpi_module

  implicit none
  integer, intent(in) :: nx
  complex(8), intent(inout) :: data (nx)

  integer(8)         :: pb
  integer, parameter :: FFTW_ESTIMATE = 64 
  integer, parameter :: FFTW_BACKWARD = +1

  integer scount, ecount, rate, count_max

  call system_clock(scount, rate, count_max )

  call dfftw_plan_dft_1d( pb, nx, data, data, FFTW_BACKWARD, FFTW_ESTIMATE )
  call dfftw_execute_dft( pb, data, data )
  call dfftw_destroy_plan(pb)

  call system_clock(ecount, rate, count_max )
  time_fft = time_fft + real(ecount-scount)/rate

  return
end subroutine ZFFT1D_backward

subroutine ZFFT2D_forward( nx, ny, data )
  use ac_mpi_module

  implicit none
  integer, intent(in) :: nx, ny
  complex(8), intent(inout) :: data (nx,ny)

  integer(8)         :: pf
  integer, parameter :: FFTW_ESTIMATE = 64 
  integer, parameter :: FFTW_FORWARD  = -1

  integer scount, ecount, rate, count_max

  call system_clock(scount, rate, count_max )

  call dfftw_plan_dft_2d( pf, nx, ny, data, data, FFTW_FORWARD, FFTW_ESTIMATE )
  call dfftw_execute_dft( pf, data, data )
  call dfftw_destroy_plan(pf)

  call system_clock(ecount, rate, count_max )
  time_fft = time_fft + real(ecount-scount)/rate

  return
end subroutine ZFFT2D_forward

subroutine ZFFT2D_backward( nx, ny, data )
  use ac_mpi_module

  implicit none
  integer, intent(in) :: nx, ny
  complex(8), intent(inout) :: data (nx,ny)

  integer(8)         :: pb
  integer, parameter :: FFTW_ESTIMATE = 64 
  integer, parameter :: FFTW_BACKWARD = +1

  integer scount, ecount, rate, count_max

  call system_clock(scount, rate, count_max )

  call dfftw_plan_dft_2d( pb, nx, ny, data, data, FFTW_BACKWARD, FFTW_ESTIMATE )
  call dfftw_execute_dft( pb, data, data )
  call dfftw_destroy_plan(pb)

  call system_clock(ecount, rate, count_max )
  time_fft = time_fft + real(ecount-scount)/rate

  return
end subroutine ZFFT2D_backward

subroutine ZFFT3D_forward( nx, ny, nz, data )
  use ac_mpi_module

  implicit none
  integer, intent(in) :: nx, ny, nz
  complex(8), intent(inout) :: data (nx,ny,nz)

  integer(8)         :: pf
  integer, parameter :: FFTW_ESTIMATE = 64 
  integer, parameter :: FFTW_FORWARD  = -1

  integer scount, ecount, rate, count_max

  call system_clock(scount, rate, count_max )

  call dfftw_plan_dft_3d( pf, nx, ny, nz, data, data, FFTW_FORWARD, FFTW_ESTIMATE )
  call dfftw_execute_dft( pf, data, data )
  call dfftw_destroy_plan(pf)

  call system_clock(ecount, rate, count_max )
  time_fft = time_fft + real(ecount-scount)/rate

  return
end subroutine ZFFT3D_forward

subroutine ZFFT3D_backward( nx, ny, nz, data )
  use ac_mpi_module

  implicit none
  integer, intent(in) :: nx, ny, nz
  complex(8), intent(inout) :: data (nx,ny,nz)

  integer(8)         :: pb
  integer, parameter :: FFTW_ESTIMATE = 64 
  integer, parameter :: FFTW_BACKWARD = +1

  integer scount, ecount, rate, count_max

  call system_clock(scount, rate, count_max )

  call dfftw_plan_dft_3d( pb, nx, ny, nz, data, data, FFTW_BACKWARD, FFTW_ESTIMATE )
  call dfftw_execute_dft( pb, data, data )
  call dfftw_destroy_plan(pb)

  call system_clock(ecount, rate, count_max )
  time_fft = time_fft + real(ecount-scount)/rate

  return
end subroutine ZFFT3D_backward

subroutine RFFT3D__forward( nx, ny, nz, data_in, data_out )
  use ac_mpi_module

  implicit none

  integer, intent(in)  :: nx, ny, nz
  real(8), intent(in)  :: data_in (nx,ny,nz)
  real(8), intent(out) :: data_out(2*(nx/2+1),ny,nz)

  integer(8)           :: pf
  integer, parameter   :: FFTW_ESTIMATE = 64 

  integer scount, ecount, rate, count_max

  call system_clock(scount, rate, count_max )

  call dfftw_plan_dft_r2c_3d( pf, &
       nx, ny, nz, data_in, data_out, FFTW_ESTIMATE )
  call dfftw_execute( pf )
  call dfftw_destroy_plan( pf )

  call system_clock(ecount, rate, count_max )
  time_fft = time_fft + real(ecount-scount)/rate

  return
end subroutine RFFT3D__forward

subroutine RFFT3D__backward( nx, ny, nz, data_in, data_out )
  use ac_mpi_module

  implicit none
  integer, intent(in)    :: nx, ny, nz
  real(8), intent(inout) :: data_in (2*(nx/2+1),ny,nz)
  real(8), intent(out)   :: data_out(nx,ny,nz)

  integer(8)             :: pb
  integer, parameter     :: FFTW_ESTIMATE = 64 

  integer scount, ecount, rate, count_max

  call system_clock(scount, rate, count_max )

  call dfftw_plan_dft_c2r_3d( pb, &
       nx, ny, nz, data_in, data_out, FFTW_ESTIMATE )
  call dfftw_execute( pb )
  call dfftw_destroy_plan( pb )

  call system_clock(ecount, rate, count_max )
  time_fft = time_fft + real(ecount-scount)/rate

  return
end subroutine RFFT3D__backward
