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

!**** MPL_BROADCAST Message broadcast

!     Purpose.
!     --------
!     Broadcasts a message from the process with rank root
!     to all processes in the group.

!**   Interface.
!     ----------
!        CALL MPL_BROADCAST

!        Input required arguments :
!        -------------------------
!           PBUF     -  buffer containing message
!                       (can be type REAL*4, REAL*8 or INTEGER)
!           KTAG     -  message tag

!        Input optional arguments :
!        -------------------------
!           KROOT    -  number of root process (default=1)
!           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_BROADCAST aborts when an error is detected.
!     Author.
!     -------
!        D.Dent, M.Hamrud, S.Saarinen    ECMWF

!     Modifications.
!     --------------
!        Original: 2000-09-01
!        P.Marguinaud : 2012-04-13 : Cleaning & refactor PREAMB1
!        P.Marguinaud : 2012-09-11 : Add MPL_BROADCAST_LOGICAL1
!        M.Hamrud     : 2014-10-22 : Add nonblocking option
!      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_STATS_MOD
USE YOMMPLSTATS
USE MPL_MESSAGE_MOD
USE MPL_SEND_MOD
USE MPL_RECV_MOD
USE MPL_BARRIER_MOD
USE MPL_MYRANK_MOD

IMPLICIT NONE
PRIVATE

LOGICAL :: LLABORT=.TRUE.

INTERFACE MPL_BROADCAST
MODULE PROCEDURE MPL_BROADCAST_REAL4,MPL_BROADCAST_REAL8, &
     & MPL_BROADCAST_REAL42,MPL_BROADCAST_REAL43,MPL_BROADCAST_REAL44,&
     & MPL_BROADCAST_REAL82,MPL_BROADCAST_REAL83,MPL_BROADCAST_REAL84,&
     & MPL_BROADCAST_REAL4_SCALAR,MPL_BROADCAST_REAL8_SCALAR, &
     & MPL_BROADCAST_INT,MPL_BROADCAST_INT2,MPL_BROADCAST_INT3,MPL_BROADCAST_INT_SCALAR, &
     & MPL_BROADCAST_CHAR_SCALAR, MPL_BROADCAST_CHAR1, &
     & MPL_BROADCAST_LOGICAL_SCALAR, MPL_BROADCAST_LOGICAL1
END INTERFACE

PUBLIC MPL_BROADCAST

CONTAINS

SUBROUTINE MPL_BROADCAST_PREAMB1(KROOTR,KCOMMR,KPL_NUMPROC,KPL_MYRANK,KMP_TYPER,LDRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8
#endif


INTEGER(KIND=JPIM),INTENT(OUT)          :: KROOTR
INTEGER(KIND=JPIM),INTENT(OUT)          :: KCOMMR
INTEGER(KIND=JPIM),INTENT(OUT)          :: KPL_NUMPROC
INTEGER(KIND=JPIM),INTENT(OUT)          :: KPL_MYRANK
INTEGER(KIND=JPIM),INTENT(OUT)          :: KMP_TYPER
LOGICAL,           INTENT(OUT)          :: LDRETURN
INTEGER(KIND=JPIM),INTENT(OUT),OPTIONAL :: KERROR
INTEGER(KIND=JPIM),INTENT(IN), OPTIONAL :: KROOT
INTEGER(KIND=JPIM),INTENT(IN), OPTIONAL :: KCOMM
INTEGER(KIND=JPIM),INTENT(IN), OPTIONAL :: KMP_TYPE

INTEGER(KIND=JPIM) :: IERROR
INTEGER(KIND=JPIM) :: ITID

ITID = OML_MY_THREAD()
IERROR = 0

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

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

IF(KCOMMR == MPL_COMM_OML(ITID)) THEN
  KPL_NUMPROC = MPL_NUMPROC
  KPL_MYRANK  = MPL_RANK
ELSE
  CALL MPI_COMM_SIZE(KCOMMR,KPL_NUMPROC,IERROR)
  KPL_MYRANK  = MPL_MYRANK(KCOMMR)
ENDIF

IF(PRESENT(KROOT)) THEN
  KROOTR=KROOT
ELSE
  KROOTR=1
ENDIF

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

IF (PRESENT (KERROR)) KERROR = IERROR

IF (KPL_NUMPROC == 1) THEN
  IF(PRESENT(KERROR)) THEN
    KERROR=0
  ENDIF
  LDRETURN=.TRUE.
ELSE
  LDRETURN=.FALSE.
ENDIF

END SUBROUTINE MPL_BROADCAST_PREAMB1

SUBROUTINE MPL_BROADCAST_REAL4(PBUF,KTAG,KROOT,KMP_TYPE,&
                               KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = SIZE(PBUF)

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF,ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF,ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL4))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_REAL4))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_REAL4

