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.
sshwzv.F90 in branches/2012/dev_MERGE_2012/NEMOGCM/NEMO/OPA_SRC/DYN – NEMO

source: branches/2012/dev_MERGE_2012/NEMOGCM/NEMO/OPA_SRC/DYN/sshwzv.F90 @ 3802

Last change on this file since 3802 was 3764, checked in by smasson, 11 years ago

dev_MERGE_2012: report bugfixes done in the trunk from r3555 to r3763 into dev_MERGE_2012

  • Property svn:keywords set to Id
File size: 18.7 KB
RevLine 
[1565]1MODULE sshwzv   
[3]2   !!==============================================================================
[1438]3   !!                       ***  MODULE  sshwzv  ***
4   !! Ocean dynamics : sea surface height and vertical velocity
[3]5   !!==============================================================================
[1438]6   !! History :  3.1  !  2009-02  (G. Madec, M. Leclair)  Original code
[2528]7   !!            3.3  !  2010-04  (M. Leclair, G. Madec)  modified LF-RA
8   !!             -   !  2010-05  (K. Mogensen, A. Weaver, M. Martin, D. Lea) Assimilation interface
9   !!             -   !  2010-09  (D.Storkey and E.O'Dea) bug fixes for BDY module
[3]10   !!----------------------------------------------------------------------
[1438]11
[3]12   !!----------------------------------------------------------------------
[1438]13   !!   ssh_wzv        : after ssh & now vertical velocity
14   !!   ssh_nxt        : filter ans swap the ssh arrays
15   !!----------------------------------------------------------------------
[3]16   USE oce             ! ocean dynamics and tracers variables
17   USE dom_oce         ! ocean space and time domain variables
[888]18   USE sbc_oce         ! surface boundary condition: ocean
19   USE domvvl          ! Variable volume
[1565]20   USE divcur          ! hor. divergence and curl      (div & cur routines)
[1438]21   USE iom             ! I/O library
[3]22   USE in_out_manager  ! I/O manager
[258]23   USE prtctl          ! Print control
[592]24   USE phycst
25   USE lbclnk          ! ocean lateral boundary condition (or mpp link)
[2715]26   USE lib_mpp         ! MPP library
[1241]27   USE obc_par         ! open boundary cond. parameter
28   USE obc_oce
[2528]29   USE bdy_oce
[2715]30   USE diaar5, ONLY:   lk_diaar5
[1482]31   USE iom
[2715]32   USE sbcrnf, ONLY: h_rnf, nk_rnf   ! River runoff
[2528]33#if defined key_agrif
34   USE agrif_opa_update
[2486]35   USE agrif_opa_interp
[2528]36#endif
37#if defined key_asminc   
38   USE asminc          ! Assimilation increment
39#endif
[3294]40   USE wrk_nemo        ! Memory Allocation
41   USE timing          ! Timing
[592]42
[3]43   IMPLICIT NONE
44   PRIVATE
45
[1438]46   PUBLIC   ssh_wzv    ! called by step.F90
47   PUBLIC   ssh_nxt    ! called by step.F90
[3]48
49   !! * Substitutions
50#  include "domzgr_substitute.h90"
[1438]51#  include "vectopt_loop_substitute.h90"
[3]52   !!----------------------------------------------------------------------
[2528]53   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
[888]54   !! $Id$
[2715]55   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
[592]56   !!----------------------------------------------------------------------
[3]57CONTAINS
58
[1438]59   SUBROUTINE ssh_wzv( kt ) 
[3]60      !!----------------------------------------------------------------------
[1438]61      !!                ***  ROUTINE ssh_wzv  ***
62      !!                   
63      !! ** Purpose :   compute the after ssh (ssha), the now vertical velocity
64      !!              and update the now vertical coordinate (lk_vvl=T).
[3]65      !!
[2528]66      !! ** Method  : - Using the incompressibility hypothesis, the vertical
[1438]67      !!      velocity is computed by integrating the horizontal divergence 
68      !!      from the bottom to the surface minus the scale factor evolution.
69      !!        The boundary conditions are w=0 at the bottom (no flux) and.
[3]70      !!
[1438]71      !! ** action  :   ssha    : after sea surface height
72      !!                wn      : now vertical velocity
[2528]73      !!                sshu_a, sshv_a, sshf_a  : after sea surface height (lk_vvl=T)
74      !!                hu, hv, hur, hvr        : ocean depth and its inverse at u-,v-points
75      !!
76      !! Reference  : Leclair, M., and G. Madec, 2009, Ocean Modelling.
[3]77      !!----------------------------------------------------------------------
[1438]78      INTEGER, INTENT(in) ::   kt   ! time step
[2715]79      !
80      INTEGER  ::   ji, jj, jk   ! dummy loop indices
81      REAL(wp) ::   zcoefu, zcoefv, zcoeff, z2dt, z1_2dt, z1_rau0   ! local scalars
[3294]82      REAL(wp), POINTER, DIMENSION(:,:  ) ::  z2d, zhdiv
83      REAL(wp), POINTER, DIMENSION(:,:,:) ::  z3d
[3]84      !!----------------------------------------------------------------------
[3294]85      !
86      IF( nn_timing == 1 )  CALL timing_start('ssh_wzv')
87      !
88      CALL wrk_alloc( jpi, jpj, z2d, zhdiv ) 
89      !
[3]90      IF( kt == nit000 ) THEN
[2528]91         !
[3]92         IF(lwp) WRITE(numout,*)
[1438]93         IF(lwp) WRITE(numout,*) 'ssh_wzv : after sea surface height and now vertical velocity '
94         IF(lwp) WRITE(numout,*) '~~~~~~~ '
95         !
[2715]96         wn(:,:,jpk) = 0._wp                  ! bottom boundary condition: w=0 (set once for all)
[1438]97         !
98         IF( lk_vvl ) THEN                    ! before and now Sea SSH at u-, v-, f-points (vvl case only)
99            DO jj = 1, jpjm1
100               DO ji = 1, jpim1                    ! caution: use of Vector Opt. not possible
101                  zcoefu = 0.5  * umask(ji,jj,1) / ( e1u(ji,jj) * e2u(ji,jj) )
102                  zcoefv = 0.5  * vmask(ji,jj,1) / ( e1v(ji,jj) * e2v(ji,jj) )
103                  zcoeff = 0.25 * umask(ji,jj,1) * umask(ji,jj+1,1)
104                  sshu_b(ji,jj) = zcoefu * ( e1t(ji  ,jj) * e2t(ji  ,jj) * sshb(ji  ,jj)     &
105                     &                     + e1t(ji+1,jj) * e2t(ji+1,jj) * sshb(ji+1,jj) )
106                  sshv_b(ji,jj) = zcoefv * ( e1t(ji,jj  ) * e2t(ji,jj  ) * sshb(ji,jj  )     &
107                     &                     + e1t(ji,jj+1) * e2t(ji,jj+1) * sshb(ji,jj+1) )
108                  sshu_n(ji,jj) = zcoefu * ( e1t(ji  ,jj) * e2t(ji  ,jj) * sshn(ji  ,jj)     &
109                     &                     + e1t(ji+1,jj) * e2t(ji+1,jj) * sshn(ji+1,jj) )
110                  sshv_n(ji,jj) = zcoefv * ( e1t(ji,jj  ) * e2t(ji,jj  ) * sshn(ji,jj  )     &
111                     &                     + e1t(ji,jj+1) * e2t(ji,jj+1) * sshn(ji,jj+1) )
112               END DO
113            END DO
114            CALL lbc_lnk( sshu_b, 'U', 1. )   ;   CALL lbc_lnk( sshu_n, 'U', 1. )
115            CALL lbc_lnk( sshv_b, 'V', 1. )   ;   CALL lbc_lnk( sshv_n, 'V', 1. )
[2528]116            DO jj = 1, jpjm1
117               DO ji = 1, jpim1      ! NO Vector Opt.
118                  sshf_n(ji,jj) = 0.5  * umask(ji,jj,1) * umask(ji,jj+1,1)                   &
119                       &               / ( e1f(ji,jj  ) * e2f(ji,jj  ) )                     &
120                       &               * ( e1u(ji,jj  ) * e2u(ji,jj  ) * sshu_n(ji,jj  )     &
121                       &                 + e1u(ji,jj+1) * e2u(ji,jj+1) * sshu_n(ji,jj+1) )
122               END DO
123            END DO
124            CALL lbc_lnk( sshf_n, 'F', 1. )
[1438]125         ENDIF
126         !
[3]127      ENDIF
128
[2528]129      !                                           !------------------------------------------!
130      IF( lk_vvl ) THEN                           !  Regridding: Update Now Vertical coord.  !   (only in vvl case)
131         !                                        !------------------------------------------!
[1565]132         DO jk = 1, jpkm1
[2528]133            fsdept(:,:,jk) = fsdept_n(:,:,jk)         ! now local depths stored in fsdep. arrays
[1565]134            fsdepw(:,:,jk) = fsdepw_n(:,:,jk)
135            fsde3w(:,:,jk) = fsde3w_n(:,:,jk)
136            !
[2528]137            fse3t (:,:,jk) = fse3t_n (:,:,jk)         ! vertical scale factors stored in fse3. arrays
[1565]138            fse3u (:,:,jk) = fse3u_n (:,:,jk)
139            fse3v (:,:,jk) = fse3v_n (:,:,jk)
140            fse3f (:,:,jk) = fse3f_n (:,:,jk)
141            fse3w (:,:,jk) = fse3w_n (:,:,jk)
142            fse3uw(:,:,jk) = fse3uw_n(:,:,jk)
143            fse3vw(:,:,jk) = fse3vw_n(:,:,jk)
144         END DO
[2528]145         !
146         hu(:,:) = hu_0(:,:) + sshu_n(:,:)            ! now ocean depth (at u- and v-points)
[1565]147         hv(:,:) = hv_0(:,:) + sshv_n(:,:)
[2528]148         !                                            ! now masked inverse of the ocean depth (at u- and v-points)
[2715]149         hur(:,:) = umask(:,:,1) / ( hu(:,:) + 1._wp - umask(:,:,1) )
150         hvr(:,:) = vmask(:,:,1) / ( hv(:,:) + 1._wp - vmask(:,:,1) )
[2528]151         !
[1565]152      ENDIF
[2528]153      !
154      CALL div_cur( kt )                              ! Horizontal divergence & Relative vorticity
155      !
[2715]156      z2dt = 2._wp * rdt                              ! set time step size (Euler/Leapfrog)
157      IF( neuler == 0 .AND. kt == nit000 )   z2dt = rdt
[3]158
[1438]159      !                                           !------------------------------!
160      !                                           !   After Sea Surface Height   !
161      !                                           !------------------------------!
[2715]162      zhdiv(:,:) = 0._wp
[1438]163      DO jk = 1, jpkm1                                 ! Horizontal divergence of barotropic transports
164        zhdiv(:,:) = zhdiv(:,:) + fse3t(:,:,jk) * hdivn(:,:,jk)
165      END DO
166      !                                                ! Sea surface elevation time stepping
[2528]167      ! In forward Euler time stepping case, the same formulation as in the leap-frog case can be used
168      ! because emp_b field is initialized with the vlaues of emp field. Hence, 0.5 * ( emp + emp_b ) = emp
169      z1_rau0 = 0.5 / rau0
[2715]170      ssha(:,:) = (  sshb(:,:) - z2dt * ( z1_rau0 * ( emp_b(:,:) + emp(:,:) ) + zhdiv(:,:) )  ) * tmask(:,:,1)
[1438]171
[2486]172#if defined key_agrif
[2715]173      CALL agrif_ssh( kt )
[2486]174#endif
[1438]175#if defined key_obc
[2528]176      IF( Agrif_Root() ) THEN
[1438]177         ssha(:,:) = ssha(:,:) * obctmsk(:,:)
[2715]178         CALL lbc_lnk( ssha, 'T', 1. )                 ! absolutly compulsory !! (jmm)
[1438]179      ENDIF
180#endif
[2528]181#if defined key_bdy
182      ssha(:,:) = ssha(:,:) * bdytmask(:,:)
[3764]183      CALL lbc_lnk( ssha, 'T', 1. )                    ! absolutly compulsory !! (jmm)
[2528]184#endif
[3764]185#if defined key_asminc
186      !                                                ! Include the IAU weighted SSH increment
187      IF( lk_asminc .AND. ln_sshinc .AND. ln_asmiau ) THEN
188         CALL ssh_asm_inc( kt )
189         ssha(:,:) = ssha(:,:) + z2dt * ssh_iau(:,:)
190      ENDIF
191#endif
[1438]192      !                                                ! Sea Surface Height at u-,v- and f-points (vvl case only)
193      IF( lk_vvl ) THEN                                ! (required only in key_vvl case)
194         DO jj = 1, jpjm1
[1694]195            DO ji = 1, jpim1      ! NO Vector Opt.
[1438]196               sshu_a(ji,jj) = 0.5  * umask(ji,jj,1) / ( e1u(ji  ,jj) * e2u(ji  ,jj) )                   &
197                  &                                  * ( e1t(ji  ,jj) * e2t(ji  ,jj) * ssha(ji  ,jj)     &
198                  &                                    + e1t(ji+1,jj) * e2t(ji+1,jj) * ssha(ji+1,jj) )
199               sshv_a(ji,jj) = 0.5  * vmask(ji,jj,1) / ( e1v(ji,jj  ) * e2v(ji,jj  ) )                   &
200                  &                                  * ( e1t(ji,jj  ) * e2t(ji,jj  ) * ssha(ji,jj  )     &
201                  &                                    + e1t(ji,jj+1) * e2t(ji,jj+1) * ssha(ji,jj+1) )
[592]202            END DO
203         END DO
[2715]204         CALL lbc_lnk( sshu_a, 'U', 1. )   ;   CALL lbc_lnk( sshv_a, 'V', 1. )      ! Boundaries conditions
[1438]205      ENDIF
[592]206
[1438]207      !                                           !------------------------------!
208      !                                           !     Now Vertical Velocity    !
209      !                                           !------------------------------!
[2528]210      z1_2dt = 1.e0 / z2dt
211      DO jk = jpkm1, 1, -1                             ! integrate from the bottom the hor. divergence
212         ! - ML - need 3 lines here because replacement of fse3t by its expression yields too long lines otherwise
[2715]213         wn(:,:,jk) = wn(:,:,jk+1) -   fse3t_n(:,:,jk) * hdivn(:,:,jk)        &
214            &                      - ( fse3t_a(:,:,jk) - fse3t_b(:,:,jk) )    &
[2528]215            &                         * tmask(:,:,jk) * z1_2dt
216#if defined key_bdy
217         wn(:,:,jk) = wn(:,:,jk) * bdytmask(:,:)
218#endif
[1438]219      END DO
[2528]220
221      !                                           !------------------------------!
222      !                                           !           outputs            !
223      !                                           !------------------------------!
[1756]224      CALL iom_put( "woce", wn                    )   ! vertical velocity
225      CALL iom_put( "ssh" , sshn                  )   ! sea surface height
226      CALL iom_put( "ssh2", sshn(:,:) * sshn(:,:) )   ! square of sea surface height
[2528]227      IF( lk_diaar5 ) THEN                            ! vertical mass transport & its square value
228         ! Caution: in the VVL case, it only correponds to the baroclinic mass transport.
[3294]229         CALL wrk_alloc( jpi,jpj,jpk, z3d )
[1756]230         z2d(:,:) = rau0 * e1t(:,:) * e2t(:,:)
231         DO jk = 1, jpk
232            z3d(:,:,jk) = wn(:,:,jk) * z2d(:,:)
233         END DO
[2528]234         CALL iom_put( "w_masstr" , z3d                     ) 
235         CALL iom_put( "w_masstr2", z3d(:,:,:) * z3d(:,:,:) )
[3294]236         CALL wrk_dealloc( jpi,jpj,jpk, z3d )
[1756]237      ENDIF
[1438]238      !
[2528]239      IF(ln_ctl)   CALL prt_ctl( tab2d_1=ssha, clinfo1=' ssha  - : ', mask1=tmask, ovlap=1 )
240      !
[3294]241      CALL wrk_dealloc( jpi, jpj, z2d, zhdiv ) 
[2715]242      !
[3294]243      IF( nn_timing == 1 )  CALL timing_stop('ssh_wzv')
244      !
[1438]245   END SUBROUTINE ssh_wzv
[592]246
247
[1438]248   SUBROUTINE ssh_nxt( kt )
249      !!----------------------------------------------------------------------
250      !!                    ***  ROUTINE ssh_nxt  ***
251      !!
252      !! ** Purpose :   achieve the sea surface  height time stepping by
253      !!              applying Asselin time filter and swapping the arrays
254      !!              ssha  already computed in ssh_wzv 
255      !!
[2528]256      !! ** Method  : - apply Asselin time fiter to now ssh (excluding the forcing
257      !!              from the filter, see Leclair and Madec 2010) and swap :
258      !!                sshn = ssha + atfp * ( sshb -2 sshn + ssha )
259      !!                            - atfp * rdt * ( emp_b - emp ) / rau0
260      !!                sshn = ssha
[1438]261      !!
262      !! ** action  : - sshb, sshn   : before & now sea surface height
263      !!                               ready for the next time step
[2528]264      !!
265      !! Reference  : Leclair, M., and G. Madec, 2009, Ocean Modelling.
[1438]266      !!----------------------------------------------------------------------
[2528]267      INTEGER, INTENT(in) ::   kt   ! ocean time-step index
[1438]268      !!
[2528]269      INTEGER  ::   ji, jj   ! dummy loop indices
270      REAL(wp) ::   zec      ! temporary scalar
[1438]271      !!----------------------------------------------------------------------
[3294]272      !
273      IF( nn_timing == 1 )  CALL timing_start('ssh_nxt')
274      !
[1438]275      IF( kt == nit000 ) THEN
276         IF(lwp) WRITE(numout,*)
277         IF(lwp) WRITE(numout,*) 'ssh_nxt : next sea surface height (Asselin time filter + swap)'
278         IF(lwp) WRITE(numout,*) '~~~~~~~ '
279      ENDIF
[592]280
[2528]281      !                       !--------------------------!
[2715]282      IF( lk_vvl ) THEN       !  Variable volume levels  !     (ssh at t-, u-, v, f-points)
[2528]283         !                    !--------------------------!
284         !
[2715]285         IF( neuler == 0 .AND. kt == nit000 ) THEN    !** Euler time-stepping at first time-step : no filter
286            sshn  (:,:) = ssha  (:,:)                       ! now <-- after  (before already = now)
[1438]287            sshu_n(:,:) = sshu_a(:,:)
288            sshv_n(:,:) = sshv_a(:,:)
[2715]289            DO jj = 1, jpjm1                                ! ssh now at f-point
[2528]290               DO ji = 1, jpim1      ! NO Vector Opt.
[2715]291                  sshf_n(ji,jj) = 0.5  * umask(ji,jj,1) * umask(ji,jj+1,1)                 &
[2528]292                     &               / ( e1f(ji,jj  ) * e2f(ji,jj  ) )                     &
293                     &               * ( e1u(ji,jj  ) * e2u(ji,jj  ) * sshu_n(ji,jj  )     &
294                     &                 + e1u(ji,jj+1) * e2u(ji,jj+1) * sshu_n(ji,jj+1) )
295               END DO
296            END DO
[2715]297            CALL lbc_lnk( sshf_n, 'F', 1. )                 ! Boundaries conditions
298            !
299         ELSE                                         !** Leap-Frog time-stepping: Asselin filter + swap
[2528]300            zec = atfp * rdt / rau0
[1438]301            DO jj = 1, jpj
[2715]302               DO ji = 1, jpi                               ! before <-- now filtered
[2528]303                  sshb  (ji,jj) = sshn  (ji,jj) + atfp * ( sshb(ji,jj) - 2 * sshn(ji,jj) + ssha(ji,jj) )   &
304                     &                          - zec  * ( emp_b(ji,jj) - emp(ji,jj) ) * tmask(ji,jj,1)
[2715]305                  sshn  (ji,jj) = ssha  (ji,jj)             ! now <-- after
[1438]306                  sshu_n(ji,jj) = sshu_a(ji,jj)
307                  sshv_n(ji,jj) = sshv_a(ji,jj)
308               END DO
309            END DO
[2715]310            DO jj = 1, jpjm1                                ! ssh now at f-point
[2528]311               DO ji = 1, jpim1      ! NO Vector Opt.
312                  sshf_n(ji,jj) = 0.5  * umask(ji,jj,1) * umask(ji,jj+1,1)                 &
313                     &               / ( e1f(ji,jj  ) * e2f(ji,jj  ) )                     &
314                     &               * ( e1u(ji,jj  ) * e2u(ji,jj  ) * sshu_n(ji,jj  )     &
315                     &                 + e1u(ji,jj+1) * e2u(ji,jj+1) * sshu_n(ji,jj+1) )
316               END DO
317            END DO
[2715]318            CALL lbc_lnk( sshf_n, 'F', 1. )                 ! Boundaries conditions
319            !
320            DO jj = 1, jpjm1                                ! ssh before at u- & v-points
[2528]321               DO ji = 1, jpim1      ! NO Vector Opt.
322                  sshu_b(ji,jj) = 0.5  * umask(ji,jj,1) / ( e1u(ji  ,jj) * e2u(ji  ,jj) )                   &
323                     &                                  * ( e1t(ji  ,jj) * e2t(ji  ,jj) * sshb(ji  ,jj)     &
324                     &                                    + e1t(ji+1,jj) * e2t(ji+1,jj) * sshb(ji+1,jj) )
325                  sshv_b(ji,jj) = 0.5  * vmask(ji,jj,1) / ( e1v(ji,jj  ) * e2v(ji,jj  ) )                   &
326                     &                                  * ( e1t(ji,jj  ) * e2t(ji,jj  ) * sshb(ji,jj  )     &
327                     &                                    + e1t(ji,jj+1) * e2t(ji,jj+1) * sshb(ji,jj+1) )
328               END DO
329            END DO
330            CALL lbc_lnk( sshu_b, 'U', 1. )
[2715]331            CALL lbc_lnk( sshv_b, 'V', 1. )            !  Boundaries conditions
332            !
[1438]333         ENDIF
[2528]334         !                    !--------------------------!
[2715]335      ELSE                    !        fixed levels      !     (ssh at t-point only)
[2528]336         !                    !--------------------------!
[1438]337         !
[2715]338         IF( neuler == 0 .AND. kt == nit000 ) THEN    !** Euler time-stepping at first time-step : no filter
339            sshn(:,:) = ssha(:,:)                           ! now <-- after  (before already = now)
[1438]340            !
[2715]341         ELSE                                               ! Leap-Frog time-stepping: Asselin filter + swap
[1438]342            DO jj = 1, jpj
[2715]343               DO ji = 1, jpi                               ! before <-- now filtered
[2528]344                  sshb(ji,jj) = sshn(ji,jj) + atfp * ( sshb(ji,jj) - 2 * sshn(ji,jj) + ssha(ji,jj) )
[2715]345                  sshn(ji,jj) = ssha(ji,jj)                 ! now <-- after
[1438]346               END DO
347            END DO
348         ENDIF
349         !
350      ENDIF
351      !
[2528]352      ! Update velocity at AGRIF zoom boundaries
[2486]353#if defined key_agrif
[2528]354      IF ( .NOT.Agrif_Root() ) CALL Agrif_Update_Dyn( kt )
[2486]355#endif
[1438]356      !
[2528]357      IF(ln_ctl)   CALL prt_ctl( tab2d_1=sshb, clinfo1=' sshb  - : ', mask1=tmask, ovlap=1 )
358      !
[3294]359      IF( nn_timing == 1 )  CALL timing_stop('ssh_nxt')
360      !
[1438]361   END SUBROUTINE ssh_nxt
[3]362
363   !!======================================================================
[1565]364END MODULE sshwzv
Note: See TracBrowser for help on using the repository browser.