!wrf:model_layer:physics
!
!
!

module module_bl_ysu 2
contains
!
!-------------------------------------------------------------------
!

   subroutine ysu(u3d,v3d,th3d,t3d,qv3d,qc3d,qi3d,p3d,pi3d,        & 1,1
                  rublten,rvblten,rthblten,                        &
                  rqvblten,rqcblten,rqiblten,          		   &
                  cp,g,rovcp,rd,rovg,p_qi,p_first_scalar,          &
                  dz8w,z,xlv,rv,psfc,                              &
                  znt,ust,zol,hol,hpbl,regime,psim,psih,           &
                  xland,hfx,qfx,tsk,gz1oz0,wspd,br,                &
                  dt,dtmin,kpbl2d,                                 &
                  svp1,svp2,svp3,svpt0,ep1,ep2,karman,eomeg,stbolt,&
                  ids,ide, jds,jde, kds,kde,                       &
                  ims,ime, jms,jme, kms,kme,                       &
                  its,ite, jts,jte, kts,kte                        )
!-------------------------------------------------------------------
      implicit none
!-------------------------------------------------------------------
!-- u3d         3d u-velocity interpolated to theta points (m/s)
!-- v3d         3d v-velocity interpolated to theta points (m/s)
!-- th3d	3d potential temperature (k)
!-- t3d         temperature (k)
!-- qv3d        3d water vapor mixing ratio (kg/kg)
!-- qc3d        3d cloud mixing ratio (kg/kg)
!-- qi3d        3d ice mixing ratio (kg/kg)
!-- p3d         3d pressure (pa)
!-- pi3d	3d exner function (dimensionless)
!-- rr3d	3d dry air density (kg/m^3)
!-- rublten     rho_du tendency due to
!               pbl parameterization (kg/m^3 . m/s)
!-- rvblten     rho_dv tendency due to
!               pbl parameterization (kg/m^3 . m/s)
!-- rthblten    rho_dtheta_m tendency due to
!               pbl parameterization (kg/m^3 . k)
!-- rqvblten    rho_dqv tendency due to
!               pbl parameterization (kg/m^3 . kg/kg)
!-- rqcblten    rho_dqc tendency due to
!               pbl parameterization (kg/m^3 . kg/kg)
!-- rqiblten    rho_dqi tendency due to
!               pbl parameterization (kg/m^3 . kg/kg)
!-- cp          heat capacity at constant pressure for dry air (j/kg/k)
!-- g           acceleration due to gravity (m/s^2)
!-- rovcp       r/cp
!-- rd          gas constant for dry air (j/kg/k)
!-- rovg 	r/g
!-- p_qi	species index for cloud ice
!-- dz8w	dz between full levels (m)
!-- z		height above sea level (m)
!-- xlv         latent heat of vaporization (j/kg)
!-- rv 		gas constant for water vapor (j/kg/k)
!-- psfc        pressure at the surface (pa)
!-- znt		roughness length (m)
!-- ust		u* in similarity theory (m/s)
!-- zol		z/l height over monin-obukhov length
!-- hol		pbl height over monin-obukhov length
!-- hpbl	pbl height (m)
!-- regime	flag indicating pbl regime (stable, unstable, etc.)
!-- psim        similarity stability function for momentum
!-- psih        similarity stability function for heat
!-- xland	land mask (1 for land, 2 for water)
!-- hfx		upward heat flux at the surface (w/m^2)
!-- qfx		upward moisture flux at the surface (kg/m^2/s)
!-- tsk		surface temperature (k)
!-- gz1oz0      log(z/z0) where z0 is roughness length
!-- wspd        wind speed at lowest model level (m/s)
!-- br          bulk richardson number in surface layer
!-- dt		time step (s)
!-- dtmin	time step (minute)
!-- rvovrd      r_v divided by r_d (dimensionless)
!-- svp1        constant for saturation vapor pressure (kpa)
!-- svp2        constant for saturation vapor pressure (dimensionless)
!-- svp3        constant for saturation vapor pressure (k)
!-- svpt0       constant for saturation vapor pressure (k)
!-- ep1         constant for virtual temperature (r_v/r_d - 1) (dimensionless)
!-- ep2         constant for specific humidity calculation
!-- karman      von karman constant
!-- eomeg       angular velocity of earths rotation (rad/s)
!-- stbolt      stefan-boltzmann constant (w/m^2/k^4)
!-- ids         start index for i in domain
!-- ide         end index for i in domain
!-- jds         start index for j in domain
!-- jde         end index for j in domain
!-- kds         start index for k in domain
!-- kde         end index for k in domain
!-- ims         start index for i in memory
!-- ime         end index for i in memory
!-- jms         start index for j in memory
!-- jme         end index for j in memory
!-- kms         start index for k in memory
!-- kme         end index for k in memory
!-- its         start index for i in tile
!-- ite         end index for i in tile
!-- jts         start index for j in tile
!-- jte         end index for j in tile
!-- kts         start index for k in tile
!-- kte         end index for k in tile
!-------------------------------------------------------------------

      integer,  intent(in   )   ::      ids,ide, jds,jde, kds,kde, &
                                        ims,ime, jms,jme, kms,kme, &
                                        its,ite, jts,jte, kts,kte, &
                                        p_qi,p_first_scalar
!
      real,     intent(in   )   ::      dt,dtmin,cp,g,rovcp,       &
				        rovg,rd,xlv,rv
!
      real,     intent(in )     ::     svp1,svp2,svp3,svpt0
      real,     intent(in )     ::     ep1,ep2,karman,eomeg,stbolt
!
      real,     dimension( ims:ime, kms:kme, jms:jme )           , &
                intent(in   )   ::                           qv3d, &
							     qc3d, &
 		 				             qi3d, &
							      p3d, &
							     pi3d, &
							     th3d, &
							      t3d, &
							     dz8w, &
							        z
