trazdf_exp.F90 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. MODULE trazdf_exp
  2. !!==============================================================================
  3. !! *** MODULE trazdf_exp ***
  4. !! Ocean tracers: vertical component of the tracer mixing trend using
  5. !! a split-explicit time-stepping
  6. !!==============================================================================
  7. !! History : OPA ! 1990-10 (B. Blanke) Original code
  8. !! 7.0 ! 1991-11 (G. Madec)
  9. !! ! 1992-06 (M. Imbard) correction on tracer trend loops
  10. !! ! 1996-01 (G. Madec) statement function for e3
  11. !! ! 1997-05 (G. Madec) vertical component of isopycnal
  12. !! ! 1997-07 (G. Madec) geopotential diffusion in s-coord
  13. !! ! 2000-08 (G. Madec) double diffusive mixing
  14. !! NEMO 1.0 ! 2002-08 (G. Madec) F90: Free form and module
  15. !! - ! 2004-08 (C. Talandier) New trends organisation
  16. !! - ! 2005-11 (G. Madec) New organisation
  17. !! 3.0 ! 2008-04 (G. Madec) leap-frog time stepping done in trazdf
  18. !! 3.3 ! 2010-06 (C. Ethe, G. Madec) Merge TRA-TRC
  19. !!----------------------------------------------------------------------
  20. !!----------------------------------------------------------------------
  21. !! tra_zdf_exp : compute the tracer the vertical diffusion trend using a
  22. !! split-explicit time stepping and provide the after tracer
  23. !!----------------------------------------------------------------------
  24. USE oce ! ocean dynamics and active tracers
  25. USE dom_oce ! ocean space and time domain
  26. USE domvvl ! variable volume levels
  27. USE zdf_oce ! ocean vertical physics
  28. USE zdfddm ! ocean vertical physics: double diffusion
  29. USE trc_oce ! share passive tracers/Ocean variables
  30. USE in_out_manager ! I/O manager
  31. USE lib_mpp ! MPP library
  32. USE wrk_nemo ! Memory Allocation
  33. USE timing ! Timing
  34. IMPLICIT NONE
  35. PRIVATE
  36. PUBLIC tra_zdf_exp ! routine called by step.F90
  37. !! * Substitutions
  38. # include "domzgr_substitute.h90"
  39. # include "zdfddm_substitute.h90"
  40. # include "vectopt_loop_substitute.h90"
  41. !!----------------------------------------------------------------------
  42. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  43. !! $Id: trazdf_exp.F90 3294 2012-01-28 16:44:18Z rblod $
  44. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  45. !!----------------------------------------------------------------------
  46. CONTAINS
  47. SUBROUTINE tra_zdf_exp( kt, kit000, cdtype, p2dt, kn_zdfexp, &
  48. & ptb , pta , kjpt )
  49. !!----------------------------------------------------------------------
  50. !! *** ROUTINE tra_zdf_exp ***
  51. !!
  52. !! ** Purpose : Compute the after tracer fields due to the vertical
  53. !! tracer mixing alone, and then due to the whole tracer trend.
  54. !!
  55. !! ** Method : - The after tracer fields due to the vertical diffusion
  56. !! of tracers alone is given by:
  57. !! zwx = ptb + p2dt difft
  58. !! where difft = dz( avt dz(ptb) ) = 1/e3t dk+1( avt/e3w dk(ptb) )
  59. !! (if lk_zdfddm=T use avs on salinity and passive tracers instead of avt)
  60. !! difft is evaluated with an Euler split-explit scheme using a
  61. !! no flux boundary condition at both surface and bottomi boundaries.
  62. !! (N.B. bottom condition is applied through the masked field avt).
  63. !! - the after tracer fields due to the whole trend is
  64. !! obtained in leap-frog environment by :
  65. !! pta = zwx + p2dt pta
  66. !! - in case of variable level thickness (lk_vvl=T) the
  67. !! the leap-frog is applied on thickness weighted tracer. That is:
  68. !! pta = [ ptb*e3tb + e3tn*( zwx - ptb + p2dt pta ) ] / e3tn
  69. !!
  70. !! ** Action : - after tracer fields pta
  71. !!---------------------------------------------------------------------
  72. !
  73. INTEGER , INTENT(in ) :: kt ! ocean time-step index
  74. INTEGER , INTENT(in ) :: kit000 ! first time step index
  75. CHARACTER(len=3) , INTENT(in ) :: cdtype ! =TRA or TRC (tracer indicator)
  76. INTEGER , INTENT(in ) :: kjpt ! number of tracers
  77. INTEGER , INTENT(in ) :: kn_zdfexp ! number of sub-time step
  78. REAL(wp), DIMENSION( jpk ), INTENT(in ) :: p2dt ! vertical profile of tracer time-step
  79. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(in ) :: ptb ! before and now tracer fields
  80. REAL(wp), DIMENSION(jpi,jpj,jpk,kjpt), INTENT(inout) :: pta ! tracer trend
  81. !
  82. INTEGER :: ji, jj, jk, jn, jl ! dummy loop indices
  83. REAL(wp) :: zlavmr, zave3r, ze3tr ! local scalars
  84. REAL(wp) :: ztra, ze3tb ! - -
  85. REAL(wp), POINTER, DIMENSION(:,:,:) :: zwx, zwy
  86. !!---------------------------------------------------------------------
  87. !
  88. IF( nn_timing == 1 ) CALL timing_start('tra_zdf_exp')
  89. !
  90. CALL wrk_alloc( jpi, jpj, jpk, zwx, zwy )
  91. !
  92. IF( kt == kit000 ) THEN
  93. IF(lwp) WRITE(numout,*)
  94. IF(lwp) WRITE(numout,*) 'tra_zdf_exp : explicit vertical mixing on ', cdtype
  95. IF(lwp) WRITE(numout,*) '~~~~~~~~~~~'
  96. ENDIF
  97. ! Initializations
  98. ! ---------------
  99. zlavmr = 1. / float( kn_zdfexp ) ! Local constant
  100. !
  101. !
  102. DO jn = 1, kjpt ! loop over tracers
  103. !
  104. zwy(:,:, 1 ) = 0.e0 ! surface boundary conditions: no flux
  105. zwy(:,:,jpk) = 0.e0 ! bottom boundary conditions: no flux
  106. !
  107. zwx(:,:,:) = ptb(:,:,:,jn) ! zwx array set to before tracer values
  108. ! Split-explicit loop (after tracer due to the vertical diffusion alone)
  109. ! -------------------
  110. !
  111. DO jl = 1, kn_zdfexp
  112. ! ! first vertical derivative
  113. DO jk = 2, jpk
  114. DO jj = 2, jpjm1
  115. DO ji = fs_2, fs_jpim1 ! vector opt.
  116. zave3r = 1.e0 / fse3w_n(ji,jj,jk)
  117. IF( cdtype == 'TRA' .AND. jn == jp_tem ) THEN ! temperature : use of avt
  118. zwy(ji,jj,jk) = avt(ji,jj,jk) * ( zwx(ji,jj,jk-1) - zwx(ji,jj,jk) ) * zave3r
  119. ELSE ! salinity or pass. tracer : use of avs
  120. zwy(ji,jj,jk) = fsavs(ji,jj,jk) * ( zwx(ji,jj,jk-1) - zwx(ji,jj,jk) ) * zave3r
  121. END IF
  122. END DO
  123. END DO
  124. END DO
  125. !
  126. DO jk = 1, jpkm1 ! second vertical derivative ==> tracer at kt+l*2*rdt/nn_zdfexp
  127. DO jj = 2, jpjm1
  128. DO ji = fs_2, fs_jpim1 ! vector opt.
  129. ze3tr = zlavmr / fse3t_n(ji,jj,jk)
  130. zwx(ji,jj,jk) = zwx(ji,jj,jk) + p2dt(jk) * ( zwy(ji,jj,jk) - zwy(ji,jj,jk+1) ) * ze3tr
  131. END DO
  132. END DO
  133. END DO
  134. !
  135. END DO
  136. ! After tracer due to all trends
  137. ! ------------------------------
  138. IF( lk_vvl ) THEN ! variable level thickness : leap-frog on tracer*e3t
  139. DO jk = 1, jpkm1
  140. DO jj = 2, jpjm1
  141. DO ji = fs_2, fs_jpim1 ! vector opt.
  142. ze3tb = fse3t_b(ji,jj,jk) / fse3t(ji,jj,jk) ! before e3t
  143. ztra = zwx(ji,jj,jk) - ptb(ji,jj,jk,jn) + p2dt(jk) * pta(ji,jj,jk,jn) ! total trends * 2*rdt
  144. pta(ji,jj,jk,jn) = ( ze3tb * ptb(ji,jj,jk,jn) + ztra ) * tmask(ji,jj,jk)
  145. END DO
  146. END DO
  147. END DO
  148. ELSE ! fixed level thickness : leap-frog on tracers
  149. DO jk = 1, jpkm1
  150. DO jj = 2, jpjm1
  151. DO ji = fs_2, fs_jpim1 ! vector opt.
  152. pta(ji,jj,jk,jn) = ( zwx(ji,jj,jk) + p2dt(jk) * pta(ji,jj,jk,jn) ) * tmask(ji,jj,jk)
  153. END DO
  154. END DO
  155. END DO
  156. ENDIF
  157. !
  158. END DO
  159. !
  160. CALL wrk_dealloc( jpi, jpj, jpk, zwx, zwy )
  161. !
  162. IF( nn_timing == 1 ) CALL timing_stop('tra_zdf_exp')
  163. !
  164. END SUBROUTINE tra_zdf_exp
  165. !!==============================================================================
  166. END MODULE trazdf_exp