SUBROUTINE LANHSI(KST,KPROF,LDGWADV,PRCORI,PREDIV,PGMV,PGMVS,PGFL,&
 & PSDIV0,PSDIV9,PTOD0,PTOD9,PGAGT0L,PGAGT0M,PGAGT9L,PGAGT9M,&
 & PSPDS0,PSPDS9,PLPD0,PLPD9,PDPD0,PDPD9)  

!**** *LANHSI*   Semi-Lagrangian scheme.
!                Computation of linear terms used in the semi-implicit scheme. 
!                NH-PDVD model (LNH_PDVD=T).

!     Purpose.
!     --------
!        Computation of linear terms used in the semi-implicit scheme
!        for U,V (momentum) equation, T (temperature) equation,
!        ps or ln(ps) (continuity) equation, NH variables equations.
!        NH model with (log(pre/prehyd),d3 or d4) NH variables. 

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

!        Explicit arguments :
!        --------------------

!        INPUT:
!          KST      - first element of work.
!          KPROF    - depth of work.
!          LDGWADV  - T/F: SVD var is 'gw' or vertical divergence
!          PRCORI   - Coriolis parameter.
!          PREDIV   - (c**2)/(M**2).
!          PGMV     - GMV variables at t-dt and t.
!          PGMVS    - GMVS variables at t-dt and t.
!          PGFL     - unified_treatment grid-point fields.

!        OUTPUT:
!          PSDIV0   - semi-implicit term at time t for continuity equation.
!          PSDIV9   - semi-implicit term at time t-dt for continuity equation.
!          PTOD0    - semi-implicit term at time t for temperature equation.
!          PTOD9    - semi-implicit term at time t-dt for temperature equation.
!          PGAGT0L  - semi-implicit term at time t for U-wind equation.
!          PGAGT0M  - semi-implicit term at time t for V-wind equation.
!          PGAGT9L  - semi-implicit term at time t-dt for U-wind equation.
!          PGAGT9M  - semi-implicit term at time t-dt for V-wind equation.
!          PSPDS0   - semi-implicit term at time t for SPD-var equation.
!          PSPDS9   - semi-implicit term at time t-dt for SPD-var equation.
!          PLPD0    - semi-implicit term at time t for SVD-var equation.
!          PLPD9    - semi-implicit term at time t-dt for SVD-var equation.
!          PDPD0    - SI term at time t for "gw" equation (LDGWADV only).
!          PDPD9    - SI term at time t-dt for "gw" equation (LDGWADV only).

!        Implicit arguments :
!        --------------------

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

!     Externals.
!     ----------
!        Called by LACDYN.

!     Reference.
!     ----------
!        Arpege documentation about semi-Lagrangian scheme (IDSL).
!        Arpege documentation about semi-implicit scheme (IDSI).

!     Author.
!     -------
!        K. YESSAD (METEO FRANCE/CNRM/GMAP) after routine LASSIE and
!        code introduced by M. JANOUSEK and R. BUBNOVA.

!     Modifications.
!     --------------
!   Original : APRIL 1996.
!   Modified NOV 1999 by K. YESSAD:
!       - rewrite according the Eulerian code using SITNU and SIGAM.
!       - additional cleaning.
!   Modified 08-2002 C. Smith : use "w" as prognostic variable in the
!       semi-lag advection of vertical divergence in the NH model.
!   M.Hamrud      01-Oct-2003 CY28 Cleaning
!   Modified 04-02-06: Y. Seity : new arg to GPRCP (rain, snow and graupel)
!   20-Feb-2005 J. Vivoda GWADV scheme (no L term for "gw" formulation)
!   M.Hamrud  15-Jan-2006  Revised GPRCP
!   K. Yessad 07-03-2007: Remove useless (gw)_surf interpol. in NH+LGWADV.
!   N. Wedi and K. Yessad (Jan 2008): different dev for NH model and PC scheme
!   K. Yessad Aug 2008: rationalisation of dummy argument interfaces
!  End Modifications
!     ------------------------------------------------------------------

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
USE YOM_YGFL  ,ONLY : YGFL
USE YOMCST    ,ONLY : RD       ,RG
USE YOMCT0    ,ONLY : LSPRT    ,LTWOTL
USE YOMDIM   , ONLY : NPROMA   ,NFLEVG
USE YOMDYN    ,ONLY : LIMPF    ,SITRA
USE YOMGMV   , ONLY : NDIMGMV  ,NDIMGMVS ,YT0      ,YT9

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

