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 @ 13759

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

minor changes to include writing statements and update n. of max coupling fields with oasis - tickets #2155 #2339

  • Property svn:keywords set to Id
File size: 50.2 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      DO_2D( 0, 0, 0, 0 )         ! en(1)   = rn_ebb taum / rau0  (min value rn_emin0)
242!! clem: this should be the right formulation but it makes the model unstable unless drags are calculated implicitly
243!!       one way around would be to increase zbbirau
244!!          en(ji,jj,1) = MAX( rn_emin0, ( ( 1._wp - fr_i(ji,jj) ) * zbbrau + &
245!!             &                                     fr_i(ji,jj)   * zbbirau ) * taum(ji,jj) ) * tmask(ji,jj,1)
246         en(ji,jj,1) = MAX( rn_emin0, zbbrau * taum(ji,jj) ) * tmask(ji,jj,1)
247      END_2D
248      !
249      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
250      !                     !  Bottom boundary condition on tke
251      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
252      !
253      !   en(bot)   = (ebb0/rho0)*0.5*sqrt(u_botfr^2+v_botfr^2) (min value rn_emin)
254      ! where ebb0 does not includes surface wave enhancement (i.e. ebb0=3.75)
255      ! Note that stress averaged is done using an wet-only calculation of u and v at t-point like in zdfsh2
256      !
257      IF( .NOT.ln_drg_OFF ) THEN    !== friction used as top/bottom boundary condition on TKE
258         !
259         DO_2D( 0, 0, 0, 0 )        ! bottom friction
260            zmsku = ( 2. - umask(ji-1,jj,mbkt(ji,jj)) * umask(ji,jj,mbkt(ji,jj)) )
261            zmskv = ( 2. - vmask(ji,jj-1,mbkt(ji,jj)) * vmask(ji,jj,mbkt(ji,jj)) )
262            !                       ! where 0.001875 = (rn_ebb0/rho0) * 0.5 = 3.75*0.5/1000. (CAUTION CdU<0)
263            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  &
264               &                                           + ( zmskv*( vv(ji,jj,mbkt(ji,jj),Kbb)+vv(ji,jj-1,mbkt(ji,jj),Kbb) ) )**2  )
265            en(ji,jj,mbkt(ji,jj)+1) = MAX( zebot, rn_emin ) * ssmask(ji,jj)
266         END_2D
267         IF( ln_isfcav ) THEN
268            DO_2D( 0, 0, 0, 0 )     ! top friction
269               zmsku = ( 2. - umask(ji-1,jj,mikt(ji,jj)) * umask(ji,jj,mikt(ji,jj)) )
270               zmskv = ( 2. - vmask(ji,jj-1,mikt(ji,jj)) * vmask(ji,jj,mikt(ji,jj)) )
271               !                             ! where 0.001875 = (rn_ebb0/rho0) * 0.5 = 3.75*0.5/1000.  (CAUTION CdU<0)
272               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  &
273                  &                                           + ( zmskv*( vv(ji,jj,mikt(ji,jj),Kbb)+vv(ji,jj-1,mikt(ji,jj),Kbb) ) )**2  )
274               ! (1._wp - tmask(ji,jj,1)) * ssmask(ji,jj) = 1 where ice shelves are present
275               en(ji,jj,mikt(ji,jj)) = en(ji,jj,1)           * tmask(ji,jj,1) &
276                  &                  + MAX( zetop, rn_emin ) * (1._wp - tmask(ji,jj,1)) * ssmask(ji,jj)
277            END_2D
278         ENDIF
279         !
280      ENDIF
281      !
282      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
283      IF( ln_lc ) THEN      !  Langmuir circulation source term added to tke (Axell JGR 2002)
284         !                  !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
285         !
286         !                       !* Langmuir velocity scale
287         !
288         IF ( cpl_sdrftx )  THEN       ! Surface Stokes Drift available
289            !                                ! Craik-Leibovich velocity scale Wlc = ( u* u_s )^1/2    with u* = (taum/rho0)^1/2
290            !                                ! associated kinetic energy : 1/2 (Wlc)^2 = u* u_s
291            !                                ! more precisely, it is the dot product that must be used :
292            !                                !     1/2  (W_lc)^2 = MAX( u* u_s + v* v_s , 0 )   only the positive part
293!!gm  ! PS: currently we don't have neither the 2 stress components at t-point !nor the angle between u* and u_s
294!!gm  ! so we will overestimate the LC velocity....   !!gm I will do the work if !LC have an effect !
295            DO_2D( 0, 0, 0, 0 )
296!!XC                  zWlc2(ji,jj) = 0.5_wp * SQRT( taum(ji,jj) * r1_rho0 * ( ut0sd(ji,jj)**2 +vt0sd(ji,jj)**2 )  )
297                  zWlc2(ji,jj) = 0.5_wp *  ( ut0sd(ji,jj)**2 +vt0sd(ji,jj)**2 )
298            END_2D
299!
300!  Projection of Stokes drift in the wind stress direction
301!
302            DO_2D( 0, 0, 0, 0 )
303                  ztaui   = 0.5_wp * ( utau(ji,jj) + utau(ji-1,jj) )
304                  ztauj   = 0.5_wp * ( vtau(ji,jj) + vtau(ji,jj-1) )
305                  z1_norm = 1._wp / MAX( SQRT(ztaui*ztaui+ztauj*ztauj), 1.e-12 ) * tmask(ji,jj,1)
306                  zWlc2(ji,jj) = 0.5_wp * z1_norm * ( MAX( ut0sd(ji,jj)*ztaui + vt0sd(ji,jj)*ztauj, 0._wp ) )**2
307            END_2D
308         CALL lbc_lnk      ( 'zdftke', zWlc2, 'T', 1. )
309!
310         ELSE                          ! Surface Stokes drift deduced from surface stress
311            !                                ! Wlc = u_s   with u_s = 0.016*U_10m, the surface stokes drift  (Axell 2002, Eq.44)
312            !                                ! using |tau| = rho_air Cd |U_10m|^2 , it comes:
313            !                                ! Wlc = 0.016 * [|tau|/(rho_air Cdrag) ]^1/2   and thus:
314            !                                ! 1/2 Wlc^2 = 0.5 * 0.016 * 0.016 |tau| /( rho_air Cdrag )
315            zcof = 0.5 * 0.016 * 0.016 / ( zrhoa * zcdrag )      ! to convert stress in 10m wind using a constant drag
316            DO_2D( 1, 1, 1, 1 )
317               zWlc2(ji,jj) = zcof * taum(ji,jj)
318            END_2D
319            !
320         ENDIF
321         !
322         !                       !* Depth of the LC circulation  (Axell 2002, Eq.47)
323         !                             !- LHS of Eq.47
324         zpelc(:,:,1) =  MAX( rn2b(:,:,1), 0._wp ) * gdepw(:,:,1,Kmm) * e3w(:,:,1,Kmm)
325         DO jk = 2, jpk
326            zpelc(:,:,jk)  = zpelc(:,:,jk-1) +   &
327               &        MAX( rn2b(:,:,jk), 0._wp ) * gdepw(:,:,jk,Kmm) * e3w(:,:,jk,Kmm)
328         END DO
329         !
330         !                             !- compare LHS to RHS of Eq.47
331         imlc(:,:) = mbkt(:,:) + 1       ! Initialization to the number of w ocean point (=2 over land)
332         DO_3DS( 1, 1, 1, 1, jpkm1, 2, -1 )
333            IF( zpelc(ji,jj,jk) > zWlc2(ji,jj) )   imlc(ji,jj) = jk
334         END_3D
335         !                               ! finite LC depth
336         DO_2D( 1, 1, 1, 1 )
337            zhlc(ji,jj) = gdepw(ji,jj,imlc(ji,jj),Kmm)
338         END_2D
339         !
340         zcof = 0.016 / SQRT( zrhoa * zcdrag )
341         DO_2D( 0, 0, 0, 0 )
342            zus = SQRT( 2. * zWlc2(ji,jj) )             ! Stokes drift
343            zus3(ji,jj) = MAX( 0._wp, 1._wp - zice_fra(ji,jj) ) * zus * zus * zus * tmask(ji,jj,1) ! zus > 0. ok
344         END_2D
345         DO_3D( 0, 0, 0, 0, 2, jpkm1 )                  !* TKE Langmuir circulation source term added to en
346            IF ( zus3(ji,jj) /= 0._wp ) THEN               
347               IF ( gdepw(ji,jj,jk,Kmm) - zhlc(ji,jj) < 0 .AND. wmask(ji,jj,jk) /= 0. ) THEN
348                  !                                           ! vertical velocity due to LC
349                  zwlc = rn_lc * SIN( rpi * gdepw(ji,jj,jk,Kmm) / zhlc(ji,jj) )
350                  !                                           ! TKE Langmuir circulation source term
351                  en(ji,jj,jk) = en(ji,jj,jk) + rn_Dt * zus3(ji,jj) * ( zwlc * zwlc * zwlc ) / zhlc(ji,jj)
352               ENDIF
353            ENDIF
354         END_3D
355         !
356      ENDIF
357      !
358      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
359      !                     !  Now Turbulent kinetic energy (output in en)
360      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
361      !                     ! Resolution of a tridiagonal linear system by a "methode de chasse"
362      !                     ! computation from level 2 to jpkm1  (e(1) already computed and e(jpk)=0 ).
363      !                     ! zdiag : diagonal zd_up : upper diagonal zd_lw : lower diagonal
364      !
365      IF( nn_pdl == 1 ) THEN          !* Prandtl number = F( Ri )
366         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
367            !                             ! local Richardson number
368            IF (rn2b(ji,jj,jk) <= 0.0_wp) then
369                zri = 0.0_wp
370            ELSE
371                zri = rn2b(ji,jj,jk) * p_avm(ji,jj,jk) / ( p_sh2(ji,jj,jk) + rn_bshear )
372            ENDIF
373            !                             ! inverse of Prandtl number
374            apdlr(ji,jj,jk) = MAX(  0.1_wp,  ri_cri / MAX( ri_cri , zri )  )
375         END_3D
376      ENDIF
377      !         
378      DO_3D( 0, 0, 0, 0, 2, jpkm1 )   !* Matrix and right hand side in en
379         zcof   = zfact1 * tmask(ji,jj,jk)
380         !                                   ! A minimum of 2.e-5 m2/s is imposed on TKE vertical
381         !                                   ! eddy coefficient (ensure numerical stability)
382         zzd_up = zcof * MAX(  p_avm(ji,jj,jk+1) + p_avm(ji,jj,jk  ) , 2.e-5_wp  )   &  ! upper diagonal
383            &          /    (  e3t(ji,jj,jk  ,Kmm) * e3w(ji,jj,jk  ,Kmm)  )
384         zzd_lw = zcof * MAX(  p_avm(ji,jj,jk  ) + p_avm(ji,jj,jk-1) , 2.e-5_wp  )   &  ! lower diagonal
385            &          /    (  e3t(ji,jj,jk-1,Kmm) * e3w(ji,jj,jk  ,Kmm)  )
386         !
387         zd_up(ji,jj,jk) = zzd_up            ! Matrix (zdiag, zd_up, zd_lw)
388         zd_lw(ji,jj,jk) = zzd_lw
389         zdiag(ji,jj,jk) = 1._wp - zzd_lw - zzd_up + zfact2 * dissl(ji,jj,jk) * wmask(ji,jj,jk)
390         !
391         !                                   ! right hand side in en
392         en(ji,jj,jk) = en(ji,jj,jk) + rn_Dt * (  p_sh2(ji,jj,jk)                        &   ! shear
393            &                                 - p_avt(ji,jj,jk) * rn2(ji,jj,jk)          &   ! stratification
394            &                                 + zfact3 * dissl(ji,jj,jk) * en(ji,jj,jk)  &   ! dissipation
395            &                                ) * wmask(ji,jj,jk)
396      END_3D
397      !
398      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
399      !                            ! choose to keep coherence with previous estimation of
400      !                            !  Surface boundary condition on tke
401      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
402      ! [EC] Should we keep this??
403      IF ( ln_isfcav ) THEN
404         DO_2D( 1, 1, 1, 1 )       ! en(mikt(ji,jj))   = rn_emin
405            en(ji,jj,mikt(ji,jj))=rn_emin * tmask(ji,jj,1)
406         END_2D
407      END IF
408
409      IF ( cpl_phioc .and. ln_phioc )  THEN
410         SELECT CASE (nn_bc_surf)  ! Boundary Condition using surface TKE flux from waves
411
412         CASE ( 0 ) ! Dirichlet BC
413
414            DO_2D( 0, 0, 0, 0 )    ! en(1)   = rn_ebb taum / rho0  (min value rn_emin0)
415               IF ( phioc(ji,jj) < 0 )  phioc(ji,jj) = 0._wp
416               en(ji,jj,1) = MAX( rn_emin0, .5 * ( 15.8 * phioc(ji,jj) / rho0 )**(2./3.) )  * tmask(ji,jj,1)
417               zdiag(ji,jj,1) = 1._wp/en(ji,jj,1)  ! choose to keep coherence with former estimation of
418               zd_lw(ji,jj,1) = 1._wp              ! zd_lw(ji,jj,2) = en(ji,jj,2) - zd_lw(ji,jj,2) * en(ji,jj,1)
419               zd_up(ji,jj,1) = 0._wp
420            END_2D
421
422         CASE ( 1 ) ! Neumann BC
423            DO_2D( 0, 0, 0, 0 )
424               IF ( phioc(ji,jj) < 0 )  phioc(ji,jj) = 0._wp
425               en(ji,jj,2)    = en(ji,jj,2) + ( rn_Dt * phioc(ji,jj) / rho0 ) /e3w(ji,jj,2,Kmm)
426               en(ji,jj,1)    = en(ji,jj,2) + (2 * e3t(ji,jj,1,Kmm) * phioc(ji,jj)) / ( p_avm(ji,jj,1) + p_avm(ji,jj,2) )
427               zdiag(ji,jj,2) = zdiag(ji,jj,2) + zd_lw(ji,jj,2)
428               zd_lw(ji,jj,2) = 0._wp
429               zd_up(ji,jj,1) = 0._wp
430            END_2D
431!
432         END SELECT
433
434      ELSE  ! TKE Dirichlet boundary condition (without wave coupling)
435
436         DO_2D( 0, 0, 0, 0 )       ! en(1)   = rn_ebb taum / rho0  (min value rn_emin0)
437            en(ji,jj,1) = MAX( rn_emin0, zbbrau * taum(ji,jj) ) * tmask(ji,jj,1)
438            zdiag(ji,jj,1) = 1._wp/en(ji,jj,1) ! choose to keep coherence with former estimation of
439            zd_lw(ji,jj,1) = 1._wp             ! zd_lw(ji,jj,2) = en(ji,jj,2) - zd_lw(ji,jj,2) * en(ji,jj,1)
440            zd_up(ji,jj,1) = 0._wp
441         END_2D
442
443      ENDIF
444      !
445      !                          !* Matrix inversion from level 2 (tke prescribed at level 1)
446!      DO_3D( 0, 0, 0, 0, 3, jpkm1 )                ! First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1
447      DO_3D( 0, 0, 0, 0, 2, jpkm1 )                ! First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1
448         zdiag(ji,jj,jk) = zdiag(ji,jj,jk) - zd_lw(ji,jj,jk) * zd_up(ji,jj,jk-1) / zdiag(ji,jj,jk-1)
449      END_3D
450!XC : commented to allow for neumann boundary condition
451!      DO_2D( 0, 0, 0, 0 )
452!         zd_lw(ji,jj,2) = en(ji,jj,2) - zd_lw(ji,jj,2) * en(ji,jj,1)    ! Surface boudary conditions on tke
453!      END_2D
454!      DO_3D( 0, 0, 0, 0, 3, jpkm1 )
455      DO_3D( 0, 0, 0, 0, 2, jpkm1 )
456         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)
457      END_3D
458      DO_2D( 0, 0, 0, 0 )                          ! thrid recurrence : Ek = ( Lk - Uk * Ek+1 ) / Dk
459         en(ji,jj,jpkm1) = zd_lw(ji,jj,jpkm1) / zdiag(ji,jj,jpkm1)
460      END_2D
461      DO_3DS( 0, 0, 0, 0, jpk-2, 2, -1 )
462         en(ji,jj,jk) = ( zd_lw(ji,jj,jk) - zd_up(ji,jj,jk) * en(ji,jj,jk+1) ) / zdiag(ji,jj,jk)
463      END_3D
464      DO_3D( 0, 0, 0, 0, 2, jpkm1 )                ! set the minimum value of tke
465         en(ji,jj,jk) = MAX( en(ji,jj,jk), rn_emin ) * wmask(ji,jj,jk)
466      END_3D
467      !
468      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
469      !                            !  TKE due to surface and internal wave breaking
470      !                            !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
471!!gm BUG : in the exp  remove the depth of ssh !!!
472!!gm       i.e. use gde3w in argument (gdepw(:,:,:,Kmm))
473      !
474      ! penetration is partly switched off below sea-ice if nn_eice/=0
475      !
476      IF( nn_etau == 1 ) THEN           !* penetration below the mixed layer (rn_efr fraction)
477         DO_3D( 0, 0, 0, 0, 2, jpkm1 ) 
478            en(ji,jj,jk) = en(ji,jj,jk) + rn_efr * en(ji,jj,1) * EXP( -gdepw(ji,jj,jk,Kmm) / htau(ji,jj) )   &
479               &                                 * MAX( 0._wp, 1._wp - zice_fra(ji,jj) ) * wmask(ji,jj,jk) * tmask(ji,jj,1)
480         END_3D
481      ELSEIF( nn_etau == 2 ) THEN       !* act only at the base of the mixed layer (jk=nmln)  (rn_efr fraction)
482         DO_2D( 0, 0, 0, 0 )
483            jk = nmln(ji,jj)
484            en(ji,jj,jk) = en(ji,jj,jk) + rn_efr * en(ji,jj,1) * EXP( -gdepw(ji,jj,jk,Kmm) / htau(ji,jj) )   &
485               &                                 * MAX( 0._wp, 1._wp - zice_fra(ji,jj) ) * wmask(ji,jj,jk) * tmask(ji,jj,1)
486         END_2D
487      ELSEIF( nn_etau == 3 ) THEN       !* penetration belox the mixed layer (HF variability)
488         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
489            ztx2 = utau(ji-1,jj  ) + utau(ji,jj)
490            zty2 = vtau(ji  ,jj-1) + vtau(ji,jj)
491            ztau = 0.5_wp * SQRT( ztx2 * ztx2 + zty2 * zty2 ) * tmask(ji,jj,1)    ! module of the mean stress
492            zdif = taum(ji,jj) - ztau                            ! mean of modulus - modulus of the mean
493            zdif = rhftau_scl * MAX( 0._wp, zdif + rhftau_add )  ! apply some modifications...
494            en(ji,jj,jk) = en(ji,jj,jk) + zbbrau * zdif * EXP( -gdepw(ji,jj,jk,Kmm) / htau(ji,jj) )   &
495               &                        * MAX( 0._wp, 1._wp - zice_fra(ji,jj) ) * wmask(ji,jj,jk) * tmask(ji,jj,1)
496         END_3D
497      ENDIF
498      !
499   END SUBROUTINE tke_tke
500
501
502   SUBROUTINE tke_avn( Kbb, Kmm, p_avm, p_avt )
503      !!----------------------------------------------------------------------
504      !!                   ***  ROUTINE tke_avn  ***
505      !!
506      !! ** Purpose :   Compute the vertical eddy viscosity and diffusivity
507      !!
508      !! ** Method  :   At this stage, en, the now TKE, is known (computed in
509      !!              the tke_tke routine). First, the now mixing lenth is
510      !!      computed from en and the strafification (N^2), then the mixings
511      !!      coefficients are computed.
512      !!              - Mixing length : a first evaluation of the mixing lengh
513      !!      scales is:
514      !!                      mxl = sqrt(2*en) / N 
515      !!      where N is the brunt-vaisala frequency, with a minimum value set
516      !!      to rmxl_min (rn_mxl0) in the interior (surface) ocean.
517      !!        The mixing and dissipative length scale are bound as follow :
518      !!         nn_mxl=0 : mxl bounded by the distance to surface and bottom.
519      !!                        zmxld = zmxlm = mxl
520      !!         nn_mxl=1 : mxl bounded by the e3w and zmxld = zmxlm = mxl
521      !!         nn_mxl=2 : mxl bounded such that the vertical derivative of mxl is
522      !!                    less than 1 (|d/dz(mxl)|<1) and zmxld = zmxlm = mxl
523      !!         nn_mxl=3 : mxl is bounded from the surface to the bottom usings
524      !!                    |d/dz(xml)|<1 to obtain lup, and from the bottom to
525      !!                    the surface to obtain ldown. the resulting length
526      !!                    scales are:
527      !!                        zmxld = sqrt( lup * ldown )
528      !!                        zmxlm = min ( lup , ldown )
529      !!              - Vertical eddy viscosity and diffusivity:
530      !!                      avm = max( avtb, rn_ediff * zmxlm * en^1/2 )
531      !!                      avt = max( avmb, pdlr * avm ) 
532      !!      with pdlr=1 if nn_pdl=0, pdlr=1/pdl=F(Ri) otherwise.
533      !!
534      !! ** Action  : - avt, avm : now vertical eddy diffusivity and viscosity (w-point)
535      !!----------------------------------------------------------------------
536      USE zdf_oce , ONLY : en, avtb, avmb, avtb_2d   ! ocean vertical physics
537      !!
538      INTEGER                   , INTENT(in   ) ::   Kbb, Kmm       ! ocean time level indices
539      REAL(wp), DIMENSION(:,:,:), INTENT(  out) ::   p_avm, p_avt   ! vertical eddy viscosity & diffusivity (w-points)
540      !
541      INTEGER  ::   ji, jj, jk   ! dummy loop indices
542      REAL(wp) ::   zrn2, zraug, zcoef, zav   ! local scalars
543      REAL(wp) ::   zdku,   zdkv, zsqen       !   -      -
544      REAL(wp) ::   zemxl, zemlm, zemlp, zmaxice       !   -      -
545      REAL(wp), DIMENSION(jpi,jpj,jpk) ::   zmxlm, zmxld   ! 3D workspace
546      !!--------------------------------------------------------------------
547      !
548      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
549      !                     !  Mixing length
550      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
551      !
552      !                     !* Buoyancy length scale: l=sqrt(2*e/n**2)
553      !
554      ! initialisation of interior minimum value (avoid a 2d loop with mikt)
555      zmxlm(:,:,:)  = rmxl_min   
556      zmxld(:,:,:)  = rmxl_min
557      !
558      IF(ln_sdw .AND. ln_mxhsw) THEN
559         zmxlm(:,:,1)= vkarmn * MAX ( 1.6 * hsw(:,:) , 0.02 )        ! surface mixing length = F(wave height)
560         ! from terray et al 1999 and mellor and blumberg 2004 it should be 0.85 and not 1.6
561         zcoef       = vkarmn * ( (rn_ediff*rn_ediss)**0.25 ) / rn_ediff
562         zmxlm(:,:,1)= zcoef * MAX ( 1.6 * hsw(:,:) , 0.02 )        ! surface mixing length = F(wave height)
563      ELSE
564      !
565         IF( ln_mxl0 ) THEN            ! surface mixing length = F(stress) : l=vkarmn*2.e5*taum/(rho0*g)
566         !
567            zraug = vkarmn * 2.e5_wp / ( rho0 * grav )
568#if ! defined key_si3 && ! defined key_cice
569            DO_2D( 0, 0, 0, 0 )                  ! No sea-ice
570               zmxlm(ji,jj,1) =  zraug * taum(ji,jj) * tmask(ji,jj,1)
571            END_2D
572#else
573            SELECT CASE( nn_mxlice )             ! Type of scaling under sea-ice
574            !
575            CASE( 0 )                      ! No scaling under sea-ice
576               DO_2D( 0, 0, 0, 0 )
577                  zmxlm(ji,jj,1) = zraug * taum(ji,jj) * tmask(ji,jj,1)
578               END_2D
579               !
580            CASE( 1 )                      ! scaling with constant sea-ice thickness
581               DO_2D( 0, 0, 0, 0 )
582                  zmxlm(ji,jj,1) =  ( ( 1._wp - fr_i(ji,jj) ) * zraug * taum(ji,jj) + &
583                     &                          fr_i(ji,jj)   * rn_mxlice           ) * tmask(ji,jj,1)
584               END_2D
585               !
586            CASE( 2 )                      ! scaling with mean sea-ice thickness
587               DO_2D( 0, 0, 0, 0 )
588#if defined key_si3
589                  zmxlm(ji,jj,1) = ( ( 1._wp - fr_i(ji,jj) ) * zraug * taum(ji,jj) + &
590                     &                         fr_i(ji,jj)   * hm_i(ji,jj) * 2._wp ) * tmask(ji,jj,1)
591#elif defined key_cice
592                  zmaxice = MAXVAL( h_i(ji,jj,:) )
593                  zmxlm(ji,jj,1) = ( ( 1._wp - fr_i(ji,jj) ) * zraug * taum(ji,jj) + &
594                     &                         fr_i(ji,jj)   * zmaxice             ) * tmask(ji,jj,1)
595#endif
596               END_2D
597               !
598            CASE( 3 )                      ! scaling with max sea-ice thickness
599               DO_2D( 0, 0, 0, 0 )
600                  zmaxice = MAXVAL( h_i(ji,jj,:) )
601                  zmxlm(ji,jj,1) = ( ( 1._wp - fr_i(ji,jj) ) * zraug * taum(ji,jj) + &
602                     &                         fr_i(ji,jj)   * zmaxice             ) * tmask(ji,jj,1)
603               END_2D
604               !
605            END SELECT
606#endif
607            !
608            DO_2D( 0, 0, 0, 0 )
609               zmxlm(ji,jj,1) = MAX( rn_mxl0, zmxlm(ji,jj,1) )
610            END_2D
611            !
612         ELSE
613            zmxlm(:,:,1) = rn_mxl0
614         ENDIF
615      ENDIF
616      !
617      DO_3D( 0, 0, 0, 0, 2, jpkm1 )
618         zrn2 = MAX( rn2(ji,jj,jk), rsmall )
619         zmxlm(ji,jj,jk) = MAX(  rmxl_min,  SQRT( 2._wp * en(ji,jj,jk) / zrn2 )  )
620      END_3D
621      !
622      !                     !* Physical limits for the mixing length
623      !
624      zmxld(:,:, 1 ) = zmxlm(:,:,1)   ! surface set to the minimum value
625      zmxld(:,:,jpk) = rmxl_min       ! last level  set to the minimum value
626      !
627      SELECT CASE ( nn_mxl )
628      !
629 !!gm Not sure of that coding for ISF....
630      ! where wmask = 0 set zmxlm == e3w(:,:,:,Kmm)
631      CASE ( 0 )           ! bounded by the distance to surface and bottom
632         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
633            zemxl = MIN( gdepw(ji,jj,jk,Kmm) - gdepw(ji,jj,mikt(ji,jj),Kmm), zmxlm(ji,jj,jk),   &
634            &            gdepw(ji,jj,mbkt(ji,jj)+1,Kmm) - gdepw(ji,jj,jk,Kmm) )
635            ! wmask prevent zmxlm = 0 if jk = mikt(ji,jj)
636            zmxlm(ji,jj,jk) = zemxl * wmask(ji,jj,jk)   &
637               &            + MIN( zmxlm(ji,jj,jk) , e3w(ji,jj,jk,Kmm) ) * (1 - wmask(ji,jj,jk))
638            zmxld(ji,jj,jk) = zemxl * wmask(ji,jj,jk)   &
639               &            + MIN( zmxlm(ji,jj,jk) , e3w(ji,jj,jk,Kmm) ) * (1 - wmask(ji,jj,jk))
640         END_3D
641         !
642      CASE ( 1 )           ! bounded by the vertical scale factor
643         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
644            zemxl = MIN( e3w(ji,jj,jk,Kmm), zmxlm(ji,jj,jk) )
645            zmxlm(ji,jj,jk) = zemxl
646            zmxld(ji,jj,jk) = zemxl
647         END_3D
648         !
649      CASE ( 2 )           ! |dk[xml]| bounded by e3t :
650         DO_3D( 0, 0, 0, 0, 2, jpkm1 )        ! from the surface to the bottom :
651            zmxlm(ji,jj,jk) =   &
652               &    MIN( zmxlm(ji,jj,jk-1) + e3t(ji,jj,jk-1,Kmm), zmxlm(ji,jj,jk) )
653         END_3D
654         DO_3DS( 0, 0, 0, 0, jpkm1, 2, -1 )   ! from the bottom to the surface :
655            zemxl = MIN( zmxlm(ji,jj,jk+1) + e3t(ji,jj,jk+1,Kmm), zmxlm(ji,jj,jk) )
656            zmxlm(ji,jj,jk) = zemxl
657            zmxld(ji,jj,jk) = zemxl
658         END_3D
659         !
660      CASE ( 3 )           ! lup and ldown, |dk[xml]| bounded by e3t :
661         DO_3D( 0, 0, 0, 0, 2, jpkm1 )        ! from the surface to the bottom : lup
662            zmxld(ji,jj,jk) =    &
663               &    MIN( zmxld(ji,jj,jk-1) + e3t(ji,jj,jk-1,Kmm), zmxlm(ji,jj,jk) )
664         END_3D
665         DO_3DS( 0, 0, 0, 0, jpkm1, 2, -1 )   ! from the bottom to the surface : ldown
666            zmxlm(ji,jj,jk) =   &
667               &    MIN( zmxlm(ji,jj,jk+1) + e3t(ji,jj,jk+1,Kmm), zmxlm(ji,jj,jk) )
668         END_3D
669         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
670            zemlm = MIN ( zmxld(ji,jj,jk),  zmxlm(ji,jj,jk) )
671            zemlp = SQRT( zmxld(ji,jj,jk) * zmxlm(ji,jj,jk) )
672            zmxlm(ji,jj,jk) = zemlm
673            zmxld(ji,jj,jk) = zemlp
674         END_3D
675         !
676      END SELECT
677      !
678      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
679      !                     !  Vertical eddy viscosity and diffusivity  (avm and avt)
680      !                     !<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
681      DO_3D( 0, 0, 0, 0, 1, jpkm1 )   !* vertical eddy viscosity & diffivity at w-points
682         zsqen = SQRT( en(ji,jj,jk) )
683         zav   = rn_ediff * zmxlm(ji,jj,jk) * zsqen
684         p_avm(ji,jj,jk) = MAX( zav,                  avmb(jk) ) * wmask(ji,jj,jk)
685         p_avt(ji,jj,jk) = MAX( zav, avtb_2d(ji,jj) * avtb(jk) ) * wmask(ji,jj,jk)
686         dissl(ji,jj,jk) = zsqen / zmxld(ji,jj,jk)
687      END_3D
688      !
689      !
690      IF( nn_pdl == 1 ) THEN          !* Prandtl number case: update avt
691         DO_3D( 0, 0, 0, 0, 2, jpkm1 )
692            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)
693         END_3D
694      ENDIF
695      !
696      IF(sn_cfctl%l_prtctl) THEN
697         CALL prt_ctl( tab3d_1=en   , clinfo1=' tke  - e: ', tab3d_2=p_avt, clinfo2=' t: ', kdim=jpk)
698         CALL prt_ctl( tab3d_1=p_avm, clinfo1=' tke  - m: ', kdim=jpk )
699      ENDIF
700      !
701   END SUBROUTINE tke_avn
702
703
704   SUBROUTINE zdf_tke_init( Kmm )
705      !!----------------------------------------------------------------------
706      !!                  ***  ROUTINE zdf_tke_init  ***
707      !!                     
708      !! ** Purpose :   Initialization of the vertical eddy diffivity and
709      !!              viscosity when using a tke turbulent closure scheme
710      !!
711      !! ** Method  :   Read the namzdf_tke namelist and check the parameters
712      !!              called at the first timestep (nit000)
713      !!
714      !! ** input   :   Namlist namzdf_tke
715      !!
716      !! ** Action  :   Increase by 1 the nstop flag is setting problem encounter
717      !!----------------------------------------------------------------------
718      USE zdf_oce , ONLY : ln_zdfiwm   ! Internal Wave Mixing flag
719      !!
720      INTEGER, INTENT(in) ::   Kmm          ! time level index
721      INTEGER             ::   ji, jj, jk   ! dummy loop indices
722      INTEGER             ::   ios
723      !!
724      NAMELIST/namzdf_tke/ rn_ediff, rn_ediss , rn_ebb   , rn_emin  ,  &
725         &                 rn_emin0, rn_bshear, nn_mxl   , ln_mxl0  ,  &
726         &                 rn_mxl0 , nn_mxlice, rn_mxlice,             &
727         &                 nn_pdl  , ln_lc    , rn_lc    ,             &
728         &                 nn_etau , nn_htau  , rn_efr   , nn_eice  ,  &   
729         &                 nn_bc_surf, nn_bc_bot, ln_mxhsw
730      !!----------------------------------------------------------------------
731      !
732      READ  ( numnam_ref, namzdf_tke, IOSTAT = ios, ERR = 901)
733901   IF( ios /= 0 ) CALL ctl_nam ( ios , 'namzdf_tke in reference namelist' )
734
735      READ  ( numnam_cfg, namzdf_tke, IOSTAT = ios, ERR = 902 )
736902   IF( ios >  0 ) CALL ctl_nam ( ios , 'namzdf_tke in configuration namelist' )
737      IF(lwm) WRITE ( numond, namzdf_tke )
738      !
739      ri_cri   = 2._wp    / ( 2._wp + rn_ediss / rn_ediff )   ! resulting critical Richardson number
740      !
741      IF(lwp) THEN                    !* Control print
742         WRITE(numout,*)
743         WRITE(numout,*) 'zdf_tke_init : tke turbulent closure scheme - initialisation'
744         WRITE(numout,*) '~~~~~~~~~~~~'
745         WRITE(numout,*) '   Namelist namzdf_tke : set tke mixing parameters'
746         WRITE(numout,*) '      coef. to compute avt                        rn_ediff  = ', rn_ediff
747         WRITE(numout,*) '      Kolmogoroff dissipation coef.               rn_ediss  = ', rn_ediss
748         WRITE(numout,*) '      tke surface input coef.                     rn_ebb    = ', rn_ebb
749         WRITE(numout,*) '      minimum value of tke                        rn_emin   = ', rn_emin
750         WRITE(numout,*) '      surface minimum value of tke                rn_emin0  = ', rn_emin0
751         WRITE(numout,*) '      prandl number flag                          nn_pdl    = ', nn_pdl
752         WRITE(numout,*) '      background shear (>0)                       rn_bshear = ', rn_bshear
753         WRITE(numout,*) '      mixing length type                          nn_mxl    = ', nn_mxl
754         WRITE(numout,*) '         surface mixing length = F(stress) or not    ln_mxl0   = ', ln_mxl0
755         WRITE(numout,*) '         surface  mixing length minimum value        rn_mxl0   = ', rn_mxl0
756         IF( ln_mxl0 ) THEN
757            WRITE(numout,*) '      type of scaling under sea-ice               nn_mxlice = ', nn_mxlice
758            IF( nn_mxlice == 1 ) &
759            WRITE(numout,*) '      ice thickness when scaling under sea-ice    rn_mxlice = ', rn_mxlice
760            SELECT CASE( nn_mxlice )             ! Type of scaling under sea-ice
761            CASE( 0 )   ;   WRITE(numout,*) '   ==>>>   No scaling under sea-ice'
762            CASE( 1 )   ;   WRITE(numout,*) '   ==>>>   scaling with constant sea-ice thickness'
763            CASE( 2 )   ;   WRITE(numout,*) '   ==>>>   scaling with mean sea-ice thickness'
764            CASE( 3 )   ;   WRITE(numout,*) '   ==>>>   scaling with max sea-ice thickness'
765            CASE DEFAULT
766               CALL ctl_stop( 'zdf_tke_init: wrong value for nn_mxlice, should be 0,1,2,3 or 4')
767            END SELECT
768         ENDIF
769         WRITE(numout,*) '      Langmuir cells parametrization              ln_lc     = ', ln_lc
770         WRITE(numout,*) '         coef to compute vertical velocity of LC     rn_lc  = ', rn_lc
771         IF ( cpl_phioc .and. ln_phioc )  THEN
772            SELECT CASE( nn_bc_surf)             ! Type of scaling under sea-ice
773            CASE( 0 )   ;   WRITE(numout,*) '  nn_bc_surf=0  ==>>>   DIRICHLET Surface Boundary Condition using surface TKE flux from waves'
774            CASE( 1 )   ;   WRITE(numout,*) '  nn_bc_surf=1  ==>>>   NEUMANN Surface Boundary Condition using surface TKE flux from waves'
775            END SELECT
776         ENDIF
777         WRITE(numout,*) '      test param. to add tke induced by wind      nn_etau   = ', nn_etau
778         WRITE(numout,*) '          type of tke penetration profile            nn_htau   = ', nn_htau
779         WRITE(numout,*) '          fraction of TKE that penetrates            rn_efr    = ', rn_efr
780         WRITE(numout,*) '      langmuir & surface wave breaking under ice  nn_eice = ', nn_eice
781         SELECT CASE( nn_eice ) 
782         CASE( 0 )   ;   WRITE(numout,*) '   ==>>>   no impact of ice cover on langmuir & surface wave breaking'
783         CASE( 1 )   ;   WRITE(numout,*) '   ==>>>   weigthed by 1-TANH( fr_i(:,:) * 10 )'
784         CASE( 2 )   ;   WRITE(numout,*) '   ==>>>   weighted by 1-fr_i(:,:)'
785         CASE( 3 )   ;   WRITE(numout,*) '   ==>>>   weighted by 1-MIN( 1, 4 * fr_i(:,:) )'
786         CASE DEFAULT
787            CALL ctl_stop( 'zdf_tke_init: wrong value for nn_eice, should be 0,1,2, or 3')
788         END SELECT     
789         WRITE(numout,*)
790         WRITE(numout,*) '   ==>>>   critical Richardson nb with your parameters  ri_cri = ', ri_cri
791         WRITE(numout,*)
792      ENDIF
793      !
794      IF( ln_zdfiwm ) THEN          ! Internal wave-driven mixing
795         rn_emin  = 1.e-10_wp             ! specific values of rn_emin & rmxl_min are used
796         rmxl_min = 1.e-03_wp             ! associated avt minimum = molecular salt diffusivity (10^-9 m2/s)
797         IF(lwp) WRITE(numout,*) '   ==>>>   Internal wave-driven mixing case:   force   rn_emin = 1.e-10 and rmxl_min = 1.e-3'
798      ELSE                          ! standard case : associated avt minimum = molecular viscosity (10^-6 m2/s)
799         rmxl_min = 1.e-6_wp / ( rn_ediff * SQRT( rn_emin ) )    ! resulting minimum length to recover molecular viscosity
800         IF(lwp) WRITE(numout,*) '   ==>>>   minimum mixing length with your parameters rmxl_min = ', rmxl_min
801      ENDIF
802      !
803      !                              ! allocate tke arrays
804      IF( zdf_tke_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'zdf_tke_init : unable to allocate arrays' )
805      !
806      !                               !* Check of some namelist values
807      IF( nn_mxl  < 0   .OR.  nn_mxl  > 3 )   CALL ctl_stop( 'bad flag: nn_mxl is  0, 1 or 2 ' )
808      IF( nn_pdl  < 0   .OR.  nn_pdl  > 1 )   CALL ctl_stop( 'bad flag: nn_pdl is  0 or 1    ' )
809      IF( nn_htau < 0   .OR.  nn_htau > 1 )   CALL ctl_stop( 'bad flag: nn_htau is 0, 1 or 2 ' )
810      IF( nn_etau == 3 .AND. .NOT. ln_cpl )   CALL ctl_stop( 'nn_etau == 3 : HF taum only known in coupled mode' )
811      !
812      IF( ln_mxl0 ) THEN
813         IF(lwp) WRITE(numout,*)
814         IF(lwp) WRITE(numout,*) '   ==>>>   use a surface mixing length = F(stress) :   set rn_mxl0 = rmxl_min'
815         rn_mxl0 = rmxl_min
816      ENDIF
817     
818      IF( nn_etau == 2  )   CALL zdf_mxl( nit000, Kmm )      ! Initialization of nmln
819
820      !                               !* depth of penetration of surface tke
821      IF( nn_etau /= 0 ) THEN     
822         SELECT CASE( nn_htau )             ! Choice of the depth of penetration
823         CASE( 0 )                                 ! constant depth penetration (here 10 meters)
824            htau(:,:) = 10._wp
825         CASE( 1 )                                 ! F(latitude) : 0.5m to 30m poleward of 40 degrees
826            htau(:,:) = MAX(  0.5_wp, MIN( 30._wp, 45._wp* ABS( SIN( rpi/180._wp * gphit(:,:) ) ) )   )           
827         END SELECT
828      ENDIF
829      !                                !* read or initialize all required files
830      CALL tke_rst( nit000, 'READ' )      ! (en, avt_k, avm_k, dissl)
831      !
832      IF( lwxios ) THEN
833         CALL iom_set_rstw_var_active('en')
834         CALL iom_set_rstw_var_active('avt_k')
835         CALL iom_set_rstw_var_active('avm_k')
836         CALL iom_set_rstw_var_active('dissl')
837      ENDIF
838   END SUBROUTINE zdf_tke_init
839
840
841   SUBROUTINE tke_rst( kt, cdrw )
842      !!---------------------------------------------------------------------
843      !!                   ***  ROUTINE tke_rst  ***
844      !!                     
845      !! ** Purpose :   Read or write TKE file (en) in restart file
846      !!
847      !! ** Method  :   use of IOM library
848      !!                if the restart does not contain TKE, en is either
849      !!                set to rn_emin or recomputed
850      !!----------------------------------------------------------------------
851      USE zdf_oce , ONLY : en, avt_k, avm_k   ! ocean vertical physics
852      !!
853      INTEGER         , INTENT(in) ::   kt     ! ocean time-step
854      CHARACTER(len=*), INTENT(in) ::   cdrw   ! "READ"/"WRITE" flag
855      !
856      INTEGER ::   jit, jk              ! dummy loop indices
857      INTEGER ::   id1, id2, id3, id4   ! local integers
858      !!----------------------------------------------------------------------
859      !
860      IF( TRIM(cdrw) == 'READ' ) THEN        ! Read/initialise
861         !                                   ! ---------------
862         IF( ln_rstart ) THEN                   !* Read the restart file
863            id1 = iom_varid( numror, 'en'   , ldstop = .FALSE. )
864            id2 = iom_varid( numror, 'avt_k', ldstop = .FALSE. )
865            id3 = iom_varid( numror, 'avm_k', ldstop = .FALSE. )
866            id4 = iom_varid( numror, 'dissl', ldstop = .FALSE. )
867            !
868            IF( MIN( id1, id2, id3, id4 ) > 0 ) THEN      ! fields exist
869               CALL iom_get( numror, jpdom_auto, 'en'   , en   , ldxios = lrxios )
870               CALL iom_get( numror, jpdom_auto, 'avt_k', avt_k, ldxios = lrxios )
871               CALL iom_get( numror, jpdom_auto, 'avm_k', avm_k, ldxios = lrxios )
872               CALL iom_get( numror, jpdom_auto, 'dissl', dissl, ldxios = lrxios )
873            ELSE                                          ! start TKE from rest
874               IF(lwp) WRITE(numout,*)
875               IF(lwp) WRITE(numout,*) '   ==>>>   previous run without TKE scheme, set en to background values'
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         ELSE                                   !* Start from rest
881            IF(lwp) WRITE(numout,*)
882            IF(lwp) WRITE(numout,*) '   ==>>>   start from rest: set en to the background value'
883            en   (:,:,:) = rn_emin * wmask(:,:,:)
884            dissl(:,:,:) = 1.e-12_wp
885            ! avt_k, avm_k already set to the background value in zdf_phy_init
886         ENDIF
887         !
888      ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN   ! Create restart file
889         !                                   ! -------------------
890         IF(lwp) WRITE(numout,*) '---- tke_rst ----'
891         IF( lwxios ) CALL iom_swap(      cwxios_context          ) 
892         CALL iom_rstput( kt, nitrst, numrow, 'en'   , en   , ldxios = lwxios )
893         CALL iom_rstput( kt, nitrst, numrow, 'avt_k', avt_k, ldxios = lwxios )
894         CALL iom_rstput( kt, nitrst, numrow, 'avm_k', avm_k, ldxios = lwxios )
895         CALL iom_rstput( kt, nitrst, numrow, 'dissl', dissl, ldxios = lwxios )
896         IF( lwxios ) CALL iom_swap(      cxios_context          )
897         !
898      ENDIF
899      !
900   END SUBROUTINE tke_rst
901
902   !!======================================================================
903END MODULE zdftke
Note: See TracBrowser for help on using the repository browser.