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.
dynadv_ubs.F90 in NEMO/trunk/src/OCE/DYN – NEMO

source: NEMO/trunk/src/OCE/DYN/dynadv_ubs.F90

Last change on this file was 14834, checked in by hadcv, 3 years ago

#2600: Merge in dev_r14273_HPC-02_Daley_Tiling

  • Property svn:keywords set to Id
File size: 15.2 KB
Line 
1MODULE dynadv_ubs
2   !!======================================================================
3   !!                       ***  MODULE  dynadv_ubs  ***
4   !! Ocean dynamics: Update the momentum trend with the flux form advection
5   !!                 trend using a 3rd order upstream biased scheme
6   !!======================================================================
7   !! History :  2.0  ! 2006-08  (R. Benshila, L. Debreu)  Original code
8   !!            3.2  ! 2009-07  (R. Benshila)  Suppression of rigid-lid option
9   !!----------------------------------------------------------------------
10
11   !!----------------------------------------------------------------------
12   !!   dyn_adv_ubs   : flux form momentum advection using    (ln_dynadv=T)
13   !!                   an 3rd order Upstream Biased Scheme or Quick scheme
14   !!                   combined with 2nd or 4th order finite differences
15   !!----------------------------------------------------------------------
16   USE oce            ! ocean dynamics and tracers
17   USE dom_oce        ! ocean space and time domain
18   USE trd_oce        ! trends: ocean variables
19   USE trddyn         ! trend manager: dynamics
20   !
21   USE in_out_manager ! I/O manager
22   USE prtctl         ! Print control
23   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
24   USE lib_mpp        ! MPP library
25
26   IMPLICIT NONE
27   PRIVATE
28
29   REAL(wp), PARAMETER :: gamma1 = 1._wp/3._wp  ! =1/4 quick      ; =1/3  3rd order UBS
30   REAL(wp), PARAMETER :: gamma2 = 1._wp/32._wp ! =0   2nd order  ; =1/32 4th order centred
31
32   PUBLIC   dyn_adv_ubs   ! routine called by step.F90
33
34   !! * Substitutions
35#  include "do_loop_substitute.h90"
36#  include "domzgr_substitute.h90"
37   !!----------------------------------------------------------------------
38   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
39   !! $Id$
40   !! Software governed by the CeCILL license (see ./LICENSE)
41   !!----------------------------------------------------------------------
42CONTAINS
43
44   SUBROUTINE dyn_adv_ubs( kt, Kbb, Kmm, puu, pvv, Krhs )
45      !!----------------------------------------------------------------------
46      !!                  ***  ROUTINE dyn_adv_ubs  ***
47      !!
48      !! ** Purpose :   Compute the now momentum advection trend in flux form
49      !!              and the general trend of the momentum equation.
50      !!
51      !! ** Method  :   The scheme is the one implemeted in ROMS. It depends
52      !!      on two parameter gamma1 and gamma2. The former control the
53      !!      upstream baised part of the scheme and the later the centred
54      !!      part:     gamma1 = 0    pure centered  (no diffusive part)
55      !!                       = 1/4  Quick scheme
56      !!                       = 1/3  3rd order Upstream biased scheme
57      !!                gamma2 = 0    2nd order finite differencing
58      !!                       = 1/32 4th order finite differencing
59      !!      For stability reasons, the first term of the fluxes which cor-
60      !!      responds to a second order centered scheme is evaluated using 
61      !!      the now velocity (centered in time) while the second term which 
62      !!      is the diffusive part of the scheme, is evaluated using the
63      !!      before velocity (forward in time).
64      !!      Default value (hard coded in the begining of the module) are
65      !!      gamma1=1/3 and gamma2=1/32.
66      !!
67      !! ** Action : - (puu(:,:,:,Krhs),pvv(:,:,:,Krhs)) updated with the 3D advective momentum trends
68      !!
69      !! Reference : Shchepetkin & McWilliams, 2005, Ocean Modelling.
70      !!----------------------------------------------------------------------
71      INTEGER                             , INTENT( in )  ::  kt              ! ocean time-step index
72      INTEGER                             , INTENT( in )  ::  Kbb, Kmm, Krhs  ! ocean time level indices
73      REAL(wp), DIMENSION(jpi,jpj,jpk,jpt), INTENT(inout) ::  puu, pvv        ! ocean velocities and RHS of momentum equation
74      !
75      INTEGER  ::   ji, jj, jk   ! dummy loop indices
76      REAL(wp) ::   zui, zvj, zfuj, zfvi, zl_u, zl_v   ! local scalars
77      REAL(wp), DIMENSION(A2D(nn_hls),jpk)   ::   zfu_t, zfu_f, zfu_uw, zfu
78      REAL(wp), DIMENSION(A2D(nn_hls),jpk)   ::   zfv_t, zfv_f, zfv_vw, zfv, zfw
79      REAL(wp), DIMENSION(A2D(nn_hls),jpk,2) ::   zlu_uu, zlu_uv
80      REAL(wp), DIMENSION(A2D(nn_hls),jpk,2) ::   zlv_vv, zlv_vu
81      !!----------------------------------------------------------------------
82      !
83      IF( .NOT. l_istiled .OR. ntile == 1 )  THEN                       ! Do only on the first tile
84         IF( kt == nit000 ) THEN
85            IF(lwp) WRITE(numout,*)
86            IF(lwp) WRITE(numout,*) 'dyn_adv_ubs : UBS flux form momentum advection'
87            IF(lwp) WRITE(numout,*) '~~~~~~~~~~~'
88         ENDIF
89      ENDIF
90      !
91      zfu_t(:,:,:) = 0._wp
92      zfv_t(:,:,:) = 0._wp
93      zfu_f(:,:,:) = 0._wp
94      zfv_f(:,:,:) = 0._wp
95      !
96      zlu_uu(:,:,:,:) = 0._wp
97      zlv_vv(:,:,:,:) = 0._wp 
98      zlu_uv(:,:,:,:) = 0._wp 
99      zlv_vu(:,:,:,:) = 0._wp 
100      !
101      IF( l_trddyn ) THEN           ! trends: store the input trends
102         zfu_uw(:,:,:) = puu(:,:,:,Krhs)
103         zfv_vw(:,:,:) = pvv(:,:,:,Krhs)
104      ENDIF
105      !                                      ! =========================== !
106      DO jk = 1, jpkm1                       !  Laplacian of the velocity  !
107         !                                   ! =========================== !
108         !                                         ! horizontal volume fluxes
109         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
110            zfu(ji,jj,jk) = e2u(ji,jj) * e3u(ji,jj,jk,Kmm) * puu(ji,jj,jk,Kmm)
111            zfv(ji,jj,jk) = e1v(ji,jj) * e3v(ji,jj,jk,Kmm) * pvv(ji,jj,jk,Kmm)
112         END_2D
113         !           
114         DO_2D( nn_hls-1, nn_hls-1, nn_hls-1, nn_hls-1 )                       ! laplacian
115            ! round brackets added to fix the order of floating point operations
116            ! needed to ensure halo 1 - halo 2 compatibility
117            zlu_uu(ji,jj,jk,1) = ( ( puu (ji+1,jj  ,jk,Kbb) - puu (ji  ,jj  ,jk,Kbb) &
118               &                   )                                                 & ! bracket for halo 1 - halo 2 compatibility
119               &                 + ( puu (ji-1,jj  ,jk,Kbb) - puu (ji  ,jj  ,jk,Kbb) &
120               &                   )                                                 & ! bracket for halo 1 - halo 2 compatibility
121               &                 ) * umask(ji  ,jj  ,jk)
122            zlv_vv(ji,jj,jk,1) = ( ( pvv (ji  ,jj+1,jk,Kbb) - pvv (ji  ,jj  ,jk,Kbb) &
123               &                   )                                                 & ! bracket for halo 1 - halo 2 compatibility
124               &                 + ( pvv (ji  ,jj-1,jk,Kbb) - pvv (ji  ,jj  ,jk,Kbb) &
125               &                   )                                                 & ! bracket for halo 1 - halo 2 compatibility
126               &                 ) * vmask(ji  ,jj  ,jk)
127            zlu_uv(ji,jj,jk,1) = (  puu (ji  ,jj+1,jk,Kbb) - puu (ji  ,jj  ,jk,Kbb)  ) * fmask(ji  ,jj  ,jk)   &
128               &               - (  puu (ji  ,jj  ,jk,Kbb) - puu (ji  ,jj-1,jk,Kbb)  ) * fmask(ji  ,jj-1,jk)
129            zlv_vu(ji,jj,jk,1) = (  pvv (ji+1,jj  ,jk,Kbb) - pvv (ji  ,jj  ,jk,Kbb)  ) * fmask(ji  ,jj  ,jk)   &
130               &               - (  pvv (ji  ,jj  ,jk,Kbb) - pvv (ji-1,jj  ,jk,Kbb)  ) * fmask(ji-1,jj  ,jk)
131            !
132            ! round brackets added to fix the order of floating point operations
133            ! needed to ensure halo 1 - halo 2 compatibility
134            zlu_uu(ji,jj,jk,2) = ( ( zfu(ji+1,jj  ,jk) - zfu(ji  ,jj  ,jk)           &
135               &                   )                                                 & ! bracket for halo 1 - halo 2 compatibility
136               &                 + ( zfu(ji-1,jj  ,jk) - zfu(ji  ,jj  ,jk)           &
137               &                   )                                                 & ! bracket for halo 1 - halo 2 compatibility
138               &                 ) * umask(ji  ,jj  ,jk)
139            zlv_vv(ji,jj,jk,2) = ( ( zfv(ji  ,jj+1,jk) - zfv(ji  ,jj  ,jk)           &
140               &                   )                                                 & ! bracket for halo 1 - halo 2 compatibility
141               &                 + ( zfv(ji  ,jj-1,jk) - zfv(ji  ,jj  ,jk)           &
142               &                   )                                                 & ! bracket for halo 1 - halo 2 compatibility
143               &                 ) * vmask(ji  ,jj  ,jk)
144            zlu_uv(ji,jj,jk,2) = (  zfu(ji  ,jj+1,jk) - zfu(ji  ,jj  ,jk)  ) * fmask(ji  ,jj  ,jk)             &
145               &               - (  zfu(ji  ,jj  ,jk) - zfu(ji  ,jj-1,jk)  ) * fmask(ji  ,jj-1,jk)
146            zlv_vu(ji,jj,jk,2) = (  zfv(ji+1,jj  ,jk) - zfv(ji  ,jj  ,jk)  ) * fmask(ji  ,jj  ,jk)             &
147               &               - (  zfv(ji  ,jj  ,jk) - zfv(ji-1,jj  ,jk)  ) * fmask(ji-1,jj  ,jk)
148         END_2D
149      END DO
150      IF( nn_hls == 1 ) CALL lbc_lnk( 'dynadv_ubs', zlu_uu(:,:,:,1), 'U', -1.0_wp , zlu_uv(:,:,:,1), 'U', -1.0_wp,  &
151                                              &   zlu_uu(:,:,:,2), 'U', -1.0_wp , zlu_uv(:,:,:,2), 'U', -1.0_wp,  &
152                                              &   zlv_vv(:,:,:,1), 'V', -1.0_wp , zlv_vu(:,:,:,1), 'V', -1.0_wp,  &
153                                              &   zlv_vv(:,:,:,2), 'V', -1.0_wp , zlv_vu(:,:,:,2), 'V', -1.0_wp   )
154      !
155      !                                      ! ====================== !
156      !                                      !  Horizontal advection  !
157      DO jk = 1, jpkm1                       ! ====================== !
158         !                                         ! horizontal volume fluxes
159         DO_2D( 1, 1, 1, 1 )
160            zfu(ji,jj,jk) = 0.25_wp * e2u(ji,jj) * e3u(ji,jj,jk,Kmm) * puu(ji,jj,jk,Kmm)
161            zfv(ji,jj,jk) = 0.25_wp * e1v(ji,jj) * e3v(ji,jj,jk,Kmm) * pvv(ji,jj,jk,Kmm)
162         END_2D
163         !
164         DO_2D( 1, 0, 1, 0 )                       ! horizontal momentum fluxes at T- and F-point
165            zui = ( puu(ji,jj,jk,Kmm) + puu(ji+1,jj  ,jk,Kmm) )
166            zvj = ( pvv(ji,jj,jk,Kmm) + pvv(ji  ,jj+1,jk,Kmm) )
167            !
168            IF( zui > 0 ) THEN   ;   zl_u = zlu_uu(ji  ,jj,jk,1)
169            ELSE                 ;   zl_u = zlu_uu(ji+1,jj,jk,1)
170            ENDIF
171            IF( zvj > 0 ) THEN   ;   zl_v = zlv_vv(ji,jj  ,jk,1)
172            ELSE                 ;   zl_v = zlv_vv(ji,jj+1,jk,1)
173            ENDIF
174            !
175            zfu_t(ji+1,jj  ,jk) = ( zfu(ji,jj,jk) + zfu(ji+1,jj  ,jk)                               &
176               &                    - gamma2 * ( zlu_uu(ji,jj,jk,2) + zlu_uu(ji+1,jj  ,jk,2) )  )   &
177               &                * ( zui - gamma1 * zl_u)
178            zfv_t(ji  ,jj+1,jk) = ( zfv(ji,jj,jk) + zfv(ji  ,jj+1,jk)                               &
179               &                    - gamma2 * ( zlv_vv(ji,jj,jk,2) + zlv_vv(ji  ,jj+1,jk,2) )  )   &
180               &                * ( zvj - gamma1 * zl_v)
181            !
182            zfuj = ( zfu(ji,jj,jk) + zfu(ji  ,jj+1,jk) )
183            zfvi = ( zfv(ji,jj,jk) + zfv(ji+1,jj  ,jk) )
184            IF( zfuj > 0 ) THEN   ;    zl_v = zlv_vu( ji  ,jj  ,jk,1)
185            ELSE                  ;    zl_v = zlv_vu( ji+1,jj,jk,1)
186            ENDIF
187            IF( zfvi > 0 ) THEN   ;    zl_u = zlu_uv( ji,jj  ,jk,1)
188            ELSE                  ;    zl_u = zlu_uv( ji,jj+1,jk,1)
189            ENDIF
190            !
191            zfv_f(ji  ,jj  ,jk) = ( zfvi - gamma2 * ( zlv_vu(ji,jj,jk,2) + zlv_vu(ji+1,jj  ,jk,2) )  )   &
192               &                * ( puu(ji,jj,jk,Kmm) + puu(ji  ,jj+1,jk,Kmm) - gamma1 * zl_u )
193            zfu_f(ji  ,jj  ,jk) = ( zfuj - gamma2 * ( zlu_uv(ji,jj,jk,2) + zlu_uv(ji  ,jj+1,jk,2) )  )   &
194               &                * ( pvv(ji,jj,jk,Kmm) + pvv(ji+1,jj  ,jk,Kmm) - gamma1 * zl_v )
195         END_2D
196         DO_2D( 0, 0, 0, 0 )                       ! divergence of horizontal momentum fluxes
197            puu(ji,jj,jk,Krhs) = puu(ji,jj,jk,Krhs) - (  zfu_t(ji+1,jj,jk) - zfu_t(ji,jj  ,jk)    &
198               &                           + zfv_f(ji  ,jj,jk) - zfv_f(ji,jj-1,jk)  ) * r1_e1e2u(ji,jj)   &
199               &                           / e3u(ji,jj,jk,Kmm)
200            pvv(ji,jj,jk,Krhs) = pvv(ji,jj,jk,Krhs) - (  zfu_f(ji,jj  ,jk) - zfu_f(ji-1,jj,jk)    &
201               &                           + zfv_t(ji,jj+1,jk) - zfv_t(ji  ,jj,jk)  ) * r1_e1e2v(ji,jj)   &
202               &                           / e3v(ji,jj,jk,Kmm)
203         END_2D
204      END DO
205      IF( l_trddyn ) THEN                          ! trends: send trends to trddyn for diagnostic
206         zfu_uw(:,:,:) = puu(:,:,:,Krhs) - zfu_uw(:,:,:)
207         zfv_vw(:,:,:) = pvv(:,:,:,Krhs) - zfv_vw(:,:,:)
208         CALL trd_dyn( zfu_uw, zfv_vw, jpdyn_keg, kt, Kmm )
209         zfu_t(:,:,:) = puu(:,:,:,Krhs)
210         zfv_t(:,:,:) = pvv(:,:,:,Krhs)
211      ENDIF
212      !                                      ! ==================== !
213      !                                      !  Vertical advection  !
214      !                                      ! ==================== !
215      DO_2D( 0, 0, 0, 0 )                          ! surface/bottom advective fluxes set to zero
216         zfu_uw(ji,jj,jpk) = 0._wp
217         zfv_vw(ji,jj,jpk) = 0._wp
218         zfu_uw(ji,jj, 1 ) = 0._wp
219         zfv_vw(ji,jj, 1 ) = 0._wp
220      END_2D
221      IF( ln_linssh ) THEN                         ! constant volume : advection through the surface
222         DO_2D( 0, 0, 0, 0 )
223            zfu_uw(ji,jj,1) = 0.5_wp * ( e1e2t(ji,jj) * ww(ji,jj,1) + e1e2t(ji+1,jj) * ww(ji+1,jj,1) ) * puu(ji,jj,1,Kmm)
224            zfv_vw(ji,jj,1) = 0.5_wp * ( e1e2t(ji,jj) * ww(ji,jj,1) + e1e2t(ji,jj+1) * ww(ji,jj+1,1) ) * pvv(ji,jj,1,Kmm)
225         END_2D
226      ENDIF
227      DO jk = 2, jpkm1                          ! interior fluxes
228         DO_2D( 0, 1, 0, 1 )
229            zfw(ji,jj,jk) = 0.25_wp * e1e2t(ji,jj) * ww(ji,jj,jk)
230         END_2D
231         DO_2D( 0, 0, 0, 0 )
232            zfu_uw(ji,jj,jk) = ( zfw(ji,jj,jk)+ zfw(ji+1,jj,jk) ) * ( puu(ji,jj,jk,Kmm) + puu(ji,jj,jk-1,Kmm) )
233            zfv_vw(ji,jj,jk) = ( zfw(ji,jj,jk)+ zfw(ji,jj+1,jk) ) * ( pvv(ji,jj,jk,Kmm) + pvv(ji,jj,jk-1,Kmm) )
234         END_2D
235      END DO
236      DO_3D( 0, 0, 0, 0, 1, jpkm1 )             ! divergence of vertical momentum flux divergence
237         puu(ji,jj,jk,Krhs) =  puu(ji,jj,jk,Krhs) - ( zfu_uw(ji,jj,jk) - zfu_uw(ji,jj,jk+1) ) * r1_e1e2u(ji,jj)   &
238            &                                       / e3u(ji,jj,jk,Kmm)
239         pvv(ji,jj,jk,Krhs) =  pvv(ji,jj,jk,Krhs) - ( zfv_vw(ji,jj,jk) - zfv_vw(ji,jj,jk+1) ) * r1_e1e2v(ji,jj)   &
240            &                                       / e3v(ji,jj,jk,Kmm)
241      END_3D
242      !
243      IF( l_trddyn ) THEN                       ! save the vertical advection trend for diagnostic
244         zfu_t(:,:,:) = puu(:,:,:,Krhs) - zfu_t(:,:,:)
245         zfv_t(:,:,:) = pvv(:,:,:,Krhs) - zfv_t(:,:,:)
246         CALL trd_dyn( zfu_t, zfv_t, jpdyn_zad, kt, Kmm )
247      ENDIF
248      !                                         ! Control print
249      IF(sn_cfctl%l_prtctl)   CALL prt_ctl( tab3d_1=puu(:,:,:,Krhs), clinfo1=' ubs2 adv - Ua: ', mask1=umask,   &
250         &                                  tab3d_2=pvv(:,:,:,Krhs), clinfo2=           ' Va: ', mask2=vmask, clinfo3='dyn' )
251      !
252   END SUBROUTINE dyn_adv_ubs
253
254   !!==============================================================================
255END MODULE dynadv_ubs
Note: See TracBrowser for help on using the repository browser.