module OW_fftw
!--------------------------------------------------
! Setting FFTW plans
!

use OW_type
use OW_parms

implicit none

integer*8,public					:: planFs, planIs,planFr, planIr,planF, planI !,planF1, planI1
integer*8,pointer,private	   			:: planF1s(:),planI1s(:),planF1r(:),planI1r(:)

contains

!-------------------------------------------------------------------------
subroutine owfftw(tfld,nodes)

integer,optional					:: nodes
complex						:: tfld(:)
integer						:: i

integer, parameter   				:: FFTW_R2HC=0,FTW_HC2R=1,FFTW_DHT=2,FFTW_REDFT00=3,FFTW_REDFT01=4
integer, parameter   				:: FFTW_REDFT10=5,FFTW_REDFT11=6,FFTW_RODFT00=7,FFTW_RODFT01=8,FFTW_RODFT10=9
integer, parameter   				:: FFTW_RODFT11=10,FFTW_FORWARD=-1,FFTW_BACKWARD=+1,FFTW_DESTROY_INPUT=1
integer, parameter   				:: FFTW_UNALIGNED=2,FFTW_CONSERVE_MEMORY=4,FFTW_EXHAUSTIVE=8,FTW_PRESERVE_INPUT=16
integer, parameter   				:: FFTW_PATIENT=32,FFTW_ESTIMATE=64,FFTW_ESTIMATE_PATIENT=128
integer, parameter   				:: FFTW_BELIEVE_PCOST=256,FFTW_DFT_R2HC_ICKY=512,FFTW_NONTHREADED_ICKY=1024
integer, parameter   				:: FFTW_NO_BUFFERING=2048,FFTW_NO_INDIRECT_OP=4096,FFTW_ALLOW_LARGE_GENERIC=8192
integer, parameter   				:: FFTW_NO_RANK_SPLITS=16384,FFTW_NO_VRANK_SPLITS=32768,FFTW_NO_VRECURSE=65536

!if(present(nodes)) then
!   allocate(planF1(nodes),planI1(nodes))
!   do i=1,nodes
!      call sfftw_plan_dft(planF1(i),1,size(tfld),tfld,tfld,fftW_FORWARD,fftW_PATIENT)
!      call sfftw_plan_dft(planI1(i),1,size(tfld),tfld,tfld,fftw_BACKWARD,fftW_PATIENT)
!   end do
!else
      call sfftw_plan_dft(planF,1,size(tfld),tfld,tfld,fftW_FORWARD,fftW_PATIENT)
      call sfftw_plan_dft(planI,1,size(tfld),tfld,tfld,fftw_BACKWARD,fftW_PATIENT)
!end if
!write(0,*) " planF and planI created"

end subroutine
!!----------------------------------------------------------------------------
!subroutine owfftexe(tfld,inode)
!complex				:: tfld(:)
!integer				:: inode
!
!call sfftw_execute(planF1(inode))
!
!end subroutine
!!----------------------------------------------------------------------------
!subroutine owifftexe(tfld,inode)
!complex				:: tfld(:)
!integer				:: inode
!
!call sfftw_execute(planI1(inode))
!
!end subroutine
!-------------------------------------------------------------------------
subroutine owfftws(tflds,nodes)
integer,optional					:: nodes
complex						:: tflds(:)
integer						:: i

integer, parameter   				:: FFTW_R2HC=0,FTW_HC2R=1,FFTW_DHT=2,FFTW_REDFT00=3,FFTW_REDFT01=4
integer, parameter   				:: FFTW_REDFT10=5,FFTW_REDFT11=6,FFTW_RODFT00=7,FFTW_RODFT01=8,FFTW_RODFT10=9
integer, parameter   				:: FFTW_RODFT11=10,FFTW_FORWARD=-1,FFTW_BACKWARD=+1,FFTW_DESTROY_INPUT=1
integer, parameter   				:: FFTW_UNALIGNED=2,FFTW_CONSERVE_MEMORY=4,FFTW_EXHAUSTIVE=8,FTW_PRESERVE_INPUT=16
integer, parameter   				:: FFTW_PATIENT=32,FFTW_ESTIMATE=64,FFTW_ESTIMATE_PATIENT=128
integer, parameter   				:: FFTW_BELIEVE_PCOST=256,FFTW_DFT_R2HC_ICKY=512,FFTW_NONTHREADED_ICKY=1024
integer, parameter   				:: FFTW_NO_BUFFERING=2048,FFTW_NO_INDIRECT_OP=4096,FFTW_ALLOW_LARGE_GENERIC=8192
integer, parameter   				:: FFTW_NO_RANK_SPLITS=16384,FFTW_NO_VRANK_SPLITS=32768,FFTW_NO_VRECURSE=65536

