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

source: trunk/NEMO/OPA_SRC/DYN/dynspg_fsc_atsk.F90 @ 183

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

CT : BUGFIX117 : remove the EMP gradient computation to avoid negative salinity close to rivers in the Arctic

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