SUBROUTINE GNHGRPRE( &
 ! --- INPUT -------------------------------------------
 & KPROMA,KFLEV,KSTART,KEND,PRTGR,PREL,PREM,PNHPREF,PSPDL,PSPDM, &
 ! --- OUTPUT ------------------------------------------
 & PNHPREFL,PNHPREFM,PLNNHPREFL,PLNNHPREFM,PQCHAL,PQCHAM, &
 ! --- OPTIONAL INPUT ----------------------------------
 & PSPD,PLNPR,PLNPRL,PLNPRM,PRT,PRTL,PRTM,POROG,POROGL,POROGM, &
 & PHIHYD,PHIHYDL,PHIHYDM &
 & )

! GNHGRPRE - Computation of the horizontal gradient of the
!            total pressure "pre" at full levels.
!            For deep layer equations the gradient computed is rssavnabla.

! Purpose
! -------
!   Computes on model full levels.
!    * "grad pre" at full levels.
!    * the ratio [grad pre]/pre at full levels.
!    * the difference [grad pre]/pre - [grad prehyd]/prehyd
!      (which is equal to "grad(log(pre/prehyd))") at full levels.

!   Abbreviation "pdv" means "pressure departure variable"
!   (this is Qcha = log(pre/prehyd) for NPDVAR=2)

! Interface
! ---------
!   INPUT:
!    KPROMA     - horizontal dimension.
!    KFLEV      - number of levels.
!    KSTART     - start of work.
!    KEND       - end of work.
!    PRTGR      - the ratio [grad prehyd/prehyd]/[grad prehyds/prehyds]
!                 at full levels.
!    PREL       - zonal component of "grad (prehyds)".
!    PREM       - meridian component of "grad (prehyds)".
!    PNHPREF    - total pressure "pre" at full levels.
!    PSPDL      - zonal component of "grad pdv" at full levels.
!    PSPDM      - meridian component of "grad pdv" at full levels.

!   OUTPUT:
!    PNHPREFL   - zonal component of "grad pre" at full levels.
!    PNHPREFM   - merid component of "grad pre" at full levels.
!    PLNNHPREFL - zonal component of "[grad pre]/pre" at full levels.
!    PLNNHPREFM - merid component of "[grad pre]/pre" at full levels.
!    PQCHAL     - zonal comp of "grad(log(pre/prehyd))" at full levels.
!    PQCHAM     - merid comp of "grad(log(pre/prehyd))" at full levels.

!   OPTIONAL INPUT:
!    PSPD       - "pdv" at full levels.
!    PLNPR      - 'delta=delta(log(prehyd))' at full levels.
!    PLNPRL     - zonal comp of grad(delta=delta(log(prehyd))) at full levels.
!    PLNPRM     - merid comp of grad(delta=delta(log(prehyd))) at full levels.
!    PRT        - RT at full levels.
!    PRTL       - zonal component of "grad RT" at full levels.
!    PRTM       - meridian component of "grad RT" at full levels.
!    POROG      - surface orography.
!    POROGL     - zonal component of "grad surface orography".
!    POROGM     - meridian component of "grad surface orography".
!    PHIHYD     - hydrostatic part of Phi at full levels.
!    PHIHYDL    - hydrostatic part of zonal grad(phi) at full levels.
!    PHIHYDM    - hydrostatic part of meridian grad(phi) at full levels.

! Externals
! ---------

! Method
! ------

! Reference
! ---------

! Author
! ------
!   K. YESSAD (MF/CNRM/GMAP), Dec 2004.

! Modifications
! -------------
!   N. Wedi and K. Yessad (Jan 2008): different dev for NH model and PC scheme
!------------------------------------------------------------------

USE PARKIND1 , ONLY : JPIM     ,JPRB
USE YOMCVER  , ONLY : LVERTFE  ,LVFE_DERIB
USE YOMGEM   , ONLY : VFE_RDETAH,VBF
USE YOMDYNA  , ONLY : NPDVAR
USE YOMHOOK  , ONLY : LHOOK    ,DR_HOOK

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

IMPLICIT NONE

