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_imp.F90 in branches/2014/dev_r4650_UKMO2_ice_shelves/NEMOGCM/NEMO/OPA_SRC/DYN – NEMO

source: branches/2014/dev_r4650_UKMO2_ice_shelves/NEMOGCM/NEMO/OPA_SRC/DYN/dynzdf_imp.F90 @ 4704

Last change on this file since 4704 was 4704, checked in by mathiot, 10 years ago

Ice Shelf: correction of minor bugs if running without ice shelf

  • Property svn:keywords set to Id
File size: 17.0 KB
RevLine 
[3]1MODULE dynzdf_imp
[2715]2   !!======================================================================
[3]3   !!                    ***  MODULE  dynzdf_imp  ***
4   !! Ocean dynamics:  vertical component(s) of the momentum mixing trend
[2715]5   !!======================================================================
[2528]6   !! History :  OPA  !  1990-10  (B. Blanke)  Original code
7   !!            8.0  !  1997-05  (G. Madec)  vertical component of isopycnal
[2715]8   !!   NEMO     0.5  !  2002-08  (G. Madec)  F90: Free form and module
[2528]9   !!            3.3  !  2010-04  (M. Leclair, G. Madec)  Forcing averaged over 2 time steps
[3294]10   !!            3.4  !  2012-01  (H. Liu) Semi-implicit bottom friction
[503]11   !!----------------------------------------------------------------------
[3]12
13   !!----------------------------------------------------------------------
[2715]14   !!   dyn_zdf_imp  : update the momentum trend with the vertical diffusion using a implicit time-stepping
[3]15   !!----------------------------------------------------------------------
16   USE oce             ! ocean dynamics and tracers
17   USE dom_oce         ! ocean space and time domain
[4292]18   USE domvvl          ! variable volume
[888]19   USE sbc_oce         ! surface boundary condition: ocean
20   USE zdf_oce         ! ocean vertical physics
[719]21   USE phycst          ! physical constants
[3]22   USE in_out_manager  ! I/O manager
[2715]23   USE lib_mpp         ! MPP library
[3294]24   USE zdfbfr          ! Bottom friction setup
25   USE wrk_nemo        ! Memory Allocation
26   USE timing          ! Timing
[4292]27   USE dynadv          ! dynamics: vector invariant versus flux form
[4354]28   USE dynspg_oce, ONLY: lk_dynspg_ts
[3]29
30   IMPLICIT NONE
31   PRIVATE
32
[2528]33   PUBLIC   dyn_zdf_imp   ! called by step.F90
[3]34
[4292]35   REAL(wp) ::  r_vvl     ! variable volume indicator, =1 if lk_vvl=T, =0 otherwise
36
[3]37   !! * Substitutions
38#  include "domzgr_substitute.h90"
39#  include "vectopt_loop_substitute.h90"
40   !!----------------------------------------------------------------------
[2528]41   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
[888]42   !! $Id$
[2528]43   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
[3]44   !!----------------------------------------------------------------------
45CONTAINS
46
[503]47   SUBROUTINE dyn_zdf_imp( kt, p2dt )
[3]48      !!----------------------------------------------------------------------
49      !!                  ***  ROUTINE dyn_zdf_imp  ***
50      !!                   
51      !! ** Purpose :   Compute the trend due to the vert. momentum diffusion
52      !!      and the surface forcing, and add it to the general trend of
53      !!      the momentum equations.
54      !!
55      !! ** Method  :   The vertical momentum mixing trend is given by :
56      !!             dz( avmu dz(u) ) = 1/e3u dk+1( avmu/e3uw dk(ua) )
57      !!      backward time stepping
[2528]58      !!      Surface boundary conditions: wind stress input (averaged over kt-1/2 & kt+1/2)
[3]59      !!      Bottom boundary conditions : bottom stress (cf zdfbfr.F)
60      !!      Add this trend to the general trend ua :
61      !!         ua = ua + dz( avmu dz(u) )
62      !!
[2528]63      !! ** Action : - Update (ua,va) arrays with the after vertical diffusive mixing trend.
[3]64      !!---------------------------------------------------------------------
[3294]65      INTEGER , INTENT(in) ::  kt     ! ocean time-step index
[2715]66      REAL(wp), INTENT(in) ::  p2dt   ! vertical profile of tracer time-step
[2528]67      !!
[2715]68      INTEGER  ::   ji, jj, jk   ! dummy loop indices
[3294]69      INTEGER  ::   ikbu, ikbv   ! local integers
[2715]70      REAL(wp) ::   z1_p2dt, zcoef, zzwi, zzws, zrhs   ! local scalars
[4292]71      REAL(wp) ::   ze3ua, ze3va
[3]72      !!----------------------------------------------------------------------
73
[3294]74      REAL(wp), POINTER, DIMENSION(:,:,:) ::  zwi, zwd, zws
75      !!----------------------------------------------------------------------
76      !
77      IF( nn_timing == 1 )  CALL timing_start('dyn_zdf_imp')
78      !
79      CALL wrk_alloc( jpi,jpj,jpk, zwi, zwd, zws ) 
80      !
[3]81      IF( kt == nit000 ) THEN
82         IF(lwp) WRITE(numout,*)
83         IF(lwp) WRITE(numout,*) 'dyn_zdf_imp : vertical momentum diffusion implicit operator'
84         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~ '
[4292]85         !
86         IF( lk_vvl ) THEN   ;    r_vvl = 1._wp       ! Variable volume indicator
87         ELSE                ;    r_vvl = 0._wp       
88         ENDIF
[3]89      ENDIF
90
91      ! 0. Local constant initialization
92      ! --------------------------------
[2528]93      z1_p2dt = 1._wp / p2dt      ! inverse of the timestep
[455]94
[3294]95      ! 1. Apply semi-implicit bottom friction
96      ! --------------------------------------
97      ! Only needed for semi-implicit bottom friction setup. The explicit
98      ! bottom friction has been included in "u(v)a" which act as the R.H.S
99      ! column vector of the tri-diagonal matrix equation
100      !
101
102      IF( ln_bfrimp ) THEN
103# if defined key_vectopt_loop
[4292]104         DO jj = 1, 1
105            DO ji = jpi+2, jpij-jpi-1   ! vector opt. (forced unrolling)
[3294]106# else
[4292]107         DO jj = 2, jpjm1
108            DO ji = 2, jpim1
[3294]109# endif
[4292]110               ikbu = mbku(ji,jj)       ! ocean bottom level at u- and v-points
111               ikbv = mbkv(ji,jj)       ! (deepest ocean u- and v-points)
112               avmu(ji,jj,ikbu+1) = -bfrua(ji,jj) * fse3uw(ji,jj,ikbu+1)
113               avmv(ji,jj,ikbv+1) = -bfrva(ji,jj) * fse3vw(ji,jj,ikbv+1)
[4666]114               ikbu = miku(ji,jj)       ! ocean top level at u- and v-points
115               ikbv = mikv(ji,jj)       ! (first wet ocean u- and v-points)
[4704]116               IF (ikbu .GE. 2) avmu(ji,jj,ikbu-1) = -tfrua(ji,jj) * fse3uw(ji,jj,ikbu-1)
117               IF (ikbv .GE. 2) avmv(ji,jj,ikbv-1) = -tfrva(ji,jj) * fse3vw(ji,jj,ikbv-1)
[4292]118            END DO
[3294]119         END DO
120      ENDIF
121
[4292]122#if defined key_dynspg_ts
123      IF( ln_dynadv_vec .OR. .NOT. lk_vvl ) THEN      ! applied on velocity
124         DO jk = 1, jpkm1
125            ua(:,:,jk) = ( ub(:,:,jk) + p2dt * ua(:,:,jk) ) * umask(:,:,jk)
126            va(:,:,jk) = ( vb(:,:,jk) + p2dt * va(:,:,jk) ) * vmask(:,:,jk)
127         END DO
128      ELSE                                            ! applied on thickness weighted velocity
129         DO jk = 1, jpkm1
130            ua(:,:,jk) = (          ub(:,:,jk) * fse3u_b(:,:,jk)      &
131               &           + p2dt * ua(:,:,jk) * fse3u_n(:,:,jk)  )   &
132               &                               / fse3u_a(:,:,jk) * umask(:,:,jk)
133            va(:,:,jk) = (          vb(:,:,jk) * fse3v_b(:,:,jk)      &
134               &           + p2dt * va(:,:,jk) * fse3v_n(:,:,jk)  )   &
135               &                               / fse3v_a(:,:,jk) * vmask(:,:,jk)
136         END DO
137      ENDIF
138
139      IF ( ln_bfrimp .AND.lk_dynspg_ts ) THEN
140         ! remove barotropic velocities:
141         DO jk = 1, jpkm1
142            ua(:,:,jk) = (ua(:,:,jk) - ua_b(:,:)) * umask(:,:,jk)
143            va(:,:,jk) = (va(:,:,jk) - va_b(:,:)) * vmask(:,:,jk)
144         ENDDO
[4666]145         ! Add bottom/top stress due to barotropic component only:
[4292]146         DO jj = 2, jpjm1       
147            DO ji = fs_2, fs_jpim1   ! vector opt.
148               ikbu = mbku(ji,jj)         ! ocean bottom level at u- and v-points
149               ikbv = mbkv(ji,jj)         ! (deepest ocean u- and v-points)
150               ze3ua =  ( 1._wp - r_vvl ) * fse3u_n(ji,jj,ikbu) + r_vvl   * fse3u_a(ji,jj,ikbu)
151               ze3va =  ( 1._wp - r_vvl ) * fse3v_n(ji,jj,ikbv) + r_vvl   * fse3v_a(ji,jj,ikbv)
152               ua(ji,jj,ikbu) = ua(ji,jj,ikbu) + p2dt * bfrua(ji,jj) * ua_b(ji,jj) / ze3ua
153               va(ji,jj,ikbv) = va(ji,jj,ikbv) + p2dt * bfrva(ji,jj) * va_b(ji,jj) / ze3va
[4704]154               ikbu = miku(ji,jj)         ! top ocean level at u- and v-points
155               ikbv = mikv(ji,jj)         ! (first wet ocean u- and v-points)
[4666]156               ze3ua =  ( 1._wp - r_vvl ) * fse3u_n(ji,jj,ikbu) + r_vvl   * fse3u_a(ji,jj,ikbu)
157               ze3va =  ( 1._wp - r_vvl ) * fse3v_n(ji,jj,ikbv) + r_vvl   * fse3v_a(ji,jj,ikbv)
158               ua(ji,jj,ikbu) = ua(ji,jj,ikbu) + p2dt * tfrua(ji,jj) * ua_b(ji,jj) / ze3ua
159               va(ji,jj,ikbv) = va(ji,jj,ikbv) + p2dt * tfrva(ji,jj) * va_b(ji,jj) / ze3va
[4292]160            END DO
161         END DO
162      ENDIF
163#endif
164
[3294]165      ! 2. Vertical diffusion on u
[3]166      ! ---------------------------
167      ! Matrix and second member construction
[1662]168      ! bottom boundary condition: both zwi and zws must be masked as avmu can take
[3294]169      ! non zero value at the ocean bottom depending on the bottom friction used.
[2528]170      !
171      DO jk = 1, jpkm1        ! Matrix
[3]172         DO jj = 2, jpjm1 
173            DO ji = fs_2, fs_jpim1   ! vector opt.
[4292]174               ze3ua =  ( 1._wp - r_vvl ) * fse3u_n(ji,jj,jk) + r_vvl   * fse3u_a(ji,jj,jk)   ! after scale factor at T-point
175               zcoef = - p2dt / ze3ua     
[2528]176               zzwi          = zcoef * avmu (ji,jj,jk  ) / fse3uw(ji,jj,jk  )
177               zwi(ji,jj,jk) = zzwi  * umask(ji,jj,jk)
178               zzws          = zcoef * avmu (ji,jj,jk+1) / fse3uw(ji,jj,jk+1)
179               zws(ji,jj,jk) = zzws  * umask(ji,jj,jk+1)
180               zwd(ji,jj,jk) = 1._wp - zwi(ji,jj,jk) - zzws
[3]181            END DO
182         END DO
183      END DO
[4292]184      DO jj = 2, jpjm1        ! Surface boundary conditions
[3]185         DO ji = fs_2, fs_jpim1   ! vector opt.
[4666]186            zwi(ji,jj,miku(ji,jj)) = 0._wp
187            zwd(ji,jj,miku(ji,jj)) = 1._wp - zws(ji,jj,miku(ji,jj))
[3]188         END DO
189      END DO
190
191      ! Matrix inversion starting from the first level
192      !-----------------------------------------------------------------------
193      !   solve m.x = y  where m is a tri diagonal matrix ( jpk*jpk )
194      !
195      !        ( zwd1 zws1   0    0    0  )( zwx1 ) ( zwy1 )
196      !        ( zwi2 zwd2 zws2   0    0  )( zwx2 ) ( zwy2 )
197      !        (  0   zwi3 zwd3 zws3   0  )( zwx3 )=( zwy3 )
198      !        (        ...               )( ...  ) ( ...  )
199      !        (  0    0    0   zwik zwdk )( zwxk ) ( zwyk )
200      !
201      !   m is decomposed in the product of an upper and a lower triangular matrix
202      !   The 3 diagonal terms are in 2d arrays: zwd, zws, zwi
203      !   The solution (the after velocity) is in ua
204      !-----------------------------------------------------------------------
[2528]205      !
[4666]206      !==  First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1   (increasing k)  ==
207      DO jj = 2, jpjm1   
208         DO ji = fs_2, fs_jpim1   ! vector opt.
209            DO jk = miku(ji,jj)+1, jpkm1
[3]210               zwd(ji,jj,jk) = zwd(ji,jj,jk) - zwi(ji,jj,jk) * zws(ji,jj,jk-1) / zwd(ji,jj,jk-1)
211            END DO
212         END DO
213      END DO
[2528]214      !
215      DO jj = 2, jpjm1        !==  second recurrence:    SOLk = RHSk - Lk / Dk-1  Lk-1  ==
[3]216         DO ji = fs_2, fs_jpim1   ! vector opt.
[4666]217            ze3ua =  ( 1._wp - r_vvl ) * fse3u_n(ji,jj,miku(ji,jj)) + r_vvl   * fse3u_a(ji,jj,miku(ji,jj)) 
[4292]218#if defined key_dynspg_ts
[4666]219            ua(ji,jj,miku(ji,jj)) = ua(ji,jj,miku(ji,jj)) + p2dt * 0.5_wp * ( utau_b(ji,jj) + utau(ji,jj) )   &
[4292]220               &                                      / ( ze3ua * rau0 ) 
221#else
[4666]222            ua(ji,jj,miku(ji,jj)) = ub(ji,jj,miku(ji,jj)) + p2dt *(ua(ji,jj,miku(ji,jj)) +  0.5_wp * ( utau_b(ji,jj) + utau(ji,jj) )   &
223               &                                                     / ( fse3u(ji,jj,miku(ji,jj)) * rau0     ) ) 
[4292]224#endif
[4666]225            DO jk = miku(ji,jj)+1, jpkm1
[4292]226#if defined key_dynspg_ts
227               zrhs = ua(ji,jj,jk)   ! zrhs=right hand side
228#else
229               zrhs = ub(ji,jj,jk) + p2dt * ua(ji,jj,jk)
230#endif
[3]231               ua(ji,jj,jk) = zrhs - zwi(ji,jj,jk) / zwd(ji,jj,jk-1) * ua(ji,jj,jk-1)
232            END DO
233         END DO
234      END DO
[2528]235      !
236      DO jj = 2, jpjm1        !==  thrid recurrence : SOLk = ( Lk - Uk * Ek+1 ) / Dk  ==
[3]237         DO ji = fs_2, fs_jpim1   ! vector opt.
238            ua(ji,jj,jpkm1) = ua(ji,jj,jpkm1) / zwd(ji,jj,jpkm1)
[4666]239            DO jk = jpk-2, miku(ji,jj), -1
[2528]240               ua(ji,jj,jk) = ( ua(ji,jj,jk) - zws(ji,jj,jk) * ua(ji,jj,jk+1) ) / zwd(ji,jj,jk)
[3]241            END DO
242         END DO
243      END DO
244
[4292]245#if ! defined key_dynspg_ts
[3]246      ! Normalization to obtain the general momentum trend ua
247      DO jk = 1, jpkm1
248         DO jj = 2, jpjm1   
249            DO ji = fs_2, fs_jpim1   ! vector opt.
[2528]250               ua(ji,jj,jk) = ( ua(ji,jj,jk) - ub(ji,jj,jk) ) * z1_p2dt
[3]251            END DO
252         END DO
253      END DO
[4292]254#endif
[3]255
[3294]256      ! 3. Vertical diffusion on v
[3]257      ! ---------------------------
258      ! Matrix and second member construction
[1662]259      ! bottom boundary condition: both zwi and zws must be masked as avmv can take
[3294]260      ! non zero value at the ocean bottom depending on the bottom friction used
[2528]261      !
262      DO jk = 1, jpkm1        ! Matrix
[3]263         DO jj = 2, jpjm1   
264            DO ji = fs_2, fs_jpim1   ! vector opt.
[4292]265               ze3va =  ( 1._wp - r_vvl ) * fse3v_n(ji,jj,jk)  + r_vvl * fse3v_a(ji,jj,jk)   ! after scale factor at T-point
266               zcoef = - p2dt / ze3va
[2528]267               zzwi          = zcoef * avmv (ji,jj,jk  ) / fse3vw(ji,jj,jk  )
[1662]268               zwi(ji,jj,jk) =  zzwi * vmask(ji,jj,jk)
[2528]269               zzws          = zcoef * avmv (ji,jj,jk+1) / fse3vw(ji,jj,jk+1)
[3]270               zws(ji,jj,jk) =  zzws * vmask(ji,jj,jk+1)
[2528]271               zwd(ji,jj,jk) = 1._wp - zwi(ji,jj,jk) - zzws
[3]272            END DO
273         END DO
274      END DO
[4292]275      DO jj = 2, jpjm1        ! Surface boundary conditions
[3]276         DO ji = fs_2, fs_jpim1   ! vector opt.
[4666]277            zwi(ji,jj,mikv(ji,jj)) = 0._wp
278            zwd(ji,jj,mikv(ji,jj)) = 1._wp - zws(ji,jj,mikv(ji,jj))
[3]279         END DO
280      END DO
281
282      ! Matrix inversion
283      !-----------------------------------------------------------------------
284      !   solve m.x = y  where m is a tri diagonal matrix ( jpk*jpk )
285      !
286      !        ( zwd1 zws1   0    0    0  )( zwx1 ) ( zwy1 )
287      !        ( zwi2 zwd2 zws2   0    0  )( zwx2 ) ( zwy2 )
288      !        (  0   zwi3 zwd3 zws3   0  )( zwx3 )=( zwy3 )
289      !        (        ...               )( ...  ) ( ...  )
290      !        (  0    0    0   zwik zwdk )( zwxk ) ( zwyk )
291      !
[2528]292      !   m is decomposed in the product of an upper and lower triangular matrix
[3]293      !   The 3 diagonal terms are in 2d arrays: zwd, zws, zwi
294      !   The solution (after velocity) is in 2d array va
295      !-----------------------------------------------------------------------
[2528]296      !
[4666]297      !==  First recurrence : Dk = Dk - Lk * Uk-1 / Dk-1   (increasing k)  ==
298      DO jj = 2, jpjm1   
299         DO ji = fs_2, fs_jpim1   ! vector opt.
300            DO jk = mikv(ji,jj)+1, jpkm1       
[3]301               zwd(ji,jj,jk) = zwd(ji,jj,jk) - zwi(ji,jj,jk) * zws(ji,jj,jk-1) / zwd(ji,jj,jk-1)
302            END DO
303         END DO
304      END DO
[2528]305      !
306      DO jj = 2, jpjm1        !==  second recurrence:    SOLk = RHSk - Lk / Dk-1  Lk-1  ==
[3]307         DO ji = fs_2, fs_jpim1   ! vector opt.
[4292]308            ze3va =  ( 1._wp - r_vvl ) * fse3v_n(ji,jj,1) + r_vvl   * fse3v_a(ji,jj,1) 
309#if defined key_dynspg_ts           
[4666]310            va(ji,jj,mikv(ji,jj)) = va(ji,jj,mikv(ji,jj)) + p2dt * 0.5_wp * ( vtau_b(ji,jj) + vtau(ji,jj) )   &
[4292]311               &                                      / ( ze3va * rau0 ) 
312#else
[4666]313            va(ji,jj,mikv(ji,jj)) = vb(ji,jj,mikv(ji,jj)) + p2dt *(va(ji,jj,mikv(ji,jj)) +  0.5_wp * ( vtau_b(ji,jj) + vtau(ji,jj) )   &
314               &                                                       / ( fse3v(ji,jj,mikv(ji,jj)) * rau0     )  )
[4292]315#endif
[4666]316            DO jk = mikv(ji,jj)+1, jpkm1
[4292]317#if defined key_dynspg_ts
318               zrhs = va(ji,jj,jk)   ! zrhs=right hand side
319#else
320               zrhs = vb(ji,jj,jk) + p2dt * va(ji,jj,jk)
321#endif
[3]322               va(ji,jj,jk) = zrhs - zwi(ji,jj,jk) / zwd(ji,jj,jk-1) * va(ji,jj,jk-1)
323            END DO
324         END DO
325      END DO
[2528]326      !
[4292]327      DO jj = 2, jpjm1        !==  third recurrence : SOLk = ( Lk - Uk * SOLk+1 ) / Dk  ==
[3]328         DO ji = fs_2, fs_jpim1   ! vector opt.
329            va(ji,jj,jpkm1) = va(ji,jj,jpkm1) / zwd(ji,jj,jpkm1)
[4666]330            DO jk = jpk-2, mikv(ji,jj), -1
[2528]331               va(ji,jj,jk) = ( va(ji,jj,jk) - zws(ji,jj,jk) * va(ji,jj,jk+1) ) / zwd(ji,jj,jk)
[3]332            END DO
333         END DO
334      END DO
335
336      ! Normalization to obtain the general momentum trend va
[4292]337#if ! defined key_dynspg_ts
[3]338      DO jk = 1, jpkm1
339         DO jj = 2, jpjm1   
340            DO ji = fs_2, fs_jpim1   ! vector opt.
[2528]341               va(ji,jj,jk) = ( va(ji,jj,jk) - vb(ji,jj,jk) ) * z1_p2dt
[3]342            END DO
343         END DO
344      END DO
[4292]345#endif
[3294]346
[4292]347      ! J. Chanut: Lines below are useless ?
[3294]348      !! restore bottom layer avmu(v)
349      IF( ln_bfrimp ) THEN
350# if defined key_vectopt_loop
351      DO jj = 1, 1
352         DO ji = jpi+2, jpij-jpi-1   ! vector opt. (forced unrolling)
353# else
354      DO jj = 2, jpjm1
355         DO ji = 2, jpim1
356# endif
357            ikbu = mbku(ji,jj)         ! ocean bottom level at u- and v-points
358            ikbv = mbkv(ji,jj)         ! (deepest ocean u- and v-points)
[4292]359            avmu(ji,jj,ikbu+1) = 0.e0
360            avmv(ji,jj,ikbv+1) = 0.e0
[4666]361            ikbu = miku(ji,jj)         ! ocean top level at u- and v-points
362            ikbv = mikv(ji,jj)         ! (first wet ocean u- and v-points)
363            avmu(ji,jj,ikbu-1) = 0.e0
364            avmv(ji,jj,ikbv-1) = 0.e0
[3294]365         END DO
366      END DO
367      ENDIF
[2528]368      !
[3294]369      CALL wrk_dealloc( jpi,jpj,jpk, zwi, zwd, zws) 
[2715]370      !
[3294]371      IF( nn_timing == 1 )  CALL timing_stop('dyn_zdf_imp')
372      !
[3]373   END SUBROUTINE dyn_zdf_imp
374
375   !!==============================================================================
376END MODULE dynzdf_imp
Note: See TracBrowser for help on using the repository browser.