! (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_SEND_MOD

!**** MPL_SEND Send a message

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

!**   Interface.
!     ----------
!        CALL MPL_SEND

!        Input required arguments :
!        -------------------------
!           PBUF     -  buffer containing message
!                       (can be type REAL*4, REAL*8 or INTEGER)
!           KTAG     -  message tag
!           KDEST    -  rank of process to receive the message

!        Input optional arguments :
!        -------------------------
!           KCOMM    -  Communicator number if different from MPI_COMM_WORLD 
!                       or from that established as the default 
!                       by an MPL communicator routine
!           KMP_TYPE -  buffering type (see MPL_BUFFER_METHOD)
!                       overrides value provided to MPL_BUFFER_METHOD
!           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
!           KERROR   -  return error code.     If not supplied, 
!                       MPL_SEND aborts when an error is detected.
!     Author.
!     -------
!        D.Dent, M.Hamrud     ECMWF

!     Modifications.
!     --------------
!        Original: 2000-09-01
!        P. Marguinaud : 01-Jan-2011 : Do not raise an error when
!                        the numproc is beyond model limits and KCOMM is passed
!                        as argument
!      F. Vana  05-Mar-2015  Support for single precision
!     ------------------------------------------------------------------

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

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

IMPLICIT NONE

PRIVATE

!---Moved into subroutines to keep threadsafe----
! INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
! LOGICAL :: LLABORT=.TRUE.

INTERFACE MPL_SEND
MODULE PROCEDURE MPL_SEND_REAL4, MPL_SEND_REAL8,&
               & MPL_SEND_INT,   MPL_SEND_REAL42, MPL_SEND_REAL43, &
               & MPL_SEND_REAL82,MPL_SEND_REAL83, MPL_SEND_INT_SCALAR, &
               & MPL_SEND_INT2,  MPL_SEND_CHAR_SCALAR, &
               & MPL_SEND_REAL4_SCALAR, MPL_SEND_REAL8_SCALAR, &
               & MPL_SEND_INT8,  MPL_SEND_CHAR
END INTERFACE

PUBLIC MPL_SEND

CONTAINS

SUBROUTINE MPL_SEND_REAL4(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif


! real_m,intent(in) :: PBUF(:)
REAL(KIND=JPRM)            :: PBUF(:)
INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
REAL(KIND=JPRM)    :: ZDUM(1:0)
ITID = OML_MY_THREAD()

IF(MPL_NUMPROC < 1) CALL MPL_MESSAGE( &
  & CDMESSAGE='MPL_SEND: MPL NOT INITIALISED ',LDABORT=LLABORT) 
  
IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

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

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL4))
ENDIF

