traadv.F90 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. MODULE traadv
  2. !!==============================================================================
  3. !! *** MODULE traadv ***
  4. !! Ocean active tracers: advection trend
  5. !!==============================================================================
  6. !! History : 2.0 ! 2005-11 (G. Madec) Original code
  7. !! 3.3 ! 2010-09 (C. Ethe, G. Madec) merge TRC-TRA + switch from velocity to transport
  8. !! 4.0 ! 2011-06 (G. Madec) Addition of Mixed Layer Eddy parameterisation
  9. !!----------------------------------------------------------------------
  10. !!----------------------------------------------------------------------
  11. !! tra_adv : compute ocean tracer advection trend
  12. !! tra_adv_ctl : control the different options of advection scheme
  13. !!----------------------------------------------------------------------
  14. USE oce ! ocean dynamics and active tracers
  15. USE dom_oce ! ocean space and time domain
  16. USE domvvl ! variable vertical scale factors
  17. USE traadv_cen2 ! 2nd order centered scheme (tra_adv_cen2 routine)
  18. USE traadv_tvd ! TVD scheme (tra_adv_tvd routine)
  19. USE traadv_muscl ! MUSCL scheme (tra_adv_muscl routine)
  20. USE traadv_muscl2 ! MUSCL2 scheme (tra_adv_muscl2 routine)
  21. USE traadv_ubs ! UBS scheme (tra_adv_ubs routine)
  22. USE traadv_qck ! QUICKEST scheme (tra_adv_qck routine)
  23. USE traadv_eiv ! eddy induced velocity (tra_adv_eiv routine)
  24. USE traadv_mle ! ML eddy induced velocity (tra_adv_mle routine)
  25. USE cla ! cross land advection (cla_traadv routine)
  26. USE ldftra_oce ! lateral diffusion coefficient on tracers
  27. USE trd_oce ! trends: ocean variables
  28. USE trdtra ! trends manager: tracers
  29. !
  30. USE in_out_manager ! I/O manager
  31. USE iom ! I/O module
  32. USE prtctl ! Print control
  33. USE lib_mpp ! MPP library
  34. USE wrk_nemo ! Memory Allocation
  35. USE timing ! Timing
  36. USE sbc_oce
  37. USE diaptr ! Poleward heat transport
  38. IMPLICIT NONE
  39. PRIVATE
  40. PUBLIC tra_adv ! routine called by step module
  41. PUBLIC tra_adv_init ! routine called by opa module
  42. ! !!* Namelist namtra_adv *
  43. LOGICAL :: ln_traadv_cen2 ! 2nd order centered scheme flag
  44. LOGICAL :: ln_traadv_tvd ! TVD scheme flag
  45. LOGICAL :: ln_traadv_tvd_zts ! TVD scheme flag with vertical sub time-stepping
  46. LOGICAL :: ln_traadv_muscl ! MUSCL scheme flag
  47. LOGICAL :: ln_traadv_muscl2 ! MUSCL2 scheme flag
  48. LOGICAL :: ln_traadv_ubs ! UBS scheme flag
  49. LOGICAL :: ln_traadv_qck ! QUICKEST scheme flag
  50. LOGICAL :: ln_traadv_msc_ups ! use upstream scheme within muscl
  51. INTEGER :: nadv ! choice of the type of advection scheme
  52. !! * Substitutions
  53. # include "domzgr_substitute.h90"
  54. # include "vectopt_loop_substitute.h90"
  55. !!----------------------------------------------------------------------
  56. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  57. !! $Id: traadv.F90 7494 2016-12-14 09:02:43Z timgraham $
  58. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  59. !!----------------------------------------------------------------------
  60. CONTAINS
  61. SUBROUTINE tra_adv( kt )
  62. !!----------------------------------------------------------------------
  63. !! *** ROUTINE tra_adv ***
  64. !!
  65. !! ** Purpose : compute the ocean tracer advection trend.
  66. !!
  67. !! ** Method : - Update (ua,va) with the advection term following nadv
  68. !!----------------------------------------------------------------------
  69. !
  70. INTEGER, INTENT( in ) :: kt ! ocean time-step index
  71. !
  72. INTEGER :: jk ! dummy loop index
  73. REAL(wp), POINTER, DIMENSION(:,:,:) :: zun, zvn, zwn
  74. REAL(wp), POINTER, DIMENSION(:,:,:) :: ztrdt, ztrds ! 3D workspace
  75. REAL(wp), POINTER, DIMENSION(:,:,:) :: zu_eiv, zv_eiv, zw_eiv
  76. REAL(wp), POINTER, DIMENSION(:,:,:,:) :: ztsa_eiv
  77. LOGICAL :: lldia
  78. !!----------------------------------------------------------------------
  79. !
  80. IF( nn_timing == 1 ) CALL timing_start('tra_adv')
  81. !
  82. CALL wrk_alloc( jpi, jpj, jpk, zun, zvn, zwn )
  83. ! ! set time step
  84. IF( neuler == 0 .AND. kt == nit000 ) THEN ! at nit000
  85. r2dtra(:) = rdttra(:) ! = rdtra (restarting with Euler time stepping)
  86. ELSEIF( kt <= nit000 + 1) THEN ! at nit000 or nit000+1
  87. r2dtra(:) = 2._wp * rdttra(:) ! = 2 rdttra (leapfrog)
  88. ENDIF
  89. !
  90. IF( nn_cla == 1 .AND. cp_cfg == 'orca' .AND. jp_cfg == 2 ) CALL cla_traadv( kt ) !== Cross Land Advection ==! (hor. advection)
  91. !
  92. ! !== effective transport ==!
  93. DO jk = 1, jpkm1
  94. zun(:,:,jk) = e2u(:,:) * fse3u(:,:,jk) * un(:,:,jk) ! eulerian transport only
  95. zvn(:,:,jk) = e1v(:,:) * fse3v(:,:,jk) * vn(:,:,jk)
  96. zwn(:,:,jk) = e1t(:,:) * e2t(:,:) * wn(:,:,jk)
  97. END DO
  98. !
  99. IF( ln_vvl_ztilde .OR. ln_vvl_layer ) THEN
  100. zun(:,:,:) = zun(:,:,:) + un_td(:,:,:)
  101. zvn(:,:,:) = zvn(:,:,:) + vn_td(:,:,:)
  102. ENDIF
  103. !
  104. zun(:,:,jpk) = 0._wp ! no transport trough the bottom
  105. zvn(:,:,jpk) = 0._wp ! no transport trough the bottom
  106. zwn(:,:,jpk) = 0._wp ! no transport trough the bottom
  107. !
  108. IF( lk_traldf_eiv .AND. .NOT. ln_traldf_grif ) &
  109. & CALL tra_adv_eiv( kt, nit000, zun, zvn, zwn, 'TRA' ) ! add the eiv transport (if necessary)
  110. !
  111. IF( ln_mle ) CALL tra_adv_mle( kt, nit000, zun, zvn, zwn, 'TRA' ) ! add the mle transport (if necessary)
  112. !
  113. CALL iom_put( "uocetr_eff", zun ) ! output effective transport
  114. CALL iom_put( "vocetr_eff", zvn )
  115. CALL iom_put( "wocetr_eff", zwn )
  116. !
  117. IF( ln_diaptr ) CALL dia_ptr( zvn ) ! diagnose the effective MSF
  118. !
  119. IF( l_trdtra ) THEN !* Save ta and sa trends
  120. CALL wrk_alloc( jpi, jpj, jpk, ztrdt, ztrds )
  121. ztrdt(:,:,:) = tsa(:,:,:,jp_tem)
  122. ztrds(:,:,:) = tsa(:,:,:,jp_sal)
  123. ENDIF
  124. !
  125. SELECT CASE ( nadv ) !== compute advection trend and add it to general trend ==!
  126. CASE ( 1 ) ; CALL tra_adv_cen2 ( kt, nit000, 'TRA', zun, zvn, zwn, tsb, tsn, tsa, jpts ) ! 2nd order centered
  127. CASE ( 2 ) ; CALL tra_adv_tvd ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts ) ! TVD
  128. CASE ( 3 ) ; CALL tra_adv_muscl ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsa, jpts, ln_traadv_msc_ups ) ! MUSCL
  129. CASE ( 4 ) ; CALL tra_adv_muscl2 ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts ) ! MUSCL2
  130. CASE ( 5 ) ; CALL tra_adv_ubs ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts ) ! UBS
  131. CASE ( 6 ) ; CALL tra_adv_qck ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts ) ! QUICKEST
  132. CASE ( 7 ) ; CALL tra_adv_tvd_zts( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts ) ! TVD ZTS
  133. !
  134. CASE (-1 ) !== esopa: test all possibility with control print ==!
  135. CALL tra_adv_cen2 ( kt, nit000, 'TRA', zun, zvn, zwn, tsb, tsn, tsa, jpts )
  136. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' adv0 - Ta: ', mask1=tmask, &
  137. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  138. CALL tra_adv_tvd ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts )
  139. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' adv1 - Ta: ', mask1=tmask, &
  140. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  141. CALL tra_adv_muscl ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsa, jpts, ln_traadv_msc_ups )
  142. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' adv3 - Ta: ', mask1=tmask, &
  143. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  144. CALL tra_adv_muscl2( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts )
  145. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' adv4 - Ta: ', mask1=tmask, &
  146. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  147. CALL tra_adv_ubs ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts )
  148. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' adv5 - Ta: ', mask1=tmask, &
  149. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  150. CALL tra_adv_qck ( kt, nit000, 'TRA', r2dtra, zun, zvn, zwn, tsb, tsn, tsa, jpts )
  151. CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' adv6 - Ta: ', mask1=tmask, &
  152. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  153. END SELECT
  154. !
  155. IF( l_trdtra ) THEN ! save the advective trends for further diagnostics
  156. DO jk = 1, jpkm1
  157. ztrdt(:,:,jk) = tsa(:,:,jk,jp_tem) - ztrdt(:,:,jk)
  158. ztrds(:,:,jk) = tsa(:,:,jk,jp_sal) - ztrds(:,:,jk)
  159. END DO
  160. CALL trd_tra( kt, 'TRA', jp_tem, jptra_totad, ztrdt )
  161. CALL trd_tra( kt, 'TRA', jp_sal, jptra_totad, ztrds )
  162. CALL wrk_dealloc( jpi, jpj, jpk, ztrdt, ztrds )
  163. IF( lk_traldf_eiv .AND. .NOT. ln_traldf_grif ) THEN
  164. lldia = .FALSE.
  165. CALL wrk_alloc( jpi, jpj, jpk, zu_eiv, zv_eiv, zw_eiv )
  166. CALL wrk_alloc( jpi, jpj, jpk, jpts, ztsa_eiv )
  167. !
  168. ztsa_eiv(:,:,:,:) = 0._wp
  169. DO jk = 1, jpkm1
  170. zu_eiv(:,:,jk) = e2u(:,:) * fse3u(:,:,jk) * u_eiv(:,:,jk) ! eulerian transport only
  171. zv_eiv(:,:,jk) = e1v(:,:) * fse3v(:,:,jk) * v_eiv(:,:,jk)
  172. zw_eiv(:,:,jk) = e1t(:,:) * e2t(:,:) * w_eiv(:,:,jk)
  173. END DO
  174. CALL tra_adv_tvd( kt, nit000, 'TRA', r2dtra, zu_eiv, zv_eiv, zw_eiv, tsb, tsn, ztsa_eiv, jpts, ld_dia=lldia ) ! TVD
  175. CALL trd_tra( kt, 'TRA', jp_tem, jptra_eivad, ztsa_eiv(:,:,:,jp_tem) )
  176. CALL trd_tra( kt, 'TRA', jp_sal, jptra_eivad, ztsa_eiv(:,:,:,jp_sal) )
  177. !
  178. CALL wrk_dealloc( jpi, jpj, jpk, zu_eiv, zv_eiv, zw_eiv )
  179. CALL wrk_dealloc( jpi, jpj, jpk, jpts, ztsa_eiv )
  180. ENDIF
  181. ENDIF
  182. ! ! print mean trends (used for debugging)
  183. IF(ln_ctl) CALL prt_ctl( tab3d_1=tsa(:,:,:,jp_tem), clinfo1=' adv - Ta: ', mask1=tmask, &
  184. & tab3d_2=tsa(:,:,:,jp_sal), clinfo2= ' Sa: ', mask2=tmask, clinfo3='tra' )
  185. !
  186. IF( nn_timing == 1 ) CALL timing_stop( 'tra_adv' )
  187. !
  188. CALL wrk_dealloc( jpi, jpj, jpk, zun, zvn, zwn )
  189. !
  190. END SUBROUTINE tra_adv
  191. SUBROUTINE tra_adv_init
  192. !!---------------------------------------------------------------------
  193. !! *** ROUTINE tra_adv_init ***
  194. !!
  195. !! ** Purpose : Control the consistency between namelist options for
  196. !! tracer advection schemes and set nadv
  197. !!----------------------------------------------------------------------
  198. INTEGER :: ioptio
  199. INTEGER :: ios ! Local integer output status for namelist read
  200. !!
  201. NAMELIST/namtra_adv/ ln_traadv_cen2 , ln_traadv_tvd, &
  202. & ln_traadv_muscl, ln_traadv_muscl2, &
  203. & ln_traadv_ubs , ln_traadv_qck, &
  204. & ln_traadv_msc_ups, ln_traadv_tvd_zts
  205. !!----------------------------------------------------------------------
  206. REWIND( numnam_ref ) ! Namelist namtra_adv in reference namelist : Tracer advection scheme
  207. READ ( numnam_ref, namtra_adv, IOSTAT = ios, ERR = 901)
  208. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namtra_adv in reference namelist', lwp )
  209. REWIND( numnam_cfg ) ! Namelist namtra_adv in configuration namelist : Tracer advection scheme
  210. READ ( numnam_cfg, namtra_adv, IOSTAT = ios, ERR = 902 )
  211. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namtra_adv in configuration namelist', lwp )
  212. IF(lwm) WRITE ( numond, namtra_adv )
  213. IF(lwp) THEN ! Namelist print
  214. WRITE(numout,*)
  215. WRITE(numout,*) 'tra_adv_init : choice/control of the tracer advection scheme'
  216. WRITE(numout,*) '~~~~~~~~~~~'
  217. WRITE(numout,*) ' Namelist namtra_adv : chose a advection scheme for tracers'
  218. WRITE(numout,*) ' 2nd order advection scheme ln_traadv_cen2 = ', ln_traadv_cen2
  219. WRITE(numout,*) ' TVD advection scheme ln_traadv_tvd = ', ln_traadv_tvd
  220. WRITE(numout,*) ' MUSCL advection scheme ln_traadv_muscl = ', ln_traadv_muscl
  221. WRITE(numout,*) ' MUSCL2 advection scheme ln_traadv_muscl2 = ', ln_traadv_muscl2
  222. WRITE(numout,*) ' UBS advection scheme ln_traadv_ubs = ', ln_traadv_ubs
  223. WRITE(numout,*) ' QUICKEST advection scheme ln_traadv_qck = ', ln_traadv_qck
  224. WRITE(numout,*) ' upstream scheme within muscl ln_traadv_msc_ups = ', ln_traadv_msc_ups
  225. WRITE(numout,*) ' TVD advection scheme with zts ln_traadv_tvd_zts = ', ln_traadv_tvd_zts
  226. ENDIF
  227. ioptio = 0 ! Parameter control
  228. IF( ln_traadv_cen2 ) ioptio = ioptio + 1
  229. IF( ln_traadv_tvd ) ioptio = ioptio + 1
  230. IF( ln_traadv_muscl ) ioptio = ioptio + 1
  231. IF( ln_traadv_muscl2 ) ioptio = ioptio + 1
  232. IF( ln_traadv_ubs ) ioptio = ioptio + 1
  233. IF( ln_traadv_qck ) ioptio = ioptio + 1
  234. IF( ln_traadv_tvd_zts) ioptio = ioptio + 1
  235. IF( lk_esopa ) ioptio = 1
  236. IF( ( ln_traadv_muscl .OR. ln_traadv_muscl2 .OR. ln_traadv_ubs .OR. ln_traadv_qck .OR. ln_traadv_tvd_zts ) &
  237. .AND. ln_isfcav ) CALL ctl_stop( 'Only traadv_cen2 and traadv_tvd is compatible with ice shelf cavity')
  238. IF( ioptio /= 1 ) CALL ctl_stop( 'Choose ONE advection scheme in namelist namtra_adv' )
  239. ! ! Set nadv
  240. IF( ln_traadv_cen2 ) nadv = 1
  241. IF( ln_traadv_tvd ) nadv = 2
  242. IF( ln_traadv_muscl ) nadv = 3
  243. IF( ln_traadv_muscl2 ) nadv = 4
  244. IF( ln_traadv_ubs ) nadv = 5
  245. IF( ln_traadv_qck ) nadv = 6
  246. IF( ln_traadv_tvd_zts) nadv = 7
  247. IF( lk_esopa ) nadv = -1
  248. IF(lwp) THEN ! Print the choice
  249. WRITE(numout,*)
  250. IF( nadv == 1 ) WRITE(numout,*) ' 2nd order scheme is used'
  251. IF( nadv == 2 ) WRITE(numout,*) ' TVD scheme is used'
  252. IF( nadv == 3 ) WRITE(numout,*) ' MUSCL scheme is used'
  253. IF( nadv == 4 ) WRITE(numout,*) ' MUSCL2 scheme is used'
  254. IF( nadv == 5 ) WRITE(numout,*) ' UBS scheme is used'
  255. IF( nadv == 6 ) WRITE(numout,*) ' QUICKEST scheme is used'
  256. IF( nadv == 7 ) WRITE(numout,*) ' TVD ZTS scheme is used'
  257. IF( nadv == -1 ) WRITE(numout,*) ' esopa test: use all advection scheme'
  258. ENDIF
  259. !
  260. CALL tra_adv_mle_init ! initialisation of the Mixed Layer Eddy parametrisation (MLE)
  261. !
  262. END SUBROUTINE tra_adv_init
  263. !!======================================================================
  264. END MODULE traadv