!
      real,     dimension( ims:ime, kms:kme, jms:jme )           , &
                intent(inout)   ::                        rublten, &
							  rvblten, &
							 rthblten, &
							 rqvblten, &
							 rqcblten, &
							 rqiblten
!
      real,     dimension( ims:ime, jms:jme )                    , &
                intent(in   )   ::                          xland, &
     					                     psim, &
           					             psih, &
							   gz1oz0, &
							       br, &
           			                              hfx, &
           					              qfx
!
      real,     dimension( ims:ime, jms:jme )                    , &
                intent(inout)   ::                            hol, &
							      ust, &
						             wspd, &
							     hpbl, &
                                                              znt, &
						           regime
!
     real,     dimension( ims:ime, kms:kme, jms:jme )           , &
                intent(in   )   ::                            u3d, &
                                                              v3d
!
     real,     dimension( ims:ime, jms:jme ), intent(inout)   ::   &
                                                              zol
     integer,  dimension( ims:ime, jms:jme )                    , &
                intent(out  )   ::                        kpbl2d

!
     real,     dimension( ims:ime, jms:jme ), intent(in   )  ::    &
                                                             psfc, &
                                                              tsk
!
   integer ::  i,j,k
!
   do j = jts,jte
      call ysu2d(j,u3d(ims,kms,j),v3d(ims,kms,j),t3d(ims,kms,j),    &
               qv3d(ims,kms,j),qc3d(ims,kms,j),qi3d(ims,kms,j),     &
               p3d(ims,kms,j),rublten(ims,kms,j),rvblten(ims,kms,j),&
               rthblten(ims,kms,j),rqvblten(ims,kms,j),             &
               rqcblten(ims,kms,j),rqiblten(ims,kms,j),             &
               cp,g,rovcp,rd,rovg,p_first_scalar,p_qi,              &
               dz8w(ims,kms,j),z(ims,kms,j),xlv,rv,                 &
               psfc(ims,j),znt(ims,j),ust(ims,j),zol(ims,j),        &
               hol(ims,j),hpbl(ims,j),regime(ims,j),psim(ims,j),    &
               psih(ims,j),xland(ims,j),hfx(ims,j),qfx(ims,j),      &
               tsk(ims,j),gz1oz0(ims,j),wspd(ims,j),br(ims,j),      &
               dt,dtmin,kpbl2d(ims,j),                              &
               svp1,svp2,svp3,svpt0,ep1,ep2,karman,eomeg,stbolt,    &
               ids,ide, jds,jde, kds,kde,                           &
               ims,ime, jms,jme, kms,kme,                           &
               its,ite, jts,jte, kts,kte                            )
      do k = kts,kte
      do i = its,ite
         rthblten(i,k,j) = rthblten(i,k,j)/pi3d(i,k,j)
      enddo
      enddo
    enddo
!
   end subroutine ysu
!
!-------------------------------------------------------------------
!

   subroutine ysu2d(j,ux,vx,tx,qx,qcx,qix,p2d,                     & 1,2
                  utnp,vtnp,ttnp,                                  &
                  qtnp,qctnp,qitnp,             		   &
                  cp,g,rovcp,rd,rovg,p_qi,p_first_scalar,          &
                  dz8w2d,z2d,xlv,rv,psfcpa,                        &
                  znt,ust,zol,hol,hpbl,regime,psim,psih,           &
                  xland,hfx,qfx,tsk,gz1oz0,wspd,br,                &
                  dt,dtmin,kpbl1d,                                 &
                  svp1,svp2,svp3,svpt0,ep1,ep2,karman,eomeg,stbolt,&
                  ids,ide, jds,jde, kds,kde,                       &
                  ims,ime, jms,jme, kms,kme,                       &
                  its,ite, jts,jte, kts,kte                        )
!-------------------------------------------------------------------
      implicit none
!-------------------------------------------------------------------
!     based on the "countergradient" transport term of troen
!     and mahrt (1986) for the unstable pbl.
!     this routine uses an implicit approach for vertical flux
!     divergence and does not require "miter" timesteps.
!     it includes vertical diffusion in the stable atmosphere
!     and moist vertical diffusion in clouds.
!     surface fluxes calculated as in hirpbl.
!     5-layer soil model option required in slab due to long timestep
!
!     coded by song-you hong (ncep), implemented by jimy dudhia (ncar)
!     fall 1996
!
!     references:
!
!        hong and pan (1996), mon. wea. rev.
!        troen and mahrt (1986), boundary layer met.
!
!     changes:
!        increase rlam from 30 to 150, and change free atmosphere
!        stability function to increase vertical diffusion
!        (hong, june 1997)
!
!        put lower limit on psi for stable conditions. this will
!        prevent fluxes from becoming too small (dudhia, october 1997)
!
!        correction to regime calculation. this will allow points in
!        regime 4 much more frequently giving larger surface fluxes
!        regime 3 no longer uses hol < 1.5 or thvx lapse-rate check
!        in ysu scheme. this will make regime 3 much less frequent.
!
!        add surface pressure, ps(i), array for efficiency
!
!        fix for problem with thin layers and high roughness
!
!        charnock constant now comes from namelist (default same)
!
!-------------------------------------------------------------------

      real      rlam,prmin,prmax,xkzmin,xkzmax,rimin,brcr,            &
                bfac,pfac,sfcfrac,ckz,zfmin,aphi5,aphi16,gamcrt,      &
                gamcrq,xka

      parameter (xkzmin = 0.01,xkzmax = 1000.,rimin = -100.)
      integer ncloud
      parameter (ncloud = 3)

      real afac, phifac, qmin
      real d1,d2,d3
      real h1,h2
      parameter (rlam = 150.,prmin = 0.25,prmax = 4.)
      parameter (brcr = 0.0,bfac = 6.8,pfac = 2.0,sfcfrac = 0.1)
      parameter (afac = 6.8,phifac = 8.,qmin=1.e-2)
      parameter (d1 = 0.02, d2 = 0.05, d3 = 0.001)
      parameter (h1 = 0.33333335, h2 = 0.6666667)

      parameter (ckz = 0.001,zfmin = 1.e-8,aphi5 = 5.,aphi16 = 16.)
      parameter (gamcrt = 3.,gamcrq = 2.e-3)
      parameter (xka = 2.4e-5)
