SUBROUTINE MAXGPFV(PFLD,PMAX)

!**** *MAXGPFV*  - COMPUTE MAXIMUM VALUE OF A GRIDPOINT FIELD

!     PURPOSE.
!     --------
!        COMPUTE MAXIMUM VALUE.

!**   INTERFACE.
!     ----------
!       *CALL* *MAXGPFV*

!        EXPLICIT ARGUMENTS
!        --------------------

!        INPUT:
!         PFLD    : FIELD 

!        OUTPUT:
!         PMAX    : MAXIMUM VALUE OF FIELD

!        IMPLICIT ARGUMENTS
!        --------------------
!        See #include below.

!     METHOD.
!     -------
!        SEE DOCUMENTATION

!     EXTERNALS.
!     ----------


!     REFERENCE.
!     ----------
!        ECMWF Research Department documentation of the IFS
!        Documentation about FULL-POS.

!     AUTHOR.
!     -------
!        RYAD EL KHATIB *METEO-FRANCE*

!     MODIFICATIONS.
!     --------------
!        ORIGINAL : 94-04-08
!        M.Hamrud : 95-10-20 Interface block for EXTGPF
!        Modified : 95-12-18 R. El Khatib (case LRPOLE)
!        Modified by K. YESSAD (APRIL 1997): parallelisation of FULL-POS.
!        Modified 98-08-10 by K. YESSAD: removal of LRPOLE option.
!          - ZREAL does not contain polar values any longer, and non polar
!            values are stored from its element 1, so (IGL1,IGL2) is always
!            (1,NDGLG).
!    R. El Khatib : 99-12-28 remove poles rows
!        Modified : 00-04-24 A.Bogatchev, J.Vivoda, call mpe for nproc>1 only
!        Modified : 00-05-26 E.Sevault introduction of LMPOFF
!        Modified : 00-09-01 D.Dent: convert from MPE to MPL
!    R. El Khatib : 00-11-03 Optional communications in extgpf
!        M.Hamrud      01-Oct-2003 CY28 Cleaning
!        M.Hamrud      10-Jan-2004 CY28R1 Cleaning
!    R. El Khatib & J-F Estrade : 04-08-03 No comminication if 1 proc only.
!        M.Hamrud      01-Jul-2006  Revised surface fields
!     ------------------------------------------------------------------

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
USE YOMLUN   , ONLY : NULOUT
USE YOMCT0   , ONLY : NPROC    ,N_REGIONS ,N_REGIONS_NS ,&
 & LMPOFF  
USE YOMDIM   , ONLY : NDGLG    ,&
 & NDGUNG   ,NDGUXG   ,NDLUNG   ,NDLUXG   ,&
 & NPROMA  
USE YOMGEM   , ONLY : NLOENG   ,NGPTOT   ,NGPTOTG  ,NGPTOTMX
USE YOMMP    , ONLY : NPRCIDS  ,MY_REGION_NS   ,MY_REGION_EW ,NGPSET2PE
USE YOMTAG   , ONLY : MTAGDISTGP
USE MPL_MODULE

IMPLICIT NONE

! * INPUT:
REAL(KIND=JPRB)   ,INTENT(IN)    :: PFLD(:,:) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PMAX 
! * OUTPUT:
REAL(KIND=JPRB) :: ZREAL(NGPTOTG)
REAL(KIND=JPRB) :: ZREALG(NGPTOTG)
REAL(KIND=JPRB) :: ZMAX(1)
REAL(KIND=JPRB),ALLOCATABLE :: ZREALL(:)

INTEGER(KIND=JPIM) :: IEND, IGL1, IGL2, ILEN, ILRECV,&
 & IBL, IPROC1, IPROCA1, IPROCB1, IRCV, &
 & ISND, IST, ITAG, JA, &
 & JB, JGL, JKGLO, JLON, JROF  

LOGICAL :: LLPROC1
REAL(KIND=JPRB) :: ZHOOK_HANDLE

#include "abor1.intfb.h"
#include "orcvgpf.intfb.h"
#include "osndgpf.intfb.h"
!     ------------------------------------------------------------------

