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

source: branches/2011/dev_NEMO_MERGE_2011/NEMOGCM/NEMO/OPA_SRC/DYN/dynspg_flt.F90 @ 3161

Last change on this file since 3161 was 3161, checked in by cetlod, 12 years ago

New dynamical allocation & timing in OPA_SRC/DYN routines

  • Property svn:keywords set to Id
File size: 19.0 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 bdy_oce         ! Lateral open boundary condition
29   USE sol_oce         ! ocean elliptic solver
30   USE phycst          ! physical constants
31   USE domvvl          ! variable volume
32   USE dynadv          ! advection
33   USE solmat          ! matrix construction for elliptic solvers
34   USE solpcg          ! preconditionned conjugate gradient solver
35   USE solsor          ! Successive Over-relaxation solver
36   USE obcdyn          ! ocean open boundary condition on dynamics
37   USE obcvol          ! ocean open boundary condition (obc_vol routine)
38   USE bdydyn          ! ocean open boundary condition on dynamics
39   USE bdyvol          ! ocean open boundary condition (bdy_vol routine)
40   USE cla             ! cross land advection
41   USE in_out_manager  ! I/O manager
42   USE lib_mpp         ! distributed memory computing library
43   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
44   USE prtctl          ! Print control
45   USE iom
46   USE restart         ! only for lrst_oce
47   USE lib_fortran
48#if defined key_agrif
49   USE agrif_opa_interp
50#endif
51   USE timing          ! Timing
52
53   IMPLICIT NONE
54   PRIVATE
55
56   PUBLIC   dyn_spg_flt  ! routine called by step.F90
57   PUBLIC   flt_rst      ! routine called by istate.F90
58
59   !! * Substitutions
60#  include "domzgr_substitute.h90"
61#  include "vectopt_loop_substitute.h90"
62   !!----------------------------------------------------------------------
63   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
64   !! $Id$
65   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
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:   tsa                 ! tsa used as 2 3D workspace
107      !!
108      INTEGER, INTENT(in   ) ::   kt       ! ocean time-step index
109      INTEGER, INTENT(  out) ::   kindic   ! solver convergence flag (<0 if not converge)
110      !!                                   
111      INTEGER  ::   ji, jj, jk   ! dummy loop indices
112      REAL(wp) ::   z2dt, z2dtg, zgcb, zbtd, ztdgu, ztdgv   ! local scalars
113      REAL(wp), POINTER, DIMENSION(:,:,:) ::  zub, zvb
114      !!----------------------------------------------------------------------
115      !
116      IF( nn_timing == 1 )  CALL timing_start('dyn_spg_flt')
117      !
118      zub => tsa(:,:,:,1) 
119      zvb => tsa(:,:,:,2) 
120      !
121      IF( kt == nit000 ) THEN
122         IF(lwp) WRITE(numout,*)
123         IF(lwp) WRITE(numout,*) 'dyn_spg_flt : surface pressure gradient trend'
124         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~   (free surface constant volume case)'
125       
126         ! set to zero free surface specific arrays
127         spgu(:,:) = 0._wp                     ! surface pressure gradient (i-direction)
128         spgv(:,:) = 0._wp                     ! surface pressure gradient (j-direction)
129
130         ! read filtered free surface arrays in restart file
131         ! when using agrif, sshn, gcx have to be read in istate
132         IF(.NOT. lk_agrif)   CALL flt_rst( nit000, 'READ' )      ! read or initialize the following fields:
133         !                                                        ! gcx, gcxb
134      ENDIF
135
136      ! Local constant initialization
137      z2dt = 2. * rdt                                             ! time step: leap-frog
138      IF( neuler == 0 .AND. kt == nit000   )   z2dt = rdt         ! time step: Euler if restart from rest
139      IF( neuler == 0 .AND. kt == nit000+1 )   CALL sol_mat( kt )
140      z2dtg  = grav * z2dt
141
142      ! Evaluate the masked next velocity (effect of the additional force not included)
143      ! --------------------------------- 
144      IF( lk_vvl ) THEN          ! variable volume  (surface pressure gradient already included in dyn_hpg)
145         !
146         IF( ln_dynadv_vec ) THEN      ! vector form : applied on velocity
147            DO jk = 1, jpkm1
148               DO jj = 2, jpjm1
149                  DO ji = fs_2, fs_jpim1   ! vector opt.
150                     ua(ji,jj,jk) = (  ub(ji,jj,jk) + z2dt * ua(ji,jj,jk)  ) * umask(ji,jj,jk)
151                     va(ji,jj,jk) = (  vb(ji,jj,jk) + z2dt * va(ji,jj,jk)  ) * vmask(ji,jj,jk)
152                  END DO
153               END DO
154            END DO
155            !
156         ELSE                          ! flux form : applied on thickness weighted velocity
157            DO jk = 1, jpkm1
158               DO jj = 2, jpjm1
159                  DO ji = fs_2, fs_jpim1   ! vector opt.
160                     ua(ji,jj,jk) = (        ub(ji,jj,jk) * fse3u_b(ji,jj,jk)      &
161                        &           + z2dt * ua(ji,jj,jk) * fse3u_n(ji,jj,jk)  )   &
162                        &         / fse3u_a(ji,jj,jk) * umask(ji,jj,jk)
163                     va(ji,jj,jk) = (        vb(ji,jj,jk) * fse3v_b(ji,jj,jk)      &
164                        &           + z2dt * va(ji,jj,jk) * fse3v_n(ji,jj,jk)  )   &
165                        &         / fse3v_a(ji,jj,jk) * vmask(ji,jj,jk)
166                 END DO
167               END DO
168            END DO
169            !
170         ENDIF
171         !
172      ELSE                       ! fixed volume  (add the surface pressure gradient + unweighted time stepping)
173         !
174         DO jj = 2, jpjm1              ! Surface pressure gradient (now)
175            DO ji = fs_2, fs_jpim1   ! vector opt.
176               spgu(ji,jj) = - grav * ( sshn(ji+1,jj) - sshn(ji,jj) ) / e1u(ji,jj)
177               spgv(ji,jj) = - grav * ( sshn(ji,jj+1) - sshn(ji,jj) ) / e2v(ji,jj)
178            END DO
179         END DO
180         DO jk = 1, jpkm1              ! unweighted time stepping
181            DO jj = 2, jpjm1
182               DO ji = fs_2, fs_jpim1   ! vector opt.
183                  ua(ji,jj,jk) = (  ub(ji,jj,jk) + z2dt * ( ua(ji,jj,jk) + spgu(ji,jj) )  ) * umask(ji,jj,jk)
184                  va(ji,jj,jk) = (  vb(ji,jj,jk) + z2dt * ( va(ji,jj,jk) + spgv(ji,jj) )  ) * vmask(ji,jj,jk)
185               END DO
186            END DO
187         END DO
188         !
189      ENDIF
190
191#if defined key_obc
192      CALL obc_dyn( kt )      ! Update velocities on each open boundary with the radiation algorithm
193      CALL obc_vol( kt )      ! Correction of the barotropic componant velocity to control the volume of the system
194#endif
195#if defined key_bdy
196      CALL bdy_dyn( kt )      ! Update velocities on each open boundary
197      CALL bdy_vol( kt )      ! Correction of the barotropic component velocity to control the volume of the system
198#endif
199#if defined key_agrif
200      CALL Agrif_dyn( kt )    ! Update velocities on each coarse/fine interfaces
201#endif
202      IF( nn_cla == 1 )   CALL cla_dynspg( kt )      ! Cross Land Advection (update (ua,va))
203
204      ! compute the next vertically averaged velocity (effect of the additional force not included)
205      ! ---------------------------------------------
206      DO jj = 2, jpjm1
207         DO ji = fs_2, fs_jpim1   ! vector opt.
208            spgu(ji,jj) = 0._wp
209            spgv(ji,jj) = 0._wp
210         END DO
211      END DO
212
213      ! vertical sum
214!CDIR NOLOOPCHG
215      IF( lk_vopt_loop ) THEN          ! vector opt., forced unroll
216         DO jk = 1, jpkm1
217            DO ji = 1, jpij
218               spgu(ji,1) = spgu(ji,1) + fse3u(ji,1,jk) * ua(ji,1,jk)
219               spgv(ji,1) = spgv(ji,1) + fse3v(ji,1,jk) * va(ji,1,jk)
220            END DO
221         END DO
222      ELSE                        ! No  vector opt.
223         DO jk = 1, jpkm1
224            DO jj = 2, jpjm1
225               DO ji = 2, jpim1
226                  spgu(ji,jj) = spgu(ji,jj) + fse3u(ji,jj,jk) * ua(ji,jj,jk)
227                  spgv(ji,jj) = spgv(ji,jj) + fse3v(ji,jj,jk) * va(ji,jj,jk)
228               END DO
229            END DO
230         END DO
231      ENDIF
232
233      ! transport: multiplied by the horizontal scale factor
234      DO jj = 2, jpjm1
235         DO ji = fs_2, fs_jpim1   ! vector opt.
236            spgu(ji,jj) = spgu(ji,jj) * e2u(ji,jj)
237            spgv(ji,jj) = spgv(ji,jj) * e1v(ji,jj)
238         END DO
239      END DO
240      CALL lbc_lnk( spgu, 'U', -1. )       ! lateral boundary conditions
241      CALL lbc_lnk( spgv, 'V', -1. )
242
243      IF( lk_vvl ) CALL sol_mat( kt )      ! build the matrix at kt (vvl case only)
244
245      ! Right hand side of the elliptic equation and first guess
246      ! --------------------------------------------------------
247      DO jj = 2, jpjm1
248         DO ji = fs_2, fs_jpim1   ! vector opt.
249            ! Divergence of the after vertically averaged velocity
250            zgcb =  spgu(ji,jj) - spgu(ji-1,jj)   &
251                  + spgv(ji,jj) - spgv(ji,jj-1)
252            gcb(ji,jj) = gcdprc(ji,jj) * zgcb
253            ! First guess of the after barotropic transport divergence
254            zbtd = gcx(ji,jj)
255            gcx (ji,jj) = 2. * zbtd   - gcxb(ji,jj)
256            gcxb(ji,jj) =      zbtd
257         END DO
258      END DO
259      ! applied the lateral boundary conditions
260      IF( nn_solv == 2 .AND. MAX( jpr2di, jpr2dj ) > 0 )   CALL lbc_lnk_e( gcb, c_solver_pt, 1. )   
261
262#if defined key_agrif
263      IF( .NOT. AGRIF_ROOT() ) THEN
264         ! add contribution of gradient of after barotropic transport divergence
265         IF( nbondi == -1 .OR. nbondi == 2 )   gcb(3     ,:) =   &
266            &    gcb(3     ,:) - z2dtg * z2dt * laplacu(2     ,:) * gcdprc(3     ,:) * hu(2     ,:) * e2u(2     ,:)
267         IF( nbondi ==  1 .OR. nbondi == 2 )   gcb(nlci-2,:) =   &
268            &    gcb(nlci-2,:) + z2dtg * z2dt * laplacu(nlci-2,:) * gcdprc(nlci-2,:) * hu(nlci-2,:) * e2u(nlci-2,:)
269         IF( nbondj == -1 .OR. nbondj == 2 )   gcb(:     ,3) =   &
270            &    gcb(:,3     ) - z2dtg * z2dt * laplacv(:,2     ) * gcdprc(:,3     ) * hv(:,2     ) * e1v(:,2     )
271         IF( nbondj ==  1 .OR. nbondj == 2 )   gcb(:,nlcj-2) =   &
272            &    gcb(:,nlcj-2) + z2dtg * z2dt * laplacv(:,nlcj-2) * gcdprc(:,nlcj-2) * hv(:,nlcj-2) * e1v(:,nlcj-2)
273      ENDIF
274#endif
275
276
277      ! Relative precision (computation on one processor)
278      ! ------------------
279      rnorme =0.e0
280      rnorme = GLOB_SUM( gcb(1:jpi,1:jpj) * gcdmat(1:jpi,1:jpj) * gcb(1:jpi,1:jpj) * bmask(:,:) )
281
282      epsr = eps * eps * rnorme
283      ncut = 0
284      ! if rnorme is 0, the solution is 0, the solver is not called
285      IF( rnorme == 0._wp ) THEN
286         gcx(:,:) = 0._wp
287         res   = 0._wp
288         niter = 0
289         ncut  = 999
290      ENDIF
291
292      ! Evaluate the next transport divergence
293      ! --------------------------------------
294      !    Iterarive solver for the elliptic equation (except IF sol.=0)
295      !    (output in gcx with boundary conditions applied)
296      kindic = 0
297      IF( ncut == 0 ) THEN
298         IF    ( nn_solv == 1 ) THEN   ;   CALL sol_pcg( kindic )      ! diagonal preconditioned conjuguate gradient
299         ELSEIF( nn_solv == 2 ) THEN   ;   CALL sol_sor( kindic )      ! successive-over-relaxation
300         ENDIF
301      ENDIF
302
303      ! Transport divergence gradient multiplied by z2dt
304      ! --------------------------------------------====
305      DO jj = 2, jpjm1
306         DO ji = fs_2, fs_jpim1   ! vector opt.
307            ! trend of Transport divergence gradient
308            ztdgu = z2dtg * (gcx(ji+1,jj  ) - gcx(ji,jj) ) / e1u(ji,jj)
309            ztdgv = z2dtg * (gcx(ji  ,jj+1) - gcx(ji,jj) ) / e2v(ji,jj)
310            ! multiplied by z2dt
311#if defined key_obc
312            ! caution : grad D = 0 along open boundaries
313            ! Remark: The filtering force could be reduced here in the FRS zone
314            !         by multiplying spgu/spgv by (1-alpha) ?? 
315            spgu(ji,jj) = z2dt * ztdgu * obcumask(ji,jj)
316            spgv(ji,jj) = z2dt * ztdgv * obcvmask(ji,jj)
317#elif defined key_bdy
318            ! caution : grad D = 0 along open boundaries
319            spgu(ji,jj) = z2dt * ztdgu * bdyumask(ji,jj)
320            spgv(ji,jj) = z2dt * ztdgv * bdyvmask(ji,jj)
321#else
322            spgu(ji,jj) = z2dt * ztdgu
323            spgv(ji,jj) = z2dt * ztdgv
324#endif
325         END DO
326      END DO
327
328#if defined key_agrif     
329      IF( .NOT. Agrif_Root() ) THEN
330         ! caution : grad D (fine) = grad D (coarse) at coarse/fine interface
331         IF( nbondi == -1 .OR. nbondi == 2 ) spgu(2     ,:) = z2dtg * z2dt * laplacu(2     ,:) * umask(2     ,:,1)
332         IF( nbondi ==  1 .OR. nbondi == 2 ) spgu(nlci-2,:) = z2dtg * z2dt * laplacu(nlci-2,:) * umask(nlci-2,:,1)
333         IF( nbondj == -1 .OR. nbondj == 2 ) spgv(:,2     ) = z2dtg * z2dt * laplacv(:,2     ) * vmask(:     ,2,1)
334         IF( nbondj ==  1 .OR. nbondj == 2 ) spgv(:,nlcj-2) = z2dtg * z2dt * laplacv(:,nlcj-2) * vmask(:,nlcj-2,1)
335      ENDIF
336#endif     
337      ! Add the trends multiplied by z2dt to the after velocity
338      ! -------------------------------------------------------
339      !     ( c a u t i o n : (ua,va) here are the after velocity not the
340      !                       trend, the leap-frog time stepping will not
341      !                       be done in dynnxt.F90 routine)
342      DO jk = 1, jpkm1
343         DO jj = 2, jpjm1
344            DO ji = fs_2, fs_jpim1   ! vector opt.
345               ua(ji,jj,jk) = ( ua(ji,jj,jk) + spgu(ji,jj) ) * umask(ji,jj,jk)
346               va(ji,jj,jk) = ( va(ji,jj,jk) + spgv(ji,jj) ) * vmask(ji,jj,jk)
347            END DO
348         END DO
349      END DO
350
351      ! write filtered free surface arrays in restart file
352      ! --------------------------------------------------
353      IF( lrst_oce ) CALL flt_rst( kt, 'WRITE' )
354      !
355      IF( nn_timing == 1 )  CALL timing_stop('dyn_spg_flt')
356      !
357   END SUBROUTINE dyn_spg_flt
358
359
360   SUBROUTINE flt_rst( kt, cdrw )
361      !!---------------------------------------------------------------------
362      !!                   ***  ROUTINE ts_rst  ***
363      !!
364      !! ** Purpose : Read or write filtered free surface arrays in restart file
365      !!----------------------------------------------------------------------
366      INTEGER         , INTENT(in) ::   kt         ! ocean time-step
367      CHARACTER(len=*), INTENT(in) ::   cdrw       ! "READ"/"WRITE" flag
368      !!----------------------------------------------------------------------
369      !
370      IF( TRIM(cdrw) == 'READ' ) THEN
371         IF( iom_varid( numror, 'gcx', ldstop = .FALSE. ) > 0 ) THEN
372! Caution : extra-hallow
373! gcx and gcxb are defined as: DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj)
374            CALL iom_get( numror, jpdom_autoglo, 'gcx' , gcx (1:jpi,1:jpj) )
375            CALL iom_get( numror, jpdom_autoglo, 'gcxb', gcxb(1:jpi,1:jpj) )
376            IF( neuler == 0 )   gcxb(:,:) = gcx (:,:)
377         ELSE
378            gcx (:,:) = 0.e0
379            gcxb(:,:) = 0.e0
380         ENDIF
381      ELSEIF( TRIM(cdrw) == 'WRITE' ) THEN
382! Caution : extra-hallow
383! gcx and gcxb are defined as: DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj)
384         CALL iom_rstput( kt, nitrst, numrow, 'gcx' , gcx (1:jpi,1:jpj) )
385         CALL iom_rstput( kt, nitrst, numrow, 'gcxb', gcxb(1:jpi,1:jpj) )
386      ENDIF
387      !
388   END SUBROUTINE flt_rst
389
390#else
391   !!----------------------------------------------------------------------
392   !!   Default case :   Empty module   No standart free surface cst volume
393   !!----------------------------------------------------------------------
394CONTAINS
395   SUBROUTINE dyn_spg_flt( kt, kindic )       ! Empty routine
396      WRITE(*,*) 'dyn_spg_flt: You should not have seen this print! error?', kt, kindic
397   END SUBROUTINE dyn_spg_flt
398   SUBROUTINE flt_rst    ( kt, cdrw )         ! Empty routine
399      INTEGER         , INTENT(in) ::   kt         ! ocean time-step
400      CHARACTER(len=*), INTENT(in) ::   cdrw       ! "READ"/"WRITE" flag
401      WRITE(*,*) 'flt_rst: You should not have seen this print! error?', kt, cdrw
402   END SUBROUTINE flt_rst
403#endif
404   
405   !!======================================================================
406END MODULE dynspg_flt
Note: See TracBrowser for help on using the repository browser.