IMPLICIT NONE

INTEGER(KIND=JPIM),INTENT(IN)    :: KST 
INTEGER(KIND=JPIM),INTENT(IN)    :: KPROF 
LOGICAL           ,INTENT(IN)    :: LDGWADV 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PRCORI(NPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PREDIV(NPROMA) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PGMV(NPROMA,NFLEVG,NDIMGMV)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PGMVS(NPROMA,NDIMGMVS)
REAL(KIND=JPRB)   ,INTENT(IN)    :: PGFL(NPROMA,NFLEVG,YGFL%NDIM) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PSDIV0(NPROMA) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PSDIV9(NPROMA) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PTOD0(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PTOD9(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PGAGT0L(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PGAGT0M(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PGAGT9L(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PGAGT9M(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PSPDS0(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PSPDS9(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PLPD0(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PLPD9(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PDPD0(NPROMA,NFLEVG) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PDPD9(NPROMA,NFLEVG) 

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

REAL(KIND=JPRB) :: ZR9  (NPROMA,NFLEVG)
REAL(KIND=JPRB) :: ZSVDT(NPROMA,NFLEVG)
REAL(KIND=JPRB) :: ZDUM(NPROMA,NFLEVG)

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

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

#include "gprcp.intfb.h"
#include "siseve.intfb.h"
#include "sidd.intfb.h"
#include "siptp.intfb.h"

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

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

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

IPROFS=KPROF-KST+1

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

! * Variables at time 0 (SL3TL and SL2TL).

IF (LDGWADV) THEN

  DO JLEV=1,NFLEVG
    DO JROF=KST,KPROF
      PGAGT0L(JROF,JLEV)=0.0_JPRB
      PGAGT0M(JROF,JLEV)=0.0_JPRB
      PTOD0  (JROF,JLEV)=0.0_JPRB
      PSPDS0 (JROF,JLEV)=0.0_JPRB
      PLPD0  (JROF,JLEV)=0.0_JPRB
      PDPD0  (JROF,JLEV)=0.0_JPRB
    ENDDO
  ENDDO
  PSDIV0(KST:KPROF)=0.0_JPRB

ELSEIF (.NOT.LDGWADV) THEN

  ! - Computation of SI terms for continuity, T and Pcha equations.
  DO JLEV=1,NFLEVG
    DO JROF=KST,KPROF
      ZSVDT(JROF,JLEV)=PGMV(JROF,JLEV,YT0%MSVD)/PREDIV(JROF)
    ENDDO
  ENDDO
  CALL SIPTP(NPROMA,1,PGMV(KST,1,YT0%MDIV),ZSVDT(KST,1),&
   & PSPDS0(KST,1),PTOD0(KST,1),PSDIV0(KST),IPROFS)  
  ! - Computation of SI terms for momentum equation.
  CALL SIDD(NPROMA,1,PGAGT0L(KST,1),ZDUM(KST,1),&
   & PGMV(KST,1,YT0%MSPDL),PGMV(KST,1,YT0%MTL),PGMVS(KST,YT0%MSPL),IPROFS)  
  CALL SIDD(NPROMA,1,PGAGT0M(KST,1),ZDUM(KST,1),&
   & PGMV(KST,1,YT0%MSPDM),PGMV(KST,1,YT0%MTM),PGMVS(KST,YT0%MSPM),IPROFS)  
  ! - Computation of SI terms for rescaled "pseudo" vertical divergence eqn.
  CALL SISEVE(NPROMA,1,PGMV(KST,1,YT0%MSPD),PLPD0(KST,1),IPROFS)
  DO JLEV=1,NFLEVG
    DO JROF=KST,KPROF
      PLPD0(JROF,JLEV)=(RG*RG/(RD*SITRA))*PLPD0(JROF,JLEV)
    ENDDO
  ENDDO

ENDIF

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

! * Variables at time 9 (SL3TL only).

IF (.NOT.LTWOTL) THEN

  IF (LDGWADV) THEN

    DO JLEV=1,NFLEVG
      DO JROF=KST,KPROF
        PGAGT9L(JROF,JLEV)=0.0_JPRB
        PGAGT9M(JROF,JLEV)=0.0_JPRB
        PTOD9  (JROF,JLEV)=0.0_JPRB
        PSPDS9 (JROF,JLEV)=0.0_JPRB
        PLPD9  (JROF,JLEV)=0.0_JPRB
        PDPD9  (JROF,JLEV)=0.0_JPRB
      ENDDO
    ENDDO
    PSDIV9(KST:KPROF)=0.0_JPRB

  ELSEIF (.NOT.LDGWADV) THEN

    ! - Computation of SI terms for continuity, T and Pcha equations.
    DO JLEV=1,NFLEVG
      DO JROF=KST,KPROF
        ZSVDT(JROF,JLEV)=PGMV(JROF,JLEV,YT9%MSVD)/PREDIV(JROF)
      ENDDO
    ENDDO
    CALL SIPTP(NPROMA,1,PGMV(KST,1,YT9%MDIV),ZSVDT(KST,1),&
     & PSPDS9(KST,1),PTOD9(KST,1),PSDIV9(KST),IPROFS)  
    ! - Computation of SI terms for momentum equation.
    CALL SIDD(NPROMA,1,PGAGT9L(KST,1),ZDUM(KST,1),&
     & PGMV(KST,1,YT9%MSPDL),PGMV(KST,1,YT9%MTL),PGMVS(KST,YT9%MSPL),IPROFS)  
    CALL SIDD(NPROMA,1,PGAGT9M(KST,1),ZDUM(KST,1),&
     & PGMV(KST,1,YT9%MSPDM),PGMV(KST,1,YT9%MTM),PGMVS(KST,YT9%MSPM),IPROFS)  
    ! - Computation of SI terms for rescaled "pseudo" vertical divergence eqn.
    CALL SISEVE(NPROMA,1,PGMV(KST,1,YT9%MSPD),PLPD9(KST,1),IPROFS)
    DO JLEV=1,NFLEVG
      DO JROF=KST,KPROF
        PLPD9(JROF,JLEV)=(RG*RG/(RD*SITRA))*PLPD9(JROF,JLEV)
      ENDDO
    ENDDO

  ENDIF

ENDIF

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

! * For "spectral RT" option, adjust semi-implicit term in
!   T-equation to compensate for later multiplication by R/Rd

IF (LSPRT) THEN
  IF (LTWOTL) THEN
    ! remark for lpc_full:
    !  predictor: treatment of "t" data.
    !  corrector: treatment of provisional "t+dt" data.
    ! So in this case this is always the Y[X]%MP data which are used.
    CALL GPRCP(NPROMA,KST,KPROF,NFLEVG,PGFL=PGFL,PR=ZR9)
    DO JLEV=1,NFLEVG
      DO JROF=KST,KPROF
        PTOD0(JROF,JLEV)=RD*PTOD0(JROF,JLEV)/ZR9(JROF,JLEV)
      ENDDO
    ENDDO
  ELSE
    CALL GPRCP(NPROMA,KST,KPROF,NFLEVG,PGFL=PGFL,KGFLTYP=9,PR=ZR9)
    DO JLEV=1,NFLEVG
      DO JROF=KST,KPROF
        PTOD0(JROF,JLEV)=RD*PTOD0(JROF,JLEV)/ZR9(JROF,JLEV)
        PTOD9(JROF,JLEV)=RD*PTOD9(JROF,JLEV)/ZR9(JROF,JLEV)
      ENDDO
    ENDDO
  ENDIF
ENDIF

! * Add semi-implicit Coriolis terms to momentum eqn SI terms
!   if required (LIMPF=.T.).

IF (LIMPF) THEN
  DO JLEV=1,NFLEVG
    DO JROF=KST,KPROF
      PGAGT0L(JROF,JLEV)=PGAGT0L(JROF,JLEV)-PRCORI(JROF)*PGMV(JROF,JLEV,YT0%MV)
      PGAGT0M(JROF,JLEV)=PGAGT0M(JROF,JLEV)+PRCORI(JROF)*PGMV(JROF,JLEV,YT0%MU)
    ENDDO
  ENDDO
  IF (.NOT.LTWOTL) THEN
    DO JLEV=1,NFLEVG
      DO JROF=KST,KPROF
        PGAGT9L(JROF,JLEV)=PGAGT9L(JROF,JLEV) &
         & -PRCORI(JROF)*PGMV(JROF,JLEV,YT9%MV)
        PGAGT9M(JROF,JLEV)=PGAGT9M(JROF,JLEV) &
         & +PRCORI(JROF)*PGMV(JROF,JLEV,YT9%MU)
      ENDDO
    ENDDO
  ENDIF
ENDIF

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

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

