! (C) Copyright 2005- ECMWF.
! (C) Copyright 2013- Meteo-France.
! 
! This software is licensed under the terms of the Apache Licence Version 2.0
! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
! In applying this licence, ECMWF does not waive the privileges and immunities
! granted to it by virtue of its status as an intergovernmental organisation
! nor does it submit to any jurisdiction.
!

MODULE MPL_RECV_MOD

!**** MPL_RECV Receive a message

!     Purpose.
!     --------
!     Receive a message from a named source into a buffer.
!     The data may be REAL*4, REAL*8,or INTEGER, one dimensional array
!                     REAL*4,or REAL*8, two dimensional array
!                  or REAL or INTEGER scalar

!**   Interface.
!     ----------
!        CALL MPL_RECV

!        Input required arguments :
!        -------------------------
!           PBUF     -  buffer to receive the message
!                       (can be type REAL*4, REAL*8 or INTEGER)

!        Input optional arguments :
!        -------------------------
!           KTAG     -  message tag
!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
!           KMP_TYPE -  buffering type (see MPL_BUFFER_METHOD)
!                       overrides value provided to MPL_BUFFER_METHOD
!           KSOURCE  -  rank of process sending the message
!                       default is MPI_ANY_SOURCE
!           CDSTRING -  Character string for ABORT messages
!                       used when KERROR is not provided

!        Output required arguments :
!        -------------------------
!           none

!        Output optional arguments :
!        -------------------------
!           KREQUEST -  Communication request
!                       required when buffering type is non-blocking
!           KFROM    -  rank of process sending the message
!           KRECVTAG -  tag of received message
!           KOUNT    -  number of items in received message
!           KERROR   -  return error code.     If not supplied, 
!                       MPL_RECV aborts when an error is detected.
!     Author.
!     -------
!        D.Dent, M.Hamrud     ECMWF

!     Modifications.
!     --------------
!        Original: 2000-09-01
!      F. Vana  05-Mar-2015  Support for single precision

!     ------------------------------------------------------------------

USE EC_PARKIND , ONLY : JPRD, JPIB, JPIM, JPRM
USE OML_MOD   ,ONLY : OML_MY_THREAD

USE MPL_MPIF
USE MPL_DATA_MODULE
USE MPL_STATS_MOD
USE YOMMPLSTATS
USE MPL_MESSAGE_MOD
USE MPL_NPROC_MOD

IMPLICIT NONE

PRIVATE

INTERFACE MPL_RECV
MODULE PROCEDURE MPL_RECV_REAL4,  MPL_RECV_REAL8, &
               & MPL_RECV_INT,    MPL_RECV_REAL42, MPL_RECV_REAL43, &
               & MPL_RECV_REAL82, MPL_RECV_REAL83, MPL_RECV_INT_SCALAR, &
               & MPL_RECV_INT2,   MPL_RECV_REAL4_SCALAR, &
               & MPL_RECV_REAL8_SCALAR, MPL_RECV_CHAR_SCALAR, &
               & MPL_RECV_INT8, MPL_RECV_CHAR
END INTERFACE

PUBLIC MPL_RECV

CONTAINS

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_PREAMB(KMP_TYPER,KCOMMR,KSOURCER,KTAGR,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)
INTEGER(KIND=JPIM),INTENT(OUT) :: KMP_TYPER,KCOMMR,KSOURCER,KTAGR
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KMP_TYPE,KCOMM,KSOURCE,KTAG
INTEGER(KIND=JPIM),OPTIONAL :: KREQUEST

LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID

ITID = OML_MY_THREAD()

IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE(&
  & CDMESSAGE='MPL_RECV: MPL NOT INITIALISED ',LDABORT=LLABORT) 

IF(PRESENT(KMP_TYPE)) THEN
  KMP_TYPER=KMP_TYPE
ELSE
  KMP_TYPER=MPL_METHOD
ENDIF

IF(KMP_TYPER == JP_NON_BLOCKING_STANDARD) THEN
  IF( .NOT. PRESENT(KREQUEST)) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:KREQUEST MISSING ',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(PRESENT(KCOMM)) THEN
  KCOMMR=KCOMM
ELSE
  KCOMMR=MPL_COMM_OML(ITID)
ENDIF

IF(PRESENT(KSOURCE)) THEN
  IF(KSOURCE < 1 .OR. KSOURCE >MPL_NPROC(KCOMMR)) THEN
    WRITE(MPL_ERRUNIT,*)'MPL_RECV: ERROR KSOURCE=',KSOURCE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL KSOURCE ',LDABORT=LLABORT)
  ENDIF
  KSOURCER=KSOURCE-1
ELSE
  KSOURCER=MPI_ANY_SOURCE
ENDIF

IF(PRESENT(KTAG)) THEN
  KTAGR=KTAG
ELSE
  KTAGR=MPI_ANY_TAG
ENDIF

