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.
zdftke.F90 in branches/UKMO/dev_r5518_GO6_package_FOAMv14/NEMOGCM/NEMO/OPA_SRC/ZDF – NEMO

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, 5 years 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
RevLine 
[1531]1MODULE zdftke
[1239]2   !!======================================================================
[1531]3   !!                       ***  MODULE  zdftke  ***
[1239]4   !! Ocean physics:  vertical mixing coefficient computed from the tke
5   !!                 turbulent closure parameterization
6   !!=====================================================================
[1492]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
[2528]27   !!            3.3  !  2010-10  (C. Ethe, G. Madec) reorganisation of initialisation phase
[5120]28   !!            3.6  !  2014-11  (P. Mathiot) add ice shelf capability
[1239]29   !!----------------------------------------------------------------------
[1531]30#if defined key_zdftke   ||   defined key_esopa
[1239]31   !!----------------------------------------------------------------------
[1531]32   !!   'key_zdftke'                                   TKE vertical physics
[1239]33   !!----------------------------------------------------------------------
[3625]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
[1239]39   !!----------------------------------------------------------------------
[2528]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
[1492]44   USE sbc_oce        ! surface boundary condition: ocean
[2528]45   USE zdf_oce        ! vertical physics: ocean variables
46   USE zdfmxl         ! vertical physics: mixed layer
[1492]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
[2715]51   USE lib_mpp        ! MPP library
[3294]52   USE wrk_nemo       ! work arrays
53   USE timing         ! Timing
[3625]54   USE lib_fortran    ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined) 
[6487]55#if defined key_agrif
56   USE agrif_opa_interp
57   USE agrif_opa_update
58#endif
[11442]59   USE stopack
[1239]60
61   IMPLICIT NONE
62   PRIVATE
63
[2528]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
[1239]67
[2715]68   LOGICAL , PUBLIC, PARAMETER ::   lk_zdftke = .TRUE.  !: TKE vertical mixing flag
[1239]69
[4147]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
[6491]84   REAL(wp) ::   rn_c      ! fraction of TKE added within the mixed layer by nn_etau
[4147]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
[1239]87
[4147]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]
[6491]90   REAL(wp) ::   rhtau                     ! coefficient to relate MLD to htau when nn_htau == 2
[2528]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)
[1239]93
[2715]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
[11442]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   
[1239]105   !! * Substitutions
106#  include "domzgr_substitute.h90"
107#  include "vectopt_loop_substitute.h90"
108   !!----------------------------------------------------------------------
[2715]109   !! NEMO/OPA 4.0 , NEMO Consortium (2011)
[2528]110   !! $Id$
111   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
[1239]112   !!----------------------------------------------------------------------
113CONTAINS
114
[2715]115   INTEGER FUNCTION zdf_tke_alloc()
116      !!----------------------------------------------------------------------
117      !!                ***  FUNCTION zdf_tke_alloc  ***
118      !!----------------------------------------------------------------------
119      ALLOCATE(                                                                    &
[6491]120         &      efr  (jpi,jpj)     , e_niw(jpi,jpj,jpk) ,                         &     
[2715]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
[6487]125         &      htau  (jpi,jpj)    , dissl(jpi,jpj,jpk) , STAT= zdf_tke_alloc      )
[2715]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
[1531]133   SUBROUTINE zdf_tke( kt )
[1239]134      !!----------------------------------------------------------------------
[1531]135      !!                   ***  ROUTINE zdf_tke  ***
[1239]136      !!
137      !! ** Purpose :   Compute the vertical eddy viscosity and diffusivity
[1492]138      !!              coefficients using a turbulent closure scheme (TKE).
[1239]139      !!
[1492]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
[1239]146      !!      with the boundary conditions:
[1695]147      !!         surface: en = max( rn_emin0, rn_ebb * taum )
[1239]148      !!         bottom : en = rn_emin
[1492]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                 ) 
[1239]165      !!              eav = max( avmb, avm )
[1492]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
[1239]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
[1492]176      !!              Bruchard OM 2002
[1239]177      !!----------------------------------------------------------------------
[1492]178      INTEGER, INTENT(in) ::   kt   ! ocean time step
179      !!----------------------------------------------------------------------
[1481]180      !
[3632]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(:,:,:) 
[11442]186      ENDIF
[3632]187      !
[11442]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      !
[2528]211      CALL tke_tke      ! now tke (en)
[1492]212      !
[2528]213      CALL tke_avn      ! now avt, avm, avmu, avmv
214      !
[3632]215      avt_k (:,:,:) = avt (:,:,:) 
216      avm_k (:,:,:) = avm (:,:,:) 
217      avmu_k(:,:,:) = avmu(:,:,:) 
218      avmv_k(:,:,:) = avmv(:,:,:) 
219      !
[6487]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     
[11442]224      IF (  kt == nitend ) THEN
225        DEALLOCATE ( rn_lc0, rn_ediff0, rn_ediss0, rn_ebb0, rn_efr0 )
226      ENDIF
227      !
228
[1531]229   END SUBROUTINE zdf_tke
[1239]230
[1492]231
[1481]232   SUBROUTINE tke_tke
[1239]233      !!----------------------------------------------------------------------
[1492]234      !!                   ***  ROUTINE tke_tke  ***
235      !!
236      !! ** Purpose :   Compute the now Turbulente Kinetic Energy (TKE)
237      !!
238      !! ** Method  : - TKE surface boundary condition
[2528]239      !!              - source term due to Langmuir cells (Axell JGR 2002) (ln_lc=T)
[1492]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] )
[1239]248      !! ---------------------------------------------------------------------
[1705]249      INTEGER  ::   ji, jj, jk                      ! dummy loop arguments
[2528]250!!bfr      INTEGER  ::   ikbu, ikbv, ikbum1, ikbvm1      ! temporary scalar
251!!bfr      INTEGER  ::   ikbt, ikbumm1, ikbvmm1          ! temporary scalar
[1705]252      REAL(wp) ::   zrhoa  = 1.22                   ! Air density kg/m3
253      REAL(wp) ::   zcdrag = 1.5e-3                 ! drag coefficient
[11442]254      REAL(wp) ::   zesh2                           ! temporary scalars
255      REAL(wp) ::   zfact1                          !    -         -
[1705]256      REAL(wp) ::   ztx2  , zty2  , zcof            !    -         -
257      REAL(wp) ::   ztau  , zdif                    !    -         -
258      REAL(wp) ::   zus   , zwlc  , zind            !    -         -
259      REAL(wp) ::   zzd_up, zzd_lw                  !    -         -
[2528]260!!bfr      REAL(wp) ::   zebot                           !    -         -
[3294]261      INTEGER , POINTER, DIMENSION(:,:  ) :: imlc
[11442]262      REAL(wp), POINTER, DIMENSION(:,:  ) :: zhlc, zbbrau,zfact2,zfact3
[3294]263      REAL(wp), POINTER, DIMENSION(:,:,:) :: zpelc, zdiag, zd_up, zd_lw
[1239]264      !!--------------------------------------------------------------------
[1492]265      !
[3294]266      IF( nn_timing == 1 )  CALL timing_start('tke_tke')
267      !
268      CALL wrk_alloc( jpi,jpj, imlc )    ! integer
[11442]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 )
[3294]273      CALL wrk_alloc( jpi,jpj,jpk, zpelc, zdiag, zd_up, zd_lw ) 
274      !
[11442]275      zbbrau = rn_ebb0 / rau0       ! Local constant initialisation
[2528]276      zfact1 = -.5_wp * rdt 
[11442]277      zfact2 = 1.5_wp * rdt * rn_ediss0
278      zfact3 = 0.5_wp       * rn_ediss0
[1492]279      !
[5120]280      !
[1492]281      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
282      !                     !  Surface boundary condition on tke
283      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[5120]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
[1695]291      DO jj = 2, jpjm1            ! en(1)   = rn_ebb taum / rau0  (min value rn_emin0)
[1481]292         DO ji = fs_2, fs_jpim1   ! vector opt.
[11442]293            en(ji,jj,1) = MAX( rn_emin0, zbbrau(ji,jj) * taum(ji,jj) ) * tmask(ji,jj,1)
[1481]294         END DO
295      END DO
[2528]296     
297!!bfr   - start commented area
[1492]298      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
299      !                     !  Bottom boundary condition on tke
300      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[1719]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)
[1662]308!CDIR NOVERRCHK
[1719]309!!    DO jj = 2, jpjm1
[1662]310!CDIR NOVERRCHK
[1719]311!!       DO ji = fs_2, fs_jpim1   ! vector opt.
[2528]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) )
[1719]316!!          zebot = 0.001875_wp * SQRT( ztx2 * ztx2 + zty2 * zty2 )   !  where 0.001875 = (rn_ebb0/rau0) * 0.5 = 3.75*0.5/1000.
[2528]317!!          en (ji,jj,mbkt(ji,jj)+1) = MAX( zebot, rn_emin ) * tmask(ji,jj,1)
[1719]318!!       END DO
319!!    END DO
[2528]320!!bfr   - end commented area
[1492]321      !
322      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[2528]323      IF( ln_lc ) THEN      !  Langmuir circulation source term added to tke       (Axell JGR 2002)
[1492]324         !                  !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
[1239]325         !
[1492]326         !                        !* total energy produce by LC : cumulative sum over jk
[2528]327         zpelc(:,:,1) =  MAX( rn2b(:,:,1), 0._wp ) * fsdepw(:,:,1) * fse3w(:,:,1)
[1239]328         DO jk = 2, jpk
[2528]329            zpelc(:,:,jk)  = zpelc(:,:,jk-1) + MAX( rn2b(:,:,jk), 0._wp ) * fsdepw(:,:,jk) * fse3w(:,:,jk)
[1239]330         END DO
[1492]331         !                        !* finite Langmuir Circulation depth
[1705]332         zcof = 0.5 * 0.016 * 0.016 / ( zrhoa * zcdrag )
[2528]333         imlc(:,:) = mbkt(:,:) + 1       ! Initialization to the number of w ocean point (=2 over land)
[1239]334         DO jk = jpkm1, 2, -1
[1492]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)
[1705]337                  zus  = zcof * taum(ji,jj)
[1239]338                  IF( zpelc(ji,jj,jk) > zus )   imlc(ji,jj) = jk
339               END DO
340            END DO
341         END DO
[1492]342         !                               ! finite LC depth
343         DO jj = 1, jpj 
[1239]344            DO ji = 1, jpi
345               zhlc(ji,jj) = fsdepw(ji,jj,imlc(ji,jj))
346            END DO
347         END DO
[1705]348         zcof = 0.016 / SQRT( zrhoa * zcdrag )
[5120]349!CDIR NOVERRCHK
[1492]350         DO jk = 2, jpkm1         !* TKE Langmuir circulation source term added to en
[5120]351!CDIR NOVERRCHK
[1239]352            DO jj = 2, jpjm1
[5120]353!CDIR NOVERRCHK
[1239]354               DO ji = fs_2, fs_jpim1   ! vector opt.
[1705]355                  zus  = zcof * SQRT( taum(ji,jj) )           ! Stokes drift
[1492]356                  !                                           ! vertical velocity due to LC
[1239]357                  zind = 0.5 - SIGN( 0.5, fsdepw(ji,jj,jk) - zhlc(ji,jj) )
[11442]358                  zwlc = zind * rn_lc0(ji,jj) * zus * SIN( rpi * fsdepw(ji,jj,jk) / zhlc(ji,jj) )
[1492]359                  !                                           ! TKE Langmuir circulation source term
[11442]360                  en(ji,jj,jk) = en(ji,jj,jk) + rdt * ( 1._wp - fr_i(ji,jj) )* ( zwlc * zwlc * zwlc ) /   &
[6487]361                     &   zhlc(ji,jj) * wmask(ji,jj,jk) * tmask(ji,jj,1)
[11442]362
[1239]363               END DO
364            END DO
365         END DO
366         !
367      ENDIF
[1492]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) )   & 
[5120]381                  &                            / (  fse3uw_n(ji,jj,jk)               &
382                  &                              *  fse3uw_b(ji,jj,jk)  )
[1492]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      !
[5120]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.
[1492]394               zcof   = zfact1 * tmask(ji,jj,jk)
[6498]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
[1492]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  ) )
[6498]406# endif
[1492]407                  !                                                           ! shear prod. at w-point weightened by mask
[2528]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) )   
[1492]410                  !
411               zd_up(ji,jj,jk) = zzd_up            ! Matrix (zdiag, zd_up, zd_lw)
412               zd_lw(ji,jj,jk) = zzd_lw
[11442]413               zdiag(ji,jj,jk) = 1._wp - zzd_lw - zzd_up + zfact2(ji,jj) * dissl(ji,jj,jk) * tmask(ji,jj,jk)
[1239]414               !
[1492]415               !                                   ! right hand side in en
[1481]416               en(ji,jj,jk) = en(ji,jj,jk) + rdt * (  zesh2  -   avt(ji,jj,jk) * rn2(ji,jj,jk)    &
[11442]417                  &                                 + zfact3(ji,jj) * dissl(ji,jj,jk) * en (ji,jj,jk)  ) &
[5120]418                  &                                 * wmask(ji,jj,jk)
[1239]419            END DO
[5120]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.
[1492]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)
[1239]427            END DO
[5120]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.
[1492]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)
[1239]441            END DO
[5120]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.
[1492]448            en(ji,jj,jpkm1) = zd_lw(ji,jj,jpkm1) / zdiag(ji,jj,jpkm1)
[5120]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.
[1492]454               en(ji,jj,jk) = ( zd_lw(ji,jj,jk) - zd_up(ji,jj,jk) * en(ji,jj,jk+1) ) / zdiag(ji,jj,jk)
[1239]455            END DO
[5120]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)
[1239]462            END DO
463         END DO
464      END DO
465
[6491]466      !                                 ! Save TKE prior to nn_etau addition 
467      e_niw(:,:,:) = en(:,:,:) 
468     
[1492]469      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
470      !                            !  TKE due to surface and internal wave breaking
471      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[6491]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      !
[2528]484      IF( nn_etau == 1 ) THEN           !* penetration below the mixed layer (rn_efr fraction)
[1492]485         DO jk = 2, jpkm1
[1239]486            DO jj = 2, jpjm1
487               DO ji = fs_2, fs_jpim1   ! vector opt.
[11442]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) )   &
[5120]489                     &                                 * ( 1._wp - fr_i(ji,jj) )  * wmask(ji,jj,jk) * tmask(ji,jj,1)
[1239]490               END DO
491            END DO
[1492]492         END DO
[2528]493      ELSEIF( nn_etau == 2 ) THEN       !* act only at the base of the mixed layer (jk=nmln)  (rn_efr fraction)
[1492]494         DO jj = 2, jpjm1
495            DO ji = fs_2, fs_jpim1   ! vector opt.
496               jk = nmln(ji,jj)
[11442]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) )   &
[5120]498                  &                                 * ( 1._wp - fr_i(ji,jj) )  * wmask(ji,jj,jk) * tmask(ji,jj,1)
[1239]499            END DO
[1492]500         END DO
[2528]501      ELSEIF( nn_etau == 3 ) THEN       !* penetration belox the mixed layer (HF variability)
[1705]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)
[4990]510                  ztau = 0.5_wp * SQRT( ztx2 * ztx2 + zty2 * zty2 ) * tmask(ji,jj,1)    ! module of the mean stress
[2528]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...
[11442]513                  en(ji,jj,jk) = en(ji,jj,jk) + zbbrau(ji,jj) * zdif * EXP( -fsdepw(ji,jj,jk) / htau(ji,jj) )   &
[5120]514                     &                        * ( 1._wp - fr_i(ji,jj) ) * wmask(ji,jj,jk) * tmask(ji,jj,1)
[1705]515               END DO
516            END DO
517         END DO
[6491]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
[1239]534      ENDIF
[1492]535      CALL lbc_lnk( en, 'W', 1. )      ! Lateral boundary conditions (sign unchanged)
536      !
[6491]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      !
[3294]547      CALL wrk_dealloc( jpi,jpj, imlc )    ! integer
548      CALL wrk_dealloc( jpi,jpj, zhlc ) 
[11442]549      CALL wrk_dealloc( jpi,jpj, zbbrau ) 
550      CALL wrk_dealloc( jpi,jpj, zfact2 ) 
551      CALL wrk_dealloc( jpi,jpj, zfact3 ) 
[3294]552      CALL wrk_dealloc( jpi,jpj,jpk, zpelc, zdiag, zd_up, zd_lw ) 
[2715]553      !
[3294]554      IF( nn_timing == 1 )  CALL timing_stop('tke_tke')
555      !
[1239]556   END SUBROUTINE tke_tke
557
[1492]558
559   SUBROUTINE tke_avn
[1239]560      !!----------------------------------------------------------------------
[1492]561      !!                   ***  ROUTINE tke_avn  ***
[1239]562      !!
[1492]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
[2528]573      !!      to rmxl_min (rn_mxl0) in the interior (surface) ocean.
[1492]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
[1239]593      !!----------------------------------------------------------------------
[2715]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   !   -      -
[3294]598      REAL(wp), POINTER, DIMENSION(:,:,:) :: zmpdl, zmxlm, zmxld
[1239]599      !!--------------------------------------------------------------------
[3294]600      !
601      IF( nn_timing == 1 )  CALL timing_start('tke_avn')
[1239]602
[3294]603      CALL wrk_alloc( jpi,jpj,jpk, zmpdl, zmxlm, zmxld ) 
604
[1492]605      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
606      !                     !  Mixing length
607      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
608      !
609      !                     !* Buoyancy length scale: l=sqrt(2*e/n**2)
610      !
[5120]611      ! initialisation of interior minimum value (avoid a 2d loop with mikt)
612      zmxlm(:,:,:)  = rmxl_min   
613      zmxld(:,:,:)  = rmxl_min
614      !
[2528]615      IF( ln_mxl0 ) THEN            ! surface mixing length = F(stress) : l=vkarmn*2.e5*taum/(rau0*g)
[4990]616         DO jj = 2, jpjm1
617            DO ji = fs_2, fs_jpim1
[5120]618               zraug = vkarmn * 2.e5_wp / ( rau0 * grav )
619               zmxlm(ji,jj,1) = MAX( rn_mxl0, zraug * taum(ji,jj) * tmask(ji,jj,1) )
[4990]620            END DO
621         END DO
622      ELSE
[5120]623         zmxlm(:,:,1) = rn_mxl0
[1239]624      ENDIF
625      !
626!CDIR NOVERRCHK
[5120]627      DO jk = 2, jpkm1              ! interior value : l=sqrt(2*e/n^2)
[1239]628!CDIR NOVERRCHK
[5120]629         DO jj = 2, jpjm1
630!CDIR NOVERRCHK
631            DO ji = fs_2, fs_jpim1   ! vector opt.
[1239]632               zrn2 = MAX( rn2(ji,jj,jk), rsmall )
[5120]633               zmxlm(ji,jj,jk) = MAX(  rmxl_min,  SQRT( 2._wp * en(ji,jj,jk) / zrn2 ) )
[1239]634            END DO
635         END DO
636      END DO
[1492]637      !
638      !                     !* Physical limits for the mixing length
639      !
[5120]640      zmxld(:,:,1  ) = zmxlm(:,:,1)   ! surface set to the minimum value
[2528]641      zmxld(:,:,jpk) = rmxl_min       ! last level  set to the minimum value
[1492]642      !
[1239]643      SELECT CASE ( nn_mxl )
644      !
[5120]645      ! where wmask = 0 set zmxlm == fse3w
[1239]646      CASE ( 0 )           ! bounded by the distance to surface and bottom
[5120]647         DO jk = 2, jpkm1
648            DO jj = 2, jpjm1
649               DO ji = fs_2, fs_jpim1   ! vector opt.
[4990]650                  zemxl = MIN( fsdepw(ji,jj,jk) - fsdepw(ji,jj,mikt(ji,jj)), zmxlm(ji,jj,jk),   &
[2528]651                  &            fsdepw(ji,jj,mbkt(ji,jj)+1) - fsdepw(ji,jj,jk) )
[5120]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))
[1239]655               END DO
656            END DO
657         END DO
658         !
659      CASE ( 1 )           ! bounded by the vertical scale factor
[5120]660         DO jk = 2, jpkm1
661            DO jj = 2, jpjm1
662               DO ji = fs_2, fs_jpim1   ! vector opt.
[1239]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 :
[5120]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.
[1239]674                  zmxlm(ji,jj,jk) = MIN( zmxlm(ji,jj,jk-1) + fse3t(ji,jj,jk-1), zmxlm(ji,jj,jk) )
675               END DO
[5120]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.
[1239]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 :
[5120]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.
[1239]692                  zmxld(ji,jj,jk) = MIN( zmxld(ji,jj,jk-1) + fse3t(ji,jj,jk-1), zmxlm(ji,jj,jk) )
693               END DO
[5120]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.
[1239]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
[1492]718      !
[1239]719# if defined key_c1d
[1492]720      e_dis(:,:,:) = zmxld(:,:,:)      ! c1d configuration : save mixing and dissipation turbulent length scales
[1239]721      e_mix(:,:,:) = zmxlm(:,:,:)
722# endif
723
[1492]724      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
725      !                     !  Vertical eddy viscosity and diffusivity  (avmu, avmv, avt)
726      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[1239]727!CDIR NOVERRCHK
[1492]728      DO jk = 1, jpkm1            !* vertical eddy viscosity & diffivity at w-points
[1239]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) )
[11442]734               zav   = rn_ediff0(ji,jj) * zmxlm(ji,jj,jk) * zsqen
[5120]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)
[1239]737               dissl(ji,jj,jk) = zsqen / zmxld(ji,jj,jk)
738            END DO
739         END DO
[11442]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
[1239]744      END DO
[1492]745      CALL lbc_lnk( avm, 'W', 1. )      ! Lateral boundary conditions (sign unchanged)
746      !
[5120]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)
[4990]752            END DO
[1239]753         END DO
754      END DO
755      CALL lbc_lnk( avmu, 'U', 1. )   ;   CALL lbc_lnk( avmv, 'V', 1. )      ! Lateral boundary conditions
[1492]756      !
757      IF( nn_pdl == 1 ) THEN      !* Prandtl number case: update avt
[5120]758         DO jk = 2, jpkm1
759            DO jj = 2, jpjm1
760               DO ji = fs_2, fs_jpim1   ! vector opt.
[2528]761                  zcoef = avm(ji,jj,jk) * 2._wp * fse3w(ji,jj,jk) * fse3w(ji,jj,jk)
[1492]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
[2528]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 )  )
[1492]770!!gm and even better with the use of the "true" ri_crit=0.22222...  (this change the results!)
[2528]771!!gm              zpdlr = MAX(  0.1_wp,  ri_crit / MAX( ri_crit , zri )  )
[5120]772                  avt(ji,jj,jk)   = MAX( zpdlr * avt(ji,jj,jk), avtb_2d(ji,jj) * avtb(jk) ) * wmask(ji,jj,jk)
[1492]773# if defined key_c1d
[5120]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
[1239]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      !
[3294]789      CALL wrk_dealloc( jpi,jpj,jpk, zmpdl, zmxlm, zmxld ) 
790      !
791      IF( nn_timing == 1 )  CALL timing_stop('tke_avn')
792      !
[1492]793   END SUBROUTINE tke_avn
[1239]794
[1492]795
[2528]796   SUBROUTINE zdf_tke_init
[1239]797      !!----------------------------------------------------------------------
[2528]798      !!                  ***  ROUTINE zdf_tke_init  ***
[1239]799      !!                     
800      !! ** Purpose :   Initialization of the vertical eddy diffivity and
[1492]801      !!              viscosity when using a tke turbulent closure scheme
[1239]802      !!
[1601]803      !! ** Method  :   Read the namzdf_tke namelist and check the parameters
[1492]804      !!              called at the first timestep (nit000)
[1239]805      !!
[1601]806      !! ** input   :   Namlist namzdf_tke
[1239]807      !!
808      !! ** Action  :   Increase by 1 the nstop flag is setting problem encounter
809      !!----------------------------------------------------------------------
810      INTEGER ::   ji, jj, jk   ! dummy loop indices
[6487]811      INTEGER ::   ios, ierr
[1239]812      !!
[2528]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    ,   &
[6491]816         &                 nn_etau , nn_htau  , rn_efr , rn_c   
[1239]817      !!----------------------------------------------------------------------
[6491]818
[4147]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 )
[4624]826      IF(lwm) WRITE ( numond, namzdf_tke )
[2715]827      !
[2528]828      ri_cri   = 2._wp    / ( 2._wp + rn_ediss / rn_ediff )   ! resulting critical Richardson number
[6498]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
[2528]839      rmxl_min = 1.e-6_wp / ( rn_ediff * SQRT( rn_emin ) )    ! resulting minimum length to recover molecular viscosity
[6498]840# endif
[2715]841      !
[1492]842      IF(lwp) THEN                    !* Control print
[1239]843         WRITE(numout,*)
[2528]844         WRITE(numout,*) 'zdf_tke_init : tke turbulent closure scheme - initialisation'
845         WRITE(numout,*) '~~~~~~~~~~~~'
[1601]846         WRITE(numout,*) '   Namelist namzdf_tke : set tke mixing parameters'
[1705]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
[2528]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
[1705]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
[6491]862         WRITE(numout,*) '      fraction of TKE added within the mixed layer by nn_etau rn_c    = ', rn_c
[1239]863         WRITE(numout,*)
[1601]864         WRITE(numout,*) '      critical Richardson nb with your parameters  ri_cri = ', ri_cri
[1239]865      ENDIF
[2715]866      !
867      !                              ! allocate tke arrays
868      IF( zdf_tke_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'zdf_tke_init : unable to allocate arrays' )
869      !
[1492]870      !                               !* Check of some namelist values
[4990]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    ' )
[6491]873      IF( nn_htau < 0  .OR.  nn_htau > 5 )   CALL ctl_stop( 'bad flag: nn_htau is 0 to 5    ' )
[5407]874      IF( nn_etau == 3 .AND. .NOT. ln_cpl )   CALL ctl_stop( 'nn_etau == 3 : HF taum only known in coupled mode' )
[1239]875
[2528]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
[11442]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
[2528]886     
[6487]887      IF( nn_etau == 2  ) THEN
888          ierr = zdf_mxl_alloc()
889          nmln(:,:) = nlb10           ! Initialization of nmln
890      ENDIF
[1239]891
[6491]892      IF( nn_etau /= 0 .and. nn_htau == 2 ) THEN
893          ierr = zdf_mxl_alloc()
894          nmln(:,:) = nlb10           ! Initialization of nmln
895      ENDIF
896
[1492]897      !                               !* depth of penetration of surface tke
898      IF( nn_etau /= 0 ) THEN     
[6491]899         htau(:,:) = 0._wp
[1601]900         SELECT CASE( nn_htau )             ! Choice of the depth of penetration
[2528]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(:,:) ) ) )   )           
[6491]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
[1492]929         END SELECT
[6491]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
[1492]938      ENDIF
939      !                               !* set vertical eddy coef. to the background value
[1239]940      DO jk = 1, jpk
[5120]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)
[1239]945      END DO
[2528]946      dissl(:,:,:) = 1.e-12_wp
[2715]947      !                             
948      CALL tke_rst( nit000, 'READ' )  !* read or initialize all required files
[1239]949      !
[2528]950   END SUBROUTINE zdf_tke_init
[1239]951
952
[1531]953   SUBROUTINE tke_rst( kt, cdrw )
[1239]954     !!---------------------------------------------------------------------
[1531]955     !!                   ***  ROUTINE tke_rst  ***
[1239]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
[1537]961     !!                set to rn_emin or recomputed
[1239]962     !!----------------------------------------------------------------------
[2715]963     INTEGER         , INTENT(in) ::   kt     ! ocean time-step
964     CHARACTER(len=*), INTENT(in) ::   cdrw   ! "READ"/"WRITE" flag
[1239]965     !
[1481]966     INTEGER ::   jit, jk   ! dummy loop indices
[2715]967     INTEGER ::   id1, id2, id3, id4, id5, id6   ! local integers
[1239]968     !!----------------------------------------------------------------------
969     !
[1481]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
[1239]981              CALL iom_get( numror, jpdom_autoglo, 'en', en )
[1481]982              IF( MIN( id2, id3, id4, id5, id6 ) > 0 ) THEN        ! all required arrays exist
[10302]983                 IF(nn_timing == 2)  CALL timing_start('iom_rstget')
[1481]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 )
[10302]989                 IF(nn_timing == 2)  CALL timing_stop('iom_rstget')
[1492]990              ELSE                                                 ! one at least array is missing
991                 CALL tke_avn                                          ! compute avt, avm, avmu, avmv and dissl (approximation)
[1481]992              ENDIF
993           ELSE                                     ! No TKE array found: initialisation
994              IF(lwp) WRITE(numout,*) ' ===>>>> : previous run without tke scheme, en computed by iterative loop'
[1239]995              en (:,:,:) = rn_emin * tmask(:,:,:)
[1492]996              CALL tke_avn                               ! recompute avt, avm, avmu, avmv and dissl (approximation)
[5112]997              !
[1531]998              DO jit = nit000 + 1, nit000 + 10   ;   CALL zdf_tke( jit )   ;   END DO
[1239]999           ENDIF
[1481]1000        ELSE                                   !* Start from rest
1001           en(:,:,:) = rn_emin * tmask(:,:,:)
[1239]1002        ENDIF
[1481]1003        !
[11442]1004        avt_k (:,:,:) = avt (:,:,:)
1005        avm_k (:,:,:) = avm (:,:,:)
1006        avmu_k(:,:,:) = avmu(:,:,:)
1007        avmv_k(:,:,:) = avmv(:,:,:)
1008       
[1481]1009     ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN   ! Create restart file
1010        !                                   ! -------------------
[1531]1011        IF(lwp) WRITE(numout,*) '---- tke-rst ----'
[10302]1012        IF(nn_timing == 2)  CALL timing_start('iom_rstput')
[3632]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  )
[10302]1019        IF(nn_timing == 2)  CALL timing_stop('iom_rstput')
[1481]1020        !
[1239]1021     ENDIF
1022     !
[1531]1023   END SUBROUTINE tke_rst
[1239]1024
1025#else
1026   !!----------------------------------------------------------------------
1027   !!   Dummy module :                                        NO TKE scheme
1028   !!----------------------------------------------------------------------
[1531]1029   LOGICAL, PUBLIC, PARAMETER ::   lk_zdftke = .FALSE.   !: TKE flag
[1239]1030CONTAINS
[2528]1031   SUBROUTINE zdf_tke_init           ! Dummy routine
1032   END SUBROUTINE zdf_tke_init
1033   SUBROUTINE zdf_tke( kt )          ! Dummy routine
[1531]1034      WRITE(*,*) 'zdf_tke: You should not have seen this print! error?', kt
1035   END SUBROUTINE zdf_tke
1036   SUBROUTINE tke_rst( kt, cdrw )
[1492]1037     CHARACTER(len=*) ::   cdrw
[1531]1038     WRITE(*,*) 'tke_rst: You should not have seen this print! error?', kt, cdwr
1039   END SUBROUTINE tke_rst
[1239]1040#endif
1041
1042   !!======================================================================
[1531]1043END MODULE zdftke
Note: See TracBrowser for help on using the repository browser.