!copyright (C) 2001  MSC-RPN COMM  %%%CCC%%%
***S/P SGOFLX2 - sub-grid orographic drag (gravity waves + blocking)
#include "phy_macros_f.h"

      SUBROUTINE SGOFLX2 (U,V,TH,TF,ENV,GC,S,SEXPK,SH,SHEXPK, 1
     $                    UTENDGW,VTENDGW,GRAV,RGAS,TAU,
     $                    ILEV,IL1,IL2,ILG,DAMPFAC,ENVELOP,LREF,
     $                    TAUFAC,PSURF,BLOCKING,SXX,SYY,SXY)
*
#include "impnone.cdk"
*
*     LOGICAL SWITCHES TO CONTROL ROOF DRAG AND ENVELOP GW DRAG.
*
      LOGICAL DAMPFAC, ENVELOP
      LOGICAL BLOCKING,dirfac
*
      INTEGER ILEV,ILG
      REAL*8 U(ILG,ILEV),       V(ILG,ILEV),       TH(ILG,ILEV),
     1       TF(ILG,ILEV),      ENV(ILG),          GC(ILG),
     2       UTENDGW(ILG,ILEV), VTENDGW(ILG,ILEV)
C
      REAL*8 PSURF(ILG),SXX(ILG),SYY(ILG),SXY(ILG)
*
*    VERTICAL POSITIONNING ARRAYS. ...become local sigma (2D)
*
      REAL*8 S(ilg,ILEV), SEXPK(ilg,ILEV), SH(ilg,ILEV),
     1     SHEXPK(ilg,ILEV)
*
*Author
*          N.McFarlane - Flux formula, semi-implicit (May15/86)
*
*Revision
* 001      G.Pellerin CMC(June 90)- Standard documentation
* 002      N. Brunet  (May91) - New version of thermodynamic
*                 functions and file of constants
* 003      B. Bilodeau  (August 1991)- Adaptation to UNIX
* 004      R. Benoit (August 1993)- Local Sigma
* 005      N. Brunet (Feb 1994) - Changes to the numerical scheme to
*                 make it more stable according to C.Girard's analysis
* 006      B. Bilodeau (March 1994) - Optimization
* 007      B. Bilodeau (May 1994) - New physics interface
* 008      L. Lefaivre (Nov 1995) - TAUFAC passed in argument 
* 009      B. Bilodeau (Feb 2001) - Automatic arrays
* 010      A. Zadra (august 2001) - Introduction of blocking + gwd scheme with 
*                                   no overshoot
* 011      B. Bilodeau (May 2002) - Replace CVMGT by IF statements for execution
*                                   on front ends in double precision
*
*Object
*          to calculate the tendencies on wind components due
*          to gravity wave drag
*
*Arguments
*
*          - Input/Output -
* U        U component of wind as input
*          U component of wind modified by the gravity wave
*          drag as output
* V        V component of wind as input
*          V component of wind modified by the gravity wave
*          drag as output
*
*          - Input -
* TH       temperature level means
* TF       temperature
* ENV      variance associated with unresolved orography
* GC       land-sea mask (between 0(sea) and 1(land))
* S        sigma levels
* SEXPK    vertical positioning arrays; (full levels)
* SH       intermediate levels
* SHEXPK   vertical positioning arrays (half levels)
*
*          - Output -
* UTENDGW  gravity wave drag tendency on the U component of real
*          wind
* VTENDGW  gravity wave drag tendency on the V component of real
*          wind
*
*          - Input -
* GRAV     gravitational constant
* RGAS     gas constant
* TAU      timestep times a factor: 1 for two time-level models
*                                   2 for three time-level models
* ILEV     number of levels
* IL1      1st dimension of U,V,T to start calculation
* IL2      index on horizontal dimension to stop calculation
* ILG      total horizontal dimension
* DAMPFAC  .TRUE. for applying roof drag factor
* ENVELOP  .TRUE. for gravity wave drag
* LREF     number of tranche
* TAUFAC   1/(length scale).
*
*          - Internally allocated work fields -
* BVFREQ   B V frequency
* BVFREQG  gathered relevant points of BVFREQ
* VELN     the projection of the local wind on the reference wind.
*          Negative or zero values are eliminated.
* UB       U component unit vector of the reference level
*          wind(equivalenced to RATB)
* VB       V component unit vector of the reference level
*          wind(equivalenced to AMPBSQ)
* UBG      gathered relevant points of UB
* VBG      gathered relevant points of VB
* VMODB    reference wind level (equivalenced to AMPMSQ)
* VMODBG   gathered relevant points of VMODBG
* DEPFAC   dampening factor
* HEIGHT   gathered relevant points of ENV
* HITESQ   effective squared launching height
* RATB     the U component of the reference level wind
* AMPBSQ   the V component of the reference level wind
* AMPMSQ   the reference level wind
* AMPDIF   work space
* DENFAC   DFAC*TENDFAC
* TFG      gather relevant points of TF
*
*          - Output -
* UTEND    gravity wave drag tendency on UB
* VTEND    gravity wave drag tendency on VB
* DGW      equivalenced to TFG
* DGWG     equivalenced to DEPFAC
* TOP      not used inside the routine
* DRAG     contains the points where GW calculations will be done,
*          that is:
*          A - if over land
*          B - if bottom wind > VMIN
*          C - if requested and enveloppe height >= HMIN
* sg       gathered values of sigma coordinate (s)
* shg      gathered values of sh
*
**
*
*
************************************************************************
*    AUTOMATIC ARRAYS
************************************************************************
*
     AUTOMATIC ( DRAG     , INTEGER , (ILG     ) )
     AUTOMATIC ( TOP      , INTEGER , (ILG     ) )
