#define DBG0 if(pid==0)print*, __FILE__, __LINE__
#define DBG  print*, pid ,__FILE__, __LINE__
!#################################################################################################
!-------------------------------------------------------------------------------------------------
  module irrp_smpi_mod
!-------------------------------------------------------------------------------------------------
  public
!-------------------------------------------------------------------------------------------------
  include "mpif.h"
  type mpipacket
    integer :: bsize = 0
    integer :: pos = 0
    integer :: dsize = 0
    integer(4), pointer :: buf(:)=>null()
  end type mpipacket
!-------------------------------------------------------------------------------------------------
  interface set_mpipacket; module procedure &
    set_mpipacket_3d_cc, set_mpipacket_2d_cc, set_mpipacket_1d_cc, set_mpipacket_0d_cc, &
    set_mpipacket_3d_i1, set_mpipacket_2d_i1, set_mpipacket_1d_i1, set_mpipacket_0d_i1, &
    set_mpipacket_3d_i2, set_mpipacket_2d_i2, set_mpipacket_1d_i2, set_mpipacket_0d_i2, &
    set_mpipacket_3d_i4, set_mpipacket_2d_i4, set_mpipacket_1d_i4, set_mpipacket_0d_i4, &
    set_mpipacket_3d_r4, set_mpipacket_2d_r4, set_mpipacket_1d_r4, set_mpipacket_0d_r4, &
    set_mpipacket_3d_r8, set_mpipacket_2d_r8, set_mpipacket_1d_r8, set_mpipacket_0d_r8
  end interface set_mpipacket
  interface get_mpipacket; module procedure &
    get_mpipacket_3d_cc, get_mpipacket_2d_cc, get_mpipacket_1d_cc, get_mpipacket_0d_cc, &
    get_mpipacket_3d_i1, get_mpipacket_2d_i1, get_mpipacket_1d_i1, get_mpipacket_0d_i1, &
    get_mpipacket_3d_i2, get_mpipacket_2d_i2, get_mpipacket_1d_i2, get_mpipacket_0d_i2, &
    get_mpipacket_3d_i4, get_mpipacket_2d_i4, get_mpipacket_1d_i4, get_mpipacket_0d_i4, &
    get_mpipacket_3d_r4, get_mpipacket_2d_r4, get_mpipacket_1d_r4, get_mpipacket_0d_r4, &
    get_mpipacket_3d_r8, get_mpipacket_2d_r8, get_mpipacket_1d_r8, get_mpipacket_0d_r8
  end interface get_mpipacket
  interface irrp_pget_mpipacket; module procedure &
    pget_mpipacket_2d_cc, pget_mpipacket_1d_cc, pget_mpipacket_0d_cc, &
    pget_mpipacket_2d_i1, pget_mpipacket_1d_i1, pget_mpipacket_0d_i1, &
    pget_mpipacket_2d_i2, pget_mpipacket_1d_i2, pget_mpipacket_0d_i2, &
    pget_mpipacket_2d_i4, pget_mpipacket_1d_i4, pget_mpipacket_0d_i4, &
    pget_mpipacket_2d_r4, pget_mpipacket_1d_r4, pget_mpipacket_0d_r4, &
    pget_mpipacket_2d_r8, pget_mpipacket_1d_r8, pget_mpipacket_0d_r8, &
    pget_mpipacket_4d_cc, pget_mpipacket_3d_cc, &
    pget_mpipacket_4d_i1, pget_mpipacket_3d_i1, &
    pget_mpipacket_4d_i2, pget_mpipacket_3d_i2, &
    pget_mpipacket_4d_i4, pget_mpipacket_3d_i4, &
    pget_mpipacket_4d_r4, pget_mpipacket_3d_r4, &
    pget_mpipacket_4d_r8, pget_mpipacket_3d_r8 
  end interface irrp_pget_mpipacket
!-------------------------------------------------------------------------------------------------
  contains
!-------------------------------------------------------------------------------------------------
 subroutine Zbarrier(comm, npe)
    integer, intent(in) :: npe, comm
    integer :: it
    integer, allocatable, save :: vi(:)
    integer :: ierr
   if(.not.allocated(vi))allocate(vi(npe))
    call MPI_GATHER(it, 1, MPI_INTEGER, vi, 1, MPI_INTEGER, 0, comm, ierr)
 end subroutine Zbarrier
  subroutine irrp_abort(file, line, msg)
    character(len=*), intent(in) :: file
    integer, intent(in) :: line
    character(len=*), intent(in), optional :: msg
    integer :: it
    print*,"aa"//"bb"//file
    if(present(msg))then
      write(6,'(a,i5,2a )')'IRRP Error ',line,' ',msg
    else
      write(6,'(a,i5)')'IRRP Error ',line
    endif
    call MPI_FINALIZE(it); stop
  end subroutine irrp_abort
