traldf.F90 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. MODULE traldf
  2. !!======================================================================
  3. !! *** MODULE traldf ***
  4. !! Ocean Active tracers : lateral diffusive trends
  5. !!=====================================================================
  6. !! History : 9.0 ! 2005-11 (G. Madec) Original code
  7. !! NEMO 3.0 ! 2008-01 (C. Ethe, G. Madec) merge TRC-TRA
  8. !!----------------------------------------------------------------------
  9. !!----------------------------------------------------------------------
  10. !! tra_ldf : update the tracer trend with the lateral diffusion
  11. !! tra_ldf_init : initialization, namelist read, and parameters control
  12. !! ldf_ano : compute lateral diffusion for constant T-S profiles
  13. !!----------------------------------------------------------------------
  14. USE oce ! ocean dynamics and tracers
  15. USE dom_oce ! ocean space and time domain
  16. USE phycst ! physical constants
  17. USE ldftra_oce ! ocean tracer lateral physics
  18. USE ldfslp ! ???
  19. USE traldf_bilapg ! lateral mixing (tra_ldf_bilapg routine)
  20. USE traldf_bilap ! lateral mixing (tra_ldf_bilap routine)
  21. USE traldf_iso ! lateral mixing (tra_ldf_iso routine)
  22. USE traldf_iso_grif ! lateral mixing (tra_ldf_iso_grif routine)
  23. USE traldf_lap ! lateral mixing (tra_ldf_lap routine)
  24. USE trd_oce ! trends: ocean variables
  25. USE trdtra ! trends manager: tracers
  26. !
  27. USE prtctl ! Print control
  28. USE in_out_manager ! I/O manager
  29. USE lib_mpp ! distribued memory computing library
  30. USE lbclnk ! ocean lateral boundary conditions (or mpp link)
  31. USE wrk_nemo ! Memory allocation
  32. USE timing ! Timing
  33. IMPLICIT NONE
  34. PRIVATE
  35. PUBLIC tra_ldf ! called by step.F90
  36. PUBLIC tra_ldf_init ! called by opa.F90
  37. !
  38. INTEGER :: nldf = 0 ! type of lateral diffusion used defined from ln_traldf_... namlist logicals)
  39. REAL, SAVE, ALLOCATABLE, DIMENSION(:,:,:) :: t0_ldf, s0_ldf !: lateral diffusion trends of T & S for a cst profile
  40. ! ! (key_traldf_ano only)
  41. !! * Substitutions
  42. # include "domzgr_substitute.h90"
  43. # include "vectopt_loop_substitute.h90"
  44. !!----------------------------------------------------------------------
  45. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  46. !! $Id: traldf.F90 4990 2014-12-15 16:42:49Z timgraham $
  47. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  48. !!----------------------------------------------------------------------
  49. CONTAINS
  50. SUBROUTINE tra_ldf( kt )
  51. !!----------------------------------------------------------------------
  52. !! *** ROUTINE tra_ldf ***
  53. !!
  54. !! ** Purpose : compute the lateral ocean tracer physics.
  55. !!----------------------------------------------------------------------
  56. INTEGER, INTENT( in ) :: kt ! ocean time-step index
  57. !!
  58. REAL(wp), POINTER, DIMENSION(:,:,:) :: ztrdt, ztrds
  59. !!----------------------------------------------------------------------
  60. !
  61. IF( nn_timing == 1 ) CALL timing_start('tra_ldf')
  62. !
  63. rldf = 1 ! For active tracers the
  64. r_fact_lap(:,:,:) = 1.0
  65. IF( l_trdtra ) THEN !* Save ta and sa trends
  66. CALL wrk_alloc( jpi, jpj, jpk, ztrdt, ztrds )
  67. ztrdt(:,:,:) = tsa(:,:,:,jp_tem)
  68. ztrds(:,:,:) = tsa(:,:,:,jp_sal)
  69. ENDIF
  70. SELECT CASE ( nldf ) ! compute lateral mixing trend and add it to the general trend
  71. CASE ( 0 ) ; CALL tra_ldf_lap ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi, &
  72. & tsb, tsa, jpts ) ! iso-level laplacian
  73. CASE ( 1 ) ! rotated laplacian
  74. IF( ln_traldf_grif ) THEN
  75. CALL tra_ldf_iso_grif( kt, nit000,'TRA', gtsu, gtsv, tsb, tsa, jpts, ahtb0 ) ! Griffies operator
  76. ELSE
  77. CALL tra_ldf_iso ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi, &
  78. & tsb, tsa, jpts, ahtb0 ) ! Madec operator
  79. ENDIF
  80. CASE ( 2 ) ; CALL tra_ldf_bilap ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi, &
  81. & tsb, tsa, jpts ) ! iso-level bilaplacian
  82. CASE ( 3 ) ; CALL tra_ldf_bilapg ( kt, nit000, 'TRA', tsb, tsa, jpts ) ! s-coord. geopot. bilap.
  83. !
  84. CASE ( -1 ) ! esopa: test all possibility with control print
  85. CALL tra_ldf_lap ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi, &
  86. & tsb, tsa, jpts )
  87. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf0 - Ta: ', mask1=tmask, &
  88. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  89. IF( ln_traldf_grif ) THEN
  90. CALL tra_ldf_iso_grif( kt, nit000, 'TRA', gtsu, gtsv, tsb, tsa, jpts, ahtb0 )
  91. ELSE
  92. CALL tra_ldf_iso ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi, &
  93. & tsb, tsa, jpts, ahtb0 )
  94. ENDIF
  95. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf1 - Ta: ', mask1=tmask, &
  96. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  97. CALL tra_ldf_bilap ( kt, nit000, 'TRA', gtsu, gtsv, gtui, gtvi, &
  98. & tsb, tsa, jpts )
  99. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf2 - Ta: ', mask1=tmask, &
  100. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  101. CALL tra_ldf_bilapg( kt, nit000, 'TRA', tsb, tsa, jpts )
  102. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf3 - Ta: ', mask1=tmask, &
  103. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  104. END SELECT
  105. #if defined key_traldf_ano
  106. tsa(:,:,:,jp_tem) = tsa(:,:,:,jp_tem) - t0_ldf(:,:,:) ! anomaly: substract the reference diffusivity
  107. tsa(:,:,:,jp_sal) = tsa(:,:,:,jp_sal) - s0_ldf(:,:,:)
  108. #endif
  109. IF( l_trdtra ) THEN ! save the horizontal diffusive trends for further diagnostics
  110. ztrdt(:,:,:) = tsa(:,:,:,jp_tem) - ztrdt(:,:,:)
  111. ztrds(:,:,:) = tsa(:,:,:,jp_sal) - ztrds(:,:,:)
  112. CALL trd_tra( kt, 'TRA', jp_tem, jptra_ldf, ztrdt )
  113. CALL trd_tra( kt, 'TRA', jp_sal, jptra_ldf, ztrds )
  114. CALL wrk_dealloc( jpi, jpj, jpk, ztrdt, ztrds )
  115. ENDIF
  116. ! ! print mean trends (used for debugging)
  117. IF(ln_ctl) CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' ldf - Ta: ', mask1=tmask, &
  118. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  119. !
  120. IF( nn_timing == 1 ) CALL timing_stop('tra_ldf')
  121. !
  122. END SUBROUTINE tra_ldf
  123. SUBROUTINE tra_ldf_init
  124. !!----------------------------------------------------------------------
  125. !! *** ROUTINE tra_ldf_init ***
  126. !!
  127. !! ** Purpose : Choice of the operator for the lateral tracer diffusion
  128. !!
  129. !! ** Method : set nldf from the namtra_ldf logicals
  130. !! nldf == -1 ESOPA test: ALL operators are used
  131. !! nldf == 0 laplacian operator
  132. !! nldf == 1 Rotated laplacian operator
  133. !! nldf == 2 bilaplacian operator
  134. !! nldf == 3 Rotated bilaplacian
  135. !!----------------------------------------------------------------------
  136. INTEGER :: ioptio, ierr ! temporary integers
  137. !!----------------------------------------------------------------------
  138. ! Define the lateral mixing oparator for tracers
  139. ! ===============================================
  140. IF(lwp) THEN ! Namelist print
  141. WRITE(numout,*)
  142. WRITE(numout,*) 'tra_ldf_init : lateral tracer diffusive operator'
  143. WRITE(numout,*) '~~~~~~~~~~~'
  144. WRITE(numout,*) ' Namelist namtra_ldf already read in ldftra module'
  145. WRITE(numout,*) ' see ldf_tra_init report for lateral mixing parameters'
  146. WRITE(numout,*)
  147. ENDIF
  148. ! ! control the input
  149. ioptio = 0
  150. IF( ln_traldf_lap ) ioptio = ioptio + 1
  151. IF( ln_traldf_bilap ) ioptio = ioptio + 1
  152. IF( ioptio > 1 ) CALL ctl_stop( ' use ONE or NONE of the 2 lap/bilap operator type on tracer' )
  153. IF( ioptio == 0 ) nldf = -2 ! No lateral diffusion
  154. ioptio = 0
  155. IF( ln_traldf_level ) ioptio = ioptio + 1
  156. IF( ln_traldf_hor ) ioptio = ioptio + 1
  157. IF( ln_traldf_iso ) ioptio = ioptio + 1
  158. IF( ioptio > 1 ) CALL ctl_stop( ' use only ONE direction (level/hor/iso)' )
  159. ! defined the type of lateral diffusion from ln_traldf_... logicals
  160. ! CAUTION : nldf = 1 is used in trazdf_imp, change it carefully
  161. ierr = 0
  162. IF( ln_traldf_lap ) THEN ! laplacian operator
  163. IF ( ln_zco ) THEN ! z-coordinate
  164. IF ( ln_traldf_level ) nldf = 0 ! iso-level (no rotation)
  165. IF ( ln_traldf_hor ) nldf = 0 ! horizontal (no rotation)
  166. IF ( ln_traldf_iso ) nldf = 1 ! isoneutral ( rotation)
  167. ENDIF
  168. IF ( ln_zps ) THEN ! zps-coordinate
  169. IF ( ln_traldf_level ) ierr = 1 ! iso-level not allowed
  170. IF ( ln_traldf_hor ) nldf = 0 ! horizontal (no rotation)
  171. IF ( ln_traldf_iso ) nldf = 1 ! isoneutral ( rotation)
  172. ENDIF
  173. IF ( ln_sco ) THEN ! s-coordinate
  174. IF ( ln_traldf_level ) nldf = 0 ! iso-level (no rotation)
  175. IF ( ln_traldf_hor ) nldf = 1 ! horizontal ( rotation)
  176. IF ( ln_traldf_iso ) nldf = 1 ! isoneutral ( rotation)
  177. ENDIF
  178. ENDIF
  179. IF( ln_traldf_bilap ) THEN ! bilaplacian operator
  180. IF ( ln_zco ) THEN ! z-coordinate
  181. IF ( ln_traldf_level ) nldf = 2 ! iso-level (no rotation)
  182. IF ( ln_traldf_hor ) nldf = 2 ! horizontal (no rotation)
  183. IF ( ln_traldf_iso ) ierr = 2 ! isoneutral ( rotation)
  184. ENDIF
  185. IF ( ln_zps ) THEN ! zps-coordinate
  186. IF ( ln_traldf_level ) ierr = 1 ! iso-level not allowed
  187. IF ( ln_traldf_hor ) nldf = 2 ! horizontal (no rotation)
  188. IF ( ln_traldf_iso ) ierr = 2 ! isoneutral ( rotation)
  189. ENDIF
  190. IF ( ln_sco ) THEN ! s-coordinate
  191. IF ( ln_traldf_level ) nldf = 2 ! iso-level (no rotation)
  192. IF ( ln_traldf_hor ) nldf = 3 ! horizontal ( rotation)
  193. IF ( ln_traldf_iso ) ierr = 2 ! isoneutral ( rotation)
  194. ENDIF
  195. ENDIF
  196. IF( nldf == 3 ) CALL ctl_warn( 'geopotential bilaplacian tracer diffusion in s-coords not thoroughly tested' )
  197. IF( ierr == 1 ) CALL ctl_stop( ' iso-level in z-coordinate - partial step, not allowed' )
  198. IF( ierr == 2 ) CALL ctl_stop( ' isoneutral bilaplacian operator does not exist' )
  199. IF( ln_traldf_hor .AND. ln_traldf_grif ) &
  200. & CALL ctl_stop( ' horizontal operator and Griffies triads not available; sitch to isoneutral operator' )
  201. IF( ln_traldf_grif .AND. ln_isfcav ) &
  202. CALL ctl_stop( ' ice shelf and traldf_grif not tested')
  203. IF( lk_traldf_eiv .AND. .NOT.ln_traldf_iso ) &
  204. CALL ctl_stop( ' eddy induced velocity on tracers', &
  205. & ' the eddy induced velocity on tracers requires isopycnal laplacian diffusion' )
  206. IF( nldf == 1 .OR. nldf == 3 ) THEN ! rotation
  207. IF( .NOT.lk_ldfslp ) CALL ctl_stop( ' the rotation of the diffusive tensor require key_ldfslp' )
  208. l_traldf_rot = .TRUE. ! needed for trazdf_imp
  209. ENDIF
  210. IF( lk_esopa ) THEN
  211. IF(lwp) WRITE(numout,*) ' esopa control: use all lateral physics options'
  212. nldf = -1
  213. ENDIF
  214. IF(lwp) THEN
  215. WRITE(numout,*)
  216. IF( nldf == -2 ) WRITE(numout,*) ' NO lateral diffusion'
  217. IF( nldf == -1 ) WRITE(numout,*) ' ESOPA test All scheme used'
  218. IF( nldf == 0 ) WRITE(numout,*) ' laplacian operator'
  219. IF( nldf == 1 ) WRITE(numout,*) ' Rotated laplacian operator'
  220. IF( nldf == 2 ) WRITE(numout,*) ' bilaplacian operator'
  221. IF( nldf == 3 ) WRITE(numout,*) ' Rotated bilaplacian'
  222. ENDIF
  223. ! Reference T & S diffusivity (if necessary)
  224. ! ===========================
  225. CALL ldf_ano
  226. !
  227. END SUBROUTINE tra_ldf_init
  228. #if defined key_traldf_ano
  229. !!----------------------------------------------------------------------
  230. !! 'key_traldf_ano' T & S lateral diffusion on anomalies
  231. !!----------------------------------------------------------------------
  232. SUBROUTINE ldf_ano
  233. !!----------------------------------------------------------------------
  234. !! *** ROUTINE ldf_ano ***
  235. !!
  236. !! ** Purpose : initializations of
  237. !!----------------------------------------------------------------------
  238. !
  239. USE zdf_oce ! vertical mixing
  240. USE trazdf ! vertical mixing: double diffusion
  241. USE zdfddm ! vertical mixing: double diffusion
  242. !
  243. INTEGER :: jk ! Dummy loop indice
  244. INTEGER :: ierr ! local integer
  245. LOGICAL :: llsave ! local logical
  246. REAL(wp) :: zt0, zs0, z12 ! local scalar
  247. REAL(wp), POINTER, DIMENSION(:,:,:) :: zt_ref, zs_ref, ztb, zsb, zavt
  248. !!----------------------------------------------------------------------
  249. !
  250. IF( nn_timing == 1 ) CALL timing_start('ldf_ano')
  251. !
  252. CALL wrk_alloc( jpi, jpj, jpk, zt_ref, zs_ref, ztb, zsb, zavt )
  253. !
  254. IF(lwp) THEN
  255. WRITE(numout,*)
  256. WRITE(numout,*) 'tra:ldf_ano : lateral diffusion acting on anomalies'
  257. WRITE(numout,*) '~~~~~~~~~~~'
  258. ENDIF
  259. ! ! allocate trabbl arrays
  260. ALLOCATE( t0_ldf(jpi,jpj,jpk) , s0_ldf(jpi,jpj,jpk) , STAT=ierr )
  261. IF( lk_mpp ) CALL mpp_sum( ierr )
  262. IF( ierr /= 0 ) CALL ctl_stop( 'STOP', 'ldf_ano: unable to allocate arrays' )
  263. ! defined the T & S reference profiles
  264. ! ------------------------------------
  265. zt0 =10.e0 ! homogeneous ocean
  266. zs0 =35.e0
  267. zt_ref(:,:,:) = 10.0 * tmask(:,:,:)
  268. zs_ref(:,:,:) = 35.0 * tmask(:,:,:)
  269. IF(lwp) WRITE(numout,*) ' homogeneous ocean T = ', zt0, ' S = ',zs0
  270. ! Initialisation of gtui/gtvi in case of no cavity
  271. IF ( .NOT. ln_isfcav ) THEN
  272. gtui(:,:,:) = 0.0_wp
  273. gtvi(:,:,:) = 0.0_wp
  274. END IF
  275. ! ! T & S profile (to be coded +namelist parameter
  276. ! prepare the ldf computation
  277. ! ---------------------------
  278. llsave = l_trdtra
  279. l_trdtra = .false. ! desactivate trend computation
  280. t0_ldf(:,:,:) = 0.e0
  281. s0_ldf(:,:,:) = 0.e0
  282. ztb (:,:,:) = tsb (:,:,:,jp_tem)
  283. zsb (:,:,:) = tsb (:,:,:,jp_sal)
  284. ua (:,:,:) = tsa (:,:,:,jp_tem)
  285. va (:,:,:) = tsa (:,:,:,jp_sal)
  286. zavt (:,:,:) = avt(:,:,:)
  287. IF( lk_zdfddm ) THEN CALL ctl_stop( ' key_traldf_ano with key_zdfddm not implemented' )
  288. ! set tb, sb to reference values and avr to zero
  289. tsb (:,:,:,jp_tem) = zt_ref(:,:,:)
  290. tsb (:,:,:,jp_sal) = zs_ref(:,:,:)
  291. tsa (:,:,:,jp_tem) = 0.e0
  292. tsa (:,:,:,jp_sal) = 0.e0
  293. avt(:,:,:) = 0.e0
  294. ! Compute the ldf trends
  295. ! ----------------------
  296. CALL tra_ldf( nit000 + 1 ) ! horizontal components (+1: no more init)
  297. CALL tra_zdf( nit000 ) ! vertical component (if necessary nit000 to performed the init)
  298. ! finalise the computation and recover all arrays
  299. ! -----------------------------------------------
  300. l_trdtra = llsave
  301. z12 = 2.e0
  302. IF( neuler == 1) z12 = 1.e0
  303. IF( ln_zdfexp ) THEN ! ta,sa are the trends
  304. t0_ldf(:,:,:) = tsa(:,:,:,jp_tem)
  305. s0_ldf(:,:,:) = tsa(:,:,:,jp_sal)
  306. ELSE
  307. DO jk = 1, jpkm1
  308. t0_ldf(:,:,jk) = ( tsa(:,:,jk,jp_tem) - tsb(:,:,jk,jp_tem) ) / ( z12 *rdttra(jk) )
  309. s0_ldf(:,:,jk) = ( tsa(:,:,jk,jp_sal) - tsb(:,:,jk,jp_sal) ) / ( z12 *rdttra(jk) )
  310. END DO
  311. ENDIF
  312. tsb(:,:,:,jp_tem) = ztb (:,:,:)
  313. tsb(:,:,:,jp_sal) = zsb (:,:,:)
  314. tsa(:,:,:,jp_tem) = ua (:,:,:)
  315. tsa(:,:,:,jp_sal) = va (:,:,:)
  316. avt(:,:,:) = zavt(:,:,:)
  317. !
  318. CALL wrk_dealloc( jpi, jpj, jpk, zt_ref, zs_ref, ztb, zsb, zavt )
  319. !
  320. IF( nn_timing == 1 ) CALL timing_stop('ldf_ano')
  321. !
  322. END SUBROUTINE ldf_ano
  323. #else
  324. !!----------------------------------------------------------------------
  325. !! default option : Dummy code NO T & S background profiles
  326. !!----------------------------------------------------------------------
  327. SUBROUTINE ldf_ano
  328. IF(lwp) THEN
  329. WRITE(numout,*)
  330. WRITE(numout,*) 'tra:ldf_ano : lateral diffusion acting on the full fields'
  331. WRITE(numout,*) '~~~~~~~~~~~'
  332. ENDIF
  333. END SUBROUTINE ldf_ano
  334. #endif
  335. !!======================================================================
  336. END MODULE traldf