source: branches/UKMO/dev_r5518_GO6_package_FOAMv14/NEMOGCM/NEMO/OPA_SRC/ZDF/zdftke.F90 @ 11442

Last change on this file since 11442 was 11442, checked in by mattmartin, 18 months ago

Introduction of stochastic physics in NEMO, based on Andrea Storto's code.
For details, see ticket https://code.metoffice.gov.uk/trac/utils/ticket/251.

File size: 53.1 KB
Line 
1MODULE zdftke
2   !!======================================================================
3   !!                       ***  MODULE  zdftke  ***
4   !! Ocean physics:  vertical mixing coefficient computed from the tke
5   !!                 turbulent closure parameterization
6   !!=====================================================================
7   !! History :  OPA  !  1991-03  (b. blanke)  Original code
8   !!            7.0  !  1991-11  (G. Madec)   bug fix
9   !!            7.1  !  1992-10  (G. Madec)   new mixing length and eav
10   !!            7.2  !  1993-03  (M. Guyon)   symetrical conditions
11   !!            7.3  !  1994-08  (G. Madec, M. Imbard)  nn_pdl flag
12   !!            7.5  !  1996-01  (G. Madec)   s-coordinates
13   !!            8.0  !  1997-07  (G. Madec)   lbc
14   !!            8.1  !  1999-01  (E. Stretta) new option for the mixing length
15   !!  NEMO      1.0  !  2002-06  (G. Madec) add tke_init routine
16   !!             -   !  2004-10  (C. Ethe )  1D configuration
17   !!            2.0  !  2006-07  (S. Masson)  distributed restart using iom
18   !!            3.0  !  2008-05  (C. Ethe,  G.Madec) : update TKE physics:
19   !!                 !           - tke penetration (wind steering)
20   !!                 !           - suface condition for tke & mixing length
21   !!                 !           - Langmuir cells
22   !!             -   !  2008-05  (J.-M. Molines, G. Madec)  2D form of avtb
23   !!             -   !  2008-06  (G. Madec)  style + DOCTOR name for namelist parameters
24   !!             -   !  2008-12  (G. Reffray) stable discretization of the production term
25   !!            3.2  !  2009-06  (G. Madec, S. Masson) TKE restart compatible with key_cpl
26   !!                 !                                + cleaning of the parameters + bugs correction
27   !!            3.3  !  2010-10  (C. Ethe, G. Madec) reorganisation of initialisation phase
28   !!            3.6  !  2014-11  (P. Mathiot) add ice shelf capability
29   !!----------------------------------------------------------------------
30#if defined key_zdftke   ||   defined key_esopa
31   !!----------------------------------------------------------------------
32   !!   'key_zdftke'                                   TKE vertical physics
33   !!----------------------------------------------------------------------
34   !!   zdf_tke       : update momentum and tracer Kz from a tke scheme
35   !!   tke_tke       : tke time stepping: update tke at now time step (en)
36   !!   tke_avn       : compute mixing length scale and deduce avm and avt
37   !!   zdf_tke_init  : initialization, namelist read, and parameters control
38   !!   tke_rst       : read/write tke restart in ocean restart file
39   !!----------------------------------------------------------------------
40   USE oce            ! ocean: dynamics and active tracers variables
41   USE phycst         ! physical constants
42   USE dom_oce        ! domain: ocean
43   USE domvvl         ! domain: variable volume layer
44   USE sbc_oce        ! surface boundary condition: ocean
45   USE zdf_oce        ! vertical physics: ocean variables
46   USE zdfmxl         ! vertical physics: mixed layer
47   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
48   USE prtctl         ! Print control
49   USE in_out_manager ! I/O manager
50   USE iom            ! I/O manager library
51   USE lib_mpp        ! MPP library
52   USE wrk_nemo       ! work arrays
53   USE timing         ! Timing
54   USE lib_fortran    ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined) 
55#if defined key_agrif
56   USE agrif_opa_interp
57   USE agrif_opa_update
58#endif
59   USE stopack
60
61   IMPLICIT NONE
62   PRIVATE
63
64   PUBLIC   zdf_tke        ! routine called in step module
65   PUBLIC   zdf_tke_init   ! routine called in opa module
66   PUBLIC   tke_rst        ! routine called in step module
67
68   LOGICAL , PUBLIC, PARAMETER ::   lk_zdftke = .TRUE.  !: TKE vertical mixing flag
69
70   !                      !!** Namelist  namzdf_tke  **
71   LOGICAL  ::   ln_mxl0   ! mixing length scale surface value as function of wind stress or not
72   INTEGER  ::   nn_mxl    ! type of mixing length (=0/1/2/3)
73   REAL(wp) ::   rn_mxl0   ! surface  min value of mixing length (kappa*z_o=0.4*0.1 m)  [m]
74   INTEGER  ::   nn_pdl    ! Prandtl number or not (ratio avt/avm) (=0/1)
75   REAL(wp) ::   rn_ediff  ! coefficient for avt: avt=rn_ediff*mxl*sqrt(e)
76   REAL(wp) ::   rn_ediss  ! coefficient of the Kolmogoroff dissipation
77   REAL(wp) ::   rn_ebb    ! coefficient of the surface input of tke
78   REAL(wp) ::   rn_emin   ! minimum value of tke           [m2/s2]
79   REAL(wp) ::   rn_emin0  ! surface minimum value of tke   [m2/s2]
80   REAL(wp) ::   rn_bshear ! background shear (>0) currently a numerical threshold (do not change it)
81   INTEGER  ::   nn_etau   ! type of depth penetration of surface tke (=0/1/2/3)
82   INTEGER  ::   nn_htau   ! type of tke profile of penetration (=0/1)
83   REAL(wp) ::   rn_efr    ! fraction of TKE surface value which penetrates in the ocean
84   REAL(wp) ::   rn_c      ! fraction of TKE added within the mixed layer by nn_etau
85   LOGICAL  ::   ln_lc     ! Langmuir cells (LC) as a source term of TKE or not
86   REAL(wp) ::   rn_lc     ! coef to compute vertical velocity of Langmuir cells
87
88   REAL(wp) ::   ri_cri    ! critic Richardson number (deduced from rn_ediff and rn_ediss values)
89   REAL(wp) ::   rmxl_min  ! minimum mixing length value (deduced from rn_ediff and rn_emin values)  [m]
90   REAL(wp) ::   rhtau                     ! coefficient to relate MLD to htau when nn_htau == 2
91   REAL(wp) ::   rhftau_add = 1.e-3_wp     ! add offset   applied to HF part of taum  (nn_etau=3)
92   REAL(wp) ::   rhftau_scl = 1.0_wp       ! scale factor applied to HF part of taum  (nn_etau=3)
93
94   REAL(wp)        , ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   htau           ! depth of tke penetration (nn_htau)
95   REAL(wp)        , ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   dissl          ! now mixing lenght of dissipation
96#if defined key_c1d
97   !                                                                        !!** 1D cfg only  **   ('key_c1d')
98   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   e_dis, e_mix   !: dissipation and mixing turbulent lengh scales
99   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   e_pdl, e_ric   !: prandl and local Richardson numbers
100#endif
101   REAL(wp)        , ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   rn_lc0, rn_ediff0, rn_ediss0, rn_ebb0, rn_efr0
102   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   e_niw          !: TKE budget- near-inertial waves term
103   REAL(wp)        , ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   efr            ! surface boundary condition for nn_etau = 4
104   
105   !! * Substitutions
106#  include "domzgr_substitute.h90"
107#  include "vectopt_loop_substitute.h90"
108   !!----------------------------------------------------------------------
109   !! NEMO/OPA 4.0 , NEMO Consortium (2011)
110   !! $Id$
111   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
112   !!----------------------------------------------------------------------
113CONTAINS
114
115   INTEGER FUNCTION zdf_tke_alloc()
116      !!----------------------------------------------------------------------
117      !!                ***  FUNCTION zdf_tke_alloc  ***
118      !!----------------------------------------------------------------------
119      ALLOCATE(                                                                    &
120         &      efr  (jpi,jpj)     , e_niw(jpi,jpj,jpk) ,                         &     
121#if defined key_c1d
122         &      e_dis(jpi,jpj,jpk) , e_mix(jpi,jpj,jpk) ,                          &
123         &      e_pdl(jpi,jpj,jpk) , e_ric(jpi,jpj,jpk) ,                          &
124#endif
125         &      htau  (jpi,jpj)    , dissl(jpi,jpj,jpk) , STAT= zdf_tke_alloc      )
126         !
127      IF( lk_mpp             )   CALL mpp_sum ( zdf_tke_alloc )
128      IF( zdf_tke_alloc /= 0 )   CALL ctl_warn('zdf_tke_alloc: failed to allocate arrays')
129      !
130   END FUNCTION zdf_tke_alloc
131
132
133   SUBROUTINE zdf_tke( kt )
134      !!----------------------------------------------------------------------
135      !!                   ***  ROUTINE zdf_tke  ***
136      !!
137      !! ** Purpose :   Compute the vertical eddy viscosity and diffusivity
138      !!              coefficients using a turbulent closure scheme (TKE).
139      !!
140      !! ** Method  :   The time evolution of the turbulent kinetic energy (tke)
141      !!              is computed from a prognostic equation :
142      !!         d(en)/dt = avm (d(u)/dz)**2             ! shear production
143      !!                  + d( avm d(en)/dz )/dz         ! diffusion of tke
144      !!                  + avt N^2                      ! stratif. destruc.
145      !!                  - rn_ediss / emxl en**(2/3)    ! Kolmogoroff dissipation
146      !!      with the boundary conditions:
147      !!         surface: en = max( rn_emin0, rn_ebb * taum )
148      !!         bottom : en = rn_emin
149      !!      The associated critical Richardson number is: ri_cri = 2/(2+rn_ediss/rn_ediff)
150      !!
151      !!        The now Turbulent kinetic energy is computed using the following
152      !!      time stepping: implicit for vertical diffusion term, linearized semi
153      !!      implicit for kolmogoroff dissipation term, and explicit forward for
154      !!      both buoyancy and shear production terms. Therefore a tridiagonal
155      !!      linear system is solved. Note that buoyancy and shear terms are
156      !!      discretized in a energy conserving form (Bruchard 2002).
157      !!
158      !!        The dissipative and mixing length scale are computed from en and
159      !!      the stratification (see tke_avn)
160      !!
161      !!        The now vertical eddy vicosity and diffusivity coefficients are
162      !!      given by:
163      !!              avm = max( avtb, rn_ediff * zmxlm * en^1/2 )
164      !!              avt = max( avmb, pdl * avm                 ) 
165      !!              eav = max( avmb, avm )
166      !!      where pdl, the inverse of the Prandtl number is 1 if nn_pdl=0 and
167      !!      given by an empirical funtion of the localRichardson number if nn_pdl=1
168      !!
169      !! ** Action  :   compute en (now turbulent kinetic energy)
170      !!                update avt, avmu, avmv (before vertical eddy coef.)
171      !!
172      !! References : Gaspar et al., JGR, 1990,
173      !!              Blanke and Delecluse, JPO, 1991
174      !!              Mellor and Blumberg, JPO 2004
175      !!              Axell, JGR, 2002
176      !!              Bruchard OM 2002
177      !!----------------------------------------------------------------------
178      INTEGER, INTENT(in) ::   kt   ! ocean time step
179      !!----------------------------------------------------------------------
180      !
181      IF( kt /= nit000 ) THEN   ! restore before value to compute tke
182         avt (:,:,:) = avt_k (:,:,:) 
183         avm (:,:,:) = avm_k (:,:,:) 
184         avmu(:,:,:) = avmu_k(:,:,:) 
185         avmv(:,:,:) = avmv_k(:,:,:) 
186      ENDIF
187      !
188      IF( ln_stopack) THEN
189         IF( nn_spp_tkelc > 0 ) THEN
190             rn_lc0 = rn_lc
191             CALL spp_gen( kt, rn_lc0, nn_spp_tkelc, rn_tkelc_sd, jk_spp_tkelc )
192         ENDIF
193         IF( nn_spp_tkedf > 0 ) THEN
194             rn_ediff0 = rn_ediff
195             CALL spp_gen( kt, rn_ediff0, nn_spp_tkedf, rn_tkedf_sd, jk_spp_tkedf )
196         ENDIF
197         IF( nn_spp_tkeds > 0 ) THEN
198             rn_ediss0 = rn_ediss
199             CALL spp_gen( kt, rn_ediss0, nn_spp_tkeds, rn_tkeds_sd, jk_spp_tkeds )
200         ENDIF
201         IF( nn_spp_tkebb > 0 ) THEN
202             rn_ebb0 = rn_ebb
203             CALL spp_gen( kt, rn_ebb0, nn_spp_tkebb, rn_tkebb_sd, jk_spp_tkebb )
204        ENDIF
205         IF( nn_spp_tkefr > 0 ) THEN
206             rn_efr0 = rn_efr
207             CALL spp_gen( kt, rn_efr0, nn_spp_tkefr, rn_tkefr_sd, jk_spp_tkefr )
208         ENDIF
209      ENDIF
210      !
211      CALL tke_tke      ! now tke (en)
212      !
213      CALL tke_avn      ! now avt, avm, avmu, avmv
214      !
215      avt_k (:,:,:) = avt (:,:,:) 
216      avm_k (:,:,:) = avm (:,:,:) 
217      avmu_k(:,:,:) = avmu(:,:,:) 
218      avmv_k(:,:,:) = avmv(:,:,:) 
219      !
220#if defined key_agrif
221      ! Update child grid f => parent grid
222      IF( .NOT.Agrif_Root() )   CALL Agrif_Update_Tke( kt )      ! children only
223#endif     
224      IF (  kt == nitend ) THEN
225        DEALLOCATE ( rn_lc0, rn_ediff0, rn_ediss0, rn_ebb0, rn_efr0 )
226      ENDIF
227      !
228
229   END SUBROUTINE zdf_tke
230
231
232   SUBROUTINE tke_tke
233      !!----------------------------------------------------------------------
234      !!                   ***  ROUTINE tke_tke  ***
235      !!
236      !! ** Purpose :   Compute the now Turbulente Kinetic Energy (TKE)
237      !!
238      !! ** Method  : - TKE surface boundary condition
239      !!              - source term due to Langmuir cells (Axell JGR 2002) (ln_lc=T)
240      !!              - source term due to shear (saved in avmu, avmv arrays)
241      !!              - Now TKE : resolution of the TKE equation by inverting
242      !!                a tridiagonal linear system by a "methode de chasse"
243      !!              - increase TKE due to surface and internal wave breaking
244      !!
245      !! ** Action  : - en : now turbulent kinetic energy)
246      !!              - avmu, avmv : production of TKE by shear at u and v-points
247      !!                (= Kz dz[Ub] * dz[Un] )
248      !! ---------------------------------------------------------------------
249      INTEGER  ::   ji, jj, jk                      ! dummy loop arguments
250!!bfr      INTEGER  ::   ikbu, ikbv, ikbum1, ikbvm1      ! temporary scalar
251!!bfr      INTEGER  ::   ikbt, ikbumm1, ikbvmm1          ! temporary scalar
252      REAL(wp) ::   zrhoa  = 1.22                   ! Air density kg/m3
253      REAL(wp) ::   zcdrag = 1.5e-3                 ! drag coefficient
254      REAL(wp) ::   zesh2                           ! temporary scalars
255      REAL(wp) ::   zfact1                          !    -         -
256      REAL(wp) ::   ztx2  , zty2  , zcof            !    -         -
257      REAL(wp) ::   ztau  , zdif                    !    -         -
258      REAL(wp) ::   zus   , zwlc  , zind            !    -         -
259      REAL(wp) ::   zzd_up, zzd_lw                  !    -         -
260!!bfr      REAL(wp) ::   zebot                           !    -         -
261      INTEGER , POINTER, DIMENSION(:,:  ) :: imlc
262      REAL(wp), POINTER, DIMENSION(:,:  ) :: zhlc, zbbrau,zfact2,zfact3
263      REAL(wp), POINTER, DIMENSION(:,:,:) :: zpelc, zdiag, zd_up, zd_lw
264      !!--------------------------------------------------------------------
265      !
266      IF( nn_timing == 1 )  CALL timing_start('tke_tke')
267      !
268      CALL wrk_alloc( jpi,jpj, imlc )    ! integer
269      CALL wrk_alloc( jpi,jpj, zhlc )
270      CALL wrk_alloc( jpi,jpj, zbbrau )
271      CALL wrk_alloc( jpi,jpj, zfact2 )
272      CALL wrk_alloc( jpi,jpj, zfact3 )
273      CALL wrk_alloc( jpi,jpj,jpk, zpelc, zdiag, zd_up, zd_lw ) 
274      !
275      zbbrau = rn_ebb0 / rau0       ! Local constant initialisation
276      zfact1 = -.5_wp * rdt 
277      zfact2 = 1.5_wp * rdt * rn_ediss0
278      zfact3 = 0.5_wp       * rn_ediss0
279      !
280      !
281      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
282      !                     !  Surface boundary condition on tke
283      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
284      IF ( ln_isfcav ) THEN
285         DO jj = 2, jpjm1            ! en(mikt(ji,jj))   = rn_emin
286            DO ji = fs_2, fs_jpim1   ! vector opt.
287               en(ji,jj,mikt(ji,jj))=rn_emin * tmask(ji,jj,1)
288            END DO
289         END DO
290      END IF
291      DO jj = 2, jpjm1            ! en(1)   = rn_ebb taum / rau0  (min value rn_emin0)
292         DO ji = fs_2, fs_jpim1   ! vector opt.
293            en(ji,jj,1) = MAX( rn_emin0, zbbrau(ji,jj) * taum(ji,jj) ) * tmask(ji,jj,1)
294         END DO
295      END DO
296     
297!!bfr   - start commented area
298      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
299      !                     !  Bottom boundary condition on tke
300      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
301      !
302      !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
303      ! Tests to date have found the bottom boundary condition on tke to have very little effect.
304      ! The condition is coded here for completion but commented out until there is proof that the
305      ! computational cost is justified
306      !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
307      !                     en(bot)   = (rn_ebb0/rau0)*0.5*sqrt(u_botfr^2+v_botfr^2) (min value rn_emin)
308!CDIR NOVERRCHK
309!!    DO jj = 2, jpjm1
310!CDIR NOVERRCHK
311!!       DO ji = fs_2, fs_jpim1   ! vector opt.
312!!          ztx2 = bfrua(ji-1,jj) * ub(ji-1,jj,mbku(ji-1,jj)) + &
313!!                 bfrua(ji  ,jj) * ub(ji  ,jj,mbku(ji  ,jj) )
314!!          zty2 = bfrva(ji,jj  ) * vb(ji,jj  ,mbkv(ji,jj  )) + &
315!!                 bfrva(ji,jj-1) * vb(ji,jj-1,mbkv(ji,jj-1) )
316!!          zebot = 0.001875_wp * SQRT( ztx2 * ztx2 + zty2 * zty2 )   !  where 0.001875 = (rn_ebb0/rau0) * 0.5 = 3.75*0.5/1000.
317!!          en (ji,jj,mbkt(ji,jj)+1) = MAX( zebot, rn_emin ) * tmask(ji,jj,1)
318!!       END DO
319!!    END DO
320!!bfr   - end commented area
321      !
322      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
323      IF( ln_lc ) THEN      !  Langmuir circulation source term added to tke       (Axell JGR 2002)
324         !                  !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
325         !
326         !                        !* total energy produce by LC : cumulative sum over jk
327         zpelc(:,:,1) =  MAX( rn2b(:,:,1), 0._wp ) * fsdepw(:,:,1) * fse3w(:,:,1)
328         DO jk = 2, jpk
329            zpelc(:,:,jk)  = zpelc(:,:,jk-1) + MAX( rn2b(:,:,jk), 0._wp ) * fsdepw(:,:,jk) * fse3w(:,:,jk)
330         END DO
331         !                        !* finite Langmuir Circulation depth
332         zcof = 0.5 * 0.016 * 0.016 / ( zrhoa * zcdrag )
333         imlc(:,:) = mbkt(:,:) + 1       ! Initialization to the number of w ocean point (=2 over land)
334         DO jk = jpkm1, 2, -1
335            DO jj = 1, jpj               ! Last w-level at which zpelc>=0.5*us*us
336               DO ji = 1, jpi            !      with us=0.016*wind(starting from jpk-1)
337                  zus  = zcof * taum(ji,jj)
338                  IF( zpelc(ji,jj,jk) > zus )   imlc(ji,jj) = jk
339               END DO
340            END DO
341         END DO
342         !                               ! finite LC depth
343         DO jj = 1, jpj 
344            DO ji = 1, jpi
345               zhlc(ji,jj) = fsdepw(ji,jj,imlc(ji,jj))
346            END DO
347         END DO
348         zcof = 0.016 / SQRT( zrhoa * zcdrag )
349!CDIR NOVERRCHK
350         DO jk = 2, jpkm1         !* TKE Langmuir circulation source term added to en
351!CDIR NOVERRCHK
352            DO jj = 2, jpjm1
353!CDIR NOVERRCHK
354               DO ji = fs_2, fs_jpim1   ! vector opt.
355                  zus  = zcof * SQRT( taum(ji,jj) )           ! Stokes drift
356                  !                                           ! vertical velocity due to LC
357                  zind = 0.5 - SIGN( 0.5, fsdepw(ji,jj,jk) - zhlc(ji,jj) )
358                  zwlc = zind * rn_lc0(ji,jj) * zus * SIN( rpi * fsdepw(ji,jj,jk) / zhlc(ji,jj) )
359                  !                                           ! TKE Langmuir circulation source term
360                  en(ji,jj,jk) = en(ji,jj,jk) + rdt * ( 1._wp - fr_i(ji,jj) )* ( zwlc * zwlc * zwlc ) /   &
361                     &   zhlc(ji,jj) * wmask(ji,jj,jk) * tmask(ji,jj,1)
362
363               END DO
364            END DO
365         END DO
366         !
367      ENDIF
368      !
369      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
370      !                     !  Now Turbulent kinetic energy (output in en)
371      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
372      !                     ! Resolution of a tridiagonal linear system by a "methode de chasse"
373      !                     ! computation from level 2 to jpkm1  (e(1) already computed and e(jpk)=0 ).
374      !                     ! zdiag : diagonal zd_up : upper diagonal zd_lw : lower diagonal
375      !
376      DO jk = 2, jpkm1           !* Shear production at uw- and vw-points (energy conserving form)
377         DO jj = 1, jpj                 ! here avmu, avmv used as workspace
378            DO ji = 1, jpi
379               avmu(ji,jj,jk) = avmu(ji,jj,jk) * ( un(ji,jj,jk-1) - un(ji,jj,jk) )   &
380                  &                            * ( ub(ji,jj,jk-1) - ub(ji,jj,jk) )   & 
381                  &                            / (  fse3uw_n(ji,jj,jk)               &
382                  &                              *  fse3uw_b(ji,jj,jk)  )
383               avmv(ji,jj,jk) = avmv(ji,jj,jk) * ( vn(ji,jj,jk-1) - vn(ji,jj,jk) )   &
384                  &                            * ( vb(ji,jj,jk-1) - vb(ji,jj,jk) )   &
385                  &                            / (  fse3vw_n(ji,jj,jk)               &
386                  &                              *  fse3vw_b(ji,jj,jk)  )
387            END DO
388         END DO
389      END DO
390      !
391      DO jk = 2, jpkm1           !* Matrix and right hand side in en
392         DO jj = 2, jpjm1
393            DO ji = fs_2, fs_jpim1   ! vector opt.
394               zcof   = zfact1 * tmask(ji,jj,jk)
395# if defined key_zdftmx_new
396               ! key_zdftmx_new: New internal wave-driven param: set a minimum value for Kz on TKE (ensure numerical stability)
397               zzd_up = zcof * ( MAX( avm(ji,jj,jk+1) + avm(ji,jj,jk), 2.e-5_wp ) )   &  ! upper diagonal
398                  &          / ( fse3t(ji,jj,jk  ) * fse3w(ji,jj,jk  ) )
399               zzd_lw = zcof * ( MAX( avm(ji,jj,jk) + avm(ji,jj,jk-1), 2.e-5_wp ) )   &  ! lower diagonal
400                  &          / ( fse3t(ji,jj,jk-1) * fse3w(ji,jj,jk  ) )
401# else
402               zzd_up = zcof * ( avm  (ji,jj,jk+1) + avm  (ji,jj,jk  ) )   &  ! upper diagonal
403                  &          / ( fse3t(ji,jj,jk  ) * fse3w(ji,jj,jk  ) )
404               zzd_lw = zcof * ( avm  (ji,jj,jk  ) + avm  (ji,jj,jk-1) )   &  ! lower diagonal
405                  &          / ( fse3t(ji,jj,jk-1) * fse3w(ji,jj,jk  ) )
406# endif
407                  !                                                           ! shear prod. at w-point weightened by mask
408               zesh2  =  ( avmu(ji-1,jj,jk) + avmu(ji,jj,jk) ) / MAX( 1._wp , umask(ji-1,jj,jk) + umask(ji,jj,jk) )   &
409                  &    + ( avmv(ji,jj-1,jk) + avmv(ji,jj,jk) ) / MAX( 1._wp , vmask(ji,jj-1,jk) + vmask(ji,jj,jk) )   
410                  !
411               zd_up(ji,jj,jk) = zzd_up            ! Matrix (zdiag, zd_up, zd_lw)
412               zd_lw(ji,jj,jk) = zzd_lw
413               zdiag(ji,jj,jk) = 1._wp - zzd_lw - zzd_up + zfact2(ji,jj) * dissl(ji,jj,jk) * tmask(ji,jj,jk)
414               !
415               !                                   ! right hand side in en
416               en(ji,jj,jk) = en(ji,jj,jk) + rdt * (  zesh2  -   avt(ji,jj,jk) * rn2(ji,jj,jk)    &
417                  &                                 + zfact3(ji,jj) * dissl(ji,jj,jk) * en (ji,jj,jk)  ) &
418                  &                                 * wmask(ji,jj,jk)
419            END DO
420         END DO
421      END DO
422      !                          !* Matrix inversion from level 2 (tke prescribed at level 1)
423      DO jk = 3, jpkm1                             ! First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1
424         DO jj = 2, jpjm1
425            DO ji = fs_2, fs_jpim1    ! vector opt.
426               zdiag(ji,jj,jk) = zdiag(ji,jj,jk) - zd_lw(ji,jj,jk) * zd_up(ji,jj,jk-1) / zdiag(ji,jj,jk-1)
427            END DO
428         END DO
429      END DO
430      !
431      ! Second recurrence : Lk = RHSk - Lk / Dk-1 * Lk-1
432      DO jj = 2, jpjm1
433         DO ji = fs_2, fs_jpim1   ! vector opt.
434            zd_lw(ji,jj,2) = en(ji,jj,2) - zd_lw(ji,jj,2) * en(ji,jj,1)    ! Surface boudary conditions on tke
435         END DO
436      END DO
437      DO jk = 3, jpkm1
438         DO jj = 2, jpjm1
439            DO ji = fs_2, fs_jpim1    ! vector opt.
440               zd_lw(ji,jj,jk) = en(ji,jj,jk) - zd_lw(ji,jj,jk) / zdiag(ji,jj,jk-1) *zd_lw(ji,jj,jk-1)
441            END DO
442         END DO
443      END DO
444      !
445      ! thrid recurrence : Ek = ( Lk - Uk * Ek+1 ) / Dk
446      DO jj = 2, jpjm1
447         DO ji = fs_2, fs_jpim1   ! vector opt.
448            en(ji,jj,jpkm1) = zd_lw(ji,jj,jpkm1) / zdiag(ji,jj,jpkm1)
449         END DO
450      END DO
451      DO jk = jpk-2, 2, -1
452         DO jj = 2, jpjm1
453            DO ji = fs_2, fs_jpim1    ! vector opt.
454               en(ji,jj,jk) = ( zd_lw(ji,jj,jk) - zd_up(ji,jj,jk) * en(ji,jj,jk+1) ) / zdiag(ji,jj,jk)
455            END DO
456         END DO
457      END DO
458      DO jk = 2, jpkm1                             ! set the minimum value of tke
459         DO jj = 2, jpjm1
460            DO ji = fs_2, fs_jpim1   ! vector opt.
461               en(ji,jj,jk) = MAX( en(ji,jj,jk), rn_emin ) * wmask(ji,jj,jk)
462            END DO
463         END DO
464      END DO
465
466      !                                 ! Save TKE prior to nn_etau addition 
467      e_niw(:,:,:) = en(:,:,:) 
468     
469      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
470      !                            !  TKE due to surface and internal wave breaking
471      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
472      IF( nn_htau == 2 ) THEN           !* mixed-layer depth dependant length scale
473         DO jj = 2, jpjm1
474            DO ji = fs_2, fs_jpim1   ! vector opt.
475               htau(ji,jj) = rhtau * hmlp(ji,jj)
476            END DO
477         END DO
478      ENDIF
479#if defined key_iomput
480      !
481      CALL iom_put( "htau", htau(:,:) )  ! Check htau (even if constant in time)
482#endif
483      !
484      IF( nn_etau == 1 ) THEN           !* penetration below the mixed layer (rn_efr fraction)
485         DO jk = 2, jpkm1
486            DO jj = 2, jpjm1
487               DO ji = fs_2, fs_jpim1   ! vector opt.
488                  en(ji,jj,jk) = en(ji,jj,jk) + rn_efr0(ji,jj) * en(ji,jj,1) * EXP( -fsdepw(ji,jj,jk) / htau(ji,jj) )   &
489                     &                                 * ( 1._wp - fr_i(ji,jj) )  * wmask(ji,jj,jk) * tmask(ji,jj,1)
490               END DO
491            END DO
492         END DO
493      ELSEIF( nn_etau == 2 ) THEN       !* act only at the base of the mixed layer (jk=nmln)  (rn_efr fraction)
494         DO jj = 2, jpjm1
495            DO ji = fs_2, fs_jpim1   ! vector opt.
496               jk = nmln(ji,jj)
497               en(ji,jj,jk) = en(ji,jj,jk) + rn_efr0(ji,jj) * en(ji,jj,1) * EXP( -fsdepw(ji,jj,jk) / htau(ji,jj) )   &
498                  &                                 * ( 1._wp - fr_i(ji,jj) )  * wmask(ji,jj,jk) * tmask(ji,jj,1)
499            END DO
500         END DO
501      ELSEIF( nn_etau == 3 ) THEN       !* penetration belox the mixed layer (HF variability)
502!CDIR NOVERRCHK
503         DO jk = 2, jpkm1
504!CDIR NOVERRCHK
505            DO jj = 2, jpjm1
506!CDIR NOVERRCHK
507               DO ji = fs_2, fs_jpim1   ! vector opt.
508                  ztx2 = utau(ji-1,jj  ) + utau(ji,jj)
509                  zty2 = vtau(ji  ,jj-1) + vtau(ji,jj)
510                  ztau = 0.5_wp * SQRT( ztx2 * ztx2 + zty2 * zty2 ) * tmask(ji,jj,1)    ! module of the mean stress
511                  zdif = taum(ji,jj) - ztau                            ! mean of modulus - modulus of the mean
512                  zdif = rhftau_scl * MAX( 0._wp, zdif + rhftau_add )  ! apply some modifications...
513                  en(ji,jj,jk) = en(ji,jj,jk) + zbbrau(ji,jj) * zdif * EXP( -fsdepw(ji,jj,jk) / htau(ji,jj) )   &
514                     &                        * ( 1._wp - fr_i(ji,jj) ) * wmask(ji,jj,jk) * tmask(ji,jj,1)
515               END DO
516            END DO
517         END DO
518      ELSEIF( nn_etau == 4 ) THEN       !* column integral independant of htau (rn_efr must be scaled up)
519         IF( nn_htau == 2 ) THEN        ! efr dependant on time-varying htau
520            DO jj = 2, jpjm1
521               DO ji = fs_2, fs_jpim1   ! vector opt.
522                  efr(ji,jj) = rn_efr / ( htau(ji,jj) * ( 1._wp - EXP( -bathy(ji,jj) / htau(ji,jj) ) ) )
523               END DO
524            END DO
525         ENDIF
526         DO jk = 2, jpkm1
527            DO jj = 2, jpjm1
528               DO ji = fs_2, fs_jpim1   ! vector opt.
529                  en(ji,jj,jk) = en(ji,jj,jk) + efr(ji,jj) * en(ji,jj,1) * EXP( -fsdepw(ji,jj,jk) / htau(ji,jj) )   &
530                     &                                                   * ( 1._wp - fr_i(ji,jj) )  * tmask(ji,jj,jk)
531               END DO
532            END DO
533         END DO
534      ENDIF
535      CALL lbc_lnk( en, 'W', 1. )      ! Lateral boundary conditions (sign unchanged)
536      !
537      DO jk = 2, jpkm1                             ! TKE budget: near-inertial waves term 
538         DO jj = 2, jpjm1 
539            DO ji = fs_2, fs_jpim1   ! vector opt. 
540               e_niw(ji,jj,jk) = en(ji,jj,jk) - e_niw(ji,jj,jk) 
541            END DO 
542         END DO 
543      END DO 
544     
545      CALL lbc_lnk( e_niw, 'W', 1. ) 
546      !
547      CALL wrk_dealloc( jpi,jpj, imlc )    ! integer
548      CALL wrk_dealloc( jpi,jpj, zhlc ) 
549      CALL wrk_dealloc( jpi,jpj, zbbrau ) 
550      CALL wrk_dealloc( jpi,jpj, zfact2 ) 
551      CALL wrk_dealloc( jpi,jpj, zfact3 ) 
552      CALL wrk_dealloc( jpi,jpj,jpk, zpelc, zdiag, zd_up, zd_lw ) 
553      !
554      IF( nn_timing == 1 )  CALL timing_stop('tke_tke')
555      !
556   END SUBROUTINE tke_tke
557
558
559   SUBROUTINE tke_avn
560      !!----------------------------------------------------------------------
561      !!                   ***  ROUTINE tke_avn  ***
562      !!
563      !! ** Purpose :   Compute the vertical eddy viscosity and diffusivity
564      !!
565      !! ** Method  :   At this stage, en, the now TKE, is known (computed in
566      !!              the tke_tke routine). First, the now mixing lenth is
567      !!      computed from en and the strafification (N^2), then the mixings
568      !!      coefficients are computed.
569      !!              - Mixing length : a first evaluation of the mixing lengh
570      !!      scales is:
571      !!                      mxl = sqrt(2*en) / N 
572      !!      where N is the brunt-vaisala frequency, with a minimum value set
573      !!      to rmxl_min (rn_mxl0) in the interior (surface) ocean.
574      !!        The mixing and dissipative length scale are bound as follow :
575      !!         nn_mxl=0 : mxl bounded by the distance to surface and bottom.
576      !!                        zmxld = zmxlm = mxl
577      !!         nn_mxl=1 : mxl bounded by the e3w and zmxld = zmxlm = mxl
578      !!         nn_mxl=2 : mxl bounded such that the vertical derivative of mxl is
579      !!                    less than 1 (|d/dz(mxl)|<1) and zmxld = zmxlm = mxl
580      !!         nn_mxl=3 : mxl is bounded from the surface to the bottom usings
581      !!                    |d/dz(xml)|<1 to obtain lup, and from the bottom to
582      !!                    the surface to obtain ldown. the resulting length
583      !!                    scales are:
584      !!                        zmxld = sqrt( lup * ldown )
585      !!                        zmxlm = min ( lup , ldown )
586      !!              - Vertical eddy viscosity and diffusivity:
587      !!                      avm = max( avtb, rn_ediff * zmxlm * en^1/2 )
588      !!                      avt = max( avmb, pdlr * avm ) 
589      !!      with pdlr=1 if nn_pdl=0, pdlr=1/pdl=F(Ri) otherwise.
590      !!
591      !! ** Action  : - avt : now vertical eddy diffusivity (w-point)
592      !!              - avmu, avmv : now vertical eddy viscosity at uw- and vw-points
593      !!----------------------------------------------------------------------
594      INTEGER  ::   ji, jj, jk   ! dummy loop indices
595      REAL(wp) ::   zrn2, zraug, zcoef, zav     ! local scalars
596      REAL(wp) ::   zdku, zpdlr, zri, zsqen     !   -      -
597      REAL(wp) ::   zdkv, zemxl, zemlm, zemlp   !   -      -
598      REAL(wp), POINTER, DIMENSION(:,:,:) :: zmpdl, zmxlm, zmxld
599      !!--------------------------------------------------------------------
600      !
601      IF( nn_timing == 1 )  CALL timing_start('tke_avn')
602
603      CALL wrk_alloc( jpi,jpj,jpk, zmpdl, zmxlm, zmxld ) 
604
605      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
606      !                     !  Mixing length
607      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
608      !
609      !                     !* Buoyancy length scale: l=sqrt(2*e/n**2)
610      !
611      ! initialisation of interior minimum value (avoid a 2d loop with mikt)
612      zmxlm(:,:,:)  = rmxl_min   
613      zmxld(:,:,:)  = rmxl_min
614      !
615      IF( ln_mxl0 ) THEN            ! surface mixing length = F(stress) : l=vkarmn*2.e5*taum/(rau0*g)
616         DO jj = 2, jpjm1
617            DO ji = fs_2, fs_jpim1
618               zraug = vkarmn * 2.e5_wp / ( rau0 * grav )
619               zmxlm(ji,jj,1) = MAX( rn_mxl0, zraug * taum(ji,jj) * tmask(ji,jj,1) )
620            END DO
621         END DO
622      ELSE
623         zmxlm(:,:,1) = rn_mxl0
624      ENDIF
625      !
626!CDIR NOVERRCHK
627      DO jk = 2, jpkm1              ! interior value : l=sqrt(2*e/n^2)
628!CDIR NOVERRCHK
629         DO jj = 2, jpjm1
630!CDIR NOVERRCHK
631            DO ji = fs_2, fs_jpim1   ! vector opt.
632               zrn2 = MAX( rn2(ji,jj,jk), rsmall )
633               zmxlm(ji,jj,jk) = MAX(  rmxl_min,  SQRT( 2._wp * en(ji,jj,jk) / zrn2 ) )
634            END DO
635         END DO
636      END DO
637      !
638      !                     !* Physical limits for the mixing length
639      !
640      zmxld(:,:,1  ) = zmxlm(:,:,1)   ! surface set to the minimum value
641      zmxld(:,:,jpk) = rmxl_min       ! last level  set to the minimum value
642      !
643      SELECT CASE ( nn_mxl )
644      !
645      ! where wmask = 0 set zmxlm == fse3w
646      CASE ( 0 )           ! bounded by the distance to surface and bottom
647         DO jk = 2, jpkm1
648            DO jj = 2, jpjm1
649               DO ji = fs_2, fs_jpim1   ! vector opt.
650                  zemxl = MIN( fsdepw(ji,jj,jk) - fsdepw(ji,jj,mikt(ji,jj)), zmxlm(ji,jj,jk),   &
651                  &            fsdepw(ji,jj,mbkt(ji,jj)+1) - fsdepw(ji,jj,jk) )
652                  ! wmask prevent zmxlm = 0 if jk = mikt(ji,jj)
653                  zmxlm(ji,jj,jk) = zemxl * wmask(ji,jj,jk) + MIN(zmxlm(ji,jj,jk),fse3w(ji,jj,jk)) * (1 - wmask(ji,jj,jk))
654                  zmxld(ji,jj,jk) = zemxl * wmask(ji,jj,jk) + MIN(zmxlm(ji,jj,jk),fse3w(ji,jj,jk)) * (1 - wmask(ji,jj,jk))
655               END DO
656            END DO
657         END DO
658         !
659      CASE ( 1 )           ! bounded by the vertical scale factor
660         DO jk = 2, jpkm1
661            DO jj = 2, jpjm1
662               DO ji = fs_2, fs_jpim1   ! vector opt.
663                  zemxl = MIN( fse3w(ji,jj,jk), zmxlm(ji,jj,jk) )
664                  zmxlm(ji,jj,jk) = zemxl
665                  zmxld(ji,jj,jk) = zemxl
666               END DO
667            END DO
668         END DO
669         !
670      CASE ( 2 )           ! |dk[xml]| bounded by e3t :
671         DO jk = 2, jpkm1         ! from the surface to the bottom :
672            DO jj = 2, jpjm1
673               DO ji = fs_2, fs_jpim1   ! vector opt.
674                  zmxlm(ji,jj,jk) = MIN( zmxlm(ji,jj,jk-1) + fse3t(ji,jj,jk-1), zmxlm(ji,jj,jk) )
675               END DO
676            END DO
677         END DO
678         DO jk = jpkm1, 2, -1     ! from the bottom to the surface :
679            DO jj = 2, jpjm1
680               DO ji = fs_2, fs_jpim1   ! vector opt.
681                  zemxl = MIN( zmxlm(ji,jj,jk+1) + fse3t(ji,jj,jk+1), zmxlm(ji,jj,jk) )
682                  zmxlm(ji,jj,jk) = zemxl
683                  zmxld(ji,jj,jk) = zemxl
684               END DO
685            END DO
686         END DO
687         !
688      CASE ( 3 )           ! lup and ldown, |dk[xml]| bounded by e3t :
689         DO jk = 2, jpkm1         ! from the surface to the bottom : lup
690            DO jj = 2, jpjm1
691               DO ji = fs_2, fs_jpim1   ! vector opt.
692                  zmxld(ji,jj,jk) = MIN( zmxld(ji,jj,jk-1) + fse3t(ji,jj,jk-1), zmxlm(ji,jj,jk) )
693               END DO
694            END DO
695         END DO
696         DO jk = jpkm1, 2, -1     ! from the bottom to the surface : ldown
697            DO jj = 2, jpjm1
698               DO ji = fs_2, fs_jpim1   ! vector opt.
699                  zmxlm(ji,jj,jk) = MIN( zmxlm(ji,jj,jk+1) + fse3t(ji,jj,jk+1), zmxlm(ji,jj,jk) )
700               END DO
701            END DO
702         END DO
703!CDIR NOVERRCHK
704         DO jk = 2, jpkm1
705!CDIR NOVERRCHK
706            DO jj = 2, jpjm1
707!CDIR NOVERRCHK
708               DO ji = fs_2, fs_jpim1   ! vector opt.
709                  zemlm = MIN ( zmxld(ji,jj,jk),  zmxlm(ji,jj,jk) )
710                  zemlp = SQRT( zmxld(ji,jj,jk) * zmxlm(ji,jj,jk) )
711                  zmxlm(ji,jj,jk) = zemlm
712                  zmxld(ji,jj,jk) = zemlp
713               END DO
714            END DO
715         END DO
716         !
717      END SELECT
718      !
719# if defined key_c1d
720      e_dis(:,:,:) = zmxld(:,:,:)      ! c1d configuration : save mixing and dissipation turbulent length scales
721      e_mix(:,:,:) = zmxlm(:,:,:)
722# endif
723
724      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
725      !                     !  Vertical eddy viscosity and diffusivity  (avmu, avmv, avt)
726      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
727!CDIR NOVERRCHK
728      DO jk = 1, jpkm1            !* vertical eddy viscosity & diffivity at w-points
729!CDIR NOVERRCHK
730         DO jj = 2, jpjm1
731!CDIR NOVERRCHK
732            DO ji = fs_2, fs_jpim1   ! vector opt.
733               zsqen = SQRT( en(ji,jj,jk) )
734               zav   = rn_ediff0(ji,jj) * zmxlm(ji,jj,jk) * zsqen
735               avm  (ji,jj,jk) = MAX( zav,                  avmb(jk) ) * wmask(ji,jj,jk)
736               avt  (ji,jj,jk) = MAX( zav, avtb_2d(ji,jj) * avtb(jk) ) * wmask(ji,jj,jk)
737               dissl(ji,jj,jk) = zsqen / zmxld(ji,jj,jk)
738            END DO
739         END DO
740         IF( ln_stopack) THEN
741            IF(nn_spp_avt > 0 ) CALL spp_gen( 1, avt(:,:,jk), nn_spp_avt, rn_avt_sd, jk_spp_avt, jk)
742            IF(nn_spp_avm > 0 ) CALL spp_gen( 1, avm(:,:,jk), nn_spp_avm, rn_avm_sd, jk_spp_avm, jk)
743         ENDIF
744      END DO
745      CALL lbc_lnk( avm, 'W', 1. )      ! Lateral boundary conditions (sign unchanged)
746      !
747      DO jk = 2, jpkm1            !* vertical eddy viscosity at wu- and wv-points
748         DO jj = 2, jpjm1
749            DO ji = fs_2, fs_jpim1   ! vector opt.
750               avmu(ji,jj,jk) = 0.5 * ( avm(ji,jj,jk) + avm(ji+1,jj  ,jk) ) * wumask(ji,jj,jk)
751               avmv(ji,jj,jk) = 0.5 * ( avm(ji,jj,jk) + avm(ji  ,jj+1,jk) ) * wvmask(ji,jj,jk)
752            END DO
753         END DO
754      END DO
755      CALL lbc_lnk( avmu, 'U', 1. )   ;   CALL lbc_lnk( avmv, 'V', 1. )      ! Lateral boundary conditions
756      !
757      IF( nn_pdl == 1 ) THEN      !* Prandtl number case: update avt
758         DO jk = 2, jpkm1
759            DO jj = 2, jpjm1
760               DO ji = fs_2, fs_jpim1   ! vector opt.
761                  zcoef = avm(ji,jj,jk) * 2._wp * fse3w(ji,jj,jk) * fse3w(ji,jj,jk)
762                  !                                          ! shear
763                  zdku = avmu(ji-1,jj,jk) * ( un(ji-1,jj,jk-1) - un(ji-1,jj,jk) ) * ( ub(ji-1,jj,jk-1) - ub(ji-1,jj,jk) )   &
764                    &  + avmu(ji  ,jj,jk) * ( un(ji  ,jj,jk-1) - un(ji  ,jj,jk) ) * ( ub(ji  ,jj,jk-1) - ub(ji  ,jj,jk) )
765                  zdkv = avmv(ji,jj-1,jk) * ( vn(ji,jj-1,jk-1) - vn(ji,jj-1,jk) ) * ( vb(ji,jj-1,jk-1) - vb(ji,jj-1,jk) )   &
766                    &  + avmv(ji,jj  ,jk) * ( vn(ji,jj  ,jk-1) - vn(ji,jj  ,jk) ) * ( vb(ji,jj  ,jk-1) - vb(ji,jj  ,jk) )
767                  !                                          ! local Richardson number
768                  zri   = MAX( rn2b(ji,jj,jk), 0._wp ) * zcoef / (zdku + zdkv + rn_bshear )
769                  zpdlr = MAX(  0.1_wp,  0.2 / MAX( 0.2 , zri )  )
770!!gm and even better with the use of the "true" ri_crit=0.22222...  (this change the results!)
771!!gm              zpdlr = MAX(  0.1_wp,  ri_crit / MAX( ri_crit , zri )  )
772                  avt(ji,jj,jk)   = MAX( zpdlr * avt(ji,jj,jk), avtb_2d(ji,jj) * avtb(jk) ) * wmask(ji,jj,jk)
773# if defined key_c1d
774                  e_pdl(ji,jj,jk) = zpdlr * wmask(ji,jj,jk)  ! c1d configuration : save masked Prandlt number
775                  e_ric(ji,jj,jk) = zri   * wmask(ji,jj,jk)  ! c1d config. : save Ri
776# endif
777              END DO
778            END DO
779         END DO
780      ENDIF
781      CALL lbc_lnk( avt, 'W', 1. )                      ! Lateral boundary conditions on avt  (sign unchanged)
782
783      IF(ln_ctl) THEN
784         CALL prt_ctl( tab3d_1=en  , clinfo1=' tke  - e: ', tab3d_2=avt, clinfo2=' t: ', ovlap=1, kdim=jpk)
785         CALL prt_ctl( tab3d_1=avmu, clinfo1=' tke  - u: ', mask1=umask,                   &
786            &          tab3d_2=avmv, clinfo2=       ' v: ', mask2=vmask, ovlap=1, kdim=jpk )
787      ENDIF
788      !
789      CALL wrk_dealloc( jpi,jpj,jpk, zmpdl, zmxlm, zmxld ) 
790      !
791      IF( nn_timing == 1 )  CALL timing_stop('tke_avn')
792      !
793   END SUBROUTINE tke_avn
794
795
796   SUBROUTINE zdf_tke_init
797      !!----------------------------------------------------------------------
798      !!                  ***  ROUTINE zdf_tke_init  ***
799      !!                     
800      !! ** Purpose :   Initialization of the vertical eddy diffivity and
801      !!              viscosity when using a tke turbulent closure scheme
802      !!
803      !! ** Method  :   Read the namzdf_tke namelist and check the parameters
804      !!              called at the first timestep (nit000)
805      !!
806      !! ** input   :   Namlist namzdf_tke
807      !!
808      !! ** Action  :   Increase by 1 the nstop flag is setting problem encounter
809      !!----------------------------------------------------------------------
810      INTEGER ::   ji, jj, jk   ! dummy loop indices
811      INTEGER ::   ios, ierr
812      !!
813      NAMELIST/namzdf_tke/ rn_ediff, rn_ediss , rn_ebb , rn_emin  ,   &
814         &                 rn_emin0, rn_bshear, nn_mxl , ln_mxl0  ,   &
815         &                 rn_mxl0 , nn_pdl   , ln_lc  , rn_lc    ,   &
816         &                 nn_etau , nn_htau  , rn_efr , rn_c   
817      !!----------------------------------------------------------------------
818
819      REWIND( numnam_ref )              ! Namelist namzdf_tke in reference namelist : Turbulent Kinetic Energy
820      READ  ( numnam_ref, namzdf_tke, IOSTAT = ios, ERR = 901)
821901   IF( ios /= 0 ) CALL ctl_nam ( ios , 'namzdf_tke in reference namelist', lwp )
822
823      REWIND( numnam_cfg )              ! Namelist namzdf_tke in configuration namelist : Turbulent Kinetic Energy
824      READ  ( numnam_cfg, namzdf_tke, IOSTAT = ios, ERR = 902 )
825902   IF( ios /= 0 ) CALL ctl_nam ( ios , 'namzdf_tke in configuration namelist', lwp )
826      IF(lwm) WRITE ( numond, namzdf_tke )
827      !
828      ri_cri   = 2._wp    / ( 2._wp + rn_ediss / rn_ediff )   ! resulting critical Richardson number
829# if defined key_zdftmx_new
830      ! key_zdftmx_new: New internal wave-driven param: specified value of rn_emin & rmxl_min are used
831      rn_emin  = 1.e-10_wp
832      rmxl_min = 1.e-03_wp
833      IF(lwp) THEN                  ! Control print
834         WRITE(numout,*)
835         WRITE(numout,*) 'zdf_tke_init :  New tidal mixing case: force rn_emin = 1.e-10 and rmxl_min = 1.e-3 '
836         WRITE(numout,*) '~~~~~~~~~~~~'
837      ENDIF
838# else
839      rmxl_min = 1.e-6_wp / ( rn_ediff * SQRT( rn_emin ) )    ! resulting minimum length to recover molecular viscosity
840# endif
841      !
842      IF(lwp) THEN                    !* Control print
843         WRITE(numout,*)
844         WRITE(numout,*) 'zdf_tke_init : tke turbulent closure scheme - initialisation'
845         WRITE(numout,*) '~~~~~~~~~~~~'
846         WRITE(numout,*) '   Namelist namzdf_tke : set tke mixing parameters'
847         WRITE(numout,*) '      coef. to compute avt                        rn_ediff  = ', rn_ediff
848         WRITE(numout,*) '      Kolmogoroff dissipation coef.               rn_ediss  = ', rn_ediss
849         WRITE(numout,*) '      tke surface input coef.                     rn_ebb    = ', rn_ebb
850         WRITE(numout,*) '      minimum value of tke                        rn_emin   = ', rn_emin
851         WRITE(numout,*) '      surface minimum value of tke                rn_emin0  = ', rn_emin0
852         WRITE(numout,*) '      background shear (>0)                       rn_bshear = ', rn_bshear
853         WRITE(numout,*) '      mixing length type                          nn_mxl    = ', nn_mxl
854         WRITE(numout,*) '      prandl number flag                          nn_pdl    = ', nn_pdl
855         WRITE(numout,*) '      surface mixing length = F(stress) or not    ln_mxl0   = ', ln_mxl0
856         WRITE(numout,*) '      surface  mixing length minimum value        rn_mxl0   = ', rn_mxl0
857         WRITE(numout,*) '      flag to take into acc.  Langmuir circ.      ln_lc     = ', ln_lc
858         WRITE(numout,*) '      coef to compute verticla velocity of LC     rn_lc     = ', rn_lc
859         WRITE(numout,*) '      test param. to add tke induced by wind      nn_etau   = ', nn_etau
860         WRITE(numout,*) '      flag for computation of exp. tke profile    nn_htau   = ', nn_htau
861         WRITE(numout,*) '      fraction of en which pene. the thermocline  rn_efr    = ', rn_efr
862         WRITE(numout,*) '      fraction of TKE added within the mixed layer by nn_etau rn_c    = ', rn_c
863         WRITE(numout,*)
864         WRITE(numout,*) '      critical Richardson nb with your parameters  ri_cri = ', ri_cri
865      ENDIF
866      !
867      !                              ! allocate tke arrays
868      IF( zdf_tke_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'zdf_tke_init : unable to allocate arrays' )
869      !
870      !                               !* Check of some namelist values
871      IF( nn_mxl  < 0   .OR.  nn_mxl  > 3 )   CALL ctl_stop( 'bad flag: nn_mxl is  0, 1 or 2 ' )
872      IF( nn_pdl  < 0   .OR.  nn_pdl  > 1 )   CALL ctl_stop( 'bad flag: nn_pdl is  0 or 1    ' )
873      IF( nn_htau < 0  .OR.  nn_htau > 5 )   CALL ctl_stop( 'bad flag: nn_htau is 0 to 5    ' )
874      IF( nn_etau == 3 .AND. .NOT. ln_cpl )   CALL ctl_stop( 'nn_etau == 3 : HF taum only known in coupled mode' )
875
876      IF( ln_mxl0 ) THEN
877         IF(lwp) WRITE(numout,*) '   use a surface mixing length = F(stress) :   set rn_mxl0 = rmxl_min'
878         rn_mxl0 = rmxl_min
879      ENDIF
880
881      ALLOCATE( rn_lc0   (jpi,jpj) ) ; rn_lc0    = rn_lc
882      ALLOCATE( rn_ediff0(jpi,jpj) ) ; rn_ediff0 = rn_ediff
883      ALLOCATE( rn_ediss0(jpi,jpj) ) ; rn_ediss0 = rn_ediss
884      ALLOCATE( rn_ebb0  (jpi,jpj) ) ; rn_ebb0   = rn_ebb
885      ALLOCATE( rn_efr0  (jpi,jpj) ) ; rn_efr0   = rn_efr
886     
887      IF( nn_etau == 2  ) THEN
888          ierr = zdf_mxl_alloc()
889          nmln(:,:) = nlb10           ! Initialization of nmln
890      ENDIF
891
892      IF( nn_etau /= 0 .and. nn_htau == 2 ) THEN
893          ierr = zdf_mxl_alloc()
894          nmln(:,:) = nlb10           ! Initialization of nmln
895      ENDIF
896
897      !                               !* depth of penetration of surface tke
898      IF( nn_etau /= 0 ) THEN     
899         htau(:,:) = 0._wp
900         SELECT CASE( nn_htau )             ! Choice of the depth of penetration
901         CASE( 0 )                                 ! constant depth penetration (here 10 meters)
902            htau(:,:) = 10._wp
903         CASE( 1 )                                 ! F(latitude) : 0.5m to 30m poleward of 40 degrees
904            htau(:,:) = MAX(  0.5_wp, MIN( 30._wp, 45._wp* ABS( SIN( rpi/180._wp * gphit(:,:) ) ) )   )           
905         CASE( 2 )                                 ! fraction of depth-integrated TKE within mixed-layer
906            rhtau = -1._wp / LOG( 1._wp - rn_c )
907         CASE( 3 )                                 ! F(latitude) : 0.5m to 15m poleward of 20 degrees
908            htau(:,:) = MAX(  0.5_wp, MIN( 15._wp, 45._wp* ABS( SIN( rpi/180._wp * gphit(:,:) ) ) )   )
909         CASE( 4 )                                 ! F(latitude) : 0.5m to 10m/30m poleward of 13/40 degrees north/south
910            DO jj = 2, jpjm1
911               DO ji = fs_2, fs_jpim1   ! vector opt.
912                  IF( gphit(ji,jj) <= 0._wp ) THEN
913                     htau(ji,jj) = MAX(  0.5_wp, MIN( 30._wp, 45._wp* ABS( SIN( rpi/180._wp * gphit(ji,jj) ) ) )   )
914                  ELSE
915                     htau(ji,jj) = MAX(  0.5_wp, MIN( 10._wp, 45._wp* ABS( SIN( rpi/180._wp * gphit(ji,jj) ) ) )   )
916                  ENDIF
917               END DO
918            END DO
919         CASE ( 5 )                                ! F(latitude) : 0.5m to 10m poleward of 13 degrees north/south,
920            DO jj = 2, jpjm1                       !               10m to 30m between 30/45 degrees south
921               DO ji = fs_2, fs_jpim1   ! vector opt.
922                  IF( gphit(ji,jj) <= -30._wp ) THEN
923                     htau(ji,jj) = MAX(  10._wp, MIN( 30._wp, 55._wp* ABS( SIN( rpi/120._wp * ( gphit(ji,jj) + 23._wp ) ) ) )   )
924                  ELSE
925                     htau(ji,jj) = MAX(  0.5_wp, MIN( 10._wp, 45._wp* ABS( SIN( rpi/180._wp * gphit(ji,jj) ) ) )   )
926                  ENDIF
927               END DO
928            END DO
929         END SELECT
930         !
931         IF( nn_etau == 4 .AND. nn_htau /= 2 ) THEN            ! efr dependant on constant htau
932            DO jj = 2, jpjm1
933               DO ji = fs_2, fs_jpim1   ! vector opt.
934                  efr(ji,jj) = rn_efr / ( htau(ji,jj) * ( 1._wp - EXP( -bathy(ji,jj) / htau(ji,jj) ) ) )
935               END DO
936            END DO
937         ENDIF
938      ENDIF
939      !                               !* set vertical eddy coef. to the background value
940      DO jk = 1, jpk
941         avt (:,:,jk) = avtb(jk) * wmask (:,:,jk)
942         avm (:,:,jk) = avmb(jk) * wmask (:,:,jk)
943         avmu(:,:,jk) = avmb(jk) * wumask(:,:,jk)
944         avmv(:,:,jk) = avmb(jk) * wvmask(:,:,jk)
945      END DO
946      dissl(:,:,:) = 1.e-12_wp
947      !                             
948      CALL tke_rst( nit000, 'READ' )  !* read or initialize all required files
949      !
950   END SUBROUTINE zdf_tke_init
951
952
953   SUBROUTINE tke_rst( kt, cdrw )
954     !!---------------------------------------------------------------------
955     !!                   ***  ROUTINE tke_rst  ***
956     !!                     
957     !! ** Purpose :   Read or write TKE file (en) in restart file
958     !!
959     !! ** Method  :   use of IOM library
960     !!                if the restart does not contain TKE, en is either
961     !!                set to rn_emin or recomputed
962     !!----------------------------------------------------------------------
963     INTEGER         , INTENT(in) ::   kt     ! ocean time-step
964     CHARACTER(len=*), INTENT(in) ::   cdrw   ! "READ"/"WRITE" flag
965     !
966     INTEGER ::   jit, jk   ! dummy loop indices
967     INTEGER ::   id1, id2, id3, id4, id5, id6   ! local integers
968     !!----------------------------------------------------------------------
969     !
970     IF( TRIM(cdrw) == 'READ' ) THEN        ! Read/initialise
971        !                                   ! ---------------
972        IF( ln_rstart ) THEN                   !* Read the restart file
973           id1 = iom_varid( numror, 'en'   , ldstop = .FALSE. )
974           id2 = iom_varid( numror, 'avt'  , ldstop = .FALSE. )
975           id3 = iom_varid( numror, 'avm'  , ldstop = .FALSE. )
976           id4 = iom_varid( numror, 'avmu' , ldstop = .FALSE. )
977           id5 = iom_varid( numror, 'avmv' , ldstop = .FALSE. )
978           id6 = iom_varid( numror, 'dissl', ldstop = .FALSE. )
979           !
980           IF( id1 > 0 ) THEN                       ! 'en' exists
981              CALL iom_get( numror, jpdom_autoglo, 'en', en )
982              IF( MIN( id2, id3, id4, id5, id6 ) > 0 ) THEN        ! all required arrays exist
983                 IF(nn_timing == 2)  CALL timing_start('iom_rstget')
984                 CALL iom_get( numror, jpdom_autoglo, 'avt'  , avt   )
985                 CALL iom_get( numror, jpdom_autoglo, 'avm'  , avm   )
986                 CALL iom_get( numror, jpdom_autoglo, 'avmu' , avmu  )
987                 CALL iom_get( numror, jpdom_autoglo, 'avmv' , avmv  )
988                 CALL iom_get( numror, jpdom_autoglo, 'dissl', dissl )
989                 IF(nn_timing == 2)  CALL timing_stop('iom_rstget')
990              ELSE                                                 ! one at least array is missing
991                 CALL tke_avn                                          ! compute avt, avm, avmu, avmv and dissl (approximation)
992              ENDIF
993           ELSE                                     ! No TKE array found: initialisation
994              IF(lwp) WRITE(numout,*) ' ===>>>> : previous run without tke scheme, en computed by iterative loop'
995              en (:,:,:) = rn_emin * tmask(:,:,:)
996              CALL tke_avn                               ! recompute avt, avm, avmu, avmv and dissl (approximation)
997              !
998              DO jit = nit000 + 1, nit000 + 10   ;   CALL zdf_tke( jit )   ;   END DO
999           ENDIF
1000        ELSE                                   !* Start from rest
1001           en(:,:,:) = rn_emin * tmask(:,:,:)
1002        ENDIF
1003        !
1004        avt_k (:,:,:) = avt (:,:,:)
1005        avm_k (:,:,:) = avm (:,:,:)
1006        avmu_k(:,:,:) = avmu(:,:,:)
1007        avmv_k(:,:,:) = avmv(:,:,:)
1008       
1009     ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN   ! Create restart file
1010        !                                   ! -------------------
1011        IF(lwp) WRITE(numout,*) '---- tke-rst ----'
1012        IF(nn_timing == 2)  CALL timing_start('iom_rstput')
1013        CALL iom_rstput( kt, nitrst, numrow, 'en'   , en     )
1014        CALL iom_rstput( kt, nitrst, numrow, 'avt'  , avt_k  )
1015        CALL iom_rstput( kt, nitrst, numrow, 'avm'  , avm_k  )
1016        CALL iom_rstput( kt, nitrst, numrow, 'avmu' , avmu_k )
1017        CALL iom_rstput( kt, nitrst, numrow, 'avmv' , avmv_k )
1018        CALL iom_rstput( kt, nitrst, numrow, 'dissl', dissl  )
1019        IF(nn_timing == 2)  CALL timing_stop('iom_rstput')
1020        !
1021     ENDIF
1022     !
1023   END SUBROUTINE tke_rst
1024
1025#else
1026   !!----------------------------------------------------------------------
1027   !!   Dummy module :                                        NO TKE scheme
1028   !!----------------------------------------------------------------------
1029   LOGICAL, PUBLIC, PARAMETER ::   lk_zdftke = .FALSE.   !: TKE flag
1030CONTAINS
1031   SUBROUTINE zdf_tke_init           ! Dummy routine
1032   END SUBROUTINE zdf_tke_init
1033   SUBROUTINE zdf_tke( kt )          ! Dummy routine
1034      WRITE(*,*) 'zdf_tke: You should not have seen this print! error?', kt
1035   END SUBROUTINE zdf_tke
1036   SUBROUTINE tke_rst( kt, cdrw )
1037     CHARACTER(len=*) ::   cdrw
1038     WRITE(*,*) 'tke_rst: You should not have seen this print! error?', kt, cdwr
1039   END SUBROUTINE tke_rst
1040#endif
1041
1042   !!======================================================================
1043END MODULE zdftke
Note: See TracBrowser for help on using the repository browser.