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.
dynspg_flt.F90 in branches/2011/dev_LOCEAN_2011/NEMOGCM/NEMO/OPA_SRC/DYN – NEMO

source: branches/2011/dev_LOCEAN_2011/NEMOGCM/NEMO/OPA_SRC/DYN/dynspg_flt.F90 @ 2977

Last change on this file since 2977 was 2977, checked in by cetlod, 13 years ago

Add in branch 2011/dev_LOCEAN_2011 changes from 2011/dev_r2787_PISCES_improvment, 2011/dev_r2787_LOCEAN_offline_fldread and 2011/dev_r2787_LOCEAN3_TRA_TRP branches, see ticket #877

  • Property svn:keywords set to Id
File size: 19.0 KB
RevLine 
[358]1MODULE dynspg_flt
2   !!======================================================================
3   !!                   ***  MODULE  dynspg_flt  ***
4   !! Ocean dynamics:  surface pressure gradient trend
5   !!======================================================================
[1438]6   !! History    OPA  !  1998-05  (G. Roullet)  free surface
7   !!                 !  1998-10  (G. Madec, M. Imbard)  release 8.2
8   !!   NEMO     O.1  !  2002-08  (G. Madec)  F90: Free form and module
9   !!             -   !  2002-11  (C. Talandier, A-M Treguier) Open boundaries
10   !!            1.0  !  2004-08  (C. Talandier) New trends organization
11   !!             -   !  2005-11  (V. Garnier) Surface pressure gradient organization
12   !!            2.0  !  2006-07  (S. Masson)  distributed restart using iom
13   !!             -   !  2006-08  (J.Chanut, A.Sellar) Calls to BDY routines.
14   !!            3.2  !  2009-03  (G. Madec, M. Leclair, R. Benshila) introduce sshwzv module
[358]15   !!----------------------------------------------------------------------
[575]16#if defined key_dynspg_flt   ||   defined key_esopa 
[508]17   !!----------------------------------------------------------------------
[358]18   !!   'key_dynspg_flt'                              filtered free surface
19   !!----------------------------------------------------------------------
[1601]20   !!   dyn_spg_flt  : update the momentum trend with the surface pressure gradient in the filtered free surface case
[508]21   !!   flt_rst      : read/write the time-splitting restart fields in the ocean restart file
[358]22   !!----------------------------------------------------------------------
23   USE oce             ! ocean dynamics and tracers
24   USE dom_oce         ! ocean space and time domain
25   USE zdf_oce         ! ocean vertical physics
[888]26   USE sbc_oce         ! surface boundary condition: ocean
27   USE obc_oce         ! Lateral open boundary condition
28   USE sol_oce         ! ocean elliptic solver
[719]29   USE phycst          ! physical constants
[888]30   USE domvvl          ! variable volume
[1683]31   USE dynadv          ! advection
[1601]32   USE solmat          ! matrix construction for elliptic solvers
[358]33   USE solpcg          ! preconditionned conjugate gradient solver
34   USE solsor          ! Successive Over-relaxation solver
35   USE obcdyn          ! ocean open boundary condition (obc_dyn routines)
36   USE obcvol          ! ocean open boundary condition (obc_vol routines)
[911]37   USE bdy_oce         ! Unstructured open boundaries condition
38   USE bdydyn          ! Unstructured open boundaries condition (bdy_dyn routine)
39   USE bdyvol          ! Unstructured open boundaries condition (bdy_vol routine)
[2528]40   USE cla             ! cross land advection
[888]41   USE in_out_manager  ! I/O manager
[358]42   USE lib_mpp         ! distributed memory computing library
43   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
44   USE prtctl          ! Print control
[508]45   USE iom
46   USE restart         ! only for lrst_oce
[2528]47   USE lib_fortran
48#if defined key_agrif
49   USE agrif_opa_interp
50#endif
[358]51
52   IMPLICIT NONE
53   PRIVATE
54
[1438]55   PUBLIC   dyn_spg_flt  ! routine called by step.F90
56   PUBLIC   flt_rst      ! routine called by istate.F90
[358]57
58   !! * Substitutions
59#  include "domzgr_substitute.h90"
60#  include "vectopt_loop_substitute.h90"
61   !!----------------------------------------------------------------------
[2528]62   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
[888]63   !! $Id$
[2715]64   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
[358]65   !!----------------------------------------------------------------------
66CONTAINS
67
68   SUBROUTINE dyn_spg_flt( kt, kindic )
69      !!----------------------------------------------------------------------
70      !!                  ***  routine dyn_spg_flt  ***
71      !!
72      !! ** Purpose :   Compute the now trend due to the surface pressure
73      !!      gradient in case of filtered free surface formulation  and add
74      !!      it to the general trend of momentum equation.
75      !!
76      !! ** Method  :   Filtered free surface formulation. The surface
77      !!      pressure gradient is given by:
[1601]78      !!         spgu = 1/rau0 d/dx(ps) =  1/e1u di( sshn + btda )
79      !!         spgv = 1/rau0 d/dy(ps) =  1/e2v dj( sshn + btda )
[358]80      !!      where sshn is the free surface elevation and btda is the after
[1438]81      !!      time derivative of the free surface elevation
82      !!       -1- evaluate the surface presure trend (including the addi-
[358]83      !!      tional force) in three steps:
84      !!        a- compute the right hand side of the elliptic equation:
85      !!            gcb = 1/(e1t e2t) [ di(e2u spgu) + dj(e1v spgv) ]
86      !!         where (spgu,spgv) are given by:
87      !!            spgu = vertical sum[ e3u (ub+ 2 rdt ua ) ]
[2528]88      !!                 - grav 2 rdt hu /e1u di[sshn + (emp-rnf)]
[358]89      !!            spgv = vertical sum[ e3v (vb+ 2 rdt va) ]
[2528]90      !!                 - grav 2 rdt hv /e2v dj[sshn + (emp-rnf)]
[358]91      !!         and define the first guess from previous computation :
92      !!            zbtd = btda
93      !!            btda = 2 zbtd - btdb
94      !!            btdb = zbtd
95      !!        b- compute the relative accuracy to be reached by the
96      !!         iterative solver
97      !!        c- apply the solver by a call to sol... routine
[1438]98      !!       -2- compute and add the free surface pressure gradient inclu-
[358]99      !!      ding the additional force used to stabilize the equation.
100      !!
101      !! ** Action : - Update (ua,va) with the surf. pressure gradient trend
102      !!
[508]103      !! References : Roullet and Madec 1999, JGR.
[358]104      !!---------------------------------------------------------------------
[2977]105      USE oce, ONLY:   tsa                 ! tsa used as 2 3D workspace
[1438]106      !!
[1601]107      INTEGER, INTENT(in   ) ::   kt       ! ocean time-step index
108      INTEGER, INTENT(  out) ::   kindic   ! solver convergence flag (<0 if not converge)
[508]109      !!                                   
[2715]110      INTEGER  ::   ji, jj, jk   ! dummy loop indices
111      REAL(wp) ::   z2dt, z2dtg, zgcb, zbtd, ztdgu, ztdgv   ! local scalars
[2977]112      REAL(wp), POINTER, DIMENSION(:,:,:) ::  zub, zvb
[358]113      !!----------------------------------------------------------------------
[508]114      !
[2977]115      zub => tsa(:,:,:,1) 
116      zvb => tsa(:,:,:,2) 
117      !
[358]118      IF( kt == nit000 ) THEN
119         IF(lwp) WRITE(numout,*)
120         IF(lwp) WRITE(numout,*) 'dyn_spg_flt : surface pressure gradient trend'
121         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~   (free surface constant volume case)'
122       
123         ! set to zero free surface specific arrays
[2715]124         spgu(:,:) = 0._wp                     ! surface pressure gradient (i-direction)
125         spgv(:,:) = 0._wp                     ! surface pressure gradient (j-direction)
[508]126
127         ! read filtered free surface arrays in restart file
[1200]128         ! when using agrif, sshn, gcx have to be read in istate
[1601]129         IF(.NOT. lk_agrif)   CALL flt_rst( nit000, 'READ' )      ! read or initialize the following fields:
[1438]130         !                                                        ! gcx, gcxb
[358]131      ENDIF
132
133      ! Local constant initialization
[1601]134      z2dt = 2. * rdt                                             ! time step: leap-frog
135      IF( neuler == 0 .AND. kt == nit000   )   z2dt = rdt         ! time step: Euler if restart from rest
136      IF( neuler == 0 .AND. kt == nit000+1 )   CALL sol_mat( kt )
[358]137      z2dtg  = grav * z2dt
138
[1683]139      ! Evaluate the masked next velocity (effect of the additional force not included)
140      ! --------------------------------- 
141      IF( lk_vvl ) THEN          ! variable volume  (surface pressure gradient already included in dyn_hpg)
142         !
143         IF( ln_dynadv_vec ) THEN      ! vector form : applied on velocity
144            DO jk = 1, jpkm1
145               DO jj = 2, jpjm1
146                  DO ji = fs_2, fs_jpim1   ! vector opt.
147                     ua(ji,jj,jk) = (  ub(ji,jj,jk) + z2dt * ua(ji,jj,jk)  ) * umask(ji,jj,jk)
148                     va(ji,jj,jk) = (  vb(ji,jj,jk) + z2dt * va(ji,jj,jk)  ) * vmask(ji,jj,jk)
149                  END DO
[592]150               END DO
151            END DO
[1683]152            !
153         ELSE                          ! flux form : applied on thickness weighted velocity
154            DO jk = 1, jpkm1
155               DO jj = 2, jpjm1
156                  DO ji = fs_2, fs_jpim1   ! vector opt.
157                     ua(ji,jj,jk) = (        ub(ji,jj,jk) * fse3u_b(ji,jj,jk)      &
158                        &           + z2dt * ua(ji,jj,jk) * fse3u_n(ji,jj,jk)  )   &
159                        &         / fse3u_a(ji,jj,jk) * umask(ji,jj,jk)
160                     va(ji,jj,jk) = (        vb(ji,jj,jk) * fse3v_b(ji,jj,jk)      &
161                        &           + z2dt * va(ji,jj,jk) * fse3v_n(ji,jj,jk)  )   &
162                        &         / fse3v_a(ji,jj,jk) * vmask(ji,jj,jk)
163                 END DO
164               END DO
165            END DO
166            !
167         ENDIF
168         !
169      ELSE                       ! fixed volume  (add the surface pressure gradient + unweighted time stepping)
170         !
171         DO jj = 2, jpjm1              ! Surface pressure gradient (now)
[358]172            DO ji = fs_2, fs_jpim1   ! vector opt.
[592]173               spgu(ji,jj) = - grav * ( sshn(ji+1,jj) - sshn(ji,jj) ) / e1u(ji,jj)
174               spgv(ji,jj) = - grav * ( sshn(ji,jj+1) - sshn(ji,jj) ) / e2v(ji,jj)
175            END DO
176         END DO
[1683]177         DO jk = 1, jpkm1              ! unweighted time stepping
[592]178            DO jj = 2, jpjm1
179               DO ji = fs_2, fs_jpim1   ! vector opt.
[1438]180                  ua(ji,jj,jk) = (  ub(ji,jj,jk) + z2dt * ( ua(ji,jj,jk) + spgu(ji,jj) )  ) * umask(ji,jj,jk)
181                  va(ji,jj,jk) = (  vb(ji,jj,jk) + z2dt * ( va(ji,jj,jk) + spgv(ji,jj) )  ) * vmask(ji,jj,jk)
[592]182               END DO
[358]183            END DO
184         END DO
[1438]185         !
[592]186      ENDIF
187
[358]188#if defined key_obc
[2528]189      CALL obc_dyn( kt )      ! Update velocities on each open boundary with the radiation algorithm
190      CALL obc_vol( kt )      ! Correction of the barotropic componant velocity to control the volume of the system
[358]191#endif
[911]192#if defined key_bdy
[2528]193      CALL bdy_dyn_frs( kt )       ! Update velocities on unstructured boundary using the Flow Relaxation Scheme
194      CALL bdy_vol( kt )           ! Correction of the barotropic component velocity to control the volume of the system
[911]195#endif
[392]196#if defined key_agrif
[508]197      CALL Agrif_dyn( kt )    ! Update velocities on each coarse/fine interfaces
[389]198#endif
[2528]199      IF( nn_cla == 1 )   CALL cla_dynspg( kt )      ! Cross Land Advection (update (ua,va))
[358]200
201      ! compute the next vertically averaged velocity (effect of the additional force not included)
202      ! ---------------------------------------------
203      DO jj = 2, jpjm1
204         DO ji = fs_2, fs_jpim1   ! vector opt.
[2715]205            spgu(ji,jj) = 0._wp
206            spgv(ji,jj) = 0._wp
[358]207         END DO
208      END DO
209
210      ! vertical sum
211!CDIR NOLOOPCHG
212      IF( lk_vopt_loop ) THEN          ! vector opt., forced unroll
213         DO jk = 1, jpkm1
214            DO ji = 1, jpij
215               spgu(ji,1) = spgu(ji,1) + fse3u(ji,1,jk) * ua(ji,1,jk)
216               spgv(ji,1) = spgv(ji,1) + fse3v(ji,1,jk) * va(ji,1,jk)
217            END DO
218         END DO
219      ELSE                        ! No  vector opt.
220         DO jk = 1, jpkm1
221            DO jj = 2, jpjm1
222               DO ji = 2, jpim1
223                  spgu(ji,jj) = spgu(ji,jj) + fse3u(ji,jj,jk) * ua(ji,jj,jk)
224                  spgv(ji,jj) = spgv(ji,jj) + fse3v(ji,jj,jk) * va(ji,jj,jk)
225               END DO
226            END DO
227         END DO
228      ENDIF
229
230      ! transport: multiplied by the horizontal scale factor
231      DO jj = 2, jpjm1
232         DO ji = fs_2, fs_jpim1   ! vector opt.
233            spgu(ji,jj) = spgu(ji,jj) * e2u(ji,jj)
234            spgv(ji,jj) = spgv(ji,jj) * e1v(ji,jj)
235         END DO
236      END DO
[1601]237      CALL lbc_lnk( spgu, 'U', -1. )       ! lateral boundary conditions
[358]238      CALL lbc_lnk( spgv, 'V', -1. )
239
[1438]240      IF( lk_vvl ) CALL sol_mat( kt )      ! build the matrix at kt (vvl case only)
[592]241
[358]242      ! Right hand side of the elliptic equation and first guess
[1601]243      ! --------------------------------------------------------
[358]244      DO jj = 2, jpjm1
245         DO ji = fs_2, fs_jpim1   ! vector opt.
246            ! Divergence of the after vertically averaged velocity
247            zgcb =  spgu(ji,jj) - spgu(ji-1,jj)   &
248                  + spgv(ji,jj) - spgv(ji,jj-1)
249            gcb(ji,jj) = gcdprc(ji,jj) * zgcb
250            ! First guess of the after barotropic transport divergence
251            zbtd = gcx(ji,jj)
252            gcx (ji,jj) = 2. * zbtd   - gcxb(ji,jj)
253            gcxb(ji,jj) =      zbtd
254         END DO
255      END DO
256      ! applied the lateral boundary conditions
[1601]257      IF( nn_solv == 2 .AND. MAX( jpr2di, jpr2dj ) > 0 )   CALL lbc_lnk_e( gcb, c_solver_pt, 1. )   
[358]258
[392]259#if defined key_agrif
[413]260      IF( .NOT. AGRIF_ROOT() ) THEN
[389]261         ! add contribution of gradient of after barotropic transport divergence
[508]262         IF( nbondi == -1 .OR. nbondi == 2 )   gcb(3     ,:) =   &
[1601]263            &    gcb(3     ,:) - z2dtg * z2dt * laplacu(2     ,:) * gcdprc(3     ,:) * hu(2     ,:) * e2u(2     ,:)
[508]264         IF( nbondi ==  1 .OR. nbondi == 2 )   gcb(nlci-2,:) =   &
[1601]265            &    gcb(nlci-2,:) + z2dtg * z2dt * laplacu(nlci-2,:) * gcdprc(nlci-2,:) * hu(nlci-2,:) * e2u(nlci-2,:)
[508]266         IF( nbondj == -1 .OR. nbondj == 2 )   gcb(:     ,3) =   &
[1601]267            &    gcb(:,3     ) - z2dtg * z2dt * laplacv(:,2     ) * gcdprc(:,3     ) * hv(:,2     ) * e1v(:,2     )
[508]268         IF( nbondj ==  1 .OR. nbondj == 2 )   gcb(:,nlcj-2) =   &
[1601]269            &    gcb(:,nlcj-2) + z2dtg * z2dt * laplacv(:,nlcj-2) * gcdprc(:,nlcj-2) * hv(:,nlcj-2) * e1v(:,nlcj-2)
[413]270      ENDIF
[389]271#endif
272
273
[358]274      ! Relative precision (computation on one processor)
275      ! ------------------
[1438]276      rnorme =0.e0
[2528]277      rnorme = GLOB_SUM( gcb(1:jpi,1:jpj) * gcdmat(1:jpi,1:jpj) * gcb(1:jpi,1:jpj) * bmask(:,:) )
[358]278
279      epsr = eps * eps * rnorme
280      ncut = 0
[508]281      ! if rnorme is 0, the solution is 0, the solver is not called
[2715]282      IF( rnorme == 0._wp ) THEN
283         gcx(:,:) = 0._wp
284         res   = 0._wp
[358]285         niter = 0
286         ncut  = 999
287      ENDIF
288
289      ! Evaluate the next transport divergence
290      ! --------------------------------------
291      !    Iterarive solver for the elliptic equation (except IF sol.=0)
292      !    (output in gcx with boundary conditions applied)
293      kindic = 0
294      IF( ncut == 0 ) THEN
[1601]295         IF    ( nn_solv == 1 ) THEN   ;   CALL sol_pcg( kindic )      ! diagonal preconditioned conjuguate gradient
296         ELSEIF( nn_solv == 2 ) THEN   ;   CALL sol_sor( kindic )      ! successive-over-relaxation
[358]297         ENDIF
298      ENDIF
299
300      ! Transport divergence gradient multiplied by z2dt
301      ! --------------------------------------------====
302      DO jj = 2, jpjm1
303         DO ji = fs_2, fs_jpim1   ! vector opt.
304            ! trend of Transport divergence gradient
[1601]305            ztdgu = z2dtg * (gcx(ji+1,jj  ) - gcx(ji,jj) ) / e1u(ji,jj)
306            ztdgv = z2dtg * (gcx(ji  ,jj+1) - gcx(ji,jj) ) / e2v(ji,jj)
[358]307            ! multiplied by z2dt
308#if defined key_obc
309            ! caution : grad D = 0 along open boundaries
[2528]310            spgu(ji,jj) = z2dt * ztdgu * obcumask(ji,jj)
311            spgv(ji,jj) = z2dt * ztdgv * obcvmask(ji,jj)
[911]312#elif defined key_bdy
313            ! caution : grad D = 0 along open boundaries
314            ! Remark: The filtering force could be reduced here in the FRS zone
315            !         by multiplying spgu/spgv by (1-alpha) ?? 
316            spgu(ji,jj) = z2dt * ztdgu * bdyumask(ji,jj)
317            spgv(ji,jj) = z2dt * ztdgv * bdyvmask(ji,jj)           
[358]318#else
319            spgu(ji,jj) = z2dt * ztdgu
320            spgv(ji,jj) = z2dt * ztdgv
321#endif
322         END DO
323      END DO
324
[1876]325#if defined key_agrif     
[413]326      IF( .NOT. Agrif_Root() ) THEN
327         ! caution : grad D (fine) = grad D (coarse) at coarse/fine interface
[1601]328         IF( nbondi == -1 .OR. nbondi == 2 ) spgu(2     ,:) = z2dtg * z2dt * laplacu(2     ,:) * umask(2     ,:,1)
329         IF( nbondi ==  1 .OR. nbondi == 2 ) spgu(nlci-2,:) = z2dtg * z2dt * laplacu(nlci-2,:) * umask(nlci-2,:,1)
330         IF( nbondj == -1 .OR. nbondj == 2 ) spgv(:,2     ) = z2dtg * z2dt * laplacv(:,2     ) * vmask(:     ,2,1)
331         IF( nbondj ==  1 .OR. nbondj == 2 ) spgv(:,nlcj-2) = z2dtg * z2dt * laplacv(:,nlcj-2) * vmask(:,nlcj-2,1)
[389]332      ENDIF
[1876]333#endif     
[1438]334      ! Add the trends multiplied by z2dt to the after velocity
335      ! -------------------------------------------------------
[358]336      !     ( c a u t i o n : (ua,va) here are the after velocity not the
337      !                       trend, the leap-frog time stepping will not
[508]338      !                       be done in dynnxt.F90 routine)
[358]339      DO jk = 1, jpkm1
340         DO jj = 2, jpjm1
341            DO ji = fs_2, fs_jpim1   ! vector opt.
[1438]342               ua(ji,jj,jk) = ( ua(ji,jj,jk) + spgu(ji,jj) ) * umask(ji,jj,jk)
343               va(ji,jj,jk) = ( va(ji,jj,jk) + spgv(ji,jj) ) * vmask(ji,jj,jk)
[358]344            END DO
345         END DO
346      END DO
347
[508]348      ! write filtered free surface arrays in restart file
349      ! --------------------------------------------------
350      IF( lrst_oce ) CALL flt_rst( kt, 'WRITE' )
351      !
[358]352   END SUBROUTINE dyn_spg_flt
353
[508]354
355   SUBROUTINE flt_rst( kt, cdrw )
[2715]356      !!---------------------------------------------------------------------
357      !!                   ***  ROUTINE ts_rst  ***
358      !!
359      !! ** Purpose : Read or write filtered free surface arrays in restart file
360      !!----------------------------------------------------------------------
361      INTEGER         , INTENT(in) ::   kt         ! ocean time-step
362      CHARACTER(len=*), INTENT(in) ::   cdrw       ! "READ"/"WRITE" flag
363      !!----------------------------------------------------------------------
364      !
365      IF( TRIM(cdrw) == 'READ' ) THEN
366         IF( iom_varid( numror, 'gcx', ldstop = .FALSE. ) > 0 ) THEN
[508]367! Caution : extra-hallow
368! gcx and gcxb are defined as: DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj)
[2715]369            CALL iom_get( numror, jpdom_autoglo, 'gcx' , gcx (1:jpi,1:jpj) )
370            CALL iom_get( numror, jpdom_autoglo, 'gcxb', gcxb(1:jpi,1:jpj) )
371            IF( neuler == 0 )   gcxb(:,:) = gcx (:,:)
372         ELSE
373            gcx (:,:) = 0.e0
374            gcxb(:,:) = 0.e0
375         ENDIF
376      ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN
[508]377! Caution : extra-hallow
378! gcx and gcxb are defined as: DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj)
[2715]379         CALL iom_rstput( kt, nitrst, numrow, 'gcx' , gcx (1:jpi,1:jpj) )
380         CALL iom_rstput( kt, nitrst, numrow, 'gcxb', gcxb(1:jpi,1:jpj) )
381      ENDIF
382      !
[508]383   END SUBROUTINE flt_rst
384
[358]385#else
386   !!----------------------------------------------------------------------
387   !!   Default case :   Empty module   No standart free surface cst volume
388   !!----------------------------------------------------------------------
389CONTAINS
390   SUBROUTINE dyn_spg_flt( kt, kindic )       ! Empty routine
391      WRITE(*,*) 'dyn_spg_flt: You should not have seen this print! error?', kt, kindic
392   END SUBROUTINE dyn_spg_flt
[657]393   SUBROUTINE flt_rst    ( kt, cdrw )         ! Empty routine
394      INTEGER         , INTENT(in) ::   kt         ! ocean time-step
395      CHARACTER(len=*), INTENT(in) ::   cdrw       ! "READ"/"WRITE" flag
396      WRITE(*,*) 'flt_rst: You should not have seen this print! error?', kt, cdrw
397   END SUBROUTINE flt_rst
[358]398#endif
399   
400   !!======================================================================
401END MODULE dynspg_flt
Note: See TracBrowser for help on using the repository browser.