END SUBROUTINE MPL_RECV_PREAMB

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_TAIL(KRECV_STATUS,KTYPE,KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8, MPI_GET_COUNT => MPI_GET_COUNT8
#endif

INTEGER(KIND=JPIM),INTENT(IN) :: KRECV_STATUS(MPI_STATUS_SIZE)
INTEGER(KIND=JPIM),INTENT(IN) :: KTYPE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: IFROM,IRECVTAG,IRECVCOUNT
LOGICAL :: LLABORT=.TRUE.

IFROM=KRECV_STATUS(MPI_SOURCE)+1
IF(PRESENT(KFROM)) THEN
  KFROM=IFROM
ENDIF
CALL MPI_GET_COUNT(KRECV_STATUS,KTYPE,IRECVCOUNT,IERROR)
IF(PRESENT(KOUNT)) THEN
  KOUNT=IRECVCOUNT
ENDIF
IF(LMPLSTATS) CALL MPL_RECVSTATS(IRECVCOUNT,KTYPE)
IRECVTAG=KRECV_STATUS(MPI_TAG)
IF(PRESENT(KRECVTAG)) THEN
  KRECVTAG=IRECVTAG
ENDIF
!IF(MPL_OUTPUT > 1 )THEN
!  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_RECV ',IRECVCOUNT,IMP_TYPE,IFROM,IRECVTAG,ICOMM
!ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_RECV',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_RECV_TAIL

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_REAL4(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif


REAL(KIND=JPRM)            :: PBUF(:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
REAL(KIND=JPRM)    :: ZDUM(1)
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(PBUF)

#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(PBUF(UBOUND(PBUF,1))) - LOC(PBUF(LBOUND(PBUF,1)))) /= 4_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IBUFFSIZE == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(ZDUM(1),1,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(ZDUM(1),1,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(ZDUM(1),1,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL4),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_REAL4))
ENDIF

END SUBROUTINE MPL_RECV_REAL4  

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_REAL8(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

! real_b,intent(in) :: PBUF(:)
REAL(KIND=JPRD)            :: PBUF(:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
REAL(KIND=JPRD)    :: ZDUM(1)
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(PBUF)
#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(PBUF(UBOUND(PBUF,1))) - LOC(PBUF(LBOUND(PBUF,1)))) /= 8_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IBUFFSIZE == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(ZDUM(1),1,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(ZDUM(1),1,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(ZDUM(1),1,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(PBUF(1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_REAL8))
ENDIF

END SUBROUTINE MPL_RECV_REAL8

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_INT(KBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,KOUNT,&
 &KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

INTEGER(KIND=JPIM)           :: KBUF(:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID,IDUM(1)
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(KBUF)
#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(KBUF(UBOUND(KBUF,1)))-LOC(KBUF(LBOUND(KBUF,1)))) /= 4_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IBUFFSIZE == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(IDUM(1),1,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(IDUM(1),1,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(IDUM(1),1,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_INTEGER))
ENDIF

END SUBROUTINE MPL_RECV_INT

SUBROUTINE MPL_RECV_INT8(KBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,KOUNT,&
 &KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

INTEGER(KIND=JPIB)           :: KBUF(:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
INTEGER(KIND=JPIB) :: IDUM(1)
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(KBUF)
#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(KBUF(UBOUND(KBUF,1)))-LOC(KBUF(LBOUND(KBUF,1)))) /= 8_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IBUFFSIZE == 0 ) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(IDUM(1),1,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(IDUM(1),1,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(IDUM(1),1,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(KBUF(1),IBUFFSIZE,INT(MPI_INTEGER8),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_INTEGER8))
ENDIF

END SUBROUTINE MPL_RECV_INT8

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_INT2(KBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

INTEGER(KIND=JPIM)           :: KBUF(:,:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID, IDUM(1)
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(KBUF)
#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(KBUF(UBOUND(KBUF,1),UBOUND(KBUF,2))) - &
     & LOC(KBUF(LBOUND(KBUF,1),LBOUND(KBUF,2)))) /= 4_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IBUFFSIZE == 0 ) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(IDUM(1),1,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(IDUM(1),1,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(IDUM(1),1,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(KBUF(1,1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(KBUF(1,1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(KBUF(1,1),IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_INTEGER))
ENDIF

END SUBROUTINE MPL_RECV_INT2

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_INT_SCALAR(KINT,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

INTEGER(KIND=JPIM)           :: KINT
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = 1

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_RECV(KINT,IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_RECV(KINT,IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_IRECV(KINT,IBUFFSIZE,INT(MPI_INTEGER),ISOURCE,ITAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE
  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_INTEGER),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_INTEGER))
ENDIF

END SUBROUTINE MPL_RECV_INT_SCALAR

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_REAL4_SCALAR(PREAL4,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif


REAL(KIND=JPRM)           :: PREAL4
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = 1

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_RECV(PREAL4,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_RECV(PREAL4,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_IRECV(PREAL4,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE
  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL4),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_REAL4))
ENDIF

END SUBROUTINE MPL_RECV_REAL4_SCALAR

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_REAL8_SCALAR(PREAL8,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

REAL(KIND=JPRD)           :: PREAL8
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = 1

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_RECV(PREAL8,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_RECV(PREAL8,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_IRECV(PREAL8,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
   & KREQUEST,IERROR)
ELSE
  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_REAL8))
ENDIF

END SUBROUTINE MPL_RECV_REAL8_SCALAR

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_REAL42(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8, MPI_IRECV => MPI_IRECV8
#endif


REAL(KIND=JPRM)            :: PBUF(:,:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
REAL(KIND=JPRM)    :: ZDUM(1)
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(PBUF)
#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2))) - &
     & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2)))) /= 4_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IBUFFSIZE == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(ZDUM(1),1,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(ZDUM(1),1,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(ZDUM(1),1,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL4),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_REAL4))
ENDIF

END SUBROUTINE MPL_RECV_REAL42  

SUBROUTINE MPL_RECV_REAL43(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

REAL(KIND=JPRM)            :: PBUF(:,:,:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(PBUF)

#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2),UBOUND(PBUF,3))) - &
     & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2),LBOUND(PBUF,3)))) /= 4_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_RECV(PBUF,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_RECV(PBUF,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_IRECV(PBUF,IBUFFSIZE,INT(MPI_REAL4),ISOURCE,ITAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE
  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL4),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_REAL4))
ENDIF

END SUBROUTINE MPL_RECV_REAL43


!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_REAL82(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

REAL(KIND=JPRD)            :: PBUF(:,:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
REAL(KIND=JPRD)    :: ZDUM(1)
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(PBUF)
#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2))) - &
     & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2)))) /= 8_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IBUFFSIZE == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(ZDUM(1),1,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(ZDUM(1),1,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(ZDUM(1),1,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_RECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_RECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
  ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_IRECV(PBUF(1,1),IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
     & KREQUEST,IERROR)
  ELSE
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_REAL8))
ENDIF

END SUBROUTINE MPL_RECV_REAL82

SUBROUTINE MPL_RECV_REAL83(PBUF,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

REAL(KIND=JPRD)            :: PBUF(:,:,:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = SIZE(PBUF)

#ifndef NAG
IF (IBUFFSIZE > 0) THEN
  IF( (LOC(PBUF(UBOUND(PBUF,1),UBOUND(PBUF,2),UBOUND(PBUF,3))) - &
     & LOC(PBUF(LBOUND(PBUF,1),LBOUND(PBUF,2),LBOUND(PBUF,3)))) /= 8_JPIB*(IBUFFSIZE - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_RECV(PBUF,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_RECV(PBUF,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_IRECV(PBUF,IBUFFSIZE,INT(MPI_REAL8),ISOURCE,ITAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE
  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_REAL8),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_REAL8))
ENDIF

END SUBROUTINE MPL_RECV_REAL83

!     ------------------------------------------------------------------

SUBROUTINE MPL_RECV_CHAR_SCALAR(CDCHAR,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

CHARACTER(LEN=*) :: CDCHAR
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = LEN(CDCHAR)

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_RECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_RECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_IRECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE
  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_BYTE),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_BYTE))
ENDIF

END SUBROUTINE MPL_RECV_CHAR_SCALAR

SUBROUTINE MPL_RECV_CHAR(CDCHAR,KSOURCE,KTAG,KCOMM,KFROM,KRECVTAG,&
 &KOUNT,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_RECV => MPI_RECV8,  MPI_IRECV => MPI_IRECV8
#endif

CHARACTER(LEN=*) :: CDCHAR(:)
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KTAG,KCOMM,KMP_TYPE,KSOURCE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR,KFROM,KRECVTAG,KOUNT
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: IBUFFSIZE,IMP_TYPE,ICOMM,IERROR 
INTEGER(KIND=JPIM) :: ISOURCE,ITAG
INTEGER(KIND=JPIM) :: IRECV_STATUS(MPI_STATUS_SIZE)
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

CALL MPL_RECV_PREAMB(IMP_TYPE,ICOMM,ISOURCE,ITAG,KMP_TYPE,KCOMM,KSOURCE,KTAG,KREQUEST)

IBUFFSIZE = LEN(CDCHAR) * SIZE(CDCHAR)

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_RECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_RECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM,IRECV_STATUS,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_IRECV(CDCHAR,IBUFFSIZE,INT(MPI_BYTE),ISOURCE,ITAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE
  CALL MPL_MESSAGE(CDMESSAGE='MPL_RECV:ILLEGAL MP_TYPE ',LDABORT=LLABORT)
ENDIF

IF(IMP_TYPE /= JP_NON_BLOCKING_STANDARD) THEN
  CALL MPL_RECV_TAIL(IRECV_STATUS,INT(MPI_BYTE),KFROM,KOUNT,KRECVTAG,KERROR,CDSTRING)
ELSE
  IF(LMPLSTATS) CALL MPL_RECVSTATS(IBUFFSIZE,INT(MPI_BYTE))
ENDIF

END SUBROUTINE MPL_RECV_CHAR

!     ------------------------------------------------------------------

END MODULE MPL_RECV_MOD
