!
! $Id: $
!
SUBROUTINE top_bound_loc(vcov,ucov,teta,masse,dt)
  USE iniprint_mod_h
  USE comgeom2_mod_h
  USE comdissipn_mod_h
  USE parallel_lmdz
  USE comconst_mod, ONLY: iflag_top_bound, mode_top_bound, &
        tau_top_bound
  USE comvert_mod, ONLY: presnivs, preff, scaleheight

  USE dimensions_mod, ONLY: iim, jjm, llm, ndm
USE paramet_mod_h
IMPLICIT NONE
  !




  ! ..  DISSIPATION LINEAIRE A HAUT NIVEAU, RUN MESO,
  ! F. LOTT DEC. 2006
  !                             (  10/12/06  )

  !=======================================================================
  !
  !   Auteur:  F. LOTT
  !   -------
  !
  !   Objet:
  !   ------
  !
  !   Dissipation lin�aire (ex top_bound de la physique)
  !
  !=======================================================================

  ! top_bound sponge layer model:
  ! Quenching is modeled as: A(t)=Am+A0*exp(-lambda*t)
  ! where Am is the zonal average of the field (or zero), and lambda the inverse
  ! of the characteristic quenching/relaxation time scale
  ! Thus, assuming Am to be time-independent, field at time t+dt is given by:
  ! A(t+dt)=A(t)-(A(t)-Am)*(1-exp(-lambda*t))
  ! Moreover lambda can be a function of model level (see below), and relaxation
  ! can be toward the average zonal field or just zero (see below).

  ! NB: top_bound sponge is only called from leapfrog if ok_strato=.true.

  ! sponge parameters: (loaded/set in conf_gcm.F ; stored in comconst_mod)
  !    iflag_top_bound=0 for no sponge
  !    iflag_top_bound=1 for sponge over 4 topmost layers
  !    iflag_top_bound=2 for sponge from top to ~1% of top layer pressure
  !    mode_top_bound=0: no relaxation
  !    mode_top_bound=1: u and v relax towards 0
  !    mode_top_bound=2: u and v relax towards their zonal mean
  !    mode_top_bound=3: u,v and pot. temp. relax towards their zonal mean
  !    tau_top_bound : inverse of charactericstic relaxation time scale at
  !                   the topmost layer (Hz)



  !   Arguments:
  !   ----------

  real,intent(inout) :: ucov(iip1,jjb_u:jje_u,llm) ! covariant zonal wind
  real,intent(inout) :: vcov(iip1,jjb_v:jje_v,llm) ! covariant meridional wind
  real,intent(inout) :: teta(iip1,jjb_u:jje_u,llm) ! potential temperature
  real,intent(in) :: masse(iip1,jjb_u:jje_u,llm) ! mass of atmosphere
  real,intent(in) :: dt ! time step (s) of sponge model

   ! REAL dv(iip1,jjb_v:jje_v,llm),du(iip1,jjb_u:jje_u,llm)
   ! REAL dh(iip1,jjb_u:jje_u,llm)

  !   Local:
  !   ------
  REAL :: massebx(iip1,jjb_u:jje_u,llm),masseby(iip1,jjb_v:jje_v,llm)
  REAL :: zm
  REAL :: uzon(jjb_u:jje_u,llm),vzon(jjb_v:jje_v,llm)
  REAL :: tzon(jjb_u:jje_u,llm)

  integer :: i
  REAL,SAVE :: rdamp(llm)
  real,save :: lambda(llm) ! inverse or quenching time scale (Hz)
  LOGICAL,SAVE :: first=.true.
  INTEGER :: j,l,jjb,jje


  if (iflag_top_bound == 0) return

  if (first) then
!$OMP BARRIER
!$OMP MASTER
     if (iflag_top_bound == 1) then
  ! sponge quenching over the topmost 4 atmospheric layers
         lambda(:)=0.
         lambda(llm)=tau_top_bound
         lambda(llm-1)=tau_top_bound/2.
         lambda(llm-2)=tau_top_bound/4.
         lambda(llm-3)=tau_top_bound/8.
     else if (iflag_top_bound == 2) then
  ! sponge quenching over topmost layers down to pressures which are
  ! higher than 100 times the topmost layer pressure
         lambda(:)=tau_top_bound &
               *max(presnivs(llm)/presnivs(:)-0.01,0.)
     endif

  ! quenching coefficient rdamp(:)
      ! rdamp(:)=dt*lambda(:) ! Explicit Euler approx.
     rdamp(:)=1.-exp(-lambda(:)*dt)

     write(lunout,*)'TOP_BOUND mode',mode_top_bound
     write(lunout,*)'Sponge layer coefficients'
     write(lunout,*)'p (Pa)  z(km)  tau(s)   1./tau (Hz)'
     do l=1,llm
       if (rdamp(l).ne.0.) then
         write(lunout,'(6(1pe12.4,1x))') &
               presnivs(l),log(preff/presnivs(l))*scaleheight, &
               1./lambda(l),lambda(l)
       endif
     enddo
     first=.false.
