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

source: trunk/NEMO/OPA_SRC/DYN/dynspg_flt.F90 @ 1566

Last change on this file since 1566 was 1556, checked in by rblod, 15 years ago

Suppress FETI solver, see ticket #502

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