c
     AUTOMATIC ( BLOFF    , INTEGER , (ILG     ) )
*
     AUTOMATIC ( BVFREQ   , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( VELN     , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( DEPFAC   , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( UB       , REAL*8  , (ILG     ) )
     AUTOMATIC ( VB       , REAL*8  , (ILG     ) )
     AUTOMATIC ( VMODB    , REAL*8  , (ILG     ) )
     AUTOMATIC ( UBG      , REAL*8  , (ILG     ) )
     AUTOMATIC ( VBG      , REAL*8  , (ILG     ) )
     AUTOMATIC ( VMODBG   , REAL*8  , (ILG     ) )
     AUTOMATIC ( HEIGHT   , REAL*8  , (ILG     ) )
     AUTOMATIC ( HITESQ   , REAL*8  , (ILG     ) )
     AUTOMATIC ( RATB     , REAL*8  , (ILG     ) )
     AUTOMATIC ( AMPBSQ   , REAL*8  , (ILG     ) )
     AUTOMATIC ( AMPMSQ   , REAL*8  , (ILG     ) )
     AUTOMATIC ( AMPDIF   , REAL*8  , (ILG     ) )
     AUTOMATIC ( DENFAC   , REAL*8  , (ILG     ) )
     AUTOMATIC ( BVFREQG  , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( TFG      , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( UTEND    , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( VTEND    , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( DGW      , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( DGWG     , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( SG       , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( SHG      , REAL*8  , (ILG,ILEV) )
C
     AUTOMATIC ( IZT      , INTEGER , (ILG     ) )
     AUTOMATIC ( IZT2     , INTEGER , (ILG     ) )
     AUTOMATIC ( IZT3     , INTEGER , (ILG     ) )
     AUTOMATIC ( IZB      , INTEGER , (ILG     ) )
     AUTOMATIC ( RHO      , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( ZB       , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( UAV      , REAL*8  , (ILG     ) )
     AUTOMATIC ( VAV      , REAL*8  , (ILG     ) )
     AUTOMATIC ( VELAV    , REAL*8  , (ILG     ) )
     AUTOMATIC ( BVFREQAV , REAL*8  , (ILG     ) )
     AUTOMATIC ( RHOAV    , REAL*8  , (ILG     ) )
     AUTOMATIC ( DELZ     , REAL*8  , (ILG     ) )
     AUTOMATIC ( HBLK     , REAL*8  , (ILG     ) )
     AUTOMATIC ( HCRT     , REAL*8  , (ILG     ) )
     AUTOMATIC ( SLPF     , REAL*8  , (ILG     ) )
     AUTOMATIC ( FDIR     , REAL*8  , (ILG     ) )
     AUTOMATIC ( UTENDLLB , REAL*8  , (ILG,ILEV) )
     AUTOMATIC ( VTENDLLB , REAL*8  , (ILG,ILEV) )
*
************************************************************************

*
      INTEGER IL1,IL2,LREF,ILEVM,LEN,LREFM,LENGW
      INTEGER I,L,JYES,JNO,BLKHGT
      REAL GRAV,RGAS,TAU,TAUFAC
      REAL*8 VMIN,V0,WA,WB,HMIN,ZERO,UN,ETA,
     1       DAMPSCA,DTTDSF,DTTDZL,RATIO,
     2       SIGB,BVFB,HSQMAX,HSQ,HSCAL,DFAC,WIND,BVF,
     3       DFLXP,DENOM,TENDFAC,DFLXM,DAMPRF,VELMOD,
     4       NHMIN,CDBLK,DZ,AMP,AMPMAX,
     5       PIOTWO,SPLS,SMNS,SCRS,GAMMA,THETA,PSI,
     6       CPSI,SPSI,FVERT,SPPR,SMPR,UPARL
*
*
      integer ii
      EXTERNAL GATHER,SCATTER
C
C     * CERTAIN ARRAYS CAN BE EQUIVALENCED IN THE CALLING SEQUENCE
C     * IN ORDER TO SAVE CORE SPACE. THESE ARE SPECIFICALLY :
C
C     * EQUIVALENCE (HITESQ(1),   HEIGHT(1))
C     * EQUIVALENCE (VELN(1,1),   BVFREQ(1,1))
C     * EQUIVALENCE (UB(1),       RATB(1))
C     * EQUIVALENCE (VB(1),       AMPBSQ(1))
C     * EQUIVALENCE (VMODB(1),    AMPMSQ(1))
C     * EQUIVALENCE (DGW(1,1),    TFG(1,1))
C     * EQUIVALENCE (DEPFAC(1,1), DGWG(1,1))
C
C     * SO THAT THE TOTAL WORK SPACE IS AT MIMINUM ILG*(6*ILEV+9).
C
C     * CONSTANTS VALUES DEFINED IN DATA STATEMENT ARE :
C
C     * VMIN     = MIMINUM WIND IN THE DIRECTION OF REFERENCE LEVEL
C     *            WIND BEFORE WE CONSIDER BREAKING TO HAVE OCCURED.
C     * DAMPSCAL = DAMPING TIME FOR GW DRAG IN SECONDS.
C     * WA, WB   = WEIGHTS APPLIED TO LAST TWO MODEL LEVELS NEAR THE
C     *            SURFACE TO FIND REFERENCE VALUES OF VARIABLES.
C     * HMIN     = MIMINUM ENVELOPE HEIGHT REQUIRED TO PRODUCE GW DRAG.
C     * V0       = VALUE OF WIND THAT APPROXIMATES ZERO.
C
      SAVE VMIN,V0,WA,WB,HMIN,ZERO,UN,DAMPSCA,NHMIN,CDBLK
      DATA    VMIN /  2.0D0 /, V0    / 1.D-30 /, WA     /  0.5D0 /,
     1        WB   /  0.5D0 /, HMIN  / 10.0D0 /,
     2        ZERO /  0.0D0 /, UN    /  1.0D0 /, DAMPSCA/ 6.5D+6 /
     3        NHMIN/  3.0D0 /, CDBLK /  1.0D0 /
C
C---------------------------------------------------------------------
      ILEVM = ILEV - 1
      LEN   = IL2 - IL1 + 1
      LREFM = LREF-1
C
C     * VMOD IS THE REFERENCE LEVEL WIND AND ( UB, VB)
C     * ARE IT'S UNIT VECTOR COMPONENTS.
C
      DO 100 I=IL1,IL2
          UB(I)    = U(I,LREFM)
          VB(I)    = V(I,LREFM)
          VMODB(I) = SQRT (UB(I)**2 + VB(I)**2)
          VMODB(I) = MAX  (VMODB(I), UN)
          UB(I)    = UB(I)/VMODB(I)
          VB(I)    = VB(I)/VMODB(I)
  100 CONTINUE
C
C     * DRAG CONTAINS THE POINTS WHERE GW CALCULATIONS WILL BE DONE,
C     * THAT IS (A- IF OVER LAND, B- IF BOTTOM WIND > VMIN, C- IF WE
C     * ASK FOR IT AND C- IF ENVELOPPE HEIGHT >= HMIN )
C
      JYES = 0
      JNO  = LEN + 1
*VDIR NODEP
      DO 110 I=IL1,IL2
          IF (GC(I).EQ.-1. .AND. VMODB(I).GT.VMIN .AND.
     1        ENVELOP      .AND. ENV(I)  .GE.HMIN     )         THEN
              JYES        = JYES + 1
              DRAG(JYES) = I
          ELSE
              JNO         = JNO - 1
              DRAG(JNO)  = I
          ENDIF
  110 CONTINUE
C
C     * INITIALISE NECESSARY ARRAYS.
C
      LENGW = JYES
      IF (LENGW.GT.0)                                          THEN
          DO 120 L=1,ILEV
              DO 120 I=1,LEN
                  DGWG(I,L)    = ZERO
                  UTEND(I,L)   = ZERO
                  VTEND(I,L)   = ZERO
  120     CONTINUE
      ELSE
          DO 130 L=1,ILEV
              DO 130 I=IL1,IL2
                  DGW(I,L)     = ZERO
                  UTENDGW(I,L) = ZERO
                  VTENDGW(I,L) = ZERO
  130     CONTINUE
          GOTO 300
      ENDIF
C
C     * CALCULATE  B V FREQUENCY EVERYWHERE.
C
      DO 140 L=2,ILEV
          DO 140 I=IL1,IL2
              DTTDSF     =(TH(I,L)/SHEXPK(i,L)-TH(I,L-1)/SHEXPK(i,L-1))
     1                      /(SH(i,L)-SH(i,L-1))
              DTTDSF      = MIN ( DTTDSF, -5./S(i,L))
              DTTDZL      = -DTTDSF*S(i,L)*GRAV/(RGAS*TF(I,L))
              BVFREQ(I,L) = SQRT (GRAV*DTTDZL*SEXPK(i,L)/TF(I,L))
  140 CONTINUE
      DO 150 I=IL1,IL2
          BVFREQ(I,1)     = BVFREQ(I,2)
  150 CONTINUE
C
C     * GATHER RELEVANT POINTS OF UB, VB, VMODB, BVFREQ, TF,
C     * AND ENV INTO UBG, VBG, BFREQG, TFG AND HEIGHT.
C
*     CALL GATHER(LEN, UBG,    UB(IL1),   DRAG)
*     CALL GATHER(LEN, VBG,    VB(IL1),   DRAG)
*     CALL GATHER(LEN, VMODBG, VMODB(IL1),DRAG)
*     CALL GATHER(LEN, HEIGHT, ENV(IL1),  DRAG)
*
      do 155 i=1,len
         ii = drag(i) + il1 - 1
         ubg   (i) = ub   (ii)
         vbg   (i) = vb   (ii)
         vmodbg(i) = vmodb(ii)
         height(i) = env  (ii) 
  155 continue
C
      DO 160 L=1,ILEV
*         CALL GATHER(LEN, BVFREQG(1,L), BVFREQ(IL1,L),DRAG)
*         CALL GATHER(LEN, TFG(1,L),     TF(IL1,L),    DRAG)
*         CALL GATHER(LEN, sG(1,L),      s(IL1,L),     DRAG)
*         CALL GATHER(LEN, shG(1,L),     sh(IL1,L),    DRAG)
*
          do 165 i=1,len
             ii = drag(i) + il1 - 1
             bvfreqg(i,l) = bvfreq(ii,l)
             tfg    (i,l) = tf    (ii,l)
             sg     (i,l) = s     (ii,l)
             shg    (i,l) = sh    (ii,l)
  165     continue
*
  160 CONTINUE
C
C     * SMOOTH B V FREQ.
C
      DO 170 L=2,ILEV
*         RATIO = 5.*ALOG(S(L)/S(L-1))
          DO 170 I=1,LENGW
              RATIO = 5.*DLOG(Sg(i,L)/Sg(i,L-1))
              BVFREQG(I,L) = (BVFREQG(I,L-1) + RATIO*BVFREQG(I,L))
     1                       /(1.+RATIO)
  170 CONTINUE
C
C     * VELN IS THE PROJECTION OF THE LOCAL WIND ON
C     * THE REFERENCE WIND. NEGATIVE OR NUL VALUES
C     * ARE ELEMINATED. AMPDIFF IS ONLY USED AS
C     * TEMPORARY HOLDING SPACE. GATHER THE RESULT.
C
      DO 190 L=1,ILEV
          DO 180 I=IL1,IL2
              AMPDIF(I)=MAX (U(I,L)*UB(I)+V(I,L)*VB(I), V0)
  180     CONTINUE
*
*         CALL GATHER (LEN, VELN(1,L), AMPDIF(IL1), DRAG)
          do 185 i=1,len
             ii = drag(i) + il1 - 1
             veln (i,l) = ampdif(ii)
  185     continue
*
  190 CONTINUE
C
C     * CALCULATE EFFECTIVE SQUARE LAUNCHING
C     * HEIGHT, REFERENCE B V FREQUENCY, ETC.
C
*     SIGB = SH(LREFM)
      DO 200 I=1,LENGW
               BVFB = BVFREQG(I,LREFM)
               HSQMAX=    (VMODBG(I)/BVFB)**2
               HSQ=HEIGHT(I)*HEIGHT(I)
               HSCAL=RGAS*TFG(I,LREFM)/GRAV
               SIGB = SHg(i,LREFM)
               DFAC=BVFB*SIGB*VMODBG(I)/HSCAL
               AMPBSQ(I)=DFAC
               HITESQ(I)=HSQ
  200 CONTINUE
C
C
C     * CALCULATE TERMS FROM THE BOTTOM-UP.
C
      DO 240 L=LREFM,1,-1
          DO 240 I=1,LENGW
               WIND=VELN(I,L)
               BVF=BVFREQG(I,L)
               HSCAL=RGAS*TFG(I,L)/GRAV
               HSQMAX=0.5*(WIND/BVF)**2
               IF (VELN(I,L).LT.UN) HSQMAX = ZERO
               DFAC=BVF*Sg(i,L)*WIND/HSCAL
               RATIO=AMPBSQ(I)/DFAC
               HSQ=MIN(RATIO*HITESQ(I),HSQMAX)
               HITESQ(I)=HSQ
               AMPBSQ(I)=DFAC
               DEPFAC(I,L)  =TAUFAC*DFAC*HSQ
  240 CONTINUE
C
C
C
C     * CALCULATE GW TENDENCIES.
C
C           * TOP LAYER AND BOTTOM LAYER *
      DO 260 I=1,LENGW
               DEPFAC(I,LREF)=DEPFAC(I,LREFM)
               WIND=   VELN(I,1)
               DFLXP=DEPFAC(I,2)-DEPFAC(I,1)
               IF (DFLXP.GT.1.E-10) THEN
                  ETA = UN
               ELSE
                  ETA = ZERO
               ENDIF
               DFAC=3.*TAU*DEPFAC(I,1)/WIND
               DENOM=2.*SHg(i,1)+DFAC*eta
               TENDFAC=2.*eta*DEPFAC(I,1)/DENOM
               DENFAC(I)=DFAC*TENDFAC
               UTEND(I,1)=-TENDFAC*UBG(I)
               VTEND(I,1)=-TENDFAC*VBG(I)
               UTEND(I,LREF)=ZERO
               VTEND(I,LREF)=ZERO
  260 CONTINUE
       DO 270 L=2,LREFM
          DO 270 I=1,LENGW
               WIND=   VELN(I,L)
               DFLXP=DEPFAC(I,L+1)-DEPFAC(I,L)
               DFLXM=DEPFAC(I,L)-DEPFAC(I,L-1)
               IF (DFLXM.GT.1.E-10) THEN
                  ETA = UN
               ELSE
                  ETA = ZERO
               ENDIF
               DFAC=3.*TAU*DEPFAC(I,L)/WIND
               DENOM=2.*(SHg(i,L)-SHg(i,L-1))+DFAC*eta
               TENDFAC=(2.*DFLXM+DENFAC(I)*eta)/DENOM
               DENFAC(I)=DFAC*TENDFAC
              UTEND(I,L) = -TENDFAC*UBG(I)
              VTEND(I,L) = -TENDFAC*VBG(I)
  270 CONTINUE
C           *  ROOF DRAG FACTOR  *
            DO 275 I=1,LENGW
                TENDFAC=SQRT(UTEND(I,1)**2 + VTEND(I,1)**2)
                DGWG(I,1)=DAMPSCA*TENDFAC*VELN(I,1)
  275       CONTINUE
C
C     * SCATTER THESE VALUES OF DGWG AND (U-V)TEND
C     * INTO DGW AND (U-V)TENDGW.
C
      DO 280 L=1,ILEV
*         CALL SCATTER (LEN, UTENDGW(IL1,L), DRAG, UTEND(1,L))
*         CALL SCATTER (LEN, VTENDGW(IL1,L), DRAG, VTEND(1,L))
*         CALL SCATTER (LEN, DGW(IL1,L),     DRAG, DGWG(1,L))
*
          do 285 i=1,len
             ii = drag(i) + il1 - 1
             utendgw(ii,l) = utend(i,l)
             vtendgw(ii,l) = vtend(i,l)
             dgw    (ii,l) = dgwg (i,l) 
  285     continue
*
  280 CONTINUE
c
  300 CONTINUE
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C     * LOW-LEVEL BLOCKING PARAMETERIZATION (ISOTROPIC CASE)
C
C     Initialize arrays
      do 400 l=1,ilev
	do 400 i=il1,il2
          rho(i,l)      = zero
          zb(i,l)       = zero
          utendllb(i,l) = zero
          vtendllb(i,l) = zero
  400 continue
      do 405 i=il1,il2
        izt(i)  = ilev-1
        izt2(i) = ilev
        izt3(i) = ilev
        hcrt(i) = zero
        hblk(i) = zero
        izb(i)  = ilev
        uav(i)      = v0
        vav(i)      = v0
        velav(i)    = v0
        bvfreqav(i) = zero
        rhoav(i)    = zero
        delz(i)     = zero
        slpf(i) = taufac
        fdir(i) = un
        bloff(i) = 0
c
*       sxx(i)  = ( taufac * (1.+.01*env(i)) * env(i) )**2
*       syy(i)  = ( taufac * (1.+.01*env(i)) * env(i) )**2
*       sxy(i)  = zero
  405 continue
c
      if (blocking) then
ccccccccccccccccccccccccccccccccc
c     Reconstruct buoyancy frequency (not smoothed):
      do 410 l=2,ilev
        do 410 i=il1,il2
              dttdsf      =(th(i,l)/shexpk(i,l)-th(i,l-1)/shexpk(i,l-1))
     +                     /(sh(i,l)-sh(i,l-1))
              dttdsf      = min ( dttdsf, -5./s(i,l))
              dttdzl      = -dttdsf*s(i,l)*grav/(rgas*tf(i,l))
              bvfreq(i,l) = sqrt (grav*dttdzl*sexpk(i,l)/tf(i,l))
  410 continue 
      do 415 i=il1,il2
          bvfreq(i,1)     = bvfreq(i,2)
  415 continue
c
c     Build densities and elevations:
      do 420 i=il1,il2
        if (gc(i).eq.-1.) then 
          rho(i,ilev) = (psurf(i)*s(i,ilev))/(rgas*tf(i,ilev))
          zb(i,ilev)  = -(rgas/grav)*tf(i,ilev)*log(sh(i,ilev))
        endif
  420 continue
      do 425 l=ilev-1,1,-1
        do 425 i=il1,il2
          if (gc(i).eq.-1.) then
            rho(i,l) = (psurf(i)*s(i,l))/(rgas*tf(i,l))
            zb(i,l)  = zb(i,l+1) + 
     +                 (rgas/grav)*tf(i,l)*log(sh(i,l+1)/sh(i,l))
          endif
  425 continue
cccccccccccccccccccccccccccccccc
      blkhgt = 2
cccccccccccccccccccccccccccccccc
      if (blkhgt.eq.1) then
c
c     Find upper level for averaging:
      do 440 l=ilev-2,1,-1
        do 440 i=il1,il2
          if (gc(i).eq.-1.) then
            if (zb(i,l).lt.env(i))    izt(i) = l
          endif
  440 continue        
c
c     Compute averages:
      do 470 l=ilev,2,-1
        do 470 i=il1,il2
          if (gc(i).eq.-1. .and. l.ge.izt(i)) then
            dz          = zb(i,l-1) - zb(i,l)
            delz(i)     = delz(i) + dz
            uav(i)      = uav(i) + dz*u(i,l)
            vav(i)      = vav(i) + dz*v(i,l)
            bvfreqav(i) = bvfreqav(i) + dz*bvfreq(i,l)
            rhoav(i)    = rhoav(i) + dz*rho(i,l)
          endif
  470 continue
      do 490 i=il1,il2
        if (gc(i).eq.-1.) then
          uav(i)      = uav(i)/delz(i)
          vav(i)      = vav(i)/delz(i)
          if ( abs(vav(i)) .lt. v0 .and. abs(uav(i)) .lt. v0) then           
            velav(i)  = v0
          else
            velav(i)  = sqrt( uav(i)**2 + vav(i)**2 )
          endif
          bvfreqav(i) = bvfreqav(i)/delz(i)
          rhoav(i)    = rhoav(i)/delz(i)
        endif
  490 continue
c    
c     Compute blocking height and upper blocking level:
      do 500 i=il1,il2
        if (gc(i).eq.-1.) then      
          hcrt(i) = sqrt(0.5) * velav(i) / bvfreqav(i)
          hblk(i) = env(i) - hcrt(i)
          if (hblk(i) .lt. zero)       hblk(i) = zero
        endif
  500 continue
      do 510 l=ilev-1,2,-1
        do 510 i=il1,il2
          if (gc(i).eq.-1. .and. zb(i,l).lt.hblk(i))   then
            izb(i) = l-1
          endif
  510 continue
c
      endif
ccccccccccccccccccccccccccccccccccccccc
      if (blkhgt.eq.2) then
c
c     Find upper level for averaging:
      do 511 l=ilev-2,1,-1
        do 511 i=il1,il2
          if (gc(i).eq.-1.) then
            if (zb(i,l).lt.env(i))    izt(i) = l
          endif
  511 continue        
c
c     Find lower level for averaging:
      do 512 l=ilev-1,1,-1
        do 512 i=il1,il2
          if (gc(i).eq.-1.) then
            if (zb(i,l).lt.(0.5*env(i)))    izt2(i) = l
          endif
  512 continue    
c
c     Compute averages:
      do 513 l=ilev,2,-1
        do 513 i=il1,il2
          if (gc(i).eq.-1. .and. l.le.izt2(i) .and. 
     +        l.ge.izt(i))   then
            dz          = zb(i,l-1) - zb(i,l)
            delz(i)     = delz(i) + dz
            uav(i)      = uav(i) + dz*u(i,l)
            vav(i)      = vav(i) + dz*v(i,l)
            bvfreqav(i) = bvfreqav(i) + dz*bvfreq(i,l)
            rhoav(i)    = rhoav(i) + dz*rho(i,l)
          endif
  513 continue
      do 514 i=il1,il2
        if (gc(i).eq.-1.) then
          uav(i)      = uav(i)/delz(i)
          vav(i)      = vav(i)/delz(i)
          if ( abs(vav(i)) .lt. v0 .and. abs(uav(i)) .lt. v0) then           
            velav(i)    = v0
          else
            velav(i)    = sqrt( uav(i)**2 + vav(i)**2 )
          endif
          bvfreqav(i) = bvfreqav(i)/delz(i)
          rhoav(i)    = rhoav(i)/delz(i)
        endif
  514 continue
c    
c     Compute blocking height and upper blocking level:
      do 515 l=ilev-2,1,-1
        do 515 i=il1,il2
          if (gc(i).eq.-1.) then
            if (zb(i,l).lt.(1.5*env(i)))    izt3(i) = l
          endif
  515 continue        
c
        do 516 l=2,ilev
          do 516 i=il1,il2
            if (gc(i).eq.-1. .and. l.ge.izt3(i) .and. 
     +          bloff(i).eq.0)                         then
              dz    = zb(i,l-1) - zb(i,l)
              uparl = (u(i,l)*uav(i) + v(i,l)*vav(i))/velav(i)
              if (uparl .lt. v0) then
                izb(i)   = l-1
                bloff(i) = 1
              else
                hblk(i) = hblk(i) + dz*bvfreq(i,l)/uparl
                if (hblk(i) .gt. 0.5) then
                  izb(i)   = l-1
                  bloff(i) = 1
                endif
              endif
            endif
  516   continue
c
      endif
ccccccccccccccccccccccccccccccccccccccc
c     Compute directional factor:
c
      piotwo = .5*acos(-1.)
      do 520 i=il1,il2
        if (gc(i).eq.-1.)      then
c
c       Slope factor, eccentricity and orientation of topography:
          spls = .5*( sxx(i) + syy(i) )
          smns = .5*( sxx(i) - syy(i) )
          scrs = sxy(i)
          sppr = spls + sqrt(smns**2 + scrs**2)
          smpr = abs(spls - sqrt(smns**2 + scrs**2))
c
            if (env(i) .lt. nhmin) then
              slpf(i) = (sqrt(sppr))/nhmin
            else
              slpf(i) = (sqrt(sppr))/env(i)
            endif
c
          if (sppr .lt. 1.e-10) then 
            gamma = un
          else
            gamma = sqrt(smpr/sppr)
          endif
c
          if ( abs(scrs) .lt. 1.e-10 .and. abs(smns) .lt. 1.e-10) then
            theta = zero
          else  
            theta = .5*atan2(scrs,smns)
          endif
c
c         Angle between wind and topography:
          if ( abs(vav(i)) .lt. v0 .and. abs(uav(i)) .lt. v0) then 
            psi = zero
          else
            psi = theta - atan2(vav(i),uav(i))
            if (psi .gt.   piotwo )  psi = psi - 2.*piotwo 
            if (psi .lt. (-piotwo))  psi = psi + 2.*piotwo
          endif
          cpsi = ( cos(psi) )**2
          spsi = ( sin(psi) )**2
c
c         Directional factor:
          amp = cpsi + gamma*spsi 
          if (amp .lt. 1.e-10) then 
            amp = zero
          else 
            amp = 2. - ( gamma*cpsi + spsi )/( cpsi + gamma*spsi )
            if (amp.lt.zero)     amp = zero
          endif
          fdir(i) = amp*(  (1. - .18*gamma - .04*(gamma**2))*cpsi           
     +                   + (     .48*gamma + .30*(gamma**2))*spsi )
c
        endif  
  520 continue  
cccccccccccccccccccccccccccccccccccccccccccccc     
c     Compute tendencies:
c
      if (blkhgt.eq.1) then
c
      do 530 l=ilev,1,-1
        do 530 i=il1,il2
          if (gc(i).eq.-1. .and. velav(i).ge.vmin      .and.
     +        l.gt.izb(i)  .and. zb(i,izb(i)).ge.nhmin      ) then

c           Vertical factor:
            fvert = sqrt( (zb(i,izb(i)) - zb(i,l))
     +                   /(0.5*env(i)   + zb(i,l)) )
c
c           Drag intensity:
            amp = 0.5*cdblk*slpf(i)*fdir(i)*fvert*
     +            (velav(i)**2)*rhoav(i)/rho(i,l)
            ampmax = sqrt( u(i,l)**2 + v(i,l)**2 )/tau
            if (amp.gt.ampmax)   amp = ampmax
c
c           Tendecies:
            utendllb(i,l) = -amp*uav(i)/velav(i)
            vtendllb(i,l) = -amp*vav(i)/velav(i)
          endif
  530 continue                
c
      endif
c
      if (blkhgt.eq.2) then
c
      do 540 l=ilev,1,-1
        do 540 i=il1,il2
          if (gc(i).eq.-1. .and. velav(i).ge.vmin      .and.
     +        l.gt.izb(i)  .and. zb(i,izb(i)).ge.nhmin      ) then

c           Vertical factor:
            fvert = sqrt( (zb(i,izb(i)) - zb(i,l))
     +                   /(0.5*env(i)   + zb(i,l)) )
c
c           Drag intensity:
            amp = 0.5*cdblk*slpf(i)*fdir(i)*fvert*
     +            (u(i,l)**2 + v(i,l)**2)
            ampmax = sqrt( u(i,l)**2 + v(i,l)**2 )/tau
            if (amp.gt.ampmax)   then 
              utendllb(i,l) = -u(i,l)/tau
              vtendllb(i,l) = -v(i,l)/tau
            else
              utendllb(i,l) = -0.5*cdblk*slpf(i)*fdir(i)*fvert*
     +                       u(i,l)*sqrt(u(i,l)**2 + v(i,l)**2)                            
              vtendllb(i,l) = -0.5*cdblk*slpf(i)*fdir(i)*fvert*
     +                       v(i,l)*sqrt(u(i,l)**2 + v(i,l)**2)
            endif
          endif
  540 continue                
c
      endif
c
      endif
c
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
c
C
C     * APPLY GW DRAG ON U AND V.
C
      DO 290 L=1,ILEV
          DO 290 I=IL1,IL2
              UTENDGW(I,L) = UTENDGW(I,L) + UTENDLLB(I,L)
              VTENDGW(I,L) = VTENDGW(I,L) + VTENDLLB(I,L)
              U(I,L) = U(I,L) + TAU*UTENDGW(I,L)
              V(I,L) = V(I,L) + TAU*VTENDGW(I,L)
  290 CONTINUE
C
C     * APPLY ROOF DRAG IF THE BACKGROUND GW DRAG IS SMALL ENOUGH.
C
c  300 CONTINUE
C
      IF (DAMPFAC)                                                THEN
          DAMPRF = UN
      ELSE
          DAMPRF = ZERO
      ENDIF
C
      DO 310 I=IL1,IL2
          VELMOD       = MAX (SQRT (U(I,1)**2 + V(I,1)**2), UN)
          DFAC         = MAX (UN-DGW(I,1)/(VELMOD*VELMOD), ZERO)
     1                 * DAMPRF / DAMPSCA
          DENOM        = UN + TAU*DFAC
          U(I,1)       = U(I,1)/DENOM
          V(I,1)       = V(I,1)/DENOM
          UTENDGW(I,1) = UTENDGW(I,1) - DFAC*U(I,1)
          VTENDGW(I,1) = VTENDGW(I,1) - DFAC*V(I,1)
  310 CONTINUE
C
      RETURN
C
C-----------------------------------------------------------------------
      END