!-------------------------------------------------------------------------------------------------
! Set dsize and pos equal to zero as initial of mpipacket
! If lsize is given, allocate memory for the buffer.
  subroutine InitMpiPacket(pk, lsize)
    type(mpipacket), intent(inout) :: pk
    integer*4, optional, intent(in) :: lsize
    if(present(lsize))then
      if(lsize<=0 .or. pk%bsize<lsize)then
        if(pk%bsize > 0)then
          deallocate(pk%buf) ! If buf is not empty, deallocate it first.
          pk%bsize = 0 ! And set bsize equal to zero.
        endif
        if(lsize>0)then ! If lsize is given and greater than 0,
          pk%bsize = lsize ! set it as bsize and use it to allocate buf.
          allocate(pk%buf((pk%bsize+4)/4))
        endif
      endif
    endif
    pk%dsize = 0; pk%pos = 0 ! Initialize dsize and pos for the begining of packet.
  end subroutine InitMpiPacket
  subroutine FinalMpiPacket(pk)
    type(mpipacket), intent(inout) :: pk
    pk%bsize = 0; pk%pos = 0; pk%dsize = 0
    if(associated(pk%buf))then; deallocate(pk%buf); nullify(pk%buf); endif
  end subroutine FinalMpiPacket
! Get dsize before using it (i.e. send, isend, bcast, unpack, recv, irecv, ...)
  subroutine SetMpiPacketDSize(pk, dsize)
     type(mpipacket), intent(inout) :: pk
     integer*4, optional, intent(in) :: dsize
     if(present(dsize))then
       pk%dsize = dsize
     else
       pk%dsize = pk%pos
     endif
     pk%pos = 0
  end subroutine SetMpiPacketDSize
  subroutine bcast_packet(pk, root, pid, mpicomm)
    type(mpipacket), intent(inout) :: pk
    integer, intent(in) :: root, pid, mpicomm
    integer :: lsize, ierr
    !if(pid == root)then
    call SetMpiPacketDSize(pk)
    lsize = pk%dsize;
    !endif
    DBG0,lsize
    call MPI_BCAST(lsize, 1, MPI_INTEGER4, root, mpicomm, ierr)
    if(pid /= root)then
      call InitMpiPacket(pk, lsize+100)
    endif
    call MPI_BCAST(pk%buf, lsize, MPI_PACKED, root, mpicomm, ierr)
    !if(pid /= root)then
    call SetMpiPacketDSize(pk, lsize)
    !endif
  end subroutine bcast_packet
 subroutine set_mpipacket_0d_i1(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(1), intent(in) :: var
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_0d_i1
 subroutine set_mpipacket_1d_i1(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(1), intent(in) :: var (:)
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_1d_i1
 subroutine set_mpipacket_2d_i1(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(1), intent(in) :: var (:,:)
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_2d_i1
 subroutine set_mpipacket_3d_i1(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(1), intent(in) :: var (:,:,:)
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_3d_i1
 subroutine set_mpipacket_0d_i2(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(2), intent(in) :: var
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_0d_i2
 subroutine set_mpipacket_1d_i2(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(2), intent(in) :: var (:)
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_1d_i2
 subroutine set_mpipacket_2d_i2(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(2), intent(in) :: var (:,:)
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_2d_i2
 subroutine set_mpipacket_3d_i2(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(2), intent(in) :: var (:,:,:)
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_3d_i2
 subroutine set_mpipacket_0d_i4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(4), intent(in) :: var
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_0d_i4
 subroutine set_mpipacket_1d_i4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(4), intent(in) :: var (:)
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_1d_i4
 subroutine set_mpipacket_2d_i4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(4), intent(in) :: var (:,:)
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_2d_i4
 subroutine set_mpipacket_3d_i4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(4), intent(in) :: var (:,:,:)
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_3d_i4
 subroutine set_mpipacket_0d_r4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(4), intent(in) :: var
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_0d_r4
 subroutine set_mpipacket_1d_r4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(4), intent(in) :: var (:)
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_1d_r4
 subroutine set_mpipacket_2d_r4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(4), intent(in) :: var (:,:)
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_2d_r4
 subroutine set_mpipacket_3d_r4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(4), intent(in) :: var (:,:,:)
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_3d_r4
 subroutine set_mpipacket_0d_r8(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(8), intent(in) :: var
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_0d_r8
 subroutine set_mpipacket_1d_r8(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(8), intent(in) :: var (:)
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_1d_r8
 subroutine set_mpipacket_2d_r8(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(8), intent(in) :: var (:,:)
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_2d_r8
 subroutine set_mpipacket_3d_r8(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(8), intent(in) :: var (:,:,:)
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_3d_r8
 subroutine set_mpipacket_0d_cc(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 character(len=*), intent(in) :: var
 call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_0d_cc
 subroutine set_mpipacket_1d_cc(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 character(len=*), intent(in) :: var (:)
 call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_1d_cc
 subroutine set_mpipacket_2d_cc(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 character(len=*), intent(in) :: var (:,:)
 call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_2d_cc
 subroutine set_mpipacket_3d_cc(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 character(len=*), intent(in) :: var (:,:,:)
 call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpi_comm, ierr)
 end subroutine set_mpipacket_3d_cc
 subroutine get_mpipacket_0d_i1(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(1), intent(out) :: var
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpi_comm, ierr)
 end subroutine get_mpipacket_0d_i1
 subroutine get_mpipacket_1d_i1(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(1), intent(out) :: var (:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpi_comm, ierr)
 end subroutine get_mpipacket_1d_i1
 subroutine get_mpipacket_2d_i1(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(1), intent(out) :: var (:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpi_comm, ierr)
 end subroutine get_mpipacket_2d_i1
 subroutine get_mpipacket_3d_i1(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(1), intent(out) :: var (:,:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpi_comm, ierr)
 end subroutine get_mpipacket_3d_i1
 subroutine get_mpipacket_0d_i2(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(2), intent(out) :: var
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpi_comm, ierr)
 end subroutine get_mpipacket_0d_i2
 subroutine get_mpipacket_1d_i2(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(2), intent(out) :: var (:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpi_comm, ierr)
 end subroutine get_mpipacket_1d_i2
 subroutine get_mpipacket_2d_i2(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(2), intent(out) :: var (:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpi_comm, ierr)
 end subroutine get_mpipacket_2d_i2
 subroutine get_mpipacket_3d_i2(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(2), intent(out) :: var (:,:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpi_comm, ierr)
 end subroutine get_mpipacket_3d_i2
 subroutine get_mpipacket_0d_i4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(4), intent(out) :: var
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpi_comm, ierr)
 end subroutine get_mpipacket_0d_i4
 subroutine get_mpipacket_1d_i4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(4), intent(out) :: var (:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpi_comm, ierr)
 end subroutine get_mpipacket_1d_i4
 subroutine get_mpipacket_2d_i4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(4), intent(out) :: var (:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpi_comm, ierr)
 end subroutine get_mpipacket_2d_i4
 subroutine get_mpipacket_3d_i4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 integer(4), intent(out) :: var (:,:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpi_comm, ierr)
 end subroutine get_mpipacket_3d_i4
 subroutine get_mpipacket_0d_r4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(4), intent(out) :: var
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpi_comm, ierr)
 end subroutine get_mpipacket_0d_r4
 subroutine get_mpipacket_1d_r4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(4), intent(out) :: var (:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpi_comm, ierr)
 end subroutine get_mpipacket_1d_r4
 subroutine get_mpipacket_2d_r4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(4), intent(out) :: var (:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpi_comm, ierr)
 end subroutine get_mpipacket_2d_r4
 subroutine get_mpipacket_3d_r4(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(4), intent(out) :: var (:,:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpi_comm, ierr)
 end subroutine get_mpipacket_3d_r4
 subroutine get_mpipacket_0d_r8(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(8), intent(out) :: var
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpi_comm, ierr)
 end subroutine get_mpipacket_0d_r8
 subroutine get_mpipacket_1d_r8(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(8), intent(out) :: var (:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpi_comm, ierr)
 end subroutine get_mpipacket_1d_r8
 subroutine get_mpipacket_2d_r8(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(8), intent(out) :: var (:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpi_comm, ierr)
 end subroutine get_mpipacket_2d_r8
 subroutine get_mpipacket_3d_r8(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 real(8), intent(out) :: var (:,:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpi_comm, ierr)
 end subroutine get_mpipacket_3d_r8
 subroutine get_mpipacket_0d_cc(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 character(len=*), intent(out) :: var
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpi_comm, ierr)
 end subroutine get_mpipacket_0d_cc
 subroutine get_mpipacket_1d_cc(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 character(len=*), intent(out) :: var (:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpi_comm, ierr)
 end subroutine get_mpipacket_1d_cc
 subroutine get_mpipacket_2d_cc(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 character(len=*), intent(out) :: var (:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpi_comm, ierr)
 end subroutine get_mpipacket_2d_cc
 subroutine get_mpipacket_3d_cc(pk, var, n, mpicomm)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm
 character(len=*), intent(out) :: var (:,:,:)
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpi_comm, ierr)
 end subroutine get_mpipacket_3d_cc
 subroutine pget_mpipacket_0d_i1(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(1), intent(inout) :: var
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_0d_i1
 subroutine pget_mpipacket_1d_i1(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(1), intent(inout) :: var (:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_1d_i1
 subroutine pget_mpipacket_2d_i1(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(1), intent(inout) :: var (:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_2d_i1
 subroutine pget_mpipacket_3d_i1(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(1), intent(inout) :: var (:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_3d_i1
 subroutine pget_mpipacket_4d_i1(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(1), intent(inout) :: var (:,:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER1, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER1, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_4d_i1
 subroutine pget_mpipacket_0d_i2(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(2), intent(inout) :: var
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_0d_i2
 subroutine pget_mpipacket_1d_i2(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(2), intent(inout) :: var (:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_1d_i2
 subroutine pget_mpipacket_2d_i2(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(2), intent(inout) :: var (:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_2d_i2
 subroutine pget_mpipacket_3d_i2(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(2), intent(inout) :: var (:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_3d_i2
 subroutine pget_mpipacket_4d_i2(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(2), intent(inout) :: var (:,:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER2, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER2, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_4d_i2
 subroutine pget_mpipacket_0d_i4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(4), intent(inout) :: var
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_0d_i4
 subroutine pget_mpipacket_1d_i4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(4), intent(inout) :: var (:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_1d_i4
 subroutine pget_mpipacket_2d_i4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(4), intent(inout) :: var (:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_2d_i4
 subroutine pget_mpipacket_3d_i4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(4), intent(inout) :: var (:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_3d_i4
 subroutine pget_mpipacket_4d_i4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 integer(4), intent(inout) :: var (:,:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_INTEGER4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_4d_i4
 subroutine pget_mpipacket_0d_r4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(4), intent(inout) :: var
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_0d_r4
 subroutine pget_mpipacket_1d_r4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(4), intent(inout) :: var (:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_1d_r4
 subroutine pget_mpipacket_2d_r4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(4), intent(inout) :: var (:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_2d_r4
 subroutine pget_mpipacket_3d_r4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(4), intent(inout) :: var (:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_3d_r4
 subroutine pget_mpipacket_4d_r4(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(4), intent(inout) :: var (:,:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL4, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_4d_r4
 subroutine pget_mpipacket_0d_r8(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(8), intent(inout) :: var
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_0d_r8
 subroutine pget_mpipacket_1d_r8(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(8), intent(inout) :: var (:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_1d_r8
 subroutine pget_mpipacket_2d_r8(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(8), intent(inout) :: var (:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_2d_r8
 subroutine pget_mpipacket_3d_r8(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(8), intent(inout) :: var (:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_3d_r8
 subroutine pget_mpipacket_4d_r8(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 real(8), intent(inout) :: var (:,:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_REAL8, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_REAL8, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_4d_r8
 
  subroutine pget_mpipacket_0d_cc(pk, var, n, mpicomm, act)
    type(mpipacket), intent(inout) :: pk
    integer, intent(in) :: n, mpicomm, act
    character(len=*), intent(inout) :: var
    integer :: ierr,i
    if(act==0)then
      i=len_trim(var)
      call MPI_PACK(i, 1, MPI_INTEGER4, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
      call MPI_PACK(var, i, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
    elseif(act==1)then
      var=' '
      call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, i, 1, MPI_INTEGER4, mpicomm, ierr)
      call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, i, MPI_CHARACTER, mpicomm, ierr)
    endif
    ! if(act==0)then
    !   i=len_trim(var);!var(l+1:n)=' '
    !   write(*,*)'test 0dcc',i,n
    !   call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
    ! elseif(act==1)then
    !   call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpicomm, ierr)
    ! endif
 end subroutine pget_mpipacket_0d_cc
 
 subroutine pget_mpipacket_1d_cc(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 character(len=*), intent(inout) :: var (:)
 integer :: ierr
! write(*,*)'test 1dcc'
 if(act==0)then
 call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_1d_cc
 subroutine pget_mpipacket_2d_cc(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 character(len=*), intent(inout) :: var (:,:)
 integer :: ierr
! write(*,*)'test 2dcc'
 if(act==0)then
 call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_2d_cc
 subroutine pget_mpipacket_3d_cc(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 character(len=*), intent(inout) :: var (:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_3d_cc
 subroutine pget_mpipacket_4d_cc(pk, var, n, mpicomm, act)
 type(mpipacket), intent(inout) :: pk
 integer, intent(in) :: n, mpicomm, act
 character(len=*), intent(inout) :: var (:,:,:,:)
 integer :: ierr
 if(act==0)then
 call MPI_PACK(var, n, MPI_CHARACTER, pk%buf, pk%bsize, pk%pos, mpicomm, ierr)
 elseif(act==1)then
 call MPI_UNPACK(pk%buf, pk%dsize, pk%pos, var, n, MPI_CHARACTER, mpicomm, ierr)
 endif
 end subroutine pget_mpipacket_4d_cc
!-------------------------------------------------------------------------------------------------
  subroutine next(flg, pid, npe, mpicomm)
    integer, intent(in) :: flg, pid, npe, mpicomm
    integer :: ierr,v
    call flush(6)
    if(flg==2)then
        if(pid==npe-1)call MPI_SEND(v,1,MPI_INTEGER,0,1000,mpicomm,ierr)
    else
      if(pid<npe-1)then
        call MPI_SEND(v,1,MPI_INTEGER,pid+1,1000,mpicomm,ierr)
      else if(flg/=0)then
        call MPI_SEND(v,1,MPI_INTEGER,0,1000,mpicomm,ierr)
      endif
    endif
  end subroutine next
  subroutine prev(flg, pid, npe, mpicomm)
    integer, intent(in) :: flg, pid, npe, mpicomm
    integer :: ierr,v
    integer :: status(MPI_STATUS_SIZE) ! mpi status info
    if(flg==2)then
      if(pid==0)call MPI_RECV(v,1,MPI_INTEGER,npe-1,1000,mpicomm,status,ierr)
    else
      if(pid>0)then
        call MPI_RECV(v,1,MPI_INTEGER,pid-1,1000,mpicomm,status,ierr)
      else if(flg/=0)then
        call MPI_RECV(v,1,MPI_INTEGER,npe-1,1000,mpicomm,status,ierr)
      endif
    endif
  end subroutine prev
  subroutine prevnext(flg, pid, npe, mpicomm)
    integer, intent(in) :: flg, pid, npe, mpicomm
    call prev(flg, pid, npe, mpicomm)
    call Next(flg, pid, npe, mpicomm)
  end subroutine prevnext
!-------------------------------------------------------------------------------------------------
  subroutine barr(pid, npe, mpicomm)
    integer, intent(in) :: pid, npe, mpicomm
    integer :: ierr,v,req,tag
    integer :: status(MPI_STATUS_SIZE) ! mpi status info
    req=0;status=0;tag=10000
    if(pid<npe-1)then
      call MPI_ISEND(v, 1, MPI_INTEGER, pid+1,tag, mpicomm, req, ierr)
    else
      call MPI_ISEND(v, 1, MPI_INTEGER, 0,tag, mpicomm, req, ierr)
    endif
    !call MPI_REQUEST_FREE(req,ierr) ! yinxq 20180102
    if(pid>0)then
      call MPI_RECV(v,1,MPI_INTEGER,pid-1,tag,mpicomm,status,ierr)
    else
      call MPI_RECV(v,1,MPI_INTEGER,npe-1,tag,mpicomm,status,ierr)
    endif
    !call MPI_BARRIER(gsi%mpi_comm,ierr)
  end subroutine barr
!-------------------------------------------------------------------------------------------------
  end module irrp_smpi_mod
!-------------------------------------------------------------------------------------------------
!#################################################################################################
