SUBROUTINE LAIDLITLAD(KPROMA,KPROMB,KSTART,KPROF,KFLEV,&
 & KFLDN,KFLDX,KFLD,KSEP,KMAP,PSIGN,LDVECADIN,&
 & PDLAT,PDLO,PDLAT5,PDLO5,KL0,&
 & KINC,PZINC,KDIM,PXSL,PXSL5,PXF,PXF5)  

USE YOMSLREP, ONLY : LSLADREP
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK

!**** *LAIDLITLAD - semi-LAgrangian scheme:   (adjoint version)
!                 Bilinear horizontal interpolations for one variable.
!     N.B.: Not to be confused with LAIDLIAD, which is used when the
!     interpolation point is NOT a function of the control variable!

!     Purpose.
!     --------
!       Performs bilinear horizontal interpolations for one variable.

!**   Interface.
!     ----------
!        *CALL* *LAIDLITLAD(KPROMA,KPROMB,KSTART,KPROF,KFLEV
!                      ,KFLDN,KFLDX,KFLD,KSEP,KMAP,PSIGN,LDVECADIN
!                      ,PDLAT,PDLO,PDLAT5,PDLO5,KL0
!                      ,KINC,PZINC,KDIM,PXSL,PXSL5,PXF,PXF5)

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

!        INPUT:
!          KPROMA  - horizontal dimension for grid-point quantities.
!          KPROMB  - horizontal dimension for interpolation point
!                    quantities.
!          KSTART  - first element of arrays where
!                    computations are performed.
!          KPROF   - depth of work.
!          KFLEV   - vertical dimension.
!          KFLDN   - number of the first field.
!          KFLDX   - number of the last field.
!          KFLD    - field offset in semi-lagrangian buffer.
!          KSEP    - vertical separation for updates.
!          KMAP    - mapping array for bit reproducibility
!          PSIGN   - sign (+ or -) to be applied to point (symmetric/
!                    antisymmetric properties at polar latitudes)
!          LDVECADIN - switch for scalar adjoint interpolation
!          KL0     - indices of the four western points
!                    of the 16 points interpolation grid.
!          KDIM    - first dimension of KINC and PZINC
!          PXF     - interpolated variable.
! ----------------------- trajectory variables ---------------------------
!          PDLAT5  - weight (distance) for horizontal linear interpolation
!                    on a same latitude.
!          PDLO5   - weights (distances) for horizontal linear interpolation
!                    on a same longitude.
!          PXSL5   - quantity to be interpolated.
! ------------------------------------------------------------------------

!        OUTPUT:
!          KINC    - addresses for increments.
!          PZINC   - increments (saved for later).
!          PXF5    - interpolated variable (TRAJECTORY).

!        INPUT/OUTPUT:
!          PDLAT   - weight (distance) for horizontal linear interpolation
!                    on a same latitude.
!          PDLO    - weights (distances) for horizontal linear interpolation
!                    on a same longitude.
!          PXSL    - quantity to be interpolated.

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

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

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

!        No external.

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

!     Author.
!     -------
!        C. Temperton (ECMWF)

!     Modifications.
!     --------------
!      Original : 98/10/15.
!      Modified 99-11-16 by C. Temperton: correct vectorization!      
!      Modified 00-02-04 by C. Temperton: KINC array transposed.
!      Modified 00-02-09 by C. Temperton: KSEP introduced.     
!      Modified 00-02-17 by C. Temperton: more optimization....
!      Modified 00-07-11 by G. Mozdzynski: bit reproducibility support
!      Modified 01-02-27 by C. Temperton: LVECADIN option.
!      M.Hamrud      01-Oct-2003 CY28 Cleaning
!      K. Yessad (Sep 2008): update comments + cleanings.
!     ------------------------------------------------------------------

USE PARKIND1  ,ONLY : JPIM     ,JPRB

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

IMPLICIT NONE

