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

source: branches/nemo_v3_3_beta/NEMOGCM/NEMO/OPA_SRC/DYN/dynspg_flt.F90 @ 2287

Last change on this file since 2287 was 2287, checked in by smasson, 14 years ago

update licence of all NEMO files...

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