SUBROUTINE MPL_BROADCAST_REAL8(PBUF,KTAG,KROOT,KMP_TYPE,&
                               KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = SIZE(PBUF)

! Passing PBUF(1) here causes incorrect results on IBM
IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF,ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF,ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL8))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_REAL8))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_REAL8


SUBROUTINE MPL_BROADCAST_REAL42(PBUF,KTAG,KROOT,KMP_TYPE,KCOMM,KERROR,KREQUEST,CDSTRING)

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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

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_BROADCAST: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF(1,1),ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF(1,1),ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL4))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_REAL4))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_BROADCAST_REAL42


SUBROUTINE MPL_BROADCAST_REAL43(PBUF,KTAG,KROOT,KMP_TYPE,KCOMM,KERROR,KREQUEST,CDSTRING)

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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = SIZE(PBUF)
#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_BROADCAST: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF(1,1,1),ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF(1,1,1),ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL4))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_REAL4))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_BROADCAST_REAL43


SUBROUTINE MPL_BROADCAST_REAL44(PBUF,KTAG,KROOT,KMP_TYPE,KCOMM,KERROR,KREQUEST,CDSTRING)

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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

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

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF(1,1,1,1),ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF(1,1,1,1),ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL4))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_REAL4))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_BROADCAST_REAL44


SUBROUTINE MPL_BROADCAST_REAL82(PBUF,KTAG,KROOT,KMP_TYPE,&
                                KCOMM,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif

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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

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)))) /= 8_JPIB*(ICOUNT - 1) ) THEN
    CALL MPL_MESSAGE(CDMESSAGE='MPL_BROADCAST: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF(1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF(1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL8))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_REAL8))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_REAL82

SUBROUTINE MPL_BROADCAST_REAL83(PBUF,KTAG,KROOT,KMP_TYPE,&
                                KCOMM,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = SIZE(PBUF)
#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_BROADCAST: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF(1,1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF(1,1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF
IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL8))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_REAL8))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_REAL83

SUBROUTINE MPL_BROADCAST_REAL84(PBUF,KTAG,KROOT,KMP_TYPE,&
                                KCOMM,KERROR,KREQUEST,CDSTRING)

#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

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

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF(1,1,1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF(1,1,1,1),ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_REAL8))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_REAL8))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_REAL84


SUBROUTINE MPL_BROADCAST_REAL4_SCALAR(PBUF,KTAG,KROOT,KMP_TYPE,&
                                      KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = 1

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF,ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF,ICOUNT,INT(MPI_REAL4),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_BROADCAST_REAL4_SCALAR


SUBROUTINE MPL_BROADCAST_REAL8_SCALAR(PBUF,KTAG,KROOT,KMP_TYPE,&
                                      KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = 1

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(PBUF,ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(PBUF,ICOUNT,INT(MPI_REAL8),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_REAL8_SCALAR


SUBROUTINE MPL_BROADCAST_INT(KBUF,KTAG,KROOT,KMP_TYPE,&
                             KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = SIZE(KBUF)

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(KBUF,ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(KBUF,ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_INTEGER))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_INTEGER))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_INT


SUBROUTINE MPL_BROADCAST_INT2(KBUF,KTAG,KROOT,KMP_TYPE,&
                              KCOMM,KERROR,KREQUEST,CDSTRING)

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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN


CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0
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_BROADCAST: BUFFER NOT CONTIGUOUS ',LDABORT=LLABORT)
  ENDIF
ENDIF
#endif

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(KBUF(1,1),ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_INTEGER))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_INTEGER))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_BROADCAST_INT2


SUBROUTINE MPL_BROADCAST_INT3(KBUF,KTAG,KROOT,KMP_TYPE,&
                              KCOMM,KERROR,KREQUEST,CDSTRING)

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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN


CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0
ICOUNT = SIZE(KBUF)

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

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(KBUF(1,1,1),ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(KBUF(1,1,1),ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_INTEGER))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_INTEGER))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF

