dynldf_bilap.F90 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. MODULE dynldf_bilap
  2. !!======================================================================
  3. !! *** MODULE dynldf_bilap ***
  4. !! Ocean dynamics: lateral viscosity trend
  5. !!======================================================================
  6. !! History : OPA ! 1990-09 (G. Madec) Original code
  7. !! 4.0 ! 1993-03 (M. Guyon) symetrical conditions (M. Guyon)
  8. !! 6.0 ! 1996-01 (G. Madec) statement function for e3
  9. !! 8.0 ! 1997-07 (G. Madec) lbc calls
  10. !! NEMO 1.0 ! 2002-08 (G. Madec) F90: Free form and module
  11. !! 2.0 ! 2004-08 (C. Talandier) New trends organization
  12. !!----------------------------------------------------------------------
  13. !!----------------------------------------------------------------------
  14. !! dyn_ldf_bilap : update the momentum trend with the lateral diffusion
  15. !! using an iso-level bilaplacian operator
  16. !!----------------------------------------------------------------------
  17. USE oce ! ocean dynamics and tracers
  18. USE dom_oce ! ocean space and time domain
  19. USE phycst ! physical constants
  20. USE ldfdyn_oce ! ocean dynamics: lateral physics
  21. !
  22. USE in_out_manager ! I/O manager
  23. USE iom ! I/O library
  24. USE lbclnk ! ocean lateral boundary conditions (or mpp link)
  25. USE wrk_nemo ! Memory Allocation
  26. USE timing ! Timing
  27. IMPLICIT NONE
  28. PRIVATE
  29. PUBLIC dyn_ldf_bilap ! called by step.F90
  30. !! * Substitutions
  31. # include "domzgr_substitute.h90"
  32. # include "ldfdyn_substitute.h90"
  33. # include "vectopt_loop_substitute.h90"
  34. !!----------------------------------------------------------------------
  35. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  36. !! $Id: dynldf_bilap.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_ldf_bilap( kt )
  41. !!----------------------------------------------------------------------
  42. !! *** ROUTINE dyn_ldf_bilap ***
  43. !!
  44. !! ** Purpose : Compute the before trend of the lateral momentum
  45. !! diffusion and add it to the general trend of momentum equation.
  46. !!
  47. !! ** Method : The before horizontal momentum diffusion trend is a
  48. !! bi-harmonic operator (bilaplacian type) which separates the
  49. !! divergent and rotational parts of the flow.
  50. !! Its horizontal components are computed as follow:
  51. !! laplacian:
  52. !! zlu = 1/e1u di[ hdivb ] - 1/(e2u*e3u) dj-1[ e3f rotb ]
  53. !! zlv = 1/e2v dj[ hdivb ] + 1/(e1v*e3v) di-1[ e3f rotb ]
  54. !! third derivative:
  55. !! * multiply by the eddy viscosity coef. at u-, v-point, resp.
  56. !! zlu = ahmu * zlu
  57. !! zlv = ahmv * zlv
  58. !! * curl and divergence of the laplacian
  59. !! zuf = 1/(e1f*e2f) ( di[e2v zlv] - dj[e1u zlu] )
  60. !! zut = 1/(e1t*e2t*e3t) ( di[e2u*e3u zlu] + dj[e1v*e3v zlv] )
  61. !! bilaplacian:
  62. !! diffu = 1/e1u di[ zut ] - 1/(e2u*e3u) dj-1[ e3f zuf ]
  63. !! diffv = 1/e2v dj[ zut ] + 1/(e1v*e3v) di-1[ e3f zuf ]
  64. !! If ln_sco=F and ln_zps=F, the vertical scale factors in the
  65. !! rotational part of the diffusion are simplified
  66. !! Add this before trend to the general trend (ua,va):
  67. !! (ua,va) = (ua,va) + (diffu,diffv)
  68. !!
  69. !! ** Action : - Update (ua,va) with the before iso-level biharmonic
  70. !! mixing trend.
  71. !!----------------------------------------------------------------------
  72. INTEGER, INTENT(in) :: kt ! ocean time-step index
  73. !
  74. INTEGER :: ji, jj, jk ! dummy loop indices
  75. REAL(wp) :: zua, zva, zbt, ze2u, ze2v, zzz ! local scalar
  76. REAL(wp), POINTER, DIMENSION(:,: ) :: zcu, zcv
  77. REAL(wp), POINTER, DIMENSION(:,:,:) :: zuf, zut, zlu, zlv
  78. REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: z2d ! 2D workspace
  79. !!----------------------------------------------------------------------
  80. !
  81. IF( nn_timing == 1 ) CALL timing_start('dyn_ldf_bilap')
  82. !
  83. CALL wrk_alloc( jpi, jpj, zcu, zcv )
  84. CALL wrk_alloc( jpi, jpj, jpk, zuf, zut, zlu, zlv )
  85. !
  86. IF( kt == nit000 .AND. lwp ) THEN
  87. WRITE(numout,*)
  88. WRITE(numout,*) 'dyn_ldf_bilap : iso-level bilaplacian operator'
  89. WRITE(numout,*) '~~~~~~~~~~~~~'
  90. ENDIF
  91. !!bug gm this should be enough
  92. !!$ zuf(:,:,jpk) = 0.e0
  93. !!$ zut(:,:,jpk) = 0.e0
  94. !!$ zlu(:,:,jpk) = 0.e0
  95. !!$ zlv(:,:,jpk) = 0.e0
  96. zuf(:,:,:) = 0._wp
  97. zut(:,:,:) = 0._wp
  98. zlu(:,:,:) = 0._wp
  99. zlv(:,:,:) = 0._wp
  100. ! ! ===============
  101. DO jk = 1, jpkm1 ! Horizontal slab
  102. ! ! ===============
  103. ! Laplacian
  104. ! ---------
  105. IF( ln_sco .OR. ln_zps ) THEN ! s-coordinate or z-coordinate with partial steps
  106. zuf(:,:,jk) = rotb(:,:,jk) * fse3f(:,:,jk)
  107. DO jj = 2, jpjm1
  108. DO ji = fs_2, fs_jpim1 ! vector opt.
  109. zlu(ji,jj,jk) = - ( zuf(ji ,jj,jk) - zuf(ji,jj-1,jk) ) / ( e2u(ji,jj) * fse3u(ji,jj,jk) ) &
  110. & + ( hdivb(ji+1,jj,jk) - hdivb(ji,jj ,jk) ) / e1u(ji,jj)
  111. zlv(ji,jj,jk) = + ( zuf(ji,jj ,jk) - zuf(ji-1,jj,jk) ) / ( e1v(ji,jj) * fse3v(ji,jj,jk) ) &
  112. & + ( hdivb(ji,jj+1,jk) - hdivb(ji ,jj,jk) ) / e2v(ji,jj)
  113. END DO
  114. END DO
  115. ELSE ! z-coordinate - full step
  116. DO jj = 2, jpjm1
  117. DO ji = fs_2, fs_jpim1 ! vector opt.
  118. zlu(ji,jj,jk) = - ( rotb (ji ,jj,jk) - rotb (ji,jj-1,jk) ) / e2u(ji,jj) &
  119. & + ( hdivb(ji+1,jj,jk) - hdivb(ji,jj ,jk) ) / e1u(ji,jj)
  120. zlv(ji,jj,jk) = + ( rotb (ji,jj ,jk) - rotb (ji-1,jj,jk) ) / e1v(ji,jj) &
  121. & + ( hdivb(ji,jj+1,jk) - hdivb(ji ,jj,jk) ) / e2v(ji,jj)
  122. END DO
  123. END DO
  124. ENDIF
  125. END DO
  126. CALL lbc_lnk( zlu, 'U', -1. ) ; CALL lbc_lnk( zlv, 'V', -1. ) ! Boundary conditions
  127. IF( iom_use('dispkexyfo') ) THEN ! ocean kinetic energy dissipation per unit area
  128. ! ! due to xy friction (xy=lateral)
  129. ! see NEMO_book appendix C, §C.7.2 (N.B. here averaged at t-points)
  130. ! local dissipation of KE at t-point due to bilaplacian operator is given by :
  131. ! + ahmu mi( zlu**2 ) + mj( ahmv zlv**2 )
  132. ! Note that a sign + is used as in v3.6 ahm is negative for bilaplacian viscosity
  133. !
  134. ! NB: ahm is negative when bilaplacian is used
  135. ALLOCATE( z2d(jpi,jpj) )
  136. z2d(:,:) = 0._wp
  137. DO jk = 1, jpkm1
  138. DO jj = 2, jpjm1
  139. DO ji = 2, jpim1
  140. z2d(ji,jj) = z2d(ji,jj) &
  141. & + ( fsahmu(ji,jj,jk)*zlu(ji,jj,jk)**2 + fsahmu(ji-1,jj,jk)*zlu(ji-1,jj,jk)**2 &
  142. & + fsahmv(ji,jj,jk)*zlv(ji,jj,jk)**2 + fsahmv(ji,jj-1,jk)*zlv(ji,jj-1,jk)**2 ) * tmask(ji,jj,jk)
  143. END DO
  144. END DO
  145. END DO
  146. zzz = 0.5_wp * rau0
  147. z2d(:,:) = zzz * z2d(:,:)
  148. CALL lbc_lnk( z2d,'T', 1. )
  149. CALL iom_put( 'dispkexyfo', z2d )
  150. DEALLOCATE( z2d )
  151. ENDIF
  152. ! Third derivative
  153. ! ----------------
  154. !
  155. DO jk = 1, jpkm1
  156. !
  157. ! Multiply by the eddy viscosity coef. (at u- and v-points)
  158. zlu(:,:,jk) = zlu(:,:,jk) * fsahmu(:,:,jk)
  159. zlv(:,:,jk) = zlv(:,:,jk) * fsahmv(:,:,jk)
  160. !
  161. ! Contravariant "laplacian"
  162. zcu(:,:) = e1u(:,:) * zlu(:,:,jk)
  163. zcv(:,:) = e2v(:,:) * zlv(:,:,jk)
  164. ! Laplacian curl ( * e3f if s-coordinates or z-coordinate with partial steps)
  165. DO jj = 1, jpjm1
  166. DO ji = 1, fs_jpim1 ! vector opt.
  167. zuf(ji,jj,jk) = fmask(ji,jj,jk) * ( zcv(ji+1,jj ) - zcv(ji,jj) &
  168. & - zcu(ji ,jj+1) + zcu(ji,jj) ) &
  169. & * fse3f(ji,jj,jk) * r1_e12f(ji,jj)
  170. END DO
  171. END DO
  172. ! Laplacian Horizontal fluxes
  173. DO jj = 1, jpjm1
  174. DO ji = 1, fs_jpim1 ! vector opt.
  175. zlu(ji,jj,jk) = e2u(ji,jj) * fse3u(ji,jj,jk) * zlu(ji,jj,jk)
  176. zlv(ji,jj,jk) = e1v(ji,jj) * fse3v(ji,jj,jk) * zlv(ji,jj,jk)
  177. END DO
  178. END DO
  179. ! Laplacian divergence
  180. DO jj = 2, jpj
  181. DO ji = fs_2, jpi ! vector opt.
  182. zbt = e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk)
  183. zut(ji,jj,jk) = ( zlu(ji,jj,jk) - zlu(ji-1,jj ,jk) &
  184. & + zlv(ji,jj,jk) - zlv(ji ,jj-1,jk) ) / zbt
  185. END DO
  186. END DO
  187. END DO
  188. ! boundary conditions on the laplacian curl and div (zuf,zut)
  189. !!bug gm no need to do this 2 following lbc...
  190. CALL lbc_lnk( zuf, 'F', 1. )
  191. CALL lbc_lnk( zut, 'T', 1. )
  192. DO jk = 1, jpkm1 ! Bilaplacian
  193. DO jj = 2, jpjm1
  194. DO ji = fs_2, fs_jpim1 ! vector opt.
  195. ze2u = e2u(ji,jj) * fse3u(ji,jj,jk)
  196. ze2v = e1v(ji,jj) * fse3v(ji,jj,jk)
  197. ! horizontal biharmonic diffusive trends
  198. zua = - ( zuf(ji ,jj,jk) - zuf(ji,jj-1,jk) ) / ze2u &
  199. & + ( zut(ji+1,jj,jk) - zut(ji,jj ,jk) ) / e1u(ji,jj)
  200. zva = + ( zuf(ji,jj ,jk) - zuf(ji-1,jj,jk) ) / ze2v &
  201. & + ( zut(ji,jj+1,jk) - zut(ji ,jj,jk) ) / e2v(ji,jj)
  202. ! add it to the general momentum trends
  203. ua(ji,jj,jk) = ua(ji,jj,jk) + zua
  204. va(ji,jj,jk) = va(ji,jj,jk) + zva
  205. END DO
  206. END DO
  207. ! ! ===============
  208. END DO ! End of slab
  209. ! ! ===============
  210. CALL wrk_dealloc( jpi, jpj, zcu, zcv )
  211. CALL wrk_dealloc( jpi, jpj, jpk, zuf, zut, zlu, zlv )
  212. !
  213. IF( nn_timing == 1 ) CALL timing_stop('dyn_ldf_bilap')
  214. !
  215. END SUBROUTINE dyn_ldf_bilap
  216. !!======================================================================
  217. END MODULE dynldf_bilap