trdken.F90 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. MODULE trdken
  2. !!======================================================================
  3. !! *** MODULE trdken ***
  4. !! Ocean diagnostics: compute and output 3D kinetic energy trends
  5. !!=====================================================================
  6. !! History : 3.5 ! 2012-02 (G. Madec) original code
  7. !!----------------------------------------------------------------------
  8. !!----------------------------------------------------------------------
  9. !! trd_ken : compute and output 3D Kinetic energy trends using IOM
  10. !! trd_ken_init : initialisation
  11. !!----------------------------------------------------------------------
  12. USE oce ! ocean dynamics and tracers variables
  13. USE dom_oce ! ocean space and time domain variables
  14. USE zdf_oce ! ocean vertical physics variables
  15. USE trd_oce ! trends: ocean variables
  16. !!gm USE dynhpg ! hydrostatic pressure gradient
  17. USE zdfbfr ! bottom friction
  18. USE ldftra_oce ! ocean active tracers lateral physics
  19. USE sbc_oce ! surface boundary condition: ocean
  20. USE phycst ! physical constants
  21. USE trdvor ! ocean vorticity trends
  22. USE trdglo ! trends:global domain averaged
  23. USE trdmxl ! ocean active mixed layer tracers trends
  24. USE in_out_manager ! I/O manager
  25. USE iom ! I/O manager library
  26. USE lib_mpp ! MPP library
  27. USE wrk_nemo ! Memory allocation
  28. USE ldfslp ! Isopycnal slopes
  29. IMPLICIT NONE
  30. PRIVATE
  31. PUBLIC trd_ken ! called by trddyn module
  32. PUBLIC trd_ken_init ! called by trdini module
  33. INTEGER :: nkstp ! current time step
  34. REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) :: bu, bv ! volume of u- and v-boxes
  35. REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) :: r1_bt ! inverse of t-box volume
  36. !! * Substitutions
  37. # include "domzgr_substitute.h90"
  38. # include "vectopt_loop_substitute.h90"
  39. # include "ldfeiv_substitute.h90"
  40. !!----------------------------------------------------------------------
  41. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  42. !! $Id: trdken.F90 5424 2018-04-27 07:03:10Z ufla $
  43. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  44. !!----------------------------------------------------------------------
  45. CONTAINS
  46. INTEGER FUNCTION trd_ken_alloc()
  47. !!---------------------------------------------------------------------
  48. !! *** FUNCTION trd_ken_alloc ***
  49. !!---------------------------------------------------------------------
  50. ALLOCATE( bu(jpi,jpj,jpk) , bv(jpi,jpj,jpk) , r1_bt(jpi,jpj,jpk) , STAT= trd_ken_alloc )
  51. !
  52. IF( lk_mpp ) CALL mpp_sum ( trd_ken_alloc )
  53. IF( trd_ken_alloc /= 0 ) CALL ctl_warn('trd_ken_alloc: failed to allocate arrays')
  54. END FUNCTION trd_ken_alloc
  55. SUBROUTINE trd_ken( putrd, pvtrd, ktrd, kt )
  56. !!---------------------------------------------------------------------
  57. !! *** ROUTINE trd_ken ***
  58. !!
  59. !! ** Purpose : output 3D Kinetic Energy trends using IOM
  60. !!
  61. !! ** Method : - apply lbc to the input masked velocity trends
  62. !! - compute the associated KE trend:
  63. !! zke = 0.5 * ( mi-1[ un * putrd * bu ] + mj-1[ vn * pvtrd * bv] ) / bt
  64. !! where bu, bv, bt are the volume of u-, v- and t-boxes.
  65. !! - vertical diffusion case (jpdyn_zdf):
  66. !! diagnose separately the KE trend associated with wind stress
  67. !! - bottom friction case (jpdyn_bfr):
  68. !! explicit case (ln_bfrimp=F): bottom trend put in the 1st level
  69. !! of putrd, pvtrd
  70. !
  71. !
  72. !!----------------------------------------------------------------------
  73. REAL(wp), DIMENSION(:,:,:), INTENT(inout) :: putrd, pvtrd ! U and V masked trends
  74. INTEGER , INTENT(in ) :: ktrd ! trend index
  75. INTEGER , INTENT(in ) :: kt ! time step
  76. !
  77. INTEGER :: ji, jj, jk ! dummy loop indices
  78. INTEGER :: ikbu , ikbv ! local integers
  79. INTEGER :: ikbum1, ikbvm1 ! - -
  80. REAL(wp), POINTER, DIMENSION(:,:) :: z2dx, z2dy, zke2d ! 2D workspace
  81. REAL(wp), POINTER, DIMENSION(:,:,:) :: zke ! 3D workspace
  82. !!----------------------------------------------------------------------
  83. !
  84. CALL wrk_alloc( jpi, jpj, jpk, zke )
  85. !
  86. CALL lbc_lnk( putrd, 'U', -1. ) ; CALL lbc_lnk( pvtrd, 'V', -1. ) ! lateral boundary conditions
  87. !
  88. IF ( lk_vvl .AND. kt /= nkstp ) THEN ! Variable volume: set box volume at the 1st call of kt time step
  89. nkstp = kt
  90. DO jk = 1, jpkm1
  91. bu (:,:,jk) = e1u(:,:) * e2u(:,:) * fse3u_n(:,:,jk)
  92. bv (:,:,jk) = e1v(:,:) * e2v(:,:) * fse3v_n(:,:,jk)
  93. r1_bt(:,:,jk) = 1._wp / ( e1e2t(:,:) * fse3t_n(:,:,jk) ) * tmask(:,:,jk)
  94. END DO
  95. ENDIF
  96. !
  97. zke(:,:,jpk) = 0._wp
  98. zke(1,:, : ) = 0._wp
  99. zke(:,1, : ) = 0._wp
  100. DO jk = 1, jpkm1
  101. DO jj = 2, jpj
  102. DO ji = 2, jpi
  103. zke(ji,jj,jk) = 0.5_wp * rau0 *( un(ji ,jj,jk) * putrd(ji ,jj,jk) * bu(ji ,jj,jk) &
  104. & + un(ji-1,jj,jk) * putrd(ji-1,jj,jk) * bu(ji-1,jj,jk) &
  105. & + vn(ji,jj ,jk) * pvtrd(ji,jj ,jk) * bv(ji,jj ,jk) &
  106. & + vn(ji,jj-1,jk) * pvtrd(ji,jj-1,jk) * bv(ji,jj-1,jk) ) * r1_bt(ji,jj,jk)
  107. END DO
  108. END DO
  109. END DO
  110. !
  111. SELECT CASE( ktrd )
  112. CASE( jpdyn_hpg ) ; CALL iom_put( "ketrd_hpg", zke ) ! hydrostatic pressure gradient
  113. CASE( jpdyn_spg ) ; CALL iom_put( "ketrd_spg", zke ) ! surface pressure gradient
  114. CASE( jpdyn_spgexp ); CALL iom_put( "ketrd_spgexp", zke ) ! surface pressure gradient (explicit)
  115. CASE( jpdyn_spgflt ); CALL iom_put( "ketrd_spgflt", zke ) ! surface pressure gradient (filter)
  116. CASE( jpdyn_pvo ) ; CALL iom_put( "ketrd_pvo", zke ) ! planetary vorticity
  117. CASE( jpdyn_rvo ) ; CALL iom_put( "ketrd_rvo", zke ) ! relative vorticity (or metric term)
  118. CASE( jpdyn_keg ) ; CALL iom_put( "ketrd_keg", zke ) ! Kinetic Energy gradient (or had)
  119. CASE( jpdyn_zad ) ; CALL iom_put( "ketrd_zad", zke ) ! vertical advection
  120. CASE( jpdyn_ldf ) ; CALL iom_put( "ketrd_ldf", zke ) ! lateral diffusion
  121. CASE( jpdyn_zdf ) ; CALL iom_put( "ketrd_zdf", zke ) ! vertical diffusion
  122. ! ! wind stress trends
  123. CALL wrk_alloc( jpi, jpj, z2dx, z2dy, zke2d )
  124. z2dx(:,:) = un(:,:,1) * ( utau_b(:,:) + utau(:,:) ) * e1u(:,:) * e2u(:,:) * umask(:,:,1)
  125. z2dy(:,:) = vn(:,:,1) * ( vtau_b(:,:) + vtau(:,:) ) * e1v(:,:) * e2v(:,:) * vmask(:,:,1)
  126. zke2d(1,:) = 0._wp ; zke2d(:,1) = 0._wp
  127. DO jj = 2, jpj
  128. DO ji = 2, jpi
  129. zke2d(ji,jj) = 0.5_wp * ( z2dx(ji,jj) + z2dx(ji-1,jj) &
  130. & + z2dy(ji,jj) + z2dy(ji,jj-1) ) * r1_bt(ji,jj,1)
  131. END DO
  132. END DO
  133. CALL iom_put( "ketrd_tau", zke2d )
  134. CALL wrk_dealloc( jpi, jpj , z2dx, z2dy, zke2d )
  135. CASE( jpdyn_bfr ) ; CALL iom_put( "ketrd_bfr", zke ) ! bottom friction (explicit case)
  136. !!gm TO BE DONE properly
  137. !!gm only valid if ln_bfrimp=F otherwise the bottom stress as to be recomputed at the end of the computation....
  138. ! IF(.NOT. ln_bfrimp) THEN
  139. ! DO jj = 1, jpj !
  140. ! DO ji = 1, jpi
  141. ! ikbu = mbku(ji,jj) ! deepest ocean u- & v-levels
  142. ! ikbv = mbkv(ji,jj)
  143. ! z2dx(ji,jj) = un(ji,jj,ikbu) * bfrua(ji,jj) * un(ji,jj,ikbu)
  144. ! z2dy(ji,jj) = vn(ji,jj,ikbu) * bfrva(ji,jj) * vn(ji,jj,ikbv)
  145. ! END DO
  146. ! END DO
  147. ! zke2d(1,:) = 0._wp ; zke2d(:,1) = 0._wp
  148. ! DO jj = 2, jpj
  149. ! DO ji = 2, jpi
  150. ! zke2d(ji,jj) = 0.5_wp * ( z2dx(ji,jj) + z2dx(ji-1,jj) &
  151. ! & + z2dy(ji,jj) + z2dy(ji,jj-1) ) * r1_bt(ji,jj, BEURK!!!
  152. ! END DO
  153. ! END DO
  154. ! CALL iom_put( "ketrd_bfr", zke2d ) ! bottom friction (explicit case)
  155. ! ENDIF
  156. !!gm end
  157. CASE( jpdyn_atf ) ; CALL iom_put( "ketrd_atf", zke ) ! asselin filter trends
  158. !! a faire !!!! idee changer dynnxt pour avoir un appel a jpdyn_bfr avant le swap !!!
  159. !! reflechir a une possible sauvegarde du "vrai" un,vn pour le calcul de atf....
  160. !
  161. ! IF( ln_bfrimp ) THEN ! bottom friction (implicit case)
  162. ! DO jj = 1, jpj ! after velocity known (now filed at this stage)
  163. ! DO ji = 1, jpi
  164. ! ikbu = mbku(ji,jj) ! deepest ocean u- & v-levels
  165. ! ikbv = mbkv(ji,jj)
  166. ! z2dx(ji,jj) = un(ji,jj,ikbu) * bfrua(ji,jj) * un(ji,jj,ikbu) / fse3u(ji,jj,ikbu)
  167. ! z2dy(ji,jj) = un(ji,jj,ikbu) * bfrva(ji,jj) * vn(ji,jj,ikbv) / fse3v(ji,jj,ikbv)
  168. ! END DO
  169. ! END DO
  170. ! zke2d(1,:) = 0._wp ; zke2d(:,1) = 0._wp
  171. ! DO jj = 2, jpj
  172. ! DO ji = 2, jpi
  173. ! zke2d(ji,jj) = 0.5_wp * ( z2dx(ji,jj) + z2dx(ji-1,jj) &
  174. ! & + z2dy(ji,jj) + z2dy(ji,jj-1) )
  175. ! END DO
  176. ! END DO
  177. ! CALL iom_put( "ketrd_bfri", zke2d )
  178. ! ENDIF
  179. CASE( jpdyn_ken ) ; ! kinetic energy
  180. ! called in dynnxt.F90 before asselin time filter
  181. ! with putrd=ua and pvtrd=va
  182. zke(:,:,:) = 0.5_wp * zke(:,:,:)
  183. CALL iom_put( "KE", zke )
  184. !
  185. CALL ken_p2k( kt , zke )
  186. CALL iom_put( "ketrd_convP2K", zke ) ! conversion -rau*g*w
  187. !!gm moved in traadv_eiv ===>>> diag becomes accessible without ln_trdtra=T
  188. ! CASE( jpdyn_eivke )
  189. ! ! CMIP6 diagnostic tknebto = tendency of EKE from
  190. ! ! parameterized mesoscale eddy advection
  191. ! ! = vertical_integral( k (N S)^2 ) rho dz
  192. ! ! rho = reference density
  193. ! ! S = isoneutral slope.
  194. ! ! Most terms are on W grid so work on this grid
  195. !#ifdef key_traldf_eiv
  196. ! CALL wrk_alloc( jpi, jpj, zke2d )
  197. ! zke2d(:,:) = 0._wp
  198. ! DO jk = 1,jpk
  199. ! DO ji = 1,jpi
  200. ! DO jj = 1,jpj
  201. ! zke2d(ji,jj) = zke2d(ji,jj) + rau0 * fsaeiw(ji, jj, jk) &
  202. ! & * ( wslpi(ji, jj, jk) * wslpi(ji,jj,jk) &
  203. ! & + wslpj(ji, jj, jk) * wslpj(ji,jj,jk) ) &
  204. ! & * rn2(ji,jj,jk) * fse3w(ji, jj, jk)
  205. ! ENDDO
  206. ! ENDDO
  207. ! ENDDO
  208. ! CALL iom_put("ketrd_eiv", zke2d)
  209. ! CALL wrk_dealloc( jpi, jpj, zke2d )
  210. !#endif
  211. !!gm end
  212. !
  213. END SELECT
  214. !
  215. CALL wrk_dealloc( jpi, jpj, jpk, zke )
  216. !
  217. END SUBROUTINE trd_ken
  218. SUBROUTINE ken_p2k( kt , pconv )
  219. !!---------------------------------------------------------------------
  220. !! *** ROUTINE ken_p2k ***
  221. !!
  222. !! ** Purpose : compute rate of conversion from potential to kinetic energy
  223. !!
  224. !! ** Method : - compute conv defined as -rau*g*w on T-grid points
  225. !!
  226. !! ** Work only for full steps and partial steps (ln_hpg_zco or ln_hpg_zps)
  227. !!----------------------------------------------------------------------
  228. INTEGER, INTENT(in) :: kt ! ocean time-step index
  229. !!
  230. REAL(wp), DIMENSION(jpi,jpj,jpk ), INTENT( out) :: pconv
  231. !
  232. INTEGER :: ji, jj, jk ! dummy loop indices
  233. INTEGER :: iku, ikv ! temporary integers
  234. REAL(wp) :: zcoef ! temporary scalars
  235. REAL(wp), POINTER, DIMENSION(:,:,:) :: zconv ! temporary conv on W-grid
  236. !!----------------------------------------------------------------------
  237. !
  238. CALL wrk_alloc( jpi,jpj,jpk, zconv )
  239. !
  240. ! Local constant initialization
  241. zcoef = - rau0 * grav * 0.5_wp
  242. ! Surface value (also valid in partial step case)
  243. zconv(:,:,1) = zcoef * ( 2._wp * rhd(:,:,1) ) * wn(:,:,1) * fse3w(:,:,1)
  244. ! interior value (2=<jk=<jpkm1)
  245. DO jk = 2, jpk
  246. zconv(:,:,jk) = zcoef * ( rhd(:,:,jk) + rhd(:,:,jk-1) ) * wn(:,:,jk) * fse3w(:,:,jk)
  247. END DO
  248. ! conv value on T-point
  249. DO jk = 1, jpkm1
  250. DO jj = 1, jpj
  251. DO ji = 1, jpi
  252. zcoef = 0.5_wp / fse3t(ji,jj,jk)
  253. pconv(ji,jj,jk) = zcoef * ( zconv(ji,jj,jk) + zconv(ji,jj,jk+1) ) * tmask(ji,jj,jk)
  254. END DO
  255. END DO
  256. END DO
  257. !
  258. CALL wrk_dealloc( jpi,jpj,jpk, zconv )
  259. !
  260. END SUBROUTINE ken_p2k
  261. SUBROUTINE trd_ken_init
  262. !!---------------------------------------------------------------------
  263. !! *** ROUTINE trd_ken_init ***
  264. !!
  265. !! ** Purpose : initialisation of 3D Kinetic Energy trend diagnostic
  266. !!----------------------------------------------------------------------
  267. INTEGER :: ji, jj, jk ! dummy loop indices
  268. !!----------------------------------------------------------------------
  269. !
  270. IF(lwp) THEN
  271. WRITE(numout,*)
  272. WRITE(numout,*) 'trd_ken_init : 3D Kinetic Energy trends'
  273. WRITE(numout,*) '~~~~~~~~~~~~~'
  274. ENDIF
  275. ! ! allocate box volume arrays
  276. IF ( trd_ken_alloc() /= 0 ) CALL ctl_stop('trd_ken_alloc: failed to allocate arrays')
  277. !
  278. !!gm IF( .NOT. (ln_hpg_zco.OR.ln_hpg_zps) ) &
  279. !!gm & CALL ctl_stop('trd_ken_init : only full and partial cells are coded for conversion rate')
  280. !
  281. IF ( .NOT.lk_vvl ) THEN ! constant volume: bu, bv, 1/bt computed one for all
  282. DO jk = 1, jpkm1
  283. bu (:,:,jk) = e1u(:,:) * e2u(:,:) * fse3u_n(:,:,jk)
  284. bv (:,:,jk) = e1v(:,:) * e2v(:,:) * fse3v_n(:,:,jk)
  285. r1_bt(:,:,jk) = 1._wp / ( e1e2t(:,:) * fse3t_n(:,:,jk) )
  286. END DO
  287. ENDIF
  288. !
  289. END SUBROUTINE trd_ken_init
  290. !!======================================================================
  291. END MODULE trdken