!
      integer,  intent(in   )   ::      ids,ide, jds,jde, kds,kde, &
                                        ims,ime, jms,jme, kms,kme, &
                                        its,ite, jts,jte, kts,kte, &
                                        p_qi,p_first_scalar,j
!
      real,     intent(in   )   ::      dt,dtmin,cp,g,rovcp,       &
				        rovg,rd,xlv,rv

      real,     intent(in )     ::     svp1,svp2,svp3,svpt0
      real,     intent(in )     ::     ep1,ep2,karman,eomeg,stbolt

!
      real,     dimension( ims:ime, kms:kme ),                     &
                intent(in)      ::                         dz8w2d, &
                                                              z2d
!
      real,     dimension( ims:ime, kms:kme )                    , &
                intent(in   )   ::                             tx, &
                                                               qx, &
						  	      qcx, &
 		 				              qix, &
							      p2d
!
      real,     dimension( ims:ime, kms:kme )                    , &
                intent(inout)   ::                           utnp, &
							     vtnp, &
							     ttnp, &
							     qtnp, &
							    qctnp, &
							    qitnp
!
      real,     dimension( ims:ime )                             , &
                intent(inout)   ::                            hol, &
							      ust, &
							     hpbl, &
                                                              znt, &
						           regime
      real,     dimension( ims:ime )                             , &
                intent(in   )   ::                          xland, &
           			                              hfx, &
           					              qfx
!
      real,     dimension( ims:ime ), intent(inout)   ::      wspd
      real,     dimension( ims:ime ), intent(in  )    ::        br
!

      real,     dimension( ims:ime ), intent(in   )   ::      psim, &
           					              psih
      real,     dimension( ims:ime ), intent(in   )   ::    gz1oz0

!
      real,     dimension( ims:ime ), intent(in   )   ::    psfcpa
      real,     dimension( ims:ime ), intent(in   )   ::       tsk
      real,     dimension( ims:ime ), intent(inout)   ::       zol
      integer,  dimension( ims:ime ), intent(out  )   ::    kpbl1d
           			
!
      real,     dimension( ims:ime, kms:kme )                    , &
                intent(in   )   ::                             ux, &
                                                               vx
!
! local vars
!



      real,     dimension( its:ite, kts:kte+1 ) ::             zq

      real,     dimension( its:ite, kts:kte )   ::     		   &
                  				         thx,thvx, &
                  				          dzq,dza, &
						               za, &
						          uxs,vxs, &
							 thxs,qxs, &
                   				        qcxs,qixs
!
      real,    dimension( its:ite )             ::     qixsv,rhox, &
       				                           govrth, &
   						            thxsv, &
							uxsv,vxsv, &
                  			               qxsv,qcxsv, &
                  			             qgh,tgdsa,ps
!
      real,    dimension( its:ite )             ::                 &
                                                      zl1,thermal, &
						     wscale,hgamt, &
                                                       hgamq,brdn, &
                 				        brup,phim, &
						         phih,cpm, &
					              dusfc,dvsfc, &
						      dtsfc,dqsfc, &
                                                       thgb,prpbl, &
                                                            wspd1
!
      real,    dimension( its:ite, kts:kte )    ::      xkzm,xkzh, &
							    a1,a2, &
                                                            ad,au, &
                                                               al, &
                                                             zfac, &
                                                             scr4
      real,    dimension( its:ite, kts:kte, ncloud)  ::        a3
!
      logical, dimension( its:ite )             ::         pblflg, &
					                   sfcflg, &
							   stable
!
      integer ::  n,i,k,l,nzol,imvdif,ic
      integer ::  klpbl
!
      integer, dimension( its:ite )             ::           kpbl
!
      real    ::  zoln,x,y,thcon,tvcon,e1,dtstep
      real    ::  zl,tskv,dthvdz,dthvm,vconv,rzol
      real    ::  dtthx,psix,dtg,psiq,ustm
      real    ::  dt4,rdt,spdk2,fm,fh,hol1,gamfac,vpert,prnum
      real    ::  xkzo,ss,ri,qmean,tmean,alph,chi,zk,rl2,dk,sri
      real    ::  brint,dtodsd,dsig,rdz,dsdzt,dsdzq,dsdz2,ttend,qtend
      real    ::  utend,vtend,qctend,qitend,tgc,dtodsu


      real, dimension( its:ite, kts:kte )     ::         wscalek, &
                                                     xkzml,xkzhl, &
                                                  zfacent,entfac
      real, dimension( its:ite )              ::            ust3, &
                                                    wstar3,wstar, &
                                                     hgamu,hgamv, &
                                                         wm2, &
                                                          bfxpbl, &
                                                   hfxpbl,qfxpbl, &
                                                   ufxpbl,vfxpbl, &
                                                     delta,dthvx 
      real    ::  prnumfac,bfx0,hfx0,qfx0,delb,dux,dvx,           &
                  dsdzu,dsdzv,wm3,dthx,dqx


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



      klpbl = kte

!
!-- imvdif      imvdif = 1 for moist adiabat vertical diffusion

      imvdif = 1
!
!----convert ground temperature to potential temperature:
!
      do i = its,ite
        tgdsa(i) = tsk(i)
        ps(i) = psfcpa(i)/1000.          ! ps psfc cmb
        thgb(i) = tsk(i)*(100./ps(i))**rovcp
      enddo
!
!     scr4(i,k) store virtual temperature.
!
      do k = kts,kte
        do i = its,ite
          thcon = (100000./p2d(i,k))**rovcp
          thx(i,k) = tx(i,k)*thcon
          scr4(i,k) = tx(i,k)
          thvx(i,k) = thx(i,k)
        enddo
      enddo
!
      do i = its,ite
        qgh(i) = 0.
        cpm(i) = cp
      enddo
