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

source: branches/2011/DEV_r2739_STFC_dCSE/NEMOGCM/NEMO/OPA_SRC/DYN/dynspg_flt.F90 @ 3211

Last change on this file since 3211 was 3211, checked in by spickles2, 13 years ago

Stephen Pickles, 11 Dec 2011

Commit to bring the rest of the DCSE NEMO development branch
in line with the latest development version. This includes
array index re-ordering of all OPA_SRC/.

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