SUBROUTINE GNHX( &
 ! ----- INPUT ---------------------------------------------------------------
 & KPROMA   ,KSTART   ,KEND     ,POROG    ,POROGL   ,POROGM   , &
 & PSP      ,PSPL     , &
 & PSPM     ,PT       ,PTL      ,PTM      ,PQ       , &
 & PQL      ,PQM      ,PL       ,PLL      ,PLM      , &
 & PI       ,PIL      ,PIM      ,PR       ,PS       , &
 & PG       ,PUF      ,PVF      ,PSPD     ,PSPDL    ,PSPDM    , &
 ! ----- OUTPUT --------------------------------------------------------------
 & PNHX &
 & )

! -----
! REMARKS:
!  - Variables PLL, PLM, PIL, PIM are not used currently, but they
!    might be needed in corrected version of GPRT.
!  - The structure of this routine must remain consistent with the
!    one of CPG_GP.
!  - When LRWSDLR=T, PSP, PSPL, PSPM contain log(presim) and its derivatives,
!    where d presim/d prehyd = (r**2/a**2)*(G/g).
! -----

! GNHX - Diagnose NHX-term

! Purpose
! -------
!   Diagnose NHX-term (D3 = D + NHX + (Rd/R) dver)

! Interface
! ---------
!   KPROMA  - length of work
!   KSTART  - start of work
!   KEND    - end of work
!   POROG   - surface geopotential
!   POROGL  - zonal gradient of surface geopotential
!   POROGM  - meridional gradient of surface geopotential
!   PSP     - ln(prehyds)
!   PSPL    - zonal gradient of ln(prehyds)
!   PSPM    - meridional gradient of ln(prehyds)
!   PT      - temperature T
!   PTL     - zonal gradient of temperature
!   PTM     - meridional gradient of temperature
!   PQ      - specific humidity q
!   PQL     - zonal gradient of q
!   PQM     - meridional gradient of q
!   PL      - specific mass of liquid ql
!   PLL     - zonal gradient of ql
!   PLM     - meridional gradient of ql
!   PI      - specific mass of ice qi
!   PIL     - zonal gradient of qi
!   PIM     - meridional gradient of qi
!   PR      - specific mass of rain qr
!   PS      - specific mass of snow qs
!   PG      - specific mass of graupel qg
!   PUF     - U-wind at full levels
!   PVF     - V-wind at full levels
!   PSPD    - NH pressure departure (depends on NPDVAR)
!   PSPDL   - zonal gradient of NH pressure departure
!   PSPDM   - meridional gradient of NH pressure departure
!   PNHX    - NHX-term

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

! Method
! ------

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

! Author
! ------
!   08-Mar-2002 J. Masek (SHMI)

! Modifications
! -------------
!   11-Oct-2002 J. Masek      Subroutine enters al25t2 together with a new
!                             sponge. Removed bug: Forgotten conversion
!                             ln(prehyds) ---> prehyds.
!   31-Jan-2003 P. Smolikova  cleaning, use of KPROMA
!   01-Oct-2003 M. Hamrud     CY28 Cleaning
!   03-Jun-2004 J. Masek      NH cleaning (NPDVAR)
!   24-Jan-2005 K. Yessad     cleaning and more modularization.
!   21-Aug-2007 K. Yessad     remove useless calculations.
!   09-Oct-2007 J. Vivoda and K. Yessad: VFE in NH model
!   N. Wedi and K. Yessad (Jan 2008): different dev for NH model and PC scheme
!   K. Yessad (March 2009): correct false comments for LRWSDLG=T
! End Modifications
!---------------------------------------------------------------------

USE PARKIND1 , ONLY : JPIM     ,JPRB
USE YOMCST   , ONLY : RD       ,RV
USE YOMCT0   , ONLY : LNHDYN   ,LSPRT
USE YOMDYNA  , ONLY : LNH_PDVD ,LRWSDLR
USE YOMDIM   , ONLY : NFLEVG
USE YOMGEM   , ONLY : VAH      ,VBH      ,VDELB    ,VC
USE YOMCVER  , ONLY : LVERTFE  ,LVFE_X_TERM
USE YOMHOOK  , ONLY : LHOOK    ,DR_HOOK
USE PAR_RDLR , ONLY : JP_DIMR

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

IMPLICIT NONE