!
!     if(idry.eq.1)goto 80
      do k = kts,kte
        do i = its,ite
          tvcon = (1.+ep1*qx(i,k))
          thvx(i,k) = thx(i,k)*tvcon

          scr4(i,k) = tx(i,k)*tvcon
        enddo
      enddo
!
      do i = its,ite
        e1 = svp1*exp(svp2*(tgdsa(i)-svpt0)/(tgdsa(i)-svp3))
        qgh(i) = ep2*e1/(ps(i)-e1)
        cpm(i) = cp*(1.+0.8*qx(i,1))
      enddo
!
!-----compute the height of full- and half-sigma levels above ground
!     level, and the layer thicknesses.
!
      do i = its,ite
        zq(i,1) = 0.
        rhox(i) = ps(i)*1000./(rd*scr4(i,1))
      enddo
!
      do k = kts,kte
        do i = its,ite
          zq(i,k+1) = dz8w2d(i,k)+zq(i,k)
        enddo
      enddo
!
      do k = kts,kte
        do i = its,ite
          za(i,k) = 0.5*(zq(i,k)+zq(i,k+1))
          dzq(i,k) = zq(i,k+1)-zq(i,k)
        enddo
      enddo
!
      do i = its,ite
        dza(i,1) = za(i,1)
      enddo
      do k = kts+1,kte
        do i = its,ite
          dza(i,k) = za(i,k)-za(i,k-1)
        enddo
      enddo
!
      do i = its,ite
        govrth(i) = g/thx(i,1)
      enddo
!
!-----initialize vertical tendencies and
!
      do i = its,ite
        do k = kts,kte
          utnp(i,k) = 0.
          vtnp(i,k) = 0.
          ttnp(i,k) = 0.
        enddo
      enddo
!
!     if(idry.eq.1)goto 250
      do k = kts,kte
        do i = its,ite
          qtnp(i,k) = 0.
        enddo
      enddo
!
!     if(imoist.eq.1)goto 250
      do k = kts,kte
        do i = its,ite
          qctnp(i,k) = 0.
          qitnp(i,k) = 0.
        enddo
      enddo
  250 continue
!

!
!-----compute the frictional velocity:
!     za(1982) eqs(2.60),(2.61).
      do i = its,ite
        dtg = thx(i,1)-thgb(i)
        psix = gz1oz0(i)-psim(i)
        if((xland(i)-1.5).ge.0)then
          zl = znt(i)
        else
          zl = 0.01
        endif
        psiq = alog(karman*ust(i)*za(i,1)/xka+za(i,1)/zl)-psih(i)
        ust(i) = karman*wspd(i)/psix
!
        ustm = amax1(ust(i),0.1)
        if((xland(i)-1.5).ge.0)then
          ust(i) = ust(i)
        else
          ust(i) = ustm
        endif
!       mol(i,j) = karman*dtg/(gz1oz0(i)-psih(i))

      enddo
!
      do i = its,ite

        wspd1(i) = sqrt(ux(i,1)*ux(i,1)+vx(i,1)*vx(i,1))+1.e-9

      enddo
!
!---- compute vertical diffusion
!
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!     compute preliminary variables
!
      dtstep = dt
      dt4 = 2.*dtstep
      rdt = 1./dt4
!


      do i = its,ite
        bfxpbl(i) = 0.0
        hfxpbl(i) = 0.0
        qfxpbl(i) = 0.0
        ufxpbl(i) = 0.0
        vfxpbl(i) = 0.0
        hgamu(i)  = 0.0
        hgamv(i)  = 0.0
        delta(i)  = 0.0
      enddo
      do k = kts,klpbl
        do i = its,ite
          wscalek(i,k) = 0.0
        enddo
      enddo

!
      do k = kts,klpbl
        do i = its,ite
          zfac(i,k) = 0.0
        enddo
      enddo
      do i = its,ite
        hgamt(i)  = 0.
        hgamq(i)  = 0.
        wscale(i) = 0.
        kpbl(i)   = 1
        hpbl(i)   = zq(i,1)
        zl1(i)    = za(i,1)
        thermal(i)= thvx(i,1)
        pblflg(i) = .true.
        sfcflg(i) = .true.
        if(br(i).gt.0.0) sfcflg(i) = .false.
      enddo
!
!     compute the first guess of pbl height
!
      do i = its,ite
        stable(i) = .false.
        brup(i) = br(i)
      enddo
      do k = 2,klpbl
        do i = its,ite
          if(.not.stable(i))then
            brdn(i) = brup(i)
            spdk2   = max(ux(i,k)**2+vx(i,k)**2,1.)
            brup(i) = (thvx(i,k)-thermal(i))*(g*za(i,k)/thvx(i,1))/spdk2
            kpbl(i) = k
            stable(i) = brup(i).gt.brcr

          endif
        enddo
      enddo
!
      do i = its,ite
        k = kpbl(i)
        if(brdn(i).ge.brcr)then
          brint = 0.
        elseif(brup(i).le.brcr)then
          brint = 1.
        else
          brint = (brcr-brdn(i))/(brup(i)-brdn(i))
        endif
        hpbl(i) = za(i,k-1)+brint*(za(i,k)-za(i,k-1))
        if(hpbl(i).lt.zq(i,2)) kpbl(i) = 1
        if(kpbl(i).le.1) pblflg(i) = .false.
!       if(hpbl(i).lt.zq(i,kpbl(i))) kpbl(i) = kpbl(i)-1
      enddo
!
      do i = its,ite
        fm = gz1oz0(i)-psim(i)
        fh = gz1oz0(i)-psih(i)
        hol(i) = max(br(i)*fm*fm/fh,rimin)
        if(sfcflg(i))then
          hol(i) = min(hol(i),-zfmin)
        else
          hol(i) = max(hol(i),zfmin)
        endif
