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 branches/UKMO/dev_r8126_LIM3_couple/NEMOGCM/NEMO/OPA_SRC/DYN – NEMO

source: branches/UKMO/dev_r8126_LIM3_couple/NEMOGCM/NEMO/OPA_SRC/DYN/dynzad.F90 @ 8877

Last change on this file since 8877 was 8877, checked in by frrh, 6 years ago

Clear out SVN keywords and properties.

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