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 @ 2808

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

Corrected version of simplified harmonic Neptune effect.
This version runs OK in ORCA2 and ORCA1 configurations.

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