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.
dynzad.F90 in NEMO/releases/release-3.6/NEMOGCM/NEMO/OPA_SRC/DYN – NEMO

source: NEMO/releases/release-3.6/NEMOGCM/NEMO/OPA_SRC/DYN/dynzad.F90 @ 9967

Last change on this file since 9967 was 9967, checked in by mathiot, 4 years ago

fix #2120 in 3.6_STABLE

  • Property svn:keywords set to Id
File size: 12.7 KB
Line 
1MODULE dynzad
2   !!======================================================================
3   !!                       ***  MODULE  dynzad  ***
4   !! Ocean dynamics : vertical advection trend
5   !!======================================================================
6   !! History :  OPA  ! 1991-01  (G. Madec) Original code
7   !!            7.0  ! 1991-11  (G. Madec)
8   !!            7.5  ! 1996-01  (G. Madec) statement function for e3
9   !!   NEMO     0.5  ! 2002-07  (G. Madec) Free form, F90
10   !!----------------------------------------------------------------------
11   
12   !!----------------------------------------------------------------------
13   !!   dyn_zad       : vertical advection momentum trend
14   !!----------------------------------------------------------------------
15   USE oce            ! ocean dynamics and tracers
16   USE dom_oce        ! ocean space and time domain
17   USE sbc_oce        ! surface boundary condition: ocean
18   USE trd_oce        ! trends: ocean variables
19   USE trddyn         ! trend manager: dynamics
20   !
21   USE in_out_manager ! I/O manager
22   USE lib_mpp        ! MPP library
23   USE prtctl         ! Print control
24   USE wrk_nemo       ! Memory Allocation
25   USE timing         ! Timing
26
27   IMPLICIT NONE
28   PRIVATE
29   
30   PUBLIC   dyn_zad       ! routine called by dynadv.F90
31   PUBLIC   dyn_zad_zts   ! routine called by dynadv.F90
32
33   !! * Substitutions
34#  include "domzgr_substitute.h90"
35#  include "vectopt_loop_substitute.h90"
36   !!----------------------------------------------------------------------
37   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
38   !! $Id$
39   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
40   !!----------------------------------------------------------------------
41CONTAINS
42
43   SUBROUTINE dyn_zad ( kt )
44      !!----------------------------------------------------------------------
45      !!                  ***  ROUTINE dynzad  ***
46      !!
47      !! ** Purpose :   Compute the now vertical momentum advection trend and
48      !!      add it to the general trend of momentum equation.
49      !!
50      !! ** Method  :   The now vertical advection of momentum is given by:
51      !!         w dz(u) = ua + 1/(e1u*e2u*e3u) mk+1[ mi(e1t*e2t*wn) dk(un) ]
52      !!         w dz(v) = va + 1/(e1v*e2v*e3v) mk+1[ mj(e1t*e2t*wn) dk(vn) ]
53      !!      Add this trend to the general trend (ua,va):
54      !!         (ua,va) = (ua,va) + w dz(u,v)
55      !!
56      !! ** Action  : - Update (ua,va) with the vert. momentum adv. trends
57      !!              - Send the trends to trddyn for diagnostics (l_trddyn=T)
58      !!----------------------------------------------------------------------
59      INTEGER, INTENT(in) ::   kt   ! ocean time-step inedx
60      !
61      INTEGER  ::   ji, jj, jk      ! dummy loop indices
62      REAL(wp) ::   zua, zva        ! temporary scalars
63      REAL(wp), POINTER, DIMENSION(:,:,:) ::  zwuw , zwvw
64      REAL(wp), POINTER, DIMENSION(:,:  ) ::  zww
65      REAL(wp), POINTER, DIMENSION(:,:,:) ::  ztrdu, ztrdv
66      !!----------------------------------------------------------------------
67      !
68      IF( nn_timing == 1 )  CALL timing_start('dyn_zad')
69      !
70      CALL wrk_alloc( jpi,jpj, zww ) 
71      CALL wrk_alloc( jpi,jpj,jpk, zwuw , zwvw ) 
72      !
73      IF( kt == nit000 ) THEN
74         IF(lwp)WRITE(numout,*)
75         IF(lwp)WRITE(numout,*) 'dyn_zad : arakawa advection scheme'
76      ENDIF
77
78      IF( l_trddyn )   THEN         ! Save ua and va trends
79         CALL wrk_alloc( jpi, jpj, jpk, ztrdu, ztrdv ) 
80         ztrdu(:,:,:) = ua(:,:,:) 
81         ztrdv(:,:,:) = va(:,:,:) 
82      ENDIF
83     
84      DO jk = 2, jpkm1              ! Vertical momentum advection at level w and u- and v- vertical
85         DO jj = 2, jpj                   ! vertical fluxes
86            DO ji = fs_2, jpi             ! vector opt.
87               zww(ji,jj) = 0.25_wp * e1t(ji,jj) * e2t(ji,jj) * wn(ji,jj,jk)
88            END DO
89         END DO
90         DO jj = 2, jpjm1                 ! vertical momentum advection at w-point
91            DO ji = fs_2, fs_jpim1        ! vector opt.
92               zwuw(ji,jj,jk) = ( zww(ji+1,jj  ) + zww(ji,jj) ) * ( un(ji,jj,jk-1)-un(ji,jj,jk) )
93               zwvw(ji,jj,jk) = ( zww(ji  ,jj+1) + zww(ji,jj) ) * ( vn(ji,jj,jk-1)-vn(ji,jj,jk) )
94            END DO 
95         END DO   
96      END DO
97      !
98      ! Surface and bottom advective fluxes set to zero
99      DO jj = 2, jpjm1       
100         DO ji = fs_2, fs_jpim1           ! vector opt.
101            zwuw(ji,jj, 1 ) = 0._wp
102            zwvw(ji,jj, 1 ) = 0._wp
103            zwuw(ji,jj,jpk) = 0._wp
104            zwvw(ji,jj,jpk) = 0._wp
105         END DO 
106      END DO
107
108      DO jk = 1, jpkm1              ! Vertical momentum advection at u- and v-points
109         DO jj = 2, jpjm1
110            DO ji = fs_2, fs_jpim1       ! vector opt.
111               !                         ! vertical momentum advective trends
112               zua = - ( zwuw(ji,jj,jk) + zwuw(ji,jj,jk+1) ) / ( e1u(ji,jj) * e2u(ji,jj) * fse3u(ji,jj,jk) )
113               zva = - ( zwvw(ji,jj,jk) + zwvw(ji,jj,jk+1) ) / ( e1v(ji,jj) * e2v(ji,jj) * fse3v(ji,jj,jk) )
114               !                         ! add the trends to the general momentum trends
115               ua(ji,jj,jk) = ua(ji,jj,jk) + zua
116               va(ji,jj,jk) = va(ji,jj,jk) + zva
117            END DO 
118         END DO 
119      END DO
120
121      IF( l_trddyn ) THEN           ! save the vertical advection trends for diagnostic
122         ztrdu(:,:,:) = ua(:,:,:) - ztrdu(:,:,:)
123         ztrdv(:,:,:) = va(:,:,:) - ztrdv(:,:,:)
124         CALL trd_dyn( ztrdu, ztrdv, jpdyn_zad, kt )
125         CALL wrk_dealloc( jpi, jpj, jpk, ztrdu, ztrdv ) 
126      ENDIF
127      !                             ! Control print
128      IF(ln_ctl)   CALL prt_ctl( tab3d_1=ua, clinfo1=' zad  - Ua: ', mask1=umask,   &
129         &                       tab3d_2=va, clinfo2=       ' Va: ', mask2=vmask, clinfo3='dyn' )
130      !
131      CALL wrk_dealloc( jpi,jpj, zww ) 
132      CALL wrk_dealloc( jpi,jpj,jpk, zwuw , zwvw ) 
133      !
134      IF( nn_timing == 1 )  CALL timing_stop('dyn_zad')
135      !
136   END SUBROUTINE dyn_zad
137
138   SUBROUTINE dyn_zad_zts ( kt )
139      !!----------------------------------------------------------------------
140      !!                  ***  ROUTINE dynzad_zts  ***
141      !!
142      !! ** Purpose :   Compute the now vertical momentum advection trend and
143      !!      add it to the general trend of momentum equation. This version
144      !!      uses sub-timesteps for improved numerical stability with small
145      !!      vertical grid sizes. This is especially relevant when using
146      !!      embedded ice with thin surface boxes.
147      !!
148      !! ** Method  :   The now vertical advection of momentum is given by:
149      !!         w dz(u) = ua + 1/(e1u*e2u*e3u) mk+1[ mi(e1t*e2t*wn) dk(un) ]
150      !!         w dz(v) = va + 1/(e1v*e2v*e3v) mk+1[ mj(e1t*e2t*wn) dk(vn) ]
151      !!      Add this trend to the general trend (ua,va):
152      !!         (ua,va) = (ua,va) + w dz(u,v)
153      !!
154      !! ** Action  : - Update (ua,va) with the vert. momentum adv. trends
155      !!              - Save the trends in (ztrdu,ztrdv) ('key_trddyn')
156      !!----------------------------------------------------------------------
157      INTEGER, INTENT(in) ::   kt   ! ocean time-step inedx
158      !
159      INTEGER  ::   ji, jj, jk, jl  ! dummy loop indices
160      INTEGER  ::   jnzts = 5       ! number of sub-timesteps for vertical advection
161      INTEGER  ::   jtb, jtn, jta   ! sub timestep pointers for leap-frog/euler forward steps
162      REAL(wp) ::   zua, zva        ! temporary scalars
163      REAL(wp) ::   zr_rdt          ! temporary scalar
164      REAL(wp) ::   z2dtzts         ! length of Euler forward sub-timestep for vertical advection
165      REAL(wp) ::   zts             ! length of sub-timestep for vertical advection
166      REAL(wp), POINTER, DIMENSION(:,:,:)   ::  zwuw , zwvw, zww
167      REAL(wp), POINTER, DIMENSION(:,:,:)   ::  ztrdu, ztrdv
168      REAL(wp), POINTER, DIMENSION(:,:,:,:) ::  zus , zvs
169      !!----------------------------------------------------------------------
170      !
171      IF( nn_timing == 1 )  CALL timing_start('dyn_zad_zts')
172      !
173      CALL wrk_alloc( jpi,jpj,jpk, zwuw , zwvw, zww ) 
174      CALL wrk_alloc( jpi,jpj,jpk,3, zus, zvs ) 
175      !
176      IF( kt == nit000 ) THEN
177         IF(lwp)WRITE(numout,*)
178         IF(lwp)WRITE(numout,*) 'dyn_zad_zts : arakawa advection scheme with sub-timesteps'
179      ENDIF
180
181      IF( l_trddyn )   THEN         ! Save ua and va trends
182         CALL wrk_alloc( jpi, jpj, jpk, ztrdu, ztrdv ) 
183         ztrdu(:,:,:) = ua(:,:,:) 
184         ztrdv(:,:,:) = va(:,:,:) 
185      ENDIF
186     
187      IF( neuler == 0 .AND. kt == nit000 ) THEN
188          z2dtzts =         rdt / REAL( jnzts, wp )   ! = rdt (restart with Euler time stepping)
189      ELSE
190          z2dtzts = 2._wp * rdt / REAL( jnzts, wp )   ! = 2 rdt (leapfrog)
191      ENDIF
192     
193      DO jk = 2, jpkm1                    ! Calculate and store vertical fluxes
194         DO jj = 2, jpj                   
195            DO ji = fs_2, jpi             ! vector opt.
196               zww(ji,jj,jk) = 0.25_wp * e1t(ji,jj) * e2t(ji,jj) * wn(ji,jj,jk)
197            END DO
198         END DO
199      END DO
200      !
201      ! Surface and bottom advective fluxes set to zero
202      DO jj = 2, jpjm1       
203         DO ji = fs_2, fs_jpim1           ! vector opt.
204            zwuw(ji,jj, 1 ) = 0._wp
205            zwvw(ji,jj, 1 ) = 0._wp
206            zwuw(ji,jj,jpk) = 0._wp
207            zwvw(ji,jj,jpk) = 0._wp
208         END DO 
209      END DO
210
211! Start with before values and use sub timestepping to reach after values
212
213      zus(:,:,:,1) = ub(:,:,:)
214      zvs(:,:,:,1) = vb(:,:,:)
215
216      DO jl = 1, jnzts                   ! Start of sub timestepping loop
217
218         IF( jl == 1 ) THEN              ! Euler forward to kick things off
219           jtb = 1   ;   jtn = 1   ;   jta = 2
220           zts = z2dtzts
221         ELSEIF( jl == 2 ) THEN          ! First leapfrog step
222           jtb = 1   ;   jtn = 2   ;   jta = 3
223           zts = 2._wp * z2dtzts
224         ELSE                            ! Shuffle pointers for subsequent leapfrog steps
225           jtb = MOD(jtb,3) + 1
226           jtn = MOD(jtn,3) + 1
227           jta = MOD(jta,3) + 1
228         ENDIF
229
230         DO jk = 2, jpkm1           ! Vertical momentum advection at level w and u- and v- vertical
231            DO jj = 2, jpjm1                 ! vertical momentum advection at w-point
232               DO ji = fs_2, fs_jpim1        ! vector opt.
233                  zwuw(ji,jj,jk) = ( zww(ji+1,jj  ,jk) + zww(ji,jj,jk) ) * ( zus(ji,jj,jk-1,jtn)-zus(ji,jj,jk,jtn) ) !* wumask(ji,jj,jk)
234                  zwvw(ji,jj,jk) = ( zww(ji  ,jj+1,jk) + zww(ji,jj,jk) ) * ( zvs(ji,jj,jk-1,jtn)-zvs(ji,jj,jk,jtn) ) !* wvmask(ji,jj,jk)
235               END DO 
236            END DO   
237         END DO
238         DO jk = 1, jpkm1           ! Vertical momentum advection at u- and v-points
239            DO jj = 2, jpjm1
240               DO ji = fs_2, fs_jpim1       ! vector opt.
241                  !                         ! vertical momentum advective trends
242                  zua = - ( zwuw(ji,jj,jk) + zwuw(ji,jj,jk+1) ) / ( e1u(ji,jj) * e2u(ji,jj) * fse3u(ji,jj,jk) )
243                  zva = - ( zwvw(ji,jj,jk) + zwvw(ji,jj,jk+1) ) / ( e1v(ji,jj) * e2v(ji,jj) * fse3v(ji,jj,jk) )
244                  zus(ji,jj,jk,jta) = zus(ji,jj,jk,jtb) + zua * zts
245                  zvs(ji,jj,jk,jta) = zvs(ji,jj,jk,jtb) + zva * zts
246               END DO 
247            END DO 
248         END DO
249
250      END DO      ! End of sub timestepping loop
251
252      zr_rdt = 1._wp / ( REAL( jnzts, wp ) * z2dtzts )
253      DO jk = 1, jpkm1              ! Recover trends over the outer timestep
254         DO jj = 2, jpjm1
255            DO ji = fs_2, fs_jpim1       ! vector opt.
256               !                         ! vertical momentum advective trends
257               !                         ! add the trends to the general momentum trends
258               ua(ji,jj,jk) = ua(ji,jj,jk) + ( zus(ji,jj,jk,jta) - ub(ji,jj,jk)) * zr_rdt
259               va(ji,jj,jk) = va(ji,jj,jk) + ( zvs(ji,jj,jk,jta) - vb(ji,jj,jk)) * zr_rdt
260            END DO 
261         END DO 
262      END DO
263
264      IF( l_trddyn ) THEN           ! save the vertical advection trends for diagnostic
265         ztrdu(:,:,:) = ua(:,:,:) - ztrdu(:,:,:)
266         ztrdv(:,:,:) = va(:,:,:) - ztrdv(:,:,:)
267         CALL trd_dyn( ztrdu, ztrdv, jpdyn_zad, kt )
268         CALL wrk_dealloc( jpi, jpj, jpk, ztrdu, ztrdv ) 
269      ENDIF
270      !                             ! Control print
271      IF(ln_ctl)   CALL prt_ctl( tab3d_1=ua, clinfo1=' zad  - Ua: ', mask1=umask,   &
272         &                       tab3d_2=va, clinfo2=       ' Va: ', mask2=vmask, clinfo3='dyn' )
273      !
274      CALL wrk_dealloc( jpi,jpj,jpk, zwuw , zwvw, zww ) 
275      CALL wrk_dealloc( jpi,jpj,jpk,3, zus, zvs ) 
276      !
277      IF( nn_timing == 1 )  CALL timing_stop('dyn_zad_zts')
278      !
279   END SUBROUTINE dyn_zad_zts
280
281   !!======================================================================
282END MODULE dynzad
Note: See TracBrowser for help on using the repository browser.