New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
dynzdf.F90 in NEMO/branches/2021/dev_r14318_RK3_stage1/src/OCE/DYN – NEMO

source: NEMO/branches/2021/dev_r14318_RK3_stage1/src/OCE/DYN/dynzdf.F90 @ 14618

Last change on this file since 14618 was 14547, checked in by techene, 3 years ago

#2605 RK3 time-stepping on OCE only (run on GYRE_PISCES without key_top)

  • Property svn:keywords set to Id
File size: 25.2 KB
RevLine 
[456]1MODULE dynzdf
2   !!==============================================================================
3   !!                 ***  MODULE  dynzdf  ***
4   !! Ocean dynamics :  vertical component of the momentum mixing trend
5   !!==============================================================================
[2528]6   !! History :  1.0  !  2005-11  (G. Madec)  Original code
7   !!            3.3  !  2010-10  (C. Ethe, G. Madec) reorganisation of initialisation phase
[9019]8   !!            4.0  !  2017-06  (G. Madec) remove the explicit time-stepping option + avm at t-point
[456]9   !!----------------------------------------------------------------------
[503]10
11   !!----------------------------------------------------------------------
[9019]12   !!   dyn_zdf       : compute the after velocity through implicit calculation of vertical mixing
[456]13   !!----------------------------------------------------------------------
[5836]14   USE oce            ! ocean dynamics and tracers variables
[9019]15   USE phycst         ! physical constants
[5836]16   USE dom_oce        ! ocean space and time domain variables
[9019]17   USE sbc_oce        ! surface boundary condition: ocean
[5836]18   USE zdf_oce        ! ocean vertical physics variables
[9019]19   USE zdfdrg         ! vertical physics: top/bottom drag coef.
20   USE dynadv    ,ONLY: ln_dynadv_vec    ! dynamics: advection form
21   USE dynldf_iso,ONLY: akzu, akzv       ! dynamics: vertical component of rotated lateral mixing
[9490]22   USE ldfdyn         ! lateral diffusion: eddy viscosity coef. and type of operator
[5836]23   USE trd_oce        ! trends: ocean variables
24   USE trddyn         ! trend manager: dynamics
25   !
26   USE in_out_manager ! I/O manager
27   USE lib_mpp        ! MPP library
28   USE prtctl         ! Print control
29   USE timing         ! Timing
[456]30
31   IMPLICIT NONE
32   PRIVATE
33
[9019]34   PUBLIC   dyn_zdf   !  routine called by step.F90
[456]35
[9019]36   REAL(wp) ::  r_vvl     ! non-linear free surface indicator: =0 if ln_linssh=T, =1 otherwise
[456]37
38   !! * Substitutions
[12377]39#  include "do_loop_substitute.h90"
[13237]40#  include "domzgr_substitute.h90"
[456]41   !!----------------------------------------------------------------------
[9598]42   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
[1152]43   !! $Id$
[10068]44   !! Software governed by the CeCILL license (see ./LICENSE)
[456]45   !!----------------------------------------------------------------------
46CONTAINS
47   
[12377]48   SUBROUTINE dyn_zdf( kt, Kbb, Kmm, Krhs, puu, pvv, Kaa )
[456]49      !!----------------------------------------------------------------------
50      !!                  ***  ROUTINE dyn_zdf  ***
51      !!
[9019]52      !! ** Purpose :   compute the trend due to the vert. momentum diffusion
53      !!              together with the Leap-Frog time stepping using an
54      !!              implicit scheme.
55      !!
56      !! ** Method  :  - Leap-Frog time stepping on all trends but the vertical mixing
[12377]57      !!         u(after) =         u(before) + 2*dt *       u(rhs)                vector form or linear free surf.
[13237]58      !!         u(after) = ( e3u_b*u(before) + 2*dt * e3u_n*u(rhs) ) / e3u_after   otherwise
[9019]59      !!               - update the after velocity with the implicit vertical mixing.
60      !!      This requires to solver the following system:
[13237]61      !!         u(after) = u(after) + 1/e3u_after  dk+1[ mi(avm) / e3uw_after dk[ua] ]
[9019]62      !!      with the following surface/top/bottom boundary condition:
63      !!      surface: wind stress input (averaged over kt-1/2 & kt+1/2)
64      !!      top & bottom : top stress (iceshelf-ocean) & bottom stress (cf zdfdrg.F90)
65      !!
[12377]66      !! ** Action :   (puu(:,:,:,Kaa),pvv(:,:,:,Kaa))   after velocity
[456]67      !!---------------------------------------------------------------------
[12377]68      INTEGER                             , INTENT( in )  ::  kt                  ! ocean time-step index
69      INTEGER                             , INTENT( in )  ::  Kbb, Kmm, Krhs, Kaa ! ocean time level indices
70      REAL(wp), DIMENSION(jpi,jpj,jpk,jpt), INTENT(inout) ::  puu, pvv            ! ocean velocities and RHS of momentum equation
[3294]71      !
[14547]72      INTEGER  ::   ji, jj, jk           ! dummy loop indices
73      INTEGER  ::   iku, ikv             ! local integers
74      REAL(wp) ::   zzwi, ze3ua, zDt_2   ! local scalars
75      REAL(wp) ::   zzws, ze3va          !   -      -
76      REAL(wp) ::   z1_e3ua, z1_e3va     !   -      -
77      REAL(wp) ::   zWu , zWv            !   -      -
78      REAL(wp) ::   zWui, zWvi           !   -      -
79      REAL(wp) ::   zWus, zWvs           !   -      -
[9019]80      REAL(wp), DIMENSION(jpi,jpj,jpk)        ::  zwi, zwd, zws   ! 3D workspace
81      REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::   ztrdu, ztrdv   !  -      -
[456]82      !!---------------------------------------------------------------------
[3294]83      !
[9019]84      IF( ln_timing )   CALL timing_start('dyn_zdf')
[3294]85      !
[9019]86      IF( kt == nit000 ) THEN       !* initialization
87         IF(lwp) WRITE(numout,*)
88         IF(lwp) WRITE(numout,*) 'dyn_zdf_imp : vertical momentum diffusion implicit operator'
89         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~ '
90         !
91         If( ln_linssh ) THEN   ;    r_vvl = 0._wp    ! non-linear free surface indicator
92         ELSE                   ;    r_vvl = 1._wp
93         ENDIF
94      ENDIF
[14547]95      !
96      zDt_2 = rDt * 0.5_wp
97      !
[9250]98      !                             !* explicit top/bottom drag case
[12377]99      IF( .NOT.ln_drgimp )   CALL zdf_drg_exp( kt, Kmm, puu(:,:,:,Kbb), pvv(:,:,:,Kbb), puu(:,:,:,Krhs), pvv(:,:,:,Krhs) )  ! add top/bottom friction trend to (puu(Kaa),pvv(Kaa))
[9250]100      !
101      !
[9019]102      IF( l_trddyn )   THEN         !* temporary save of ta and sa trends
103         ALLOCATE( ztrdu(jpi,jpj,jpk), ztrdv(jpi,jpj,jpk) ) 
[12377]104         ztrdu(:,:,:) = puu(:,:,:,Krhs)
105         ztrdv(:,:,:) = pvv(:,:,:,Krhs)
[456]106      ENDIF
[9019]107      !
[12377]108      !              !==  RHS: Leap-Frog time stepping on all trends but the vertical mixing  ==!   (put in puu(:,:,:,Kaa),pvv(:,:,:,Kaa))
[9019]109      !
110      !                    ! time stepping except vertical diffusion
111      IF( ln_dynadv_vec .OR. ln_linssh ) THEN   ! applied on velocity
[13295]112         DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13286]113            puu(ji,jj,jk,Kaa) = ( puu(ji,jj,jk,Kbb) + rDt * puu(ji,jj,jk,Krhs) ) * umask(ji,jj,jk)
114            pvv(ji,jj,jk,Kaa) = ( pvv(ji,jj,jk,Kbb) + rDt * pvv(ji,jj,jk,Krhs) ) * vmask(ji,jj,jk)
115         END_3D
[9019]116      ELSE                                      ! applied on thickness weighted velocity
[13295]117         DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13286]118            puu(ji,jj,jk,Kaa) = (         e3u(ji,jj,jk,Kbb) * puu(ji,jj,jk,Kbb )  &
119               &                  + rDt * e3u(ji,jj,jk,Kmm) * puu(ji,jj,jk,Krhs)  ) &
120               &                        / e3u(ji,jj,jk,Kaa) * umask(ji,jj,jk)
121            pvv(ji,jj,jk,Kaa) = (         e3v(ji,jj,jk,Kbb) * pvv(ji,jj,jk,Kbb )  &
122               &                  + rDt * e3v(ji,jj,jk,Kmm) * pvv(ji,jj,jk,Krhs)  ) &
123               &                        / e3v(ji,jj,jk,Kaa) * vmask(ji,jj,jk)
124         END_3D
[9019]125      ENDIF
126      !                    ! add top/bottom friction
127      !     With split-explicit free surface, barotropic stress is treated explicitly Update velocities at the bottom.
128      !     J. Chanut: The bottom stress is computed considering after barotropic velocities, which does
129      !                not lead to the effective stress seen over the whole barotropic loop.
[12377]130      !     G. Madec : in linear free surface, e3u(:,:,:,Kaa) = e3u(:,:,:,Kmm) = e3u_0, so systematic use of e3u(:,:,:,Kaa)
[9019]131      IF( ln_drgimp .AND. ln_dynspg_ts ) THEN
[13295]132         DO_3D( 0, 0, 0, 0, 1, jpkm1 )      ! remove barotropic velocities
[13286]133            puu(ji,jj,jk,Kaa) = ( puu(ji,jj,jk,Kaa) - uu_b(ji,jj,Kaa) ) * umask(ji,jj,jk)
134            pvv(ji,jj,jk,Kaa) = ( pvv(ji,jj,jk,Kaa) - vv_b(ji,jj,Kaa) ) * vmask(ji,jj,jk)
135         END_3D
[13497]136         DO_2D( 0, 0, 0, 0 )      ! Add bottom/top stress due to barotropic component only
[12377]137            iku = mbku(ji,jj)         ! ocean bottom level at u- and v-points
138            ikv = mbkv(ji,jj)         ! (deepest ocean u- and v-points)
[13237]139            ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,iku,Kmm)    &
140               &             + r_vvl   * e3u(ji,jj,iku,Kaa)
141            ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,ikv,Kmm)    &
142               &             + r_vvl   * e3v(ji,jj,ikv,Kaa)
[14547]143            puu(ji,jj,iku,Kaa) = puu(ji,jj,iku,Kaa) + zDt_2 *( rCdU_bot(ji+1,jj)+rCdU_bot(ji,jj) ) * uu_b(ji,jj,Kaa) / ze3ua
144            pvv(ji,jj,ikv,Kaa) = pvv(ji,jj,ikv,Kaa) + zDt_2 *( rCdU_bot(ji,jj+1)+rCdU_bot(ji,jj) ) * vv_b(ji,jj,Kaa) / ze3va
[12377]145         END_2D
[13472]146         IF( ln_isfcav.OR.ln_drgice_imp ) THEN    ! Ocean cavities (ISF)
[13295]147            DO_2D( 0, 0, 0, 0 )
[12377]148               iku = miku(ji,jj)         ! top ocean level at u- and v-points
149               ikv = mikv(ji,jj)         ! (first wet ocean u- and v-points)
[13237]150               ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,iku,Kmm)    &
151                  &             + r_vvl   * e3u(ji,jj,iku,Kaa)
152               ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,ikv,Kmm)    &
153                  &             + r_vvl   * e3v(ji,jj,ikv,Kaa)
[14547]154               puu(ji,jj,iku,Kaa) = puu(ji,jj,iku,Kaa) + zDt_2 *( rCdU_top(ji+1,jj)+rCdU_top(ji,jj) ) * uu_b(ji,jj,Kaa) / ze3ua
155               pvv(ji,jj,ikv,Kaa) = pvv(ji,jj,ikv,Kaa) + zDt_2 *( rCdU_top(ji,jj+1)+rCdU_top(ji,jj) ) * vv_b(ji,jj,Kaa) / ze3va
[12377]156            END_2D
[9019]157         END IF
158      ENDIF
159      !
160      !              !==  Vertical diffusion on u  ==!
161      !
162      !                    !* Matrix construction
[10364]163      IF( ln_zad_Aimp ) THEN   !!
164         SELECT CASE( nldf_dyn )
165         CASE( np_lap_i )           ! rotated lateral mixing: add its vertical mixing (akzu)
[13295]166            DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13237]167               ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,jk,Kmm)    &
168                  &             + r_vvl   * e3u(ji,jj,jk,Kaa)   ! after scale factor at U-point
[14547]169               zzwi = - zDt_2 * ( avm(ji+1,jj,jk  ) + avm(ji,jj,jk  ) + akzu(ji,jj,jk  ) )   &
[12377]170                  &         / ( ze3ua * e3uw(ji,jj,jk  ,Kmm) ) * wumask(ji,jj,jk  )
[14547]171               zzws = - zDt_2 * ( avm(ji+1,jj,jk+1) + avm(ji,jj,jk+1) + akzu(ji,jj,jk+1) )   &
[12377]172                  &         / ( ze3ua * e3uw(ji,jj,jk+1,Kmm) ) * wumask(ji,jj,jk+1)
173               zWui = ( wi(ji,jj,jk  ) + wi(ji+1,jj,jk  ) ) / ze3ua
174               zWus = ( wi(ji,jj,jk+1) + wi(ji+1,jj,jk+1) ) / ze3ua
[14547]175               zwi(ji,jj,jk) = zzwi + zDt_2 * MIN( zWui, 0._wp ) 
176               zws(ji,jj,jk) = zzws - zDt_2 * MAX( zWus, 0._wp )
177               zwd(ji,jj,jk) = 1._wp - zzwi - zzws + zDt_2 * ( MAX( zWui, 0._wp ) - MIN( zWus, 0._wp ) )
[12377]178            END_3D
[10364]179         CASE DEFAULT               ! iso-level lateral mixing
[13295]180            DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13237]181               ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,jk,Kmm)    &    ! after scale factor at U-point
182                  &             + r_vvl   * e3u(ji,jj,jk,Kaa)
[14547]183               zzwi = - zDt_2 * ( avm(ji+1,jj,jk  ) + avm(ji,jj,jk  ) )   &
[13237]184                  &         / ( ze3ua * e3uw(ji,jj,jk  ,Kmm) ) * wumask(ji,jj,jk  )
[14547]185               zzws = - zDt_2 * ( avm(ji+1,jj,jk+1) + avm(ji,jj,jk+1) )   &
[13237]186                  &         / ( ze3ua * e3uw(ji,jj,jk+1,Kmm) ) * wumask(ji,jj,jk+1)
[12377]187               zWui = ( wi(ji,jj,jk  ) + wi(ji+1,jj,jk  ) ) / ze3ua
188               zWus = ( wi(ji,jj,jk+1) + wi(ji+1,jj,jk+1) ) / ze3ua
[14547]189               zwi(ji,jj,jk) = zzwi + zDt_2 * MIN( zWui, 0._wp )
190               zws(ji,jj,jk) = zzws - zDt_2 * MAX( zWus, 0._wp )
191               zwd(ji,jj,jk) = 1._wp - zzwi - zzws + zDt_2 * ( MAX( zWui, 0._wp ) - MIN( zWus, 0._wp ) )
[12377]192            END_3D
[10364]193         END SELECT
[13497]194         DO_2D( 0, 0, 0, 0 )     !* Surface boundary conditions
[12377]195            zwi(ji,jj,1) = 0._wp
[13237]196            ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,1,Kmm)    &
197               &             + r_vvl   * e3u(ji,jj,1,Kaa)
[14547]198            zzws = - zDt_2 * ( avm(ji+1,jj,2) + avm(ji  ,jj,2) )   &
[13237]199               &         / ( ze3ua * e3uw(ji,jj,2,Kmm) ) * wumask(ji,jj,2)
[12377]200            zWus = ( wi(ji  ,jj,2) +  wi(ji+1,jj,2) ) / ze3ua
[14547]201            zws(ji,jj,1 ) = zzws - zDt_2 * MAX( zWus, 0._wp )
202            zwd(ji,jj,1 ) = 1._wp - zzws - zDt_2 * ( MIN( zWus, 0._wp ) )
[12377]203         END_2D
[10364]204      ELSE
205         SELECT CASE( nldf_dyn )
206         CASE( np_lap_i )           ! rotated lateral mixing: add its vertical mixing (akzu)
[13295]207            DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13237]208               ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,jk,Kmm)    &
209                  &             + r_vvl   * e3u(ji,jj,jk,Kaa)   ! after scale factor at U-point
[14547]210               zzwi = - zDt_2 * ( avm(ji+1,jj,jk  ) + avm(ji,jj,jk  ) + akzu(ji,jj,jk  ) )   &
[12377]211                  &         / ( ze3ua * e3uw(ji,jj,jk  ,Kmm) ) * wumask(ji,jj,jk  )
[14547]212               zzws = - zDt_2 * ( avm(ji+1,jj,jk+1) + avm(ji,jj,jk+1) + akzu(ji,jj,jk+1) )   &
[12377]213                  &         / ( ze3ua * e3uw(ji,jj,jk+1,Kmm) ) * wumask(ji,jj,jk+1)
214               zwi(ji,jj,jk) = zzwi
215               zws(ji,jj,jk) = zzws
216               zwd(ji,jj,jk) = 1._wp - zzwi - zzws
217            END_3D
[10364]218         CASE DEFAULT               ! iso-level lateral mixing
[13295]219            DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13237]220               ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,jk,Kmm)    &
221                  &             + r_vvl   * e3u(ji,jj,jk,Kaa)   ! after scale factor at U-point
[14547]222               zzwi = - zDt_2 * ( avm(ji+1,jj,jk  ) + avm(ji,jj,jk  ) )    &
[13237]223                  &         / ( ze3ua * e3uw(ji,jj,jk  ,Kmm) ) * wumask(ji,jj,jk  )
[14547]224               zzws = - zDt_2 * ( avm(ji+1,jj,jk+1) + avm(ji,jj,jk+1) )    &
[13237]225                  &         / ( ze3ua * e3uw(ji,jj,jk+1,Kmm) ) * wumask(ji,jj,jk+1)
[12377]226               zwi(ji,jj,jk) = zzwi
227               zws(ji,jj,jk) = zzws
228               zwd(ji,jj,jk) = 1._wp - zzwi - zzws
229            END_3D
[10364]230         END SELECT
[13497]231         DO_2D( 0, 0, 0, 0 )     !* Surface boundary conditions
[12377]232            zwi(ji,jj,1) = 0._wp
233            zwd(ji,jj,1) = 1._wp - zws(ji,jj,1)
234         END_2D
[10364]235      ENDIF
[9019]236      !
237      !
238      !              !==  Apply semi-implicit bottom friction  ==!
239      !
240      !     Only needed for semi-implicit bottom friction setup. The explicit
241      !     bottom friction has been included in "u(v)a" which act as the R.H.S
242      !     column vector of the tri-diagonal matrix equation
243      !
244      IF ( ln_drgimp ) THEN      ! implicit bottom friction
[13295]245         DO_2D( 0, 0, 0, 0 )
[12377]246            iku = mbku(ji,jj)       ! ocean bottom level at u- and v-points
[13237]247            ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,iku,Kmm)    &
248               &             + r_vvl   * e3u(ji,jj,iku,Kaa)   ! after scale factor at T-point
[14547]249            zwd(ji,jj,iku) = zwd(ji,jj,iku) - zDt_2 *( rCdU_bot(ji+1,jj)+rCdU_bot(ji,jj) ) / ze3ua
[12377]250         END_2D
[13472]251         IF ( ln_isfcav.OR.ln_drgice_imp ) THEN   ! top friction (always implicit)
[13295]252            DO_2D( 0, 0, 0, 0 )
[12377]253               !!gm   top Cd is masked (=0 outside cavities) no need of test on mik>=2  ==>> it has been suppressed
254               iku = miku(ji,jj)       ! ocean top level at u- and v-points
[13237]255               ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,iku,Kmm)    &
256                  &             + r_vvl   * e3u(ji,jj,iku,Kaa)   ! after scale factor at T-point
[14547]257               zwd(ji,jj,iku) = zwd(ji,jj,iku) - zDt_2 *( rCdU_top(ji+1,jj)+rCdU_top(ji,jj) ) / ze3ua
[12377]258            END_2D
[9019]259         END IF
260      ENDIF
261      !
262      ! Matrix inversion starting from the first level
263      !-----------------------------------------------------------------------
264      !   solve m.x = y  where m is a tri diagonal matrix ( jpk*jpk )
265      !
266      !        ( zwd1 zws1   0    0    0  )( zwx1 ) ( zwy1 )
267      !        ( zwi2 zwd2 zws2   0    0  )( zwx2 ) ( zwy2 )
268      !        (  0   zwi3 zwd3 zws3   0  )( zwx3 )=( zwy3 )
269      !        (        ...               )( ...  ) ( ...  )
270      !        (  0    0    0   zwik zwdk )( zwxk ) ( zwyk )
271      !
272      !   m is decomposed in the product of an upper and a lower triangular matrix
273      !   The 3 diagonal terms are in 2d arrays: zwd, zws, zwi
[12377]274      !   The solution (the after velocity) is in puu(:,:,:,Kaa)
[9019]275      !-----------------------------------------------------------------------
276      !
[13472]277      DO_3D( 0, 0, 0, 0, 2, jpkm1 )   !==  First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1   (increasing k)  ==
[12377]278         zwd(ji,jj,jk) = zwd(ji,jj,jk) - zwi(ji,jj,jk) * zws(ji,jj,jk-1) / zwd(ji,jj,jk-1)
279      END_3D
[9019]280      !
[13472]281      DO_2D( 0, 0, 0, 0 )             !==  second recurrence:    SOLk = RHSk - Lk / Dk-1  Lk-1  ==!
[13237]282         ze3ua =  ( 1._wp - r_vvl ) * e3u(ji,jj,1,Kmm)    &
283            &             + r_vvl   * e3u(ji,jj,1,Kaa) 
[14547]284         puu(ji,jj,1,Kaa) = puu(ji,jj,1,Kaa) + zDt_2 * ( utau_b(ji,jj) + utau(ji,jj) )   &
[12489]285            &                                      / ( ze3ua * rho0 ) * umask(ji,jj,1) 
[12377]286      END_2D
[13295]287      DO_3D( 0, 0, 0, 0, 2, jpkm1 )
[12377]288         puu(ji,jj,jk,Kaa) = puu(ji,jj,jk,Kaa) - zwi(ji,jj,jk) / zwd(ji,jj,jk-1) * puu(ji,jj,jk-1,Kaa)
289      END_3D
[9019]290      !
[13472]291      DO_2D( 0, 0, 0, 0 )             !==  thrid recurrence : SOLk = ( Lk - Uk * Ek+1 ) / Dk  ==!
[12377]292         puu(ji,jj,jpkm1,Kaa) = puu(ji,jj,jpkm1,Kaa) / zwd(ji,jj,jpkm1)
293      END_2D
[13295]294      DO_3DS( 0, 0, 0, 0, jpk-2, 1, -1 )
[12377]295         puu(ji,jj,jk,Kaa) = ( puu(ji,jj,jk,Kaa) - zws(ji,jj,jk) * puu(ji,jj,jk+1,Kaa) ) / zwd(ji,jj,jk)
296      END_3D
[9019]297      !
298      !              !==  Vertical diffusion on v  ==!
299      !
300      !                       !* Matrix construction
[10364]301      IF( ln_zad_Aimp ) THEN   !!
302         SELECT CASE( nldf_dyn )
303         CASE( np_lap_i )           ! rotated lateral mixing: add its vertical mixing (akzv)
[13295]304            DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13237]305               ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,jk,Kmm)    &
306                  &             + r_vvl   * e3v(ji,jj,jk,Kaa)   ! after scale factor at V-point
[14547]307               zzwi = - zDt_2 * ( avm(ji,jj+1,jk  ) + avm(ji,jj,jk  ) + akzv(ji,jj,jk  ) )   &
[12377]308                  &         / ( ze3va * e3vw(ji,jj,jk  ,Kmm) ) * wvmask(ji,jj,jk  )
[14547]309               zzws = - zDt_2 * ( avm(ji,jj+1,jk+1) + avm(ji,jj,jk+1) + akzv(ji,jj,jk+1) )   &
[12377]310                  &         / ( ze3va * e3vw(ji,jj,jk+1,Kmm) ) * wvmask(ji,jj,jk+1)
311               zWvi = ( wi(ji,jj,jk  ) + wi(ji,jj+1,jk  ) ) / ze3va
312               zWvs = ( wi(ji,jj,jk+1) + wi(ji,jj+1,jk+1) ) / ze3va
[14547]313               zwi(ji,jj,jk) = zzwi + zDt_2 * MIN( zWvi, 0._wp )
314               zws(ji,jj,jk) = zzws - zDt_2 * MAX( zWvs, 0._wp )
315               zwd(ji,jj,jk) = 1._wp - zzwi - zzws - zDt_2 * ( - MAX( zWvi, 0._wp ) + MIN( zWvs, 0._wp ) )
[12377]316            END_3D
[10364]317         CASE DEFAULT               ! iso-level lateral mixing
[13295]318            DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13237]319               ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,jk,Kmm)    &
320                  &             + r_vvl   * e3v(ji,jj,jk,Kaa)   ! after scale factor at V-point
[14547]321               zzwi = - zDt_2 * ( avm(ji,jj+1,jk  ) + avm(ji,jj,jk  ) )    &
[13237]322                  &         / ( ze3va * e3vw(ji,jj,jk  ,Kmm) ) * wvmask(ji,jj,jk  )
[14547]323               zzws = - zDt_2 * ( avm(ji,jj+1,jk+1) + avm(ji,jj,jk+1) )    &
[13237]324                  &         / ( ze3va * e3vw(ji,jj,jk+1,Kmm) ) * wvmask(ji,jj,jk+1)
[12377]325               zWvi = ( wi(ji,jj,jk  ) + wi(ji,jj+1,jk  ) ) / ze3va
326               zWvs = ( wi(ji,jj,jk+1) + wi(ji,jj+1,jk+1) ) / ze3va
[14547]327               zwi(ji,jj,jk) = zzwi  + zDt_2 * MIN( zWvi, 0._wp )
328               zws(ji,jj,jk) = zzws  - zDt_2 * MAX( zWvs, 0._wp )
329               zwd(ji,jj,jk) = 1._wp - zzwi - zzws - zDt_2 * ( - MAX( zWvi, 0._wp ) + MIN( zWvs, 0._wp ) )
[12377]330            END_3D
[10364]331         END SELECT
[13472]332         DO_2D( 0, 0, 0, 0 )   !* Surface boundary conditions
[12377]333            zwi(ji,jj,1) = 0._wp
[13237]334            ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,1,Kmm)    &
335               &             + r_vvl   * e3v(ji,jj,1,Kaa)
[14547]336            zzws = - zDt_2 * ( avm(ji,jj+1,2) + avm(ji,jj,2) )    &
[13237]337               &         / ( ze3va * e3vw(ji,jj,2,Kmm) ) * wvmask(ji,jj,2)
[12377]338            zWvs = ( wi(ji,jj  ,2) +  wi(ji,jj+1,2) ) / ze3va
[14547]339            zws(ji,jj,1 ) = zzws - zDt_2 * MAX( zWvs, 0._wp )
340            zwd(ji,jj,1 ) = 1._wp - zzws - zDt_2 * ( MIN( zWvs, 0._wp ) )
[12377]341         END_2D
[10364]342      ELSE
343         SELECT CASE( nldf_dyn )
344         CASE( np_lap_i )           ! rotated lateral mixing: add its vertical mixing (akzu)
[13295]345            DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13237]346               ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,jk,Kmm)    &
347                  &             + r_vvl   * e3v(ji,jj,jk,Kaa)   ! after scale factor at V-point
[14547]348               zzwi = - zDt_2 * ( avm(ji,jj+1,jk  ) + avm(ji,jj,jk  ) + akzv(ji,jj,jk  ) )   &
[12377]349                  &         / ( ze3va * e3vw(ji,jj,jk  ,Kmm) ) * wvmask(ji,jj,jk  )
[14547]350               zzws = - zDt_2 * ( avm(ji,jj+1,jk+1) + avm(ji,jj,jk+1) + akzv(ji,jj,jk+1) )   &
[12377]351                  &         / ( ze3va * e3vw(ji,jj,jk+1,Kmm) ) * wvmask(ji,jj,jk+1)
352               zwi(ji,jj,jk) = zzwi
353               zws(ji,jj,jk) = zzws
354               zwd(ji,jj,jk) = 1._wp - zzwi - zzws
355            END_3D
[10364]356         CASE DEFAULT               ! iso-level lateral mixing
[13295]357            DO_3D( 0, 0, 0, 0, 1, jpkm1 )
[13237]358               ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,jk,Kmm)    &
359                  &             + r_vvl   * e3v(ji,jj,jk,Kaa)   ! after scale factor at V-point
[14547]360               zzwi = - zDt_2 * ( avm(ji,jj+1,jk  ) + avm(ji,jj,jk  ) )    &
[13237]361                  &         / ( ze3va * e3vw(ji,jj,jk  ,Kmm) ) * wvmask(ji,jj,jk  )
[14547]362               zzws = - zDt_2 * ( avm(ji,jj+1,jk+1) + avm(ji,jj,jk+1) )    &
[13237]363                  &         / ( ze3va * e3vw(ji,jj,jk+1,Kmm) ) * wvmask(ji,jj,jk+1)
[12377]364               zwi(ji,jj,jk) = zzwi
365               zws(ji,jj,jk) = zzws
366               zwd(ji,jj,jk) = 1._wp - zzwi - zzws
367            END_3D
[10364]368         END SELECT
[13497]369         DO_2D( 0, 0, 0, 0 )        !* Surface boundary conditions
[12377]370            zwi(ji,jj,1) = 0._wp
371            zwd(ji,jj,1) = 1._wp - zws(ji,jj,1)
372         END_2D
[10364]373      ENDIF
[9019]374      !
375      !              !==  Apply semi-implicit top/bottom friction  ==!
376      !
377      !     Only needed for semi-implicit bottom friction setup. The explicit
378      !     bottom friction has been included in "u(v)a" which act as the R.H.S
379      !     column vector of the tri-diagonal matrix equation
380      !
381      IF( ln_drgimp ) THEN
[13295]382         DO_2D( 0, 0, 0, 0 )
[12377]383            ikv = mbkv(ji,jj)       ! (deepest ocean u- and v-points)
[13237]384            ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,ikv,Kmm)    &
385               &             + r_vvl   * e3v(ji,jj,ikv,Kaa)   ! after scale factor at T-point
[14547]386            zwd(ji,jj,ikv) = zwd(ji,jj,ikv) - zDt_2*( rCdU_bot(ji,jj+1)+rCdU_bot(ji,jj) ) / ze3va           
[12377]387         END_2D
[13472]388         IF ( ln_isfcav.OR.ln_drgice_imp ) THEN
[13295]389            DO_2D( 0, 0, 0, 0 )
[12377]390               ikv = mikv(ji,jj)       ! (first wet ocean u- and v-points)
[13237]391               ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,ikv,Kmm)    &
392                  &             + r_vvl   * e3v(ji,jj,ikv,Kaa)   ! after scale factor at T-point
[14547]393               zwd(ji,jj,ikv) = zwd(ji,jj,ikv) - zDt_2*( rCdU_top(ji,jj+1)+rCdU_top(ji,jj) ) / ze3va
[12377]394            END_2D
[9019]395         ENDIF
396      ENDIF
[456]397
[9019]398      ! Matrix inversion
399      !-----------------------------------------------------------------------
400      !   solve m.x = y  where m is a tri diagonal matrix ( jpk*jpk )
[503]401      !
[9019]402      !        ( zwd1 zws1   0    0    0  )( zwx1 ) ( zwy1 )
403      !        ( zwi2 zwd2 zws2   0    0  )( zwx2 ) ( zwy2 )
404      !        (  0   zwi3 zwd3 zws3   0  )( zwx3 )=( zwy3 )
405      !        (        ...               )( ...  ) ( ...  )
406      !        (  0    0    0   zwik zwdk )( zwxk ) ( zwyk )
[503]407      !
[9019]408      !   m is decomposed in the product of an upper and lower triangular matrix
409      !   The 3 diagonal terms are in 2d arrays: zwd, zws, zwi
410      !   The solution (after velocity) is in 2d array va
411      !-----------------------------------------------------------------------
412      !
[13472]413      DO_3D( 0, 0, 0, 0, 2, jpkm1 )   !==  First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1   (increasing k)  ==
[12377]414         zwd(ji,jj,jk) = zwd(ji,jj,jk) - zwi(ji,jj,jk) * zws(ji,jj,jk-1) / zwd(ji,jj,jk-1)
415      END_3D
[9019]416      !
[13472]417      DO_2D( 0, 0, 0, 0 )             !==  second recurrence:    SOLk = RHSk - Lk / Dk-1  Lk-1  ==!
[13237]418         ze3va =  ( 1._wp - r_vvl ) * e3v(ji,jj,1,Kmm)    &
419            &             + r_vvl   * e3v(ji,jj,1,Kaa) 
[14547]420         pvv(ji,jj,1,Kaa) = pvv(ji,jj,1,Kaa) + zDt_2*( vtau_b(ji,jj) + vtau(ji,jj) )   &
[12489]421            &                                      / ( ze3va * rho0 ) * vmask(ji,jj,1) 
[12377]422      END_2D
[13295]423      DO_3D( 0, 0, 0, 0, 2, jpkm1 )
[12377]424         pvv(ji,jj,jk,Kaa) = pvv(ji,jj,jk,Kaa) - zwi(ji,jj,jk) / zwd(ji,jj,jk-1) * pvv(ji,jj,jk-1,Kaa)
425      END_3D
[9019]426      !
[13472]427      DO_2D( 0, 0, 0, 0 )             !==  third recurrence : SOLk = ( Lk - Uk * SOLk+1 ) / Dk  ==!
[12377]428         pvv(ji,jj,jpkm1,Kaa) = pvv(ji,jj,jpkm1,Kaa) / zwd(ji,jj,jpkm1)
429      END_2D
[13295]430      DO_3DS( 0, 0, 0, 0, jpk-2, 1, -1 )
[12377]431         pvv(ji,jj,jk,Kaa) = ( pvv(ji,jj,jk,Kaa) - zws(ji,jj,jk) * pvv(ji,jj,jk+1,Kaa) ) / zwd(ji,jj,jk)
432      END_3D
[9019]433      !
[503]434      IF( l_trddyn )   THEN                      ! save the vertical diffusive trends for further diagnostics
[14547]435         ztrdu(:,:,:) = ( puu(:,:,:,Kaa) - puu(:,:,:,Kbb) )*r1_Dt - ztrdu(:,:,:)
436         ztrdv(:,:,:) = ( pvv(:,:,:,Kaa) - pvv(:,:,:,Kbb) )*r1_Dt - ztrdv(:,:,:)
[12377]437         CALL trd_dyn( ztrdu, ztrdv, jpdyn_zdf, kt, Kmm )
[9019]438         DEALLOCATE( ztrdu, ztrdv ) 
[456]439      ENDIF
440      !                                          ! print mean trends (used for debugging)
[12377]441      IF(sn_cfctl%l_prtctl)   CALL prt_ctl( tab3d_1=puu(:,:,:,Kaa), clinfo1=' zdf  - Ua: ', mask1=umask,               &
442         &                                  tab3d_2=pvv(:,:,:,Kaa), clinfo2=       ' Va: ', mask2=vmask, clinfo3='dyn' )
[5836]443         !
[9019]444      IF( ln_timing )   CALL timing_stop('dyn_zdf')
[503]445      !
[456]446   END SUBROUTINE dyn_zdf
447
448   !!==============================================================================
449END MODULE dynzdf
Note: See TracBrowser for help on using the repository browser.