New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
zdfbfr.F90 in branches/nemo_v3_3_beta/NEMOGCM/NEMO/OPA_SRC/ZDF – NEMO

source: branches/nemo_v3_3_beta/NEMOGCM/NEMO/OPA_SRC/ZDF/zdfbfr.F90 @ 2346

Last change on this file since 2346 was 2346, checked in by gm, 14 years ago

v3.3beta: zdfgls compilation error + use of key_esopa in zdfbfr

  • Property svn:keywords set to Id
File size: 13.0 KB
RevLine 
[3]1MODULE zdfbfr
2   !!======================================================================
3   !!                       ***  MODULE  zdfbfr  ***
4   !! Ocean physics: Bottom friction
5   !!======================================================================
[1662]6   !! History :  OPA  ! 1997-06  (G. Madec, A.-M. Treguier)  Original code
[1601]7   !!   NEMO     1.0  ! 2002-06  (G. Madec)  F90: Free form and module
[1708]8   !!            3.2  ! 2009-09  (A.C.Coward)  Correction to include barotropic contribution
[2104]9   !!            3.3  ! 2010-10  (C. Ethe, G. Madec) reorganisation of initialisation phase
[1601]10   !!----------------------------------------------------------------------
[3]11
12   !!----------------------------------------------------------------------
[1601]13   !!   zdf_bfr      : update momentum Kz at the ocean bottom due to the type of bottom friction chosen
14   !!   zdf_bfr_init : read in namelist and control the bottom friction parameters.
[2104]15   !!   zdf_bfr_2d   : read in namelist and control the bottom friction parameters.
[3]16   !!----------------------------------------------------------------------
17   USE oce             ! ocean dynamics and tracers variables
18   USE dom_oce         ! ocean space and time domain variables
19   USE zdf_oce         ! ocean vertical physics variables
20   USE in_out_manager  ! I/O manager
21   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
[1671]22   USE lib_mpp         ! distributed memory computing
[258]23   USE prtctl          ! Print control
[3]24
25   IMPLICIT NONE
26   PRIVATE
27
[2027]28   PUBLIC   zdf_bfr         ! called by step.F90
29   PUBLIC   zdf_bfr_init    ! called by opa.F90
[1708]30   
31   REAL(wp), PUBLIC, DIMENSION(jpi,jpj) ::   bfrua , bfrva   !: Bottom friction coefficients set in zdfbfr
[2346]32#if defined key_zdfgls   ||   defined key_esopa
[2236]33   REAL(wp), PUBLIC                     ::   rn_hbro =  0.003_wp  ! Bottom roughness (m)
[2346]34   REAL(wp), PUBLIC, DIMENSION(jpi,jpj) ::   wbotu, wbotv         !  Bottom stresses
[2236]35#endif
[3]36
[1708]37   !                                    !!* Namelist nambfr: bottom friction namelist *
38   INTEGER  ::   nn_bfr    = 0           ! = 0/1/2/3 type of bottom friction
39   REAL(wp) ::   rn_bfri1  = 4.0e-4_wp   ! bottom drag coefficient (linear case)
40   REAL(wp) ::   rn_bfri2  = 1.0e-3_wp   ! bottom drag coefficient (non linear case)
41   REAL(wp) ::   rn_bfeb2  = 2.5e-3_wp   ! background bottom turbulent kinetic energy  [m2/s2]
42   REAL(wp) ::   rn_bfrien = 30_wp       ! local factor to enhance coefficient bfri
43   LOGICAL  ::   ln_bfr2d  = .false.     ! logical switch for 2D enhancement
44   
45   REAL(wp), DIMENSION(jpi,jpj) ::   bfrcoef2d = 1.e-3_wp   ! 2D bottom drag coefficient
[3]46
47   !! * Substitutions
[2309]48#  include "vectopt_loop_substitute.h90"
[3]49#  include "domzgr_substitute.h90"
50   !!----------------------------------------------------------------------
[2287]51   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
[2104]52   !! $Id$
[2287]53   !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
[3]54   !!----------------------------------------------------------------------
55
56CONTAINS
57
58   SUBROUTINE zdf_bfr( kt )
59      !!----------------------------------------------------------------------
60      !!                   ***  ROUTINE zdf_bfr  ***
61      !!                 
[1708]62      !! ** Purpose :   compute the bottom friction coefficient.
[3]63      !!
[1662]64      !! ** Method  :   Calculate and store part of the momentum trend due   
65      !!              to bottom friction following the chosen friction type
66      !!              (free-slip, linear, or quadratic). The component
67      !!              calculated here is multiplied by the bottom velocity in
68      !!              dyn_bfr to provide the trend term.
[1708]69      !!                The coefficients are updated at each time step only
70      !!              in the quadratic case.
[1662]71      !!
72      !! ** Action  :   bfrua , bfrva   bottom friction coefficients
[3]73      !!----------------------------------------------------------------------
74      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
[1601]75      !!
[1708]76      INTEGER  ::   ji, jj         ! dummy loop indices
[1662]77      INTEGER  ::   ikbu, ikbum1   ! temporary integers
[1708]78      INTEGER  ::   ikbv, ikbvm1   !    -          -
[1662]79      REAL(wp) ::   zvu, zuv, zecu, zecv   ! temporary scalars
[3]80      !!----------------------------------------------------------------------
81
[1662]82      IF( nn_bfr == 2 ) THEN                 ! quadratic botton friction
[1708]83         ! Calculate and store the quadratic bottom friction coefficient bfrua and bfrva
[1662]84         ! where bfrUa = C_d*SQRT(u_bot^2 + v_bot^2 + e_b) {U=[u,v]}
85         ! from these the trend due to bottom friction:  -F_h/e3U  can be calculated
86         ! where -F_h/e3U_bot = bfrUa*Ub/e3U_bot {U=[u,v]}
87         !
[789]88# if defined key_vectopt_loop
[1601]89         DO jj = 1, 1
[3]90!CDIR NOVERRCHK
[1601]91            DO ji = jpi+2, jpij-jpi-1   ! vector opt. (forced unrolling)
[3]92# else
93!CDIR NOVERRCHK
94         DO jj = 2, jpjm1
95!CDIR NOVERRCHK
96            DO ji = 2, jpim1
97# endif
98               ikbu   = MIN( mbathy(ji+1,jj  ), mbathy(ji,jj) )
99               ikbv   = MIN( mbathy(ji  ,jj+1), mbathy(ji,jj) )
100               ikbum1 = MAX( ikbu-1, 1 )
101               ikbvm1 = MAX( ikbv-1, 1 )
[1662]102               !
[3]103               zvu  = 0.25 * (  vn(ji,jj  ,ikbum1) + vn(ji+1,jj  ,ikbum1)     &
[1662]104                  &           + vn(ji,jj-1,ikbum1) + vn(ji+1,jj-1,ikbum1)  )
[3]105               zuv  = 0.25 * (  un(ji,jj  ,ikbvm1) + un(ji-1,jj  ,ikbvm1)     &
[1662]106                  &           + un(ji,jj+1,ikbvm1) + un(ji-1,jj+1,ikbvm1)  )
107               !
[1601]108               zecu = SQRT(  un(ji,jj,ikbum1) * un(ji,jj,ikbum1) + zvu*zvu + rn_bfeb2  )
109               zecv = SQRT(  vn(ji,jj,ikbvm1) * vn(ji,jj,ikbvm1) + zuv*zuv + rn_bfeb2  )
[1662]110               !
[1708]111               bfrua(ji,jj) = - 0.5 * ( bfrcoef2d(ji,jj) + bfrcoef2d(ji+1,jj  ) ) * zecu 
112               bfrva(ji,jj) = - 0.5 * ( bfrcoef2d(ji,jj) + bfrcoef2d(ji  ,jj+1) ) * zecv
[3]113            END DO
114         END DO
[1601]115         !
[1708]116         CALL lbc_lnk( bfrua, 'U', 1. )   ;   CALL lbc_lnk( bfrva, 'V', 1. )      ! Lateral boundary condition
117         !
118         IF(ln_ctl)   CALL prt_ctl( tab2d_1=bfrua, clinfo1=' bfr  - u: ', mask1=umask,        &
119            &                       tab2d_2=bfrva, clinfo2=       ' v: ', mask2=vmask,ovlap=1 )
[1662]120      ENDIF
121      !
[2309]122
123      !zdfgls case with explicit vertical diffusion scheme: save bottom stress for next time step
124
125#if defined key_zdfgls && defined key_dynspg_exp
126      DO jj = 2, jpjm1
127         DO ji = fs_2, fs_jpim1   ! vector opt.
128            !
129            ikbu   = MIN( mbathy(ji+1,jj  ), mbathy(ji,jj) )
130            ikbum1 = MAX( ikbu-1, 1 )
131            wbotu(ji,jj) = bfrua(ji,jj) * un(ji,jj,ikbum1) * umask(ji,jj,ikbum1)
132            !
133            ikbv   = MIN( mbathy(ji,jj+1), mbathy(ji,jj) )
134            ikbvm1 = MAX( ikbv-1, 1 )
135            wbotv(ji,jj) = bfrva(ji,jj) * vn(ji,jj,ikbvm1) * vmask(ji,jj,ikbvm1)
136            !
137         END DO
138      END DO
139      CALL lbc_lnk( wbotu(:,:), 'U', -1. )
140      CALL lbc_lnk( wbotv(:,:), 'V', -1. )
141#endif
142
[3]143   END SUBROUTINE zdf_bfr
144
145
146   SUBROUTINE zdf_bfr_init
147      !!----------------------------------------------------------------------
148      !!                  ***  ROUTINE zdf_bfr_init  ***
149      !!                   
150      !! ** Purpose :   Initialization of the bottom friction
151      !!
152      !! ** Method  :   Read the nammbf namelist and check their consistency
[1662]153      !!              called at the first timestep (nit000)
[3]154      !!----------------------------------------------------------------------
[1662]155      USE iom   ! I/O module for ehanced bottom friction file
156      !!
[1708]157      INTEGER ::   inum         ! logical unit for enhanced bottom friction file
158      INTEGER ::   ji, jj       ! dummy loop indexes
159      INTEGER ::   ikbu, ikbv   ! temporary integers
160      INTEGER ::   ictu, ictv   !    -          -
161      REAL(wp) ::  zminbfr, zmaxbfr   ! temporary scalars
162      REAL(wp) ::  zfru, zfrv         !    -         -
163      !!
[1662]164      NAMELIST/nambfr/ nn_bfr, rn_bfri1, rn_bfri2, rn_bfeb2, ln_bfr2d, rn_bfrien
[3]165      !!----------------------------------------------------------------------
166
[1662]167      REWIND ( numnam )               !* Read Namelist nam_bfr : bottom momentum boundary condition
168      READ   ( numnam, nambfr )
[3]169
[1662]170      !                               !* Parameter control and print
171      IF(lwp) WRITE(numout,*)
[3]172      IF(lwp) WRITE(numout,*) 'zdf_bfr : momentum bottom friction'
173      IF(lwp) WRITE(numout,*) '~~~~~~~'
[1708]174      IF(lwp) WRITE(numout,*) '   Namelist nam_bfr : set bottom friction parameters'
[3]175
[1662]176      SELECT CASE (nn_bfr)
177
[3]178      CASE( 0 )
[1708]179         IF(lwp) WRITE(numout,*) '      free-slip '
[1662]180         bfrua(:,:) = 0.e0
181         bfrva(:,:) = 0.e0
182         !
[3]183      CASE( 1 )
[1708]184         IF(lwp) WRITE(numout,*) '      linear botton friction'
185         IF(lwp) WRITE(numout,*) '      friction coef.   rn_bfri1  = ', rn_bfri1
186         IF( ln_bfr2d ) THEN
187            IF(lwp) WRITE(numout,*) '      read coef. enhancement distribution from file   ln_bfr2d  = ', ln_bfr2d
188            IF(lwp) WRITE(numout,*) '      coef rn_bfri2 enhancement factor                rn_bfrien  = ',rn_bfrien
[1662]189         ENDIF
[1601]190         !
[1662]191         bfrcoef2d(:,:) = rn_bfri1  ! initialize bfrcoef2d to the namelist variable
[1708]192         !
193         IF(ln_bfr2d) THEN 
[1662]194            ! bfr_coef is a coefficient in [0,1] giving the mask where to apply the bfr enhancement
195            CALL iom_open('bfr_coef.nc',inum)
196            CALL iom_get (inum, jpdom_data, 'bfr_coef',bfrcoef2d,1) ! bfrcoef2d is used as tmp array
197            CALL iom_close(inum)
[1708]198            bfrcoef2d(:,:)= rn_bfri1 * ( 1 + rn_bfrien * bfrcoef2d(:,:) )
[1662]199         ENDIF
200         bfrua(:,:) = - bfrcoef2d(:,:)
201         bfrva(:,:) = - bfrcoef2d(:,:)
202         !
[3]203      CASE( 2 )
[1708]204         IF(lwp) WRITE(numout,*) '      quadratic botton friction'
205         IF(lwp) WRITE(numout,*) '      friction coef.   rn_bfri2  = ', rn_bfri2
206         IF(lwp) WRITE(numout,*) '      background tke   rn_bfeb2  = ', rn_bfeb2
207         IF( ln_bfr2d ) THEN
208            IF(lwp) WRITE(numout,*) '      read coef. enhancement distribution from file   ln_bfr2d  = ', ln_bfr2d
209            IF(lwp) WRITE(numout,*) '      coef rn_bfri2 enhancement factor                rn_bfrien  = ',rn_bfrien
[1662]210         ENDIF
211         bfrcoef2d(:,:) = rn_bfri2  ! initialize bfrcoef2d to the namelist variable
[1708]212         !
213         IF(ln_bfr2d) THEN 
[1662]214            ! bfr_coef is a coefficient in [0,1] giving the mask where to apply the bfr enhancement
215            CALL iom_open('bfr_coef.nc',inum)
216            CALL iom_get (inum, jpdom_data, 'bfr_coef',bfrcoef2d,1) ! bfrcoef2d is used as tmp array
217            CALL iom_close(inum)
[1708]218            bfrcoef2d(:,:)= rn_bfri2 * ( 1 + rn_bfrien * bfrcoef2d(:,:) )
[1662]219         ENDIF
[1601]220         !
[3]221      CASE DEFAULT
[1708]222         IF(lwp) WRITE(ctmp1,*) '         bad flag value for nn_bfr = ', nn_bfr
[474]223         CALL ctl_stop( ctmp1 )
[1601]224         !
[3]225      END SELECT
[1601]226      !
[1662]227      ! Basic stability check on bottom friction coefficient
228      !
229      ictu = 0               ! counter for stability criterion breaches at U-pts
230      ictv = 0               ! counter for stability criterion breaches at V-pts
[1708]231      zminbfr =  1.e10_wp    ! initialise tracker for minimum of bottom friction coefficient
232      zmaxbfr = -1.e10_wp    ! initialise tracker for maximum of bottom friction coefficient
[1662]233      !
234#  if defined key_vectopt_loop
235      DO jj = 1, 1
236!CDIR NOVERRCHK
237         DO ji = jpi+2, jpij-jpi-1   ! vector opt. (forced unrolling)
238#  else
239!CDIR NOVERRCHK
240      DO jj = 2, jpjm1
241!CDIR NOVERRCHK
242         DO ji = 2, jpim1
243#  endif
[1708]244             ikbu = MIN( mbathy(ji+1,jj  ), mbathy(ji,jj) )
245             ikbv = MIN( mbathy(ji  ,jj+1), mbathy(ji,jj) )
246             zfru = 0.5 * fse3u(ji,jj,ikbu) / rdt
247             zfrv = 0.5 * fse3v(ji,jj,ikbv) / rdt
248             IF( ABS( bfrcoef2d(ji,jj) ) > zfru ) THEN
249                IF( ln_ctl ) THEN
250                   WRITE(numout,*) 'BFR ',narea,nimpp+ji,njmpp+jj,ikbu
251                   WRITE(numout,*) 'BFR ',ABS( bfrcoef2d(ji,jj) ), zfru
[1662]252                ENDIF
253                ictu = ictu + 1
254             ENDIF
[1708]255             IF( ABS( bfrcoef2d(ji,jj) ) > zfrv ) THEN
256                 IF( ln_ctl ) THEN
257                     WRITE(numout,*) 'BFR ', narea, nimpp+ji, njmpp+jj, ikbv
258                     WRITE(numout,*) 'BFR ', bfrcoef2d(ji,jj), zfrv
[1662]259                 ENDIF
260                 ictv = ictv + 1
261             ENDIF
[1708]262             zminbfr = MIN(  zminbfr, MIN( zfru, ABS( bfrcoef2d(ji,jj) ) )  )
263             zmaxbfr = MAX(  zmaxbfr, MIN( zfrv, ABS( bfrcoef2d(ji,jj) ) )  )
[1662]264         END DO
265      END DO
[1708]266      IF( lk_mpp ) THEN
[1662]267         CALL mpp_sum( ictu )
268         CALL mpp_sum( ictv )
[1708]269         CALL mpp_min( zminbfr )
270         CALL mpp_max( zmaxbfr )
[1662]271      ENDIF
[1708]272      IF( lwp .AND. ictu + ictv .GT. 0 ) THEN
[1662]273         WRITE(numout,*) ' Bottom friction stability check failed at ', ictu, ' U-points '
274         WRITE(numout,*) ' Bottom friction stability check failed at ', ictv, ' V-points '
[1708]275         WRITE(numout,*) ' Bottom friction coefficient now ranges from: ', zminbfr, ' to ', zmaxbfr
276         WRITE(numout,*) ' Bottom friction coefficient will be reduced where necessary'
[1662]277      ENDIF
278      !
[3]279   END SUBROUTINE zdf_bfr_init
280
281   !!======================================================================
282END MODULE zdfbfr
Note: See TracBrowser for help on using the repository browser.