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

module fft

  implicit none
  integer :: ix_fft,iy_fft,iz_fft,iz_fft_l,iz_fft_r
  complex(8), pointer :: wxn(:),wyn(:),wzn(:),wxn_i(:),wyn_i(:),wzn_i(:)
  complex(8), pointer :: fft1(:),fft2(:),fft3(:)

contains
  subroutine alo_fft_1(n_a,n_b)

    implicit none
    integer, intent(in) :: n_a,n_b
    integer :: i_do,ier
    real(8) :: theta

    allocate(wxn(n_a),wyn(n_b),wxn_i(n_a),wyn_i(n_b),stat=ier)
    if( ier /= 0 ) then
       write(6,*) 'error allocate: alo_fft_1'
       stop
    end if

    theta=2.d0*(datan(1.d0)*4.d0)/dfloat(n_a)
    do i_do=0,n_a-1
       wxn(i_do+1)=dcmplx(dcos(theta*dfloat(i_do)),dsin(theta*dfloat(i_do)))
    end do
    theta=2.d0*(datan(1.d0)*4.d0)/dfloat(n_b)
    do i_do=0,n_b-1
       wyn(i_do+1)=dcmplx(dcos(theta*dfloat(i_do)),dsin(theta*dfloat(i_do)))
    end do

    theta=-2.d0*(datan(1.d0)*4.d0)/dfloat(n_a)
    do i_do=0,n_a-1
       wxn_i(i_do+1)=dcmplx(dcos(theta*dfloat(i_do)),dsin(theta*dfloat(i_do)))
    end do
    theta=-2.d0*(datan(1.d0)*4.d0)/dfloat(n_b)
    do i_do=0,n_b-1
       wyn_i(i_do+1)=dcmplx(dcos(theta*dfloat(i_do)),dsin(theta*dfloat(i_do)))
    end do

    return
  end subroutine alo_fft_1

  subroutine alo_fft_21(n_a)

    implicit none
    integer, intent(in) :: n_a
    integer :: ier

    allocate(fft1(n_a),stat=ier)
    if( ier /= 0 ) then
       write(6,*) 'error allocate: alo_fft_21'
       stop
    end if

    return
  end subroutine alo_fft_21

  subroutine alo_fft_22(n_b)

    implicit none
    integer, intent(in) :: n_b
    integer :: ier

    allocate(fft2(n_b),stat=ier)
    if( ier /= 0 ) then
       write(6,*) 'error allocate: alo_fft_22'
       stop
    end if

    return
  end subroutine alo_fft_22

  subroutine unset_fft_1

    implicit none
    integer :: ier

    deallocate(wxn,wyn,wxn_i,wyn_i,stat=ier)
    if( ier /= 0 ) then
       write(6,*) 'error deallocate: unset_unset_fft'
       stop
    end if

    return
  end subroutine unset_fft_1

  subroutine unset_fft_21

    implicit none
    integer :: ier

    deallocate(fft1,stat=ier)
    if( ier /= 0 ) then
       write(6,*) 'error deallocate: unset_unset_fft21'
       stop
    end if

    return
  end subroutine unset_fft_21

  subroutine unset_fft_22

    implicit none
    integer :: ier

    deallocate(fft2,stat=ier)
    if( ier /= 0 ) then
       write(6,*) 'error deallocate: unset_unset_fft22'
       stop
    end if

    return
  end subroutine unset_fft_22

  subroutine alo_fft_zz(n_c)

    implicit none
    integer, intent(in) :: n_c
    integer :: i_do,ier
    real(8) :: theta

    allocate(fft3(n_c),wzn(n_c),wzn_i(n_c),stat=ier)
    if( ier /= 0 ) then
       write(6,*) 'error allocate: alo_fft_zz'
       stop
    end if

    theta=2.d0*(datan(1.d0)*4.d0)/dfloat(n_c)
    do i_do=0,n_c-1
       wzn(i_do+1)=dcmplx(dcos(theta*dfloat(i_do)),dsin(theta*dfloat(i_do)))
    end do
    theta=-2.d0*(datan(1.d0)*4.d0)/dfloat(n_c)
    do i_do=0,n_c-1
       wzn_i(i_do+1)=dcmplx(dcos(theta*dfloat(i_do)),dsin(theta*dfloat(i_do)))
    end do

    return
  end subroutine alo_fft_zz

  subroutine unset_fft_zz

    implicit none
    integer :: ier

    deallocate(fft3,wzn,wzn_i,stat=ier)
    if( ier /= 0 ) then
       write(6,*) 'error allocate: alo_fft_zz'
       stop
    end if

    return
  end subroutine unset_fft_zz

end module fft
