zdftke.F90 47 KB

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