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

source: branches/dev_r2586_dynamic_mem/NEMOGCM/NEMO/OPA_SRC/ZDF/zdfbfr.F90 @ 2590

Last change on this file since 2590 was 2590, checked in by trackstand2, 13 years ago

Merge branch 'dynamic_memory' into master-svn-dyn

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