ldfdyn_smag.F90 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. MODULE ldfdyn_smag
  2. !!======================================================================
  3. !! *** MODULE ldftrasmag ***
  4. !! Ocean physics: variable eddy induced velocity coefficients
  5. !!======================================================================
  6. #if defined key_dynldf_smag && defined key_dynldf_c3d
  7. !!----------------------------------------------------------------------
  8. !! 'key_dynldf_smag' and smagorinsky diffusivity
  9. !! 'key_dynldf_c3d' 3D tracer lateral mixing coef.
  10. !!----------------------------------------------------------------------
  11. !! ldf_eiv : compute the eddy induced velocity coefficients
  12. !!----------------------------------------------------------------------
  13. !! * Modules used
  14. USE oce ! ocean dynamics and tracers
  15. USE dom_oce ! ocean space and time domain
  16. USE sbc_oce ! surface boundary condition: ocean
  17. USE sbcrnf ! river runoffs
  18. USE ldfdyn_oce ! ocean tracer lateral physics
  19. USE phycst ! physical constants
  20. USE ldfslp ! iso-neutral slopes
  21. USE in_out_manager ! I/O manager
  22. USE lbclnk ! ocean lateral boundary conditions (or mpp link)
  23. USE prtctl ! Print control
  24. USE iom
  25. USE wrk_nemo
  26. IMPLICIT NONE
  27. PRIVATE
  28. !! * Routine accessibility
  29. PUBLIC ldf_dyn_smag ! routine called by step.F90
  30. !!----------------------------------------------------------------------
  31. !! OPA 9.0 , LOCEAN-IPSL (2005)
  32. !! $Id: ldfdyn_smag.F90 2355 2015-05-20 07:11:50Z ufla $
  33. !! This software is governed by the CeCILL licence see modipsl/doc/NEMO_CeCILL.txt
  34. !!----------------------------------------------------------------------
  35. !! * Substitutions
  36. # include "domzgr_substitute.h90"
  37. # include "vectopt_loop_substitute.h90"
  38. !!----------------------------------------------------------------------
  39. CONTAINS
  40. !!----------------------------------------------------------------------
  41. !! *** ldfdyn_smag.F90 ***
  42. !!----------------------------------------------------------------------
  43. !!----------------------------------------------------------------------
  44. !! OPA 9.0 , LOCEAN-IPSL (2005)
  45. !! $Id: ldfdyn_smag.F90 2355 2015-05-20 07:11:50Z ufla $
  46. !! This software is governed by the CeCILL licence see modipsl/doc/NEMO_CeCILL.txt
  47. !!----------------------------------------------------------------------
  48. !!----------------------------------------------------------------------
  49. !! 'key_dynldf_smag' 3D lateral eddy viscosity coefficients
  50. !!----------------------------------------------------------------------
  51. SUBROUTINE ldf_dyn_smag( kt )
  52. !!----------------------------------------------------------------------
  53. !! *** ROUTINE ldf_dyn_smag ***
  54. !!
  55. !! ** Purpose : initializations of the horizontal ocean physics
  56. !!
  57. !! ** Method : 3D eddy viscosity coef.
  58. !! M.Griffies, R.Hallberg AMS, 2000
  59. !! for laplacian:
  60. !! Asmag=(C/pi)^2*dx*dy sqrt(D^2), C=3-4
  61. !! for bilaplacian:
  62. !! Bsmag=Asmag*dx*dy/8
  63. !! D^2=(du/dx-dv/dy)^2+(dv/dx+du/dy)^2 for Cartesian coordinates
  64. !! in general case du/dx ==> e2 d(u/e2)/dx; du/dy ==> e1 d(u/e1)/dy;
  65. !! dv/dx ==> e2 d(v/e2)/dx; dv/dy ==> e1 d(v/e1)/dy
  66. !!
  67. !! laplacian operator : ahm1, ahm2 defined at T- and F-points
  68. !! ahm3, ahm4 never used
  69. !! bilaplacian operator : ahm1, ahm2 never used
  70. !! : ahm3, ahm4 defined at U- and V-points
  71. !! explanation of the default is missingi
  72. !! last modified : Maria Luneva, September 2011
  73. !!----------------------------------------------------------------------
  74. !! * Modules used
  75. !! ahm0 here is a background viscosity
  76. !! * Arguments
  77. !! * local variables
  78. INTEGER :: kt ! timestep
  79. INTEGER :: ji, jj, jk ! dummy loop indices
  80. REAL (wp):: zdeltat,zdeltaf,zdeltau,zdeltav ! temporary scalars
  81. REAL (wp), POINTER, DIMENSION (:,:) :: zux, zuy , zvx ,zvy, zue1, zue2, zve1, zve2
  82. REAL (wp):: zcmsmag_1, zcmsmag_2 , zcmsh
  83. !!----------------------------------------------------------------------
  84. CALL wrk_alloc( jpi,jpj,zux,zuy,zvx,zvy )
  85. CALL wrk_alloc( jpi,jpj,zue1,zue2,zve1,zve2 )
  86. IF( kt == nit000 ) THEN
  87. IF(lwp) WRITE(numout,*)
  88. IF(lwp) WRITE(numout,*) 'ldf_dyn_smag : 3D lateral eddy viscosity coefficient'
  89. IF(lwp) WRITE(numout,*) '~~~~~~~~~~~'
  90. ENDIF
  91. zcmsmag_1 = rn_cmsmag_1
  92. zcmsmag_2 = rn_cmsmag_2
  93. zcmsh = rn_cmsh
  94. ! Set ahm1 and ahm2 ( T- and F- points) (used for laplacian operators
  95. ! ================= whatever its orientation is)
  96. IF( ln_dynldf_lap ) THEN
  97. ! define ahm1 and ahm2 at the right grid point position
  98. ! (USER: modify ahm1 and ahm2 following your desiderata)
  99. DO jk=1,jpk
  100. zue2(:,:)=un(:,:,jk)/e2u(:,:)
  101. zve1(:,:)=vn(:,:,jk)/e1v(:,:)
  102. zue1(:,:)=un(:,:,jk)/e1u(:,:)
  103. zve2(:,:)=vn(:,:,jk)/e2v(:,:)
  104. DO jj=2,jpj
  105. DO ji=2,jpi
  106. zux(ji,jj)=(zue2(ji,jj)-zue2(ji-1,jj))/e1t(ji,jj)*e2t(ji,jj)*tmask(ji,jj,jk) * zcmsh
  107. zvy(ji,jj)=(zve1(ji,jj)-zve1(ji,jj-1))/e2t(ji,jj)*e1t(ji,jj)*tmask(ji,jj,jk) * zcmsh
  108. ENDDO
  109. ENDDO
  110. DO jj=1,jpjm1
  111. DO ji=1,jpim1
  112. zuy(ji,jj)=(zue1(ji,jj+1)-zue1(ji,jj))/e2f(ji,jj)*e1f(ji,jj)*fmask(ji,jj,jk)
  113. zvx(ji,jj)=(zve2(ji+1,jj)-zve2(ji,jj))/e1f(ji,jj)*e2f(ji,jj)*fmask(ji,jj,jk)
  114. ENDDO
  115. ENDDO
  116. DO jj=2,jpjm1
  117. DO ji=2,jpim1
  118. zdeltat=2._wp /(e1t(ji,jj)**(-2)+e2t(ji,jj)**(-2))
  119. zdeltaf=2._wp /(e1f(ji,jj)**(-2)+e2f(ji,jj)**(-2))
  120. ahm1(ji,jj,jk)=(zcmsmag_1/rpi)**2*zdeltat* &
  121. sqrt( (zux(ji,jj)-zvy(ji,jj))**2+ &
  122. 0.0625_wp*(zuy(ji,jj)+zuy(ji,jj-1)+zuy(ji-1,jj)+zuy(ji-1,jj-1)+ &
  123. zvx(ji,jj)+zvx(ji,jj-1)+zvx(ji-1,jj)+zvx(ji-1,jj-1))**2)
  124. ahm2(ji,jj,jk)=(zcmsmag_1/rpi)**2*zdeltaf* &
  125. sqrt( (zuy(ji,jj)+zvx(ji,jj))**2+ &
  126. 0.0625_wp*(zux(ji,jj)+zux(ji,jj+1)+zux(ji+1,jj)+zux(ji+1,jj+1)- &
  127. zvy(ji,jj)-zvy(ji,jj+1)-zvy(ji+1,jj)-zvy(ji+1,jj+1))**2)
  128. ahm1(ji,jj,jk)=MAX(ahm1(ji,jj,jk),rn_ahm_0_lap)
  129. ahm2(ji,jj,jk)=MAX(ahm2(ji,jj,jk),rn_ahm_0_lap)
  130. ! stability criteria or upper limit set from namelist
  131. ahm1(ji,jj,jk)=MIN(ahm1(ji,jj,jk),zdeltat / (16_wp*rdt),rn_ahm_m_lap)
  132. ahm2(ji,jj,jk)=MIN(ahm2(ji,jj,jk),zdeltaf / (16_wp*rdt),rn_ahm_m_lap)
  133. ENDDO
  134. ENDDO
  135. ENDDO ! jpk
  136. ahm1(:,:,jpk) = ahm1(:,:,jpkm1)
  137. ahm2(:,:,jpk) = ahm2(:,:,jpkm1)
  138. IF(lwp.and.kt==nit000) WRITE(numout,'(36x," ahm ", 7x)')
  139. DO jk = 1, jpk
  140. IF(lwp.and.kt==nit000) WRITE(numout,'(30x,E10.2,8x,i3)') ahm1(jpi/2,jpj/2,jk), jk
  141. END DO
  142. CALL lbc_lnk( ahm1, 'T', 1. ) ! Lateral boundary conditions on ( ahtt )
  143. CALL lbc_lnk( ahm2, 'F', 1. ) ! Lateral boundary conditions on ( ahtt )
  144. ENDIF ! ln_dynldf_lap
  145. ! ahm3 and ahm4 at U- and V-points (used for bilaplacian operator
  146. ! ================================ whatever its orientation is)
  147. ! Here: ahm is proportional to the cube of the maximum of the grid spacing
  148. ! in the to horizontal direction
  149. IF( ln_dynldf_bilap ) THEN
  150. DO jk=1,jpk
  151. zue2(:,:) = un(:,:,jk)/e2u(:,:)
  152. zve1(:,:) = vn(:,:,jk)/e1v(:,:)
  153. zue1(:,:) = un(:,:,jk)/e1u(:,:)
  154. zve2(:,:) = vn(:,:,jk)/e2v(:,:)
  155. DO jj=2,jpj
  156. DO ji=2,jpi
  157. zux(ji,jj) = (zue2(ji,jj)-zue2(ji-1,jj))/e1t(ji,jj)*e2t(ji,jj)*tmask(ji,jj,jk)
  158. zvy(ji,jj) = (zve1(ji,jj)-zve1(ji,jj-1))/e2t(ji,jj)*e1t(ji,jj)*tmask(ji,jj,jk)
  159. ENDDO
  160. ENDDO
  161. DO jj=1,jpjm1
  162. DO ji=1,jpim1
  163. zuy(ji,jj) = (zue1(ji,jj+1)-zue1(ji,jj))/e2f(ji,jj)*e1f(ji,jj)*fmask(ji,jj,jk)
  164. zvx(ji,jj) = (zve2(ji+1,jj)-zve2(ji,jj))/e1f(ji,jj)*e2f(ji,jj)*fmask(ji,jj,jk)
  165. ENDDO
  166. ENDDO
  167. DO jj=2,jpjm1
  168. DO ji=2,jpim1
  169. zdeltau = 2._wp/(e1u(ji,jj)**(-2)+e2u(ji,jj)**(-2))
  170. zdeltav = 2._wp/(e1v(ji,jj)**(-2)+e2v(ji,jj)**(-2))
  171. ahm3(ji,jj,jk) = -(zcmsmag_2/rpi)**2/8.0_wp*zdeltau**2* &
  172. sqrt(0.25_wp*(zux(ji,jj)+zux(ji+1,jj)-zvy(ji,jj)-zvy(ji+1,jj))**2+ &
  173. 0.25_wp*(zuy(ji,jj)+zuy(ji,jj-1)+zvx(ji,jj)+zvx(ji,jj-1))**2)
  174. ahm4(ji,jj,jk) = -(zcmsmag_2/rpi)**2/8.0_wp*zdeltav**2* &
  175. sqrt(0.25_wp*(zux(ji,jj)+zux(ji,jj+1)-zvy(ji,jj)-zvy(ji,jj+1))**2+ &
  176. 0.25_wp*(zuy(ji,jj)+zuy(ji-1,jj)+zvx(ji-1,jj)+zvx(ji,jj))**2)
  177. ahm3(ji,jj,jk) = MIN (rn_ahm_0_blp , ahm3(ji,jj,jk) )
  178. ahm4(ji,jj,jk) = MIN (rn_ahm_0_blp , ahm4(ji,jj,jk) )
  179. ! stability criteria or upper limit set in namelist
  180. ahm3(ji,jj,jk) = MAX( ahm3(ji,jj,jk),-zdeltau**2/( 128._wp*rdt ),rn_ahm_m_blp )
  181. ahm4(ji,jj,jk) = MAX( ahm4(ji,jj,jk),-zdeltav**2/( 128._wp*rdt ),rn_ahm_m_blp )
  182. ENDDO
  183. ENDDO
  184. ENDDO
  185. ahm3(:,:,jpk) = ahm3(:,:,jpkm1)
  186. ahm4(:,:,jpk) = ahm4(:,:,jpkm1)
  187. DO jk = 1, jpk
  188. IF( kt == nit000 ) THEN
  189. IF(lwp) WRITE(numout,'(30x,E10.2,8x,i3)') ahm3(jpi/2,jpj/2,jk), jk
  190. ENDIF
  191. END DO
  192. CALL lbc_lnk( ahm3, 'U', 1. ) ! Lateral boundary conditions
  193. CALL lbc_lnk( ahm4, 'V', 1. )
  194. ENDIF
  195. CALL wrk_dealloc( jpi,jpj,zux,zuy,zvx,zvy )
  196. CALL wrk_dealloc( jpi,jpj,zue1,zue2,zve1,zve2 )
  197. ! zumax = MAXVAL( ABS( ahm3(:,:,:) ) ) ! slower than the following loop on NEC SX5
  198. zdeltat = 0._wp
  199. If(ln_dynldf_lap)THEN
  200. DO jk = 1, jpk
  201. DO jj = 1, jpj
  202. DO ji = 1, jpi
  203. zdeltat = MAX(zdeltat,ABS(ahm1(ji,jj,jk)),ABS(ahm2(ji,jj,jk)) )
  204. END DO
  205. END DO
  206. END DO
  207. IF( lk_mpp ) CALL mpp_max( zdeltat ) ! max over the global domain
  208. !
  209. IF( MOD( kt, nwrite ) == 1 .AND. lwp ) WRITE(numout,*) ' ==>> time-step= ',kt,'dynlap: abs(ahm) max: ', zdeltat
  210. ENDIF
  211. If(ln_dynldf_bilap)THEN
  212. zdeltat = 0._wp
  213. DO jk = 1, jpk
  214. DO jj = 1, jpj
  215. DO ji = 1, jpi
  216. zdeltat = MAX(zdeltat,ABS(ahm3(ji,jj,jk)),ABS(ahm3(ji,jj,jk)) )
  217. END DO
  218. END DO
  219. END DO
  220. IF( lk_mpp ) CALL mpp_max( zdeltat ) ! max over the global domain
  221. !
  222. IF( MOD( kt, nwrite ) == 1 .AND. lwp ) WRITE(numout,*) ' ==>> time-step= ',kt,'dyn_bilap abs(ahm) max: ', zdeltat
  223. !
  224. ENDIF
  225. !
  226. END SUBROUTINE ldf_dyn_smag
  227. #else
  228. !!----------------------------------------------------------------------
  229. !! Default option Dummy module
  230. !!----------------------------------------------------------------------
  231. CONTAINS
  232. SUBROUTINE ldf_dyn_smag( kt ) ! Empty routine
  233. WRITE(*,*) 'ldf_dyn_smag: You should not have seen this print! error? check keys ldf:c3d+smag', kt
  234. END SUBROUTINE ldf_dyn_smag
  235. #endif
  236. END MODULE ldfdyn_smag