! Library:phys $Id: hltridiag.F90 5126 2007-05-11 16:21:54Z towil $

!options xopt(noeval)
subroutine hltridiag(khor,       klev,      kstart,  &
     &               kstop,      pvarm,     pa,      &
     &               pc   ,      ptime,     pct,     &
     &               psource,    pvarp,     pzb,     & 
     &               pzy,        pzom,      pbet     )
!     -----------------------------------------------------------------
!     PURPOSE: 
!     Solves a tridiagonal system of equations. 
!     Conceived for a variable 'pvarm' at a full level

!     The standard version of this scheme is designed for a flux
!     boundary condition at the surface level, but
!     this routine also is suitable for solving a system with
!     a zero (value) boundary condition (like for the horizontal wind)
!     In that case pc(nlev) has to be nonzero, and contains K
!     in surface layer.
!     ------------------------------------------------------------------
!     INTERFACE  :  subroutine 'hltridiag' is called 
!     ------------  from subroutine 'hlvcbr'        

!     EXTERNAL SUBROUTINES:  none
!     ----------------------     
!     AUTHOR:   Original version from Joan Cuxart 1999-09-20 
!               Update   version from B.H.Sass    2005-09-26
!     ==================================================================
!     1. Declarations. 
!     ==================================================================
!     1.1 MODULES USED  

use parkind1  ,only : jpim ,jprb
use yomhook   ,only : lhook    ,dr_hook 

!      1.2 ARGUMENT DECLARATIONS

implicit none

integer(kind=jpim),  intent(in)     ::   khor
integer(kind=jpim),  intent(in)     ::   klev
integer(kind=jpim),  intent(in)     ::   kstart
integer(kind=jpim),  intent(in)     ::   kstop

real(kind=jprb)   ,  intent(in)     ::   ptime
real(kind=jprb)   ,  intent(in)     ::   pct

real(kind=jprb)   ,  intent(in)     ::   pvarm(khor,klev)
real(kind=jprb)   ,  intent(in)     ::   pa(khor,klev) 
real(kind=jprb)   ,  intent(in)     ::   pc(khor,klev)
real(kind=jprb)   ,  intent(in)     ::   psource(khor,klev)

real(kind=jprb)   ,  intent(out)    ::   pvarp(khor,klev)

real(kind=jprb)   ,  intent(inout)  ::   pzb(khor,klev)
real(kind=jprb)   ,  intent(inout)  ::   pzy(khor,klev)
real(kind=jprb)   ,  intent(inout)  ::   pzom(khor,klev) 
real(kind=jprb)   ,  intent(inout)  ::   pbet(khor)

!  1.3  OTHER DECLARATIONS 

integer(kind=jpim)   ::   i, ik
real(kind=jprb)      ::   zhook_handle

      if (lhook) call dr_hook('hltridiag',0,zhook_handle)

      do ik=klev,1,-1
        do i=kstart,kstop
          pzy(i,ik)=pvarm(i,ik) + ptime*psource(i,ik)
          pzb(i,ik)=1.-pct*(pa(i,ik)+pc(i,ik))
          pzom(i,ik)=0.
        enddo
      enddo

      do i=kstart,kstop
        pbet(i)=pzb(i,1)
        pvarp(i,1)=pzy(i,1)/pbet(i)
      enddo

      do ik=2,klev
        do i=kstart,kstop
          pzom(i,ik)=pct*pc(i,ik-1)/pbet(i)
          pbet(i)=pzb(i,ik) -pct*pa(i,ik)*pzom(i,ik)
          pvarp(i,ik)=(pzy(i,ik) -pct*pa(i,ik)*pvarp(i,ik-1))/pbet(i)
        enddo
      enddo

      do ik=klev-1,1,-1
        do i=kstart,kstop
          pvarp(i,ik)=pvarp(i,ik) -pzom(i,ik+1)*pvarp(i,ik+1)
        enddo
      enddo

      if (lhook) call dr_hook('hltridiag',1,zhook_handle)

end subroutine hltridiag
