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

source: branches/2011/dev_NOC_2011_MERGE/NEMOGCM/NEMO/OPA_SRC/DYN/dynnept.F90 @ 2986

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

Branch dev_NOC_2011_MERGE. #874. Step 4: Merge in changes from 2011/dev_r2787_NOCS_NEPTUNE branch

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