!
        hol1 = hol(i)*hpbl(i)/zl1(i)*sfcfrac
        hol(i) = -hol(i)*hpbl(i)/zl1(i)
        if(sfcflg(i))then
          phim(i) = (1.-aphi16*hol1)**(-1./4.)
          phih(i) = (1.-aphi16*hol1)**(-1./2.)

          bfx0 = max(hfx(i)/rhox(i)/cpm(i)             &
                   +ep1*thx(i,1)*qfx(i)/rhox(i),0.)
          hfx0 = max(hfx(i)/rhox(i)/cpm(i),0.)
          qfx0 = max(ep1*thx(i,1)*qfx(i)/rhox(i),0.)
          wstar3(i) = (govrth(i)*bfx0*hpbl(i))
          wstar(i) = (wstar3(i))**h1

        else
          phim(i) = (1.+aphi5*hol1)
          phih(i) = phim(i)

          wstar(i)  = 0.
          wstar3(i) = 0.

        endif

        ust3(i)   = ust(i)**3.
        wscale(i) = (ust3(i)+phifac*karman*wstar3(i)*0.5)**h1

        wscale(i) = min(wscale(i),ust(i)*aphi16)
        wscale(i) = max(wscale(i),ust(i)/aphi5)
      enddo
!
!     compute the surface variables for pbl height estimation
!     under unstable conditions
!
      do i = its,ite
        if(sfcflg(i))then

          gamfac   = bfac/rhox(i)/wscale(i)
          hgamt(i) = min(gamfac*hfx(i)/cpm(i),gamcrt)
          hgamq(i) = min(gamfac*qfx(i),gamcrq)
          vpert = (hgamt(i)+ep1*thx(i,1)*hgamq(i))/bfac*afac

          hgamt(i) = max(hgamt(i),0.0)
          hgamq(i) = max(hgamq(i),0.0)
          thermal(i) = thermal(i)+max(vpert,0.)
          brint    = -15.9*ust(i)*ust(i)/wspd(i)*wstar3(i) &
                     /(wscale(i)**4.)
          hgamu(i) = brint*ux(i,1)
          hgamv(i) = brint*vx(i,1)



        else
          pblflg(i) = .false.
        endif
      enddo

!
!     enhance the pbl height by considering the thermal
!
      do i = its,ite
        if(pblflg(i))then
          kpbl(i) = 1
          hpbl(i) = zq(i,1)
        endif
      enddo
      do i = its,ite
        if(pblflg(i))then
          stable(i) = .false.
          brup(i) = br(i)
        endif
      enddo
      do k = 2,klpbl
        do i = its,ite
          if(.not.stable(i).and.pblflg(i))then
            brdn(i) = brup(i)
            spdk2 = max((ux(i,k)**2+vx(i,k)**2),1.)
            brup(i) = (thvx(i,k)-thermal(i))*(g*za(i,k)/thvx(i,1))/spdk2
            kpbl(i) = k
            stable(i) = brup(i).gt.brcr

          endif
        enddo
      enddo
!
      do i = its,ite
        if(pblflg(i))then
          k = kpbl(i)
          if(brdn(i).ge.brcr)then
            brint = 0.
          elseif(brup(i).le.brcr)then
            brint = 1.
          else
            brint = (brcr-brdn(i))/(brup(i)-brdn(i))
          endif
          hpbl(i) = za(i,k-1)+brint*(za(i,k)-za(i,k-1))
          if(hpbl(i).lt.zq(i,2)) kpbl(i) = 1
          if(kpbl(i).le.1) pblflg(i) = .false.
!         if(hpbl(i).lt.zq(i,kpbl(i))) kpbl(i) = kpbl(i)-1

        endif
      enddo

!

!
!     estimate the entrainemnt parameters
!
      do i = its,ite
        if(pblflg(i)) then
          k = kpbl(i) - 1
          ss = ((ux(i,k+1)-ux(i,k))*(ux(i,k+1)-ux(i,k))+(vx(i,k+1)- &
             vx(i,k))*(vx(i,k+1)-vx(i,k)))/(dza(i,k+1)*dza(i,k+1))+ &
             1.e-9
          ri = govrth(i)*(thvx(i,k+1)-thvx(i,k))/(ss*dza(i,k+1))
          if(imvdif.eq.1)then
            if((qcx(i,k)+qix(i,k)).gt.0.01e-3.and.(qcx(i,k+1)+      &
              qix(i,k+1)).gt.0.01e-3)then
!      in cloud
              qmean = 0.5*(qx(i,k)+qx(i,k+1))
              tmean = 0.5*(tx(i,k)+tx(i,k+1))
              alph  = xlv*qmean/rd/tmean
              chi   = xlv*xlv*qmean/cp/rv/tmean/tmean
              ri    = (1.+alph)*(ri-g*g/ss/tmean/cp*((chi-alph)/(1.+chi)))
            endif
          endif
!         prpbl(i) = 1.0 + 2.1 * ri
!         prpbl(i) = min(max(prpbl(i),1.),prmax)
          prpbl(i) = 1.0 
          wm3       = wstar3(i) + 5. * ust3(i)
          wm2(i)    = wm3**h2
          bfxpbl(i) = -0.15*thvx(i,1)/g*wm3/hpbl(i)
          dthvx(i)  = max(thvx(i,k+1)-thvx(i,k),qmin)
          dthx  = max(thx(i,k+1)-thx(i,k),qmin)
          dqx   = min(qx(i,k+1)-qx(i,k),0.0)
          hfxpbl(i) = bfxpbl(i)*dthx/dthvx(i)
          qfxpbl(i) = bfxpbl(i)*dqx/dthvx(i)
