dynadv_ubs.F90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. MODULE dynadv_ubs
  2. !!======================================================================
  3. !! *** MODULE dynadv_ubs ***
  4. !! Ocean dynamics: Update the momentum trend with the flux form advection
  5. !! trend using a 3rd order upstream biased scheme
  6. !!======================================================================
  7. !! History : 2.0 ! 2006-08 (R. Benshila, L. Debreu) Original code
  8. !! 3.2 ! 2009-07 (R. Benshila) Suppression of rigid-lid option
  9. !!----------------------------------------------------------------------
  10. !!----------------------------------------------------------------------
  11. !! dyn_adv_ubs : flux form momentum advection using (ln_dynadv=T)
  12. !! an 3rd order Upstream Biased Scheme or Quick scheme
  13. !! combined with 2nd or 4th order finite differences
  14. !!----------------------------------------------------------------------
  15. USE oce ! ocean dynamics and tracers
  16. USE dom_oce ! ocean space and time domain
  17. USE trd_oce ! trends: ocean variables
  18. USE trddyn ! trend manager: dynamics
  19. !
  20. USE in_out_manager ! I/O manager
  21. USE prtctl ! Print control
  22. USE lbclnk ! ocean lateral boundary conditions (or mpp link)
  23. USE lib_mpp ! MPP library
  24. USE wrk_nemo ! Memory Allocation
  25. USE timing ! Timing
  26. IMPLICIT NONE
  27. PRIVATE
  28. REAL(wp), PARAMETER :: gamma1 = 1._wp/3._wp ! =1/4 quick ; =1/3 3rd order UBS
  29. REAL(wp), PARAMETER :: gamma2 = 1._wp/32._wp ! =0 2nd order ; =1/32 4th order centred
  30. PUBLIC dyn_adv_ubs ! routine called by step.F90
  31. !! * Substitutions
  32. # include "domzgr_substitute.h90"
  33. # include "vectopt_loop_substitute.h90"
  34. !!----------------------------------------------------------------------
  35. !! NEMO/OPA 4.0 , NEMO Consortium (2011)
  36. !! $Id: dynadv_ubs.F90 4990 2014-12-15 16:42:49Z timgraham $
  37. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  38. !!----------------------------------------------------------------------
  39. CONTAINS
  40. SUBROUTINE dyn_adv_ubs( kt )
  41. !!----------------------------------------------------------------------
  42. !! *** ROUTINE dyn_adv_ubs ***
  43. !!
  44. !! ** Purpose : Compute the now momentum advection trend in flux form
  45. !! and the general trend of the momentum equation.
  46. !!
  47. !! ** Method : The scheme is the one implemeted in ROMS. It depends
  48. !! on two parameter gamma1 and gamma2. The former control the
  49. !! upstream baised part of the scheme and the later the centred
  50. !! part: gamma1 = 0 pure centered (no diffusive part)
  51. !! = 1/4 Quick scheme
  52. !! = 1/3 3rd order Upstream biased scheme
  53. !! gamma2 = 0 2nd order finite differencing
  54. !! = 1/32 4th order finite differencing
  55. !! For stability reasons, the first term of the fluxes which cor-
  56. !! responds to a second order centered scheme is evaluated using
  57. !! the now velocity (centered in time) while the second term which
  58. !! is the diffusive part of the scheme, is evaluated using the
  59. !! before velocity (forward in time).
  60. !! Default value (hard coded in the begining of the module) are
  61. !! gamma1=1/3 and gamma2=1/32.
  62. !!
  63. !! ** Action : - (ua,va) updated with the 3D advective momentum trends
  64. !!
  65. !! Reference : Shchepetkin & McWilliams, 2005, Ocean Modelling.
  66. !!----------------------------------------------------------------------
  67. INTEGER, INTENT(in) :: kt ! ocean time-step index
  68. !
  69. INTEGER :: ji, jj, jk ! dummy loop indices
  70. REAL(wp) :: zbu, zbv ! temporary scalars
  71. REAL(wp) :: zui, zvj, zfuj, zfvi, zl_u, zl_v ! temporary scalars
  72. REAL(wp), POINTER, DIMENSION(:,:,: ) :: zfu, zfv
  73. REAL(wp), POINTER, DIMENSION(:,:,: ) :: zfu_t, zfv_t, zfu_f, zfv_f, zfu_uw, zfv_vw, zfw
  74. REAL(wp), POINTER, DIMENSION(:,:,:,:) :: zlu_uu, zlv_vv, zlu_uv, zlv_vu
  75. !!----------------------------------------------------------------------
  76. !
  77. IF( nn_timing == 1 ) CALL timing_start('dyn_adv_ubs')
  78. !
  79. CALL wrk_alloc( jpi, jpj, jpk, zfu_t , zfv_t , zfu_f , zfv_f, zfu_uw, zfv_vw, zfu, zfv, zfw )
  80. CALL wrk_alloc( jpi, jpj, jpk, jpts, zlu_uu, zlv_vv, zlu_uv, zlv_vu )
  81. !
  82. IF( kt == nit000 ) THEN
  83. IF(lwp) WRITE(numout,*)
  84. IF(lwp) WRITE(numout,*) 'dyn_adv_ubs : UBS flux form momentum advection'
  85. IF(lwp) WRITE(numout,*) '~~~~~~~~~~~'
  86. ENDIF
  87. !
  88. zfu_t(:,:,:) = 0._wp
  89. zfv_t(:,:,:) = 0._wp
  90. zfu_f(:,:,:) = 0._wp
  91. zfv_f(:,:,:) = 0._wp
  92. !
  93. zlu_uu(:,:,:,:) = 0._wp
  94. zlv_vv(:,:,:,:) = 0._wp
  95. zlu_uv(:,:,:,:) = 0._wp
  96. zlv_vu(:,:,:,:) = 0._wp
  97. IF( l_trddyn ) THEN ! Save ua and va trends
  98. zfu_uw(:,:,:) = ua(:,:,:)
  99. zfv_vw(:,:,:) = va(:,:,:)
  100. ENDIF
  101. ! ! =========================== !
  102. DO jk = 1, jpkm1 ! Laplacian of the velocity !
  103. ! ! =========================== !
  104. ! ! horizontal volume fluxes
  105. zfu(:,:,jk) = e2u(:,:) * fse3u(:,:,jk) * un(:,:,jk)
  106. zfv(:,:,jk) = e1v(:,:) * fse3v(:,:,jk) * vn(:,:,jk)
  107. !
  108. DO jj = 2, jpjm1 ! laplacian
  109. DO ji = fs_2, fs_jpim1 ! vector opt.
  110. !
  111. zlu_uu(ji,jj,jk,1) = ( ub (ji+1,jj ,jk) - 2.*ub (ji,jj,jk) + ub (ji-1,jj ,jk) ) * umask(ji,jj,jk)
  112. zlv_vv(ji,jj,jk,1) = ( vb (ji ,jj+1,jk) - 2.*vb (ji,jj,jk) + vb (ji ,jj-1,jk) ) * vmask(ji,jj,jk)
  113. zlu_uv(ji,jj,jk,1) = ( ub (ji ,jj+1,jk) - ub (ji ,jj ,jk) ) * fmask(ji ,jj ,jk) &
  114. & - ( ub (ji ,jj ,jk) - ub (ji ,jj-1,jk) ) * fmask(ji ,jj-1,jk)
  115. zlv_vu(ji,jj,jk,1) = ( vb (ji+1,jj ,jk) - vb (ji ,jj ,jk) ) * fmask(ji ,jj ,jk) &
  116. & - ( vb (ji ,jj ,jk) - vb (ji-1,jj ,jk) ) * fmask(ji-1,jj ,jk)
  117. !
  118. zlu_uu(ji,jj,jk,2) = ( zfu(ji+1,jj ,jk) - 2.*zfu(ji,jj,jk) + zfu(ji-1,jj ,jk) ) * umask(ji,jj,jk)
  119. zlv_vv(ji,jj,jk,2) = ( zfv(ji ,jj+1,jk) - 2.*zfv(ji,jj,jk) + zfv(ji ,jj-1,jk) ) * vmask(ji,jj,jk)
  120. zlu_uv(ji,jj,jk,2) = ( zfu(ji ,jj+1,jk) - zfu(ji ,jj ,jk) ) * fmask(ji ,jj ,jk) &
  121. & - ( zfu(ji ,jj ,jk) - zfu(ji ,jj-1,jk) ) * fmask(ji ,jj-1,jk)
  122. zlv_vu(ji,jj,jk,2) = ( zfv(ji+1,jj ,jk) - zfv(ji ,jj ,jk) ) * fmask(ji ,jj ,jk) &
  123. & - ( zfv(ji ,jj ,jk) - zfv(ji-1,jj ,jk) ) * fmask(ji-1,jj ,jk)
  124. END DO
  125. END DO
  126. END DO
  127. CALL lbc_lnk( zlu_uu(:,:,:,1), 'U', 1. ) ; CALL lbc_lnk( zlu_uv(:,:,:,1), 'U', 1. )
  128. CALL lbc_lnk( zlu_uu(:,:,:,2), 'U', 1. ) ; CALL lbc_lnk( zlu_uv(:,:,:,2), 'U', 1. )
  129. CALL lbc_lnk( zlv_vv(:,:,:,1), 'V', 1. ) ; CALL lbc_lnk( zlv_vu(:,:,:,1), 'V', 1. )
  130. CALL lbc_lnk( zlv_vv(:,:,:,2), 'V', 1. ) ; CALL lbc_lnk( zlv_vu(:,:,:,2), 'V', 1. )
  131. ! ! ====================== !
  132. ! ! Horizontal advection !
  133. DO jk = 1, jpkm1 ! ====================== !
  134. ! ! horizontal volume fluxes
  135. zfu(:,:,jk) = 0.25 * e2u(:,:) * fse3u(:,:,jk) * un(:,:,jk)
  136. zfv(:,:,jk) = 0.25 * e1v(:,:) * fse3v(:,:,jk) * vn(:,:,jk)
  137. !
  138. DO jj = 1, jpjm1 ! horizontal momentum fluxes at T- and F-point
  139. DO ji = 1, fs_jpim1 ! vector opt.
  140. zui = ( un(ji,jj,jk) + un(ji+1,jj ,jk) )
  141. zvj = ( vn(ji,jj,jk) + vn(ji ,jj+1,jk) )
  142. !
  143. IF (zui > 0) THEN ; zl_u = zlu_uu(ji ,jj,jk,1)
  144. ELSE ; zl_u = zlu_uu(ji+1,jj,jk,1)
  145. ENDIF
  146. IF (zvj > 0) THEN ; zl_v = zlv_vv(ji,jj ,jk,1)
  147. ELSE ; zl_v = zlv_vv(ji,jj+1,jk,1)
  148. ENDIF
  149. !
  150. zfu_t(ji+1,jj ,jk) = ( zfu(ji,jj,jk) + zfu(ji+1,jj ,jk) &
  151. & - gamma2 * ( zlu_uu(ji,jj,jk,2) + zlu_uu(ji+1,jj ,jk,2) ) ) &
  152. & * ( zui - gamma1 * zl_u)
  153. zfv_t(ji ,jj+1,jk) = ( zfv(ji,jj,jk) + zfv(ji ,jj+1,jk) &
  154. & - gamma2 * ( zlv_vv(ji,jj,jk,2) + zlv_vv(ji ,jj+1,jk,2) ) ) &
  155. & * ( zvj - gamma1 * zl_v)
  156. !
  157. zfuj = ( zfu(ji,jj,jk) + zfu(ji ,jj+1,jk) )
  158. zfvi = ( zfv(ji,jj,jk) + zfv(ji+1,jj ,jk) )
  159. IF (zfuj > 0) THEN ; zl_v = zlv_vu( ji ,jj ,jk,1)
  160. ELSE ; zl_v = zlv_vu( ji+1,jj,jk,1)
  161. ENDIF
  162. IF (zfvi > 0) THEN ; zl_u = zlu_uv( ji,jj ,jk,1)
  163. ELSE ; zl_u = zlu_uv( ji,jj+1,jk,1)
  164. ENDIF
  165. !
  166. zfv_f(ji ,jj ,jk) = ( zfvi - gamma2 * ( zlv_vu(ji,jj,jk,2) + zlv_vu(ji+1,jj ,jk,2) ) ) &
  167. & * ( un(ji,jj,jk) + un(ji ,jj+1,jk) - gamma1 * zl_u )
  168. zfu_f(ji ,jj ,jk) = ( zfuj - gamma2 * ( zlu_uv(ji,jj,jk,2) + zlu_uv(ji ,jj+1,jk,2) ) ) &
  169. & * ( vn(ji,jj,jk) + vn(ji+1,jj ,jk) - gamma1 * zl_v )
  170. END DO
  171. END DO
  172. DO jj = 2, jpjm1 ! divergence of horizontal momentum fluxes
  173. DO ji = fs_2, fs_jpim1 ! vector opt.
  174. zbu = e1u(ji,jj) * e2u(ji,jj) * fse3u(ji,jj,jk)
  175. zbv = e1v(ji,jj) * e2v(ji,jj) * fse3v(ji,jj,jk)
  176. !
  177. ua(ji,jj,jk) = ua(ji,jj,jk) - ( zfu_t(ji+1,jj ,jk) - zfu_t(ji ,jj ,jk) &
  178. & + zfv_f(ji ,jj ,jk) - zfv_f(ji ,jj-1,jk) ) / zbu
  179. va(ji,jj,jk) = va(ji,jj,jk) - ( zfu_f(ji ,jj ,jk) - zfu_f(ji-1,jj ,jk) &
  180. & + zfv_t(ji ,jj+1,jk) - zfv_t(ji ,jj ,jk) ) / zbv
  181. END DO
  182. END DO
  183. END DO
  184. IF( l_trddyn ) THEN ! save the horizontal advection trend for diagnostic
  185. zfu_uw(:,:,:) = ua(:,:,:) - zfu_uw(:,:,:)
  186. zfv_vw(:,:,:) = va(:,:,:) - zfv_vw(:,:,:)
  187. CALL trd_dyn( zfu_uw, zfv_vw, jpdyn_keg, kt )
  188. zfu_t(:,:,:) = ua(:,:,:)
  189. zfv_t(:,:,:) = va(:,:,:)
  190. ENDIF
  191. ! ! ==================== !
  192. ! ! Vertical advection !
  193. DO jk = 1, jpkm1 ! ==================== !
  194. ! ! Vertical volume fluxesÊ
  195. zfw(:,:,jk) = 0.25 * e1t(:,:) * e2t(:,:) * wn(:,:,jk)
  196. !
  197. IF( jk == 1 ) THEN ! surface/bottom advective fluxes
  198. zfu_uw(:,:,jpk) = 0.e0 ! Bottom value : flux set to zero
  199. zfv_vw(:,:,jpk) = 0.e0
  200. ! ! Surface value :
  201. IF( lk_vvl ) THEN ! variable volume : flux set to zero
  202. zfu_uw(:,:, 1 ) = 0.e0
  203. zfv_vw(:,:, 1 ) = 0.e0
  204. ELSE ! constant volume : advection through the surface
  205. DO jj = 2, jpjm1
  206. DO ji = fs_2, fs_jpim1
  207. zfu_uw(ji,jj, 1 ) = 2.e0 * ( zfw(ji,jj,1) + zfw(ji+1,jj ,1) ) * un(ji,jj,1)
  208. zfv_vw(ji,jj, 1 ) = 2.e0 * ( zfw(ji,jj,1) + zfw(ji ,jj+1,1) ) * vn(ji,jj,1)
  209. END DO
  210. END DO
  211. ENDIF
  212. ELSE ! interior fluxes
  213. DO jj = 2, jpjm1
  214. DO ji = fs_2, fs_jpim1 ! vector opt.
  215. zfu_uw(ji,jj,jk) = ( zfw(ji,jj,jk)+ zfw(ji+1,jj ,jk) ) * ( un(ji,jj,jk) + un(ji,jj,jk-1) )
  216. zfv_vw(ji,jj,jk) = ( zfw(ji,jj,jk)+ zfw(ji ,jj+1,jk) ) * ( vn(ji,jj,jk) + vn(ji,jj,jk-1) )
  217. END DO
  218. END DO
  219. ENDIF
  220. END DO
  221. DO jk = 1, jpkm1 ! divergence of vertical momentum flux divergence
  222. DO jj = 2, jpjm1
  223. DO ji = fs_2, fs_jpim1 ! vector opt.
  224. ua(ji,jj,jk) = ua(ji,jj,jk) - ( zfu_uw(ji,jj,jk) - zfu_uw(ji,jj,jk+1) ) &
  225. & / ( e1u(ji,jj) * e2u(ji,jj) * fse3u(ji,jj,jk) )
  226. va(ji,jj,jk) = va(ji,jj,jk) - ( zfv_vw(ji,jj,jk) - zfv_vw(ji,jj,jk+1) ) &
  227. & / ( e1v(ji,jj) * e2v(ji,jj) * fse3v(ji,jj,jk) )
  228. END DO
  229. END DO
  230. END DO
  231. !
  232. IF( l_trddyn ) THEN ! save the vertical advection trend for diagnostic
  233. zfu_t(:,:,:) = ua(:,:,:) - zfu_t(:,:,:)
  234. zfv_t(:,:,:) = va(:,:,:) - zfv_t(:,:,:)
  235. CALL trd_dyn( zfu_t, zfv_t, jpdyn_zad, kt )
  236. ENDIF
  237. ! ! Control print
  238. IF(ln_ctl) CALL prt_ctl( tab3d_1=ua, clinfo1=' ubs2 adv - Ua: ', mask1=umask, &
  239. & tab3d_2=va, clinfo2= ' Va: ', mask2=vmask, clinfo3='dyn' )
  240. !
  241. CALL wrk_dealloc( jpi, jpj, jpk, zfu_t , zfv_t , zfu_f , zfv_f, zfu_uw, zfv_vw, zfu, zfv, zfw )
  242. CALL wrk_dealloc( jpi, jpj, jpk, jpts, zlu_uu, zlv_vv, zlu_uv, zlv_vu )
  243. !
  244. IF( nn_timing == 1 ) CALL timing_stop('dyn_adv_ubs')
  245. !
  246. END SUBROUTINE dyn_adv_ubs
  247. !!==============================================================================
  248. END MODULE dynadv_ubs