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

source: branches/dev_005_AWL/NEMO/OPA_SRC/DYN/dynspg_flt.F90 @ 1804

Last change on this file since 1804 was 1804, checked in by sga, 14 years ago

merge of trunk changes from r1782 to r1802 into NEMO branch dev_005_AWL

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