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 tags/nemo_v3_2/nemo_v3_2/NEMO/OPA_SRC/ZDF – NEMO

source: tags/nemo_v3_2/nemo_v3_2/NEMO/OPA_SRC/ZDF/zdfbfr.F90 @ 1878

Last change on this file since 1878 was 1878, checked in by flavoni, 14 years ago

initial test for nemogcm

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