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

source: branches/DEV_r2191_3partymerge2010/NEMO/OPA_SRC/DYN/dynspg_flt.F90 @ 2208

Last change on this file since 2208 was 2208, checked in by rblod, 14 years ago

Put FCM NEMO code changes in DEV_r2191_3partymerge2010 branch

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