!*    1.  EXTRACT FIELD AND COMPUTE MAXIMUM VALUE
!         ---------------------------------------

IF (LHOOK) CALL DR_HOOK('MAXGPFV',0,ZHOOK_HANDLE)


! * Define "main" processor IPROC1.

IPROCA1=1
IPROCB1=1
IPROC1=NGPSET2PE(IPROCA1,IPROCB1)
LLPROC1=(MY_REGION_NS == IPROCA1).AND.(MY_REGION_EW == IPROCB1)


  ALLOCATE(ZREALL(NGPTOTMX))

! * Fetch DM-local data ZREALL in GPPBUF.

  DO JKGLO=1,NGPTOT,NPROMA

    IST=1
    IEND=MIN(NPROMA,NGPTOT-JKGLO+1)
    IBL=(JKGLO-1)/NPROMA + 1
    
    DO JROF=IST,IEND
      ZREALL(JROF+JKGLO-1)=PFLD(JROF,IBL)
    ENDDO

  ENDDO

! * Communicate DM-local data ZREALL to the DM-global array 
!   ZREAL in the "main" processor IPROC1.

  CALL OSNDGPF(ZREALL,IPROC1)

  IF (LLPROC1) THEN
    IF (NPROC == 1) THEN
!     NGPTOT=NGPTOTG in this case.
      ZREAL(1:NGPTOTG)=ZREALL(1:NGPTOTG)
    ELSE
      CALL ORCVGPF(ZREALG,ZREALL(1))
      ZREAL(1:NGPTOTG)=ZREALG(1:NGPTOTG)
    ENDIF
  ENDIF

  IF( NPROC > 1 )THEN
    CALL MPL_BARRIER(CDSTRING='MAXGPFV:')
  ENDIF

  DEALLOCATE(ZREALL)

! First and last rows in ZREAL : 
  IGL1=1
  IGL2=NDGLG

  IF (LLPROC1) THEN

!   * Computes the maximum PMAX of field ZREAL in the "main" processor
!     IPROC1 and prints it.

    ILEN=0
    PMAX=ZREAL(ILEN+MAX(NDLUNG,1))

    DO JGL=MAX(NDGUNG,IGL1),MIN(NDGUXG,IGL2)
      DO JLON=MAX(NDLUNG,1),MIN(NDLUXG,NLOENG(JGL))
        PMAX=MAX(PMAX,ZREAL(ILEN+JLON))
      ENDDO
      ILEN=ILEN+NLOENG(JGL)
    ENDDO

    WRITE (NULOUT,*) ' MAXGPFV : MAX. VALUE = ', PMAX

  ENDIF

! * Communicates PMAX to all other processors if DM.

  IF (.NOT.LMPOFF .AND. NPROC > 1) THEN

!   send PMAX 

    IF( LLPROC1 )THEN
      DO JA=1,N_REGIONS_NS
        DO JB=1,N_REGIONS(JA)
          ISND=NGPSET2PE(JA,JB)
          ITAG=MTAGDISTGP
          ZMAX(1)=PMAX
          CALL MPL_SEND(ZMAX,KDEST=NPRCIDS(ISND),KTAG=ITAG, &
           & CDSTRING='MAXGPFV:')  
        ENDDO
      ENDDO
    ENDIF

!   receive PMAX

    ILEN=1
    IRCV=1
    ITAG=MTAGDISTGP
    CALL MPL_RECV(ZMAX,KSOURCE=NPRCIDS(IRCV),KTAG=ITAG, &
     & KOUNT=ILRECV,CDSTRING='MAXGPFV:')  
    IF (ILRECV /= ILEN ) THEN
      CALL ABOR1(' MAXGPFV:ERROR IN MPL_RECV')
    ENDIF

    CALL MPL_BARRIER(CDSTRING='MAXGPFV:')

  ENDIF


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

IF (LHOOK) CALL DR_HOOK('MAXGPFV',1,ZHOOK_HANDLE)
END SUBROUTINE MAXGPFV
