source: branches/UKMO/dev_r5518_STOPACK/NEMOGCM/NEMO/OPA_SRC/ZDF/zdfbfr.F90 @ 11384

Last change on this file since 11384 was 11384, checked in by mattmartin, 2 years ago

Included Andrea Storto's STOPACK code into NEMO3.6 branch.

  • Property svn:keywords set to Id
File size: 25.2 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   !!            3.3  ! 2010-10  (C. Ethe, G. Madec) reorganisation of initialisation phase
10   !!            3.4  ! 2011-11  (H. Liu) implementation of semi-implicit bottom friction option
11   !!                 ! 2012-06  (H. Liu) implementation of Log Layer bottom friction option
12   !!----------------------------------------------------------------------
13
14   !!----------------------------------------------------------------------
15   !!   zdf_bfr      : update bottom friction coefficient (non-linear bottom friction only)
16   !!   zdf_bfr_init : read in namelist and control the bottom friction parameters.
17   !!----------------------------------------------------------------------
18   USE oce             ! ocean dynamics and tracers variables
19   USE dom_oce         ! ocean space and time domain variables
20   USE zdf_oce         ! ocean vertical physics variables
21   USE in_out_manager  ! I/O manager
22   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
23   USE lib_mpp         ! distributed memory computing
24   USE prtctl          ! Print control
25   USE timing          ! Timing
26   USE wrk_nemo        ! Memory Allocation
27   USE phycst, ONLY: vkarmn
28   USE stopack
29
30   IMPLICIT NONE
31   PRIVATE
32
33   PUBLIC   zdf_bfr         ! called by step.F90
34   PUBLIC   zdf_bfr_init    ! called by nemogcm.F90
35
36   !                                 !!* Namelist nambfr: bottom friction namelist *
37   INTEGER , PUBLIC ::   nn_bfr       ! = 0/1/2/3 type of bottom friction  (PUBLIC for TAM)
38   REAL(wp), PUBLIC ::   rn_bfri1     ! bottom drag coefficient (linear case)  (PUBLIC for TAM)
39   REAL(wp), PUBLIC ::   rn_bfri2     ! bottom drag coefficient (non linear case) (PUBLIC for TAM)
40   REAL(wp), PUBLIC ::   rn_bfri2_max ! Maximum bottom drag coefficient (non linear case and ln_loglayer=T) (PUBLIC for TAM)
41   REAL(wp), PUBLIC ::   rn_bfeb2     ! background bottom turbulent kinetic energy  [m2/s2] (PUBLIC for TAM)
42   REAL(wp), PUBLIC ::   rn_bfrien    ! local factor to enhance coefficient bfri (PUBLIC for TAM)
43   LOGICAL , PUBLIC ::   ln_bfr2d     ! logical switch for 2D enhancement (PUBLIC for TAM)
44   REAL(wp), PUBLIC ::   rn_tfri1     ! top drag coefficient (linear case)  (PUBLIC for TAM)
45   REAL(wp), PUBLIC ::   rn_tfri2     ! top drag coefficient (non linear case) (PUBLIC for TAM)
46   REAL(wp), PUBLIC ::   rn_tfri2_max ! Maximum top drag coefficient (non linear case and ln_loglayer=T) (PUBLIC for TAM)
47   REAL(wp), PUBLIC ::   rn_tfeb2     ! background top turbulent kinetic energy  [m2/s2] (PUBLIC for TAM)
48   REAL(wp), PUBLIC ::   rn_tfrien    ! local factor to enhance coefficient tfri (PUBLIC for TAM)
49   LOGICAL , PUBLIC ::   ln_tfr2d     ! logical switch for 2D enhancement (PUBLIC for TAM)
50
51   LOGICAL , PUBLIC ::   ln_loglayer  ! switch for log layer bfr coeff. (PUBLIC for TAM)
52   REAL(wp), PUBLIC ::   rn_bfrz0     ! bottom roughness for loglayer bfr coeff (PUBLIC for TAM)
53   REAL(wp), PUBLIC ::   rn_tfrz0     ! bottom roughness for loglayer bfr coeff (PUBLIC for TAM)
54   LOGICAL , PUBLIC ::   ln_bfrimp    ! logical switch for implicit bottom friction
55   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:), PUBLIC ::  bfrcoef2d, tfrcoef2d,bfrcoef2d0   ! 2D bottom/top drag coefficient (PUBLIC for TAM)
56
57   !! * Substitutions
58#  include "vectopt_loop_substitute.h90"
59#  include "domzgr_substitute.h90"
60   !!----------------------------------------------------------------------
61   !! NEMO/OPA 4.0 , NEMO Consortium (2011)
62   !! $Id$
63   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
64   !!----------------------------------------------------------------------
65CONTAINS
66
67   INTEGER FUNCTION zdf_bfr_alloc()
68      !!----------------------------------------------------------------------
69      !!                ***  FUNCTION zdf_bfr_alloc  ***
70      !!----------------------------------------------------------------------
71      ALLOCATE( bfrcoef2d(jpi,jpj), tfrcoef2d(jpi,jpj), bfrcoef2d0(jpi,jpj),STAT=zdf_bfr_alloc )
72      !
73      IF( lk_mpp             )   CALL mpp_sum ( zdf_bfr_alloc )
74      IF( zdf_bfr_alloc /= 0 )   CALL ctl_warn('zdf_bfr_alloc: failed to allocate arrays.')
75   END FUNCTION zdf_bfr_alloc
76
77
78   SUBROUTINE zdf_bfr( kt )
79      !!----------------------------------------------------------------------
80      !!                   ***  ROUTINE zdf_bfr  ***
81      !!
82      !! ** Purpose :   compute the bottom friction coefficient.
83      !!
84      !! ** Method  :   Calculate and store part of the momentum trend due
85      !!              to bottom friction following the chosen friction type
86      !!              (free-slip, linear, or quadratic). The component
87      !!              calculated here is multiplied by the bottom velocity in
88      !!              dyn_bfr to provide the trend term.
89      !!                The coefficients are updated at each time step only
90      !!              in the quadratic case.
91      !!
92      !! ** Action  :   bfrua , bfrva   bottom friction coefficients
93      !!----------------------------------------------------------------------
94      INTEGER, INTENT( in ) ::   kt   ! ocean time-step index
95      !!
96      INTEGER  ::   ji, jj                       ! dummy loop indices
97      INTEGER  ::   ikbt, ikbu, ikbv             ! local integers
98      REAL(wp) ::   zvu, zuv, zecu, zecv, ztmp   ! temporary scalars
99      REAL(wp), POINTER, DIMENSION(:,:) ::  zbfrt, ztfrt
100      !!----------------------------------------------------------------------
101      !
102      IF( nn_timing == 1 )  CALL timing_start('zdf_bfr')
103      !
104      IF( kt == nit000 .AND. lwp ) THEN
105         WRITE(numout,*)
106         WRITE(numout,*) 'zdf_bfr : Set bottom friction coefficient (non-linear case)'
107         WRITE(numout,*) '~~~~~~~~'
108      ENDIF
109      !
110      IF( nn_spp_bfr > 0 ) THEN
111         bfrcoef2d = bfrcoef2d0
112         CALL spp_gen(kt, bfrcoef2d, nn_spp_bfr, rn_bfr_sd, jk_spp_bfr)
113      ENDIF
114      !
115      IF( nn_bfr == 2 ) THEN                 ! quadratic bottom friction only
116         !
117         CALL wrk_alloc( jpi, jpj, zbfrt, ztfrt )
118
119         IF ( ln_loglayer.AND.lk_vvl ) THEN ! "log layer" bottom friction coefficient
120
121            DO jj = 1, jpj
122               DO ji = 1, jpi
123                  ikbt = mbkt(ji,jj)
124!! JC: possible WAD implementation should modify line below if layers vanish
125                  ztmp = tmask(ji,jj,ikbt) * ( vkarmn / LOG( 0.5_wp * fse3t_n(ji,jj,ikbt) / rn_bfrz0 ))**2._wp
126                  zbfrt(ji,jj) = MAX(bfrcoef2d(ji,jj), ztmp)
127                  zbfrt(ji,jj) = MIN(zbfrt(ji,jj), rn_bfri2_max)
128               END DO
129            END DO
130! (ISF)
131            IF ( ln_isfcav ) THEN
132               DO jj = 1, jpj
133                  DO ji = 1, jpi
134                     ikbt = mikt(ji,jj)
135! JC: possible WAD implementation should modify line below if layers vanish
136                     ztmp = (1-tmask(ji,jj,1)) * ( vkarmn / LOG( 0.5_wp * fse3t_n(ji,jj,ikbt) / rn_bfrz0 ))**2._wp
137                     ztfrt(ji,jj) = MAX(tfrcoef2d(ji,jj), ztmp)
138                     ztfrt(ji,jj) = MIN(ztfrt(ji,jj), rn_tfri2_max)
139                  END DO
140               END DO
141            END IF
142         !   
143         ELSE
144            zbfrt(:,:) = bfrcoef2d(:,:)
145            ztfrt(:,:) = tfrcoef2d(:,:)
146         ENDIF
147
148         DO jj = 2, jpjm1
149            DO ji = 2, jpim1
150               ikbu = mbku(ji,jj)         ! ocean bottom level at u- and v-points
151               ikbv = mbkv(ji,jj)         ! (deepest ocean u- and v-points)
152               !
153               zvu  = 0.25 * (  vn(ji,jj  ,ikbu) + vn(ji+1,jj  ,ikbu)     &
154                  &           + vn(ji,jj-1,ikbu) + vn(ji+1,jj-1,ikbu)  )
155               zuv  = 0.25 * (  un(ji,jj  ,ikbv) + un(ji-1,jj  ,ikbv)     &
156                  &           + un(ji,jj+1,ikbv) + un(ji-1,jj+1,ikbv)  )
157               !
158               zecu = SQRT(  un(ji,jj,ikbu) * un(ji,jj,ikbu) + zvu*zvu + rn_bfeb2  )
159               zecv = SQRT(  vn(ji,jj,ikbv) * vn(ji,jj,ikbv) + zuv*zuv + rn_bfeb2  )
160               !
161               bfrua(ji,jj) = - 0.5_wp * ( zbfrt(ji,jj) + zbfrt(ji+1,jj  ) ) * zecu
162               bfrva(ji,jj) = - 0.5_wp * ( zbfrt(ji,jj) + zbfrt(ji  ,jj+1) ) * zecv
163               !
164               ! in case of 2 cell water column, we assume each cell feels the top and bottom friction
165               IF ( ln_isfcav ) THEN
166                  IF ( miku(ji,jj) + 1 .GE. mbku(ji,jj) ) THEN
167                     bfrua(ji,jj) = - 0.5_wp * ( ( zbfrt(ji,jj) + zbfrt(ji+1,jj  ) )   &
168                                  &            + ( ztfrt(ji,jj) + ztfrt(ji+1,jj  ) ) ) &
169                                  &          * zecu * (1._wp - umask(ji,jj,1))
170                  END IF
171                  IF ( mikv(ji,jj) + 1 .GE. mbkv(ji,jj) ) THEN
172                     bfrva(ji,jj) = - 0.5_wp * ( ( zbfrt(ji,jj) + zbfrt(ji  ,jj+1) )   &
173                                  &            + ( ztfrt(ji,jj) + ztfrt(ji  ,jj+1) ) ) &
174                                  &          * zecv * (1._wp - vmask(ji,jj,1))
175                  END IF
176               END IF
177            END DO
178         END DO
179         CALL lbc_lnk( bfrua, 'U', 1. )   ;   CALL lbc_lnk( bfrva, 'V', 1. )      ! Lateral boundary condition
180
181         IF ( ln_isfcav ) THEN
182            DO jj = 2, jpjm1
183               DO ji = 2, jpim1
184                  ! (ISF) ========================================================================
185                  ikbu = miku(ji,jj)         ! ocean top level at u- and v-points
186                  ikbv = mikv(ji,jj)         ! (1st wet ocean u- and v-points)
187                  !
188                  zvu  = 0.25 * (  vn(ji,jj  ,ikbu) + vn(ji+1,jj  ,ikbu)     &
189                     &           + vn(ji,jj-1,ikbu) + vn(ji+1,jj-1,ikbu)  )
190                  zuv  = 0.25 * (  un(ji,jj  ,ikbv) + un(ji-1,jj  ,ikbv)     &
191                     &           + un(ji,jj+1,ikbv) + un(ji-1,jj+1,ikbv)  )
192              !
193                  zecu = SQRT(  un(ji,jj,ikbu) * un(ji,jj,ikbu) + zvu*zvu + rn_tfeb2 )
194                  zecv = SQRT(  vn(ji,jj,ikbv) * vn(ji,jj,ikbv) + zuv*zuv + rn_tfeb2 )
195              !
196                  tfrua(ji,jj) = - 0.5_wp * ( ztfrt(ji,jj) + ztfrt(ji+1,jj  ) ) * zecu * (1._wp - umask(ji,jj,1))
197                  tfrva(ji,jj) = - 0.5_wp * ( ztfrt(ji,jj) + ztfrt(ji  ,jj+1) ) * zecv * (1._wp - vmask(ji,jj,1))
198              ! (ISF) END ====================================================================
199              ! in case of 2 cell water column, we assume each cell feels the top and bottom friction
200                  IF ( miku(ji,jj) + 1 .GE. mbku(ji,jj) ) THEN
201                     tfrua(ji,jj) = - 0.5_wp * ( ( ztfrt(ji,jj) + ztfrt(ji+1,jj  ) )   &
202                                  &            + ( zbfrt(ji,jj) + zbfrt(ji+1,jj  ) ) ) &
203                                  &          * zecu * (1._wp - umask(ji,jj,1))
204                  END IF
205                  IF ( mikv(ji,jj) + 1 .GE. mbkv(ji,jj) ) THEN
206                     tfrva(ji,jj) = - 0.5_wp * ( ( ztfrt(ji,jj) + ztfrt(ji  ,jj+1) )   &
207                                  &            + ( zbfrt(ji,jj) + zbfrt(ji  ,jj+1) ) ) &
208                                  &          * zecv * (1._wp - vmask(ji,jj,1))
209                  END IF
210               END DO
211            END DO
212            CALL lbc_lnk( tfrua, 'U', 1. )   ;   CALL lbc_lnk( tfrva, 'V', 1. )      ! Lateral boundary condition
213         END IF
214         !
215         !
216         IF(ln_ctl)   CALL prt_ctl( tab2d_1=bfrua, clinfo1=' bfr  - u: ', mask1=umask,        &
217            &                       tab2d_2=bfrva, clinfo2=       ' v: ', mask2=vmask,ovlap=1 )
218         CALL wrk_dealloc( jpi,jpj,zbfrt, ztfrt )
219      ENDIF
220      !
221      IF( nn_timing == 1 )  CALL timing_stop('zdf_bfr')
222      !
223   END SUBROUTINE zdf_bfr
224
225
226   SUBROUTINE zdf_bfr_init
227      !!----------------------------------------------------------------------
228      !!                  ***  ROUTINE zdf_bfr_init  ***
229      !!
230      !! ** Purpose :   Initialization of the bottom friction
231      !!
232      !! ** Method  :   Read the nambfr namelist and check their consistency
233      !!                called at the first timestep (nit000)
234      !!----------------------------------------------------------------------
235      USE iom   ! I/O module for ehanced bottom friction file
236      !!
237      INTEGER   ::   inum         ! logical unit for enhanced bottom friction file
238      INTEGER   ::   ji, jj       ! dummy loop indexes
239      INTEGER   ::   ikbt, ikbu, ikbv   ! temporary integers
240      INTEGER   ::   ictu, ictv         !    -          -
241      INTEGER   ::   ios
242      REAL(wp)  ::   zminbfr, zmaxbfr   ! temporary scalars
243      REAL(wp)  ::   zmintfr, zmaxtfr   ! temporary scalars
244      REAL(wp)  ::   ztmp, zfru, zfrv   !    -         -
245      !!
246      NAMELIST/nambfr/ nn_bfr, rn_bfri1, rn_bfri2, rn_bfri2_max, rn_bfeb2, rn_bfrz0, ln_bfr2d, &
247                    &          rn_tfri1, rn_tfri2, rn_tfri2_max, rn_tfeb2, rn_tfrz0, ln_tfr2d, &
248                    &  rn_bfrien, rn_tfrien, ln_bfrimp, ln_loglayer
249      !!----------------------------------------------------------------------
250      !
251      IF( nn_timing == 1 )  CALL timing_start('zdf_bfr_init')
252      !
253      !                              !* Allocate zdfbfr arrays
254      IF( zdf_bfr_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'zdf_bfr_init : unable to allocate arrays' )
255      !
256      !                              !* Parameter control and print
257      !
258      REWIND( numnam_ref )              ! Namelist nambfr in reference namelist : Bottom momentum boundary condition
259      READ  ( numnam_ref, nambfr, IOSTAT = ios, ERR = 901)
260901   IF( ios /= 0 ) CALL ctl_nam ( ios , 'nambfr in reference namelist', lwp )
261
262      REWIND( numnam_cfg )              ! Namelist nambfr in configuration namelist : Bottom momentum boundary condition
263      READ  ( numnam_cfg, nambfr, IOSTAT = ios, ERR = 902 )
264902   IF( ios /= 0 ) CALL ctl_nam ( ios , 'nambfr in configuration namelist', lwp )
265      IF(lwm) WRITE ( numond, nambfr )
266      IF(lwp) WRITE(numout,*)
267      IF(lwp) WRITE(numout,*) 'zdf_bfr_init : momentum bottom friction'
268      IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~~'
269      IF(lwp) WRITE(numout,*) '   Namelist nam_bfr : set bottom friction parameters'
270      !
271      SELECT CASE (nn_bfr)
272      !
273      CASE( 0 )
274         IF(lwp) WRITE(numout,*) '      free-slip '
275         bfrua(:,:) = 0.e0
276         bfrva(:,:) = 0.e0
277         tfrua(:,:) = 0.e0
278         tfrva(:,:) = 0.e0
279         !
280      CASE( 1 )
281         IF(lwp) WRITE(numout,*) '      linear botton friction'
282         IF(lwp) WRITE(numout,*) '      bottom friction coef.   rn_bfri1  = ', rn_bfri1
283         IF( ln_bfr2d ) THEN
284            IF(lwp) WRITE(numout,*) '      read coef. enhancement distribution from file   ln_bfr2d  = ', ln_bfr2d
285            IF(lwp) WRITE(numout,*) '      coef rn_bfri2 enhancement factor                rn_bfrien  = ',rn_bfrien
286         ENDIF
287         IF ( ln_isfcav ) THEN
288            IF(lwp) WRITE(numout,*) '      top    friction coef.   rn_bfri1  = ', rn_tfri1
289            IF( ln_tfr2d ) THEN
290               IF(lwp) WRITE(numout,*) '      read coef. enhancement distribution from file   ln_tfr2d  = ', ln_tfr2d
291               IF(lwp) WRITE(numout,*) '      coef rn_tfri2 enhancement factor                rn_tfrien  = ',rn_tfrien
292            ENDIF
293         END IF
294         !
295         IF(ln_bfr2d) THEN
296            ! bfr_coef is a coefficient in [0,1] giving the mask where to apply the bfr enhancement
297            CALL iom_open('bfr_coef.nc',inum)
298            CALL iom_get (inum, jpdom_data, 'bfr_coef',bfrcoef2d,1) ! bfrcoef2d is used as tmp array
299            CALL iom_close(inum)
300            bfrcoef2d(:,:) = rn_bfri1 * ( 1 + rn_bfrien * bfrcoef2d(:,:) )
301         ELSE
302            bfrcoef2d(:,:) = rn_bfri1  ! initialize bfrcoef2d to the namelist variable
303         ENDIF
304         !
305         bfrua(:,:) = - bfrcoef2d(:,:)
306         bfrva(:,:) = - bfrcoef2d(:,:)
307         !
308         IF ( ln_isfcav ) THEN
309            IF(ln_tfr2d) THEN
310               ! tfr_coef is a coefficient in [0,1] giving the mask where to apply the bfr enhancement
311               CALL iom_open('tfr_coef.nc',inum)
312               CALL iom_get (inum, jpdom_data, 'tfr_coef',tfrcoef2d,1) ! tfrcoef2d is used as tmp array
313               CALL iom_close(inum)
314               tfrcoef2d(:,:) = rn_tfri1 * ( 1 + rn_tfrien * tfrcoef2d(:,:) )
315            ELSE
316               tfrcoef2d(:,:) = rn_tfri1  ! initialize tfrcoef2d to the namelist variable
317            ENDIF
318            !
319            tfrua(:,:) = - tfrcoef2d(:,:)
320            tfrva(:,:) = - tfrcoef2d(:,:)
321         END IF
322         !
323      CASE( 2 )
324         IF(lwp) WRITE(numout,*) '      quadratic bottom friction'
325         IF(lwp) WRITE(numout,*) '      friction coef.   rn_bfri2  = ', rn_bfri2
326         IF(lwp) WRITE(numout,*) '      Max. coef. (log case)   rn_bfri2_max  = ', rn_bfri2_max
327         IF(lwp) WRITE(numout,*) '      background tke   rn_bfeb2  = ', rn_bfeb2
328         IF(lwp) WRITE(numout,*) '      log formulation   ln_bfr2d = ', ln_loglayer
329         IF(lwp) WRITE(numout,*) '      bottom roughness  rn_bfrz0 [m] = ', rn_bfrz0
330         IF( rn_bfrz0<=0.e0 ) THEN
331            WRITE(ctmp1,*) '      bottom roughness must be strictly positive'
332            CALL ctl_stop( ctmp1 )
333         ENDIF
334         IF( ln_bfr2d ) THEN
335            IF(lwp) WRITE(numout,*) '      read coef. enhancement distribution from file   ln_bfr2d  = ', ln_bfr2d
336            IF(lwp) WRITE(numout,*) '      coef rn_bfri2 enhancement factor                rn_bfrien  = ',rn_bfrien
337         ENDIF
338         IF ( ln_isfcav ) THEN
339            IF(lwp) WRITE(numout,*) '      quadratic top    friction'
340            IF(lwp) WRITE(numout,*) '      friction coef.    rn_tfri2     = ', rn_tfri2
341            IF(lwp) WRITE(numout,*) '      Max. coef. (log case)   rn_tfri2_max  = ', rn_tfri2_max
342            IF(lwp) WRITE(numout,*) '      background tke    rn_tfeb2     = ', rn_tfeb2
343            IF(lwp) WRITE(numout,*) '      log formulation   ln_tfr2d     = ', ln_loglayer
344            IF(lwp) WRITE(numout,*) '      top roughness     rn_tfrz0 [m] = ', rn_tfrz0
345            IF( rn_tfrz0<=0.e0 ) THEN
346               WRITE(ctmp1,*) '      top roughness must be strictly positive'
347               CALL ctl_stop( ctmp1 )
348            ENDIF
349            IF( ln_tfr2d ) THEN
350               IF(lwp) WRITE(numout,*) '      read coef. enhancement distribution from file   ln_tfr2d  = ', ln_tfr2d
351               IF(lwp) WRITE(numout,*) '      coef rn_tfri2 enhancement factor                rn_tfrien  = ',rn_tfrien
352            ENDIF
353         END IF
354         !
355         IF(ln_bfr2d) THEN
356            ! bfr_coef is a coefficient in [0,1] giving the mask where to apply the bfr enhancement
357            CALL iom_open('bfr_coef.nc',inum)
358            CALL iom_get (inum, jpdom_data, 'bfr_coef',bfrcoef2d,1) ! bfrcoef2d is used as tmp array
359            CALL iom_close(inum)
360            !
361            bfrcoef2d(:,:) = rn_bfri2 * ( 1 + rn_bfrien * bfrcoef2d(:,:) )
362         ELSE
363            bfrcoef2d(:,:) = rn_bfri2  ! initialize bfrcoef2d to the namelist variable
364         ENDIF
365         
366         IF ( ln_isfcav ) THEN
367            IF(ln_tfr2d) THEN
368               ! tfr_coef is a coefficient in [0,1] giving the mask where to apply the bfr enhancement
369               CALL iom_open('tfr_coef.nc',inum)
370               CALL iom_get (inum, jpdom_data, 'tfr_coef',tfrcoef2d,1) ! tfrcoef2d is used as tmp array
371               CALL iom_close(inum)
372               !
373               tfrcoef2d(:,:) = rn_tfri2 * ( 1 + rn_tfrien * tfrcoef2d(:,:) )
374            ELSE
375               tfrcoef2d(:,:) = rn_tfri2  ! initialize tfrcoef2d to the namelist variable
376            ENDIF
377         END IF
378         !
379         IF ( ln_loglayer.AND.(.NOT.lk_vvl) ) THEN ! set "log layer" bottom friction once for all
380            DO jj = 1, jpj
381               DO ji = 1, jpi
382                  ikbt = mbkt(ji,jj)
383                  ztmp = tmask(ji,jj,ikbt) * ( vkarmn / LOG( 0.5_wp * fse3t_n(ji,jj,ikbt) / rn_bfrz0 ))**2._wp
384                  bfrcoef2d(ji,jj) = MAX(bfrcoef2d(ji,jj), ztmp)
385                  bfrcoef2d(ji,jj) = MIN(bfrcoef2d(ji,jj), rn_bfri2_max)
386               END DO
387            END DO
388            IF ( ln_isfcav ) THEN
389               DO jj = 1, jpj
390                  DO ji = 1, jpi
391                     ikbt = mikt(ji,jj)
392                     ztmp = tmask(ji,jj,ikbt) * ( vkarmn / LOG( 0.5_wp * fse3t_n(ji,jj,ikbt) / rn_tfrz0 ))**2._wp
393                     tfrcoef2d(ji,jj) = MAX(tfrcoef2d(ji,jj), ztmp)
394                     tfrcoef2d(ji,jj) = MIN(tfrcoef2d(ji,jj), rn_tfri2_max)
395                  END DO
396               END DO
397            END IF
398         ENDIF
399         !
400      CASE DEFAULT
401         IF(lwp) WRITE(ctmp1,*) '         bad flag value for nn_bfr = ', nn_bfr
402         CALL ctl_stop( ctmp1 )
403         !
404      END SELECT
405      !
406      IF(lwp) WRITE(numout,*) '      implicit bottom friction switch                ln_bfrimp  = ', ln_bfrimp
407      !
408      !                              ! Make sure ln_zdfexp=.false. when use implicit bfr
409      IF( ln_bfrimp .AND. ln_zdfexp ) THEN
410         IF(lwp) THEN
411            WRITE(numout,*)
412            WRITE(numout,*) 'Implicit bottom friction can only be used when ln_zdfexp=.false.'
413            WRITE(numout,*) '         but you set: ln_bfrimp=.true. and ln_zdfexp=.true.!!!!'
414            WRITE(ctmp1,*)  '         set either ln_zdfexp = .false or ln_bfrimp = .false.'
415            CALL ctl_stop( ctmp1 )
416         END IF
417      END IF
418      !
419      ! Basic stability check on bottom friction coefficient
420      !
421      ictu = 0               ! counter for stability criterion breaches at U-pts
422      ictv = 0               ! counter for stability criterion breaches at V-pts
423      zminbfr =  1.e10_wp    ! initialise tracker for minimum of bottom friction coefficient
424      zmaxbfr = -1.e10_wp    ! initialise tracker for maximum of bottom friction coefficient
425      zmintfr =  1.e10_wp    ! initialise tracker for minimum of bottom friction coefficient
426      zmaxtfr = -1.e10_wp    ! initialise tracker for maximum of bottom friction coefficient
427      !
428      DO jj = 2, jpjm1
429         DO ji = 2, jpim1
430             ikbu = mbku(ji,jj)       ! deepest ocean level at u- and v-points
431             ikbv = mbkv(ji,jj)
432             zfru = 0.5 * fse3u(ji,jj,ikbu) / rdt
433             zfrv = 0.5 * fse3v(ji,jj,ikbv) / rdt
434             IF( ABS( bfrcoef2d(ji,jj) ) > zfru ) THEN
435                IF( ln_ctl ) THEN
436                   WRITE(numout,*) 'BFR ', narea, nimpp+ji, njmpp+jj, ikbu
437                   WRITE(numout,*) 'BFR ', ABS( bfrcoef2d(ji,jj) ), zfru
438                ENDIF
439                ictu = ictu + 1
440             ENDIF
441             IF( ABS( bfrcoef2d(ji,jj) ) > zfrv ) THEN
442                 IF( ln_ctl ) THEN
443                     WRITE(numout,*) 'BFR ', narea, nimpp+ji, njmpp+jj, ikbv
444                     WRITE(numout,*) 'BFR ', bfrcoef2d(ji,jj), zfrv
445                 ENDIF
446                 ictv = ictv + 1
447             ENDIF
448             zminbfr = MIN(  zminbfr, MIN( zfru, ABS( bfrcoef2d(ji,jj) ) )  )
449             zmaxbfr = MAX(  zmaxbfr, MIN( zfrv, ABS( bfrcoef2d(ji,jj) ) )  )
450! (ISF)
451             IF ( ln_isfcav ) THEN
452                ikbu = miku(ji,jj)       ! 1st wet ocean level at u- and v-points
453                ikbv = mikv(ji,jj)
454                zfru = 0.5 * fse3u(ji,jj,ikbu) / rdt
455                zfrv = 0.5 * fse3v(ji,jj,ikbv) / rdt
456                IF( ABS( tfrcoef2d(ji,jj) ) > zfru ) THEN
457                   IF( ln_ctl ) THEN
458                      WRITE(numout,*) 'TFR ', narea, nimpp+ji, njmpp+jj, ikbu
459                      WRITE(numout,*) 'TFR ', ABS( tfrcoef2d(ji,jj) ), zfru
460                   ENDIF
461                   ictu = ictu + 1
462                ENDIF
463                IF( ABS( tfrcoef2d(ji,jj) ) > zfrv ) THEN
464                   IF( ln_ctl ) THEN
465                      WRITE(numout,*) 'TFR ', narea, nimpp+ji, njmpp+jj, ikbv
466                      WRITE(numout,*) 'TFR ', tfrcoef2d(ji,jj), zfrv
467                   ENDIF
468                   ictv = ictv + 1
469                ENDIF
470                zmintfr = MIN(  zmintfr, MIN( zfru, ABS( tfrcoef2d(ji,jj) ) )  )
471                zmaxtfr = MAX(  zmaxtfr, MIN( zfrv, ABS( tfrcoef2d(ji,jj) ) )  )
472             END IF
473! END ISF
474         END DO
475      END DO
476      IF( lk_mpp ) THEN
477         CALL mpp_sum( ictu )
478         CALL mpp_sum( ictv )
479         CALL mpp_min( zminbfr )
480         CALL mpp_max( zmaxbfr )
481         IF ( ln_isfcav) CALL mpp_min( zmintfr )
482         IF ( ln_isfcav) CALL mpp_max( zmaxtfr )
483      ENDIF
484      IF( .NOT.ln_bfrimp) THEN
485      IF( lwp .AND. ictu + ictv > 0 ) THEN
486         WRITE(numout,*) ' Bottom/Top friction stability check failed at ', ictu, ' U-points '
487         WRITE(numout,*) ' Bottom/Top friction stability check failed at ', ictv, ' V-points '
488         WRITE(numout,*) ' Bottom friction coefficient now ranges from: ', zminbfr, ' to ', zmaxbfr
489         IF ( ln_isfcav ) WRITE(numout,*) ' Top friction coefficient now ranges from: ', zmintfr, ' to ', zmaxtfr
490         WRITE(numout,*) ' Bottom/Top friction coefficient will be reduced where necessary'
491      ENDIF
492      ENDIF
493      !
494      bfrcoef2d0(:,:) = bfrcoef2d(:,:)
495      IF( nn_timing == 1 )  CALL timing_stop('zdf_bfr_init')
496      !
497   END SUBROUTINE zdf_bfr_init
498
499   !!======================================================================
500END MODULE zdfbfr
Note: See TracBrowser for help on using the repository browser.