if(present(nodes)) then
   allocate(planF1s(nodes),planI1s(nodes))
   do i=1,nodes
      call sfftw_plan_dft(planF1s(i),1,size(tflds),tflds,tflds,fftW_FORWARD,fftW_PATIENT)
      call sfftw_plan_dft(planI1s(i),1,size(tflds),tflds,tflds,fftw_BACKWARD,fftW_PATIENT)
   end do
else
      call sfftw_plan_dft(planFs,1,size(tflds),tflds,tflds,fftW_FORWARD,fftW_PATIENT)
      call sfftw_plan_dft(planIs,1,size(tflds),tflds,tflds,fftw_BACKWARD,fftW_PATIENT)
end if
!write(0,*) " planF and planI created"

end subroutine
!----------------------------------------------------------------------------
subroutine owfftexes(tflds,inode)
complex				:: tflds(:)
integer				:: inode

call sfftw_execute(planF1s(inode))

end subroutine
!----------------------------------------------------------------------------
subroutine owifftexes(tflds,inode)
complex				:: tflds(:)
integer				:: inode

call sfftw_execute(planI1s(inode))

end subroutine

!-------------------------------------------------------------------------
subroutine owfftwr(tfldr,nodes)

integer,optional					:: nodes
complex						:: tfldr(:)
integer						:: i

integer, parameter   				:: FFTW_R2HC=0,FTW_HC2R=1,FFTW_DHT=2,FFTW_REDFT00=3,FFTW_REDFT01=4
integer, parameter   				:: FFTW_REDFT10=5,FFTW_REDFT11=6,FFTW_RODFT00=7,FFTW_RODFT01=8,FFTW_RODFT10=9
integer, parameter   				:: FFTW_RODFT11=10,FFTW_FORWARD=-1,FFTW_BACKWARD=+1,FFTW_DESTROY_INPUT=1
integer, parameter   				:: FFTW_UNALIGNED=2,FFTW_CONSERVE_MEMORY=4,FFTW_EXHAUSTIVE=8,FTW_PRESERVE_INPUT=16
integer, parameter   				:: FFTW_PATIENT=32,FFTW_ESTIMATE=64,FFTW_ESTIMATE_PATIENT=128
integer, parameter   				:: FFTW_BELIEVE_PCOST=256,FFTW_DFT_R2HC_ICKY=512,FFTW_NONTHREADED_ICKY=1024
integer, parameter   				:: FFTW_NO_BUFFERING=2048,FFTW_NO_INDIRECT_OP=4096,FFTW_ALLOW_LARGE_GENERIC=8192
integer, parameter   				:: FFTW_NO_RANK_SPLITS=16384,FFTW_NO_VRANK_SPLITS=32768,FFTW_NO_VRECURSE=65536

if(present(nodes)) then
   allocate(planF1r(nodes),planI1r(nodes))
   do i=1,nodes
      call sfftw_plan_dft(planF1r(i),1,size(tfldr),tfldr,tfldr,fftW_FORWARD,fftW_PATIENT)
      call sfftw_plan_dft(planI1r(i),1,size(tfldr),tfldr,tfldr,fftw_BACKWARD,fftW_PATIENT)
   end do
else
      call sfftw_plan_dft(planFr,1,size(tfldr),tfldr,tfldr,fftW_FORWARD,fftW_PATIENT)
      call sfftw_plan_dft(planIr,1,size(tfldr),tfldr,tfldr,fftw_BACKWARD,fftW_PATIENT)
end if
!write(0,*) " planF and planI created"

end subroutine
!----------------------------------------------------------------------------
subroutine owfftexer(tfldr,inode)
complex				:: tfldr(:)
integer				:: inode

call sfftw_execute(planF1r(inode))

end subroutine
!----------------------------------------------------------------------------
subroutine owifftexer(tfldr,inode)
complex				:: tfldr(:)
integer				:: inode

call sfftw_execute(planI1r(inode))

end subroutine
!----------------------------------------------------------------------------
subroutine owfftdestroy()

call sfftw_destroy_plan(planF1r)
call sfftw_destroy_plan(planI1r)
call sfftw_destroy_plan(planF1s)
call sfftw_destroy_plan(planI1s)

end subroutine

end module
