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_fsc.F90 in trunk/NEMO/OPA_SRC/DYN – NEMO

source: trunk/NEMO/OPA_SRC/DYN/dynspg_fsc.F90 @ 78

Last change on this file since 78 was 31, checked in by opalod, 20 years ago

CT : BUGFIX012 : Running problem for EEL5 configuration is solved

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.7 KB
Line 
1MODULE dynspg_fsc
2   !!======================================================================
3   !!                   ***  MODULE  dynspg_fsc  ***
4   !! Ocean dynamics:  surface pressure gradient trend
5   !!======================================================================
6#if ( defined key_dynspg_fsc && ! defined key_autotasking ) ||   defined key_esopa
7   !!----------------------------------------------------------------------
8   !!   'key_dynspg_fsc'                       free surface cst volume
9   !!   NOT 'key_autotasking'                      k-j-i loop (vector opt.)
10   !!----------------------------------------------------------------------
11   !!   dyn_spg_fsc  : update the momentum trend with the surface pressure
12   !!                  gradient in the free surface constant volume case
13   !!                  with vector optimization
14   !!----------------------------------------------------------------------
15   !! * Modules used
16   USE oce             ! ocean dynamics and tracers
17   USE dom_oce         ! ocean space and time domain
18   USE trdtra_oce      ! ocean active tracer   trend
19   USE trddyn_oce      ! ocean active dynamics trend
20   USE zdf_oce         ! ocean vertical physics
21   USE in_out_manager  ! I/O manager
22   USE phycst          ! physical constants
23   USE ocesbc          ! ocean surface boundary condition
24   USE flxrnf          ! ???
25   USE sol_oce         ! solver variables
26   USE solpcg          ! preconditionned conjugate gradient solver
27   USE solsor          ! Successive Over-relaxation solver
28   USE solfet          ! FETI solver
29   USE obc_oce         ! Lateral open boundary condition
30   USE obcdyn          ! ocean open boundary condition (obc_dyn routines)
31   USE obcvol          ! ocean open boundary condition (obc_vol routines)
32   USE lib_mpp         ! ???
33   USE lbclnk          ! ???
34   USE cla_dynspg      ! ???
35
36   IMPLICIT NONE
37   PRIVATE
38
39   !! * Accessibility
40   PUBLIC dyn_spg_fsc  ! routine called by step.F90
41
42   !! * Shared module variables
43   LOGICAL, PUBLIC, PARAMETER ::   lk_dynspg_fsc = .TRUE.    !: free surface constant volume flag
44
45   !! * Substitutions
46#  include "domzgr_substitute.h90"
47#  include "vectopt_loop_substitute.h90"
48   !!----------------------------------------------------------------------
49   !!   OPA 9.0 , LODYC-IPSL  (2003)
50   !!----------------------------------------------------------------------
51
52CONTAINS
53
54   SUBROUTINE dyn_spg_fsc( kt, kindic )
55      !!----------------------------------------------------------------------
56      !!                  ***  routine dyn_spg_fsc  ***
57      !!
58      !! ** Purpose :   Compute the now trend due to the surface pressure
59      !!      gradient in case of free surface formulation with a constant
60      !!      ocean volume add it to the general trend of momentum equation.
61      !!
62      !! ** Method  :   Free surface formulation. The surface pressure gradient
63      !!      is given by:
64      !!         spgu = 1/rau0 d/dx(ps) =  1/e1u di( etn + rnu btda )
65      !!         spgv = 1/rau0 d/dy(ps) =  1/e2v dj( etn + rnu btda )
66      !!      where etn is the free surface elevation and btda is the after
67      !!      of the free surface elevation
68      !!       -1- compute the after sea surface elevation from the cinematic
69      !!      surface boundary condition:
70      !!              zssha = sshb + 2 rdt ( wn - emp )
71      !!           Time filter applied on now sea surface elevation to avoid
72      !!      the divergence of two consecutive time-steps and swap of free
73      !!      surface arrays to start the next time step:
74      !!              sshb = sshn + atfp * [ sshb + zssha - 2 sshn ]
75      !!              sshn = zssha
76      !!       -2- evaluate the surface presure trend (including the addi-
77      !!      tional force) in three steps:
78      !!        a- compute the right hand side of the elliptic equation:
79      !!            gcb = 1/(e1t e2t) [ di(e2u spgu) + dj(e1v spgv) ]
80      !!         where (spgu,spgv) are given by:
81      !!            spgu = vertical sum[ e3u (ub+ 2 rdt ua ) ]
82      !!                 - grav 2 rdt hu /e1u di[sshn + emp]
83      !!            spgv = vertical sum[ e3v (vb+ 2 rdt va) ]
84      !!                 - grav 2 rdt hv /e2v dj[sshn + emp]
85      !!         and define the first guess from previous computation :
86      !!            zbtd = btda
87      !!            btda = 2 zbtd - btdb
88      !!            btdb = zbtd
89      !!        b- compute the relative accuracy to be reached by the
90      !!         iterative solver
91      !!        c- apply the solver by a call to sol... routine
92      !!       -3- compute and add the free surface pressure gradient inclu-
93      !!      ding the additional force used to stabilize the equation.
94      !!
95      !! ** Action : - Update (ua,va) with the surf. pressure gradient trend
96      !!             - Save the trends in (utrd,vtrd) ('key_diatrends')
97      !!
98      !! References :
99      !!      Roullet and Madec 1999, JGR.
100      !!
101      !! History :
102      !!        !  98-05 (G. Roullet)  Original code
103      !!        !  98-10  (G. Madec, M. Imbard)  release 8.2
104      !!   8.5  !  02-08  (G. Madec)  F90: Free form and module
105      !!        !  02-11  (C. Talandier, A-M Treguier) Open boundaries
106      !!---------------------------------------------------------------------
107      !! * Arguments
108      INTEGER, INTENT( in )  ::   kt         ! ocean time-step index
109      INTEGER, INTENT( out ) ::   kindic     ! solver convergence flag
110                                             ! if the solver doesn t converge
111                                             ! the flag is < 0
112      !! * Local declarations
113      INTEGER  ::   ji, jj, jk               ! dummy loop indices
114      REAL(wp) ::                         & 
115         z2dt, z2dtg, zraur, znugdt,      &  ! temporary scalars
116         znurau, zssha, zspgu, zspgv,     &  !   "          "
117         zegu, zegv, zgcb, zbtd,          &  !   "          "
118         ztdgu, ztdgv, zgwgt                 !   "          "
119      !!----------------------------------------------------------------------
120
121      IF( kt == nit000 ) THEN
122         IF(lwp) WRITE(numout,*)
123         IF(lwp) WRITE(numout,*) 'dyn_spg_fsc : 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.e0                     ! surface pressur gradient (i-direction)
128         spgv(:,:) = 0.e0                     ! surface pressur gradient (j-direction)
129      ENDIF
130
131      ! 0. Local constant initialization
132      ! --------------------------------
133      ! time step: leap-frog
134      z2dt = 2. * rdt
135      ! time step: Euler if restart from rest
136      IF( neuler == 0 .AND. kt == nit000 ) z2dt = rdt
137      ! coefficients
138      z2dtg  = grav * z2dt
139      zraur  = 1. / rauw
140      znugdt =  rnu * grav * z2dt
141      znurau =  znugdt * zraur
142      IF( lk_mpp ) THEN
143         ! Mpp : export boundary values of to neighboring processors
144         !!bug :  I don t understand why this only in mpp???? ==> Can be suppressed, no?
145         CALL lbc_lnk( ua, 'U', -1. )
146         CALL lbc_lnk( va, 'V', -1. )
147      ENDIF
148
149      ! 1. Surface pressure gradient (now)
150      ! ----------------------------
151      DO jj = 2, jpjm1
152         DO ji = fs_2, fs_jpim1   ! vector opt.
153            zspgu =      - grav * ( sshn(ji+1,jj) - sshn(ji,jj) ) / e1u(ji,jj)
154            zspgv =      - grav * ( sshn(ji,jj+1) - sshn(ji,jj) ) / e2v(ji,jj)
155            zegu  = + znurau * ( emp (ji+1,jj) - emp (ji,jj) ) / e1u(ji,jj)
156            zegv  = + znurau * ( emp (ji,jj+1) - emp (ji,jj) ) / e2v(ji,jj)
157            spgu(ji,jj) = zspgu + zegu
158            spgv(ji,jj) = zspgv + zegv
159#if defined key_trddyn
160            ! save the surface pressure gradient trends
161            utrd2(ji,jj,1) = zspgu
162            vtrd2(ji,jj,1) = zspgv
163            ! save the first part of the additional force trend
164            utrd2(ji,jj,2) = zegu
165            vtrd2(ji,jj,2) = zegv
166#endif
167         END DO
168      END DO 
169
170      ! 2. Add the surface pressure trend to the general trend
171      ! ------------------------------------------------------
172      DO jk = 1, jpkm1
173         DO jj = 2, jpjm1
174            DO ji = fs_2, fs_jpim1   ! vector opt.
175               ua(ji,jj,jk) = ua(ji,jj,jk) + spgu(ji,jj)
176               va(ji,jj,jk) = va(ji,jj,jk) + spgv(ji,jj)
177#if defined key_trddyn
178               ! save the surface pressure gradient trend for diagnostics
179               utrd(ji,jj,jk,8) = spgu(ji,jj)
180               vtrd(ji,jj,jk,8) = spgv(ji,jj) 
181#endif
182            END DO
183         END DO
184      END DO
185     
186      ! 1. Evaluate the masked next velocity
187      ! ------------------------------------
188      !     (effect of the additional force not included)
189      DO jk = 1, jpkm1
190         DO jj = 2, jpjm1
191            DO ji = fs_2, fs_jpim1   ! vector opt.
192               ua(ji,jj,jk) = ( ub(ji,jj,jk) + z2dt * ua(ji,jj,jk) ) * umask(ji,jj,jk)
193               va(ji,jj,jk) = ( vb(ji,jj,jk) + z2dt * va(ji,jj,jk) ) * vmask(ji,jj,jk)
194            END DO
195         END DO
196      END DO
197#if defined key_obc
198      ! Update velocities on each open boundary with the radiation algorithm
199      CALL obc_dyn( kt )
200      ! Correction of the barotropic componant velocity to control the volume of the system
201      CALL obc_vol( kt )
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      ! 2. compute the next vertically averaged velocity
208      ! ------------------------------------------------
209      !     (effect of the additional force not included)
210      ! initialize to zero
211      DO jj = 2, jpjm1
212         DO ji = fs_2, fs_jpim1   ! vector opt.
213            spgu(ji,jj) = 0.e0
214            spgv(ji,jj) = 0.e0
215         END DO
216      END DO
217
218      ! vertical sum
219!CDIR NOLOOPCHG
220      IF( lk_vopt_loop ) THEN          ! vector opt., forced unroll
221         DO jk = 1, jpkm1
222            DO ji = 1, jpij
223               spgu(ji,1) = spgu(ji,1) + fse3u(ji,1,jk) * ua(ji,1,jk)
224               spgv(ji,1) = spgv(ji,1) + fse3v(ji,1,jk) * va(ji,1,jk)
225            END DO
226         END DO
227      ELSE                        ! No  vector opt.
228         DO jk = 1, jpkm1
229            DO jj = 2, jpjm1
230               DO ji = 2, jpim1
231                  spgu(ji,jj) = spgu(ji,jj) + fse3u(ji,jj,jk) * ua(ji,jj,jk)
232                  spgv(ji,jj) = spgv(ji,jj) + fse3v(ji,jj,jk) * va(ji,jj,jk)
233               END DO
234            END DO
235         END DO
236      ENDIF
237
238      ! transport: multiplied by the horizontal scale factor
239      DO jj = 2, jpjm1
240         DO ji = fs_2, fs_jpim1   ! vector opt.
241            spgu(ji,jj) = spgu(ji,jj) * e2u(ji,jj)
242            spgv(ji,jj) = spgv(ji,jj) * e1v(ji,jj)
243         END DO
244      END DO
245
246      ! Boundary conditions on (spgu,spgv)
247      CALL lbc_lnk( spgu, 'U', -1. )
248      CALL lbc_lnk( spgv, 'V', -1. )
249
250      ! 3. Right hand side of the elliptic equation and first guess
251      ! -----------------------------------------------------------
252      DO jj = 2, jpjm1
253         DO ji = fs_2, fs_jpim1   ! vector opt.
254            ! Divergence of the after vertically averaged velocity
255            zgcb =  spgu(ji,jj) - spgu(ji-1,jj)   &
256                  + spgv(ji,jj) - spgv(ji,jj-1)
257            gcb(ji,jj) = gcdprc(ji,jj) * zgcb
258            ! First guess of the after barotropic transport divergence
259            zbtd = gcx(ji,jj)
260            gcx (ji,jj) = 2. * zbtd   - gcxb(ji,jj)
261            gcxb(ji,jj) =      zbtd
262         END DO
263      END DO
264
265      ! 4. Relative precision (computation on one processor)
266      ! ---------------------
267      rnorme =0.
268      DO jj = 1, jpj
269         DO ji = 1, jpi
270            zgwgt  = gcdmat(ji,jj) * gcb(ji,jj)
271            rnorme = rnorme + gcb(ji,jj) * zgwgt
272         END DO
273      END DO
274      IF( lk_mpp )   CALL mpp_sum( rnorme )   ! sum over the global domain
275
276      epsr = eps * eps * rnorme
277      ncut = 0
278      ! if rnorme is 0, the solution is 0, the solver isn't called
279      IF( rnorme == 0.e0 ) THEN
280         gcx(:,:) = 0.e0
281         res   = 0.e0
282         niter = 0
283         ncut  = 999
284      ENDIF
285
286      ! 5. Evaluate the next transport divergence
287      ! -----------------------------------------
288      !    Iterarive solver for the elliptic equation (except IF sol.=0)
289      !    (output in gcx with boundary conditions applied)
290      kindic = 0
291      IF( ncut == 0 ) THEN
292         IF( nsolv == 1 ) THEN         ! diagonal preconditioned conjuguate gradient
293            CALL sol_pcg( kindic )
294         ELSEIF( nsolv == 2 ) THEN     ! successive-over-relaxation
295            CALL sol_sor( kindic )
296         ELSEIF( nsolv == 3 ) THEN     ! FETI solver
297            CALL sol_fet( kindic )
298         ELSE                          ! e r r o r in nsolv namelist parameter
299            IF(lwp) WRITE(numout,cform_err)
300            IF(lwp) WRITE(numout,*) ' dyn_spg_fsc : e r r o r, nsolv = 1, 2 or 3'
301            IF(lwp) WRITE(numout,*) ' ~~~~~~~~~~~                not = ', nsolv
302            nstop = nstop + 1
303         ENDIF
304      ENDIF
305
306      ! 6. Transport divergence gradient multiplied by z2dt
307      ! -----------------------------------------------====
308      DO jj = 2, jpjm1
309         DO ji = fs_2, fs_jpim1   ! vector opt.
310            ! trend of Transport divergence gradient
311            ztdgu = znugdt * (gcx(ji+1,jj  ) - gcx(ji,jj) ) / e1u(ji,jj)
312            ztdgv = znugdt * (gcx(ji  ,jj+1) - gcx(ji,jj) ) / e2v(ji,jj)
313            ! multiplied by z2dt
314#if defined key_obc
315            ! caution : grad D = 0 along open boundaries
316            spgu(ji,jj) = z2dt * ztdgu * obcumask(ji,jj)
317            spgv(ji,jj) = z2dt * ztdgv * obcvmask(ji,jj)
318#else
319            spgu(ji,jj) = z2dt * ztdgu
320            spgv(ji,jj) = z2dt * ztdgv
321#endif
322#if defined key_trddyn
323            ! save the transport divergence gradient trends
324            utrd2(ji,jj,2) = utrd2(ji,jj,2) + ztdgu
325            vtrd2(ji,jj,2) = vtrd2(ji,jj,2) + ztdgv
326#endif
327         END DO
328      END DO
329
330      ! 7.  Add the trends multiplied by z2dt to the after velocity
331      ! -----------------------------------------------------------
332      !     ( c a u t i o n : (ua,va) here are the after velocity not the
333      !                       trend, the leap-frog time stepping will not
334      !                       be done in dynnxt.F routine)
335      DO jk = 1, jpkm1
336         DO jj = 2, jpjm1
337            DO ji = fs_2, fs_jpim1   ! vector opt.
338               ua(ji,jj,jk) = (ua(ji,jj,jk) + spgu(ji,jj)) * umask(ji,jj,jk)
339               va(ji,jj,jk) = (va(ji,jj,jk) + spgv(ji,jj)) * vmask(ji,jj,jk)
340#if defined key_trddyn
341               ! save the surface pressure gradient trend for diagnostics
342               utrd(ji,jj,jk,8) = utrd(ji,jj,jk,8) + spgu(ji,jj)/z2dt
343               vtrd(ji,jj,jk,8) = vtrd(ji,jj,jk,8) + spgv(ji,jj)/z2dt
344#endif
345            END DO
346         END DO
347      END DO
348
349      IF( l_ctl .AND. lwp ) THEN         ! print sum trends (used for debugging)
350         WRITE(numout,*) ' spg  - Ua: ', SUM( ua(2:jpim1,2:jpjm1,1:jpkm1)*umask(2:jpim1,2:jpjm1,1:jpkm1) ),   &
351            &                   ' Va: ', SUM( va(2:jpim1,2:jpjm1,1:jpkm1)*vmask(2:jpim1,2:jpjm1,1:jpkm1) )
352      ENDIF
353
354
355      ! 8. Sea surface elevation time stepping
356      ! --------------------------------------
357      ! Euler (forward) time stepping, no time filter
358      IF( neuler == 0 .AND. kt == nit000 ) THEN
359         DO jj = 2, jpjm1            !!bug  if 1, jpj  the lbc_lnk call can be suppress
360            DO ji = 1, jpi
361               ! after free surface elevation
362               zssha = sshb(ji,jj) + rdt * ( wn(ji,jj,1) - emp(ji,jj) * zraur ) * tmask(ji,jj,1)
363               ! swap of arrays
364               sshb(ji,jj) = sshn(ji,jj)
365               sshn(ji,jj) = zssha
366            END DO
367         END DO
368      ELSE
369         ! Leap-frog time stepping and time filter
370         DO jj = 2, jpjm1            !!bug  if 1, jpj  the lbc_lnk call can be suppress
371            DO ji = 1, jpi
372               ! after free surface elevation
373               zssha = sshb(ji,jj) + z2dt * ( wn(ji,jj,1) - emp(ji,jj) * zraur ) * tmask(ji,jj,1)
374               ! time filter and array swap
375               sshb(ji,jj) = atfp * ( sshb(ji,jj) + zssha ) + atfp1 * sshn(ji,jj)
376               sshn(ji,jj) = zssha
377            END DO
378         END DO
379      ENDIF
380
381      ! Boundary conditions on sshn
382      CALL lbc_lnk( sshn, 'T', 1. )
383
384   END SUBROUTINE dyn_spg_fsc
385
386#else
387   !!----------------------------------------------------------------------
388   !!   Default case :   Empty module   No standart free surface cst volume
389   !!----------------------------------------------------------------------
390   LOGICAL, PUBLIC, PARAMETER ::   lk_dynspg_fsc = .FALSE.   !: free surface constant volume flag
391CONTAINS
392   SUBROUTINE dyn_spg_fsc( kt, kindic )       ! Empty routine
393      WRITE(*,*) 'dyn_spg_fsc: You should not have seen this print! error?', kt, kindic
394   END SUBROUTINE dyn_spg_fsc
395#endif
396   
397   !!======================================================================
398END MODULE dynspg_fsc
Note: See TracBrowser for help on using the repository browser.