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.
dynnept.F90 in branches/2011/dev_r2787_NOCS_NEPTUNE/NEMOGCM/NEMO/OPA_SRC/DYN – NEMO

source: branches/2011/dev_r2787_NOCS_NEPTUNE/NEMOGCM/NEMO/OPA_SRC/DYN/dynnept.F90 @ 2825

Last change on this file since 2825 was 2825, checked in by acc, 13 years ago

Branch NOCS_NEPTUNE improved handling of shallow topography #843

File size: 28.0 KB
Line 
1MODULE dynnept
2   !!======================================================================
3   !!                       ***  MODULE  dynnept  ***
4   !! Ocean dynamics: Neptune effect as proposed by Greg Holloway,
5   !!                 recoded version of simplest case (u*, v* only)
6   !!======================================================================
7   !! History :  1.0  !  2007-06  (Michael Dunphy)  Modular form: - new namelist parameters
8   !!                                                             - horizontal diffusion for Neptune
9   !!                                                             - vertical diffusion for gm in momentum eqns
10   !!                                                             - option to use Neptune in Coriolis eqn
11   !!                    2011-08  (Jeff Blundell, NOCS) Simplified form for temporally invariant u*, v*
12   !!                                               Horizontal and vertical diffusivity formulations removed
13   !!                                               Dynamic allocation of storage added
14   !!                                               Option of ramping Neptune vel. down
15   !!                                               to zero added in shallow depths added
16   !!----------------------------------------------------------------------
17   !! dyn_nept_init        :
18   !! div_cur_nept_init    :
19   !! dyn_cor_topo         :
20   !! dyn_topo_neptunevel  :
21   !! smooth_topo2         :
22   !!----------------------------------------------------------------------
23   USE oce              ! ocean dynamics and tracers
24   USE dom_oce          ! ocean space and time domain
25   USE in_out_manager   ! I/O manager
26   USE lib_mpp          ! distributed memory computing
27   USE prtctl           ! Print control
28   USE phycst
29   USE lbclnk
30
31
32   IMPLICIT NONE
33   PRIVATE
34
35   !! * Routine accessibility
36   PUBLIC dyn_nept_init      ! routine called by nemogcm.F90
37   PUBLIC dyn_cor_topo       ! routine called by step.F90
38   !! dynnept_alloc()     is called only by dyn_nept_init, within this module
39   !! div_cur_nept_init   is called only by dyn_nept_init, within this module
40   !! dyn_topo_neptunevel is called only by dyn_cor_topo,  within this module
41
42   !! * Shared module variables
43   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)    :: zunep, zvnep  ! Neptune u and v
44   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:)  :: zhdivnep      ! hor. div for Neptune vel.
45   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:)  :: zmrotnep      ! curl for Neptune vel.
46
47
48   !! * Namelist nam_dynnept variables
49   LOGICAL, PUBLIC  ::  ln_neptsimp    = .FALSE.  ! yes/no simplified neptune
50
51   LOGICAL          ::  ln_smoothtopo  = .FALSE.  ! yes/no smooth zunep, zvnep
52   REAL(wp)         ::  rn_tslse       =  1.2e4   ! value of lengthscale L at the equator
53   REAL(wp)         ::  rn_tslsp       =  3.0e3   ! value of lengthscale L at the pole
54!! Specify whether to ramp down the Neptune velocity in shallow
55!! water, and the depth range controlling such ramping down
56   LOGICAL          ::  ln_neptramp    = .FALSE.  ! ramp down Neptune velocity in shallow water
57   REAL(wp)         ::  rn_htrmin      =  100.0   ! min. depth of transition range
58   REAL(wp)         ::  rn_htrmax      =  200.0   ! max. depth of transition range
59
60   !! * Module variables
61
62
63   !! * Substitutions
64#  include "vectopt_loop_substitute.h90"
65#  include "domzgr_substitute.h90"
66   !!----------------------------------------------------------------------
67   !!   OPA 9.0 , implemented by Bedford Institute of Oceanography
68   !!----------------------------------------------------------------------
69
70 CONTAINS
71
72   INTEGER FUNCTION dynnept_alloc()
73      !!----------------------------------------------------------------------
74      !!                    ***  ROUTINE dynnept_alloc  ***
75      !!----------------------------------------------------------------------
76      ALLOCATE( zunep(jpi,jpj) , zvnep(jpi,jpj) ,     &
77         &      zhdivnep(jpi,jpj,jpk) , zmrotnep(jpi,jpj,jpk) , STAT=dynnept_alloc )
78         !
79      IF( dynnept_alloc /= 0 )   CALL ctl_warn('dynnept_alloc: array allocate failed.')
80   END FUNCTION dynnept_alloc
81
82
83   SUBROUTINE dyn_nept_init
84      !!----------------------------------------------------------------------
85      !!                  ***  ROUTINE dyn_nept_init  ***
86      !!
87      !! ** Purpose :   Read namelist parameters, initialise arrays
88      !!                and compute the arrays zunep and zvnep
89      !!
90      !! ** Method  :   zunep =
91      !!                zvnep =
92      !!
93      !! ** History :  1.0  !   07-05  (Zeliang Wang)   Original code for zunep, zvnep
94      !!               1.1  !   07-06  (Michael Dunphy) namelist and  initialisation
95      !!               2.0  ! 2011-07  (Jeff Blundell, NOCS)
96      !!                    ! Simplified form for temporally invariant u*, v*
97      !!                    ! Horizontal and vertical diffusivity formulations removed
98      !!                    ! Includes optional tapering-off in shallow depths
99      !!----------------------------------------------------------------------
100      USE iom
101      !!
102!!    Local dynamic allocation
103      INTEGER  ::   ji, jj, jk    ! dummy loop indices
104      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   ht       ! temporary 2D workspace
105      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   htn      ! temporary 2D workspace
106      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   tscale   ! temporary 2D workspace
107      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   tsp      ! temporary 2D workspace
108      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   hur_n    ! temporary 2D workspace
109      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   hvr_n    ! temporary 2D workspace
110      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   hu_n     ! temporary 2D workspace
111      REAL(wp), ALLOCATABLE, DIMENSION(:,:)   ::   hv_n     ! temporary 2D workspace
112      REAL(wp), ALLOCATABLE, DIMENSION(:,:,:) ::   znmask   ! temporary 3D array for nmask
113      REAL(wp) :: unemin,unemax,vnemin,vnemax   ! extrema of (u*, v*) fields
114      REAL(wp) :: zhdivmin,zhdivmax             ! extrema of horizontal divergence of (u*, v*) fields
115      REAL(wp) :: zmrotmin,zmrotmax             ! extrema of the curl of the (u*, v*) fields
116      REAL(wp) :: ustar,vstar                   ! (u*, v*) before tapering in shallow water
117      REAL(wp) :: hramp                         ! depth over which Neptune vel. is ramped down
118      !!
119      NAMELIST/nam_dynnept/ ln_neptsimp,      &
120                            ln_smoothtopo,    &
121             rn_tslse,        &
122             rn_tslsp,        &
123                            ln_neptramp,      &
124                            rn_htrmin,        &
125             rn_htrmax
126      !!----------------------------------------------------------------------
127
128      ! Define the (simplified) Neptune parameters
129      ! ==========================================
130
131!!    WRITE(numout,*) ' start dynnept namelist'
132!!    CALL FLUSH(numout)
133      REWIND( numnam )                  ! Read Namelist nam_dynnept:  Simplified Neptune
134      READ  ( numnam, nam_dynnept )
135!!    WRITE(numout,*) ' dynnept namelist done'
136!!    CALL FLUSH(numout)
137
138      IF(lwp) THEN                      ! Control print
139         WRITE(numout,*)
140         WRITE(numout,*) 'dyn_nept_init : Simplified Neptune module enabled'
141         WRITE(numout,*) '~~~~~~~~~~~~~'
142         WRITE(numout,*) ' -->   Reading namelist nam_dynnept parameters:'
143         WRITE(numout,*) '       ln_neptsimp          = ', ln_neptsimp
144         WRITE(numout,*)
145         WRITE(numout,*) '       ln_smoothtopo        = ', ln_smoothtopo
146         WRITE(numout,*) '       rn_tslse             = ', rn_tslse
147         WRITE(numout,*) '       rn_tslsp             = ', rn_tslsp
148         WRITE(numout,*)
149         WRITE(numout,*) '       ln_neptramp          = ', ln_neptramp
150         WRITE(numout,*) '       rn_htrmin            = ', rn_htrmin
151         WRITE(numout,*) '       rn_htrmax            = ', rn_htrmax
152         WRITE(numout,*)
153         CALL FLUSH(numout)
154      ENDIF
155
156      IF( ln_smoothtopo ) THEN
157         IF(lwp) WRITE(numout,*) ' -->   neptune velocities will be smoothed'
158      ELSE
159         IF(lwp) WRITE(numout,*) ' -->   neptune velocities will not be smoothed'
160      ENDIF
161
162      IF( ln_neptsimp ) THEN
163          IF(lwp) WRITE(numout,*) ' -->   ln_neptsimp enabled, solving for U-UN'
164      ELSE
165          IF(lwp) WRITE(numout,*) ' -->   ln_neptsimp disabled'
166          RETURN
167      ENDIF
168
169      IF( ln_neptramp ) THEN
170          IF(lwp) WRITE(numout,*) ' -->   ln_neptramp enabled, ramp down Neptune'
171          IF(lwp) WRITE(numout,*) ' -->   velocity components in shallow water'
172      ELSE
173          IF(lwp) WRITE(numout,*) ' -->   ln_neptramp disabled'
174      ENDIF
175
176
177!!    Perform dynamic allocation of shared module variables
178      IF( dynnept_alloc() /= 0 )   CALL ctl_warn('dynnept_alloc: array allocate failed.')
179
180!!    Dynamically allocate local work arrays
181      ALLOCATE( ht(jpi,jpj), htn(jpi,jpj), tscale(jpi,jpj), tsp(jpi,jpj),      &
182         &      hur_n(jpi,jpj), hvr_n(jpi,jpj), hu_n(jpi,jpj), hv_n(jpi,jpj),  &
183         &      znmask(jpi,jpj,jpk) )
184
185      IF( .not. ln_rstart ) THEN      ! If restarting, these arrays are read from the restart file
186         zhdivnep(:,:,:) = 0.0_wp
187         zmrotnep(:,:,:) = 0.0_wp
188      END IF
189
190      ! Computation of nmask: same as fmask, but fmask cannot be used
191      ! because it is modified after it is computed in dom_msk
192      ! (this can be optimised to save memory, such as merge into next loop)
193      DO jk = 1, jpk
194         DO jj = 1, jpjm1
195            DO ji = 1, fs_jpim1   ! vector loop
196               znmask(ji,jj,jk) = tmask(ji,jj  ,jk) * tmask(ji+1,jj  ,jk)   &
197                   &            * tmask(ji,jj+1,jk) * tmask(ji+1,jj+1,jk)
198            END DO
199         END DO
200      END DO
201
202      CALL lbc_lnk( znmask, 'F', 1.0_wp )
203
204
205      ! now compute zunep, zvnep (renamed from earlier versions)
206
207      zunep(:,:) = 0.0_wp
208      zvnep(:,:) = 0.0_wp
209
210      htn(:,:) = 0.0_wp            ! ocean depth at F-point
211      DO jk = 1, jpk
212         htn(:,:) = htn(:,:) + fse3f(:,:,jk) * znmask(:,:,jk)
213      END DO
214
215      IF( ln_smoothtopo ) THEN
216         CALL smooth_topo2( htn, ht, .TRUE. )
217      !! overwrites ht with a smoothed version of htn
218      ELSE
219         ht(:,:) = htn(:,:)
220      !! use unsmoothed version of htn
221      ENDIF
222      CALL lbc_lnk( ht, 'F', 1.0_wp )
223
224      !! Compute tsp, a stream function for the Neptune velocity,
225      !! with the usual geophysical sign convention
226      !! Then zunep = -latitudinal derivative "-d(tsp)/dy"
227      !!      zvnep = longitudinal derivative " d(tsp)/dx"
228
229      tsp(:,:)    = 0.0_wp
230      tscale(:,:) = 0.0_wp
231
232      tscale(:,:) = rn_tslsp + (rn_tslse - rn_tslsp) *   &
233                   ( 0.5_wp + 0.5_wp * COS( 2.0_wp * rad * gphif(:,:) )  )
234      tsp   (:,:) = -2.0_wp * omega * SIN( rad * gphif(:,:) ) * tscale(:,:) * tscale(:,:) * ht(:,:)
235
236
237      IF( ln_smoothtopo ) THEN
238         CALL smooth_topo2( hu, hu_n, .TRUE. )
239      !! overwrites hu_n with a smoothed version of hu
240      ELSE
241         hu_n(:,:) = hu(:,:)
242      !! use unsmoothed version of hu
243      ENDIF
244      CALL lbc_lnk( hu_n, 'U', 1.0_wp )
245      hu_n(:,:) = hu_n(:,:) * umask(:,:,1)
246
247      WHERE( hu_n(:,:) == 0.0_wp )
248         hur_n(:,:) = 0.0_wp
249      ELSEWHERE
250         hur_n(:,:) = 1.0_wp / hu_n(:,:)
251      END WHERE
252
253
254      IF( ln_smoothtopo ) THEN
255         CALL smooth_topo2( hv, hv_n, .TRUE. )
256      !! overwrites hv_n with a smoothed version of hv
257      ELSE
258         hv_n(:,:) = hv(:,:)
259      !! use unsmoothed version of hv
260      ENDIF
261      CALL lbc_lnk( hv_n, 'V', 1.0_wp )
262      hv_n(:,:) = hv_n(:,:) * vmask(:,:,1)
263
264      WHERE( hv_n == 0.0_wp )
265         hvr_n(:,:) = 0.0_wp
266      ELSEWHERE
267         hvr_n(:,:) = 1.0_wp / hv_n(:,:)
268      END WHERE
269
270
271      unemin =  1.0e35
272      unemax = -1.0e35
273      vnemin =  1.0e35
274      vnemax = -1.0e35
275      hramp = rn_htrmax - rn_htrmin
276      DO jj = 2, jpj-1
277         DO ji = 2, jpi-1
278            if ( umask(ji,jj,1) /= 0.0_wp ) then
279               ustar =-1.0_wp/e2u(ji,jj) * hur_n(ji,jj) * ( tsp(ji,jj)-tsp(ji,jj-1) ) * umask(ji,jj,1)
280               if ( ln_neptramp ) then
281!!                Apply ramp down to velocity component
282                  if ( hu_n(ji,jj) <= rn_htrmin ) then
283                    zunep(ji,jj) = 0.0_wp
284                   else if ( hu_n(ji,jj) >= rn_htrmax ) then
285                    zunep(ji,jj) = ustar
286                   else if ( hramp > 0.0_wp ) then
287                    zunep(ji,jj) = ( hu_n(ji,jj) - rn_htrmin) * ustar/hramp
288                  endif
289                else
290                 zunep(ji,jj) = ustar
291               endif
292             else
293              zunep(ji,jj) = 0.0_wp
294            endif
295            if ( vmask(ji,jj,1) /= 0.0_wp ) then
296               vstar = 1.0_wp/e1v(ji,jj) * hvr_n(ji,jj) * ( tsp(ji,jj)-tsp(ji-1,jj) ) * vmask(ji,jj,1)
297               if ( ln_neptramp ) then
298!!                Apply ramp down to velocity component
299                  if ( hv_n(ji,jj) <= rn_htrmin ) then
300                    zvnep(ji,jj) = 0.0_wp
301                   else if ( hv_n(ji,jj) >= rn_htrmax ) then
302                    zvnep(ji,jj) = vstar
303                   else if ( hramp > 0.0_wp ) then
304                    zvnep(ji,jj) = ( hv_n(ji,jj) - rn_htrmin) * vstar/hramp
305                  endif
306                else
307                  zvnep(ji,jj) = vstar
308               endif
309             else
310              zvnep(ji,jj) = 0.0_wp
311            endif
312            unemin = min( unemin, zunep(ji,jj) )
313            unemax = max( unemax, zunep(ji,jj) )
314            vnemin = min( vnemin, zvnep(ji,jj) )
315            vnemax = max( vnemax, zvnep(ji,jj) )
316         END DO
317      END DO
318      CALL lbc_lnk( zunep, 'U', -1.0_wp )
319      CALL lbc_lnk( zvnep, 'V', -1.0_wp )
320      WRITE(numout,*) '      zunep: min, max       = ', unemin,unemax
321      WRITE(numout,*) '      zvnep: min, max       = ', vnemin,vnemax
322      WRITE(numout,*)
323
324      !!  Compute, once and for all, the horizontal divergence (zhdivnep)
325      !!  and the curl (zmrotnep) of the Neptune velocity field (zunep, zvnep)
326      CALL div_cur_nept_init
327
328      !! Check the ranges of the computed divergence & vorticity
329      zhdivmin =  1.0e35
330      zhdivmax = -1.0e35
331      zmrotmin =  1.0e35
332      zmrotmax = -1.0e35
333      hramp = rn_htrmax - rn_htrmin
334      DO jk = 1, jpkm1                                 ! Horizontal slab
335         DO jj = 2, jpj-1
336            DO ji = 2, jpi-1
337               zhdivmin = min( zhdivmin, zhdivnep(ji,jj,jk) )
338               zhdivmax = max( zhdivmax, zhdivnep(ji,jj,jk) )
339               zmrotmin = min( zmrotmin, zmrotnep(ji,jj,jk) )
340               zmrotmax = max( zmrotmax, zmrotnep(ji,jj,jk) )
341            END DO
342         END DO
343      END DO
344      WRITE(numout,*) '   zhdivnep: min, max       = ', zhdivmin,zhdivmax
345      WRITE(numout,*) '   zmrotnep: min, max       = ', zmrotmin,zmrotmax
346      WRITE(numout,*)
347
348!!    Deallocate temporary workspace arrays, which are all local to
349!!    this routine, except where passed as arguments to other routines
350      DEALLOCATE( ht, htn, tscale, tsp, hur_n, hvr_n, hu_n, hv_n, znmask )
351
352   END SUBROUTINE dyn_nept_init
353
354
355   SUBROUTINE div_cur_nept_init
356      !!----------------------------------------------------------------------
357      !!             ***  ROUTINE div_cur_nept_init  ***
358      !!
359      !! ** Purpose :   compute the horizontal divergence and the relative
360      !!                vorticity of the time-invariant u* and v* Neptune
361      !!                effect velocities (called zunep, zvnep)
362      !!
363      !! ** Method  : - Divergence:
364      !!      - compute the divergence given by :
365      !!         zhdivnep = 1/(e1t*e2t*e3t) ( di[e2u*e3u zunep] + dj[e1v*e3v zvnep] )
366      !!      - compute the curl in tensorial formalism:
367      !!         zmrotnep = 1/(e1f*e2f) ( di[e2v zvnep] - dj[e1u zunep] )
368      !!      Note: Coastal boundary condition: lateral friction set through
369      !!      the value of fmask along the coast (see dommsk.F90) and shlat
370      !!      (namelist parameter)
371      !!
372      !! ** Action  : - compute zhdivnep, the hor. divergence of (u*, v*)
373      !!              - compute zmrotnep, the rel. vorticity  of (u*, v*)
374      !!
375      !! History :  OPA  ! 1987-06  (P. Andrich, D. L Hostis)  Original code
376      !!            4.0  ! 1991-11  (G. Madec)
377      !!            6.0  ! 1993-03  (M. Guyon)  symetrical conditions
378      !!            7.0  ! 1996-01  (G. Madec)  s-coordinates
379      !!            8.0  ! 1997-06  (G. Madec)  lateral boundary cond., lbc
380      !!            8.1  ! 1997-08  (J.M. Molines)  Open boundaries
381      !!            8.2  ! 2000-03  (G. Madec)  no slip accurate
382      !!  NEMO      1.0  ! 2002-09  (G. Madec, E. Durand)  Free form, F90
383      !!             -   ! 2005-01  (J. Chanut) Unstructured open boundaries
384      !!             -   ! 2003-08  (G. Madec)  merged of cur and div, free form, F90
385      !!             -   ! 2005-01  (J. Chanut, A. Sellar) unstructured open boundaries
386      !!            3.3  ! 2010-09  (D.Storkey and E.O'Dea) bug fixes for BDY module
387      !!                 ! 2011-06  (Jeff Blundell, NOCS) Adapt code from divcur.F90
388      !!                 !           to compute Neptune effect fields only
389      !!----------------------------------------------------------------------
390      !
391      INTEGER  ::   ji, jj, jk          ! dummy loop indices
392      !!----------------------------------------------------------------------
393
394
395      IF(lwp) WRITE(numout,*)
396      IF(lwp) WRITE(numout,*) 'div_cur_nept_init :'
397      IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~~~~~~~~'
398      IF(lwp) WRITE(numout,*) 'horizontal velocity divergence and'
399      IF(lwp) WRITE(numout,*) 'relative vorticity of Neptune flow'
400#if defined key_noslip_accurate
401   !!----------------------------------------------------------------------
402   !!   'key_noslip_accurate'                     2nd order centered scheme
403   !!                                                4th order at the coast
404   !!----------------------------------------------------------------------
405      IF(lwp) WRITE(numout,*)
406      IF(lwp) WRITE(numout,*) 'WARNING: key_noslip_accurate option'
407      IF(lwp) WRITE(numout,*) 'not implemented in simplified Neptune'
408      CALL ctl_warn( ' noslip_accurate option not implemented' )
409#endif
410
411   !!----------------------------------------------------------------------
412   !!   Default option                           2nd order centered schemes
413   !!----------------------------------------------------------------------
414
415      ! Apply the div and curl operators to the depth-dependent velocity
416      ! field produced by multiplying (zunep, zvnep) by (umask, vmask), exactly
417      ! equivalent to the equivalent calculation in the unsimplified code
418      !                                                ! ===============
419      DO jk = 1, jpkm1                                 ! Horizontal slab
420         !                                             ! ===============
421         !                                             ! --------
422         ! Horizontal divergence                       !   div
423         !                                             ! --------
424         DO jj = 2, jpjm1
425            DO ji = fs_2, fs_jpim1   ! vector opt.
426               zhdivnep(ji,jj,jk) =   &
427               &   (  e2u(ji  ,jj  )*fse3u(ji  ,jj  ,jk) * zunep(ji  ,jj  ) * umask(ji  ,jj  ,jk)    &
428               &    - e2u(ji-1,jj  )*fse3u(ji-1,jj  ,jk) * zunep(ji-1,jj  ) * umask(ji-1,jj  ,jk)    &
429               &    + e1v(ji  ,jj  )*fse3v(ji  ,jj  ,jk) * zvnep(ji  ,jj  ) * vmask(ji  ,jj  ,jk)    &
430               &    - e1v(ji  ,jj-1)*fse3v(ji  ,jj-1,jk) * zvnep(ji  ,jj-1) * vmask(ji  ,jj-1,jk) )  &
431               &  / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
432            END DO
433         END DO
434
435#if defined key_obc
436         IF( Agrif_Root() ) THEN
437            ! open boundaries (div must be zero behind the open boundary)
438            !  mpp remark: The zeroing of zhdivnep can probably be extended to 1->jpi/jpj for the correct row/column
439            IF( lp_obc_east  )  zhdivnep(nie0p1:nie1p1,nje0  :nje1  ,jk) = 0.0_wp      ! east
440            IF( lp_obc_west  )  zhdivnep(niw0  :niw1  ,njw0  :njw1  ,jk) = 0.0_wp      ! west
441            IF( lp_obc_north )  zhdivnep(nin0  :nin1  ,njn0p1:njn1p1,jk) = 0.0_wp      ! north
442            IF( lp_obc_south )  zhdivnep(nis0  :nis1  ,njs0  :njs1  ,jk) = 0.0_wp      ! south
443         ENDIF
444#endif
445         IF( .NOT. AGRIF_Root() ) THEN
446            IF ((nbondi ==  1).OR.(nbondi == 2))  zhdivnep(nlci-1 , :     ,jk) = 0.0_wp   ! east
447            IF ((nbondi == -1).OR.(nbondi == 2))  zhdivnep(2      , :     ,jk) = 0.0_wp   ! west
448            IF ((nbondj ==  1).OR.(nbondj == 2))  zhdivnep(:      ,nlcj-1 ,jk) = 0.0_wp   ! north
449            IF ((nbondj == -1).OR.(nbondj == 2))  zhdivnep(:      ,2      ,jk) = 0.0_wp   ! south
450         ENDIF
451
452         !                                             ! --------
453         ! relative vorticity                          !   rot
454         !                                             ! --------
455         DO jj = 1, jpjm1
456            DO ji = 1, fs_jpim1   ! vector opt.
457               zmrotnep(ji,jj,jk) =   &
458                  &       (  e2v(ji+1,jj  ) * zvnep(ji+1,jj  ) * vmask(ji+1,jj  ,jk)     &
459                  &        - e2v(ji  ,jj  ) * zvnep(ji  ,jj  ) * vmask(ji  ,jj  ,jk)     &
460                  &        - e1u(ji  ,jj+1) * zunep(ji  ,jj+1) * umask(ji  ,jj+1,jk)     &
461                  &        + e1u(ji  ,jj  ) * zunep(ji  ,jj  ) * umask(ji  ,jj  ,jk)  )  &
462                  &       * fmask(ji,jj,jk) / ( e1f(ji,jj) * e2f(ji,jj) )
463            END DO
464         END DO
465         !                                             ! ===============
466      END DO                                           !   End of slab
467      !                                                ! ===============
468
469      ! 4. Lateral boundary conditions on zhdivnep and zmrotnep
470      ! ----------------------------------=======-----=======
471      CALL lbc_lnk( zhdivnep, 'T', 1. )   ;   CALL lbc_lnk( zmrotnep , 'F', 1. )     ! lateral boundary cond. (no sign change)
472      !
473   END SUBROUTINE div_cur_nept_init
474
475
476   SUBROUTINE dyn_cor_topo( kt )
477      !!----------------------------------------------------------------------
478      !!                  ***  ROUTINE dyn_cor_topo  ***
479      !!
480      !! ** Purpose :  Add or subtract the Neptune velocity from the now velocities
481      !!
482      !! ** Method  :  First call : kt not equal to lastkt -> subtract zunep, zvnep
483      !!               Second call: kt     equal to lastkt -> add zunep, zvnep
484      !!----------------------------------------------------------------------
485      INTEGER, INTENT( in ) ::   kt       ! ocean time-step index
486      !!
487      INTEGER, SAVE :: lastkt             ! store previous kt
488      DATA lastkt/-1/                     ! initialise previous kt
489      !!----------------------------------------------------------------------
490      !
491      IF( ln_neptsimp ) THEN
492         !
493         IF( lastkt /= kt ) THEN          ! 1st call for this kt: subtract the Neptune velocities zunep, zvnep from un, vn
494            CALL dyn_topo_neptunevel( -1 )      ! -1 = subtract
495            !
496         ELSE                              ! 2nd call for this kt: add the Neptune velocities zunep, zvnep to un, vn
497            CALL dyn_topo_neptunevel(  1 )      !  1 = add
498            !
499         ENDIF
500         !
501    lastkt = kt        ! Store kt
502    !
503      ENDIF
504      !
505   END SUBROUTINE dyn_cor_topo
506
507
508   SUBROUTINE dyn_topo_neptunevel( ksign )
509      !!----------------------------------------------------------------------
510      !!                  ***  ROUTINE dyn_topo_neptunevel  ***
511      !!
512      !! ** Purpose :  Add or subtract the Neptune velocity from the now
513      !!               velocities based on ksign
514      !!----------------------------------------------------------------------
515      INTEGER, INTENT( in ) ::   ksign    ! 1 or -1 to add or subtract neptune velocities
516      !!
517      INTEGER :: jk                       ! dummy loop index
518      !!----------------------------------------------------------------------
519      !
520      ! Adjust the current velocity un, vn by adding or subtracting the
521      ! Neptune velocities zunep, zvnep, as determined by argument ksign
522      DO jk=1, jpk
523         un(:,:,jk) = un(:,:,jk) + ksign * zunep(:,:) * umask(:,:,jk)
524         vn(:,:,jk) = vn(:,:,jk) + ksign * zvnep(:,:) * vmask(:,:,jk)
525      END DO
526      !
527   END SUBROUTINE dyn_topo_neptunevel
528
529
530   SUBROUTINE smooth_topo2( htold, htnew, option )
531
532      !!----------------------------------------------------------------------
533      !!                  ***  ROUTINE smooth_topo2  ***
534      !!
535      !! ** Purpose :  Compute smoothed topography field.
536      !!
537      !! ** Action : - Updates the array htnew (output) with a smoothed
538      !!               version of the (input) array htold. Form of smoothing
539      !!               algorithm is controlled by the (logical) argument option.
540      !!----------------------------------------------------------------------
541
542      INTEGER                                   ::   ji, jj  ! dummy loop indices
543      REAL(wp), DIMENSION(jpi,jpj), INTENT(IN)  ::   htold   ! temporary 2D workspace
544      LOGICAL, INTENT(IN)                       ::   option  ! temporary 2D workspace
545      REAL(wp), DIMENSION(jpi,jpj)              ::   htnew   ! temporary 2D workspace
546      REAL(wp), ALLOCATABLE, DIMENSION(:,:)     ::   work    ! temporary 2D workspace
547      INTEGER,  ALLOCATABLE, DIMENSION(:,:)     ::   nb      ! temporary 2D workspace
548      INTEGER,  ALLOCATABLE, DIMENSION(:,:)     ::   iwork   ! temporary 2D workspace
549
550!!    Dynamically allocate local work arrays
551      ALLOCATE( work(jpi,jpj), nb(jpi,jpj), iwork(jpi,jpj) )
552
553      iwork(:,:) = 0
554
555      !! iwork is a mask of gridpoints: iwork = 1 => ocean, iwork = 0 => land
556      WHERE( htold(:,:) > 0 )
557         iwork(:,:) = 1
558         htnew(:,:) = htold(:,:)
559      ELSEWHERE
560         iwork(:,:) = 0
561         htnew(:,:) = 0.0_wp
562      END WHERE
563      !! htnew contains valid ocean depths from htold, or zero
564
565      !! set work to a smoothed/averaged version of htnew; choice controlled by option
566      !! nb is set to the sum of the weights of the valid values used in work
567      IF( option ) THEN
568
569         !! Apply scale-selective smoothing in determining work from htnew
570         DO jj=2,jpj-1
571            DO ji=2,jpi-1
572               work(ji,jj) = 4.0*htnew( ji , jj ) +                        &
573                           & 2.0*htnew(ji+1, jj ) + 2.0*htnew(ji-1, jj ) + &
574                           & 2.0*htnew( ji ,jj+1) + 2.0*htnew( ji ,jj-1) + &
575                           &     htnew(ji+1,jj+1) +     htnew(ji+1,jj-1) + &
576                           &     htnew(ji-1,jj+1) +     htnew(ji-1,jj-1)
577
578               nb(ji,jj)   = 4 * iwork( ji , jj ) +                        &
579                           & 2 * iwork(ji+1, jj ) + 2 * iwork(ji-1, jj ) + &
580                           & 2 * iwork( ji ,jj+1) + 2 * iwork( ji ,jj-1) + &
581                           &     iwork(ji+1,jj+1) +     iwork(ji+1,jj-1) + &
582                           &     iwork(ji-1,jj+1) +     iwork(ji-1,jj-1)
583            END DO
584         END DO
585
586      ELSE
587
588         !! Apply simple 9-point averaging in determining work from htnew
589         DO jj=2,jpj-1
590            DO ji=2,jpi-1
591               work(ji,jj) =  htnew( ji , jj ) +                    &
592                           &  htnew(ji+1, jj ) + htnew(ji-1, jj ) + &
593                           &  htnew( ji ,jj+1) + htnew( ji ,jj-1) + &
594                           &  htnew(ji+1,jj+1) + htnew(ji+1,jj-1) + &
595                           &  htnew(ji-1,jj+1) + htnew(ji-1,jj-1)
596
597               nb(ji,jj) =    iwork( ji , jj ) +                    &
598                           &  iwork(ji+1, jj ) + iwork(ji-1, jj ) + &
599                           &  iwork( ji ,jj+1) + iwork( ji ,jj-1) + &
600                           &  iwork(ji+1,jj+1) + iwork(ji+1,jj-1) + &
601                           &  iwork(ji-1,jj+1) + iwork(ji-1,jj-1)
602            END DO
603         END DO
604
605      ENDIF
606
607      !! write averaged value of work into htnew,
608      !! if average is valid and point is unmasked
609      WHERE( (htold(:,:) /= 0.0_wp ) .AND. ( nb(:,:) /= 0 ) )
610         htnew(:,:) = work(:,:)/real(nb(:,:))
611      ELSEWHERE
612         htnew(:,:) = 0.0_wp
613      END WHERE
614
615!!    Deallocate temporary workspace arrays, all local to this routine
616      DEALLOCATE( work, nb, iwork )
617
618   END SUBROUTINE smooth_topo2
619
620END MODULE dynnept
Note: See TracBrowser for help on using the repository browser.