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.
dynnxt.F90 in trunk/NEMO/OPA_SRC/DYN – NEMO

source: trunk/NEMO/OPA_SRC/DYN/dynnxt.F90 @ 1566

Last change on this file since 1566 was 1566, checked in by rblod, 15 years ago

Cosmetic changes: suppress useless variables and code review of the code changed when suppressing rigid-lid, see ticket #508

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.5 KB
Line 
1MODULE dynnxt
2   !!=========================================================================
3   !!                       ***  MODULE  dynnxt  ***
4   !! Ocean dynamics: time stepping
5   !!=========================================================================
6   !! History :  OPA  !  1987-02  (P. Andrich, D. L Hostis)  Original code
7   !!                 !  1990-10  (C. Levy, G. Madec)
8   !!            7.0  !  1993-03  (M. Guyon)  symetrical conditions
9   !!            8.0  !  1997-02  (G. Madec & M. Imbard)  opa, release 8.0
10   !!            8.2  !  1997-04  (A. Weaver)  Euler forward step
11   !!             -   !  1997-06  (G. Madec)  lateral boudary cond., lbc routine
12   !!    NEMO    1.0  !  2002-08  (G. Madec)  F90: Free form and module
13   !!             -   !  2002-10  (C. Talandier, A-M. Treguier) Open boundary cond.
14   !!            2.0  !  2005-11  (V. Garnier) Surface pressure gradient organization
15   !!            2.3  !  2007-07  (D. Storkey) Calls to BDY routines.
16   !!            3.2  !  2009-06  (G. Madec, R.Benshila)  re-introduce the vvl option
17   !!-------------------------------------------------------------------------
18 
19   !!-------------------------------------------------------------------------
20   !!   dyn_nxt      : obtain the next (after) horizontal velocity
21   !!-------------------------------------------------------------------------
22   USE oce             ! ocean dynamics and tracers
23   USE dom_oce         ! ocean space and time domain
24   USE dynspg_oce      ! type of surface pressure gradient
25   USE dynadv          ! dynamics: vector invariant versus flux form
26   USE domvvl          ! variable volume
27   USE obc_oce         ! ocean open boundary conditions
28   USE obcdyn          ! open boundary condition for momentum (obc_dyn routine)
29   USE obcdyn_bt       ! 2D open boundary condition for momentum (obc_dyn_bt routine)
30   USE obcvol          ! ocean open boundary condition (obc_vol routines)
31   USE bdy_oce         ! unstructured open boundary conditions
32   USE bdydta          ! unstructured open boundary conditions
33   USE bdydyn          ! unstructured open boundary conditions
34   USE agrif_opa_update
35   USE agrif_opa_interp
36   USE in_out_manager  ! I/O manager
37   USE lbclnk          ! lateral boundary condition (or mpp link)
38   USE prtctl          ! Print control
39
40   IMPLICIT NONE
41   PRIVATE
42
43   PUBLIC    dyn_nxt   ! routine called by step.F90
44
45   !! * Substitutions
46#  include "domzgr_substitute.h90"
47   !!-------------------------------------------------------------------------
48   !! NEMO/OPA 3.2 , LOCEAN-IPSL (2009)
49   !! $Id$
50   !! Software is governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt)
51   !!-------------------------------------------------------------------------
52
53CONTAINS
54
55   SUBROUTINE dyn_nxt ( kt )
56      !!----------------------------------------------------------------------
57      !!                  ***  ROUTINE dyn_nxt  ***
58      !!                   
59      !! ** Purpose :   Compute the after horizontal velocity. Apply the boundary
60      !!             condition on the after velocity, achieved the time stepping
61      !!             by applying the Asselin filter on now fields and swapping
62      !!             the fields.
63      !!
64      !! ** Method  : * After velocity is compute using a leap-frog scheme:
65      !!                       (ua,va) = (ub,vb) + 2 rdt (ua,va)
66      !!             Note that with flux form advection and variable volume layer
67      !!             (lk_vvl=T), the leap-frog is applied on thickness weighted
68      !!             velocity.
69      !!             Note also that in filtered free surface (lk_dynspg_flt=T),
70      !!             the time stepping has already been done in dynspg module
71      !!
72      !!              * Apply lateral boundary conditions on after velocity
73      !!             at the local domain boundaries through lbc_lnk call,
74      !!             at the radiative open boundaries (lk_obc=T),
75      !!             at the relaxed   open boundaries (lk_bdy=T), and
76      !!             at the AGRIF zoom     boundaries (lk_agrif=T)
77      !!
78      !!              * Apply the time filter applied and swap of the dynamics
79      !!             arrays to start the next time step:
80      !!                (ub,vb) = (un,vn) + atfp [ (ub,vb) + (ua,va) - 2 (un,vn) ]
81      !!                (un,vn) = (ua,va).
82      !!             Note that with flux form advection and variable volume layer
83      !!             (lk_vvl=T), the time filter is applied on thickness weighted
84      !!             velocity.
85      !!
86      !! ** Action :   ub,vb   filtered before horizontal velocity of next time-step
87      !!               un,vn   now horizontal velocity of next time-step
88      !!----------------------------------------------------------------------
89      INTEGER, INTENT( in ) ::   kt      ! ocean time-step index
90      !!
91      INTEGER  ::   ji, jj, jk   ! dummy loop indices
92#if ! defined key_dynspg_flt
93      REAL(wp) ::   z2dt         ! temporary scalar
94#endif
95      REAL(wp) ::   zue3a , zue3n , zue3b    ! temporary scalar
96      REAL(wp) ::   zve3a , zve3n , zve3b    !    -         -
97      REAL(wp) ::   ze3u_b, ze3u_n, ze3u_a   !    -         -
98      REAL(wp) ::   ze3v_b, ze3v_n, ze3v_a   !    -         -
99      REAL(wp) ::   zuf   , zvf              !    -         -
100      !!----------------------------------------------------------------------
101
102      IF( kt == nit000 ) THEN
103         IF(lwp) WRITE(numout,*)
104         IF(lwp) WRITE(numout,*) 'dyn_nxt : time stepping'
105         IF(lwp) WRITE(numout,*) '~~~~~~~'
106      ENDIF
107
108#if defined key_dynspg_flt
109      !
110      ! Next velocity :   Leap-frog time stepping already done in dynspg_flt.F routine
111      ! -------------
112
113      ! Update after velocity on domain lateral boundaries      (only local domain required)
114      ! --------------------------------------------------
115      CALL lbc_lnk( ua, 'U', -1. )         ! local domain boundaries
116      CALL lbc_lnk( va, 'V', -1. ) 
117      !
118#else
119      ! Next velocity :   Leap-frog time stepping
120      ! -------------
121      z2dt = 2. * rdt                                 ! Euler or leap-frog time step
122      IF( neuler == 0 .AND. kt == nit000 )  z2dt = rdt
123      !
124      IF( ln_dynadv_vec .OR. .NOT. lk_vvl ) THEN      ! applied on velocity
125         DO jk = 1, jpkm1
126            ua(:,:,jk) = ( ub(:,:,jk) + z2dt * ua(:,:,jk) ) * umask(:,:,jk)
127            va(:,:,jk) = ( vb(:,:,jk) + z2dt * va(:,:,jk) ) * vmask(:,:,jk)
128         END DO
129      ELSE                                            ! applied on thickness weighted velocity
130         DO jk = 1, jpkm1
131            ua(:,:,jk) = (          ub(:,:,jk) * fse3u_b(:,:,jk)      &
132               &           + z2dt * ua(:,:,jk) * fse3u_n(:,:,jk)  )   &
133               &         / fse3u_a(:,:,jk) * umask(:,:,jk)
134            va(:,:,jk) = (          vb(:,:,jk) * fse3v_b(:,:,jk)      &
135               &           + z2dt * va(:,:,jk) * fse3v_n(:,:,jk)  )   &
136               &         / fse3v_a(:,:,jk) * vmask(:,:,jk)
137         END DO
138      ENDIF
139
140
141      ! Update after velocity on domain lateral boundaries
142      ! --------------------------------------------------     
143      CALL lbc_lnk( ua, 'U', -1. )     !* local domain boundaries
144      CALL lbc_lnk( va, 'V', -1. ) 
145      !
146# if defined key_obc
147      !                                !* OBC open boundaries
148      CALL obc_dyn( kt )
149      !
150      IF ( lk_dynspg_exp .OR. lk_dynspg_ts ) THEN
151         ! Flather boundary condition : - Update sea surface height on each open boundary
152         !                                       sshn   (= after ssh   ) for explicit case
153         !                                       sshn_b (= after ssha_b) for time-splitting case
154         !                              - Correct the barotropic velocities
155         CALL obc_dyn_bt( kt )
156         !
157!!gm ERROR - potential BUG: sshn should not be modified at this stage !!   ssh_nxt not alrady called
158         CALL lbc_lnk( sshn, 'T', 1. )         ! Boundary conditions on sshn
159         !
160         IF( ln_vol_cst )   CALL obc_vol( kt )
161         !
162         IF(ln_ctl)   CALL prt_ctl( tab2d_1=sshn, clinfo1=' ssh      : ', mask1=tmask )
163      ENDIF
164      !
165# elif defined key_bdy 
166      !                                !* BDY open boundaries
167      IF( lk_dynspg_exp .OR. lk_dynspg_ts ) THEN       ! except for filtered option
168         !
169         CALL bdy_dyn_frs( kt )
170         !
171         IF( ln_bdy_dyn_fla ) THEN
172            ua_e(:,:) = 0.e0
173            va_e(:,:) = 0.e0
174            ! Set these variables for use in bdy_dyn_fla
175            hur_e(:,:) = hur(:,:)
176            hvr_e(:,:) = hvr(:,:)
177            DO jk = 1, jpkm1   !! Vertically integrated momentum trends
178               ua_e(:,:) = ua_e(:,:) + fse3u(:,:,jk) * umask(:,:,jk) * ua(:,:,jk)
179               va_e(:,:) = va_e(:,:) + fse3v(:,:,jk) * vmask(:,:,jk) * va(:,:,jk)
180            END DO
181            ua_e(:,:) = ua_e(:,:) * hur(:,:)
182            va_e(:,:) = va_e(:,:) * hvr(:,:)
183            DO jk = 1 , jpkm1
184               ua(:,:,jk) = ua(:,:,jk) - ua_e(:,:)
185               va(:,:,jk) = va(:,:,jk) - va_e(:,:)
186            END DO
187            CALL bdy_dta_bt( kt+1, 0)
188            CALL bdy_dyn_fla( sshn_b )
189            DO jk = 1 , jpkm1
190               ua(:,:,jk) = ( ua(:,:,jk) + ua_e(:,:) ) * umask(:,:,jk)
191               va(:,:,jk) = ( va(:,:,jk) + va_e(:,:) ) * vmask(:,:,jk)
192            END DO
193         ENDIF
194         !
195      ENDIF
196# endif
197      !
198# if defined key_agrif
199      CALL Agrif_dyn( kt )             !* AGRIF zoom boundaries
200# endif
201#endif
202
203      ! Time filter and swap of dynamics arrays
204      ! ------------------------------------------
205      IF( neuler == 0 .AND. kt == nit000 ) THEN        !* Euler at first time-step: only swap
206         DO jk = 1, jpkm1
207            un(:,:,jk) = ua(:,:,jk)                          ! un <-- ua
208            vn(:,:,jk) = va(:,:,jk)
209         END DO
210      ELSE                                             !* Leap-Frog : Asselin filter and swap
211         IF( ln_dynadv_vec .OR. .NOT. lk_vvl ) THEN          ! applied on velocity
212            DO jk = 1, jpkm1                             
213               DO jj = 1, jpj
214                  DO ji = 1, jpi   
215                     zuf = atfp * ( ub(ji,jj,jk) + ua(ji,jj,jk) ) + atfp1 * un(ji,jj,jk)
216                     zvf = atfp * ( vb(ji,jj,jk) + va(ji,jj,jk) ) + atfp1 * vn(ji,jj,jk)
217                     !
218                     ub(ji,jj,jk) = zuf                      ! ub <-- filtered velocity
219                     vb(ji,jj,jk) = zvf
220                     un(ji,jj,jk) = ua(ji,jj,jk)             ! un <-- ua
221                     vn(ji,jj,jk) = va(ji,jj,jk)
222                  END DO
223               END DO
224            END DO
225         ELSE                                                ! applied on thickness weighted velocity
226            DO jk = 1, jpkm1
227               DO jj = 1, jpj
228                  DO ji = 1, jpi
229                     ze3u_a = fse3u_a(ji,jj,jk)
230                     ze3v_a = fse3v_a(ji,jj,jk)
231                     ze3u_n = fse3u_n(ji,jj,jk)
232                     ze3v_n = fse3v_n(ji,jj,jk)
233                     ze3u_b = fse3u_b(ji,jj,jk)
234                     ze3v_b = fse3v_b(ji,jj,jk)
235                     !
236                     zue3a = ua(ji,jj,jk) * ze3u_a
237                     zve3a = va(ji,jj,jk) * ze3v_a
238                     zue3n = un(ji,jj,jk) * ze3u_n
239                     zve3n = vn(ji,jj,jk) * ze3v_n
240                     zue3b = ub(ji,jj,jk) * ze3u_b
241                     zve3b = vb(ji,jj,jk) * ze3v_b
242                     !
243                     zuf  = ( atfp  * ( zue3b  + zue3a  ) + atfp1 * zue3n  )   &
244                        & / ( atfp  * ( ze3u_b + ze3u_a ) + atfp1 * ze3u_n ) * umask(ji,jj,jk)
245                     zvf  = ( atfp  * ( zve3b  + zve3a  ) + atfp1 * zve3n  )   &
246                        & / ( atfp  * ( ze3v_b + ze3v_a ) + atfp1 * ze3v_n ) * vmask(ji,jj,jk)
247                     !
248                     ub(ji,jj,jk) = zuf                      ! ub <-- filtered velocity
249                     vb(ji,jj,jk) = zvf
250                     un(ji,jj,jk) = ua(ji,jj,jk)             ! un <-- ua
251                     vn(ji,jj,jk) = va(ji,jj,jk)
252                  END DO
253               END DO
254            END DO
255         ENDIF
256      ENDIF
257
258#if defined key_agrif
259      ! Update velocity at AGRIF zoom boundaries
260      IF (.NOT.Agrif_Root())    CALL Agrif_Update_Dyn( kt )
261#endif     
262
263      IF(ln_ctl)   CALL prt_ctl( tab3d_1=un, clinfo1=' nxt  - Un: ', mask1=umask,   &
264         &                       tab3d_2=vn, clinfo2=' Vn: '       , mask2=vmask )
265      !
266   END SUBROUTINE dyn_nxt
267
268   !!=========================================================================
269END MODULE dynnxt
Note: See TracBrowser for help on using the repository browser.