C $Header: /u/gcmpack/MITgcm/pkg/mom_common/mom_v_bottomdrag.F,v 1.17 2015/01/04 16:16:32 jmc Exp $
C $Name:  $

#include "MOM_COMMON_OPTIONS.h"
#ifdef ALLOW_CTRL
# include "CTRL_OPTIONS.h"
#endif

CBOP
C !ROUTINE: MOM_V_BOTTOMDRAG

C !INTERFACE: ==========================================================
      SUBROUTINE MOM_V_BOTTOMDRAG(
     I        bi, bj, k,
     I        uFld, vFld, KE, kappaRV,
     O        vDragTerms,
     I        myThid )

C !DESCRIPTION:
C Calculates the drag due to friction and the no-slip condition at bottom:
C \begin{equation*}
C G^v_{drag} = - \frac{1}{\Delta r_f} ( r_b + C_D |v| + \frac{2}{\Delta r_c} ) v
C \end{equation*}

C !USES: ===============================================================
      IMPLICIT NONE
#include "SIZE.h"
#include "EEPARAMS.h"
#include "PARAMS.h"
#include "GRID.h"
#ifdef ALLOW_CTRL
# include "CTRL_FIELDS.h"
#endif

C !INPUT PARAMETERS: ===================================================
C  bi,bj                :: tile indices
C  k                    :: vertical level
C  uFld                 :: zonal flow
C  vFld                 :: meridional flow
C  KE                   :: Kinetic energy
C  kappaRV              :: vertical viscosity
C  myThid               :: thread number
      INTEGER bi,bj,k
      _RL uFld(1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL vFld(1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL KE(1-OLx:sNx+OLx,1-OLy:sNy+OLy)
      _RL kappaRV(1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr+1)
      INTEGER myThid

C !OUTPUT PARAMETERS: ==================================================
C  vDragTerms           :: drag term
      _RL vDragTerms(1-OLx:sNx+OLx,1-OLy:sNy+OLy)

C !LOCAL VARIABLES: ====================================================
C  i,j                  :: loop indices
      INTEGER i,j,kDown,kLowF,kBottom
      _RL viscFac, dragFac, vSq
      _RL recDrC
      _RL recDrF_bot(1-OLx:sNx+OLx,1-OLy:sNy+OLy)
CEOP

C-  No-slip BCs impose a drag at bottom
      viscFac = 0.
      IF (no_slip_bottom) viscFac = 2.
      IF ( usingZCoords ) THEN
       kBottom = Nr
       kDown   = MIN(k+1,Nr)
       kLowF   = k+1
c      dragFac = mass2rUnit*rhoConst
c      dragFac = wUnit2rVel(k+1)
       dragFac = 1. _d 0
      ELSE
       kBottom = 1
       kDown   = MAX(k-1,1)
       kLowF   = k
       dragFac = mass2rUnit*rhoConst
c      dragFac = wUnit2rVel(k)
      ENDIF
      IF ( k.EQ.kBottom ) THEN
       recDrC = recip_drF(k)
       DO j=1-OLy,sNy+OLy
        DO i=1-OLx,sNx+OLx
          recDrF_bot(i,j) = _recip_hFacS(i,j,k,bi,bj)*recip_drF(k)
        ENDDO
       ENDDO
      ELSE
       recDrC = recip_drC(kLowF)
       DO j=1-OLy,sNy+OLy
        DO i=1-OLx,sNx+OLx
          recDrF_bot(i,j) = _recip_hFacS(i,j,k,bi,bj)*recip_drF(k)
     &                    * ( 1. _d 0 -_maskS(i,j,kDown,bi,bj) )
        ENDDO
       ENDDO
      ENDIF

C--   Linear bottom drag:
      DO j=1-OLy+1,sNy+OLy-1
       DO i=1-OLx,sNx+OLx-1
         vDragTerms(i,j) =
     &    - recDrF_bot(i,j)
     &    *( bottomDragLinear*dragFac
#ifdef ALLOW_BOTTOMDRAG_CONTROL
     &     + halfRL*( bottomDragFld(i,j-1,bi,bj)
     &              + bottomDragFld(i,j,bi,bj) )*dragFac
#endif
     &     )*vFld(i,j)
       ENDDO
      ENDDO

C--   Add friction at the bottom (no-slip BC)
      IF ( no_slip_bottom .AND. bottomVisc_pCell ) THEN
C-    bottom friction accounts for true distance (including hFac) to the bottom
       DO j=1-OLy+1,sNy+OLy-1
        DO i=1-OLx,sNx+OLx-1
         vDragTerms(i,j) = vDragTerms(i,j)
     &    - recDrF_bot(i,j)
     &    *( kappaRV(i,j,kLowF)*recDrC*viscFac
     &                         *_recip_hFacS(i,j,k,bi,bj)
     &     )*vFld(i,j)
        ENDDO
       ENDDO
      ELSEIF ( no_slip_bottom ) THEN
C-    ignore partial-cell reduction of the distance to the bottom
       DO j=1-OLy+1,sNy+OLy-1
        DO i=1-OLx,sNx+OLx-1
         vDragTerms(i,j) = vDragTerms(i,j)
     &    - recDrF_bot(i,j)
     &    *( kappaRV(i,j,kLowF)*recDrC*viscFac
     &     )*vFld(i,j)
        ENDDO
       ENDDO
      ENDIF

C--   Add quadratic bottom drag
      IF ( selectBotDragQuadr.EQ.0 ) THEN
C-    average grid-cell-center KE to get velocity norm @ V.pt
       DO j=1-OLy+1,sNy+OLy-1
        DO i=1-OLx,sNx+OLx-1
         IF ( (KE(i,j)+KE(i,j-1)) .GT. 0. ) THEN
          vDragTerms(i,j) = vDragTerms(i,j)
     &     - recDrF_bot(i,j)
     &      *bottomDragQuadratic*SQRT(KE(i,j)+KE(i,j-1))*dragFac
     &      *vFld(i,j)
         ENDIF
        ENDDO
       ENDDO
      ELSEIF ( selectBotDragQuadr.EQ.1 ) THEN
C-    calculate locally velocity norm @ V.pt (local V & 4 U averaged)
       DO j=1-OLy+1,sNy+OLy-1
        DO i=1-OLx,sNx+OLx-1
         vSq = vFld(i,j)*vFld(i,j)
     &       + ( (uFld( i ,j-1)*uFld( i ,j-1)*hFacW( i ,j-1,k,bi,bj)
     &           +uFld( i , j )*uFld( i , j )*hFacW( i , j ,k,bi,bj))
     &         + (uFld(i+1,j-1)*uFld(i+1,j-1)*hFacW(i+1,j-1,k,bi,bj)
     &           +uFld(i+1, j )*uFld(i+1, j )*hFacW(i+1, j ,k,bi,bj))
     &         )*recip_hFacS(i,j,k,bi,bj)*0.25 _d 0
         IF ( vSq.GT.zeroRL ) THEN
          vDragTerms(i,j) = vDragTerms(i,j)
     &     - recDrF_bot(i,j)
     &      *bottomDragQuadratic*SQRT(vSq)*dragFac
     &      *vFld(i,j)
         ENDIF
        ENDDO
       ENDDO
      ELSEIF ( selectBotDragQuadr.EQ.2 ) THEN
C-    same as above but using wet-point method to average 4 U
       DO j=1-OLy+1,sNy+OLy-1
        DO i=1-OLx,sNx+OLx-1
         vSq = ( hFacW( i ,j-1,k,bi,bj) + hFacW( i , j ,k,bi,bj) )
     &       + ( hFacW(i+1,j-1,k,bi,bj) + hFacW(i+1, j ,k,bi,bj) )
         IF ( vSq.GT.zeroRL ) THEN
          vSq = vFld(i,j)*vFld(i,j)
     &        +( (uFld( i ,j-1)*uFld( i ,j-1)*hFacW( i ,j-1,k,bi,bj)
     &           +uFld( i , j )*uFld( i , j )*hFacW( i , j ,k,bi,bj))
     &         + (uFld(i+1,j-1)*uFld(i+1,j-1)*hFacW(i+1,j-1,k,bi,bj)
     &           +uFld(i+1, j )*uFld(i+1, j )*hFacW(i+1, j ,k,bi,bj))
     &         )/vSq
         ELSE
          vSq = vFld(i,j)*vFld(i,j)
         ENDIF
         IF ( vSq.GT.zeroRL ) THEN
          vDragTerms(i,j) = vDragTerms(i,j)
     &     - recDrF_bot(i,j)
     &      *bottomDragQuadratic*SQRT(vSq)*dragFac
     &      *vFld(i,j)
         ENDIF
        ENDDO
       ENDDO
      ELSEIF ( selectBotDragQuadr.NE.-1 ) THEN
        STOP 'MOM_V_BOTTOMDRAG: invalid selectBotDragQuadr value'
      ENDIF

#ifdef ALLOW_DIAGNOSTICS
      IF (useDiagnostics) THEN
        CALL DIAGNOSTICS_FILL(vDragTerms,'VBotDrag',k,1,2,bi,bj,myThid)
      ENDIF
#endif /* ALLOW_DIAGNOSTICS */

      RETURN
      END