!OCL  NOEVAL
SUBROUTINE GNHGRGW(&
 ! --- INPUT -----------------------------------------------------------------
 & KPROMA,KFLEV,KD,KF, &
 & PT,PTL,PTM,PDVER,PDVERL,PDVERM,PRNHPPI,PQCHAL,PQCHAM, &
 & PLNPR,PLNPRL,PLNPRM,PALPH,PALPHL,PALPHM, &
 & PUS,PVS,PUS_L,PVS_L,PUS_M,PVS_M, &
 & POROGL,POROGM,POROGLM,POROGLL,POROGMM, &
 ! --- OUTPUT ----------------------------------------------------------------
 & PGWFL,PGWFM,PGWHL,PGWHM &
 & )

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK

USE YOMCST   , ONLY : RD
USE YOMCVER  , ONLY : LVERTFE  ,LVFE_Z_TERM
USE YOMGEM   , ONLY : VFE_RDETAH

!**** *GNHGRGW* - Computes half and full level gradient of "gw"
!                 ("g" times the vertical velocity "w").

!     Purpose.
!     --------
!     Diagnoses "grad(gw)" from the vertical divergence "dver" and its
!      gradient.
!     For the finite element vertical discretization (lvertfe=T), "grad(gw)" is
!      computed only at full levels.
!     For the finite difference vertical discretization (lvertfe=F), "grad(gw)"
!      is computed only at both half and full levels.
!     Calculation is done by applying the gradient operator to the
!      vertical integration of the formula:
!      dver = - (g pre)/(Rd T prehyd) (d w / d log(prehyd))
!     with the following bottom condition:
!      w_surf = V_surf grad[Phi_s].


!**   Interface.
!     ----------
!        *CALL* *GNHGRGW(...)

