!-------------------------------------- LICENCE BEGIN ------------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer, 
!                     version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms 
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer 
!version 3 or (at your option) any later version that should be found at: 
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html 
!
!This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
!without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
!See the above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software; 
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec), 
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
!     #############################################################

      SUBROUTINE COEF_VER_INTERP_LIN2D(PZ1,PZ2,KKLIN,PCOEFLIN,OLEUG),1
!     #############################################################
!
!!****  from *VER_INTERP_LIN* - vertical linear interpolation
!!      (only the 2D vertical linear interpolation)
!!
!!    PURPOSE
!!    -------
!     This function computes the interpolation coefficient XCOEFLIN
!     of the level XKLIN of grid PZ1 which is just under the points of
!     grid PZ2 (respectively called hereafter 'initial' and 'target'), 
!     in order to perform linear interpolations between these 2 grids.
!
!     CAUTION:
!     * The interpolation occurs on the WHOLE grid. Therefore, one must
!     only give as argument to this function the inner points of the domain,
!     particularly for the vertical grid, where there is no physical information
!     under the ground or at and over H.
!     * The level numbers must increase from bottom to top.
!!
!!**  METHOD
!!    ------
!!    two extrapolations are possible: with the two or four nearest points.
!!
!!   Interpolation with 2 points:
!!
!!    If there is less than two points on one side, the interpolation is linear.
!!
!!    EXTERNAL
!!    --------
!!
!!    IMPLICIT ARGUMENTS
!!    ------------------
!!
!!    REFERENCE
!!    ---------
!!
!!
!!    AUTHOR
!!    ------
!!	
!     V.Masson  Meteo-France
!!
!!    MODIFICATIONS
!!    -------------
!!      Original    18/07/97
!!                  20/01/98  use explicit arguments
!!      P Jabouille 20/12/02  no extrapolation under the ground
!!      S. Malardel 11/2003   bug of no extrapolation under the ground
!!      V. Masson   10/2003   no extrapolation above top
!!      A. Lemonsu  04/2004   only 2D vertical linear interpolation
!-------------------------------------------------------------------------------
!
!*       0.    DECLARATIONS
!              ------------
!
USE MODD_VER_INTERP_LIN
!
IMPLICIT NONE
!
!*       0.1   Declaration of arguments
!              ------------------------
REAL,   DIMENSION(:,:), INTENT(IN) :: PZ1   ! altitudes of the points of the
                                            ! initial grid 
REAL,   DIMENSION(:,:), INTENT(IN) :: PZ2   ! altitudes of the points of the
                                            ! target grid 
INTEGER,DIMENSION(:,:), INTENT(OUT), OPTIONAL :: KKLIN    ! number of the level
                                                          ! of the data to be interpolated
REAL,   DIMENSION(:,:), INTENT(OUT), OPTIONAL :: PCOEFLIN ! interpolation
                                            ! coefficient
LOGICAL,OPTIONAL,       INTENT(IN) :: OLEUG ! for linear extrapolation under the ground
!
!
!*       0.2   Declaration of local variables
!              ------------------------------
!
REAL,   DIMENSION(1,SIZE(PZ1,1),SIZE(PZ1,2))          :: ZZ1   ! altitudes of the points of the
                                                               ! initial grid 
REAL,   DIMENSION(1,SIZE(PZ2,1),SIZE(PZ2,2))          :: ZZ2   ! altitudes of the points of the
                                                               ! target grid 
INTEGER,DIMENSION(1,SIZE(KKLIN,1),SIZE(KKLIN,2))      :: IKLIN 
!
REAL,   DIMENSION(1,SIZE(PCOEFLIN,1),SIZE(PCOEFLIN,2)):: ZCOEFLIN
LOGICAL,DIMENSION(SIZE(ZZ1,1),SIZE(ZZ1,2),SIZE(ZZ1,3)):: GLEVEL
INTEGER                                               :: JK2,JI,JJ
INTEGER,DIMENSION(SIZE(ZZ1,1),SIZE(ZZ1,2))            :: ILEVEL
INTEGER,DIMENSION(SIZE(ZZ1,1),SIZE(ZZ1,2))            :: IUNDER
REAL                                                  :: ZEPS  ! a small number
!-------------------------------------------------------------------------------
!
ZZ1(1,:,:)  = PZ1(:,:)
ZZ2(1,:,:)  = PZ2(:,:)
!
ZEPS = 1.E-12
!
!*       1.    ALLOCATIONS
!              -----------
!
IF ( .NOT. PRESENT(PCOEFLIN) ) THEN
!  IF (ALLOCATED(NKLIN   )) DEALLOCATE(NKLIN   )
!  IF (ALLOCATED(XCOEFLIN)) DEALLOCATE(XCOEFLIN)
  IF (ASSOCIATED(NKLIN   )) DEALLOCATE(NKLIN   )
  IF (ASSOCIATED(XCOEFLIN)) DEALLOCATE(XCOEFLIN)
  !
  ALLOCATE(NKLIN   (1,SIZE(ZZ2,2),SIZE(ZZ2,3)))
  ALLOCATE(XCOEFLIN(1,SIZE(ZZ2,2),SIZE(ZZ2,3)))