!
          dux = ux(i,k+1)-ux(i,k)
          dvx = vx(i,k+1)-vx(i,k)
          if(dux.gt.qmin) then
            ufxpbl(i) = max(prpbl(i)*bfxpbl(i)*dux/dthvx(i),-ust(i)*ust(i))
          elseif(dux.lt.-qmin) then
            ufxpbl(i) = min(prpbl(i)*bfxpbl(i)*dux/dthvx(i),ust(i)*ust(i))
          else
            ufxpbl(i) = 0.0
          endif
          if(dvx.gt.qmin) then
            vfxpbl(i) = max(prpbl(i)*bfxpbl(i)*dvx/dthvx(i),-ust(i)*ust(i))
          elseif(dvx.lt.-qmin) then
            vfxpbl(i) = min(prpbl(i)*bfxpbl(i)*dvx/dthvx(i),ust(i)*ust(i))
          else
            vfxpbl(i) = 0.0
          endif

          delb  = govrth(i)*d3*hpbl(i)
          delta(i) = min(d1*hpbl(i) + d2*wm2(i)/delb,100.)

        endif
      enddo
!
      do k = kts,klpbl
        do i = its,ite
          if(pblflg(i).and.k.ge.kpbl(i))then
            entfac(i,k) = ((zq(i,k)-hpbl(i))/delta(i))**2.
          else
            entfac(i,k) = 1.e30
          endif
        enddo
      enddo

!
!     compute diffusion coefficients below pbl
!
      do k = kts,klpbl
        do i = its,ite
          if(k.lt.kpbl(i)) then
            zfac(i,k) = min(max((1.-(zq(i,k+1)-zl1(i)) &
                        /(hpbl(i)-zl1(i))),zfmin),1.)
            xkzo = ckz*dza(i,k+1)

            zfacent(i,k) = (1.-zfac(i,k))**3.
            prnumfac = -3.*(max(zq(i,k+1)-sfcfrac*hpbl(i),0.))**2. &
                       /hpbl(i)**2.
            prnum = (phih(i)/phim(i)+bfac*karman*sfcfrac)
            prnum =  1. + (prnum-1.)*exp(prnumfac)

            prnum = min(prnum,prmax)
            prnum = max(prnum,prmin)

            wscalek(i,k) = (ust3(i)+phifac*karman*wstar3(i) &
                          *(1.-zfac(i,k)))**h1
            xkzm(i,k) = xkzo+wscalek(i,k)*karman*zq(i,k+1) &
                        *zfac(i,k)**pfac
            xkzh(i,k) = xkzm(i,k)/prnum

            xkzm(i,k) = min(xkzm(i,k),xkzmax)
            xkzm(i,k) = max(xkzm(i,k),xkzmin)
            xkzh(i,k) = min(xkzh(i,k),xkzmax)
            xkzh(i,k) = max(xkzh(i,k),xkzmin)
          endif
        enddo
      enddo
!
!     compute diffusion coefficients over pbl (free atmosphere)
!
      do k = kts,kte-1
        do i = its,ite
          xkzo = ckz*dza(i,k+1)
          if(k.ge.kpbl(i)) then
            ss = ((ux(i,k+1)-ux(i,k))*(ux(i,k+1)-ux(i,k))+(vx(i,k+1)- &
               vx(i,k))*(vx(i,k+1)-vx(i,k)))/(dza(i,k+1)*dza(i,k+1))+ &
               1.e-9
            ri = govrth(i)*(thvx(i,k+1)-thvx(i,k))/(ss*dza(i,k+1))
            if(imvdif.eq.1)then
              if((qcx(i,k)+qix(i,k)).gt.0.01e-3.and.(qcx(i,k+1)+      &
                qix(i,k+1)).gt.0.01e-3)then
!      in cloud
                qmean = 0.5*(qx(i,k)+qx(i,k+1))
                tmean = 0.5*(tx(i,k)+tx(i,k+1))
                alph  = xlv*qmean/rd/tmean
                chi   = xlv*xlv*qmean/cp/rv/tmean/tmean
                ri    = (1.+alph)*(ri-g*g/ss/tmean/cp*((chi-alph)/(1.+chi)))
              endif
            endif
            zk = karman*zq(i,k+1)

            rl2 = (zk*rlam/(rlam+zk))**2

            dk = rl2*sqrt(ss)
            if(ri.lt.0.)then
! unstable regime
              sri = sqrt(-ri)
              xkzm(i,k) = xkzo+dk*(1+8.*(-ri)/(1+1.746*sri))
              xkzh(i,k) = xkzo+dk*(1+8.*(-ri)/(1+1.286*sri))
            else
! stable regime
              xkzh(i,k) = xkzo+dk/(1+5.*ri)**2
              prnum = 1.0+2.1*ri
              prnum = min(prnum,prmax)
              xkzm(i,k) = (xkzh(i,k)-xkzo)*prnum+xkzo
            endif
!
            xkzm(i,k) = min(xkzm(i,k),xkzmax)
            xkzm(i,k) = max(xkzm(i,k),xkzmin)
            xkzh(i,k) = min(xkzh(i,k),xkzmax)
            xkzh(i,k) = max(xkzh(i,k),xkzmin)

            xkzml(i,k) = xkzm(i,k)
            xkzhl(i,k) = xkzh(i,k)

          endif
!
        enddo
      enddo
!
!     compute tridiagonal matrix elements for heat and moisture, and clouds
!
      do i = its,ite
        do k = kts,kte
          au(i,k) = 0.
          al(i,k) = 0.
          ad(i,k) = 0.
          a1(i,k) = 0.
        enddo
      enddo
      do ic = 1,ncloud
        do i = its,ite
          do k = kts,kte
            a3(i,k,ic) = 0.
          enddo
        enddo
      enddo
!
      do i = its,ite
        ad(i,1) = 1.
        a1(i,1) = tx(i,1)+hfx(i)/(rhox(i)*cpm(i))/zq(i,2)*dt4
        a3(i,1,1) = qx(i,1)+qfx(i)/(rhox(i))/zq(i,2)*dt4
      enddo
!
      if(ncloud.ge.2) then
        do ic = 2,ncloud
          do i = its,ite
            if(ic.eq.2) then
              a3(i,1,ic) = qcx(i,1)
            elseif(ic.eq.3) then
              a3(i,1,ic) = qix(i,1)
            endif
          enddo
        enddo
      endif
