traadv_mle.F90 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. MODULE traadv_mle
  2. !!======================================================================
  3. !! *** MODULE traadv_mle ***
  4. !! Ocean tracers: Mixed Layer Eddy induced transport
  5. !!======================================================================
  6. !! History : 3.3 ! 2010-08 (G. Madec) Original code
  7. !!----------------------------------------------------------------------
  8. !!----------------------------------------------------------------------
  9. !! tra_adv_mle : update the effective transport with the Mixed Layer Eddy induced transport
  10. !! tra_adv_mle_init : initialisation of the Mixed Layer Eddy induced transport computation
  11. !!----------------------------------------------------------------------
  12. USE oce ! ocean dynamics and tracers variables
  13. USE dom_oce ! ocean space and time domain variables
  14. USE phycst ! physical constant
  15. USE zdfmxl ! mixed layer depth
  16. USE lbclnk ! lateral boundary condition / mpp link
  17. USE in_out_manager ! I/O manager
  18. USE iom ! IOM library
  19. USE lib_mpp ! MPP library
  20. USE wrk_nemo ! work arrays
  21. USE timing ! Timing
  22. IMPLICIT NONE
  23. PRIVATE
  24. PUBLIC tra_adv_mle ! routine called in traadv.F90
  25. PUBLIC tra_adv_mle_init ! routine called in traadv.F90
  26. ! !!* namelist namtra_adv_mle *
  27. LOGICAL, PUBLIC :: ln_mle ! flag to activate the Mixed Layer Eddy (MLE) parameterisation
  28. INTEGER :: nn_mle ! MLE type: =0 standard Fox-Kemper ; =1 new formulation
  29. INTEGER :: nn_mld_uv ! space interpolation of MLD at u- & v-pts (0=min,1=averaged,2=max)
  30. INTEGER :: nn_conv ! =1 no MLE in case of convection ; =0 always MLE
  31. REAL(wp) :: rn_ce ! MLE coefficient
  32. ! ! parameters used in nn_mle = 0 case
  33. REAL(wp) :: rn_lf ! typical scale of mixed layer front
  34. REAL(wp) :: rn_time ! time scale for mixing momentum across the mixed layer
  35. ! ! parameters used in nn_mle = 1 case
  36. REAL(wp) :: rn_lat ! reference latitude for a 5 km scale of ML front
  37. REAL(wp) :: rn_rho_c_mle ! Density criterion for definition of MLD used by FK
  38. REAL(wp) :: r5_21 = 5.e0 / 21.e0 ! factor used in mle streamfunction computation
  39. REAL(wp) :: rb_c ! ML buoyancy criteria = g rho_c /rau0 where rho_c is defined in zdfmld
  40. REAL(wp) :: rc_f ! MLE coefficient (= rn_ce / (5 km * fo) ) in nn_mle=1 case
  41. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: rfu, rfv ! modified Coriolis parameter (f+tau) at u- & v-pts
  42. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: r1_ft ! inverse of the modified Coriolis parameter at t-pts
  43. !! * Substitutions
  44. # include "domzgr_substitute.h90"
  45. # include "vectopt_loop_substitute.h90"
  46. !!----------------------------------------------------------------------
  47. !! NEMO/OPA 4.0 , NEMO Consortium (2011)
  48. !! $Id: traadv_mle.F90 2355 2015-05-20 07:11:50Z ufla $
  49. !! Software governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt)
  50. !!----------------------------------------------------------------------
  51. CONTAINS
  52. SUBROUTINE tra_adv_mle( kt, kit000, pu, pv, pw, cdtype )
  53. !!----------------------------------------------------------------------
  54. !! *** ROUTINE adv_mle ***
  55. !!
  56. !! ** Purpose : Add to the transport the Mixed Layer Eddy induced transport
  57. !!
  58. !! ** Method : The 3 components of the Mixed Layer Eddy (MLE) induced
  59. !! transport are computed as follows :
  60. !! zu_mle = dk[ zpsi_uw ]
  61. !! zv_mle = dk[ zpsi_vw ]
  62. !! zw_mle = - di[ zpsi_uw ] - dj[ zpsi_vw ]
  63. !! where zpsi is the MLE streamfunction at uw and vw points (see the doc)
  64. !! and added to the input velocity :
  65. !! p.n = p.n + z._mle
  66. !!
  67. !! ** Action : - (pun,pvn,pwn) increased by the mle transport
  68. !! CAUTION, the transport is not updated at the last line/raw
  69. !! this may be a problem for some advection schemes
  70. !!
  71. !! References: Fox-Kemper et al., JPO, 38, 1145-1165, 2008
  72. !! Fox-Kemper and Ferrari, JPO, 38, 1166-1179, 2008
  73. !!----------------------------------------------------------------------
  74. !
  75. INTEGER , INTENT(in ) :: kt ! ocean time-step index
  76. INTEGER , INTENT(in ) :: kit000 ! first time step index
  77. CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator)
  78. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) :: pu ! in : 3 ocean transport components
  79. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) :: pv ! out: same 3 transport components
  80. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) :: pw ! increased by the MLE induced transport
  81. !
  82. INTEGER :: ji, jj, jk ! dummy loop indices
  83. INTEGER :: ikmax ! temporary integer
  84. REAL(wp) :: zcuw, zmuw ! local scalar
  85. REAL(wp) :: zcvw, zmvw ! - -
  86. REAL(wp) :: zc ! - -
  87. INTEGER :: ii, ij, ik ! local integers
  88. INTEGER, DIMENSION(3) :: ilocu !
  89. INTEGER, DIMENSION(2) :: ilocs !
  90. REAL(wp), POINTER, DIMENSION(:,: ) :: zpsim_u, zpsim_v, zmld, zbm, zhu, zhv, zn2, zLf_NH, zLf_MH
  91. REAL(wp), POINTER, DIMENSION(:,:,:) :: zpsi_uw, zpsi_vw
  92. INTEGER, POINTER, DIMENSION(:,:) :: inml_mle
  93. !!----------------------------------------------------------------------
  94. IF( nn_timing == 1 ) CALL timing_start('tra_adv_mle')
  95. CALL wrk_alloc( jpi, jpj, zpsim_u, zpsim_v, zmld, zbm, zhu, zhv, zn2, zLf_NH, zLf_MH)
  96. CALL wrk_alloc( jpi, jpj, jpk, zpsi_uw, zpsi_vw)
  97. CALL wrk_alloc( jpi, jpj, inml_mle)
  98. !
  99. ! !== MLD used for MLE ==!
  100. ! ! compute from the 10m density to deal with the diurnal cycle
  101. inml_mle(:,:) = mbkt(:,:) + 1 ! init. to number of ocean w-level (T-level + 1)
  102. DO jk = jpkm1, nlb10, -1 ! from the bottom to nlb10 (10m)
  103. DO jj = 1, jpj
  104. DO ji = 1, jpi ! index of the w-level at the ML based
  105. IF( rhop(ji,jj,jk) > rhop(ji,jj,nla10) + rn_rho_c_mle ) inml_mle(ji,jj) = jk ! Mixed layer
  106. END DO
  107. END DO
  108. END DO
  109. ikmax = MIN( MAXVAL( inml_mle(:,:) ), jpkm1 ) ! max level of the computation
  110. !
  111. !
  112. zmld(:,:) = 0._wp !== Horizontal shape of the MLE ==!
  113. zbm (:,:) = 0._wp
  114. zn2 (:,:) = 0._wp
  115. DO jk = 1, ikmax ! MLD and mean buoyancy and N2 over the mixed layer
  116. DO jj = 1, jpj
  117. DO ji = 1, jpi
  118. zc = fse3t(ji,jj,jk) * REAL( MIN( MAX( 0, inml_mle(ji,jj)-jk ) , 1 ) ) ! zc being 0 outside the ML t-points
  119. zmld(ji,jj) = zmld(ji,jj) + zc
  120. zbm (ji,jj) = zbm (ji,jj) + zc * (rau0 - rhop(ji,jj,jk) ) * r1_rau0
  121. zn2 (ji,jj) = zn2 (ji,jj) + zc * (rn2(ji,jj,jk)+rn2(ji,jj,jk+1))*0.5_wp
  122. END DO
  123. END DO
  124. END DO
  125. SELECT CASE( nn_mld_uv ) ! MLD at u- & v-pts
  126. CASE ( 0 ) != min of the 2 neighbour MLDs
  127. DO jj = 1, jpjm1
  128. DO ji = 1, fs_jpim1 ! vector opt.
  129. zhu(ji,jj) = MIN( zmld(ji+1,jj), zmld(ji,jj) )
  130. zhv(ji,jj) = MIN( zmld(ji,jj+1), zmld(ji,jj) )
  131. END DO
  132. END DO
  133. CASE ( 1 ) != average of the 2 neighbour MLDs
  134. DO jj = 1, jpjm1
  135. DO ji = 1, fs_jpim1 ! vector opt.
  136. zhu(ji,jj) = ( zmld(ji+1,jj) + zmld(ji,jj) ) * 0.5_wp
  137. zhv(ji,jj) = ( zmld(ji,jj+1) + zmld(ji,jj) ) * 0.5_wp
  138. END DO
  139. END DO
  140. CASE ( 2 ) != max of the 2 neighbour MLDs
  141. DO jj = 1, jpjm1
  142. DO ji = 1, fs_jpim1 ! vector opt.
  143. zhu(ji,jj) = MAX( zmld(ji+1,jj), zmld(ji,jj) )
  144. zhv(ji,jj) = MAX( zmld(ji,jj+1), zmld(ji,jj) )
  145. END DO
  146. END DO
  147. END SELECT
  148. ! ! convert density into buoyancy
  149. zbm(:,:) = + grav * zbm(:,:) / MAX( fse3t(:,:,1), zmld(:,:) )
  150. !
  151. !
  152. ! !== Magnitude of the MLE stream function ==!
  153. !
  154. ! di[bm] Ds
  155. ! Psi = Ce H^2 ---------------- e2u mu(z) where fu Lf = MAX( fu*rn_fl , (Db H)^1/2 )
  156. ! e1u Lf fu and the e2u for the "transport"
  157. ! (not *e3u as divided by e3u at the end)
  158. !
  159. IF( nn_mle == 0 ) THEN ! Fox-Kemper et al. 2010 formulation
  160. DO jj = 1, jpjm1
  161. DO ji = 1, fs_jpim1 ! vector opt.
  162. zpsim_u(ji,jj) = rn_ce * zhu(ji,jj) * zhu(ji,jj) * e2u(ji,jj) &
  163. & * ( zbm(ji+1,jj) - zbm(ji,jj) ) * MIN( 111.e3_wp , e1u(ji,jj) ) &
  164. & / ( e1u(ji,jj) * MAX( rn_lf * rfu(ji,jj) , SQRT( rb_c * zhu(ji,jj) ) ) )
  165. !
  166. zpsim_v(ji,jj) = rn_ce * zhv(ji,jj) * zhv(ji,jj) * e1v(ji,jj) &
  167. & * ( zbm(ji,jj+1) - zbm(ji,jj) ) * MIN( 111.e3_wp , e2v(ji,jj) ) &
  168. & / ( e2v(ji,jj) * MAX( rn_lf * rfv(ji,jj) , SQRT( rb_c * zhv(ji,jj) ) ) )
  169. END DO
  170. END DO
  171. !
  172. ELSEIF( nn_mle == 1 ) THEN ! New formulation (Lf = 5km fo/ff with fo=Coriolis parameter at latitude rn_lat)
  173. DO jj = 1, jpjm1
  174. DO ji = 1, fs_jpim1 ! vector opt.
  175. zpsim_u(ji,jj) = rc_f * zhu(ji,jj) * zhu(ji,jj) * e2u(ji,jj) / e1u(ji,jj) &
  176. & * ( zbm(ji+1,jj) - zbm(ji,jj) ) * MIN( 111.e3_wp , e1u(ji,jj) )
  177. !
  178. zpsim_v(ji,jj) = rc_f * zhv(ji,jj) * zhv(ji,jj) * e1v(ji,jj) / e2v(ji,jj) &
  179. & * ( zbm(ji,jj+1) - zbm(ji,jj) ) * MIN( 111.e3_wp , e2v(ji,jj) )
  180. END DO
  181. END DO
  182. ENDIF
  183. !
  184. IF( nn_conv == 1 ) THEN ! No MLE in case of convection
  185. DO jj = 1, jpjm1
  186. DO ji = 1, fs_jpim1 ! vector opt.
  187. IF( MIN( zn2(ji,jj) , zn2(ji+1,jj) ) < 0._wp ) zpsim_u(ji,jj) = 0._wp
  188. IF( MIN( zn2(ji,jj) , zn2(ji,jj+1) ) < 0._wp ) zpsim_v(ji,jj) = 0._wp
  189. END DO
  190. END DO
  191. ENDIF
  192. !
  193. ! !== structure function value at uw- and vw-points ==!
  194. DO jj = 1, jpjm1
  195. DO ji = 1, fs_jpim1 ! vector opt.
  196. zhu(ji,jj) = 1._wp / zhu(ji,jj) ! hu --> 1/hu
  197. zhv(ji,jj) = 1._wp / zhv(ji,jj)
  198. END DO
  199. END DO
  200. !
  201. zpsi_uw(:,:,:) = 0._wp
  202. zpsi_vw(:,:,:) = 0._wp
  203. !
  204. DO jk = 2, ikmax ! start from 2 : surface value = 0
  205. DO jj = 1, jpjm1
  206. DO ji = 1, fs_jpim1 ! vector opt.
  207. zcuw = 1._wp - ( fsdepw(ji+1,jj,jk) + fsdepw(ji,jj,jk) ) * zhu(ji,jj)
  208. zcvw = 1._wp - ( fsdepw(ji,jj+1,jk) + fsdepw(ji,jj,jk) ) * zhv(ji,jj)
  209. zcuw = zcuw * zcuw
  210. zcvw = zcvw * zcvw
  211. zmuw = MAX( 0._wp , ( 1._wp - zcuw ) * ( 1._wp + r5_21 * zcuw ) )
  212. zmvw = MAX( 0._wp , ( 1._wp - zcvw ) * ( 1._wp + r5_21 * zcvw ) )
  213. !
  214. zpsi_uw(ji,jj,jk) = zpsim_u(ji,jj) * zmuw * umask(ji,jj,jk)
  215. zpsi_vw(ji,jj,jk) = zpsim_v(ji,jj) * zmvw * vmask(ji,jj,jk)
  216. END DO
  217. END DO
  218. END DO
  219. !
  220. ! !== transport increased by the MLE induced transport ==!
  221. DO jk = 1, ikmax
  222. DO jj = 1, jpjm1 ! CAUTION pu,pv must be defined at row/column i=1 / j=1
  223. DO ji = 1, fs_jpim1 ! vector opt.
  224. pu(ji,jj,jk) = pu(ji,jj,jk) + ( zpsi_uw(ji,jj,jk) - zpsi_uw(ji,jj,jk+1) )
  225. pv(ji,jj,jk) = pv(ji,jj,jk) + ( zpsi_vw(ji,jj,jk) - zpsi_vw(ji,jj,jk+1) )
  226. END DO
  227. END DO
  228. DO jj = 2, jpjm1
  229. DO ji = fs_2, fs_jpim1 ! vector opt.
  230. pw(ji,jj,jk) = pw(ji,jj,jk) - ( zpsi_uw(ji,jj,jk) - zpsi_uw(ji-1,jj,jk) &
  231. & + zpsi_vw(ji,jj,jk) - zpsi_vw(ji,jj-1,jk) )
  232. END DO
  233. END DO
  234. END DO
  235. IF( cdtype == 'TRA') THEN !== outputs ==!
  236. !
  237. zLf_NH(:,:) = SQRT( rb_c * zmld(:,:) ) * r1_ft(:,:) ! Lf = N H / f
  238. CALL iom_put( "Lf_NHpf" , zLf_NH ) ! Lf = N H / f
  239. !
  240. ! divide by cross distance to give streamfunction with dimensions m^2/s
  241. DO jk = 1, ikmax+1
  242. zpsi_uw(:,:,jk) = zpsi_uw(:,:,jk)/e2u(:,:)
  243. zpsi_vw(:,:,jk) = zpsi_vw(:,:,jk)/e1v(:,:)
  244. END DO
  245. CALL iom_put( "psiu_mle", zpsi_uw ) ! i-mle streamfunction
  246. CALL iom_put( "psiv_mle", zpsi_vw ) ! j-mle streamfunction
  247. ENDIF
  248. CALL wrk_dealloc( jpi, jpj, zpsim_u, zpsim_v, zmld, zbm, zhu, zhv, zn2, zLf_NH, zLf_MH)
  249. CALL wrk_dealloc( jpi, jpj, jpk, zpsi_uw, zpsi_vw)
  250. CALL wrk_dealloc( jpi, jpj, inml_mle)
  251. IF( nn_timing == 1 ) CALL timing_stop('tra_adv_mle')
  252. !
  253. END SUBROUTINE tra_adv_mle
  254. SUBROUTINE tra_adv_mle_init
  255. !!---------------------------------------------------------------------
  256. !! *** ROUTINE tra_adv_mle_init ***
  257. !!
  258. !! ** Purpose : Control the consistency between namelist options for
  259. !! tracer advection schemes and set nadv
  260. !!----------------------------------------------------------------------
  261. INTEGER :: ji, jj, jk ! dummy loop indices
  262. INTEGER :: ierr
  263. INTEGER :: ios ! Local integer output status for namelist read
  264. REAL(wp) :: z1_t2, zfu, zfv ! - -
  265. !
  266. NAMELIST/namtra_adv_mle/ ln_mle , nn_mle, rn_ce, rn_lf, rn_time, rn_lat, nn_mld_uv, nn_conv, rn_rho_c_mle
  267. !!----------------------------------------------------------------------
  268. REWIND( numnam_ref ) ! Namelist namtra_adv_mle in reference namelist : Tracer advection scheme
  269. READ ( numnam_ref, namtra_adv_mle, IOSTAT = ios, ERR = 901)
  270. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namtra_adv_mle in reference namelist', lwp )
  271. REWIND( numnam_cfg ) ! Namelist namtra_adv_mle in configuration namelist : Tracer advection scheme
  272. READ ( numnam_cfg, namtra_adv_mle, IOSTAT = ios, ERR = 902 )
  273. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namtra_adv_mle in configuration namelist', lwp )
  274. IF(lwm) WRITE ( numond, namtra_adv_mle )
  275. IF(lwp) THEN ! Namelist print
  276. WRITE(numout,*)
  277. WRITE(numout,*) 'tra_adv_mle_init : mixed layer eddy (MLE) advection acting on tracers'
  278. WRITE(numout,*) '~~~~~~~~~~~~~~~~'
  279. WRITE(numout,*) ' Namelist namtra_adv_mle : mixed layer eddy advection on tracers'
  280. WRITE(numout,*) ' use mixed layer eddy (MLE, i.e. Fox-Kemper param) (T/F) ln_mle = ', ln_mle
  281. WRITE(numout,*) ' MLE type: =0 standard Fox-Kemper ; =1 new formulation nn_mle = ', nn_mle
  282. WRITE(numout,*) ' magnitude of the MLE (typical value: 0.06 to 0.08) rn_ce = ', rn_ce
  283. WRITE(numout,*) ' scale of ML front (ML radius of deformation) (rn_mle=0) rn_lf = ', rn_lf, 'm'
  284. WRITE(numout,*) ' maximum time scale of MLE (rn_mle=0) rn_time = ', rn_time, 's'
  285. WRITE(numout,*) ' reference latitude (degrees) of MLE coef. (rn_mle=1) rn_lat = ', rn_lat, 'deg'
  286. WRITE(numout,*) ' space interp. of MLD at u-(v-)pts (0=min,1=averaged,2=max) nn_mld_uv = ', nn_mld_uv
  287. WRITE(numout,*) ' =1 no MLE in case of convection ; =0 always MLE nn_conv = ', nn_conv
  288. WRITE(numout,*) ' Density difference used to define ML for FK rn_rho_c_mle = ', rn_rho_c_mle
  289. ENDIF
  290. !
  291. IF(lwp) THEN
  292. WRITE(numout,*)
  293. IF( ln_mle ) THEN
  294. WRITE(numout,*) ' Mixed Layer Eddy induced transport added to tracer advection'
  295. IF( nn_mle == 0 ) WRITE(numout,*) ' Fox-Kemper et al 2010 formulation'
  296. IF( nn_mle == 1 ) WRITE(numout,*) ' New formulation'
  297. ELSE
  298. WRITE(numout,*) ' Mixed Layer Eddy parametrisation NOT used'
  299. ENDIF
  300. ENDIF
  301. !
  302. IF( ln_mle ) THEN ! MLE initialisation
  303. !
  304. rb_c = grav * rn_rho_c_mle /rau0 ! Mixed Layer buoyancy criteria
  305. IF(lwp) WRITE(numout,*)
  306. IF(lwp) WRITE(numout,*) ' ML buoyancy criteria = ', rb_c, ' m/s2 '
  307. IF(lwp) WRITE(numout,*) ' associated ML density criteria defined in zdfmxl = ', rho_c, 'kg/m3'
  308. !
  309. IF( nn_mle == 0 ) THEN ! MLE array allocation & initialisation
  310. ALLOCATE( rfu(jpi,jpj) , rfv(jpi,jpj) , STAT= ierr )
  311. IF( ierr /= 0 ) CALL ctl_stop( 'tra_adv_mle_init: failed to allocate arrays' )
  312. z1_t2 = 1._wp / ( rn_time * rn_time )
  313. DO jj = 2, jpj ! "coriolis+ time^-1" at u- & v-points
  314. DO ji = fs_2, jpi ! vector opt.
  315. zfu = ( ff(ji,jj) + ff(ji,jj-1) ) * 0.5_wp
  316. zfv = ( ff(ji,jj) + ff(ji-1,jj) ) * 0.5_wp
  317. rfu(ji,jj) = SQRT( zfu * zfu + z1_t2 )
  318. rfv(ji,jj) = SQRT( zfv * zfv + z1_t2 )
  319. END DO
  320. END DO
  321. CALL lbc_lnk( rfu, 'U', 1. ) ; CALL lbc_lnk( rfv, 'V', 1. )
  322. !
  323. ELSEIF( nn_mle == 1 ) THEN ! MLE array allocation & initialisation
  324. rc_f = rn_ce / ( 5.e3_wp * 2._wp * omega * SIN( rad * rn_lat ) )
  325. !
  326. ENDIF
  327. !
  328. ! ! 1/(f^2+tau^2)^1/2 at t-point (needed in both nn_mle case)
  329. ALLOCATE( r1_ft(jpi,jpj) , STAT= ierr )
  330. IF( ierr /= 0 ) CALL ctl_stop( 'tra_adv_mle_init: failed to allocate r1_ft array' )
  331. !
  332. z1_t2 = 1._wp / ( rn_time * rn_time )
  333. r1_ft(:,:) = 2._wp * omega * SIN( rad * gphit(:,:) )
  334. r1_ft(:,:) = 1._wp / SQRT( r1_ft(:,:) * r1_ft(:,:) + z1_t2 )
  335. !
  336. ENDIF
  337. !
  338. END SUBROUTINE tra_adv_mle_init
  339. !!==============================================================================
  340. END MODULE traadv_mle