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 trunk/NEMOGCM/NEMO/OPA_SRC/ZDF – NEMO

source: trunk/NEMOGCM/NEMO/OPA_SRC/ZDF/zdfbfr.F90 @ 3294

Last change on this file since 3294 was 3294, checked in by rblod, 12 years ago

Merge of 3.4beta into the trunk

  • Property svn:keywords set to Id
File size: 13.6 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
[2528]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.
[2528]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
[3294]24   USE timing          ! Timing
[3]25
26   IMPLICIT NONE
27   PRIVATE
28
[2528]29   PUBLIC   zdf_bfr         ! called by step.F90
30   PUBLIC   zdf_bfr_init    ! called by opa.F90
[2715]31
[1708]32   !                                    !!* Namelist nambfr: bottom friction namelist *
33   INTEGER  ::   nn_bfr    = 0           ! = 0/1/2/3 type of bottom friction
34   REAL(wp) ::   rn_bfri1  = 4.0e-4_wp   ! bottom drag coefficient (linear case)
35   REAL(wp) ::   rn_bfri2  = 1.0e-3_wp   ! bottom drag coefficient (non linear case)
36   REAL(wp) ::   rn_bfeb2  = 2.5e-3_wp   ! background bottom turbulent kinetic energy  [m2/s2]
[2528]37   REAL(wp) ::   rn_bfrien = 30._wp      ! local factor to enhance coefficient bfri
[1708]38   LOGICAL  ::   ln_bfr2d  = .false.     ! logical switch for 2D enhancement
[3294]39   LOGICAL , PUBLIC                            ::  ln_bfrimp = .false.  ! logical switch for implicit bottom friction
40   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) ::  bfrcoef2d            ! 2D bottom drag coefficient
[3]41
42   !! * Substitutions
[2528]43#  include "vectopt_loop_substitute.h90"
[3]44#  include "domzgr_substitute.h90"
45   !!----------------------------------------------------------------------
[2715]46   !! NEMO/OPA 4.0 , NEMO Consortium (2011)
[2528]47   !! $Id$
48   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
[3]49   !!----------------------------------------------------------------------
50CONTAINS
51
[2715]52   INTEGER FUNCTION zdf_bfr_alloc()
53      !!----------------------------------------------------------------------
54      !!                ***  FUNCTION zdf_bfr_alloc  ***
55      !!----------------------------------------------------------------------
56      ALLOCATE( bfrcoef2d(jpi,jpj), STAT=zdf_bfr_alloc )
57      !
58      IF( lk_mpp             )   CALL mpp_sum ( zdf_bfr_alloc )
59      IF( zdf_bfr_alloc /= 0 )   CALL ctl_warn('zdf_bfr_alloc: failed to allocate arrays.')
60   END FUNCTION zdf_bfr_alloc
61
62
[3]63   SUBROUTINE zdf_bfr( kt )
64      !!----------------------------------------------------------------------
65      !!                   ***  ROUTINE zdf_bfr  ***
66      !!                 
[1708]67      !! ** Purpose :   compute the bottom friction coefficient.
[3]68      !!
[1662]69      !! ** Method  :   Calculate and store part of the momentum trend due   
70      !!              to bottom friction following the chosen friction type
71      !!              (free-slip, linear, or quadratic). The component
72      !!              calculated here is multiplied by the bottom velocity in
73      !!              dyn_bfr to provide the trend term.
[1708]74      !!                The coefficients are updated at each time step only
75      !!              in the quadratic case.
[1662]76      !!
77      !! ** Action  :   bfrua , bfrva   bottom friction coefficients
[3]78      !!----------------------------------------------------------------------
79      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
[1601]80      !!
[2528]81      INTEGER  ::   ji, jj       ! dummy loop indices
82      INTEGER  ::   ikbu, ikbv   ! local integers
[1662]83      REAL(wp) ::   zvu, zuv, zecu, zecv   ! temporary scalars
[3]84      !!----------------------------------------------------------------------
[3294]85      !
86      IF( nn_timing == 1 )  CALL timing_start('zdf_bfr')
87      !
[1662]88      IF( nn_bfr == 2 ) THEN                 ! quadratic botton friction
[1708]89         ! Calculate and store the quadratic bottom friction coefficient bfrua and bfrva
[1662]90         ! where bfrUa = C_d*SQRT(u_bot^2 + v_bot^2 + e_b) {U=[u,v]}
91         ! from these the trend due to bottom friction:  -F_h/e3U  can be calculated
92         ! where -F_h/e3U_bot = bfrUa*Ub/e3U_bot {U=[u,v]}
93         !
[789]94# if defined key_vectopt_loop
[1601]95         DO jj = 1, 1
[3]96!CDIR NOVERRCHK
[1601]97            DO ji = jpi+2, jpij-jpi-1   ! vector opt. (forced unrolling)
[3]98# else
99!CDIR NOVERRCHK
100         DO jj = 2, jpjm1
101!CDIR NOVERRCHK
102            DO ji = 2, jpim1
103# endif
[2528]104               ikbu = mbku(ji,jj)         ! ocean bottom level at u- and v-points
105               ikbv = mbkv(ji,jj)         ! (deepest ocean u- and v-points)
[1662]106               !
[2528]107               zvu  = 0.25 * (  vn(ji,jj  ,ikbu) + vn(ji+1,jj  ,ikbu)     &
108                  &           + vn(ji,jj-1,ikbu) + vn(ji+1,jj-1,ikbu)  )
109               zuv  = 0.25 * (  un(ji,jj  ,ikbv) + un(ji-1,jj  ,ikbv)     &
110                  &           + un(ji,jj+1,ikbv) + un(ji-1,jj+1,ikbv)  )
[1662]111               !
[2528]112               zecu = SQRT(  un(ji,jj,ikbu) * un(ji,jj,ikbu) + zvu*zvu + rn_bfeb2  )
113               zecv = SQRT(  vn(ji,jj,ikbv) * vn(ji,jj,ikbv) + zuv*zuv + rn_bfeb2  )
[1662]114               !
[2528]115               bfrua(ji,jj) = - 0.5_wp * ( bfrcoef2d(ji,jj) + bfrcoef2d(ji+1,jj  ) ) * zecu 
116               bfrva(ji,jj) = - 0.5_wp * ( bfrcoef2d(ji,jj) + bfrcoef2d(ji  ,jj+1) ) * zecv
[3]117            END DO
118         END DO
[1601]119         !
[1708]120         CALL lbc_lnk( bfrua, 'U', 1. )   ;   CALL lbc_lnk( bfrva, 'V', 1. )      ! Lateral boundary condition
121         !
122         IF(ln_ctl)   CALL prt_ctl( tab2d_1=bfrua, clinfo1=' bfr  - u: ', mask1=umask,        &
123            &                       tab2d_2=bfrva, clinfo2=       ' v: ', mask2=vmask,ovlap=1 )
[1662]124      ENDIF
[3294]125
[1662]126      !
[3294]127      IF( nn_timing == 1 )  CALL timing_stop('zdf_bfr')
128      !
[3]129   END SUBROUTINE zdf_bfr
130
131
132   SUBROUTINE zdf_bfr_init
133      !!----------------------------------------------------------------------
134      !!                  ***  ROUTINE zdf_bfr_init  ***
135      !!                   
136      !! ** Purpose :   Initialization of the bottom friction
137      !!
138      !! ** Method  :   Read the nammbf namelist and check their consistency
[1662]139      !!              called at the first timestep (nit000)
[3]140      !!----------------------------------------------------------------------
[1662]141      USE iom   ! I/O module for ehanced bottom friction file
142      !!
[2528]143      INTEGER ::   inum         ! logical unit for enhanced bottom friction file
144      INTEGER ::   ji, jj       ! dummy loop indexes
145      INTEGER ::   ikbu, ikbv   ! temporary integers
146      INTEGER ::   ictu, ictv   !    -          -
147      REAL(wp) ::  zminbfr, zmaxbfr   ! temporary scalars
148      REAL(wp) ::  zfru, zfrv         !    -         -
[1708]149      !!
[3294]150      NAMELIST/nambfr/ nn_bfr, rn_bfri1, rn_bfri2, rn_bfeb2, ln_bfr2d, rn_bfrien, ln_bfrimp
[3]151      !!----------------------------------------------------------------------
[3294]152      !
153      IF( nn_timing == 1 )  CALL timing_start('zdf_bfr_init')
154      !
[1662]155      REWIND ( numnam )               !* Read Namelist nam_bfr : bottom momentum boundary condition
156      READ   ( numnam, nambfr )
[3]157
[1662]158      !                               !* Parameter control and print
159      IF(lwp) WRITE(numout,*)
[3]160      IF(lwp) WRITE(numout,*) 'zdf_bfr : momentum bottom friction'
161      IF(lwp) WRITE(numout,*) '~~~~~~~'
[1708]162      IF(lwp) WRITE(numout,*) '   Namelist nam_bfr : set bottom friction parameters'
[3]163
[2715]164      !                              ! allocate zdfbfr arrays
165      IF( zdf_bfr_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'zdf_bfr_init : unable to allocate arrays' )
166
[3294]167      !                              ! Make sure ln_zdfexp=.false. when use implicit bfr
168      IF( ln_bfrimp .AND. ln_zdfexp ) THEN
169         IF(lwp) THEN
170            WRITE(numout,*)
171            WRITE(numout,*) 'Implicit bottom friction can only be used when ln_zdfexp=.false.'
172            WRITE(numout,*) '         but you set: ln_bfrimp=.true. and ln_zdfexp=.true.!!!!'
173            WRITE(ctmp1,*)  '         set either ln_zdfexp = .false or ln_bfrimp = .false.'
174            CALL ctl_stop( ctmp1 )
175         END IF
176      END IF
177
[1662]178      SELECT CASE (nn_bfr)
[2715]179      !
[3]180      CASE( 0 )
[1708]181         IF(lwp) WRITE(numout,*) '      free-slip '
[1662]182         bfrua(:,:) = 0.e0
183         bfrva(:,:) = 0.e0
184         !
[3]185      CASE( 1 )
[1708]186         IF(lwp) WRITE(numout,*) '      linear botton friction'
187         IF(lwp) WRITE(numout,*) '      friction coef.   rn_bfri1  = ', rn_bfri1
188         IF( ln_bfr2d ) THEN
189            IF(lwp) WRITE(numout,*) '      read coef. enhancement distribution from file   ln_bfr2d  = ', ln_bfr2d
190            IF(lwp) WRITE(numout,*) '      coef rn_bfri2 enhancement factor                rn_bfrien  = ',rn_bfrien
[1662]191         ENDIF
[1601]192         !
[1662]193         bfrcoef2d(:,:) = rn_bfri1  ! initialize bfrcoef2d to the namelist variable
[1708]194         !
195         IF(ln_bfr2d) THEN 
[1662]196            ! bfr_coef is a coefficient in [0,1] giving the mask where to apply the bfr enhancement
197            CALL iom_open('bfr_coef.nc',inum)
198            CALL iom_get (inum, jpdom_data, 'bfr_coef',bfrcoef2d,1) ! bfrcoef2d is used as tmp array
199            CALL iom_close(inum)
[2715]200            bfrcoef2d(:,:) = rn_bfri1 * ( 1 + rn_bfrien * bfrcoef2d(:,:) )
[1662]201         ENDIF
202         bfrua(:,:) = - bfrcoef2d(:,:)
203         bfrva(:,:) = - bfrcoef2d(:,:)
204         !
[3]205      CASE( 2 )
[1708]206         IF(lwp) WRITE(numout,*) '      quadratic botton friction'
207         IF(lwp) WRITE(numout,*) '      friction coef.   rn_bfri2  = ', rn_bfri2
208         IF(lwp) WRITE(numout,*) '      background tke   rn_bfeb2  = ', rn_bfeb2
209         IF( ln_bfr2d ) THEN
210            IF(lwp) WRITE(numout,*) '      read coef. enhancement distribution from file   ln_bfr2d  = ', ln_bfr2d
211            IF(lwp) WRITE(numout,*) '      coef rn_bfri2 enhancement factor                rn_bfrien  = ',rn_bfrien
[1662]212         ENDIF
213         bfrcoef2d(:,:) = rn_bfri2  ! initialize bfrcoef2d to the namelist variable
[1708]214         !
215         IF(ln_bfr2d) THEN 
[1662]216            ! bfr_coef is a coefficient in [0,1] giving the mask where to apply the bfr enhancement
217            CALL iom_open('bfr_coef.nc',inum)
218            CALL iom_get (inum, jpdom_data, 'bfr_coef',bfrcoef2d,1) ! bfrcoef2d is used as tmp array
219            CALL iom_close(inum)
[1708]220            bfrcoef2d(:,:)= rn_bfri2 * ( 1 + rn_bfrien * bfrcoef2d(:,:) )
[1662]221         ENDIF
[1601]222         !
[3]223      CASE DEFAULT
[1708]224         IF(lwp) WRITE(ctmp1,*) '         bad flag value for nn_bfr = ', nn_bfr
[474]225         CALL ctl_stop( ctmp1 )
[1601]226         !
[3]227      END SELECT
[3294]228      IF(lwp) WRITE(numout,*) '      implicit bottom friction switch                ln_bfrimp  = ', ln_bfrimp
[1601]229      !
[1662]230      ! Basic stability check on bottom friction coefficient
231      !
232      ictu = 0               ! counter for stability criterion breaches at U-pts
233      ictv = 0               ! counter for stability criterion breaches at V-pts
[1708]234      zminbfr =  1.e10_wp    ! initialise tracker for minimum of bottom friction coefficient
235      zmaxbfr = -1.e10_wp    ! initialise tracker for maximum of bottom friction coefficient
[1662]236      !
237#  if defined key_vectopt_loop
238      DO jj = 1, 1
239!CDIR NOVERRCHK
240         DO ji = jpi+2, jpij-jpi-1   ! vector opt. (forced unrolling)
241#  else
242!CDIR NOVERRCHK
243      DO jj = 2, jpjm1
244!CDIR NOVERRCHK
245         DO ji = 2, jpim1
246#  endif
[2528]247             ikbu = mbku(ji,jj)       ! deepest ocean level at u- and v-points
248             ikbv = mbkv(ji,jj)
249             zfru = 0.5 * fse3u(ji,jj,ikbu) / rdt
250             zfrv = 0.5 * fse3v(ji,jj,ikbv) / rdt
[1708]251             IF( ABS( bfrcoef2d(ji,jj) ) > zfru ) THEN
252                IF( ln_ctl ) THEN
[2528]253                   WRITE(numout,*) 'BFR ', narea, nimpp+ji, njmpp+jj, ikbu
254                   WRITE(numout,*) 'BFR ', ABS( bfrcoef2d(ji,jj) ), zfru
[1662]255                ENDIF
256                ictu = ictu + 1
257             ENDIF
[1708]258             IF( ABS( bfrcoef2d(ji,jj) ) > zfrv ) THEN
259                 IF( ln_ctl ) THEN
260                     WRITE(numout,*) 'BFR ', narea, nimpp+ji, njmpp+jj, ikbv
261                     WRITE(numout,*) 'BFR ', bfrcoef2d(ji,jj), zfrv
[1662]262                 ENDIF
263                 ictv = ictv + 1
264             ENDIF
[1708]265             zminbfr = MIN(  zminbfr, MIN( zfru, ABS( bfrcoef2d(ji,jj) ) )  )
266             zmaxbfr = MAX(  zmaxbfr, MIN( zfrv, ABS( bfrcoef2d(ji,jj) ) )  )
[1662]267         END DO
268      END DO
[1708]269      IF( lk_mpp ) THEN
[1662]270         CALL mpp_sum( ictu )
271         CALL mpp_sum( ictv )
[1708]272         CALL mpp_min( zminbfr )
273         CALL mpp_max( zmaxbfr )
[1662]274      ENDIF
[3294]275      IF( .NOT.ln_bfrimp) THEN
[2528]276      IF( lwp .AND. ictu + ictv > 0 ) THEN
[1662]277         WRITE(numout,*) ' Bottom friction stability check failed at ', ictu, ' U-points '
278         WRITE(numout,*) ' Bottom friction stability check failed at ', ictv, ' V-points '
[1708]279         WRITE(numout,*) ' Bottom friction coefficient now ranges from: ', zminbfr, ' to ', zmaxbfr
280         WRITE(numout,*) ' Bottom friction coefficient will be reduced where necessary'
[1662]281      ENDIF
[3294]282      ENDIF
[1662]283      !
[3294]284      IF( nn_timing == 1 )  CALL timing_stop('zdf_bfr_init')
285      !
[3]286   END SUBROUTINE zdf_bfr_init
287
288   !!======================================================================
289END MODULE zdfbfr
Note: See TracBrowser for help on using the repository browser.