!
      do k = kts,kte-1
        do i = its,ite
          dtodsd = dt4/dz8w2d(i,k)
          dtodsu = dt4/dz8w2d(i,k+1)
          dsig =  z2d(i,k+1) - z2d(i,k)
          rdz = 1./dza(i,k+1)
          if(pblflg(i).and.k.lt.kpbl(i)) then


            dsdzt = dsig*xkzh(i,k)*rdz*(g/cp-hgamt(i)/hpbl(i) &
                   -hfxpbl(i)*zfacent(i,k)/xkzh(i,k))
            dsdzq = dsig*xkzh(i,k)*rdz*(-hgamq(i)/hpbl(i) &
                   -qfxpbl(i)*zfacent(i,k)/xkzh(i,k))

            a3(i,k,1) = a3(i,k,1)+dtodsd*dsdzq
            a3(i,k+1,1) = qx(i,k+1)-dtodsu*dsdzq

          elseif(pblflg(i).and.k.ge.kpbl(i).and.entfac(i,k).lt.4.6) then
            xkzh(i,k) = -bfxpbl(i)*dza(i,kpbl(i)+1)*exp(-entfac(i,k))/dthvx(i)

            xkzh(i,k) = sqrt(xkzh(i,k)*xkzhl(i,k))
            xkzh(i,k) = min(xkzh(i,k),xkzmax)
            xkzh(i,k) = max(xkzh(i,k),xkzmin)
            dsdzt = dsig*xkzh(i,k)*rdz*(g/cp)
            a3(i,k+1,1) = qx(i,k+1)

          else
            dsdzt = dsig*xkzh(i,k)*rdz*(g/cp)
            a3(i,k+1,1) = qx(i,k+1)
          endif
          dsdz2 = dsig*xkzh(i,k)*rdz*rdz
          au(i,k)   = -dtodsd*dsdz2
          al(i,k)   = -dtodsu*dsdz2
          ad(i,k)   = ad(i,k)-au(i,k)
          ad(i,k+1) = 1.-al(i,k)
          a1(i,k)   = a1(i,k)+dtodsd*dsdzt
          a1(i,k+1) = tx(i,k+1)-dtodsu*dsdzt
        enddo
      enddo
      if(ncloud.ge.2) then
        do ic = 2,ncloud
          do k = kts,kte-1
            do i = its,ite
              if(ic.eq.2) then
                a3(i,k+1,ic) = qcx(i,k+1)
              elseif(ic.eq.3) then
                a3(i,k+1,ic) = qix(i,k+1)
              endif
            enddo
          enddo
        enddo
      endif
!
!     solve tridiagonal problem for heat and moisture, and clouds
!
      call tridin(al,ad,au,a1,a3,au,a1,a3,                 &
		  its,ite,kts,kte,ncloud                   )
!
!     recover tendencies of heat and moisture
!
      do k = kte,kts,-1
        do i = its,ite
          ttend = (a1(i,k)-tx(i,k))*rdt
          qtend = (a3(i,k,1)-qx(i,k))*rdt
          ttnp(i,k) = ttnp(i,k)+ttend
          qtnp(i,k) = qtnp(i,k)+qtend

        enddo
      enddo
      if(ncloud.ge.2) then
        do ic = 2,ncloud
          do k = kte,kts,-1
            do i = its,ite
              if(ic.eq.2) then
                qctend = (a3(i,k,ic)-qcx(i,k))*rdt
                qctnp(i,k) = qctnp(i,k)+qctend
              elseif(ic.eq.3) then
                qitend = (a3(i,k,ic)-qix(i,k))*rdt
                qitnp(i,k) = qitnp(i,k)+qitend
              endif
            enddo
          enddo
        enddo
      endif
!
!     compute tridiagonal matrix elements for momentum
!
      do i = its,ite
      do k = kts,kte
         au(i,k) = 0.
         al(i,k) = 0.
         ad(i,k) = 0.
         a1(i,k) = 0.
         a2(i,k) = 0.
      enddo
      enddo
!
      do i = its,ite
        ad(i,1) = 1.
        a1(i,1) = ux(i,1)-ux(i,1)/wspd1(i)*ust(i)*ust(i)/zq(i,2)*dt4 &
                        *(wspd1(i)/wspd(i))**2
        a2(i,1) = vx(i,1)-vx(i,1)/wspd1(i)*ust(i)*ust(i)/zq(i,2)*dt4 &
                        *(wspd1(i)/wspd(i))**2

      enddo
!
      do k = kts,kte-1
        do i = its,ite
          dtodsd = dt4/dz8w2d(i,k)
          dtodsu = dt4/dz8w2d(i,k+1)
          dsig =  z2d(i,k+1) - z2d(i,k)
          rdz = 1./dza(i,k+1)

        if(pblflg(i).and.k.lt.kpbl(i))then
          dsdzu=dsig*xkzm(i,k)*rdz*(-hgamu(i)/hpbl(i) &
                 -ufxpbl(i)*zfacent(i,k)/xkzm(i,k))
          dsdzv=dsig*xkzm(i,k)*rdz*(-hgamv(i)/hpbl(i) &
                 -vfxpbl(i)*zfacent(i,k)/xkzm(i,k))
          a1(i,k)   = a1(i,k)+dtodsd*dsdzu
          a1(i,k+1) = ux(i,k+1)-dtodsu*dsdzu
          a2(i,k)   = a2(i,k)+dtodsd*dsdzv
          a2(i,k+1) = vx(i,k+1)-dtodsu*dsdzv
        elseif(pblflg(i).and.k.ge.kpbl(i).and.entfac(i,k).lt.4.6) then
          xkzm(i,k) = prpbl(i)*xkzh(i,k)
          xkzm(i,k) = sqrt(xkzm(i,k)*xkzml(i,k))
          xkzm(i,k)=min(xkzm(i,k),xkzmax)
          xkzm(i,k)=max(xkzm(i,k),xkzmin)
          a1(i,k+1)=ux(i,k+1)
          a2(i,k+1)=vx(i,k+1)
        else
          a1(i,k+1) = ux(i,k+1)
          a2(i,k+1) = vx(i,k+1)
        endif

          dsdz2 = dsig*xkzm(i,k)*rdz*rdz
          au(i,k)   = -dtodsd*dsdz2
          al(i,k)   = -dtodsu*dsdz2
          ad(i,k)   = ad(i,k)-au(i,k)
          ad(i,k+1) = 1.-al(i,k)
        enddo
      enddo
