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 branches/DEV_r2106_LOCEAN2010/NEMO/OPA_SRC/DYN – NEMO

source: branches/DEV_r2106_LOCEAN2010/NEMO/OPA_SRC/DYN/dynnxt.F90 @ 2236

Last change on this file since 2236 was 2236, checked in by cetlod, 14 years ago

First guess of NEMO_v3.3

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.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   !!            3.3  !  2010-09  (D. Storkey, E.O'Dea) Bug fix for BDY module
18   !!-------------------------------------------------------------------------
19 
20   !!-------------------------------------------------------------------------
21   !!   dyn_nxt      : obtain the next (after) horizontal velocity
22   !!-------------------------------------------------------------------------
23   USE oce             ! ocean dynamics and tracers
24   USE dom_oce         ! ocean space and time domain
25   USE sbc_oce         ! Surface boundary condition: ocean fields
26   USE phycst          ! physical constants
27   USE dynspg_oce      ! type of surface pressure gradient
28   USE dynadv          ! dynamics: vector invariant versus flux form
29   USE domvvl          ! variable volume
30   USE obc_oce         ! ocean open boundary conditions
31   USE obcdyn          ! open boundary condition for momentum (obc_dyn routine)
32   USE obcdyn_bt       ! 2D open boundary condition for momentum (obc_dyn_bt routine)
33   USE obcvol          ! ocean open boundary condition (obc_vol routines)
34   USE bdy_oce         ! unstructured open boundary conditions
35   USE bdydta          ! unstructured open boundary conditions
36   USE bdydyn          ! unstructured open boundary conditions
37   USE in_out_manager  ! I/O manager
38   USE lbclnk          ! lateral boundary condition (or mpp link)
39   USE prtctl          ! Print control
40#if defined key_agrif
41   USE agrif_opa_update
42   USE agrif_opa_interp
43#endif
44
45   IMPLICIT NONE
46   PRIVATE
47
48   PUBLIC    dyn_nxt   ! routine called by step.F90
49
50   !! * Substitutions
51#  include "domzgr_substitute.h90"
52   !!-------------------------------------------------------------------------
53   !! NEMO/OPA 3.2 , LOCEAN-IPSL (2009)
54   !! $Id$
55   !! Software is governed by the CeCILL licence  (NEMOGCM/License_CeCILL.txt)
56   !!-------------------------------------------------------------------------
57
58CONTAINS
59
60   SUBROUTINE dyn_nxt ( kt )
61      !!----------------------------------------------------------------------
62      !!                  ***  ROUTINE dyn_nxt  ***
63      !!                   
64      !! ** Purpose :   Compute the after horizontal velocity. Apply the boundary
65      !!             condition on the after velocity, achieved the time stepping
66      !!             by applying the Asselin filter on now fields and swapping
67      !!             the fields.
68      !!
69      !! ** Method  : * After velocity is compute using a leap-frog scheme:
70      !!                       (ua,va) = (ub,vb) + 2 rdt (ua,va)
71      !!             Note that with flux form advection and variable volume layer
72      !!             (lk_vvl=T), the leap-frog is applied on thickness weighted
73      !!             velocity.
74      !!             Note also that in filtered free surface (lk_dynspg_flt=T),
75      !!             the time stepping has already been done in dynspg module
76      !!
77      !!              * Apply lateral boundary conditions on after velocity
78      !!             at the local domain boundaries through lbc_lnk call,
79      !!             at the radiative open boundaries (lk_obc=T),
80      !!             at the relaxed   open boundaries (lk_bdy=T), and
81      !!             at the AGRIF zoom     boundaries (lk_agrif=T)
82      !!
83      !!              * Apply the time filter applied and swap of the dynamics
84      !!             arrays to start the next time step:
85      !!                (ub,vb) = (un,vn) + atfp [ (ub,vb) + (ua,va) - 2 (un,vn) ]
86      !!                (un,vn) = (ua,va).
87      !!             Note that with flux form advection and variable volume layer
88      !!             (lk_vvl=T), the time filter is applied on thickness weighted
89      !!             velocity.
90      !!
91      !! ** Action :   ub,vb   filtered before horizontal velocity of next time-step
92      !!               un,vn   now horizontal velocity of next time-step
93      !!----------------------------------------------------------------------
94      USE oce, ONLY :   ze3u_f => ta   ! use ta as 3D workspace
95      USE oce, ONLY :   ze3v_f => sa   ! use sa as 3D workspace
96      INTEGER, INTENT( in ) ::   kt      ! ocean time-step index
97      !!
98      INTEGER  ::   ji, jj, jk   ! dummy loop indices
99#if ! defined key_dynspg_flt
100      REAL(wp) ::   z2dt         ! temporary scalar
101#endif
102      REAL(wp) ::   zue3a , zue3n , zue3b    ! temporary scalar
103      REAL(wp) ::   zve3a , zve3n , zve3b    !    -         -
104      REAL(wp) ::   zuf   , zvf              !    -         -
105      REAL(wp) ::   zec                      !    -         -
106      REAL(wp) ::   zv_t_ij  , zv_t_ip1j     !     -        -
107      REAL(wp) ::   zv_t_ijp1                !     -        -
108      REAL(wp), DIMENSION(jpi,jpj) ::  zs_t, zs_u_1, zs_v_1      ! temporary 2D workspace
109      !!----------------------------------------------------------------------
110
111      IF( kt == nit000 ) THEN
112         IF(lwp) WRITE(numout,*)
113         IF(lwp) WRITE(numout,*) 'dyn_nxt : time stepping'
114         IF(lwp) WRITE(numout,*) '~~~~~~~'
115      ENDIF
116
117#if defined key_dynspg_flt
118      !
119      ! Next velocity :   Leap-frog time stepping already done in dynspg_flt.F routine
120      ! -------------
121
122      ! Update after velocity on domain lateral boundaries      (only local domain required)
123      ! --------------------------------------------------
124      CALL lbc_lnk( ua, 'U', -1. )         ! local domain boundaries
125      CALL lbc_lnk( va, 'V', -1. ) 
126      !
127#else
128      ! Next velocity :   Leap-frog time stepping
129      ! -------------
130      z2dt = 2. * rdt                                 ! Euler or leap-frog time step
131      IF( neuler == 0 .AND. kt == nit000 )  z2dt = rdt
132      !
133      IF( ln_dynadv_vec .OR. .NOT. lk_vvl ) THEN      ! applied on velocity
134         DO jk = 1, jpkm1
135            ua(:,:,jk) = ( ub(:,:,jk) + z2dt * ua(:,:,jk) ) * umask(:,:,jk)
136            va(:,:,jk) = ( vb(:,:,jk) + z2dt * va(:,:,jk) ) * vmask(:,:,jk)
137         END DO
138      ELSE                                            ! applied on thickness weighted velocity
139         DO jk = 1, jpkm1
140            ua(:,:,jk) = (          ub(:,:,jk) * fse3u_b(:,:,jk)      &
141               &           + z2dt * ua(:,:,jk) * fse3u_n(:,:,jk)  )   &
142               &         / fse3u_a(:,:,jk) * umask(:,:,jk)
143            va(:,:,jk) = (          vb(:,:,jk) * fse3v_b(:,:,jk)      &
144               &           + z2dt * va(:,:,jk) * fse3v_n(:,:,jk)  )   &
145               &         / fse3v_a(:,:,jk) * vmask(:,:,jk)
146         END DO
147      ENDIF
148
149
150      ! Update after velocity on domain lateral boundaries
151      ! --------------------------------------------------     
152      CALL lbc_lnk( ua, 'U', -1. )     !* local domain boundaries
153      CALL lbc_lnk( va, 'V', -1. ) 
154      !
155# if defined key_obc
156      !                                !* OBC open boundaries
157      CALL obc_dyn( kt )
158      !
159      IF ( lk_dynspg_exp .OR. lk_dynspg_ts ) THEN
160         ! Flather boundary condition : - Update sea surface height on each open boundary
161         !                                       sshn   (= after ssh   ) for explicit case
162         !                                       sshn_b (= after ssha_b) for time-splitting case
163         !                              - Correct the barotropic velocities
164         CALL obc_dyn_bt( kt )
165         !
166!!gm ERROR - potential BUG: sshn should not be modified at this stage !!   ssh_nxt not alrady called
167         CALL lbc_lnk( sshn, 'T', 1. )         ! Boundary conditions on sshn
168         !
169         IF( ln_vol_cst )   CALL obc_vol( kt )
170         !
171         IF(ln_ctl)   CALL prt_ctl( tab2d_1=sshn, clinfo1=' ssh      : ', mask1=tmask )
172      ENDIF
173      !
174# elif defined key_bdy 
175      !                                !* BDY open boundaries
176      IF( lk_dynspg_exp .OR. lk_dynspg_ts ) THEN       ! except for filtered option
177         CALL bdy_dyn_frs( kt )
178      ENDIF
179# endif
180      !
181# if defined key_agrif
182      CALL Agrif_dyn( kt )             !* AGRIF zoom boundaries
183# endif
184#endif
185
186      ! Time filter and swap of dynamics arrays
187      ! ------------------------------------------
188      IF( neuler == 0 .AND. kt == nit000 ) THEN        !* Euler at first time-step: only swap
189         DO jk = 1, jpkm1
190            un(:,:,jk) = ua(:,:,jk)                          ! un <-- ua
191            vn(:,:,jk) = va(:,:,jk)
192         END DO
193      ELSE                                             !* Leap-Frog : Asselin filter and swap
194         !                                ! =============!
195         IF( .NOT. lk_vvl ) THEN          ! Fixed volume !
196            !                             ! =============!
197            DO jk = 1, jpkm1                             
198               DO jj = 1, jpj
199                  DO ji = 1, jpi   
200                     zuf = un(ji,jj,jk) + atfp * ( ub(ji,jj,jk) - 2.e0 * un(ji,jj,jk) + ua(ji,jj,jk) )
201                     zvf = vn(ji,jj,jk) + atfp * ( vb(ji,jj,jk) - 2.e0 * vn(ji,jj,jk) + va(ji,jj,jk) )
202                     !
203                     ub(ji,jj,jk) = zuf                      ! ub <-- filtered velocity
204                     vb(ji,jj,jk) = zvf
205                     un(ji,jj,jk) = ua(ji,jj,jk)             ! un <-- ua
206                     vn(ji,jj,jk) = va(ji,jj,jk)
207                  END DO
208               END DO
209            END DO
210            !                             ! ================!
211         ELSE                             ! Variable volume !
212            !                             ! ================!
213            ! Before scale factor at t-points
214            ! -------------------------------
215            DO jk = 1, jpkm1
216               fse3t_b(:,:,jk) = fse3t_n(:,:,jk)                                   &
217                  &              + atfp * (  fse3t_b(:,:,jk) + fse3t_a(:,:,jk)     &
218                  &                         - 2.e0 * fse3t_n(:,:,jk)            )
219            ENDDO
220            ! Add volume filter correction only at the first level of t-point scale factors
221            zec = atfp * rdt / rau0
222            fse3t_b(:,:,1) = fse3t_b(:,:,1) - zec * ( emp_b(:,:) - emp(:,:) ) * tmask(:,:,1)
223            ! surface at t-points and inverse surface at (u/v)-points used in surface averaging computations
224            zs_t  (:,:) =       e1t(:,:) * e2t(:,:)
225            zs_u_1(:,:) = 0.5 / e1u(:,:) * e2u(:,:)
226            zs_v_1(:,:) = 0.5 / e1v(:,:) * e2v(:,:)
227            !
228            IF( ln_dynadv_vec ) THEN
229               ! Before scale factor at (u/v)-points
230               ! -----------------------------------
231               ! Scale factor anomaly at (u/v)-points: surface averaging of scale factor at t-points
232               DO jk = 1, jpkm1
233                  DO jj = 1, jpjm1
234                     DO ji = 1, jpim1
235                        zv_t_ij           = zs_t(ji  ,jj  ) * fse3t_b(ji  ,jj  ,jk)
236                        zv_t_ip1j         = zs_t(ji+1,jj  ) * fse3t_b(ji+1,jj  ,jk)
237                        zv_t_ijp1         = zs_t(ji  ,jj+1) * fse3t_b(ji  ,jj+1,jk)
238                        fse3u_b(ji,jj,jk) = umask(ji,jj,jk) * ( zs_u_1(ji,jj) * ( zv_t_ij + zv_t_ip1j ) - fse3u_0(ji,jj,jk) )
239                        fse3v_b(ji,jj,jk) = vmask(ji,jj,jk) * ( zs_v_1(ji,jj) * ( zv_t_ij + zv_t_ijp1 ) - fse3v_0(ji,jj,jk) )
240                     END DO
241                  END DO
242               END DO
243               ! lateral boundary conditions
244               CALL lbc_lnk( fse3u_b(:,:,:), 'U', 1. )
245               CALL lbc_lnk( fse3v_b(:,:,:), 'V', 1. )
246               ! Add initial scale factor to scale factor anomaly
247               fse3u_b(:,:,:) = fse3u_b(:,:,:) + fse3u_0(:,:,:)
248               fse3v_b(:,:,:) = fse3v_b(:,:,:) + fse3v_0(:,:,:)
249               ! Leap-Frog - Asselin filter and swap: applied on velocity
250               ! -----------------------------------
251               DO jk = 1, jpkm1
252                  DO jj = 1, jpj
253                     DO ji = 1, jpi
254                        zuf = un(ji,jj,jk) + atfp * ( ub(ji,jj,jk) - 2.e0 * un(ji,jj,jk) + ua(ji,jj,jk) )
255                        zvf = vn(ji,jj,jk) + atfp * ( vb(ji,jj,jk) - 2.e0 * vn(ji,jj,jk) + va(ji,jj,jk) )
256                        !
257                        ub(ji,jj,jk) = zuf                      ! ub <-- filtered velocity
258                        vb(ji,jj,jk) = zvf
259                        un(ji,jj,jk) = ua(ji,jj,jk)             ! un <-- ua
260                        vn(ji,jj,jk) = va(ji,jj,jk)
261                     END DO
262                  END DO
263               END DO
264               !
265            ELSE
266               ! Temporary filered scale factor at (u/v)-points (will become before scale factor)
267               !-----------------------------------------------
268               ! Scale factor anomaly at (u/v)-points: surface averaging of scale factor at t-points
269               DO jk = 1, jpkm1
270                  DO jj = 1, jpjm1
271                     DO ji = 1, jpim1
272                        zv_t_ij          = zs_t(ji  ,jj  ) * fse3t_b(ji  ,jj  ,jk)
273                        zv_t_ip1j        = zs_t(ji+1,jj  ) * fse3t_b(ji+1,jj  ,jk)
274                        zv_t_ijp1        = zs_t(ji  ,jj+1) * fse3t_b(ji  ,jj+1,jk)
275                        ze3u_f(ji,jj,jk) = umask(ji,jj,jk) * ( zs_u_1(ji,jj) * ( zv_t_ij + zv_t_ip1j ) - fse3u_0(ji,jj,jk) )
276                        ze3v_f(ji,jj,jk) = vmask(ji,jj,jk) * ( zs_v_1(ji,jj) * ( zv_t_ij + zv_t_ijp1 ) - fse3v_0(ji,jj,jk) )
277                     END DO
278                  END DO
279               END DO
280               ! lateral boundary conditions
281               CALL lbc_lnk( ze3u_f, 'U', 1. )
282               CALL lbc_lnk( ze3v_f, 'V', 1. )
283               ! Add initial scale factor to scale factor anomaly
284               ze3u_f(:,:,:) = ze3u_f(:,:,:) + fse3u_0(:,:,:)
285               ze3v_f(:,:,:) = ze3v_f(:,:,:) + fse3v_0(:,:,:)
286               ! Leap-Frog - Asselin filter and swap: applied on thickness weighted velocity
287               ! -----------------------------------             ===========================
288               DO jk = 1, jpkm1
289                  DO jj = 1, jpj
290                     DO ji = 1, jpim1
291                        zue3a = ua(ji,jj,jk) * fse3u_a(ji,jj,jk)
292                        zve3a = va(ji,jj,jk) * fse3v_a(ji,jj,jk)
293                        zue3n = un(ji,jj,jk) * fse3u_n(ji,jj,jk)
294                        zve3n = vn(ji,jj,jk) * fse3v_n(ji,jj,jk)
295                        zue3b = ub(ji,jj,jk) * fse3u_b(ji,jj,jk)
296                        zve3b = vb(ji,jj,jk) * fse3v_b(ji,jj,jk)
297                        !
298                        zuf  = ( zue3n + atfp * ( zue3b - 2.e0 * zue3n  + zue3a ) ) / ze3u_f(ji,jj,jk)
299                        zvf  = ( zve3n + atfp * ( zve3b - 2.e0 * zve3n  + zve3a ) ) / ze3v_f(ji,jj,jk)
300                        !
301                        ub(ji,jj,jk) = zuf                      ! ub <-- filtered velocity
302                        vb(ji,jj,jk) = zvf
303                        un(ji,jj,jk) = ua(ji,jj,jk)             ! un <-- ua
304                        vn(ji,jj,jk) = va(ji,jj,jk)
305                     END DO
306                  END DO
307               END DO
308               fse3u_b(:,:,:) = ze3u_f(:,:,:)                   ! e3u_b <-- filtered scale factor
309               fse3v_b(:,:,:) = ze3v_f(:,:,:)
310               CALL lbc_lnk( ub, 'U', -1. )                     ! lateral boundary conditions
311               CALL lbc_lnk( vb, 'V', -1. )
312            ENDIF
313            !
314         ENDIF
315         !
316      ENDIF
317
318#if defined key_agrif
319      ! Update velocity at AGRIF zoom boundaries
320      IF (.NOT.Agrif_Root())    CALL Agrif_Update_Dyn( kt )
321#endif     
322
323      IF(ln_ctl)   CALL prt_ctl( tab3d_1=un, clinfo1=' nxt  - Un: ', mask1=umask,   &
324         &                       tab3d_2=vn, clinfo2=' Vn: '       , mask2=vmask )
325      !
326   END SUBROUTINE dyn_nxt
327
328   !!=========================================================================
329END MODULE dynnxt
Note: See TracBrowser for help on using the repository browser.