IF (ICOUNT == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(PBUF(1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_REAL4  

SUBROUTINE MPL_SEND_REAL8(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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


INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
REAL(KIND=JPRD)    :: ZDUM(1:0)
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

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

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL8))
ENDIF

IF (ICOUNT == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(PBUF(1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_REAL8

SUBROUTINE MPL_SEND_INT(KBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID,IDUM(1:0)
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

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

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_INTEGER))
ENDIF

IF (ICOUNT == 0) THEN
 IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_INT

SUBROUTINE MPL_SEND_INT2(KBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID,IDUM(1:0)
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

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

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_INTEGER))
ENDIF

IF (ICOUNT == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(IDUM,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_INT2

SUBROUTINE MPL_SEND_INT8(KBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
INTEGER(KIND=JPIB) :: IDUM(1:0)
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

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

IF (ICOUNT == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(IDUM,ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(IDUM,ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(IDUM,ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(IDUM,ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(IDUM,ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(KBUF(1),ICOUNT,INT(MPI_INTEGER8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_INT8

SUBROUTINE MPL_SEND_INT_SCALAR(KINT,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

ICOUNT = 1

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_INTEGER))
ENDIF

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_SEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BSEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_ISEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  CALL MPI_IBSEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
  CALL MPI_SSEND(KINT,ICOUNT,INT(MPI_INTEGER),KDEST-1,KTAG,ICOMM,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    KERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_INT_SCALAR

SUBROUTINE MPL_SEND_REAL42(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

! real_m,intent(in) :: PBUF(:,:)
REAL(KIND=JPRM)            :: PBUF(:,:)
INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
REAL(KIND=JPRM)    :: ZDUM(1:0)
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

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

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL4))
ENDIF

IF (ICOUNT == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(ZDUM,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_REAL42  

SUBROUTINE MPL_SEND_REAL43(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

! real_b,intent(in) :: PBUF(:,:,:)
REAL(KIND=JPRM)            :: PBUF(:,:,:)
INTEGER(KIND=JPIM),INTENT(IN) :: KDEST,KTAG
INTEGER(KIND=JPIM),INTENT(IN),OPTIONAL :: KCOMM,KMP_TYPE
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KREQUEST,KERROR
CHARACTER(LEN=*),INTENT(IN),OPTIONAL :: CDSTRING

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM).AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

ICOUNT = SIZE(PBUF)

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL4))
ENDIF

#ifndef NAG
IF (ICOUNT > 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*(ICOUNT - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_SEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BSEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_ISEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  CALL MPI_IBSEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
  CALL MPI_SSEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    KERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_REAL43



SUBROUTINE MPL_SEND_REAL82(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
REAL(KIND=JPRD)    :: ZDUM(1:0)
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

ICOUNT = SIZE(PBUF)

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL8))
ENDIF

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

IF (ICOUNT == 0) THEN
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(ZDUM,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ELSE
  IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
    CALL MPI_SEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
    CALL MPI_BSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
    CALL MPI_ISEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
    CALL MPI_IBSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
      & KREQUEST,IERROR)
  ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
    CALL MPI_SSEND(PBUF(1,1),ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
  ELSE
    IF(PRESENT(KERROR)) THEN
      KERROR=1
    ELSE
      CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
    ENDIF
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_REAL82


SUBROUTINE MPL_SEND_CHAR_SCALAR(CDCHAR,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

ICOUNT = LEN(CDCHAR)

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_BYTE))
ENDIF

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_SEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_ISEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  CALL MPI_IBSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
  CALL MPI_SSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    KERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_CHAR_SCALAR

SUBROUTINE MPL_SEND_CHAR(CDCHAR,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

ICOUNT = LEN(CDCHAR) * SIZE(CDCHAR)

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_BYTE))
ENDIF

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_SEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_ISEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  CALL MPI_IBSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
  CALL MPI_SSEND(CDCHAR,ICOUNT,INT(MPI_BYTE),KDEST-1,KTAG,ICOMM,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    KERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_CHAR

SUBROUTINE MPL_SEND_REAL4_SCALAR(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

ICOUNT = 1

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL4))
ENDIF

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_SEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BSEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_ISEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  CALL MPI_IBSEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
  CALL MPI_SSEND(PBUF,ICOUNT,INT(MPI_REAL4),KDEST-1,KTAG,ICOMM,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    KERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_REAL4_SCALAR

SUBROUTINE MPL_SEND_REAL8_SCALAR(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF((KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM)) .AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

ICOUNT = 1

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL8))
ENDIF

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_SEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_ISEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  CALL MPI_IBSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
  CALL MPI_SSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    KERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_REAL8_SCALAR

SUBROUTINE MPL_SEND_REAL83(PBUF,KDEST,KTAG,KCOMM,KMP_TYPE,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_SEND => MPI_SEND8, MPI_BSEND => MPI_BSEND8, MPI_ISEND => MPI_ISEND8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,IMP_TYPE,ICOMM,IERROR
LOGICAL :: LLABORT=.TRUE.
INTEGER(KIND=JPIM) :: ITID
ITID = OML_MY_THREAD()

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

IF(PRESENT(KMP_TYPE)) THEN
  IMP_TYPE=KMP_TYPE
ELSE
  IMP_TYPE=MPL_METHOD
ENDIF
IF(PRESENT(KCOMM)) THEN
  ICOMM=KCOMM
ELSE
  ICOMM=MPL_COMM_OML(ITID)
ENDIF
IF(KDEST < 1 .OR. KDEST >MPL_NPROC(ICOMM).AND. (.NOT. PRESENT (KCOMM))) THEN
  WRITE(MPL_ERRUNIT,*)'MPL_SEND: ERROR KDEST=',KDEST
  CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND:ILLEGAL KDEST ',LDABORT=LLABORT)
ENDIF

ICOUNT = SIZE(PBUF)

IF(LMPLSTATS) THEN
  CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL8))
ENDIF

#ifndef NAG
IF (ICOUNT > 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*(ICOUNT - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_SEND: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD) THEN
  CALL MPI_SEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_STANDARD) THEN
  CALL MPI_ISEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  CALL MPI_IBSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM, &
    & KREQUEST,IERROR)
ELSE IF(IMP_TYPE == JP_BLOCKING_SYNCHRONOUS) THEN
  CALL MPI_SSEND(PBUF,ICOUNT,INT(MPI_REAL8),KDEST-1,KTAG,ICOMM,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    KERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_SEND',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(MPL_OUTPUT > 1 )THEN
  WRITE(MPL_UNIT,'(A,5I8)') ' MPL_SEND ',ICOUNT,IMP_TYPE,KDEST,KTAG,ICOMM
ENDIF
IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_SEND',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_SEND_REAL83

END MODULE MPL_SEND_MOD