!
!     solve tridiagonal problem for momentum
!
      call tridin(al,ad,au,a1,a2,au,a1,a2,                 &
		  its,ite,kts,kte,1                         )
!
!     recover tendencies of momentum
!
      do k = kte,kts,-1
        do i = its,ite
          utend = (a1(i,k)-ux(i,k))*rdt
          vtend = (a2(i,k)-vx(i,k))*rdt
          utnp(i,k) = utnp(i,k)+utend
          vtnp(i,k) = vtnp(i,k)+vtend

        enddo
      enddo
!
!---- end of vertical diffusion
!
  690 continue
!
      do i = its,ite
        kpbl1d(i) = kpbl(i)
      enddo
!
   end subroutine ysu2d
!

   subroutine tridin(cl,cm,cu,r1,r2,au,a1,a2,                   & 2
                     its,ite,kts,kte,nt			        )
!----------------------------------------------------------------
   implicit none
!----------------------------------------------------------------

   integer, intent(in )      ::     its,ite, kts,kte, nt
!
   real, dimension( its:ite, kts+1:kte+1 )                    , &
         intent(in   )  ::                                  cl
!
   real, dimension( its:ite, kts:kte )                        , &
         intent(in   )  ::                                  cm, &
							    r1
   real, dimension( its:ite, kts:kte,nt )                     , &
         intent(in   )  ::                                  r2 
!
   real, dimension( its:ite, kts:kte )                        , &
         intent(inout)  ::                                  au, &
							    cu, &
							    a1
   real, dimension( its:ite, kts:kte,nt )                     , &
         intent(inout)  ::                                  a2
!
   real    :: fk
   integer :: i,k,l,n,it
!
!----------------------------------------------------------------
!
   l = ite
   n = kte
!
   do i = its,l
     fk = 1./cm(i,1)
     au(i,1) = fk*cu(i,1)
     a1(i,1) = fk*r1(i,1)
   enddo
   do it = 1,nt
     do i = its,l
       fk = 1./cm(i,1)
       a2(i,1,it) = fk*r2(i,1,it)
     enddo
   enddo
   do k = kts+1,n-1
     do i = its,l
       fk = 1./(cm(i,k)-cl(i,k)*au(i,k-1))
       au(i,k) = fk*cu(i,k)
       a1(i,k) = fk*(r1(i,k)-cl(i,k)*a1(i,k-1))
     enddo
   enddo
   do it = 1,nt
   do k = kts+1,n-1
     do i = its,l
       fk = 1./(cm(i,k)-cl(i,k)*au(i,k-1))
       a2(i,k,it) = fk*(r2(i,k,it)-cl(i,k)*a2(i,k-1,it))
     enddo
   enddo
   enddo
   do i = its,l
     fk = 1./(cm(i,n)-cl(i,n)*au(i,n-1))
     a1(i,n) = fk*(r1(i,n)-cl(i,n)*a1(i,n-1))
   enddo
   do it = 1,nt
   do i = its,l
     fk = 1./(cm(i,n)-cl(i,n)*au(i,n-1))
     a2(i,n,it) = fk*(r2(i,n,it)-cl(i,n)*a2(i,n-1,it))
   enddo
   enddo
   do k = n-1,kts,-1
     do i = its,l
       a1(i,k) = a1(i,k)-au(i,k)*a1(i,k+1)
     enddo
   enddo
   do it = 1,nt
   do k = n-1,kts,-1
     do i = its,l
       a2(i,k,it) = a2(i,k,it)-au(i,k)*a2(i,k+1,it)
     enddo
   enddo
   enddo
!
   end subroutine tridin
!

   subroutine ysuinit(rublten,rvblten,rthblten,rqvblten,           & 1
                      rqcblten,rqiblten,p_qi,p_first_scalar,       &
                      restart,                                     &
                      ids, ide, jds, jde, kds, kde,                &
                      ims, ime, jms, jme, kms, kme,                &
                      its, ite, jts, jte, kts, kte                 )
!-------------------------------------------------------------------
   implicit none
!-------------------------------------------------------------------
   logical , intent(in)          :: restart
   integer , intent(in)          ::  ids, ide, jds, jde, kds, kde, &
                                     ims, ime, jms, jme, kms, kme, &
                                     its, ite, jts, jte, kts, kte
   integer , intent(in)          ::  p_qi,p_first_scalar

   real , dimension( ims:ime , kms:kme , jms:jme ), intent(out) :: &
                                                          rublten, &
                                                          rvblten, &
                                                         rthblten, &
                                                         rqvblten, &
                                                         rqcblten, &
                                                         rqiblten
   integer :: i, j, k, itf, jtf, ktf

   jtf = min0(jte,jde-1)
   ktf = min0(kte,kde-1)
   itf = min0(ite,ide-1)

   if(.not.restart)then
     do j = jts,jtf
     do k = kts,ktf
     do i = its,itf
        rublten(i,k,j) = 0.
        rvblten(i,k,j) = 0.
        rthblten(i,k,j) = 0.
        rqvblten(i,k,j) = 0.
        rqcblten(i,k,j) = 0.
     enddo
     enddo
     enddo
   endif

   if (p_qi .ge. p_first_scalar .and. .not.restart) then
      do j = jts,jtf
      do k = kts,ktf
      do i = its,itf
         rqiblten(i,k,j) = 0.
      enddo
      enddo
      enddo
   endif

   end subroutine ysuinit

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


end module module_bl_ysu