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

source: trunk/NEMO/OPA_SRC/DYN/dynspg_flt_jki.F90 @ 784

Last change on this file since 784 was 784, checked in by rblod, 16 years ago

merge solsor and solsor_e, see ticket #45

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 17.6 KB
Line 
1MODULE dynspg_flt_jki
2   !!======================================================================
3   !!                  ***  MODULE  dynspg_flt_jki  ***
4   !! Ocean dynamics:  surface pressure gradient trend
5   !!======================================================================
6#if defined key_dynspg_flt   ||   defined key_esopa
7   !!----------------------------------------------------------------------
8   !!   'key_dynspg_flt'                              filtered free surface
9   !!----------------------------------------------------------------------
10   !!----------------------------------------------------------------------
11   !!   dyn_spg_flt_jki : Update the momentum trend with the surface pressure
12   !!                     gradient for the free surf. constant volume case
13   !!                     with auto-tasking (j-slab) (no vectior opt.)
14   !!----------------------------------------------------------------------
15   USE oce             ! ocean dynamics and tracers
16   USE dom_oce         ! ocean space and time domain
17   USE zdf_oce         ! ocean vertical physics
18   USE phycst          ! physical constant
19   USE ocesbc          ! Ocean Surface Boundary condition
20   USE flxrnf          ! ocean runoffs
21   USE sol_oce         ! ocean elliptic solver
22   USE solpcg          ! preconditionned conjugate gradient solver
23   USE solsor          ! Successive Over-relaxation solver
24   USE solfet          ! FETI solver
25   USE solver
26   USE obc_oce         ! Lateral open boundary condition
27   USE obcdyn          ! ocean open boundary condition (obc_dyn routines)
28   USE obcvol          ! ocean open boundary condition (obc_vol routines)
29   USE lib_mpp         ! distributed memory computing library
30   USE lbclnk          ! ocean lateral boundary conditions (or mpp link)
31   USE cla_dynspg      ! cross land advection
32   USE prtctl          ! Print control
33   USE in_out_manager  ! I/O manager
34   USE solmat          ! matrix construction for elliptic solvers
35   USE agrif_opa_interp
36   USE restart         ! only for lrst_oce
37   USE iom             ! I/O library
38   USE dynspg_flt      ! surface pressure gradient
39
40   IMPLICIT NONE
41   PRIVATE
42
43   !! * Accessibility
44   PUBLIC dyn_spg_flt_jki        ! routine called by step.F90
45
46   !! * Substitutions
47#  include "domzgr_substitute.h90"
48   !!----------------------------------------------------------------------
49   !!   OPA 9.0 , LOCEAN-IPSL (2005)
50   !! $Header$
51   !! Software governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt)
52   !!----------------------------------------------------------------------
53
54CONTAINS
55
56   SUBROUTINE dyn_spg_flt_jki( kt, kindic )
57      !!----------------------------------------------------------------------
58      !!                  ***  routine dyn_spg_flt_jki  ***
59      !!
60      !! ** Purpose :   Compute the now trend due to the surface pressure
61      !!      gradient for free surface formulation with a constant ocean
62      !!      volume case, add it to the general trend of momentum equation.
63      !!
64      !! ** Method  :   Free surface formulation. The surface pressure gradient
65      !!      is given by:
66      !!         spgu = 1/rau0 d/dx(ps) =  1/e1u di( etn + rnu btda )
67      !!         spgv = 1/rau0 d/dy(ps) =  1/e2v dj( etn + rnu btda )
68      !!      where etn is the free surface elevation and btda is the after
69      !!      of the free surface elevation
70      !!       -1- compute the after sea surface elevation from the cinematic
71      !!      surface boundary condition:
72      !!              zssha = sshb + 2 rdt ( wn - emp )
73      !!           Time filter applied on now sea surface elevation to avoid
74      !!      the divergence of two consecutive time-steps and swap of free
75      !!      surface arrays to start the next time step:
76      !!              sshb = sshn + atfp * [ sshb + zssha - 2 sshn ]
77      !!              sshn = zssha
78      !!       -2- evaluate the surface presure trend (including the addi-
79      !!      tional force) in three steps:
80      !!        a- compute the right hand side of the elliptic equation:
81      !!            gcb = 1/(e1t e2t) [ di(e2u spgu) + dj(e1v spgv) ]
82      !!         where (spgu,spgv) are given by:
83      !!            spgu = vertical sum[ e3u (ub+ 2 rdt ua ) ]
84      !!                 - grav 2 rdt hu /e1u di[sshn + emp]
85      !!            spgv = vertical sum[ e3v (vb+ 2 rdt va) ]
86      !!                 - grav 2 rdt hv /e2v dj[sshn + emp]
87      !!         and define the first guess from previous computation :
88      !!            zbtd = btda
89      !!            btda = 2 zbtd - btdb
90      !!            btdb = zbtd
91      !!        b- compute the relative accuracy to be reached by the
92      !!         iterative solver
93      !!        c- apply the solver by a call to sol... routine
94      !!       -3- compute and add the free surface pressure gradient inclu-
95      !!      ding the additional force used to stabilize the equation.
96      !!      several slabs used ('key-autotasking')
97      !!
98      !! ** Action : - Update (ua,va) with the surf. pressure gradient trend
99      !!
100      !! References : Roullet and Madec 1999, JGR.
101      !!---------------------------------------------------------------------
102      INTEGER, INTENT( in ) ::   kt          ! ocean time-step index
103      INTEGER, INTENT( out ) ::   kindic     ! solver convergence flag, <0 if the solver doesn t converge
104      !!
105      INTEGER  ::   ji, jj, jk               ! dummy loop indices
106      REAL(wp) ::   &              ! temporary scalars
107         z2dt, z2dtg, zraur, znugdt, znurau,   &
108         zssha, zgcb, zbtd, ztdgu, ztdgv, zgwgt
109      !!----------------------------------------------------------------------
110
111      IF( kt == nit000 ) THEN
112         IF(lwp) WRITE(numout,*)
113         IF(lwp) WRITE(numout,*) 'dyn_spg_flt_jki : surface pressure gradient trend'
114         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~~~~~~  (free surface constant volume, autotasking case)'
115
116         ! set to zero free surface specific arrays
117         spgu(:,:) = 0.e0                     ! surface pressure gradient (i-direction)
118         
119         spgv(:,:) = 0.e0                     ! surface pressure gradient (j-direction)
120         
121         CALL solver_init( nit000 )           ! Elliptic solver initialisation
122
123         ! read filtered free surface arrays in restart file
124         CALL flt_rst( nit000, 'READ' )       ! read or initialize the following fields:
125         !                                    ! gcx, gcxb, sshb, sshn
126      ENDIF
127
128      ! 0. Local constant initialization
129      ! --------------------------------
130      ! time step: leap-frog
131      z2dt = 2. * rdt
132      ! time step: Euler if restart from rest
133      IF( neuler == 0 .AND. kt == nit000 ) z2dt = rdt
134      IF( neuler == 0 .AND. kt == nit000+1 ) CALL sol_mat(kt)
135      ! coefficients
136      z2dtg  = grav * z2dt
137      zraur  = 1. / rauw
138      znugdt =  rnu * grav * z2dt
139      znurau =  znugdt * zraur
140
141      !                                                ! ===============
142      DO jj = 2, jpjm1                                 !  Vertical slab
143         !                                             ! ===============
144         ! Surface pressure gradient (now)
145         DO ji = 2, jpim1
146            spgu(ji,jj) = - grav * ( sshn(ji+1,jj  ) - sshn(ji,jj) ) / e1u(ji,jj)
147            spgv(ji,jj) = - grav * ( sshn(ji  ,jj+1) - sshn(ji,jj) ) / e2v(ji,jj)
148         END DO 
149         !  Add the surface pressure trend to the general trend
150         DO jk = 1, jpkm1
151            DO ji = 2, jpim1
152               ua(ji,jj,jk) = ua(ji,jj,jk) + spgu(ji,jj)
153               va(ji,jj,jk) = va(ji,jj,jk) + spgv(ji,jj)
154            END DO
155         END DO
156         ! Evaluate the masked next velocity (effect of the additional force not included)
157         DO jk = 1, jpkm1
158            DO ji = 2, jpim1
159               ua(ji,jj,jk) = ( ub(ji,jj,jk) + z2dt * ua(ji,jj,jk) ) * umask(ji,jj,jk)
160               va(ji,jj,jk) = ( vb(ji,jj,jk) + z2dt * va(ji,jj,jk) ) * vmask(ji,jj,jk)
161            END DO
162         END DO
163         !                                             ! ===============
164      END DO                                           !   End of slab
165      !                                                ! ===============
166
167#if defined key_obc
168         ! Update velocities on each open boundary with the radiation algorithm
169         CALL obc_dyn( kt )
170         ! Correction of the barotropic componant velocity to control the volume of the system
171         CALL obc_vol( kt )
172#endif
173#if defined key_agrif
174      ! Update velocities on each coarse/fine interfaces
175
176      CALL Agrif_dyn( kt )
177#endif
178#if defined key_orca_r2
179      IF( n_cla == 1 )   CALL dyn_spg_cla( kt )      ! Cross Land Advection (Update (ua,va))
180#endif
181
182      !                                                ! ===============
183      DO jj = 2, jpjm1                                 !  Vertical slab
184         !                                             ! ===============
185
186         ! 2. compute the next vertically averaged velocity
187         ! ------------------------------------------------
188         !     (effect of the additional force not included)
189         ! initialize to zero
190         DO ji = 2, jpim1
191            spgu(ji,jj) = 0.e0
192            spgv(ji,jj) = 0.e0
193         END DO
194         ! vertical sum
195         DO jk = 1, jpk
196            DO ji = 2, jpim1
197               spgu(ji,jj) = spgu(ji,jj) + fse3u(ji,jj,jk) * ua(ji,jj,jk)
198               spgv(ji,jj) = spgv(ji,jj) + fse3v(ji,jj,jk) * va(ji,jj,jk)
199            END DO
200         END DO
201         ! transport: multiplied by the horizontal scale factor
202         DO ji = 2, jpim1
203            spgu(ji,jj) = spgu(ji,jj) * e2u(ji,jj)
204            spgv(ji,jj) = spgv(ji,jj) * e1v(ji,jj)
205         END DO
206         !                                             ! ===============
207      END DO                                           !   End of slab
208      !                                                ! ===============
209
210      !,,,,,,,,,,,,,,,,,,,,,,,,,,,,,synchro,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
211     
212      ! Boundary conditions on (spgu,spgv)
213      CALL lbc_lnk( spgu, 'U', -1. )
214      CALL lbc_lnk( spgv, 'V', -1. )
215
216      !,,,,,,,,,,,,,,,,,,,,,,,,,,,,,synchro,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
217
218      ! 3. Right hand side of the elliptic equation and first guess
219      ! -----------------------------------------------------------
220      DO jj = 2, jpjm1
221         DO ji = 2, jpim1
222            ! Divergence of the after vertically averaged velocity
223            zgcb =  spgu(ji,jj) - spgu(ji-1,jj)   &
224                  + spgv(ji,jj) - spgv(ji,jj-1)
225            gcb(ji,jj) = gcdprc(ji,jj) * zgcb
226            ! First guess of the after barotropic transport divergence
227            zbtd = gcx(ji,jj)
228            gcx (ji,jj) = 2. * zbtd   - gcxb(ji,jj)
229            gcxb(ji,jj) =      zbtd
230         END DO
231      END DO
232      ! applied the lateral boundary conditions
233      IF( nsolv == 2 .AND. MAX( jpr2di, jpr2dj ) > 0 ) CALL lbc_lnk_e( gcb, c_solver_pt, 1. ) 
234
235#if defined key_agrif
236      IF( .NOT. AGRIF_ROOT() ) THEN
237         ! add contribution of gradient of after barotropic transport divergence
238        IF( (nbondi == -1) .OR. (nbondi == 2) ) gcb(3,:) = gcb(3,:) &
239           &            -znugdt * z2dt*laplacu(2,:)*gcdprc(3,:)*hu(2,:)*e2u(2,:)
240        IF( (nbondi ==  1) .OR. (nbondi == 2) )  gcb(nlci-2,:) = gcb(nlci-2,:) &
241           &           +znugdt * z2dt*laplacu(nlci-2,:)*gcdprc(nlci-2,:)*hu(nlci-2,:)*e2u(nlci-2,:)
242        IF( (nbondj == -1) .OR. (nbondj == 2) ) gcb(:,3) = gcb(:,3) &
243           &           -znugdt * z2dt*laplacv(:,2)*gcdprc(:,3)*hv(:,2)*e1v(:,2)
244        IF( (nbondj ==  1) .OR. (nbondj == 2) )  gcb(:,nlcj-2) = gcb(:,nlcj-2) &
245           &           +znugdt * z2dt*laplacv(:,nlcj-2)*gcdprc(:,nlcj-2)*hv(:,nlcj-2)*e1v(:,nlcj-2)
246      ENDIF
247#endif
248
249      !,,,,,,,,,,,,,,,,,,,,,,,,,,,,,synchro,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
250     
251      ! 4. Relative precision (computation on one processor)
252      ! ---------------------
253      rnorme =0.
254      DO jj = 1, jpj
255         DO ji = 1, jpi
256            zgwgt  = gcdmat(ji,jj) * gcb(ji,jj)
257            rnorme = rnorme + gcb(ji,jj) * zgwgt * bmask(ji,jj)
258         END DO
259      END DO
260      IF( lk_mpp )   CALL mpp_sum( rnorme )   ! sum over the global domain
261
262      epsr = eps * eps * rnorme
263      ncut = 0
264      ! if rnorme is 0, the solution is 0, the solver isn't called
265      IF( rnorme == 0.e0 ) THEN
266         gcx(:,:) = 0.e0
267         res   = 0.e0
268         niter = 0
269         ncut  = 999
270      ENDIF
271     
272      !,,,,,,,,,,,,,,,,,,,,,,,,,,,,,synchro,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
273     
274      ! 5. Evaluate the next transport divergence
275      ! -----------------------------------------
276      !    Iterarive solver for the elliptic equation (except IF sol.=0)
277      !    (output in gcx with boundary conditions applied)
278      kindic = 0
279      IF( ncut == 0 ) THEN
280         IF( nsolv == 1 ) THEN         ! diagonal preconditioned conjuguate gradient
281            CALL sol_pcg( kindic )
282         ELSEIF( nsolv == 2 ) THEN     ! successive-over-relaxation
283            CALL sol_sor( kindic )
284         ELSEIF( nsolv == 3 ) THEN     ! FETI solver
285            CALL sol_fet( kindic )
286         ELSE                          ! e r r o r in nsolv namelist parameter
287            WRITE(ctmp1,*) ' ~~~~~~~~~~~~~~~~                not = ', nsolv
288            CALL ctl_stop( ' dyn_spg_flt_jki : e r r o r, nsolv = 1, 2 or 3', ctmp1 )
289         ENDIF
290      ENDIF
291
292      !,,,,,,,,,,,,,,,,,,,,,,,,,,,,,synchro,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
293
294      !                                                ! ===============
295      DO jj = 2, jpjm1                                 !  Vertical slab
296         !                                             ! ===============
297         
298         ! 6. Transport divergence gradient multiplied by z2dt
299         ! -----------------------------------------------====
300         DO ji = 2, jpim1
301            ! trend of Transport divergence gradient
302            ztdgu = znugdt * (gcx(ji+1,jj  ) - gcx(ji,jj) ) / e1u(ji,jj)
303            ztdgv = znugdt * (gcx(ji  ,jj+1) - gcx(ji,jj) ) / e2v(ji,jj)
304            ! multiplied by z2dt
305#if defined key_obc
306            ! caution : grad D = 0 along open boundaries
307            spgu(ji,jj) = z2dt * ztdgu * obcumask(ji,jj)
308            spgv(ji,jj) = z2dt * ztdgv * obcvmask(ji,jj)
309#else
310            spgu(ji,jj) = z2dt * ztdgu
311            spgv(ji,jj) = z2dt * ztdgv
312#endif
313         END DO
314         
315#if defined key_agrif     
316      IF( .NOT. Agrif_Root() ) THEN
317         ! caution : grad D (fine) = grad D (coarse) at coarse/fine interface
318         IF( (nbondi == -1) .OR. (nbondi == 2) ) spgu(2,:) = znugdt * z2dt * laplacu(2,:) * umask(2,:,1)
319         IF( (nbondi ==  1) .OR. (nbondi == 2) ) spgu(nlci-2,:) = znugdt * z2dt * laplacu(nlci-2,:) * umask(nlci-2,:,1)
320         IF( (nbondj == -1) .OR. (nbondj == 2) ) spgv(:,2) = znugdt * z2dt * laplacv(:,2) * vmask(:,2,1)
321         IF( (nbondj ==  1) .OR. (nbondj == 2) ) spgv(:,nlcj-2) = znugdt * z2dt * laplacv(:,nlcj-2) * vmask(:,nlcj-2,1)
322      ENDIF
323#endif
324     
325         ! 7.  Add the trends multiplied by z2dt to the after velocity
326         ! -----------------------------------------------------------
327         !     ( c a u t i o n : (ua,va) here are the after velocity not the
328         !                       trend, the leap-frog time stepping will not
329         !                       be done in dynnxt.F routine)
330         DO jk = 1, jpkm1
331            DO ji = 2, jpim1
332               ua(ji,jj,jk) = (ua(ji,jj,jk) + spgu(ji,jj)) * umask(ji,jj,jk)
333               va(ji,jj,jk) = (va(ji,jj,jk) + spgv(ji,jj)) * vmask(ji,jj,jk)
334            END DO
335         END DO
336
337         ! 8. Sea surface elevation time stepping
338         ! --------------------------------------
339         IF( neuler == 0 .AND. kt == nit000 ) THEN         ! Euler (forward) time stepping, no time filter
340            DO ji = 1, jpi
341               ! after free surface elevation
342               zssha = sshb(ji,jj) + rdt * ( wn(ji,jj,1) - emp(ji,jj) * zraur ) * tmask(ji,jj,1)
343               ! swap of arrays
344               sshb(ji,jj) = sshn(ji,jj)
345               sshn(ji,jj) = zssha
346            END DO
347         ELSE                                              ! Leap-frog time stepping and time filter
348            DO ji = 1, jpi
349               ! after free surface elevation
350               zssha = sshb(ji,jj) + z2dt * ( wn(ji,jj,1) - emp(ji,jj) * zraur ) * tmask(ji,jj,1)
351               ! time filter and array swap
352               sshb(ji,jj) = atfp * ( sshb(ji,jj) + zssha ) + atfp1 * sshn(ji,jj)
353               sshn(ji,jj) = zssha
354            END DO
355         ENDIF
356         !                                             ! ===============
357      END DO                                           !   End of slab
358      !                                                ! ===============
359
360      !Boundary conditions on sshn
361      CALL lbc_lnk( sshn, 'T', 1. )
362
363      ! write filtered free surface arrays in restart file
364      ! --------------------------------------------------
365      IF( lrst_oce ) CALL flt_rst( kt, 'WRITE' )
366
367      IF(ln_ctl) THEN         ! print sum trends (used for debugging)
368         CALL prt_ctl( tab3d_1=ua  , clinfo1=' spg  - Ua : ', mask1=umask,   &
369            &          tab3d_2=va  , clinfo2='        Va : ', mask2=vmask )
370         CALL prt_ctl( tab2d_1=sshn, clinfo1=' spg  - ssh: ', mask1=tmask)
371      ENDIF
372      !
373   END SUBROUTINE dyn_spg_flt_jki
374#else
375   !!----------------------------------------------------------------------
376   !!   Default case :                                         Empty module
377   !!----------------------------------------------------------------------
378CONTAINS
379   SUBROUTINE dyn_spg_flt_jki( kt, kindic )      ! Empty module
380      WRITE(*,*) 'dyn_spg_flt_jki: You should not have seen this print! error?', kt, kindic
381   END SUBROUTINE dyn_spg_flt_jki
382#endif
383   
384   !!======================================================================
385END MODULE dynspg_flt_jki
Note: See TracBrowser for help on using the repository browser.