END SUBROUTINE MPL_BROADCAST_INT3


SUBROUTINE MPL_BROADCAST_INT_SCALAR(KBUF,KTAG,KROOT,KMP_TYPE,&
                                    KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = 1

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(KBUF,ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(KBUF,ICOUNT,INT(MPI_INTEGER),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_INTEGER))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_INTEGER))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_INT_SCALAR


SUBROUTINE MPL_BROADCAST_CHAR_SCALAR(CDBUF,KTAG,KROOT,KMP_TYPE,&
                                    KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = LEN(CDBUF)

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(CDBUF,ICOUNT,INT(MPI_BYTE),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(CDBUF,ICOUNT,INT(MPI_BYTE),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_BYTE))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_BYTE))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_CHAR_SCALAR

SUBROUTINE MPL_BROADCAST_CHAR1(CDBUF,KTAG,KROOT,KMP_TYPE,&
                               KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = LEN(CDBUF)*SIZE(CDBUF)

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(CDBUF,ICOUNT,INT(MPI_BYTE),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(CDBUF,ICOUNT,INT(MPI_BYTE),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_BYTE))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_BYTE))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_CHAR1

SUBROUTINE MPL_BROADCAST_LOGICAL_SCALAR(LDBUF,KTAG,KROOT,KMP_TYPE,&
                                    KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = 1

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST(LDBUF,ICOUNT,INT(MPI_LOGICAL),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST(LDBUF,ICOUNT,INT(MPI_LOGICAL),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF

IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_BYTE))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_BYTE))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_LOGICAL_SCALAR

SUBROUTINE MPL_BROADCAST_LOGICAL1(LDBUF,KTAG,KROOT,KMP_TYPE,&
                                  KCOMM,KERROR,KREQUEST,CDSTRING)


#ifdef USE_8_BYTE_WORDS
  USE MPI4TO8, ONLY : &
    MPI_COMM_SIZE => MPI_COMM_SIZE8, MPI_BCAST => MPI_BCAST8
#endif


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

INTEGER(KIND=JPIM) :: ICOUNT,ICOMM,IERROR,IROOT,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE
LOGICAL :: LLRETURN

CALL MPL_BROADCAST_PREAMB1(IROOT,ICOMM,IPL_NUMPROC,IPL_MYRANK,IMP_TYPE,LLRETURN,KERROR,KCOMM,KROOT,KMP_TYPE)
IF (LLRETURN) RETURN

IERROR = 0

ICOUNT = SIZE (LDBUF)

IF(IMP_TYPE == JP_BLOCKING_STANDARD .OR. IMP_TYPE == JP_BLOCKING_BUFFERED) THEN
  CALL MPI_BCAST (LDBUF,ICOUNT,INT(MPI_LOGICAL),IROOT-1,ICOMM,IERROR)
ELSEIF(IMP_TYPE == JP_NON_BLOCKING_STANDARD .OR. IMP_TYPE == JP_NON_BLOCKING_BUFFERED) THEN
  IF(.NOT.PRESENT(KREQUEST)) CALL MPL_MESSAGE(KERROR,'MPL_SEND',' KREQUEST MISSING',LDABORT=LLABORT)
  CALL MPI_IBCAST (LDBUF,ICOUNT,INT(MPI_LOGICAL),IROOT-1,ICOMM,KREQUEST,IERROR)
ELSE
  IF(PRESENT(KERROR)) THEN
    IERROR=1
  ELSE
    CALL MPL_MESSAGE(KERROR,'MPL_BROADCAST',' INVALID METHOD',LDABORT=LLABORT)
  ENDIF
ENDIF


IF(LMPLSTATS) THEN
  IF(IROOT == IPL_MYRANK) THEN
    CALL MPL_SENDSTATS(ICOUNT,INT(MPI_BYTE))
  ENDIF
  CALL MPL_RECVSTATS(ICOUNT,INT(MPI_BYTE))
ENDIF

IF(PRESENT(KERROR)) THEN
  KERROR=IERROR
ELSE
  IF(IERROR /= 0 ) CALL MPL_MESSAGE(IERROR,'MPL_BROADCAST',CDSTRING,LDABORT=LLABORT)
ENDIF


END SUBROUTINE MPL_BROADCAST_LOGICAL1

END MODULE MPL_BROADCAST_MOD