INTEGER(KIND=JPIM),INTENT(IN)    :: KPROMA
INTEGER(KIND=JPIM),INTENT(IN)    :: KFLEV
INTEGER(KIND=JPIM),INTENT(IN)    :: KSTART 
INTEGER(KIND=JPIM),INTENT(IN)    :: KEND 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PRTGR(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PREL(KPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PREM(KPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PNHPREF(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSPDL(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSPDM(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PNHPREFL(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PNHPREFM(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PLNNHPREFL(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PLNNHPREFM(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PQCHAL(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PQCHAM(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PSPD(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PLNPR(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PLNPRL(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PLNPRM(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PRT(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PRTL(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PRTM(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: POROG(KPROMA) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: POROGL(KPROMA) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: POROGM(KPROMA) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PHIHYD(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PHIHYDL(KPROMA,KFLEV) 
REAL(KIND=JPRB),OPTIONAL,INTENT(IN)  :: PHIHYDM(KPROMA,KFLEV) 

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

INTEGER(KIND=JPIM) :: JLEV, JROF
REAL(KIND=JPRB)    :: ZSPDDER(KPROMA,0:KFLEV+1) 
REAL(KIND=JPRB)    :: ZSPDDERL(KPROMA,0:KFLEV+1) 
REAL(KIND=JPRB)    :: ZSPDDERM(KPROMA,0:KFLEV+1) 
REAL(KIND=JPRB)    :: ZPHI(KPROMA,0:KFLEV+1)
REAL(KIND=JPRB)    :: ZPHIL(KPROMA,0:KFLEV+1)
REAL(KIND=JPRB)    :: ZPHIM(KPROMA,0:KFLEV+1)
REAL(KIND=JPRB)    :: ZFAC

REAL(KIND=JPRB) :: ZHOOK_HANDLE

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

#include "abor1.intfb.h"
#include "verder.intfb.h"

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

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

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

IF ( NPDVAR == 2 ) THEN

  DO JLEV=1,KFLEV
    DO JROF=KSTART,KEND
      PLNNHPREFL(JROF,JLEV)=(PSPDL(JROF,JLEV)+PRTGR(JROF,JLEV)*PREL(JROF))
      PLNNHPREFM(JROF,JLEV)=(PSPDM(JROF,JLEV)+PRTGR(JROF,JLEV)*PREM(JROF))
      PNHPREFL(JROF,JLEV)=PNHPREF(JROF,JLEV)*PLNNHPREFL(JROF,JLEV)
      PNHPREFM(JROF,JLEV)=PNHPREF(JROF,JLEV)*PLNNHPREFM(JROF,JLEV)
      PQCHAL(JROF,JLEV)=PSPDL(JROF,JLEV)
      PQCHAM(JROF,JLEV)=PSPDM(JROF,JLEV)
    ENDDO
  ENDDO

ELSEIF ( NPDVAR == 3 .OR. NPDVAR == 4 ) THEN

  IF ( .NOT.(PRESENT(PSPD) &
   & .AND.PRESENT(PLNPR).AND.PRESENT(PLNPRL).AND.PRESENT(PLNPRM) &
   & .AND.PRESENT(PRT).AND.PRESENT(PRTL).AND.PRESENT(PRTM) &
   & .AND.PRESENT(POROG).AND.PRESENT(POROGL).AND.PRESENT(POROGM) &
   & .AND.PRESENT(PHIHYD).AND.PRESENT(PHIHYDL).AND.PRESENT(PHIHYDM)) ) THEN
    CALL ABOR1('GNHGRPRE: if NPDVAR=3 or 4, arg PLNPR to PHIHYDM should be present!')
  ENDIF

  IF (LVERTFE) THEN
    IF ( NPDVAR == 3 ) THEN
      DO JLEV=1,KFLEV
        DO JROF=KSTART,KEND
          ZPHI(JROF,JLEV)= &
           & PSPD(JROF,JLEV)+VBF(JLEV)*POROG(JROF)-PHIHYD(JROF,JLEV)
          ZPHIL(JROF,JLEV)= &
           & PSPDL(JROF,JLEV)+VBF(JLEV)*POROGL(JROF)-PHIHYDL(JROF,JLEV)
          ZPHIM(JROF,JLEV)= &
           & PSPDM(JROF,JLEV)+VBF(JLEV)*POROGM(JROF)-PHIHYDM(JROF,JLEV)
        ENDDO
      ENDDO
    ELSEIF ( NPDVAR == 4 ) THEN
      DO JLEV=1,KFLEV
        DO JROF=KSTART,KEND
          ZPHI(JROF,JLEV)=PSPD(JROF,JLEV)-PHIHYD(JROF,JLEV)
          ZPHIL(JROF,JLEV)=PSPDL(JROF,JLEV)-PHIHYDL(JROF,JLEV)
          ZPHIM(JROF,JLEV)=PSPDM(JROF,JLEV)-PHIHYDM(JROF,JLEV)
        ENDDO
      ENDDO
    ENDIF
    IF (LVFE_DERIB) THEN
      ! Constant upper BC.
      ZPHI(KSTART:KEND,0)=ZPHI(KSTART:KEND,1)
      ZPHIL(KSTART:KEND,0)=ZPHIL(KSTART:KEND,1)
      ZPHIM(KSTART:KEND,0)=ZPHIM(KSTART:KEND,1)
      ! Lower BC is zero.
      ZPHI(KSTART:KEND,KFLEV+1)=0.0_JPRB
      ZPHIL(KSTART:KEND,KFLEV+1)=0.0_JPRB
      ZPHIM(KSTART:KEND,KFLEV+1)=0.0_JPRB
      CALL VERDER(KPROMA,KSTART,KEND,KFLEV+2,ZPHI(1,0),ZSPDDER(1,0),.TRUE.)
      CALL VERDER(KPROMA,KSTART,KEND,KFLEV+2,ZPHIL(1,0),ZSPDDERL(1,0),.TRUE.)
      CALL VERDER(KPROMA,KSTART,KEND,KFLEV+2,ZPHIM(1,0),ZSPDDERM(1,0),.TRUE.)
    ELSE
      CALL VERDER(KPROMA,KSTART,KEND,KFLEV,ZPHI(1,1),ZSPDDER(1,1))
      CALL VERDER(KPROMA,KSTART,KEND,KFLEV,ZPHIL(1,1),ZSPDDERL(1,1))
      CALL VERDER(KPROMA,KSTART,KEND,KFLEV,ZPHIM(1,1),ZSPDDERM(1,1))
    ENDIF
  ELSE
    CALL ABOR1('GNHGRPRE: NPDVAR=3 or 4 is coded only for VFE!')
  ENDIF
  DO JLEV=1,KFLEV
    DO JROF=KSTART,KEND
      ZSPDDER(JROF,JLEV)=ZSPDDER(JROF,JLEV)/VFE_RDETAH(JLEV)
      ZSPDDERL(JROF,JLEV)=ZSPDDERL(JROF,JLEV)/VFE_RDETAH(JLEV)
      ZSPDDERM(JROF,JLEV)=ZSPDDERM(JROF,JLEV)/VFE_RDETAH(JLEV)
      ZFAC=1.0_JPRB/(PLNPR(JROF,JLEV)*PRT(JROF,JLEV)-ZSPDDER(JROF,JLEV))
      PQCHAL(JROF,JLEV)=ZFAC*( - ZSPDDERL(JROF,JLEV) + ZSPDDER(JROF,JLEV)* &
       & (PLNPRL(JROF,JLEV)/PLNPR(JROF,JLEV)+PRTL(JROF,JLEV)/PRT(JROF,JLEV)) )
      PQCHAM(JROF,JLEV)=ZFAC*( - ZSPDDERM(JROF,JLEV) + ZSPDDER(JROF,JLEV)* &
       & (PLNPRM(JROF,JLEV)/PLNPR(JROF,JLEV)+PRTM(JROF,JLEV)/PRT(JROF,JLEV)) )
      PLNNHPREFL(JROF,JLEV)=(PQCHAL(JROF,JLEV)+PRTGR(JROF,JLEV)*PREL(JROF))
      PLNNHPREFM(JROF,JLEV)=(PQCHAM(JROF,JLEV)+PRTGR(JROF,JLEV)*PREM(JROF))
      PNHPREFL(JROF,JLEV)=PNHPREF(JROF,JLEV)*PLNNHPREFL(JROF,JLEV)
      PNHPREFM(JROF,JLEV)=PNHPREF(JROF,JLEV)*PLNNHPREFM(JROF,JLEV)
    ENDDO
  ENDDO

ENDIF

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

IF (LHOOK) CALL DR_HOOK('GNHGRPRE',1,ZHOOK_HANDLE)

END SUBROUTINE GNHGRPRE

