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 NEMO/branches/2020/dev_r12702_ASINTER-02_emanuelaclementi_Waves/src/OCE/ZDF – NEMO

source: NEMO/branches/2020/dev_r12702_ASINTER-02_emanuelaclementi_Waves/src/OCE/ZDF/zdftke.F90 @ 13851

Last change on this file since 13851 was 13851, checked in by emanuelaclementi, 3 years ago

corrections for zdftke Neumann BC plus loop alignement - ticket #2155 #2339

  • Property svn:keywords set to Id
File size: 49.6 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   !!            4.0  !  2017-04  (G. Madec)  remove CPP ddm key & avm at t-point only
30   !!             -   !  2017-05  (G. Madec)  add top/bottom friction as boundary condition
31   !!----------------------------------------------------------------------
32
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 zdfdrg         ! vertical physics: top/bottom drag coef.
46   USE zdfmxl         ! vertical physics: mixed layer
47#if defined key_si3
48   USE ice, ONLY: hm_i, h_i
49#endif
50#if defined key_cice
51   USE sbc_ice, ONLY: h_i
52#endif
53   !
54   USE in_out_manager ! I/O manager
55   USE iom            ! I/O manager library
56   USE lib_mpp        ! MPP library
57   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
58   USE prtctl         ! Print control
59   USE lib_fortran    ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined) 
60   USE sbcwave        ! Surface boundary waves
61
62   IMPLICIT NONE
63   PRIVATE
64
65   PUBLIC   zdf_tke        ! routine called in step module
66   PUBLIC   zdf_tke_init   ! routine called in opa module
67   PUBLIC   tke_rst        ! routine called in step module
68
69   !                      !!** Namelist  namzdf_tke  **
70   LOGICAL  ::   ln_mxl0   ! mixing length scale surface value as function of wind stress or not
71   LOGICAL  ::   ln_mxhsw  ! mixing length scale surface value as a fonction of wave height
72   INTEGER  ::   nn_mxlice ! type of scaling under sea-ice (=0/1/2/3)
73   REAL(wp) ::   rn_mxlice ! ice thickness value when scaling under sea-ice
74   INTEGER  ::   nn_mxl    ! type of mixing length (=0/1/2/3)
75   REAL(wp) ::   rn_mxl0   ! surface  min value of mixing length (kappa*z_o=0.4*0.1 m)  [m]
76   INTEGER  ::   nn_pdl    ! Prandtl number or not (ratio avt/avm) (=0/1)
77   REAL(wp) ::   rn_ediff  ! coefficient for avt: avt=rn_ediff*mxl*sqrt(e)
78   REAL(wp) ::   rn_ediss  ! coefficient of the Kolmogoroff dissipation
79   REAL(wp) ::   rn_ebb    ! coefficient of the surface input of tke
80   REAL(wp) ::   rn_emin   ! minimum value of tke           [m2/s2]
81   REAL(wp) ::   rn_emin0  ! surface minimum value of tke   [m2/s2]
82   REAL(wp) ::   rn_bshear ! background shear (>0) currently a numerical threshold (do not change it)
83   INTEGER  ::   nn_etau   ! type of depth penetration of surface tke (=0/1/2/3)
84   INTEGER  ::      nn_htau   ! type of tke profile of penetration (=0/1)
85   INTEGER  ::   nn_bc_surf! surface condition (0/1=Dir/Neum) ! Only applicable for wave coupling
86   INTEGER  ::   nn_bc_bot ! surface condition (0/1=Dir/Neum) ! Only applicable for wave coupling
87   REAL(wp) ::      rn_efr    ! fraction of TKE surface value which penetrates in the ocean
88   LOGICAL  ::   ln_lc     ! Langmuir cells (LC) as a source term of TKE or not
89   REAL(wp) ::      rn_lc     ! coef to compute vertical velocity of Langmuir cells
90   INTEGER  ::   nn_eice   ! attenutaion of langmuir & surface wave breaking under ice (=0/1/2/3)   
91
92   REAL(wp) ::   ri_cri    ! critic Richardson number (deduced from rn_ediff and rn_ediss values)
93   REAL(wp) ::   rmxl_min  ! minimum mixing length value (deduced from rn_ediff and rn_emin values)  [m]
94   REAL(wp) ::   rhftau_add = 1.e-3_wp     ! add offset   applied to HF part of taum  (nn_etau=3)
95   REAL(wp) ::   rhftau_scl = 1.0_wp       ! scale factor applied to HF part of taum  (nn_etau=3)
96
97   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   htau    ! depth of tke penetration (nn_htau)
98   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   dissl   ! now mixing lenght of dissipation
99   REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   apdlr   ! now mixing lenght of dissipation
100
101   !! * Substitutions
102#  include "do_loop_substitute.h90"
103#  include "domzgr_substitute.h90"
104   !!----------------------------------------------------------------------
105   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
106   !! $Id$
107   !! Software governed by the CeCILL license (see ./LICENSE)
108   !!----------------------------------------------------------------------
109CONTAINS
110
111   INTEGER FUNCTION zdf_tke_alloc()
112      !!----------------------------------------------------------------------
113      !!                ***  FUNCTION zdf_tke_alloc  ***
114      !!----------------------------------------------------------------------
115      ALLOCATE( htau(jpi,jpj) , dissl(jpi,jpj,jpk) , apdlr(jpi,jpj,jpk) ,   STAT= zdf_tke_alloc )
116      !
117      CALL mpp_sum ( 'zdftke', zdf_tke_alloc )
118      IF( zdf_tke_alloc /= 0 )   CALL ctl_stop( 'STOP', 'zdf_tke_alloc: failed to allocate arrays' )
119      !
120   END FUNCTION zdf_tke_alloc
121
122
123   SUBROUTINE zdf_tke( kt, Kbb, Kmm, p_sh2, p_avm, p_avt )
124      !!----------------------------------------------------------------------
125      !!                   ***  ROUTINE zdf_tke  ***
126      !!
127      !! ** Purpose :   Compute the vertical eddy viscosity and diffusivity
128      !!              coefficients using a turbulent closure scheme (TKE).
129      !!
130      !! ** Method  :   The time evolution of the turbulent kinetic energy (tke)
131      !!              is computed from a prognostic equation :
132      !!         d(en)/dt = avm (d(u)/dz)**2             ! shear production
133      !!                  + d( avm d(en)/dz )/dz         ! diffusion of tke
134      !!                  + avt N^2                      ! stratif. destruc.
135      !!                  - rn_ediss / emxl en**(2/3)    ! Kolmogoroff dissipation
136      !!      with the boundary conditions:
137      !!         surface: en = max( rn_emin0, rn_ebb * taum )
138      !!         bottom : en = rn_emin
139      !!      The associated critical Richardson number is: ri_cri = 2/(2+rn_ediss/rn_ediff)
140      !!
141      !!        The now Turbulent kinetic energy is computed using the following
142      !!      time stepping: implicit for vertical diffusion term, linearized semi
143      !!      implicit for kolmogoroff dissipation term, and explicit forward for
144      !!      both buoyancy and shear production terms. Therefore a tridiagonal
145      !!      linear system is solved. Note that buoyancy and shear terms are
146      !!      discretized in a energy conserving form (Bruchard 2002).
147      !!
148      !!        The dissipative and mixing length scale are computed from en and
149      !!      the stratification (see tke_avn)
150      !!
151      !!        The now vertical eddy vicosity and diffusivity coefficients are
152      !!      given by:
153      !!              avm = max( avtb, rn_ediff * zmxlm * en^1/2 )
154      !!              avt = max( avmb, pdl * avm                 ) 
155      !!              eav = max( avmb, avm )
156      !!      where pdl, the inverse of the Prandtl number is 1 if nn_pdl=0 and
157      !!      given by an empirical funtion of the localRichardson number if nn_pdl=1
158      !!
159      !! ** Action  :   compute en (now turbulent kinetic energy)
160      !!                update avt, avm (before vertical eddy coef.)
161      !!
162      !! References : Gaspar et al., JGR, 1990,
163      !!              Blanke and Delecluse, JPO, 1991
164      !!              Mellor and Blumberg, JPO 2004
165      !!              Axell, JGR, 2002
166      !!              Bruchard OM 2002
167      !!----------------------------------------------------------------------
168      INTEGER                   , INTENT(in   ) ::   kt             ! ocean time step
169      INTEGER                   , INTENT(in   ) ::   Kbb, Kmm       ! ocean time level indices
170      REAL(wp), DIMENSION(:,:,:), INTENT(in   ) ::   p_sh2          ! shear production term
171      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   p_avm, p_avt   !  momentum and tracer Kz (w-points)
172      !!----------------------------------------------------------------------
173      !
174      CALL tke_tke( Kbb, Kmm, p_sh2, p_avm, p_avt )   ! now tke (en)
175      !
176      CALL tke_avn( Kbb, Kmm,        p_avm, p_avt )   ! now avt, avm, dissl
177      !
178  END SUBROUTINE zdf_tke
179
180
181   SUBROUTINE tke_tke( Kbb, Kmm, p_sh2, p_avm, p_avt )
182      !!----------------------------------------------------------------------
183      !!                   ***  ROUTINE tke_tke  ***
184      !!
185      !! ** Purpose :   Compute the now Turbulente Kinetic Energy (TKE)
186      !!
187      !! ** Method  : - TKE surface boundary condition
188      !!              - source term due to Langmuir cells (Axell JGR 2002) (ln_lc=T)
189      !!              - source term due to shear (= Kz dz[Ub] * dz[Un] )
190      !!              - Now TKE : resolution of the TKE equation by inverting
191      !!                a tridiagonal linear system by a "methode de chasse"
192      !!              - increase TKE due to surface and internal wave breaking
193      !!             NB: when sea-ice is present, both LC parameterization
194      !!                 and TKE penetration are turned off when the ice fraction
195      !!                 is smaller than 0.25
196      !!
197      !! ** Action  : - en : now turbulent kinetic energy)
198      !! ---------------------------------------------------------------------
199      USE zdf_oce , ONLY : en   ! ocean vertical physics
200      !!
201      INTEGER                    , INTENT(in   ) ::   Kbb, Kmm       ! ocean time level indices
202      REAL(wp), DIMENSION(:,:,:) , INTENT(in   ) ::   p_sh2          ! shear production term
203      REAL(wp), DIMENSION(:,:,:) , INTENT(in   ) ::   p_avm, p_avt   ! vertical eddy viscosity & diffusivity (w-points)
204      !
205      INTEGER ::   ji, jj, jk                  ! dummy loop arguments
206      REAL(wp) ::   zetop, zebot, zmsku, zmskv ! local scalars
207      REAL(wp) ::   zrhoa  = 1.22              ! Air density kg/m3
208      REAL(wp) ::   zcdrag = 1.5e-3            ! drag coefficient
209      REAL(wp) ::   zbbrau, zbbirau, zri       ! local scalars
210      REAL(wp) ::   zfact1, zfact2, zfact3     !   -      -
211      REAL(wp) ::   ztx2  , zty2  , zcof       !   -      -
212      REAL(wp) ::   ztau  , zdif               !   -      -
213      REAL(wp) ::   zus   , zwlc  , zind       !   -      -
214      REAL(wp) ::   zzd_up, zzd_lw             !   -      -
215      REAL(wp) ::   ztaui, ztauj, z1_norm
216      INTEGER , DIMENSION(jpi,jpj)     ::   imlc
217      REAL(wp), DIMENSION(jpi,jpj)     ::   zice_fra, zhlc, zus3, zWlc2
218      REAL(wp), DIMENSION(jpi,jpj,jpk) ::   zpelc, zdiag, zd_up, zd_lw
219      !!--------------------------------------------------------------------
220      !
221      zbbrau  = rn_ebb / rho0       ! Local constant initialisation
222      zbbirau = 3.75_wp / rho0
223      zfact1  = -.5_wp * rn_Dt 
224      zfact2  = 1.5_wp * rn_Dt * rn_ediss
225      zfact3  = 0.5_wp         * rn_ediss
226      !
227      zpelc(:,:,:) = 0._wp ! need to be initialised in case ln_lc is not used
228      !
229      ! ice fraction considered for attenuation of langmuir & wave breaking
230      SELECT CASE ( nn_eice )
231      CASE( 0 )   ;   zice_fra(:,:) = 0._wp
232      CASE( 1 )   ;   zice_fra(:,:) =        TANH( fr_i(:,:) * 10._wp )
233      CASE( 2 )   ;   zice_fra(:,:) =              fr_i(:,:)
234      CASE( 3 )   ;   zice_fra(:,:) = MIN( 4._wp * fr_i(:,:) , 1._wp )
235      END SELECT
236      !
237      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
238      !                     !  Surface/top/bottom boundary condition on tke
239      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
240      !
241      zd_up(ji,jj,1) = 0._wp
242      zd_lw(ji,jj,1) = 1._wp
243
244      IF ( cpl_phioc .and. ln_phioc )  THEN
245         SELECT CASE (nn_bc_surf) ! Boundary Condition using surface TKE flux from waves
246
247         CASE ( 0 ) ! Dirichlet BC
248
249            DO_2D( 0, 0, 0, 0 )    ! en(1)   = rn_ebb taum / rho0  (min value rn_emin0)
250               IF ( phioc(ji,jj) < 0 )  phioc(ji,jj) = 0._wp
251               en(ji,jj,1) = MAX( rn_emin0, .5 * ( 15.8 * phioc(ji,jj) / rho0 )**(2./3.) )  * tmask(ji,jj,1)
252               zdiag(ji,jj,1) = 1._wp/en(ji,jj,1)  ! choose to keep coherence with former estimation of
253                                                   ! zd_lw(ji,jj,2) = en(ji,jj,2) - zd_lw(ji,jj,2) * en(ji,jj,1)
254            END_2D
255
256         CASE ( 1 ) ! Neumann BC
257            DO_2D( 0, 0, 0, 0 )
258               IF ( phioc(ji,jj) < 0 )  phioc(ji,jj) = 0._wp
259               en(ji,jj,2)    = en(ji,jj,2) + ( rn_Dt * phioc(ji,jj) / rho0 )/e3w(ji,jj,2,Kmm)
260               en(ji,jj,1)    = en(ji,jj,2) + (2 * e3t(ji,jj,1,Kmm) * phioc(ji,jj)/rho0) / ( p_avm(ji,jj,1) + p_avm(ji,jj,2) )
261               zdiag(ji,jj,2) = zdiag(ji,jj,2) + zd_lw(ji,jj,2)
262               zd_lw(ji,jj,2) = 0._wp
263               zdiag(ji,jj,1) = 1._wp
264            END_2D
265         
266         END SELECT
267
268      ELSE  ! TKE Dirichlet boundary condition (without wave coupling)
269
270         DO_2D( 0, 0, 0, 0 )       ! en(1)   = rn_ebb taum / rho0  (min value rn_emin0)
271            en(ji,jj,1) = MAX( rn_emin0, zbbrau * taum(ji,jj) ) * tmask(ji,jj,1)
272            zdiag(ji,jj,1) = 1._wp/en(ji,jj,1) ! choose to keep coherence with former estimation of
273                                               ! zd_lw(ji,jj,2) = en(ji,jj,2) - zd_lw(ji,jj,2) * en(ji,jj,1)
274         END_2D
275
276      ENDIF
277      !
278      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
279      !                     !  Bottom boundary condition on tke
280      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
281      !
282      !   en(bot)   = (ebb0/rho0)*0.5*sqrt(u_botfr^2+v_botfr^2) (min value rn_emin)
283      ! where ebb0 does not includes surface wave enhancement (i.e. ebb0=3.75)
284      ! Note that stress averaged is done using an wet-only calculation of u and v at t-point like in zdfsh2
285      !
286      IF( .NOT.ln_drg_OFF ) THEN    !== friction used as top/bottom boundary condition on TKE
287         !
288         DO_2D( 0, 0, 0, 0 )        ! bottom friction
289            zmsku = ( 2. - umask(ji-1,jj,mbkt(ji,jj)) * umask(ji,jj,mbkt(ji,jj)) )
290            zmskv = ( 2. - vmask(ji,jj-1,mbkt(ji,jj)) * vmask(ji,jj,mbkt(ji,jj)) )
291            !                       ! where 0.001875 = (rn_ebb0/rho0) * 0.5 = 3.75*0.5/1000. (CAUTION CdU<0)
292            zebot = - 0.001875_wp * rCdU_bot(ji,jj) * SQRT(  ( zmsku*( uu(ji,jj,mbkt(ji,jj),Kbb)+uu(ji-1,jj,mbkt(ji,jj),Kbb) ) )**2  &
293               &                                           + ( zmskv*( vv(ji,jj,mbkt(ji,jj),Kbb)+vv(ji,jj-1,mbkt(ji,jj),Kbb) ) )**2  )
294            en(ji,jj,mbkt(ji,jj)+1) = MAX( zebot, rn_emin ) * ssmask(ji,jj)
295         END_2D
296         IF( ln_isfcav ) THEN
297            DO_2D( 0, 0, 0, 0 )     ! top friction
298               zmsku = ( 2. - umask(ji-1,jj,mikt(ji,jj)) * umask(ji,jj,mikt(ji,jj)) )
299               zmskv = ( 2. - vmask(ji,jj-1,mikt(ji,jj)) * vmask(ji,jj,mikt(ji,jj)) )
300               !                             ! where 0.001875 = (rn_ebb0/rho0) * 0.5 = 3.75*0.5/1000.  (CAUTION CdU<0)
301               zetop = - 0.001875_wp * rCdU_top(ji,jj) * SQRT(  ( zmsku*( uu(ji,jj,mikt(ji,jj),Kbb)+uu(ji-1,jj,mikt(ji,jj),Kbb) ) )**2  &
302                  &                                           + ( zmskv*( vv(ji,jj,mikt(ji,jj),Kbb)+vv(ji,jj-1,mikt(ji,jj),Kbb) ) )**2  )
303               ! (1._wp - tmask(ji,jj,1)) * ssmask(ji,jj) = 1 where ice shelves are present
304               en(ji,jj,mikt(ji,jj)) = en(ji,jj,1)           * tmask(ji,jj,1) &
305                  &                  + MAX( zetop, rn_emin ) * (1._wp - tmask(ji,jj,1)) * ssmask(ji,jj)
306            END_2D
307         ENDIF
308         !
309      ENDIF
310      !
311      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
312      IF( ln_lc ) THEN      !  Langmuir circulation source term added to tke (Axell JGR 2002)
313         !                  !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
314         !
315         !                       !* Langmuir velocity scale
316         !
317         IF ( cpl_sdrftx )  THEN       ! Surface Stokes Drift available
318            !                                ! Craik-Leibovich velocity scale Wlc = ( u* u_s )^1/2    with u* = (taum/rho0)^1/2
319            !                                ! associated kinetic energy : 1/2 (Wlc)^2 = u* u_s
320            !                                ! more precisely, it is the dot product that must be used :
321            !                                !     1/2  (W_lc)^2 = MAX( u* u_s + v* v_s , 0 )   only the positive part
322!!gm  ! PS: currently we don't have neither the 2 stress components at t-point !nor the angle between u* and u_s
323!!gm  ! so we will overestimate the LC velocity....   !!gm I will do the work if !LC have an effect !
324            DO_2D( 0, 0, 0, 0 )
325!!XC                  zWlc2(ji,jj) = 0.5_wp * SQRT( taum(ji,jj) * r1_rho0 * ( ut0sd(ji,jj)**2 +vt0sd(ji,jj)**2 )  )
326                  zWlc2(ji,jj) = 0.5_wp *  ( ut0sd(ji,jj)**2 +vt0sd(ji,jj)**2 )
327            END_2D
328!
329!  Projection of Stokes drift in the wind stress direction
330!
331            DO_2D( 0, 0, 0, 0 )
332                  ztaui   = 0.5_wp * ( utau(ji,jj) + utau(ji-1,jj) )
333                  ztauj   = 0.5_wp * ( vtau(ji,jj) + vtau(ji,jj-1) )
334                  z1_norm = 1._wp / MAX( SQRT(ztaui*ztaui+ztauj*ztauj), 1.e-12 ) * tmask(ji,jj,1)
335                  zWlc2(ji,jj) = 0.5_wp * z1_norm * ( MAX( ut0sd(ji,jj)*ztaui + vt0sd(ji,jj)*ztauj, 0._wp ) )**2
336            END_2D
337         CALL lbc_lnk      ( 'zdftke', zWlc2, 'T', 1. )
338!
339         ELSE                          ! Surface Stokes drift deduced from surface stress
340            !                                ! Wlc = u_s   with u_s = 0.016*U_10m, the surface stokes drift  (Axell 2002, Eq.44)
341            !                                ! using |tau| = rho_air Cd |U_10m|^2 , it comes:
342            !                                ! Wlc = 0.016 * [|tau|/(rho_air Cdrag) ]^1/2   and thus:
343            !                                ! 1/2 Wlc^2 = 0.5 * 0.016 * 0.016 |tau| /( rho_air Cdrag )
344            zcof = 0.5 * 0.016 * 0.016 / ( zrhoa * zcdrag )      ! to convert stress in 10m wind using a constant drag
345            DO_2D( 1, 1, 1, 1 )
346               zWlc2(ji,jj) = zcof * taum(ji,jj)
347            END_2D
348            !
349         ENDIF
350         !
351         !                       !* Depth of the LC circulation  (Axell 2002, Eq.47)
352         !                             !- LHS of Eq.47
353         zpelc(:,:,1) =  MAX( rn2b(:,:,1), 0._wp ) * gdepw(:,:,1,Kmm) * e3w(:,:,1,Kmm)
354         DO jk = 2, jpk
355            zpelc(:,:,jk)  = zpelc(:,:,jk-1) +   &
356               &        MAX( rn2b(:,:,jk), 0._wp ) * gdepw(:,:,jk,Kmm) * e3w(:,:,jk,Kmm)
357         END DO
358         !
359         !                             !- compare LHS to RHS of Eq.47
360         imlc(:,:) = mbkt(:,:) + 1       ! Initialization to the number of w ocean point (=2 over land)
361         DO_3DS( 1, 1, 1, 1, jpkm1, 2, -1 )
362            IF( zpelc(ji,jj,jk) > zWlc2(ji,jj) )   imlc(ji,jj) = jk
363         END_3D
364         !                               ! finite LC depth
365         DO_2D( 1, 1, 1, 1 )
366            zhlc(ji,jj) = gdepw(ji,jj,imlc(ji,jj),Kmm)
367         END_2D
368         !
369         zcof = 0.016 / SQRT( zrhoa * zcdrag )
370         DO_2D( 0, 0, 0, 0 )
371            zus = SQRT( 2. * zWlc2(ji,jj) )             ! Stokes drift
372            zus3(ji,jj) = MAX( 0._wp, 1._wp - zice_fra(ji,jj) ) * zus * zus * zus * tmask(ji,jj,1) ! zus > 0. ok
373         END_2D
374         DO_3D( 0, 0, 0, 0, 2, jpkm1 )                  !* TKE Langmuir circulation source term added to en
375            IF ( zus3(ji,jj) /= 0._wp ) THEN               
376               IF ( gdepw(ji,jj,jk,Kmm) - zhlc(ji,jj) < 0 .AND. wmask(ji,jj,jk) /= 0. ) THEN
377                  !                                           ! vertical velocity due to LC
378                  zwlc = rn_lc * SIN( rpi * gdepw(ji,jj,jk,Kmm) / zhlc(ji,jj) )
379                  !                                           ! TKE Langmuir circulation source term
380                  en(ji,jj,jk) = en(ji,jj,jk) + rn_Dt * zus3(ji,jj) * ( zwlc * zwlc * zwlc ) / zhlc(ji,jj)
381               ENDIF
382            ENDIF
383         END_3D
384         !
385      ENDIF
386      !
387      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
388      !                     !  Now Turbulent kinetic energy (output in en)
389      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
390      !                     ! Resolution of a tridiagonal linear system by a "methode de chasse"
391      !                     ! computation from level 2 to jpkm1  (e(1) already computed and e(jpk)=0 ).
392      !                     ! zdiag : diagonal zd_up : upper diagonal zd_lw : lower diagonal
393      !
394      IF( nn_pdl == 1 ) THEN          !* Prandtl number = F( Ri )
395         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
396            !                             ! local Richardson number
397            IF (rn2b(ji,jj,jk) <= 0.0_wp) then
398                zri = 0.0_wp
399            ELSE
400                zri = rn2b(ji,jj,jk) * p_avm(ji,jj,jk) / ( p_sh2(ji,jj,jk) + rn_bshear )
401            ENDIF
402            !                             ! inverse of Prandtl number
403            apdlr(ji,jj,jk) = MAX(  0.1_wp,  ri_cri / MAX( ri_cri , zri )  )
404         END_3D
405      ENDIF
406      !         
407      DO_3D( 0, 0, 0, 0, 2, jpkm1 )   !* Matrix and right hand side in en
408         zcof   = zfact1 * tmask(ji,jj,jk)
409         !                                   ! A minimum of 2.e-5 m2/s is imposed on TKE vertical
410         !                                   ! eddy coefficient (ensure numerical stability)
411         zzd_up = zcof * MAX(  p_avm(ji,jj,jk+1) + p_avm(ji,jj,jk  ) , 2.e-5_wp  )   &  ! upper diagonal
412            &          /    (  e3t(ji,jj,jk  ,Kmm) * e3w(ji,jj,jk  ,Kmm)  )
413         zzd_lw = zcof * MAX(  p_avm(ji,jj,jk  ) + p_avm(ji,jj,jk-1) , 2.e-5_wp  )   &  ! lower diagonal
414            &          /    (  e3t(ji,jj,jk-1,Kmm) * e3w(ji,jj,jk  ,Kmm)  )
415         !
416         zd_up(ji,jj,jk) = zzd_up            ! Matrix (zdiag, zd_up, zd_lw)
417         zd_lw(ji,jj,jk) = zzd_lw
418         zdiag(ji,jj,jk) = 1._wp - zzd_lw - zzd_up + zfact2 * dissl(ji,jj,jk) * wmask(ji,jj,jk)
419         !
420         !                                   ! right hand side in en
421         en(ji,jj,jk) = en(ji,jj,jk) + rn_Dt * (  p_sh2(ji,jj,jk)                        &   ! shear
422            &                                 - p_avt(ji,jj,jk) * rn2(ji,jj,jk)          &   ! stratification
423            &                                 + zfact3 * dissl(ji,jj,jk) * en(ji,jj,jk)  &   ! dissipation
424            &                                ) * wmask(ji,jj,jk)
425      END_3D
426      !
427      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
428      !                            ! choose to keep coherence with previous estimation of
429      !                            !  Surface boundary condition on tke
430      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
431      ![EC] should it be removed?
432      IF ( ln_isfcav ) THEN
433         DO_2D( 1, 1, 1, 1 )       ! en(mikt(ji,jj))   = rn_emin
434            en(ji,jj,mikt(ji,jj))=rn_emin * tmask(ji,jj,1)
435         END_2D
436      END IF
437      !
438      !                          !* Matrix inversion from level 2 (tke prescribed at level 1)
439!      DO_3D( 0, 0, 0, 0, 3, jpkm1 )                ! First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1
440      DO_3D( 0, 0, 0, 0, 2, jpkm1 )                ! First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1
441         zdiag(ji,jj,jk) = zdiag(ji,jj,jk) - zd_lw(ji,jj,jk) * zd_up(ji,jj,jk-1) / zdiag(ji,jj,jk-1)
442      END_3D
443!XC : commented to allow for neumann boundary condition
444!      DO_2D( 0, 0, 0, 0 )
445!         zd_lw(ji,jj,2) = en(ji,jj,2) - zd_lw(ji,jj,2) * en(ji,jj,1)    ! Surface boudary conditions on tke
446!      END_2D
447!      DO_3D( 0, 0, 0, 0, 3, jpkm1 )
448      DO_3D( 0, 0, 0, 0, 2, jpkm1 )
449         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)
450      END_3D
451      DO_2D( 0, 0, 0, 0 )                          ! thrid recurrence : Ek = ( Lk - Uk * Ek+1 ) / Dk
452         en(ji,jj,jpkm1) = zd_lw(ji,jj,jpkm1) / zdiag(ji,jj,jpkm1)
453      END_2D
454      DO_3DS( 0, 0, 0, 0, jpk-2, 2, -1 )
455         en(ji,jj,jk) = ( zd_lw(ji,jj,jk) - zd_up(ji,jj,jk) * en(ji,jj,jk+1) ) / zdiag(ji,jj,jk)
456      END_3D
457      DO_3D( 0, 0, 0, 0, 2, jpkm1 )                ! set the minimum value of tke
458         en(ji,jj,jk) = MAX( en(ji,jj,jk), rn_emin ) * wmask(ji,jj,jk)
459      END_3D
460      !
461      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
462      !                            !  TKE due to surface and internal wave breaking
463      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
464!!gm BUG : in the exp  remove the depth of ssh !!!
465!!gm       i.e. use gde3w in argument (gdepw(:,:,:,Kmm))
466      !
467      ! penetration is partly switched off below sea-ice if nn_eice/=0
468      !
469      IF( nn_etau == 1 ) THEN           !* penetration below the mixed layer (rn_efr fraction)
470         DO_3D( 0, 0, 0, 0, 2, jpkm1 ) 
471            en(ji,jj,jk) = en(ji,jj,jk) + rn_efr * en(ji,jj,1) * EXP( -gdepw(ji,jj,jk,Kmm) / htau(ji,jj) )   &
472               &                                 * MAX( 0._wp, 1._wp - zice_fra(ji,jj) ) * wmask(ji,jj,jk) * tmask(ji,jj,1)
473         END_3D
474      ELSEIF( nn_etau == 2 ) THEN       !* act only at the base of the mixed layer (jk=nmln)  (rn_efr fraction)
475         DO_2D( 0, 0, 0, 0 )
476            jk = nmln(ji,jj)
477            en(ji,jj,jk) = en(ji,jj,jk) + rn_efr * en(ji,jj,1) * EXP( -gdepw(ji,jj,jk,Kmm) / htau(ji,jj) )   &
478               &                                 * MAX( 0._wp, 1._wp - zice_fra(ji,jj) ) * wmask(ji,jj,jk) * tmask(ji,jj,1)
479         END_2D
480      ELSEIF( nn_etau == 3 ) THEN       !* penetration belox the mixed layer (HF variability)
481         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
482            ztx2 = utau(ji-1,jj  ) + utau(ji,jj)
483            zty2 = vtau(ji  ,jj-1) + vtau(ji,jj)
484            ztau = 0.5_wp * SQRT( ztx2 * ztx2 + zty2 * zty2 ) * tmask(ji,jj,1)    ! module of the mean stress
485            zdif = taum(ji,jj) - ztau                            ! mean of modulus - modulus of the mean
486            zdif = rhftau_scl * MAX( 0._wp, zdif + rhftau_add )  ! apply some modifications...
487            en(ji,jj,jk) = en(ji,jj,jk) + zbbrau * zdif * EXP( -gdepw(ji,jj,jk,Kmm) / htau(ji,jj) )   &
488               &                        * MAX( 0._wp, 1._wp - zice_fra(ji,jj) ) * wmask(ji,jj,jk) * tmask(ji,jj,1)
489         END_3D
490      ENDIF
491      !
492   END SUBROUTINE tke_tke
493
494
495   SUBROUTINE tke_avn( Kbb, Kmm, p_avm, p_avt )
496      !!----------------------------------------------------------------------
497      !!                   ***  ROUTINE tke_avn  ***
498      !!
499      !! ** Purpose :   Compute the vertical eddy viscosity and diffusivity
500      !!
501      !! ** Method  :   At this stage, en, the now TKE, is known (computed in
502      !!              the tke_tke routine). First, the now mixing lenth is
503      !!      computed from en and the strafification (N^2), then the mixings
504      !!      coefficients are computed.
505      !!              - Mixing length : a first evaluation of the mixing lengh
506      !!      scales is:
507      !!                      mxl = sqrt(2*en) / N 
508      !!      where N is the brunt-vaisala frequency, with a minimum value set
509      !!      to rmxl_min (rn_mxl0) in the interior (surface) ocean.
510      !!        The mixing and dissipative length scale are bound as follow :
511      !!         nn_mxl=0 : mxl bounded by the distance to surface and bottom.
512      !!                        zmxld = zmxlm = mxl
513      !!         nn_mxl=1 : mxl bounded by the e3w and zmxld = zmxlm = mxl
514      !!         nn_mxl=2 : mxl bounded such that the vertical derivative of mxl is
515      !!                    less than 1 (|d/dz(mxl)|<1) and zmxld = zmxlm = mxl
516      !!         nn_mxl=3 : mxl is bounded from the surface to the bottom usings
517      !!                    |d/dz(xml)|<1 to obtain lup, and from the bottom to
518      !!                    the surface to obtain ldown. the resulting length
519      !!                    scales are:
520      !!                        zmxld = sqrt( lup * ldown )
521      !!                        zmxlm = min ( lup , ldown )
522      !!              - Vertical eddy viscosity and diffusivity:
523      !!                      avm = max( avtb, rn_ediff * zmxlm * en^1/2 )
524      !!                      avt = max( avmb, pdlr * avm ) 
525      !!      with pdlr=1 if nn_pdl=0, pdlr=1/pdl=F(Ri) otherwise.
526      !!
527      !! ** Action  : - avt, avm : now vertical eddy diffusivity and viscosity (w-point)
528      !!----------------------------------------------------------------------
529      USE zdf_oce , ONLY : en, avtb, avmb, avtb_2d   ! ocean vertical physics
530      !!
531      INTEGER                   , INTENT(in   ) ::   Kbb, Kmm       ! ocean time level indices
532      REAL(wp), DIMENSION(:,:,:), INTENT(  out) ::   p_avm, p_avt   ! vertical eddy viscosity & diffusivity (w-points)
533      !
534      INTEGER  ::   ji, jj, jk   ! dummy loop indices
535      REAL(wp) ::   zrn2, zraug, zcoef, zav   ! local scalars
536      REAL(wp) ::   zdku,   zdkv, zsqen       !   -      -
537      REAL(wp) ::   zemxl, zemlm, zemlp, zmaxice       !   -      -
538      REAL(wp), DIMENSION(jpi,jpj,jpk) ::   zmxlm, zmxld   ! 3D workspace
539      !!--------------------------------------------------------------------
540      !
541      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
542      !                     !  Mixing length
543      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
544      !
545      !                     !* Buoyancy length scale: l=sqrt(2*e/n**2)
546      !
547      ! initialisation of interior minimum value (avoid a 2d loop with mikt)
548      zmxlm(:,:,:)  = rmxl_min   
549      zmxld(:,:,:)  = rmxl_min
550      !
551      IF(ln_sdw .AND. ln_mxhsw) THEN
552         zmxlm(:,:,1)= vkarmn * MAX ( 1.6 * hsw(:,:) , 0.02 )        ! surface mixing length = F(wave height)
553         ! from terray et al 1999 and mellor and blumberg 2004 it should be 0.85 and not 1.6
554         zcoef       = vkarmn * ( (rn_ediff*rn_ediss)**0.25 ) / rn_ediff
555         zmxlm(:,:,1)= zcoef * MAX ( 1.6 * hsw(:,:) , 0.02 )        ! surface mixing length = F(wave height)
556      ELSE
557      !
558         IF( ln_mxl0 ) THEN            ! surface mixing length = F(stress) : l=vkarmn*2.e5*taum/(rho0*g)
559         !
560            zraug = vkarmn * 2.e5_wp / ( rho0 * grav )
561#if ! defined key_si3 && ! defined key_cice
562            DO_2D( 0, 0, 0, 0 )                  ! No sea-ice
563               zmxlm(ji,jj,1) =  zraug * taum(ji,jj) * tmask(ji,jj,1)
564            END_2D
565#else
566            SELECT CASE( nn_mxlice )             ! Type of scaling under sea-ice
567            !
568            CASE( 0 )                      ! No scaling under sea-ice
569               DO_2D( 0, 0, 0, 0 )
570                  zmxlm(ji,jj,1) = zraug * taum(ji,jj) * tmask(ji,jj,1)
571               END_2D
572               !
573            CASE( 1 )                      ! scaling with constant sea-ice thickness
574               DO_2D( 0, 0, 0, 0 )
575                  zmxlm(ji,jj,1) =  ( ( 1._wp - fr_i(ji,jj) ) * zraug * taum(ji,jj) + &
576                     &                          fr_i(ji,jj)   * rn_mxlice           ) * tmask(ji,jj,1)
577               END_2D
578               !
579            CASE( 2 )                      ! scaling with mean sea-ice thickness
580               DO_2D( 0, 0, 0, 0 )
581#if defined key_si3
582                  zmxlm(ji,jj,1) = ( ( 1._wp - fr_i(ji,jj) ) * zraug * taum(ji,jj) + &
583                     &                         fr_i(ji,jj)   * hm_i(ji,jj) * 2._wp ) * tmask(ji,jj,1)
584#elif defined key_cice
585                  zmaxice = MAXVAL( h_i(ji,jj,:) )
586                  zmxlm(ji,jj,1) = ( ( 1._wp - fr_i(ji,jj) ) * zraug * taum(ji,jj) + &
587                     &                         fr_i(ji,jj)   * zmaxice             ) * tmask(ji,jj,1)
588#endif
589               END_2D
590               !
591            CASE( 3 )                      ! scaling with max sea-ice thickness
592               DO_2D( 0, 0, 0, 0 )
593                  zmaxice = MAXVAL( h_i(ji,jj,:) )
594                  zmxlm(ji,jj,1) = ( ( 1._wp - fr_i(ji,jj) ) * zraug * taum(ji,jj) + &
595                     &                         fr_i(ji,jj)   * zmaxice             ) * tmask(ji,jj,1)
596               END_2D
597               !
598            END SELECT
599#endif
600            !
601            DO_2D( 0, 0, 0, 0 )
602               zmxlm(ji,jj,1) = MAX( rn_mxl0, zmxlm(ji,jj,1) )
603            END_2D
604            !
605         ELSE
606            zmxlm(:,:,1) = rn_mxl0
607         ENDIF
608      ENDIF
609      !
610      DO_3D( 0, 0, 0, 0, 2, jpkm1 )
611         zrn2 = MAX( rn2(ji,jj,jk), rsmall )
612         zmxlm(ji,jj,jk) = MAX(  rmxl_min,  SQRT( 2._wp * en(ji,jj,jk) / zrn2 )  )
613      END_3D
614      !
615      !                     !* Physical limits for the mixing length
616      !
617      zmxld(:,:, 1 ) = zmxlm(:,:,1)   ! surface set to the minimum value
618      zmxld(:,:,jpk) = rmxl_min       ! last level  set to the minimum value
619      !
620      SELECT CASE ( nn_mxl )
621      !
622 !!gm Not sure of that coding for ISF....
623      ! where wmask = 0 set zmxlm == e3w(:,:,:,Kmm)
624      CASE ( 0 )           ! bounded by the distance to surface and bottom
625         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
626            zemxl = MIN( gdepw(ji,jj,jk,Kmm) - gdepw(ji,jj,mikt(ji,jj),Kmm), zmxlm(ji,jj,jk),   &
627            &            gdepw(ji,jj,mbkt(ji,jj)+1,Kmm) - gdepw(ji,jj,jk,Kmm) )
628            ! wmask prevent zmxlm = 0 if jk = mikt(ji,jj)
629            zmxlm(ji,jj,jk) = zemxl * wmask(ji,jj,jk)   &
630               &            + MIN( zmxlm(ji,jj,jk) , e3w(ji,jj,jk,Kmm) ) * (1 - wmask(ji,jj,jk))
631            zmxld(ji,jj,jk) = zemxl * wmask(ji,jj,jk)   &
632               &            + MIN( zmxlm(ji,jj,jk) , e3w(ji,jj,jk,Kmm) ) * (1 - wmask(ji,jj,jk))
633         END_3D
634         !
635      CASE ( 1 )           ! bounded by the vertical scale factor
636         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
637            zemxl = MIN( e3w(ji,jj,jk,Kmm), zmxlm(ji,jj,jk) )
638            zmxlm(ji,jj,jk) = zemxl
639            zmxld(ji,jj,jk) = zemxl
640         END_3D
641         !
642      CASE ( 2 )           ! |dk[xml]| bounded by e3t :
643         DO_3D( 0, 0, 0, 0, 2, jpkm1 )        ! from the surface to the bottom :
644            zmxlm(ji,jj,jk) =   &
645               &    MIN( zmxlm(ji,jj,jk-1) + e3t(ji,jj,jk-1,Kmm), zmxlm(ji,jj,jk) )
646         END_3D
647         DO_3DS( 0, 0, 0, 0, jpkm1, 2, -1 )   ! from the bottom to the surface :
648            zemxl = MIN( zmxlm(ji,jj,jk+1) + e3t(ji,jj,jk+1,Kmm), zmxlm(ji,jj,jk) )
649            zmxlm(ji,jj,jk) = zemxl
650            zmxld(ji,jj,jk) = zemxl
651         END_3D
652         !
653      CASE ( 3 )           ! lup and ldown, |dk[xml]| bounded by e3t :
654         DO_3D( 0, 0, 0, 0, 2, jpkm1 )        ! from the surface to the bottom : lup
655            zmxld(ji,jj,jk) =    &
656               &    MIN( zmxld(ji,jj,jk-1) + e3t(ji,jj,jk-1,Kmm), zmxlm(ji,jj,jk) )
657         END_3D
658         DO_3DS( 0, 0, 0, 0, jpkm1, 2, -1 )   ! from the bottom to the surface : ldown
659            zmxlm(ji,jj,jk) =   &
660               &    MIN( zmxlm(ji,jj,jk+1) + e3t(ji,jj,jk+1,Kmm), zmxlm(ji,jj,jk) )
661         END_3D
662         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
663            zemlm = MIN ( zmxld(ji,jj,jk),  zmxlm(ji,jj,jk) )
664            zemlp = SQRT( zmxld(ji,jj,jk) * zmxlm(ji,jj,jk) )
665            zmxlm(ji,jj,jk) = zemlm
666            zmxld(ji,jj,jk) = zemlp
667         END_3D
668         !
669      END SELECT
670      !
671      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
672      !                     !  Vertical eddy viscosity and diffusivity  (avm and avt)
673      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
674      DO_3D( 0, 0, 0, 0, 1, jpkm1 )   !* vertical eddy viscosity & diffivity at w-points
675         zsqen = SQRT( en(ji,jj,jk) )
676         zav   = rn_ediff * zmxlm(ji,jj,jk) * zsqen
677         p_avm(ji,jj,jk) = MAX( zav,                  avmb(jk) ) * wmask(ji,jj,jk)
678         p_avt(ji,jj,jk) = MAX( zav, avtb_2d(ji,jj) * avtb(jk) ) * wmask(ji,jj,jk)
679         dissl(ji,jj,jk) = zsqen / zmxld(ji,jj,jk)
680      END_3D
681      !
682      !
683      IF( nn_pdl == 1 ) THEN          !* Prandtl number case: update avt
684         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
685            p_avt(ji,jj,jk)   = MAX( apdlr(ji,jj,jk) * p_avt(ji,jj,jk), avtb_2d(ji,jj) * avtb(jk) ) * wmask(ji,jj,jk)
686         END_3D
687      ENDIF
688      !
689      IF(sn_cfctl%l_prtctl) THEN
690         CALL prt_ctl( tab3d_1=en   , clinfo1=' tke  - e: ', tab3d_2=p_avt, clinfo2=' t: ', kdim=jpk)
691         CALL prt_ctl( tab3d_1=p_avm, clinfo1=' tke  - m: ', kdim=jpk )
692      ENDIF
693      !
694   END SUBROUTINE tke_avn
695
696
697   SUBROUTINE zdf_tke_init( Kmm )
698      !!----------------------------------------------------------------------
699      !!                  ***  ROUTINE zdf_tke_init  ***
700      !!                     
701      !! ** Purpose :   Initialization of the vertical eddy diffivity and
702      !!              viscosity when using a tke turbulent closure scheme
703      !!
704      !! ** Method  :   Read the namzdf_tke namelist and check the parameters
705      !!              called at the first timestep (nit000)
706      !!
707      !! ** input   :   Namlist namzdf_tke
708      !!
709      !! ** Action  :   Increase by 1 the nstop flag is setting problem encounter
710      !!----------------------------------------------------------------------
711      USE zdf_oce , ONLY : ln_zdfiwm   ! Internal Wave Mixing flag
712      !!
713      INTEGER, INTENT(in) ::   Kmm          ! time level index
714      INTEGER             ::   ji, jj, jk   ! dummy loop indices
715      INTEGER             ::   ios
716      !!
717      NAMELIST/namzdf_tke/ rn_ediff, rn_ediss , rn_ebb   , rn_emin  ,  &
718         &                 rn_emin0, rn_bshear, nn_mxl   , ln_mxl0  ,  &
719         &                 rn_mxl0 , nn_mxlice, rn_mxlice,             &
720         &                 nn_pdl  , ln_lc    , rn_lc    ,             &
721         &                 nn_etau , nn_htau  , rn_efr   , nn_eice  ,  &   
722         &                 nn_bc_surf, nn_bc_bot, ln_mxhsw
723      !!----------------------------------------------------------------------
724      !
725      READ  ( numnam_ref, namzdf_tke, IOSTAT = ios, ERR = 901)
726901   IF( ios /= 0 ) CALL ctl_nam ( ios , 'namzdf_tke in reference namelist' )
727
728      READ  ( numnam_cfg, namzdf_tke, IOSTAT = ios, ERR = 902 )
729902   IF( ios >  0 ) CALL ctl_nam ( ios , 'namzdf_tke in configuration namelist' )
730      IF(lwm) WRITE ( numond, namzdf_tke )
731      !
732      ri_cri   = 2._wp    / ( 2._wp + rn_ediss / rn_ediff )   ! resulting critical Richardson number
733      !
734      IF(lwp) THEN                    !* Control print
735         WRITE(numout,*)
736         WRITE(numout,*) 'zdf_tke_init : tke turbulent closure scheme - initialisation'
737         WRITE(numout,*) '~~~~~~~~~~~~'
738         WRITE(numout,*) '   Namelist namzdf_tke : set tke mixing parameters'
739         WRITE(numout,*) '      coef. to compute avt                        rn_ediff  = ', rn_ediff
740         WRITE(numout,*) '      Kolmogoroff dissipation coef.               rn_ediss  = ', rn_ediss
741         WRITE(numout,*) '      tke surface input coef.                     rn_ebb    = ', rn_ebb
742         WRITE(numout,*) '      minimum value of tke                        rn_emin   = ', rn_emin
743         WRITE(numout,*) '      surface minimum value of tke                rn_emin0  = ', rn_emin0
744         WRITE(numout,*) '      prandl number flag                          nn_pdl    = ', nn_pdl
745         WRITE(numout,*) '      background shear (>0)                       rn_bshear = ', rn_bshear
746         WRITE(numout,*) '      mixing length type                          nn_mxl    = ', nn_mxl
747         WRITE(numout,*) '         surface mixing length = F(stress) or not    ln_mxl0   = ', ln_mxl0
748         WRITE(numout,*) '         surface  mixing length minimum value        rn_mxl0   = ', rn_mxl0
749         IF( ln_mxl0 ) THEN
750            WRITE(numout,*) '      type of scaling under sea-ice               nn_mxlice = ', nn_mxlice
751            IF( nn_mxlice == 1 ) &
752            WRITE(numout,*) '      ice thickness when scaling under sea-ice    rn_mxlice = ', rn_mxlice
753            SELECT CASE( nn_mxlice )             ! Type of scaling under sea-ice
754            CASE( 0 )   ;   WRITE(numout,*) '   ==>>>   No scaling under sea-ice'
755            CASE( 1 )   ;   WRITE(numout,*) '   ==>>>   scaling with constant sea-ice thickness'
756            CASE( 2 )   ;   WRITE(numout,*) '   ==>>>   scaling with mean sea-ice thickness'
757            CASE( 3 )   ;   WRITE(numout,*) '   ==>>>   scaling with max sea-ice thickness'
758            CASE DEFAULT
759               CALL ctl_stop( 'zdf_tke_init: wrong value for nn_mxlice, should be 0,1,2,3 or 4')
760            END SELECT
761         ENDIF
762         WRITE(numout,*) '      Langmuir cells parametrization              ln_lc     = ', ln_lc
763         WRITE(numout,*) '         coef to compute vertical velocity of LC     rn_lc  = ', rn_lc
764         IF ( cpl_phioc .and. ln_phioc )  THEN
765            SELECT CASE( nn_bc_surf)             ! Type of scaling under sea-ice
766            CASE( 0 )   ;   WRITE(numout,*) '  nn_bc_surf=0 ==>>> DIRICHLET SBC using surface TKE flux from waves'
767            CASE( 1 )   ;   WRITE(numout,*) '  nn_bc_surf=1 ==>>> NEUMANN SBC using surface TKE flux from waves'
768            END SELECT
769         ENDIF
770         WRITE(numout,*) '      test param. to add tke induced by wind      nn_etau   = ', nn_etau
771         WRITE(numout,*) '          type of tke penetration profile            nn_htau   = ', nn_htau
772         WRITE(numout,*) '          fraction of TKE that penetrates            rn_efr    = ', rn_efr
773         WRITE(numout,*) '      langmuir & surface wave breaking under ice  nn_eice = ', nn_eice
774         SELECT CASE( nn_eice ) 
775         CASE( 0 )   ;   WRITE(numout,*) '   ==>>>   no impact of ice cover on langmuir & surface wave breaking'
776         CASE( 1 )   ;   WRITE(numout,*) '   ==>>>   weigthed by 1-TANH( fr_i(:,:) * 10 )'
777         CASE( 2 )   ;   WRITE(numout,*) '   ==>>>   weighted by 1-fr_i(:,:)'
778         CASE( 3 )   ;   WRITE(numout,*) '   ==>>>   weighted by 1-MIN( 1, 4 * fr_i(:,:) )'
779         CASE DEFAULT
780            CALL ctl_stop( 'zdf_tke_init: wrong value for nn_eice, should be 0,1,2, or 3')
781         END SELECT     
782         WRITE(numout,*)
783         WRITE(numout,*) '   ==>>>   critical Richardson nb with your parameters  ri_cri = ', ri_cri
784         WRITE(numout,*)
785      ENDIF
786      !
787      IF( ln_zdfiwm ) THEN          ! Internal wave-driven mixing
788         rn_emin  = 1.e-10_wp             ! specific values of rn_emin & rmxl_min are used
789         rmxl_min = 1.e-03_wp             ! associated avt minimum = molecular salt diffusivity (10^-9 m2/s)
790         IF(lwp) WRITE(numout,*) '   ==>>>   Internal wave-driven mixing case:   force   rn_emin = 1.e-10 and rmxl_min = 1.e-3'
791      ELSE                          ! standard case : associated avt minimum = molecular viscosity (10^-6 m2/s)
792         rmxl_min = 1.e-6_wp / ( rn_ediff * SQRT( rn_emin ) )    ! resulting minimum length to recover molecular viscosity
793         IF(lwp) WRITE(numout,*) '   ==>>>   minimum mixing length with your parameters rmxl_min = ', rmxl_min
794      ENDIF
795      !
796      !                              ! allocate tke arrays
797      IF( zdf_tke_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'zdf_tke_init : unable to allocate arrays' )
798      !
799      !                               !* Check of some namelist values
800      IF( nn_mxl  < 0   .OR.  nn_mxl  > 3 )   CALL ctl_stop( 'bad flag: nn_mxl is  0, 1 or 2 ' )
801      IF( nn_pdl  < 0   .OR.  nn_pdl  > 1 )   CALL ctl_stop( 'bad flag: nn_pdl is  0 or 1    ' )
802      IF( nn_htau < 0   .OR.  nn_htau > 1 )   CALL ctl_stop( 'bad flag: nn_htau is 0, 1 or 2 ' )
803      IF( nn_etau == 3 .AND. .NOT. ln_cpl )   CALL ctl_stop( 'nn_etau == 3 : HF taum only known in coupled mode' )
804      !
805      IF( ln_mxl0 ) THEN
806         IF(lwp) WRITE(numout,*)
807         IF(lwp) WRITE(numout,*) '   ==>>>   use a surface mixing length = F(stress) :   set rn_mxl0 = rmxl_min'
808         rn_mxl0 = rmxl_min
809      ENDIF
810     
811      IF( nn_etau == 2  )   CALL zdf_mxl( nit000, Kmm )      ! Initialization of nmln
812
813      !                               !* depth of penetration of surface tke
814      IF( nn_etau /= 0 ) THEN     
815         SELECT CASE( nn_htau )             ! Choice of the depth of penetration
816         CASE( 0 )                                 ! constant depth penetration (here 10 meters)
817            htau(:,:) = 10._wp
818         CASE( 1 )                                 ! F(latitude) : 0.5m to 30m poleward of 40 degrees
819            htau(:,:) = MAX(  0.5_wp, MIN( 30._wp, 45._wp* ABS( SIN( rpi/180._wp * gphit(:,:) ) ) )   )           
820         END SELECT
821      ENDIF
822      !                                !* read or initialize all required files
823      CALL tke_rst( nit000, 'READ' )      ! (en, avt_k, avm_k, dissl)
824      !
825      IF( lwxios ) THEN
826         CALL iom_set_rstw_var_active('en')
827         CALL iom_set_rstw_var_active('avt_k')
828         CALL iom_set_rstw_var_active('avm_k')
829         CALL iom_set_rstw_var_active('dissl')
830      ENDIF
831   END SUBROUTINE zdf_tke_init
832
833
834   SUBROUTINE tke_rst( kt, cdrw )
835      !!---------------------------------------------------------------------
836      !!                   ***  ROUTINE tke_rst  ***
837      !!                     
838      !! ** Purpose :   Read or write TKE file (en) in restart file
839      !!
840      !! ** Method  :   use of IOM library
841      !!                if the restart does not contain TKE, en is either
842      !!                set to rn_emin or recomputed
843      !!----------------------------------------------------------------------
844      USE zdf_oce , ONLY : en, avt_k, avm_k   ! ocean vertical physics
845      !!
846      INTEGER         , INTENT(in) ::   kt     ! ocean time-step
847      CHARACTER(len=*), INTENT(in) ::   cdrw   ! "READ"/"WRITE" flag
848      !
849      INTEGER ::   jit, jk              ! dummy loop indices
850      INTEGER ::   id1, id2, id3, id4   ! local integers
851      !!----------------------------------------------------------------------
852      !
853      IF( TRIM(cdrw) == 'READ' ) THEN        ! Read/initialise
854         !                                   ! ---------------
855         IF( ln_rstart ) THEN                   !* Read the restart file
856            id1 = iom_varid( numror, 'en'   , ldstop = .FALSE. )
857            id2 = iom_varid( numror, 'avt_k', ldstop = .FALSE. )
858            id3 = iom_varid( numror, 'avm_k', ldstop = .FALSE. )
859            id4 = iom_varid( numror, 'dissl', ldstop = .FALSE. )
860            !
861            IF( MIN( id1, id2, id3, id4 ) > 0 ) THEN      ! fields exist
862               CALL iom_get( numror, jpdom_auto, 'en'   , en   , ldxios = lrxios )
863               CALL iom_get( numror, jpdom_auto, 'avt_k', avt_k, ldxios = lrxios )
864               CALL iom_get( numror, jpdom_auto, 'avm_k', avm_k, ldxios = lrxios )
865               CALL iom_get( numror, jpdom_auto, 'dissl', dissl, ldxios = lrxios )
866            ELSE                                          ! start TKE from rest
867               IF(lwp) WRITE(numout,*)
868               IF(lwp) WRITE(numout,*) '   ==>>>   previous run without TKE scheme, set en to background values'
869               en   (:,:,:) = rn_emin * wmask(:,:,:)
870               dissl(:,:,:) = 1.e-12_wp
871               ! avt_k, avm_k already set to the background value in zdf_phy_init
872            ENDIF
873         ELSE                                   !* Start from rest
874            IF(lwp) WRITE(numout,*)
875            IF(lwp) WRITE(numout,*) '   ==>>>   start from rest: set en to the background value'
876            en   (:,:,:) = rn_emin * wmask(:,:,:)
877            dissl(:,:,:) = 1.e-12_wp
878            ! avt_k, avm_k already set to the background value in zdf_phy_init
879         ENDIF
880         !
881      ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN   ! Create restart file
882         !                                   ! -------------------
883         IF(lwp) WRITE(numout,*) '---- tke_rst ----'
884         IF( lwxios ) CALL iom_swap(      cwxios_context          ) 
885         CALL iom_rstput( kt, nitrst, numrow, 'en'   , en   , ldxios = lwxios )
886         CALL iom_rstput( kt, nitrst, numrow, 'avt_k', avt_k, ldxios = lwxios )
887         CALL iom_rstput( kt, nitrst, numrow, 'avm_k', avm_k, ldxios = lwxios )
888         CALL iom_rstput( kt, nitrst, numrow, 'dissl', dissl, ldxios = lwxios )
889         IF( lwxios ) CALL iom_swap(      cxios_context          )
890         !
891      ENDIF
892      !
893   END SUBROUTINE tke_rst
894
895   !!======================================================================
896END MODULE zdftke
Note: See TracBrowser for help on using the repository browser.