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 @ 1502

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

Update dynnxt and dynspg_ts for variable volume, see ticket #474

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.4 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      REAL(wp) ::   z2dt         ! temporary scalar
93      REAL(wp) ::   zue3a , zue3n , zue3b    ! temporary scalar
94      REAL(wp) ::   zve3a , zve3n , zve3b    !    -         -
95      REAL(wp) ::   ze3u_b, ze3u_n, ze3u_a   !    -         -
96      REAL(wp) ::   ze3v_b, ze3v_n, ze3v_a   !    -         -
97      REAL(wp) ::   zuf   , zvf              !    -         -
98      !!----------------------------------------------------------------------
99
100      IF( kt == nit000 ) THEN
101         IF(lwp) WRITE(numout,*)
102         IF(lwp) WRITE(numout,*) 'dyn_nxt : time stepping'
103         IF(lwp) WRITE(numout,*) '~~~~~~~'
104      ENDIF
105
106#if defined key_dynspg_flt
107      !
108      ! Next velocity :   Leap-frog time stepping already done in dynspg_flt.F routine
109      ! -------------
110
111      ! Update after velocity on domain lateral boundaries      (only local domain required)
112      ! --------------------------------------------------
113      CALL lbc_lnk( ua, 'U', -1. )         ! local domain boundaries
114      CALL lbc_lnk( va, 'V', -1. ) 
115      !
116#else
117      ! Next velocity :   Leap-frog time stepping
118      ! -------------
119      z2dt = 2. * rdt                                 ! Euler or leap-frog time step
120      IF( neuler == 0 .AND. kt == nit000 )  z2dt = rdt
121      !
122      IF( ln_dynadv_vec .OR. .NOT. lk_vvl ) THEN      ! applied on velocity
123         DO jk = 1, jpkm1
124            ua(:,:,jk) = ( ub(:,:,jk) + z2dt * ua(:,:,jk) ) * umask(:,:,jk)
125            va(:,:,jk) = ( vb(:,:,jk) + z2dt * va(:,:,jk) ) * vmask(:,:,jk)
126         END DO
127      ELSE                                            ! applied on thickness weighted velocity
128         DO jk = 1, jpkm1
129            ua(:,:,jk) = (          ub(:,:,jk) * fse3u_b(:,:,jk)      &
130               &           + z2dt * ua(:,:,jk) * fse3u_n(:,:,jk)  )   &
131               &         / fse3u_a(:,:,jk) * umask(:,:,jk)
132            va(:,:,jk) = (          vb(:,:,jk) * fse3v_b(:,:,jk)      &
133               &           + z2dt * va(:,:,jk) * fse3v_n(:,:,jk)  )   &
134               &         / fse3v_a(:,:,jk) * vmask(:,:,jk)
135         END DO
136      ENDIF
137
138
139      ! Update after velocity on domain lateral boundaries
140      ! --------------------------------------------------     
141      CALL lbc_lnk( ua, 'U', -1. )     !* local domain boundaries
142      CALL lbc_lnk( va, 'V', -1. ) 
143      !
144# if defined key_obc
145      !                                !* OBC open boundaries
146      CALL obc_dyn( kt )
147      !
148      IF ( lk_dynspg_exp .OR. lk_dynspg_ts ) THEN
149         ! Flather boundary condition : - Update sea surface height on each open boundary
150         !                                       sshn   (= after ssh   ) for explicit case
151         !                                       sshn_b (= after ssha_b) for time-splitting case
152         !                              - Correct the barotropic velocities
153         CALL obc_dyn_bt( kt )
154         !
155!!gm ERROR - potential BUG: sshn should not be modified at this stage !!   ssh_nxt not alrady called
156         CALL lbc_lnk( sshn, 'T', 1. )         ! Boundary conditions on sshn
157         !
158         IF( ln_vol_cst )   CALL obc_vol( kt )
159         !
160         IF(ln_ctl)   CALL prt_ctl( tab2d_1=sshn, clinfo1=' ssh      : ', mask1=tmask )
161      ENDIF
162      !
163# elif defined key_bdy 
164      !                                !* BDY open boundaries
165      IF( lk_dynspg_exp .OR. lk_dynspg_ts ) THEN       ! except for filtered option
166         !
167         CALL bdy_dyn_frs( kt )
168         !
169         IF( ln_bdy_dyn_fla ) THEN
170            ua_e(:,:) = 0.e0
171            va_e(:,:) = 0.e0
172            ! Set these variables for use in bdy_dyn_fla
173            hur_e(:,:) = hur(:,:)
174            hvr_e(:,:) = hvr(:,:)
175            DO jk = 1, jpkm1   !! Vertically integrated momentum trends
176               ua_e(:,:) = ua_e(:,:) + fse3u(:,:,jk) * umask(:,:,jk) * ua(:,:,jk)
177               va_e(:,:) = va_e(:,:) + fse3v(:,:,jk) * vmask(:,:,jk) * va(:,:,jk)
178            END DO
179            ua_e(:,:) = ua_e(:,:) * hur(:,:)
180            va_e(:,:) = va_e(:,:) * hvr(:,:)
181            DO jk = 1 , jpkm1
182               ua(:,:,jk) = ua(:,:,jk) - ua_e(:,:)
183               va(:,:,jk) = va(:,:,jk) - va_e(:,:)
184            END DO
185            CALL bdy_dta_bt( kt+1, 0)
186            CALL bdy_dyn_fla( sshn_b )
187            DO jk = 1 , jpkm1
188               ua(:,:,jk) = ( ua(:,:,jk) + ua_e(:,:) ) * umask(:,:,jk)
189               va(:,:,jk) = ( va(:,:,jk) + va_e(:,:) ) * vmask(:,:,jk)
190            END DO
191         ENDIF
192         !
193      ENDIF
194# endif
195      !
196# if defined key_agrif
197      CALL Agrif_dyn( kt )             !* AGRIF zoom boundaries
198# endif
199#endif
200
201      ! Time filter and swap of dynamics arrays
202      ! ------------------------------------------
203      IF( neuler == 0 .AND. kt == nit000 ) THEN        !* Euler at first time-step: only swap
204         DO jk = 1, jpkm1
205            un(:,:,jk) = ua(:,:,jk)                          ! un <-- ua
206            vn(:,:,jk) = va(:,:,jk)
207         END DO
208      ELSE                                             !* Leap-Frog : Asselin filter and swap
209         IF( ln_dynadv_vec .OR. .NOT. lk_vvl ) THEN          ! applied on velocity
210            DO jk = 1, jpkm1                             
211               DO jj = 1, jpj
212                  DO ji = 1, jpi   
213                     zuf = atfp * ( ub(ji,jj,jk) + ua(ji,jj,jk) ) + atfp1 * un(ji,jj,jk)
214                     zvf = atfp * ( vb(ji,jj,jk) + va(ji,jj,jk) ) + atfp1 * vn(ji,jj,jk)
215                     !
216                     ub(ji,jj,jk) = zuf                      ! ub <-- filtered velocity
217                     vb(ji,jj,jk) = zvf
218                     un(ji,jj,jk) = ua(ji,jj,jk)             ! un <-- ua
219                     vn(ji,jj,jk) = va(ji,jj,jk)
220                  END DO
221               END DO
222            END DO
223         ELSE                                                ! applied on thickness weighted velocity
224            DO jk = 1, jpkm1
225               DO jj = 1, jpj
226                  DO ji = 1, jpi
227                     ze3u_a = fse3u_a(ji,jj,jk)
228                     ze3v_a = fse3v_a(ji,jj,jk)
229                     ze3u_n = fse3u_n(ji,jj,jk)
230                     ze3v_n = fse3v_n(ji,jj,jk)
231                     ze3u_b = fse3u_b(ji,jj,jk)
232                     ze3v_b = fse3v_b(ji,jj,jk)
233                     !
234                     zue3a = ua(ji,jj,jk) * ze3u_a
235                     zve3a = va(ji,jj,jk) * ze3v_a
236                     zue3n = un(ji,jj,jk) * ze3u_n
237                     zve3n = vn(ji,jj,jk) * ze3v_n
238                     zue3b = ub(ji,jj,jk) * ze3u_b
239                     zve3b = vb(ji,jj,jk) * ze3v_b
240                     !
241                     zuf  = ( atfp  * ( zue3b  + zue3a  ) + atfp1 * zue3n  )   &
242                        & / ( atfp  * ( ze3u_b + ze3u_a ) + atfp1 * ze3u_n ) * umask(ji,jj,jk)
243                     zvf  = ( atfp  * ( zve3b  + zve3a  ) + atfp1 * zve3n  )   &
244                        & / ( atfp  * ( ze3v_b + ze3v_a ) + atfp1 * ze3v_n ) * vmask(ji,jj,jk)
245                     !
246                     ub(ji,jj,jk) = zuf                      ! ub <-- filtered velocity
247                     vb(ji,jj,jk) = zvf
248                     un(ji,jj,jk) = ua(ji,jj,jk)             ! un <-- ua
249                     vn(ji,jj,jk) = va(ji,jj,jk)
250                  END DO
251               END DO
252            END DO
253         ENDIF
254      ENDIF
255
256#if defined key_agrif
257      ! Update velocity at AGRIF zoom boundaries
258      IF (.NOT.Agrif_Root())    CALL Agrif_Update_Dyn( kt )
259#endif     
260
261      IF(ln_ctl)   CALL prt_ctl( tab3d_1=un, clinfo1=' nxt  - Un: ', mask1=umask,   &
262         &                       tab3d_2=vn, clinfo2=' Vn: '       , mask2=vmask )
263      !
264   END SUBROUTINE dyn_nxt
265
266   !!=========================================================================
267END MODULE dynnxt
Note: See TracBrowser for help on using the repository browser.