#define __PIO_FILE__ "rearrange.F90"
!>
!! @file 
!! $Revision$
!! $LastChangedDate$
!! @brief Generic interface to the rearrange layer
!<

module rearrange

  use pio_kinds
  use pio_types
  use pio_support
  use box_rearrange


#ifdef TIMING
  use perf_mod, only : t_startf, t_stopf, t_barrierf     ! _EXTERNAL
#endif

  implicit none
  private
  save

!> 
!! @private
!<
  public :: rearrange_init, &
            rearrange_create, &
            rearrange_comp2io, &
            rearrange_io2comp, &
            rearrange_free

  interface rearrange_init
    module procedure rearrange_init_
  end interface


  interface rearrange_create
    module procedure rearrange_create_box_
  end interface

  interface rearrange_comp2io
    ! TYPE real,double,int
    module procedure rearrange_comp2io_{TYPE}
  end interface

  interface rearrange_io2comp
    ! TYPE real,double,int
    module procedure rearrange_io2comp_{TYPE}
  end interface

  interface rearrange_free
    module procedure rearrange_free_
  end interface


contains

! TYPE real,double,int
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! rearrange_comp2io_{TYPE}
!

  subroutine rearrange_comp2io_{TYPE}(Iosystem,iodesc,compbuf,iobuf)
    implicit none

    type (Iosystem_desc_t) :: Iosystem
    type (io_desc_t)   :: iodesc
    {VTYPE}, intent(in) ::  compbuf(:)
    {VTYPE}, intent(out) :: iobuf(:)

#ifdef TIMING
    call t_barrierf("pio_rearrange_comp2io_{TYPE}",IoSystem%comp_comm)
    call t_startf("PIO:pio_rearrange_comp2io_{TYPE}")
#endif


    call box_rearrange_comp2io(Iosystem,iodesc,size(compbuf), compbuf,size(iobuf), iobuf)

#ifdef TIMING
    call t_stopf("PIO:pio_rearrange_comp2io_{TYPE}")
#endif

  end subroutine rearrange_comp2io_{TYPE}




! TYPE real,double,int
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! rearrange_io2comp_{TYPE}
!
  subroutine rearrange_io2comp_{TYPE} (Iosystem,iodesc,iobuf,compbuf)
    implicit none

    type (Iosystem_desc_t) :: Iosystem
    type(io_desc_t) :: iodesc
    {VTYPE} :: iobuf(:)
    {VTYPE} ::  compbuf(:)

#ifdef TIMING
    call t_startf("PIO:pio_rearrange_io2comp_{TYPE}")
#endif

    call box_rearrange_io2comp(Iosystem,iodesc,size(iobuf),iobuf,size(compbuf),compbuf)

#ifdef TIMING
    call t_stopf("PIO:pio_rearrange_io2comp_{TYPE}")
#endif

  end subroutine rearrange_io2comp_{TYPE}


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! rearrange_init
! 
! called from initFile_
!


  subroutine rearrange_init_(Iosystem)
    implicit none

    type (Iosystem_desc_t), intent(inout) :: Iosystem



        ! no general init required for box rearranger

  end subroutine rearrange_init_

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!  rearrange_create_box_
!
!  called from initDecomp
!


  subroutine rearrange_create_box_(Iosystem,compDOF, &
                               dims,ndims,ioDesc)
    implicit none

    type (Iosystem_desc_t), intent(in) :: Iosystem
    integer (kind=pio_offset), intent(in) :: compDOF(:)
    integer, intent(in) :: dims(:)
    integer, intent(in) :: ndims
    type (IO_desc_t) :: ioDesc
    
#ifdef TIMING
     call t_startf("PIO:pio_rearrange_create_box")
#endif

    if (Iosystem%rearr /= PIO_rearr_box) then
      call piodie( __PIO_FILE__,__LINE__, &
           'rearrange_create called with args for box but rearranger type is not box, Iosystem%rearr=',&
           Iosystem%rearr)
    endif


    call box_rearrange_create( Iosystem,compDOF,dims,ndims,Iosystem%num_iotasks,ioDesc)


#ifdef TIMING
     call t_stopf("PIO:pio_rearrange_create_box")
#endif

  end subroutine rearrange_create_box_




!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! rearrange_free_
!
! called from freeDecomp


  subroutine rearrange_free_(Iosystem,ioDesc)
    implicit none

    type (Iosystem_desc_t), intent(in) :: Iosystem
    type (IO_desc_t)                   :: ioDesc


    select case (Iosystem%rearr)
    case (PIO_rearr_box)
       call box_rearrange_free(Iosystem,ioDesc)
    case (PIO_rearr_none)
        ! do nothing 

    case default
       call piodie(__PIO_FILE__,__LINE__,'Unrecognized rearranger:',Iosystem%rearr)

    end select


  end subroutine rearrange_free_


end module rearrange



