traadv_qck.F90 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. MODULE traadv_qck
  2. !!==============================================================================
  3. !! *** MODULE traadv_qck ***
  4. !! Ocean tracers: horizontal & vertical advective trend
  5. !!==============================================================================
  6. !! History : 3.0 ! 2008-07 (G. Reffray) Original code
  7. !! 3.3 ! 2010-05 (C.Ethe, G. Madec) merge TRC-TRA + switch from velocity to transport
  8. !!----------------------------------------------------------------------
  9. !!----------------------------------------------------------------------
  10. !! tra_adv_qck : update the tracer trend with the horizontal advection
  11. !! trends using a 3rd order finite difference scheme
  12. !! tra_adv_qck_i : apply QUICK scheme in i-direction
  13. !! tra_adv_qck_j : apply QUICK scheme in j-direction
  14. !! tra_adv_cen2_k : 2nd centered scheme for the vertical advection
  15. !!----------------------------------------------------------------------
  16. USE oce ! ocean dynamics and active tracers
  17. USE dom_oce ! ocean space and time domain
  18. USE trc_oce ! share passive tracers/Ocean variables
  19. USE trd_oce ! trends: ocean variables
  20. USE trdtra ! trends manager: tracers
  21. USE dynspg_oce ! surface pressure gradient variables
  22. USE diaptr ! poleward transport diagnostics
  23. !
  24. USE lib_mpp ! distribued memory computing
  25. USE lbclnk ! ocean lateral boundary condition (or mpp link)
  26. USE in_out_manager ! I/O manager
  27. USE wrk_nemo ! Memory Allocation
  28. USE timing ! Timing
  29. USE lib_fortran ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined)
  30. IMPLICIT NONE
  31. PRIVATE
  32. PUBLIC tra_adv_qck ! routine called by step.F90
  33. LOGICAL :: l_trd ! flag to compute trends
  34. REAL(wp) :: r1_6 = 1./ 6. ! 1/6 ratio
  35. !! * Substitutions
  36. # include "domzgr_substitute.h90"
  37. # include "vectopt_loop_substitute.h90"
  38. !!----------------------------------------------------------------------
  39. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  40. !! $Id: traadv_qck.F90 4990 2014-12-15 16:42:49Z timgraham $
  41. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  42. !!----------------------------------------------------------------------
  43. CONTAINS
  44. SUBROUTINE tra_adv_qck ( kt, kit000, cdtype, p2dt, pun, pvn, pwn, &
  45. & ptb, ptn, pta, kjpt )
  46. !!----------------------------------------------------------------------
  47. !! *** ROUTINE tra_adv_qck ***
  48. !!
  49. !! ** Purpose : Compute the now trend due to the advection of tracers
  50. !! and add it to the general trend of passive tracer equations.
  51. !!
  52. !! ** Method : The advection is evaluated by a third order scheme
  53. !! For a positive velocity u : u(i)>0
  54. !! |--FU--|--FC--|--FD--|------|
  55. !! i-1 i i+1 i+2
  56. !!
  57. !! For a negative velocity u : u(i)<0
  58. !! |------|--FD--|--FC--|--FU--|
  59. !! i-1 i i+1 i+2
  60. !! where FU is the second upwind point
  61. !! FD is the first douwning point
  62. !! FC is the central point (or the first upwind point)
  63. !!
  64. !! Flux(i) = u(i) * { 0.5(FC+FD) -0.5C(i)(FD-FC) -((1-C(i))/6)(FU+FD-2FC) }
  65. !! with C(i)=|u(i)|dx(i)/dt (=Courant number)
  66. !!
  67. !! dt = 2*rdtra and the scalar values are tb and sb
  68. !!
  69. !! On the vertical, the simple centered scheme used ptn
  70. !!
  71. !! The fluxes are bounded by the ULTIMATE limiter to
  72. !! guarantee the monotonicity of the solution and to
  73. !! prevent the appearance of spurious numerical oscillations
  74. !!
  75. !! ** Action : - update (pta) with the now advective tracer trends
  76. !! - save the trends
  77. !!
  78. !! ** Reference : Leonard (1979, 1991)
  79. !!----------------------------------------------------------------------
  80. INTEGER , INTENT(in ) :: kt ! ocean time-step index
  81. INTEGER , INTENT(in ) :: kit000 ! first time step index
  82. CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator)
  83. INTEGER , INTENT(in ) :: kjpt ! number of tracers
  84. REAL(wp), DIMENSION( jpk ), INTENT(in ) :: p2dt ! vertical profile of tracer time-step
  85. REAL(wp), DIMENSION(jpi,jpj,jpk ), INTENT(in ) :: pun, pvn, pwn ! 3 ocean velocity components
  86. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(in ) :: ptb, ptn ! before and now tracer fields
  87. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(inout) :: pta ! tracer trend
  88. !!----------------------------------------------------------------------
  89. !
  90. IF( nn_timing == 1 ) CALL timing_start('tra_adv_qck')
  91. !
  92. IF( kt == kit000 ) THEN
  93. IF(lwp) WRITE(numout,*)
  94. IF(lwp) WRITE(numout,*) 'tra_adv_qck : 3rd order quickest advection scheme on ', cdtype
  95. IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~'
  96. IF(lwp) WRITE(numout,*)
  97. ENDIF
  98. l_trd = .FALSE.
  99. IF( ( cdtype == 'TRA' .AND. l_trdtra ) .OR. ( cdtype == 'TRC' .AND. l_trdtrc ) ) l_trd = .TRUE.
  100. !
  101. ! I. The horizontal fluxes are computed with the QUICKEST + ULTIMATE scheme
  102. CALL tra_adv_qck_i( kt, cdtype, p2dt, pun, ptb, ptn, pta, kjpt )
  103. CALL tra_adv_qck_j( kt, cdtype, p2dt, pvn, ptb, ptn, pta, kjpt )
  104. ! II. The vertical fluxes are computed with the 2nd order centered scheme
  105. CALL tra_adv_cen2_k( kt, cdtype, pwn, ptn, pta, kjpt )
  106. !
  107. IF( nn_timing == 1 ) CALL timing_stop('tra_adv_qck')
  108. !
  109. END SUBROUTINE tra_adv_qck
  110. SUBROUTINE tra_adv_qck_i( kt, cdtype, p2dt, pun, &
  111. & ptb, ptn, pta, kjpt )
  112. !!----------------------------------------------------------------------
  113. !!
  114. !!----------------------------------------------------------------------
  115. INTEGER , INTENT(in ) :: kt ! ocean time-step index
  116. CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator)
  117. INTEGER , INTENT(in ) :: kjpt ! number of tracers
  118. REAL(wp), DIMENSION( jpk ), INTENT(in ) :: p2dt ! vertical profile of tracer time-step
  119. REAL(wp), DIMENSION(jpi,jpj,jpk ), INTENT(in ) :: pun ! i-velocity components
  120. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(in ) :: ptb, ptn ! before and now tracer fields
  121. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(inout) :: pta ! tracer trend
  122. !!
  123. INTEGER :: ji, jj, jk, jn ! dummy loop indices
  124. REAL(wp) :: ztra, zbtr, zdir, zdx, zdt, zmsk ! local scalars
  125. REAL(wp), POINTER, DIMENSION(:,:,:) :: zwx, zfu, zfc, zfd
  126. !----------------------------------------------------------------------
  127. !
  128. CALL wrk_alloc( jpi, jpj, jpk, zwx, zfu, zfc, zfd )
  129. ! ! ===========
  130. DO jn = 1, kjpt ! tracer loop
  131. ! ! ===========
  132. zfu(:,:,:) = 0.0 ; zfc(:,:,:) = 0.0
  133. zfd(:,:,:) = 0.0 ; zwx(:,:,:) = 0.0
  134. !
  135. DO jk = 1, jpkm1
  136. !
  137. !--- Computation of the ustream and downstream value of the tracer and the mask
  138. DO jj = 2, jpjm1
  139. DO ji = fs_2, fs_jpim1 ! vector opt.
  140. ! Upstream in the x-direction for the tracer
  141. zfc(ji,jj,jk) = ptb(ji-1,jj,jk,jn)
  142. ! Downstream in the x-direction for the tracer
  143. zfd(ji,jj,jk) = ptb(ji+1,jj,jk,jn)
  144. END DO
  145. END DO
  146. END DO
  147. CALL lbc_lnk( zfc(:,:,:), 'T', 1. ) ; CALL lbc_lnk( zfd(:,:,:), 'T', 1. ) ! Lateral boundary conditions
  148. !
  149. ! Horizontal advective fluxes
  150. ! ---------------------------
  151. !
  152. DO jk = 1, jpkm1
  153. DO jj = 2, jpjm1
  154. DO ji = fs_2, fs_jpim1 ! vector opt.
  155. zdir = 0.5 + SIGN( 0.5, pun(ji,jj,jk) ) ! if pun > 0 : zdir = 1 otherwise zdir = 0
  156. zfu(ji,jj,jk) = zdir * zfc(ji,jj,jk ) + ( 1. - zdir ) * zfd(ji+1,jj,jk) ! FU in the x-direction for T
  157. END DO
  158. END DO
  159. END DO
  160. !
  161. DO jk = 1, jpkm1
  162. zdt = p2dt(jk)
  163. DO jj = 2, jpjm1
  164. DO ji = fs_2, fs_jpim1 ! vector opt.
  165. zdir = 0.5 + SIGN( 0.5, pun(ji,jj,jk) ) ! if pun > 0 : zdir = 1 otherwise zdir = 0
  166. zdx = ( zdir * e1t(ji,jj) + ( 1. - zdir ) * e1t(ji+1,jj) ) * e2u(ji,jj) * fse3u(ji,jj,jk)
  167. zwx(ji,jj,jk) = ABS( pun(ji,jj,jk) ) * zdt / zdx ! (0<zc_cfl<1 : Courant number on x-direction)
  168. zfc(ji,jj,jk) = zdir * ptb(ji ,jj,jk,jn) + ( 1. - zdir ) * ptb(ji+1,jj,jk,jn) ! FC in the x-direction for T
  169. zfd(ji,jj,jk) = zdir * ptb(ji+1,jj,jk,jn) + ( 1. - zdir ) * ptb(ji ,jj,jk,jn) ! FD in the x-direction for T
  170. END DO
  171. END DO
  172. END DO
  173. !--- Lateral boundary conditions
  174. CALL lbc_lnk( zfu(:,:,:), 'T', 1. ) ; CALL lbc_lnk( zfd(:,:,:), 'T', 1. )
  175. CALL lbc_lnk( zfc(:,:,:), 'T', 1. ) ; CALL lbc_lnk( zwx(:,:,:), 'T', 1. )
  176. !--- QUICKEST scheme
  177. CALL quickest( zfu, zfd, zfc, zwx )
  178. !
  179. ! Mask at the T-points in the x-direction (mask=0 or mask=1)
  180. DO jk = 1, jpkm1
  181. DO jj = 2, jpjm1
  182. DO ji = fs_2, fs_jpim1 ! vector opt.
  183. zfu(ji,jj,jk) = tmask(ji-1,jj,jk) + tmask(ji,jj,jk) + tmask(ji+1,jj,jk) - 2.
  184. END DO
  185. END DO
  186. END DO
  187. CALL lbc_lnk( zfu(:,:,:), 'T', 1. ) ! Lateral boundary conditions
  188. !
  189. ! Tracer flux on the x-direction
  190. DO jk = 1, jpkm1
  191. !
  192. DO jj = 2, jpjm1
  193. DO ji = fs_2, fs_jpim1 ! vector opt.
  194. zdir = 0.5 + SIGN( 0.5, pun(ji,jj,jk) ) ! if pun > 0 : zdir = 1 otherwise zdir = 0
  195. !--- If the second ustream point is a land point
  196. !--- the flux is computed by the 1st order UPWIND scheme
  197. zmsk = zdir * zfu(ji,jj,jk) + ( 1. - zdir ) * zfu(ji+1,jj,jk)
  198. zwx(ji,jj,jk) = zmsk * zwx(ji,jj,jk) + ( 1. - zmsk ) * zfc(ji,jj,jk)
  199. zwx(ji,jj,jk) = zwx(ji,jj,jk) * pun(ji,jj,jk)
  200. END DO
  201. END DO
  202. END DO
  203. !
  204. CALL lbc_lnk( zwx(:,:,:), 'T', 1. ) ! Lateral boundary conditions
  205. !
  206. ! Computation of the trend
  207. DO jk = 1, jpkm1
  208. DO jj = 2, jpjm1
  209. DO ji = fs_2, fs_jpim1 ! vector opt.
  210. zbtr = 1. / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
  211. ! horizontal advective trends
  212. ztra = - zbtr * ( zwx(ji,jj,jk) - zwx(ji-1,jj,jk) )
  213. !--- add it to the general tracer trends
  214. pta(ji,jj,jk,jn) = pta(ji,jj,jk,jn) + ztra
  215. END DO
  216. END DO
  217. END DO
  218. ! ! trend diagnostics (contribution of upstream fluxes)
  219. IF( l_trd ) CALL trd_tra( kt, cdtype, jn, jptra_xad, zwx, pun, ptn(:,:,:,jn) )
  220. !
  221. END DO
  222. !
  223. CALL wrk_dealloc( jpi, jpj, jpk, zwx, zfu, zfc, zfd )
  224. !
  225. END SUBROUTINE tra_adv_qck_i
  226. SUBROUTINE tra_adv_qck_j( kt, cdtype, p2dt, pvn, &
  227. & ptb, ptn, pta, kjpt )
  228. !!----------------------------------------------------------------------
  229. !!
  230. !!----------------------------------------------------------------------
  231. INTEGER , INTENT(in ) :: kt ! ocean time-step index
  232. CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator)
  233. INTEGER , INTENT(in ) :: kjpt ! number of tracers
  234. REAL(wp), DIMENSION( jpk ), INTENT(in ) :: p2dt ! vertical profile of tracer time-step
  235. REAL(wp), DIMENSION(jpi,jpj,jpk ), INTENT(in ) :: pvn ! j-velocity components
  236. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(in ) :: ptb, ptn ! before and now tracer fields
  237. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(inout) :: pta ! tracer trend
  238. !!
  239. INTEGER :: ji, jj, jk, jn ! dummy loop indices
  240. REAL(wp) :: ztra, zbtr, zdir, zdx, zdt, zmsk ! local scalars
  241. REAL(wp), POINTER, DIMENSION(:,:,:) :: zwy, zfu, zfc, zfd
  242. !----------------------------------------------------------------------
  243. !
  244. CALL wrk_alloc( jpi, jpj, jpk, zwy, zfu, zfc, zfd )
  245. !
  246. ! ! ===========
  247. DO jn = 1, kjpt ! tracer loop
  248. ! ! ===========
  249. zfu(:,:,:) = 0.0 ; zfc(:,:,:) = 0.0
  250. zfd(:,:,:) = 0.0 ; zwy(:,:,:) = 0.0
  251. !
  252. DO jk = 1, jpkm1
  253. !
  254. !--- Computation of the ustream and downstream value of the tracer and the mask
  255. DO jj = 2, jpjm1
  256. DO ji = fs_2, fs_jpim1 ! vector opt.
  257. ! Upstream in the x-direction for the tracer
  258. zfc(ji,jj,jk) = ptb(ji,jj-1,jk,jn)
  259. ! Downstream in the x-direction for the tracer
  260. zfd(ji,jj,jk) = ptb(ji,jj+1,jk,jn)
  261. END DO
  262. END DO
  263. END DO
  264. CALL lbc_lnk( zfc(:,:,:), 'T', 1. ) ; CALL lbc_lnk( zfd(:,:,:), 'T', 1. ) ! Lateral boundary conditions
  265. !
  266. ! Horizontal advective fluxes
  267. ! ---------------------------
  268. !
  269. DO jk = 1, jpkm1
  270. DO jj = 2, jpjm1
  271. DO ji = fs_2, fs_jpim1 ! vector opt.
  272. zdir = 0.5 + SIGN( 0.5, pvn(ji,jj,jk) ) ! if pun > 0 : zdir = 1 otherwise zdir = 0
  273. zfu(ji,jj,jk) = zdir * zfc(ji,jj,jk ) + ( 1. - zdir ) * zfd(ji,jj+1,jk) ! FU in the x-direction for T
  274. END DO
  275. END DO
  276. END DO
  277. !
  278. DO jk = 1, jpkm1
  279. zdt = p2dt(jk)
  280. DO jj = 2, jpjm1
  281. DO ji = fs_2, fs_jpim1 ! vector opt.
  282. zdir = 0.5 + SIGN( 0.5, pvn(ji,jj,jk) ) ! if pun > 0 : zdir = 1 otherwise zdir = 0
  283. zdx = ( zdir * e2t(ji,jj) + ( 1. - zdir ) * e2t(ji,jj+1) ) * e1v(ji,jj) * fse3v(ji,jj,jk)
  284. zwy(ji,jj,jk) = ABS( pvn(ji,jj,jk) ) * zdt / zdx ! (0<zc_cfl<1 : Courant number on x-direction)
  285. zfc(ji,jj,jk) = zdir * ptb(ji,jj ,jk,jn) + ( 1. - zdir ) * ptb(ji,jj+1,jk,jn) ! FC in the x-direction for T
  286. zfd(ji,jj,jk) = zdir * ptb(ji,jj+1,jk,jn) + ( 1. - zdir ) * ptb(ji,jj ,jk,jn) ! FD in the x-direction for T
  287. END DO
  288. END DO
  289. END DO
  290. !--- Lateral boundary conditions
  291. CALL lbc_lnk( zfu(:,:,:), 'T', 1. ) ; CALL lbc_lnk( zfd(:,:,:), 'T', 1. )
  292. CALL lbc_lnk( zfc(:,:,:), 'T', 1. ) ; CALL lbc_lnk( zwy(:,:,:), 'T', 1. )
  293. !--- QUICKEST scheme
  294. CALL quickest( zfu, zfd, zfc, zwy )
  295. !
  296. ! Mask at the T-points in the x-direction (mask=0 or mask=1)
  297. DO jk = 1, jpkm1
  298. DO jj = 2, jpjm1
  299. DO ji = fs_2, fs_jpim1 ! vector opt.
  300. zfu(ji,jj,jk) = tmask(ji,jj-1,jk) + tmask(ji,jj,jk) + tmask(ji,jj+1,jk) - 2.
  301. END DO
  302. END DO
  303. END DO
  304. !--- Lateral boundary conditions
  305. CALL lbc_lnk( zfu(:,:,:), 'T', 1. )
  306. !
  307. ! Tracer flux on the x-direction
  308. DO jk = 1, jpkm1
  309. !
  310. DO jj = 2, jpjm1
  311. DO ji = fs_2, fs_jpim1 ! vector opt.
  312. zdir = 0.5 + SIGN( 0.5, pvn(ji,jj,jk) ) ! if pun > 0 : zdir = 1 otherwise zdir = 0
  313. !--- If the second ustream point is a land point
  314. !--- the flux is computed by the 1st order UPWIND scheme
  315. zmsk = zdir * zfu(ji,jj,jk) + ( 1. - zdir ) * zfu(ji,jj+1,jk)
  316. zwy(ji,jj,jk) = zmsk * zwy(ji,jj,jk) + ( 1. - zmsk ) * zfc(ji,jj,jk)
  317. zwy(ji,jj,jk) = zwy(ji,jj,jk) * pvn(ji,jj,jk)
  318. END DO
  319. END DO
  320. END DO
  321. !
  322. CALL lbc_lnk( zwy(:,:,:), 'T', 1. ) ! Lateral boundary conditions
  323. !
  324. ! Computation of the trend
  325. DO jk = 1, jpkm1
  326. DO jj = 2, jpjm1
  327. DO ji = fs_2, fs_jpim1 ! vector opt.
  328. zbtr = 1. / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
  329. ! horizontal advective trends
  330. ztra = - zbtr * ( zwy(ji,jj,jk) - zwy(ji,jj-1,jk) )
  331. !--- add it to the general tracer trends
  332. pta(ji,jj,jk,jn) = pta(ji,jj,jk,jn) + ztra
  333. END DO
  334. END DO
  335. END DO
  336. ! ! trend diagnostics (contribution of upstream fluxes)
  337. IF( l_trd ) CALL trd_tra( kt, cdtype, jn, jptra_yad, zwy, pvn, ptn(:,:,:,jn) )
  338. ! ! "Poleward" heat and salt transports (contribution of upstream fluxes)
  339. IF( cdtype == 'TRA' .AND. ln_diaptr ) CALL dia_ptr_ohst_components( jn, 'adv', zwy(:,:,:) )
  340. !
  341. END DO
  342. !
  343. CALL wrk_dealloc( jpi, jpj, jpk, zwy, zfu, zfc, zfd )
  344. !
  345. END SUBROUTINE tra_adv_qck_j
  346. SUBROUTINE tra_adv_cen2_k( kt, cdtype, pwn, &
  347. & ptn, pta, kjpt )
  348. !!----------------------------------------------------------------------
  349. !!
  350. !!----------------------------------------------------------------------
  351. INTEGER , INTENT(in ) :: kt ! ocean time-step index
  352. CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator)
  353. INTEGER , INTENT(in ) :: kjpt ! number of tracers
  354. REAL(wp), DIMENSION(jpi,jpj,jpk ), INTENT(in ) :: pwn ! vertical velocity
  355. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(in ) :: ptn ! before and now tracer fields
  356. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(inout) :: pta ! tracer trend
  357. !
  358. INTEGER :: ji, jj, jk, jn ! dummy loop indices
  359. REAL(wp) :: zbtr , ztra ! local scalars
  360. REAL(wp), POINTER, DIMENSION(:,:,:) :: zwz
  361. !!----------------------------------------------------------------------
  362. !
  363. CALL wrk_alloc( jpi, jpj, jpk, zwz )
  364. ! ! ===========
  365. DO jn = 1, kjpt ! tracer loop
  366. ! ! ===========
  367. ! 1. Bottom value : flux set to zero
  368. zwz(:,:,jpk) = 0.e0 ! Bottom value : flux set to zero
  369. !
  370. ! ! Surface value
  371. IF( lk_vvl ) THEN ; zwz(:,:, 1 ) = 0.e0 ! Variable volume : flux set to zero
  372. ELSE ; zwz(:,:, 1 ) = pwn(:,:,1) * ptn(:,:,1,jn) ! Constant volume : advective flux through the surface
  373. ENDIF
  374. !
  375. DO jk = 2, jpkm1 ! Interior point: second order centered tracer flux at w-point
  376. DO jj = 2, jpjm1
  377. DO ji = fs_2, fs_jpim1 ! vector opt.
  378. zwz(ji,jj,jk) = 0.5 * pwn(ji,jj,jk) * ( ptn(ji,jj,jk-1,jn) + ptn(ji,jj,jk,jn) )
  379. END DO
  380. END DO
  381. END DO
  382. !
  383. DO jk = 1, jpkm1 !== Tracer flux divergence added to the general trend ==!
  384. DO jj = 2, jpjm1
  385. DO ji = fs_2, fs_jpim1 ! vector opt.
  386. zbtr = 1. / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
  387. ! k- vertical advective trends
  388. ztra = - zbtr * ( zwz(ji,jj,jk) - zwz(ji,jj,jk+1) )
  389. ! added to the general tracer trends
  390. pta(ji,jj,jk,jn) = pta(ji,jj,jk,jn) + ztra
  391. END DO
  392. END DO
  393. END DO
  394. ! ! Save the vertical advective trends for diagnostic
  395. IF( l_trd ) CALL trd_tra( kt, cdtype, jn, jptra_zad, zwz, pwn, ptn(:,:,:,jn) )
  396. !
  397. END DO
  398. !
  399. CALL wrk_dealloc( jpi, jpj, jpk, zwz )
  400. !
  401. END SUBROUTINE tra_adv_cen2_k
  402. SUBROUTINE quickest( pfu, pfd, pfc, puc )
  403. !!----------------------------------------------------------------------
  404. !!
  405. !! ** Purpose : Computation of advective flux with Quickest scheme
  406. !!
  407. !! ** Method :
  408. !!----------------------------------------------------------------------
  409. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(in ) :: pfu ! second upwind point
  410. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(in ) :: pfd ! first douwning point
  411. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(in ) :: pfc ! the central point (or the first upwind point)
  412. REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) :: puc ! input as Courant number ; output as flux
  413. !!
  414. INTEGER :: ji, jj, jk ! dummy loop indices
  415. REAL(wp) :: zcoef1, zcoef2, zcoef3 ! local scalars
  416. REAL(wp) :: zc, zcurv, zfho ! - -
  417. !----------------------------------------------------------------------
  418. !
  419. IF( nn_timing == 1 ) CALL timing_start('quickest')
  420. !
  421. DO jk = 1, jpkm1
  422. DO jj = 1, jpj
  423. DO ji = 1, jpi
  424. zc = puc(ji,jj,jk) ! Courant number
  425. zcurv = pfd(ji,jj,jk) + pfu(ji,jj,jk) - 2. * pfc(ji,jj,jk)
  426. zcoef1 = 0.5 * ( pfc(ji,jj,jk) + pfd(ji,jj,jk) )
  427. zcoef2 = 0.5 * zc * ( pfd(ji,jj,jk) - pfc(ji,jj,jk) )
  428. zcoef3 = ( 1. - ( zc * zc ) ) * r1_6 * zcurv
  429. zfho = zcoef1 - zcoef2 - zcoef3 ! phi_f QUICKEST
  430. !
  431. zcoef1 = pfd(ji,jj,jk) - pfu(ji,jj,jk)
  432. zcoef2 = ABS( zcoef1 )
  433. zcoef3 = ABS( zcurv )
  434. IF( zcoef3 >= zcoef2 ) THEN
  435. zfho = pfc(ji,jj,jk)
  436. ELSE
  437. zcoef3 = pfu(ji,jj,jk) + ( ( pfc(ji,jj,jk) - pfu(ji,jj,jk) ) / MAX( zc, 1.e-9 ) ) ! phi_REF
  438. IF( zcoef1 >= 0. ) THEN
  439. zfho = MAX( pfc(ji,jj,jk), zfho )
  440. zfho = MIN( zfho, MIN( zcoef3, pfd(ji,jj,jk) ) )
  441. ELSE
  442. zfho = MIN( pfc(ji,jj,jk), zfho )
  443. zfho = MAX( zfho, MAX( zcoef3, pfd(ji,jj,jk) ) )
  444. ENDIF
  445. ENDIF
  446. puc(ji,jj,jk) = zfho
  447. END DO
  448. END DO
  449. END DO
  450. !
  451. IF( nn_timing == 1 ) CALL timing_stop('quickest')
  452. !
  453. END SUBROUTINE quickest
  454. !!======================================================================
  455. END MODULE traadv_qck