END IF
!
!-------------------------------------------------------------------------------
!
!*       2.    LOOP ON THE TARGET VERTICAL GRID
!              --------------------------------
!
DO JK2=1,SIZE(ZZ2,3)
!
!-------------------------------------------------------------------------------
!
!*       3.    Determination of the initial level under the target level JK2
!              -------------------------------------------------------------
!
  GLEVEL(:,:,:)  = ZZ1(:,:,:)<=SPREAD(ZZ2(:,:,JK2),3,SIZE(ZZ1,3)) *(1.-ZEPS)
  ILEVEL(:,:)    = COUNT(GLEVEL(:,:,:),3)
!
!* linear extrapolation under the ground
  IUNDER=ILEVEL
  ILEVEL(:,:)    = MAX(ILEVEL(:,:),1)
!
!* linear extrapolation above the uppest level
  ILEVEL(:,:)    = MIN(ILEVEL(:,:),SIZE(ZZ1,3)-1)
!
IF ( .NOT. PRESENT(PCOEFLIN) ) THEN
!* save level in module
  NKLIN(:,:,JK2) = ILEVEL(:,:)
ELSE
!* save level in argument
  IKLIN(:,:,JK2) = ILEVEL(:,:)
END IF
!
!-------------------------------------------------------------------------------
!
!*       4.    Linear interpolation coefficients
!              ---------------------------------
!
IF ( .NOT. PRESENT(PCOEFLIN) ) THEN
  DO JI=1,SIZE(ZZ1,1)
    DO JJ=1,SIZE(ZZ1,2)
      XCOEFLIN(JI,JJ,JK2)=(ZZ2(JI,JJ,JK2)-ZZ1(JI,JJ,ILEVEL(JI,JJ)+1))              &
                         /(ZZ1(JI,JJ,ILEVEL(JI,JJ))-ZZ1(JI,JJ,ILEVEL(JI,JJ)+1)) 
      IF (.NOT. PRESENT(OLEUG) .AND. IUNDER(JI,JJ) < 1 )   &
       XCOEFLIN(JI,JJ,JK2)=0.               ! no linear extrapolation under the ground
      IF (ILEVEL(JI,JJ)==SIZE(ZZ1,3)-1) &   ! no extrapolation above
       XCOEFLIN(JI,JJ,JK2)=MIN(XCOEFLIN(JI,JJ,JK2),1.)
    ENDDO
  ENDDO
ELSE
  DO JI=1,SIZE(ZZ1,1)
    DO JJ=1,SIZE(ZZ1,2)
      ZCOEFLIN(JI,JJ,JK2)=(ZZ2(JI,JJ,JK2)-ZZ1(JI,JJ,ILEVEL(JI,JJ)+1))              &
                         /(ZZ1(JI,JJ,ILEVEL(JI,JJ))-ZZ1(JI,JJ,ILEVEL(JI,JJ)+1)) 
      IF (.NOT. PRESENT(OLEUG) .AND. IUNDER(JI,JJ) < 1 )   &
       ZCOEFLIN(JI,JJ,JK2)=0.               ! no linear extrapolation under the ground
      IF (ILEVEL(JI,JJ)==SIZE(ZZ1,3)-1) &   ! no extrapolation above
       ZCOEFLIN(JI,JJ,JK2)=MIN(ZCOEFLIN(JI,JJ,JK2),1.)
    ENDDO
  ENDDO
  PCOEFLIN(:,:) = ZCOEFLIN(1,:,:)
  KKLIN(:,:)    = IKLIN(1,:,:)
END IF
!
!-------------------------------------------------------------------------------
!
END DO
!
!-------------------------------------------------------------------------------
!
END SUBROUTINE COEF_VER_INTERP_LIN2D