SUBROUTINE GRID_BILINEAR(KLAT_IN,KLON_IN,PLAT_IN,KIN,&
                       & KLAT_OUT,KLON_OUT,PLAT_OUT,KOUT,&
                       & PFLD_IN,PFLD_OUT)  

!    Purpose.
!    --------
!      Bilinear interpolation of grid field from model resolution
!      to grid defined by input parameter. Assumes the whole
!      field is in memory.

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

!    Input:
!      KLAT_IN  - number of latitude rows of the input grid
!      KLON_IN  - number of longitudes for each row of the input grid
!      PLAT_IN  - latitude (radians) of each row of the input grid
!      KOUT     - size of input array
!      KLAT_OUT - number of latitude rows of the output grid
!      KLON_OUT - number of longitudes for each row of the output grid
!      PLAT_OUT - latitude (radians) of each row of the output grid
!      KOUT     - size of output array
!      PFLD_IN  - array of grid values at input resolution

!    Output:
!      PFLD_OUT - array of interpolated values

!    Author.
!    -------
!      Y.Tremolet

!    Modifications.
!    --------------
!      Original: 18/01/01
!        M.Hamrud      01-Oct-2003 CY28 Cleaning
!        D.Salmond     01-Jan-2006 OpenMP

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

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

USE YOMCST, ONLY : RPI

IMPLICIT NONE

INTEGER(KIND=JPIM),INTENT(IN)    :: KLAT_IN 
INTEGER(KIND=JPIM),INTENT(IN)    :: KLON_IN(KLAT_IN) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PLAT_IN(KLAT_IN) 
INTEGER(KIND=JPIM),INTENT(IN)    :: KIN 
INTEGER(KIND=JPIM),INTENT(IN)    :: KLAT_OUT 
INTEGER(KIND=JPIM),INTENT(IN)    :: KLON_OUT(KLAT_OUT) 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PLAT_OUT(KLAT_OUT) 
INTEGER(KIND=JPIM),INTENT(IN)    :: KOUT 
REAL(KIND=JPRB)   ,INTENT(IN)    :: PFLD_IN(KIN) 
REAL(KIND=JPRB)   ,INTENT(OUT)   :: PFLD_OUT(KOUT)

INTEGER(KIND=JPIM) :: jlat, jlon, ilats, ilatn, isw, inw, ise, ine, ii, ijlat
REAL(KIND=JPRB) :: zlat, zlon, zdlon, zdlonn, zdlons, zwgtlat, zwgtnw, zwgtsw, &
 & zlonnw, zlonsw  
INTEGER(KIND=JPIM) :: ind_in(KLAT_IN)
INTEGER(KIND=JPIM) :: ind_out(KLAT_OUT)
REAL(KIND=JPRB) :: ZHOOK_HANDLE

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

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

CALL GSTATS(1945,0)
ii=0
DO ijlat=1,klat_in
  ind_in(ijlat)=ii
  ii=ii+klon_in(ijlat)
ENDDO
ii=0
DO ijlat=1,klat_out
  ind_out(ijlat)=ii
  ii=ii+klon_out(ijlat)
ENDDO
CALL GSTATS(1945,1)

CALL GSTATS(1472,0)
!$OMP PARALLEL&
!$OMP& PRIVATE(jlat,zlat,ilats,ilatn,zwgtlat,&
!$OMP& zdlon,zdlons,zdlonn,jlon,zlon,&
!$OMP& isw,inw,ise,ine,zlonsw,zlonnw,zwgtsw,zwgtnw)

!$OMP DO SCHEDULE(DYNAMIC,1)
DO jlat=1,klat_out
  zlat = plat_out(jlat)
  IF (zlat <= PLAT_IN(klat_in)) THEN
    ilats = klat_in
    ilatn = klat_in
  ELSE
    ilats = 1
    DO WHILE (zlat < PLAT_IN(ilats))
      ilats = ilats+1
    ENDDO
    ilatn = MAX(1,ilats-1)
  ENDIF

  IF (ilatn == ilats) THEN
    zwgtlat = 0.
  ELSE
    zwgtlat = (zlat-PLAT_IN(ilatn))/(PLAT_IN(ilats)-PLAT_IN(ilatn))
  ENDIF

  zdlon  = 2.0*RPI/klon_out(jlat)
  zdlons = 2.0*RPI/klon_in(ilats)
  zdlonn = 2.0*RPI/klon_in(ilatn)

  DO jlon=1,klon_out(jlat)
    zlon=(jlon-1)*zdlon

    isw = 1+MOD(INT(zlon/zdlons), klon_in(ilats))
    inw = 1+MOD(INT(zlon/zdlonn), klon_in(ilatn))
    ise = 1+MOD(isw, klon_in(ilats) )
    ine = 1+MOD(inw, klon_in(ilatn) )

    zlonsw = zdlons*(isw-1)
    zlonnw = zdlonn*(inw-1)
    zwgtsw = (zlon-zlonsw)/zdlons
    zwgtnw = (zlon-zlonnw)/zdlonn

    PFLD_OUT(jlon+ind_out(jlat)) = &
     & zwgtlat *(      zwgtsw *PFLD_IN(ind_in(ilats)+ise)   &
     & +(1.0-zwgtsw)*PFLD_IN(ind_in(ilats)+isw) ) &
     & + (1.0-zwgtlat)*(      zwgtnw *PFLD_IN(ind_in(ilatn)+ine)   &
     & +(1.0-zwgtnw)*PFLD_IN(ind_in(ilatn)+inw) )  
  ENDDO
ENDDO
!$OMP END DO
!$OMP END PARALLEL
CALL GSTATS(1472,1)


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