INTEGER(KIND=JPIM),INTENT(IN)    :: KPROMA 
INTEGER(KIND=JPIM),INTENT(IN)    :: KPROMB 
INTEGER(KIND=JPIM),INTENT(IN)    :: KFLEV 
INTEGER(KIND=JPIM),INTENT(IN)    :: KFLDN 
INTEGER(KIND=JPIM),INTENT(IN)    :: KFLDX 
INTEGER(KIND=JPIM),INTENT(IN)    :: KDIM 
INTEGER(KIND=JPIM),INTENT(IN)    :: KSTART 
INTEGER(KIND=JPIM),INTENT(IN)    :: KPROF 
INTEGER(KIND=JPIM),INTENT(IN)    :: KFLD 
INTEGER(KIND=JPIM),INTENT(IN)    :: KSEP 
INTEGER(KIND=JPIM),INTENT(IN)    :: KMAP(KPROMB,4,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PSIGN(KPROMB,4,KFLEV) 
LOGICAL           ,INTENT(IN)    :: LDVECADIN 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PDLAT(KPROMB,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PDLO(KPROMB,KFLEV,1:2) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PDLAT5(KPROMB,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PDLO5(KPROMB,KFLEV,1:2) 
INTEGER(KIND=JPIM),INTENT(IN)    :: KL0(KPROMB,KFLEV,1:2) 
INTEGER(KIND=JPIM),INTENT(OUT)   :: KINC(KDIM*KFLEV+1,KPROMB) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PZINC(KDIM*KFLEV+1,KPROMB) 
REAL(KIND=JPRB)   ,INTENT(INOUT) :: PXSL(KPROMA*(KFLDX-KFLDN+1)) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PXSL5(KPROMA*(KFLDX-KFLDN+1)) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PXF(KPROMB,KFLEV) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PXF5(KPROMB,KFLEV) 

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

INTEGER(KIND=JPIM) :: IB, ILEV, JJLEV, JLEV, JROF, IBASE

REAL(KIND=JPRB) :: ZDLAT, ZDLAT5, ZDLO1, ZDLO15, ZDLO2, ZDLO25,&
 & ZVALLO1, ZVALLO15, ZVALLO2, ZVALLO25  

REAL(KIND=JPRB) :: ZSUM(KPROMB,4,KFLEV)
REAL(KIND=JPRB) :: ZHOOK_HANDLE

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

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

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

!*       1.    INTERPOLATIONS.
!              ---------------

IBASE=(KFLD-1)*KPROMA

ILEV=1

IF( LSLADREP )THEN

  IF (.NOT.LDVECADIN) THEN

    DO JLEV=1,KFLEV

      DO JROF=KSTART,KPROF

!     Computation of coordinates and distances (trajectory).

        ZDLAT5 =PDLAT5(JROF,JLEV)
        ZDLO15 =PDLO5(JROF,JLEV,1)
        ZDLO25 =PDLO5(JROF,JLEV,2)

!     Interpolation (TRAJECTORY).

        ZVALLO15=PXSL5(KL0(JROF,JLEV,1)+1) + ZDLO15*&
         & ( PXSL5(KL0(JROF,JLEV,1)+2)-PXSL5(KL0(JROF,JLEV,1)+1) )  
        ZVALLO25=PXSL5(KL0(JROF,JLEV,2)+1) + ZDLO25*&
         & ( PXSL5(KL0(JROF,JLEV,2)+2)-PXSL5(KL0(JROF,JLEV,2)+1) )  
!         May not need this, but keep it for now:
        PXF5(JROF,JLEV)= ZVALLO15 + ZDLAT5*(ZVALLO25-ZVALLO15)

!     Interpolation (adjoint).

        ZVALLO1=(1.0_JPRB-ZDLAT5)*PXF(JROF,JLEV)
        ZVALLO2=ZDLAT5*PXF(JROF,JLEV)
        ZDLAT=(ZVALLO25-ZVALLO15)*PXF(JROF,JLEV)
        ZSUM(JROF,1,JLEV)= PSIGN(JROF,1,JLEV)*((1.0_JPRB-ZDLO15)*ZVALLO1)
        ZSUM(JROF,2,JLEV)= PSIGN(JROF,2,JLEV)*(ZDLO15*ZVALLO1)
        ZDLO1=ZVALLO1*( PXSL5(KL0(JROF,JLEV,1)+2)-PXSL5(KL0(JROF,JLEV,1)+1) )
        ZSUM(JROF,3,JLEV)= PSIGN(JROF,3,JLEV)*((1.0_JPRB-ZDLO25)*ZVALLO2)
        ZSUM(JROF,4,JLEV)= PSIGN(JROF,4,JLEV)*(ZDLO25*ZVALLO2)
        ZDLO2=ZVALLO2*( PXSL5(KL0(JROF,JLEV,2)+2)-PXSL5(KL0(JROF,JLEV,2)+1) )
  
        PDLAT(JROF,JLEV)=PDLAT(JROF,JLEV)+ZDLAT
        PDLO(JROF,JLEV,1)=PDLO(JROF,JLEV,1)+ZDLO1
        PDLO(JROF,JLEV,2)=PDLO(JROF,JLEV,2)+ZDLO2

      ENDDO
    ENDDO

    DO JROF=KSTART,KPROF
      DO JLEV=1,KFLEV
        PXSL(KMAP(JROF,1,JLEV))=PXSL(KMAP(JROF,1,JLEV))+ZSUM(JROF,1,JLEV)
        PXSL(KMAP(JROF,2,JLEV))=PXSL(KMAP(JROF,2,JLEV))+ZSUM(JROF,2,JLEV)
        PXSL(KMAP(JROF,3,JLEV))=PXSL(KMAP(JROF,3,JLEV))+ZSUM(JROF,3,JLEV)
        PXSL(KMAP(JROF,4,JLEV))=PXSL(KMAP(JROF,4,JLEV))+ZSUM(JROF,4,JLEV)
      ENDDO
    ENDDO

  ELSE

    DO JJLEV=1,KSEP
      DO JLEV=JJLEV,KFLEV,KSEP

        IB=(ILEV-1)*KDIM

!OCL NOVREC
        DO JROF=KSTART,KPROF

!     Computation of coordinates and distances (trajectory).

          ZDLAT5 =PDLAT5(JROF,JLEV)
          ZDLO15 =PDLO5(JROF,JLEV,1)
          ZDLO25 =PDLO5(JROF,JLEV,2)

!     Interpolation (TRAJECTORY).

          ZVALLO15=PXSL5(KL0(JROF,JLEV,1)+1) + ZDLO15*&
           & ( PXSL5(KL0(JROF,JLEV,1)+2)-PXSL5(KL0(JROF,JLEV,1)+1) )  
          ZVALLO25=PXSL5(KL0(JROF,JLEV,2)+1) + ZDLO25*&
           & ( PXSL5(KL0(JROF,JLEV,2)+2)-PXSL5(KL0(JROF,JLEV,2)+1) )  
!         May not need this, but keep it for now:
          PXF5(JROF,JLEV)= ZVALLO15 + ZDLAT5*(ZVALLO25-ZVALLO15)

!     Interpolation (adjoint).

          KINC(IB+1,JROF)=IBASE+KMAP(JROF,1,JLEV)
          KINC(IB+2,JROF)=IBASE+KMAP(JROF,2,JLEV)
          KINC(IB+3,JROF)=IBASE+KMAP(JROF,3,JLEV)
          KINC(IB+4,JROF)=IBASE+KMAP(JROF,4,JLEV)

          ZVALLO1=(1.0_JPRB-ZDLAT5)*PXF(JROF,JLEV)
          ZVALLO2=ZDLAT5*PXF(JROF,JLEV)
          ZDLAT=(ZVALLO25-ZVALLO15)*PXF(JROF,JLEV)
          PZINC(IB+1,JROF)=PSIGN(JROF,1,JLEV)*((1.0_JPRB-ZDLO15)*ZVALLO1)
          PZINC(IB+2,JROF)=PSIGN(JROF,2,JLEV)*(ZDLO15*ZVALLO1)
          ZDLO1=ZVALLO1*( PXSL5(KL0(JROF,JLEV,1)+2)-PXSL5(KL0(JROF,JLEV,1)+1) )
          PZINC(IB+3,JROF)=PSIGN(JROF,3,JLEV)*((1.0_JPRB-ZDLO25)*ZVALLO2)
          PZINC(IB+4,JROF)=PSIGN(JROF,4,JLEV)*(ZDLO25*ZVALLO2)
          ZDLO2=ZVALLO2*( PXSL5(KL0(JROF,JLEV,2)+2)-PXSL5(KL0(JROF,JLEV,2)+1) )
  
          PDLAT(JROF,JLEV)=PDLAT(JROF,JLEV)+ZDLAT
          PDLO(JROF,JLEV,1)=PDLO(JROF,JLEV,1)+ZDLO1
          PDLO(JROF,JLEV,2)=PDLO(JROF,JLEV,2)+ZDLO2

        ENDDO
        ILEV=ILEV+1
      ENDDO
    ENDDO

  ENDIF

ELSE         ! (non-reproducible)

  IF (.NOT.LDVECADIN) THEN

    DO JLEV=1,KFLEV
  
      DO JROF=KSTART,KPROF
  
!     Computation of coordinates and distances (trajectory).

        ZDLAT5 =PDLAT5(JROF,JLEV)
        ZDLO15 =PDLO5(JROF,JLEV,1)
        ZDLO25 =PDLO5(JROF,JLEV,2)

!     Interpolation (TRAJECTORY).

        ZVALLO15=PXSL5(KL0(JROF,JLEV,1)+1) + ZDLO15*&
         & ( PXSL5(KL0(JROF,JLEV,1)+2)-PXSL5(KL0(JROF,JLEV,1)+1) )  
        ZVALLO25=PXSL5(KL0(JROF,JLEV,2)+1) + ZDLO25*&
         & ( PXSL5(KL0(JROF,JLEV,2)+2)-PXSL5(KL0(JROF,JLEV,2)+1) )  
!         May not need this, but keep it for now:
        PXF5(JROF,JLEV)= ZVALLO15 + ZDLAT5*(ZVALLO25-ZVALLO15)

!     Interpolation (adjoint).
  
        ZVALLO1=(1.0_JPRB-ZDLAT5)*PXF(JROF,JLEV)
        ZVALLO2=ZDLAT5*PXF(JROF,JLEV)
        ZDLAT=(ZVALLO25-ZVALLO15)*PXF(JROF,JLEV)
        PXSL(KL0(JROF,JLEV,1)+1)=PXSL(KL0(JROF,JLEV,1)+1)&
         & +(1.0_JPRB-ZDLO15)*ZVALLO1  
        PXSL(KL0(JROF,JLEV,1)+2)=PXSL(KL0(JROF,JLEV,1)+2)&
         & +ZDLO15*ZVALLO1  
        ZDLO1=ZVALLO1*( PXSL5(KL0(JROF,JLEV,1)+2)-PXSL5(KL0(JROF,JLEV,1)+1) )
        PXSL(KL0(JROF,JLEV,2)+1)=PXSL(KL0(JROF,JLEV,2)+1)&
         & +(1.0_JPRB-ZDLO25)*ZVALLO2  
        PXSL(KL0(JROF,JLEV,2)+2)=PXSL(KL0(JROF,JLEV,2)+2)&
         & +ZDLO25*ZVALLO2  
        ZDLO2=ZVALLO2*( PXSL5(KL0(JROF,JLEV,2)+2)-PXSL5(KL0(JROF,JLEV,2)+1) )
  
        PDLAT(JROF,JLEV)=PDLAT(JROF,JLEV)+ZDLAT
        PDLO(JROF,JLEV,1)=PDLO(JROF,JLEV,1)+ZDLO1
        PDLO(JROF,JLEV,2)=PDLO(JROF,JLEV,2)+ZDLO2
  
      ENDDO
    ENDDO

  ELSE

    DO JJLEV=1,KSEP
      DO JLEV=JJLEV,KFLEV,KSEP
  
        IB=(ILEV-1)*KDIM
    
!OCL NOVREC
        DO JROF=KSTART,KPROF
  
!     Computation of coordinates and distances (trajectory).

          ZDLAT5 =PDLAT5(JROF,JLEV)
          ZDLO15 =PDLO5(JROF,JLEV,1)
          ZDLO25 =PDLO5(JROF,JLEV,2)

!     Interpolation (TRAJECTORY).

          ZVALLO15=PXSL5(KL0(JROF,JLEV,1)+1) + ZDLO15*&
           & ( PXSL5(KL0(JROF,JLEV,1)+2)-PXSL5(KL0(JROF,JLEV,1)+1) )  
          ZVALLO25=PXSL5(KL0(JROF,JLEV,2)+1) + ZDLO25*&
           & ( PXSL5(KL0(JROF,JLEV,2)+2)-PXSL5(KL0(JROF,JLEV,2)+1) )  
!         May not need this, but keep it for now:
          PXF5(JROF,JLEV)= ZVALLO15 + ZDLAT5*(ZVALLO25-ZVALLO15)

!     Interpolation (adjoint).

          KINC(IB+1,JROF)=IBASE+KL0(JROF,JLEV,1)+1
          KINC(IB+2,JROF)=IBASE+KL0(JROF,JLEV,1)+2
          KINC(IB+3,JROF)=IBASE+KL0(JROF,JLEV,2)+1
          KINC(IB+4,JROF)=IBASE+KL0(JROF,JLEV,2)+2
  
          ZVALLO1=(1.0_JPRB-ZDLAT5)*PXF(JROF,JLEV)
          ZVALLO2=ZDLAT5*PXF(JROF,JLEV)
          ZDLAT=(ZVALLO25-ZVALLO15)*PXF(JROF,JLEV)
          PZINC(IB+1,JROF)=(1.0_JPRB-ZDLO15)*ZVALLO1
          PZINC(IB+2,JROF)=ZDLO15*ZVALLO1
          ZDLO1=ZVALLO1*( PXSL5(KL0(JROF,JLEV,1)+2)-PXSL5(KL0(JROF,JLEV,1)+1) )
          PZINC(IB+3,JROF)=(1.0_JPRB-ZDLO25)*ZVALLO2
          PZINC(IB+4,JROF)=ZDLO25*ZVALLO2
          ZDLO2=ZVALLO2*( PXSL5(KL0(JROF,JLEV,2)+2)-PXSL5(KL0(JROF,JLEV,2)+1) )
  
          PDLAT(JROF,JLEV)=PDLAT(JROF,JLEV)+ZDLAT
          PDLO(JROF,JLEV,1)=PDLO(JROF,JLEV,1)+ZDLO1
          PDLO(JROF,JLEV,2)=PDLO(JROF,JLEV,2)+ZDLO2
  
        ENDDO
        ILEV=ILEV+1
      ENDDO
    ENDDO

  ENDIF

ENDIF

!     ------------------------------------------------------------------
IF (LHOOK) CALL DR_HOOK('LAIDLITLAD',1,ZHOOK_HANDLE)
END SUBROUTINE LAIDLITLAD