!$OMP END MASTER
!$OMP BARRIER
  endif ! of if (first)


  CALL massbar_loc(masse,massebx,masseby)

  ! ! compute zonal average of vcov (or set it to zero)
  if (mode_top_bound.ge.2) then
   jjb=jj_begin
   jje=jj_end
   IF (pole_sud) jje=jj_end-1
!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
   do l=1,llm
    do j=jjb,jje
      zm=0.
      vzon(j,l)=0
      do i=1,iim
  ! NB: we can work using vcov zonal mean rather than v since the
  ! cv coefficient (which relates the two) only varies with latitudes
        vzon(j,l)=vzon(j,l)+vcov(i,j,l)*masseby(i,j,l)
        zm=zm+masseby(i,j,l)
      enddo
      vzon(j,l)=vzon(j,l)/zm
    enddo
   enddo
!$OMP END DO NOWAIT
  else
!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
   do l=1,llm
     vzon(:,l)=0.
   enddo
!$OMP END DO NOWAIT
  endif ! of if (mode_top_bound.ge.2)

  ! ! compute zonal average of u (or set it to zero)
  if (mode_top_bound.ge.2) then
   jjb=jj_begin
   jje=jj_end
   IF (pole_nord) jjb=jj_begin+1
   IF (pole_sud)  jje=jj_end-1
!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
   do l=1,llm
    do j=jjb,jje
      uzon(j,l)=0.
      zm=0.
      do i=1,iim
        uzon(j,l)=uzon(j,l)+massebx(i,j,l)*ucov(i,j,l)/cu(i,j)
        zm=zm+massebx(i,j,l)
      enddo
      uzon(j,l)=uzon(j,l)/zm
    enddo
   enddo
!$OMP END DO NOWAIT
  else
!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
   do l=1,llm
     uzon(:,l)=0.
   enddo
!$OMP END DO NOWAIT
  endif ! of if (mode_top_bound.ge.2)

  ! ! compute zonal average of potential temperature, if necessary
  if (mode_top_bound.ge.3) then
   jjb=jj_begin
   jje=jj_end
   IF (pole_nord) jjb=jj_begin+1
   IF (pole_sud)  jje=jj_end-1
!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
   do l=1,llm
    do j=jjb,jje
      zm=0.
      tzon(j,l)=0.
      do i=1,iim
        tzon(j,l)=tzon(j,l)+teta(i,j,l)*masse(i,j,l)
        zm=zm+masse(i,j,l)
      enddo
      tzon(j,l)=tzon(j,l)/zm
    enddo
   enddo
!$OMP END DO NOWAIT
  endif ! of if (mode_top_bound.ge.3)

  if (mode_top_bound.ge.1) then
   ! ! Apply sponge quenching on vcov:
   jjb=jj_begin
   jje=jj_end
   IF (pole_sud) jje=jj_end-1

!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
   do l=1,llm
    do j=jjb,jje
      do i=1,iip1
        vcov(i,j,l)=vcov(i,j,l) &
              -rdamp(l)*(vcov(i,j,l)-vzon(j,l))
      enddo
    enddo
   enddo
!$OMP END DO NOWAIT

   ! ! Apply sponge quenching on ucov:
   jjb=jj_begin
   jje=jj_end
   IF (pole_nord) jjb=jj_begin+1
   IF (pole_sud)  jje=jj_end-1

!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
   do l=1,llm
    do j=jjb,jje
      do i=1,iip1
        ucov(i,j,l)=ucov(i,j,l) &
              -rdamp(l)*(ucov(i,j,l)-cu(i,j)*uzon(j,l))
      enddo
   enddo
   enddo
!$OMP END DO NOWAIT
  endif ! of if (mode_top_bound.ge.1)

  if (mode_top_bound.ge.3) then
   ! ! Apply sponge quenching on teta:
   jjb=jj_begin
   jje=jj_end
   IF (pole_nord) jjb=jj_begin+1
   IF (pole_sud)  jje=jj_end-1

!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
   do l=1,llm
    do j=jjb,jje
      do i=1,iip1
        teta(i,j,l)=teta(i,j,l) &
              -rdamp(l)*(teta(i,j,l)-tzon(j,l))
      enddo
   enddo
   enddo
!$OMP END DO NOWAIT
  endif ! of if (mode_top_bond.ge.3)

END SUBROUTINE top_bound_loc
