module wei_step_mod
  use wei_kmap_mod
  use wei_fk_type_mod
  use sep3d_struct_mod
  use wei_wavespace_type_mod
#ifdef INTEL_MKL
  use  MKL_DFTI

 type dfti_type
   type(DFTI_DESCRIPTOR), pointer ::  dft_d
 end type
 implicit none

#endif



  type westep
    logical              :: source  !whether or not this is the source
    real                 :: sref    !slowness
    real                 :: w       !frequency
    real                 :: dstep   !step in the wavefield
    real,pointer         :: kx(:,:),ky(:,:)   !kx and ky for the current step
    integer              :: ithread           !thread represented by this step
    integer              :: iw,iz,izb         !frequency we are working on in this step


    complex,    pointer :: tmp1(:,:,:,:)     !temporary storage 1
    complex,    pointer :: tmp2(:,:,:,:)     !temporary storage 2

    real,pointer     :: srefs(:)          !slownesses for this step
    real,pointer     :: maxs(:)           !maximum slownesss for this division
    integer              :: iref              !reference we are working on


    integer, pointer :: islow(:,:,:,:)            !reference slowness at given 2-D slice
    real,    pointer :: slow(:,:,:,:)             !slowness at given 2-D slice

    real,  pointer   :: amp_hx(:),amp_hy(:)     !Damping arrays
    real,  pointer   :: amp_cx(:),amp_cy(:)     !Damping arrays

    type(wspace),pointer         :: wave              !wavespace
    type(fktype)         :: fk                !fk buffers
    type(component)      :: comp              !current component
    complex, pointer     :: ctable(:)         !dsr lookup table
#ifdef FFTW
  integer*8              :: planF,planI
#endif


#ifdef INTEL_MKL
 type(dfti_descriptor) :: dfti
#endif

  end  type westep


  contains

  
  subroutine init_step(wave,step,ith,nkxko)
    type(wspace),pointer :: wave
    type(westep) :: step
    integer      :: ith,nkxko
#ifdef DEBUG
    write(0,*) "IN INIT STEP"
#endif
    

    step%wave=>wave
    step%ithread=ith

    step%iw=ith
    allocate(step%srefs(1),step%maxs(1))
    allocate(step%kx(wave%npad(1),wave%npad(3)),step%ky(wave%npad(2),wave%npad(4)))
    if(step%wave%mem_save>0) then
      allocate(step%islow(wave%npad(1),wave%npad(2),1,1))
      allocate(step%slow(wave%npad(1),wave%npad(2),1,1))
    else
      allocate(step%islow(wave%npad(1),wave%npad(2),wave%npad(3),wave%npad(4)))
      allocate(step%slow(wave%npad(1),wave%npad(2),wave%npad(3),wave%npad(4)))
    end if

    allocate(step%ctable(nkxko))
#ifdef DEBUG
    write(0,*) "OUT INIT STEP"
#endif

  end subroutine


  subroutine set_reference(step,iref)
    type(westep) :: step
    integer      :: iref
#ifdef DEBUG
    write(0,*) "IN SET REFERENCE"
#endif

    step%iref=iref
    step%sref=step%srefs(step%iref)
#ifdef DEBUG
    write(0,*) "OUT SET REFERENCE"
#endif
  end subroutine


  subroutine set_source(step,wave)
   type(westep)   :: step
   type(wspace)   :: wave
#ifdef DEBUG
    write(0,*) "IN SET SOURCE"
#endif
   step%source=.true.
   step%kx=wave%ksx
   step%ky=wave%ksy
   step%comp=wave%src
   deallocate(step%maxs,step%srefs)
   allocate(step%maxs(size(step%comp%slow%reference(step%iz+step%izb)%maxs)))
   allocate(step%srefs(size(step%comp%slow%reference(step%iz+step%izb)%maxs)))
   step%srefs=step%comp%slow%reference(step%iz+step%izb)%sref
   step%maxs=step%comp%slow%reference(step%iz+step%izb)%maxs
#ifdef DEBUG
    write(0,*) "OUT SET SOURCE"
#endif
  end subroutine

  subroutine set_receiver(step)
   type(westep)   :: step
#ifdef DEBUG
    write(0,*) "IN SET RECEIVER"
#endif
   step%source=.false.
   step%kx=step%wave%krx
   step%ky=step%wave%kry
   step%comp=step%wave%rec
   deallocate(step%maxs,step%srefs)
   allocate(step%maxs(size(step%comp%slow%reference(step%iz+step%izb)%maxs)))
   allocate(step%srefs(size(step%comp%slow%reference(step%iz+step%izb)%maxs)))
   step%srefs=step%comp%slow%reference(step%iz+step%izb)%sref
   step%maxs=step%comp%slow%reference(step%iz+step%izb)%maxs
#ifdef DEBUG
    write(0,*) "OUT SET RECEIVER"
#endif
  end subroutine


  

  subroutine clean_step(step)
    type(westep) :: step
    integer      :: ith,nkxko
#ifdef DEBUG
    write(0,*) "IN CLEAN STEP"
#endif
    

    deallocate(step%srefs,step%maxs)
    deallocate(step%kx,step%ky)
    deallocate(step%islow,step%slow)
    deallocate(step%ctable)
#ifdef DEBUG
    write(0,*) "OUT CLEAN STEP"
#endif

  end subroutine




end module