!     Explicit arguments :
!     --------------------
!      * INPUT:
!        KPROMA    : horizontal dimension.
!        KFLEV     : number of levels.
!        KD        : start of work.
!        KF        : working length.
!        PT        : temperature T at full levels.
!        PTL       : zonal comp. of grad(T) at full levels if lsprt=F.
!                    zonal comp. of grad(Tv) at full levels if lsprt=T.
!        PTM       : merid comp. of grad(T) at full levels if lsprt=F.
!                    merid comp. of grad(Tv) at full levels if lsprt=T.
!        PDVER     : vertical divergence "dver" at full levels.
!        PDVERL    : zonal comp. of grad(dver) at full levels.
!        PDVERM    : merid comp. of grad(dver) at full levels.
!        PRNHPPI   : (prehyd/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.
!        PLNPR     : "delta" at full levels.
!        PLNPRL    : zonal comp. of "grad(delta)" at full levels.
!        PLNPRM    : merid comp. of "grad(delta)" at full levels.
!        PALPH     : "alpha" at full levels.
!        PALPHL    : zonal comp. of "grad(alpha)" at full levels.
!        PALPHM    : merid comp. of "grad(alpha)" at full levels.
!        PUS       : U-surface wind.
!        PVS       : V-surface wind.
!        PUS_L     : zonal comp. of grad(U-surface wind).
!        PVS_L     : zonal comp. of grad(V-surface wind).
!        PUS_M     : merid comp. of grad(U-surface wind).
!        PVS_M     : merid comp. of grad(V-surface wind).
!        POROGL    : zonal comp. of grad(surf orography).
!        POROGM    : merid comp. of grad(surf orography).
!        POROGLM   : -I
!        POROGLL   :  I- second order derivatives of "surf orography".
!        POROGMM   : -I

!        Remarks:
!         PRNHPPI is pre-computed in routine GNHPRE.
!         PQCHAL and PQCHAM are pre-computed in routine GNHGRPRE.
!         PLNPR and PALPH are pre-computed in routine GPXYB.
!         PLNPRL, PLNPRM, PALPHL, PALPHM are pre-computed in routine GPGRXYB.
!         PUS to PVS_M are pre-computed in routine GNHUVS.

!      * OUTPUT:
!        PGWFL     : zonal comp. of "grad(gw)" at full levels.
!        PGWFM     : merid comp. of "grad(gw)" at full levels.
!        PGWHL     : zonal comp. of "grad(gw)" at half levels (lvertfe=F only).
!        PGWHM     : merid comp. of "grad(gw)" at half levels (lvertfe=F only).

!     Implicit arguments :   None.
!     --------------------

!     Method.
!     -------
!        See documentation

!     Externals.    None.
!     ----------

!     Reference.
!     ----------

!     Author.
!     -------
!        K. YESSAD (after routines GNHPDVD, GNHGRP and GPGRGEO).

!     Modifications.
!     --------------
!        Original : 07-Dec-2004
!     ------------------------------------------------------------------

IMPLICIT NONE

INTEGER(KIND=JPIM),INTENT(IN)    :: KPROMA 
INTEGER(KIND=JPIM),INTENT(IN)    :: KFLEV 
INTEGER(KIND=JPIM),INTENT(IN)    :: KD 
INTEGER(KIND=JPIM),INTENT(IN)    :: KF 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PT(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PTL(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PTM(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PDVER(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PDVERL(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PDVERM(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PRNHPPI(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PQCHAL(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PQCHAM(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PLNPR(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PLNPRL(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PLNPRM(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PALPH(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PALPHL(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PALPHM(KPROMA,KFLEV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PUS(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PVS(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PUS_L(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PVS_L(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PUS_M(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PVS_M(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: POROGL(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: POROGM(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: POROGLM(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: POROGLL(KPROMA)
REAL(KIND=JPRB)   ,INTENT(IN)    :: POROGMM(KPROMA)
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PGWFL(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PGWFM(KPROMA,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PGWHL(KPROMA,0:KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PGWHM(KPROMA,0:KFLEV) 

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

REAL(KIND=JPRB) :: ZGPHL(KPROMA,0:KFLEV),ZGPHM(KPROMA,0:KFLEV)
REAL(KIND=JPRB) :: ZGWSL(KPROMA),ZGWSM(KPROMA)
REAL(KIND=JPRB) :: ZINL(KPROMA,KFLEV),ZINM(KPROMA,KFLEV)
REAL(KIND=JPRB) :: ZRDT(KPROMA,KFLEV),ZRDTL(KPROMA,KFLEV),ZRDTM(KPROMA,KFLEV)

INTEGER(KIND=JPIM) :: JL, JROF
REAL(KIND=JPRB) :: ZHOOK_HANDLE

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

#include "verint.intfb.h"

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

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

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

!*    1.1 Calculation of "grad (gw)" at the surface.

DO JROF=KD,KF
  ZGWSL(JROF)=PUS_L(JROF)*POROGL(JROF)+PUS(JROF)*POROGLL(JROF) &
   & +PVS_L(JROF)*POROGM(JROF)+PVS(JROF)*POROGLM(JROF)
  ZGWSM(JROF)=PUS_M(JROF)*POROGL(JROF)+PUS(JROF)*POROGLM(JROF) &
   & +PVS_M(JROF)*POROGM(JROF)+PVS(JROF)*POROGMM(JROF)
ENDDO

DO JROF=KD,KF
  PGWHL(JROF,KFLEV)=ZGWSL(JROF)
  PGWHM(JROF,KFLEV)=ZGWSM(JROF)
ENDDO

!*    1.2 Calculation of RT or [Rd T] and their derivatives according to LSPRT.

! Remark: the following expression is exact for the case lsprt=F,
! but there is an approximation done for lsprt=T, since grad(T) is not
! available in this case. When lsprt=T, Rd*grad(T) is replaced by grad(RT)
! in the computation of grad(gw) (in this case, PTL and PTM contain the
! derivatives of the virtual temperature).

DO JL=1,KFLEV
  DO JROF=KD,KF
    ZRDT(JROF,JL)=RD*PT(JROF,JL)
    ZRDTL(JROF,JL)=RD*PTL(JROF,JL)
    ZRDTM(JROF,JL)=RD*PTM(JROF,JL)
  ENDDO
ENDDO

!*    1.3 Calculation of "grad (gw)".

IF(LVERTFE.AND.LVFE_Z_TERM) THEN

  ! * Calculation of "grad (gw)" at full levels.

  DO JL=1,KFLEV
    DO JROF=KD,KF
      ZINL(JROF,JL)=VFE_RDETAH(JL)*( &
       & (-ZRDTL(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL) &
       & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PQCHAL(JROF,JL)*PDVER(JROF,JL) &
       & - ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVERL(JROF,JL) )*PLNPR(JROF,JL) &
       & - ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL)*PLNPRL(JROF,JL) )
      ZINM(JROF,JL)=VFE_RDETAH(JL)*( &
       & (-ZRDTM(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL) &
       & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PQCHAM(JROF,JL)*PDVER(JROF,JL) &
       & - ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVERM(JROF,JL) )*PLNPR(JROF,JL) &
       & - ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL)*PLNPRM(JROF,JL) )
    ENDDO
  ENDDO
  CALL VERINT(KPROMA,KD,KF,KFLEV,ZINL,ZGPHL,1)
  CALL VERINT(KPROMA,KD,KF,KFLEV,ZINM,ZGPHM,1)
  DO JL=1,KFLEV
    DO JROF=KD,KF
      PGWFL(JROF,JL)=ZGPHL(JROF,JL-1)+ZGWSL(JROF)
      PGWFM(JROF,JL)=ZGPHM(JROF,JL-1)+ZGWSM(JROF)
    ENDDO
  ENDDO  

ELSE

  ! * Calculation of "grad (gw)" at half levels.
  !   "delta" and "grad delta" terms contributions.

  DO JL=KFLEV,1,-1
    DO JROF=KD,KF
      PGWHL(JROF,JL-1)=PGWHL(JROF,JL) &
       & +(ZRDTL(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL) &
       & - ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PQCHAL(JROF,JL)*PDVER(JROF,JL) &
       & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVERL(JROF,JL) )*PLNPR(JROF,JL) &
       & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL)*PLNPRL(JROF,JL)
      PGWHM(JROF,JL-1)=PGWHM(JROF,JL) &
       & +(ZRDTM(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL) &
       & - ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PQCHAM(JROF,JL)*PDVER(JROF,JL) &
       & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVERM(JROF,JL) )*PLNPR(JROF,JL) &
       & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL)*PLNPRM(JROF,JL)
    ENDDO
  ENDDO

  ! --- ky: (PGWFL,PGWFM) useless if .NOT.(LVERTFE.AND.LVFE_Z_TERM) ---

  ! * Calculation of "grad (gw)" at full levels.
  !   "alpha" and "grad alpha" terms contributions.

  !! DO JL=1,KFLEV
  !!   DO JROF=KD,KF
  !!     PGWFL(JROF,JL)=PGWHL(JROF,JL) &
  !!      & +(ZRDTL(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL) &
  !!      & - ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PQCHAL(JROF,JL)*PDVER(JROF,JL) &
  !!      & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVERL(JROF,JL) )*PALPH(JROF,JL) &
  !!      & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL)*PALPHL(JROF,JL)
  !!     PGWFM(JROF,JL)=PGWHM(JROF,JL) &
  !!      & +(ZRDTM(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL) &
  !!      & - ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PQCHAM(JROF,JL)*PDVER(JROF,JL) &
  !!      & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVERM(JROF,JL) )*PALPH(JROF,JL) &
  !!      & + ZRDT(JROF,JL)*PRNHPPI(JROF,JL)*PDVER(JROF,JL)*PALPHM(JROF,JL)
  !!   ENDDO
  !! ENDDO

ENDIF

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

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