trcldf.F90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. MODULE trcldf
  2. !!======================================================================
  3. !! *** MODULE trcldf ***
  4. !! Ocean Passive 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. #if defined key_top
  10. !!----------------------------------------------------------------------
  11. !! 'key_top' TOP models
  12. !!----------------------------------------------------------------------
  13. !!----------------------------------------------------------------------
  14. !! trc_ldf : update the tracer trend with the lateral diffusion
  15. !! ldf_ctl : initialization, namelist read, and parameters control
  16. !!----------------------------------------------------------------------
  17. USE oce_trc ! ocean dynamics and active tracers
  18. USE trc ! ocean passive tracers variables
  19. USE trcnam_trp ! passive tracers transport namelist variables
  20. USE ldftra_oce ! lateral diffusion coefficient on tracers
  21. USE ldfslp ! ???
  22. USE traldf_bilapg ! lateral mixing (tra_ldf_bilapg routine)
  23. USE traldf_bilap ! lateral mixing (tra_ldf_bilap routine)
  24. USE traldf_iso ! lateral mixing (tra_ldf_iso routine)
  25. USE traldf_iso_grif ! lateral mixing (tra_ldf_iso_grif routine)
  26. USE traldf_lap ! lateral mixing (tra_ldf_lap routine)
  27. USE trd_oce
  28. USE trdtra
  29. USE prtctl_trc ! Print control
  30. IMPLICIT NONE
  31. PRIVATE
  32. PUBLIC trc_ldf ! called by step.F90
  33. ! !!: ** lateral mixing namelist (nam_trcldf) **
  34. REAL(wp) :: rldf_rat ! ratio between active and passive tracers diffusive coefficient
  35. INTEGER :: nldf = 0 ! type of lateral diffusion used defined from ln_trcldf_... namlist logicals)
  36. !! * Substitutions
  37. # include "domzgr_substitute.h90"
  38. # include "vectopt_loop_substitute.h90"
  39. !!----------------------------------------------------------------------
  40. !! NEMO/TOP 3.3 , NEMO Consortium (2010)
  41. !! $Id: trcldf.F90 4990 2014-12-15 16:42:49Z timgraham $
  42. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  43. !!----------------------------------------------------------------------
  44. CONTAINS
  45. SUBROUTINE trc_ldf( kt )
  46. !!----------------------------------------------------------------------
  47. !! *** ROUTINE tra_ldf ***
  48. !!
  49. !! ** Purpose : compute the lateral ocean tracer physics.
  50. !!
  51. !!----------------------------------------------------------------------
  52. INTEGER, INTENT( in ) :: kt ! ocean time-step index
  53. !!
  54. INTEGER :: ji, jj, jk, jn
  55. REAL(wp) :: zdep
  56. CHARACTER (len=22) :: charout
  57. REAL(wp), POINTER, DIMENSION(:,:,:,:) :: ztrtrd
  58. !!----------------------------------------------------------------------
  59. !
  60. IF( nn_timing == 1 ) CALL timing_start('trc_ldf')
  61. !
  62. IF( kt == nittrc000 ) CALL ldf_ctl ! initialisation & control of options
  63. rldf = rldf_rat
  64. !
  65. r_fact_lap(:,:,:) = 1.
  66. DO jk= 1, jpk
  67. DO jj = 1, jpj
  68. DO ji = 1, jpi
  69. IF( fsdept(ji,jj,jk) > 200. .AND. gphit(ji,jj) < 5. .AND. gphit(ji,jj) > -5. ) THEN
  70. zdep = MAX( fsdept(ji,jj,jk) - 1000., 0. ) / 1000.
  71. r_fact_lap(ji,jj,jk) = MAX( 1., rn_fact_lap * EXP( -zdep ) )
  72. ENDIF
  73. END DO
  74. END DO
  75. END DO
  76. !
  77. IF( l_trdtrc ) THEN
  78. CALL wrk_alloc( jpi, jpj, jpk, jptra, ztrtrd )
  79. ztrtrd(:,:,:,:) = tra(:,:,:,:)
  80. ENDIF
  81. SELECT CASE ( nldf ) ! compute lateral mixing trend and add it to the general trend
  82. CASE ( 0 ) ; CALL tra_ldf_lap ( kt, nittrc000, 'TRC', gtru, gtrv, gtrui, gtrvi, trb, tra, jptra ) ! iso-level laplacian
  83. CASE ( 1 ) ! rotated laplacian
  84. IF( ln_traldf_grif ) THEN
  85. CALL tra_ldf_iso_grif( kt, nittrc000, 'TRC', gtru, gtrv, trb, tra, jptra, rn_ahtb_0 )
  86. ELSE
  87. CALL tra_ldf_iso ( kt, nittrc000, 'TRC', gtru, gtrv, gtrui, gtrvi, trb, tra, jptra, rn_ahtb_0 )
  88. ENDIF
  89. CASE ( 2 ) ; CALL tra_ldf_bilap ( kt, nittrc000, 'TRC', gtru, gtrv, gtrui, gtrvi, trb, tra, jptra ) ! iso-level bilaplacian
  90. CASE ( 3 ) ; CALL tra_ldf_bilapg( kt, nittrc000, 'TRC', trb, tra, jptra ) ! s-coord. horizontal bilaplacian
  91. !
  92. CASE ( -1 ) ! esopa: test all possibility with control print
  93. CALL tra_ldf_lap ( kt, nittrc000, 'TRC', gtru, gtrv, gtrui, gtrvi, trb, tra, jptra )
  94. WRITE(charout, FMT="('ldf0 ')") ; CALL prt_ctl_trc_info(charout)
  95. CALL prt_ctl_trc( tab4d=tra, mask=tmask, clinfo=ctrcnm, clinfo2='trd' )
  96. IF( ln_traldf_grif ) THEN
  97. CALL tra_ldf_iso_grif( kt, nittrc000, 'TRC', gtru, gtrv, trb, tra, jptra, rn_ahtb_0 )
  98. ELSE
  99. CALL tra_ldf_iso ( kt, nittrc000, 'TRC', gtru, gtrv, gtrui, gtrvi, trb, tra, jptra, rn_ahtb_0 )
  100. ENDIF
  101. WRITE(charout, FMT="('ldf1 ')") ; CALL prt_ctl_trc_info(charout)
  102. CALL prt_ctl_trc( tab4d=tra, mask=tmask, clinfo=ctrcnm, clinfo2='trd' )
  103. CALL tra_ldf_bilap ( kt, nittrc000, 'TRC', gtru, gtrv, gtrui, gtrvi, trb, tra, jptra )
  104. WRITE(charout, FMT="('ldf2 ')") ; CALL prt_ctl_trc_info(charout)
  105. CALL prt_ctl_trc( tab4d=tra, mask=tmask, clinfo=ctrcnm, clinfo2='trd' )
  106. CALL tra_ldf_bilapg( kt, nittrc000, 'TRC', trb, tra, jptra )
  107. WRITE(charout, FMT="('ldf3 ')") ; CALL prt_ctl_trc_info(charout)
  108. CALL prt_ctl_trc( tab4d=tra, mask=tmask, clinfo=ctrcnm, clinfo2='trd' )
  109. END SELECT
  110. !
  111. IF( l_trdtrc ) THEN ! save the horizontal diffusive trends for further diagnostics
  112. DO jn = 1, jptra
  113. ztrtrd(:,:,:,jn) = tra(:,:,:,jn) - ztrtrd(:,:,:,jn)
  114. CALL trd_tra( kt, 'TRC', jn, jptra_ldf, ztrtrd(:,:,:,jn) )
  115. END DO
  116. CALL wrk_dealloc( jpi, jpj, jpk, jptra, ztrtrd )
  117. ENDIF
  118. ! ! print mean trends (used for debugging)
  119. IF( ln_ctl ) THEN
  120. WRITE(charout, FMT="('ldf ')") ; CALL prt_ctl_trc_info(charout)
  121. CALL prt_ctl_trc( tab4d=tra, mask=tmask, clinfo=ctrcnm, clinfo2='trd' )
  122. ENDIF
  123. !
  124. IF( nn_timing == 1 ) CALL timing_stop('trc_ldf')
  125. !
  126. END SUBROUTINE trc_ldf
  127. SUBROUTINE ldf_ctl
  128. !!----------------------------------------------------------------------
  129. !! *** ROUTINE ldf_ctl ***
  130. !!
  131. !! ** Purpose : Choice of the operator for the lateral tracer diffusion
  132. !!
  133. !! ** Method : set nldf from the namtra_ldf logicals
  134. !! nldf == -2 No lateral diffusion
  135. !! nldf == -1 ESOPA test: ALL operators are used
  136. !! nldf == 0 laplacian operator
  137. !! nldf == 1 Rotated laplacian operator
  138. !! nldf == 2 bilaplacian operator
  139. !! nldf == 3 Rotated bilaplacian
  140. !!----------------------------------------------------------------------
  141. INTEGER :: ioptio, ierr ! temporary integers
  142. !!----------------------------------------------------------------------
  143. IF (ABS(rn_aht_0) < 2._wp*TINY(1.e0)) THEN
  144. IF (ABS(rn_ahtrc_0) < 2._wp*TINY(1.e0)) THEN
  145. rldf_rat = 1.0_wp
  146. ELSE
  147. CALL ctl_stop( 'STOP', 'ldf_ctl : cannot define rldf_rat, rn_aht_0==0, rn_ahtrc_0 /=0' )
  148. END IF
  149. ELSE
  150. rldf_rat = rn_ahtrc_0 / rn_aht_0
  151. END IF
  152. ! Define the lateral mixing oparator for tracers
  153. ! ===============================================
  154. ! ! control the input
  155. ioptio = 0
  156. IF( ln_trcldf_lap ) ioptio = ioptio + 1
  157. IF( ln_trcldf_bilap ) ioptio = ioptio + 1
  158. IF( ioptio > 1 ) CALL ctl_stop( ' use ONE or NONE of the 2 lap/bilap operator type on tracer' )
  159. IF( ioptio == 0 ) nldf = -2 ! No lateral diffusion
  160. ioptio = 0
  161. IF( ln_trcldf_level ) ioptio = ioptio + 1
  162. IF( ln_trcldf_hor ) ioptio = ioptio + 1
  163. IF( ln_trcldf_iso ) ioptio = ioptio + 1
  164. IF( ioptio /= 1 ) CALL ctl_stop( ' use only ONE direction (level/hor/iso)' )
  165. ! defined the type of lateral diffusion from ln_trcldf_... logicals
  166. ! CAUTION : nldf = 1 is used in trazdf_imp, change it carefully
  167. ierr = 0
  168. IF( ln_trcldf_lap ) THEN ! laplacian operator
  169. IF ( ln_zco ) THEN ! z-coordinate
  170. IF ( ln_trcldf_level ) nldf = 0 ! iso-level (no rotation)
  171. IF ( ln_trcldf_hor ) nldf = 0 ! horizontal (no rotation)
  172. IF ( ln_trcldf_iso ) nldf = 1 ! isoneutral ( rotation)
  173. ENDIF
  174. IF ( ln_zps ) THEN ! z-coordinate
  175. IF ( ln_trcldf_level ) ierr = 1 ! iso-level not allowed
  176. IF ( ln_trcldf_hor ) nldf = 0 ! horizontal (no rotation)
  177. IF ( ln_trcldf_iso ) nldf = 1 ! isoneutral ( rotation)
  178. ENDIF
  179. IF ( ln_sco ) THEN ! z-coordinate
  180. IF ( ln_trcldf_level ) nldf = 0 ! iso-level (no rotation)
  181. IF ( ln_trcldf_hor ) nldf = 1 ! horizontal ( rotation)
  182. IF ( ln_trcldf_iso ) nldf = 1 ! isoneutral ( rotation)
  183. ENDIF
  184. ENDIF
  185. IF( ln_trcldf_bilap ) THEN ! bilaplacian operator
  186. IF ( ln_zco ) THEN ! z-coordinate
  187. IF ( ln_trcldf_level ) nldf = 2 ! iso-level (no rotation)
  188. IF ( ln_trcldf_hor ) nldf = 2 ! horizontal (no rotation)
  189. IF ( ln_trcldf_iso ) ierr = 2 ! isoneutral ( rotation)
  190. ENDIF
  191. IF ( ln_zps ) THEN ! z-coordinate
  192. IF ( ln_trcldf_level ) ierr = 1 ! iso-level not allowed
  193. IF ( ln_trcldf_hor ) nldf = 2 ! horizontal (no rotation)
  194. IF ( ln_trcldf_iso ) ierr = 2 ! isoneutral ( rotation)
  195. ENDIF
  196. IF ( ln_sco ) THEN ! z-coordinate
  197. IF ( ln_trcldf_level ) nldf = 2 ! iso-level (no rotation)
  198. IF ( ln_trcldf_hor ) nldf = 3 ! horizontal ( rotation)
  199. IF ( ln_trcldf_iso ) ierr = 2 ! isoneutral ( rotation)
  200. ENDIF
  201. ENDIF
  202. IF( ierr == 1 ) CALL ctl_stop( ' iso-level in z-coordinate - partial step, not allowed' )
  203. IF( ierr == 2 ) CALL ctl_stop( ' isoneutral bilaplacian operator does not exist' )
  204. IF( lk_traldf_eiv .AND. .NOT.ln_trcldf_iso ) &
  205. CALL ctl_stop( ' eddy induced velocity on tracers', &
  206. & ' the eddy induced velocity on tracers requires isopycnal laplacian diffusion' )
  207. IF( nldf == 1 .OR. nldf == 3 ) THEN ! rotation
  208. IF( .NOT.lk_ldfslp ) CALL ctl_stop( ' the rotation of the diffusive tensor require key_ldfslp' )
  209. #if defined key_offline
  210. l_traldf_rot = .TRUE. ! needed for trazdf_imp
  211. #endif
  212. ENDIF
  213. IF( lk_esopa ) THEN
  214. IF(lwp) WRITE(numout,*) ' esopa control: use all lateral physics options'
  215. nldf = -1
  216. ENDIF
  217. IF(lwp) THEN
  218. WRITE(numout,*)
  219. IF( nldf == -2 ) WRITE(numout,*) ' NO lateral diffusion'
  220. IF( nldf == -1 ) WRITE(numout,*) ' ESOPA test All scheme used'
  221. IF( nldf == 0 ) WRITE(numout,*) ' laplacian operator'
  222. IF( nldf == 1 ) WRITE(numout,*) ' Rotated laplacian operator'
  223. IF( nldf == 2 ) WRITE(numout,*) ' bilaplacian operator'
  224. IF( nldf == 3 ) WRITE(numout,*) ' Rotated bilaplacian'
  225. ENDIF
  226. IF( ln_trcldf_bilap ) THEN
  227. IF(lwp) WRITE(numout,*) ' biharmonic tracer diffusion'
  228. IF( rn_ahtrc_0 > 0 .AND. .NOT. lk_esopa ) CALL ctl_stop( 'The horizontal diffusivity coef. rn_ahtrc_0 must be negative' )
  229. ELSE
  230. IF(lwp) WRITE(numout,*) ' harmonic tracer diffusion (default)'
  231. IF( rn_ahtrc_0 < 0 .AND. .NOT. lk_esopa ) CALL ctl_stop('The horizontal diffusivity coef. rn_ahtrc_0 must be positive' )
  232. ENDIF
  233. ! ratio between active and passive tracers diffusive coef.
  234. IF (ABS(rn_aht_0) < 2._wp*TINY(1.e0)) THEN
  235. IF (ABS(rn_ahtrc_0) < 2._wp*TINY(1.e0)) THEN
  236. rldf_rat = 1.0_wp
  237. ELSE
  238. CALL ctl_stop( 'STOP', 'ldf_ctl : cannot define rldf_rat, rn_aht_0==0, rn_ahtrc_0 /=0' )
  239. END IF
  240. ELSE
  241. rldf_rat = rn_ahtrc_0 / rn_aht_0
  242. END IF
  243. IF( rldf_rat < 0 ) THEN
  244. IF( .NOT.lk_offline ) THEN
  245. CALL ctl_stop( 'Choose the same type of diffusive scheme both for active & passive tracers' )
  246. ELSE
  247. CALL ctl_stop( 'Change the sign of rn_aht_0 in namelist to -/+1' )
  248. ENDIF
  249. ENDIF
  250. !
  251. END SUBROUTINE ldf_ctl
  252. #else
  253. !!----------------------------------------------------------------------
  254. !! Default option Empty module
  255. !!----------------------------------------------------------------------
  256. CONTAINS
  257. SUBROUTINE trc_ldf( kt )
  258. INTEGER, INTENT(in) :: kt
  259. WRITE(*,*) 'trc_ldf: You should not have seen this print! error?', kt
  260. END SUBROUTINE trc_ldf
  261. #endif
  262. !!======================================================================
  263. END MODULE trcldf