INTEGER(KIND=JPIM),INTENT(IN)    :: KPROMA 
INTEGER(KIND=JPIM),INTENT(IN)    :: KSTART 
INTEGER(KIND=JPIM),INTENT(IN)    :: KEND 

REAL(KIND=JPRB)   ,INTENT(IN)    :: POROG  (KPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: POROGL (KPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: POROGM (KPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSP    (KPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSPL   (KPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSPM   (KPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PT     (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PTL    (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PTM    (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PQ     (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PQL    (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PQM    (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PL     (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PLL    (KPROMA,NFLEVG)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PLM    (KPROMA,NFLEVG)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PI     (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PIL    (KPROMA,NFLEVG)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PIM    (KPROMA,NFLEVG)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PR     (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PS     (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PG     (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PUF    (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PVF    (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSPD   (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSPDL  (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSPDM  (KPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PNHX   (KPROMA,NFLEVG) 

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

INTEGER(KIND=JPIM) :: JROF

REAL(KIND=JPRB) :: ZHOOK_HANDLE

REAL(KIND=JPRB) :: ZPIS  (KPROMA)          ! surface pressure prehyds
REAL(KIND=JPRB) :: ZPISL (KPROMA)          ! zonal derivative of prehyds 
REAL(KIND=JPRB) :: ZPISM (KPROMA)          ! meridional derivative of prehyds

REAL(KIND=JPRB) :: ZALPH (KPROMA, NFLEVG)  ! alpha
REAL(KIND=JPRB) :: ZALPHL(KPROMA, NFLEVG)  ! zonal comp of grad(alpha)
REAL(KIND=JPRB) :: ZALPHM(KPROMA, NFLEVG)  ! merid comp of grad(alpha)
REAL(KIND=JPRB) :: ZALPHPLL(KPROMA,NFLEVG) ! zon comp of grad(alpha+log prehyd)
REAL(KIND=JPRB) :: ZALPHPLM(KPROMA,NFLEVG) ! mer comp of grad(alpha+log prehyd)
REAL(KIND=JPRB) :: ZLNPR (KPROMA, NFLEVG)  ! "delta"=delta(prehyd)/prehyd
REAL(KIND=JPRB) :: ZLNPRL(KPROMA, NFLEVG)  ! zonal comp of grad(delta)
REAL(KIND=JPRB) :: ZLNPRM(KPROMA, NFLEVG)  ! merid comp of grad(delta)

REAL(KIND=JPRB) :: ZDPI  (KPROMA, NFLEVG)  ! delta(prehyd)
REAL(KIND=JPRB) :: ZRDPI (KPROMA, NFLEVG)  ! 1/delta(prehyd)
REAL(KIND=JPRB) :: ZPIH  (KPROMA, 0:NFLEVG)! prehyd at half levels
REAL(KIND=JPRB) :: ZPIF  (KPROMA, NFLEVG)  ! prehyd at full levels
REAL(KIND=JPRB) :: ZRPIF (KPROMA, NFLEVG)  ! 1/prehyd at full levels
REAL(KIND=JPRB) :: ZRPP  (KPROMA, NFLEVG)  ! 1/prehyd**2 at full levels
REAL(KIND=JPRB) :: ZRTGR (KPROMA, NFLEVG)  ! 1/delta(prehyd)*(VDELB + VC/prehyd)
REAL(KIND=JPRB) :: ZCP   (KPROMA, NFLEVG)  ! specific heat of air cp
REAL(KIND=JPRB) :: ZR    (KPROMA, NFLEVG)  ! gas "constatnt" of air R
REAL(KIND=JPRB) :: ZKAPPA(KPROMA, NFLEVG)  ! kappa = R/cp
REAL(KIND=JPRB) :: ZRT   (KPROMA, NFLEVG)  ! RT
REAL(KIND=JPRB) :: ZRTL  (KPROMA, NFLEVG)  ! zonal gradient of RT
REAL(KIND=JPRB) :: ZRTM  (KPROMA, NFLEVG)  ! meridional gradient of RT
REAL(KIND=JPRB) :: ZWUV  (KPROMA, NFLEVG)  ! interpolation weights for half 

REAL(KIND=JPRB) :: ZPHIHL(KPROMA, 0:NFLEVG)  ! zonal comp of grad(gz) (half lay)
REAL(KIND=JPRB) :: ZPHIHM(KPROMA, 0:NFLEVG)  ! merid comp of grad(gz) (half lay)
REAL(KIND=JPRB) :: ZPHIFL(KPROMA, NFLEVG)    ! zonal comp of grad(gz) (full lay)
REAL(KIND=JPRB) :: ZPHIFM(KPROMA, NFLEVG)    ! merid comp of grad(gz) (full lay)
REAL(KIND=JPRB) :: ZUH   (KPROMA, 0:NFLEVG)  ! U-wind at half levels
REAL(KIND=JPRB) :: ZVH   (KPROMA, 0:NFLEVG)  ! V-wind at half levels

REAL(KIND=JPRB) :: ZNHPREF(KPROMA,NFLEVG)    ! "pre" at full levels.
REAL(KIND=JPRB) :: ZNHPPI (KPROMA,NFLEVG)    ! "pre/prehyd" at full levels.
REAL(KIND=JPRB) :: ZRNHPPI(KPROMA,NFLEVG)    ! "prehyd/pre" at full levels.
REAL(KIND=JPRB) :: ZPDEP  (KPROMA,NFLEVG)    ! "pre-prehyd" at full levels.
REAL(KIND=JPRB) :: ZNHPREL(KPROMA,NFLEVG)    ! zon comp of "grad pre" (full lev)
REAL(KIND=JPRB) :: ZNHPREM(KPROMA,NFLEVG)    ! mer comp of "grad pre" (full lev)
REAL(KIND=JPRB) :: ZLNNHPREFL(KPROMA,NFLEVG) ! zon comp grad(ZNHPREF)/ZNHPREF
REAL(KIND=JPRB) :: ZLNNHPREFM(KPROMA,NFLEVG) ! mer comp grad(ZNHPREF)/ZNHPREF
REAL(KIND=JPRB) :: ZQCHAL(KPROMA,NFLEVG)     ! zonal comp grad(log(pre/prehyd))
REAL(KIND=JPRB) :: ZQCHAM(KPROMA,NFLEVG)     ! merid comp grad(log(pre/prehyd))

REAL(KIND=JPRB),ALLOCATABLE :: ZRDLR(:,:,:)

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

#include "gnhdlr.intfb.h"
#include "gnhgrdlr.intfb.h"
#include "gnhgrpre.intfb.h"
#include "gnhpre.intfb.h"
#include "gpgrgeo.intfb.h"
#include "gpgrxyb.intfb.h"
#include "gphluv.intfb.h"
#include "gphlwi.intfb.h"
#include "gppref.intfb.h"
#include "gppreh.intfb.h"
#include "gprcp.intfb.h"
#include "gprt.intfb.h"
#include "gpxx.intfb.h"
#include "gpxyb.intfb.h"

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

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

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

IF (LNHDYN.AND.LNH_PDVD.AND.LRWSDLR) ALLOCATE(ZRDLR(KPROMA,0:NFLEVG,JP_DIMR))

! -----
! computation of pressures
! -----

! convert ln(prehyds) to prehyds (same for derivatives)
DO JROF=KSTART,KEND
  ZPIS (JROF)=EXP(PSP(JROF))
  ZPISL(JROF)=ZPIS(JROF)*PSPL(JROF)
  ZPISM(JROF)=ZPIS(JROF)*PSPM(JROF)
ENDDO

! half level pressure
DO JROF=KSTART,KEND
  ZPIH(JROF,NFLEVG)=ZPIS(JROF)
ENDDO
CALL GPPREH(KPROMA,KSTART,KEND,NFLEVG,VAH,VBH,ZPIH)

! auxiliary quantities
CALL GPXYB(KPROMA,KSTART,KEND,NFLEVG,VDELB,VC,ZPIH,ZDPI,ZRDPI,ZLNPR, &
 & ZALPH,ZRTGR,ZRPIF,ZRPP)

! full level pressure
CALL GPPREF(KPROMA,KSTART,KEND,NFLEVG,ZALPH,ZPIH,ZPIF)  

! additional auxiliary quantities (grad(delta) and grad(alpha) for ex.)
CALL GPGRXYB(KPROMA,KSTART,KEND,NFLEVG,VC,VBH,&
 & ZPISL,ZPISM,ZRDPI,ZRPIF,ZRPP,ZLNPR,ZALPH,ZRTGR,&
 & ZLNPRL,ZLNPRM,ZALPHL,ZALPHM,ZALPHPLL,ZALPHPLM)

! -----
! computation of R, cp, kappa
! -----

CALL GPRCP(KPROMA,KSTART,KEND,NFLEVG,PQ=PQ,PQI=PI,PQL=PL,PQR=PR,PQS=PS,PQG=PG,&
 & PCP=ZCP,PR=ZR,PKAP=ZKAPPA)  

! -----
! computation of RT, grad(RT)
! -----

CALL GPRT(LSPRT,KPROMA,KSTART,KEND,NFLEVG,RD,RV,ZR,PT,PTL, &
 & PTM,PQL,PQM,ZRT,ZRTL,ZRTM)  

! -----
! computation of pre/prehyd and some other "pressure departure" quantities
! -----

CALL GNHPRE(KPROMA,NFLEVG,KSTART,KEND,PSPD,ZPIF,ZNHPREF,ZNHPPI,ZRNHPPI,ZPDEP)
CALL GNHGRPRE(KPROMA,NFLEVG,KSTART,KEND,ZRTGR,ZPISL,ZPISM, &
 & ZNHPREF,PSPDL,PSPDM, &
 & ZNHPREL,ZNHPREM,ZLNNHPREFL,ZLNNHPREFM,ZQCHAL,ZQCHAM &
 & )

! -----
! computation of grad(gz)
! -----

IF (LNHDYN.AND.LNH_PDVD.AND.LRWSDLR) THEN
  ! "r/a", "a/r" and geopotential height.
  CALL GNHDLR(KPROMA,NFLEVG,KSTART,KEND,PT,ZR,ZRNHPPI, &
   & ZLNPR,ZALPH,POROG,ZRDLR)
  ! "grad(r/a)" and gradient of geopotential height.
  CALL GNHGRDLR(KPROMA,NFLEVG,KSTART,KEND,&
   & PT,ZR,ZRNHPPI,ZRTL,ZRTM,&
   & ZLNPR,ZLNPRL,ZLNPRM,ZALPH,ZALPHL,ZALPHM,&
   & ZQCHAL,ZQCHAM,POROGL,POROGM,ZRDLR,&
   & ZPHIFL,ZPHIFM,ZPHIHL,ZPHIHM)
ELSE
  CALL GPGRGEO(LNHDYN,KPROMA,KSTART,KEND,NFLEVG,&
   & ZRNHPPI,PT,ZR,ZRTL,ZRTM,&
   & ZLNPR,ZLNPRL,ZLNPRM,ZALPH,ZALPHL,ZALPHM,&
   & ZQCHAL,ZQCHAM,POROGL,POROGM,&
   & ZPHIFL,ZPHIFM,ZPHIHL,ZPHIHM)
ENDIF

! -----
! computation of half level wind if relevant
! -----

IF (.NOT.(LVERTFE .AND. LVFE_X_TERM)) THEN
  ! compute interpolation weights
  CALL GPHLWI(KPROMA,KSTART,KEND,ZLNPR,ZALPH,ZWUV)  
  ! interpolate wind into half levels
  CALL GPHLUV(KPROMA,KSTART,KEND,ZWUV,PUF,PVF,ZUH,ZVH)  
ELSE
  ! ZUH and ZVH are useless, set to 0 for safety.
  ZUH(KSTART:KEND,0:NFLEVG)=0.0_JPRB
  ZVH(KSTART:KEND,0:NFLEVG)=0.0_JPRB
ENDIF

! -----
! computation of term NHX
! -----

IF (LNHDYN.AND.LNH_PDVD.AND.LRWSDLR) THEN
  CALL GPXX(NFLEVG,KPROMA,KSTART,KEND,ZPHIHL,ZPHIHM,ZPHIFL,ZPHIFM, &
   & ZLNPR,ZNHPPI,PT,ZR,PUF,PVF,ZUH,ZVH,PNHX,LDRWSDLR=LRWSDLR,PRDLR=ZRDLR)
ELSE
  CALL GPXX(NFLEVG,KPROMA,KSTART,KEND,ZPHIHL,ZPHIHM,ZPHIFL,ZPHIFM, &
   & ZLNPR,ZNHPPI,PT,ZR,PUF,PVF,ZUH,ZVH,PNHX)
ENDIF

IF(ALLOCATED(ZRDLR)) DEALLOCATE(ZRDLR)

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

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

END SUBROUTINE GNHX

