123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 |
- MODULE dynnept
- !!======================================================================
- !! *** MODULE dynnept ***
- !! Ocean dynamics: Neptune effect as proposed by Greg Holloway,
- !! recoded version of simplest case (u*, v* only)
- !!======================================================================
- !! History : 1.0 ! 2007-06 (Michael Dunphy) Modular form: - new namelist parameters
- !! - horizontal diffusion for Neptune
- !! - vertical diffusion for gm in momentum eqns
- !! - option to use Neptune in Coriolis eqn
- !! 2011-08 (Jeff Blundell, NOCS) Simplified form for temporally invariant u*, v*
- !! Horizontal and vertical diffusivity formulations removed
- !! Dynamic allocation of storage added
- !! Option of ramping Neptune vel. down
- !! to zero added in shallow depths added
- !!----------------------------------------------------------------------
- !! dynnept_alloc :
- !! dyn_nept_init :
- !! dyn_nept_div_cur_init:
- !! dyn_nept_cor :
- !! dyn_nept_vel :
- !! dyn_nept_smooth_vel :
- !!----------------------------------------------------------------------
- USE oce ! ocean dynamics and tracers
- USE dom_oce ! ocean space and time domain
- USE in_out_manager ! I/O manager
- USE lib_mpp ! distributed memory computing
- USE prtctl ! Print control
- USE phycst
- USE lbclnk
- USE wrk_nemo ! Memory Allocation
- IMPLICIT NONE
- PRIVATE
- !! * Routine accessibility
- PUBLIC dyn_nept_init ! routine called by nemogcm.F90
- PUBLIC dyn_nept_cor ! routine called by step.F90
- !! dynnept_alloc() is called only by dyn_nept_init, within this module
- !! dyn_nept_div_cur_init is called only by dyn_nept_init, within this module
- !! dyn_nept_vel is called only by dyn_nept_cor, within this module
- !! * Shared module variables
- REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: zunep, zvnep ! Neptune u and v
- REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: zhdivnep ! hor. div for Neptune vel.
- REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: zmrotnep ! curl for Neptune vel.
- !! * Namelist namdyn_nept variables
- LOGICAL, PUBLIC :: ln_neptsimp ! yes/no simplified neptune
- LOGICAL :: ln_smooth_neptvel ! yes/no smooth zunep, zvnep
- REAL(wp) :: rn_tslse ! value of lengthscale L at the equator
- REAL(wp) :: rn_tslsp ! value of lengthscale L at the pole
- !! Specify whether to ramp down the Neptune velocity in shallow
- !! water, and the depth range controlling such ramping down
- LOGICAL :: ln_neptramp ! ramp down Neptune velocity in shallow water
- REAL(wp) :: rn_htrmin ! min. depth of transition range
- REAL(wp) :: rn_htrmax ! max. depth of transition range
- !! * Module variables
- !! * Substitutions
- # include "vectopt_loop_substitute.h90"
- # include "domzgr_substitute.h90"
- !!----------------------------------------------------------------------
- !! OPA 9.0 , implemented by Bedford Institute of Oceanography
- !!----------------------------------------------------------------------
- !! $Id: dynnept.F90 2355 2015-05-20 07:11:50Z ufla $
- CONTAINS
- INTEGER FUNCTION dynnept_alloc()
- !!----------------------------------------------------------------------
- !! *** ROUTINE dynnept_alloc ***
- !!----------------------------------------------------------------------
- ALLOCATE( zunep(jpi,jpj) , zvnep(jpi,jpj) , &
- & zhdivnep(jpi,jpj,jpk) , zmrotnep(jpi,jpj,jpk) , STAT=dynnept_alloc )
- !
- IF( dynnept_alloc /= 0 ) CALL ctl_warn('dynnept_alloc: array allocate failed.')
- END FUNCTION dynnept_alloc
- SUBROUTINE dyn_nept_init
- !!----------------------------------------------------------------------
- !! *** ROUTINE dyn_nept_init ***
- !!
- !! ** Purpose : Read namelist parameters, initialise arrays
- !! and compute the arrays zunep and zvnep
- !!
- !! ** Method : zunep =
- !! zvnep =
- !!
- !! ** History : 1.0 ! 07-05 (Zeliang Wang) Original code for zunep, zvnep
- !! 1.1 ! 07-06 (Michael Dunphy) namelist and initialisation
- !! 2.0 ! 2011-07 (Jeff Blundell, NOCS)
- !! ! Simplified form for temporally invariant u*, v*
- !! ! Horizontal and vertical diffusivity formulations removed
- !! ! Includes optional tapering-off in shallow depths
- !!----------------------------------------------------------------------
- USE iom
- !!
- INTEGER :: ji, jj, jk ! dummy loop indices
- REAL(wp) :: unemin,unemax,vnemin,vnemax ! extrema of (u*, v*) fields
- REAL(wp) :: zhdivmin,zhdivmax ! extrema of horizontal divergence of (u*, v*) fields
- REAL(wp) :: zmrotmin,zmrotmax ! extrema of the curl of the (u*, v*) fields
- REAL(wp) :: ustar,vstar ! (u*, v*) before tapering in shallow water
- REAL(wp) :: hramp ! depth over which Neptune vel. is ramped down
- !
- REAL(wp), POINTER, DIMENSION(:,: ) :: zht, htn, tscale, tsp, hur_n, hvr_n, hu_n, hv_n
- REAL(wp), POINTER, DIMENSION(:,:,:) :: znmask
- !!
- NAMELIST/namdyn_nept/ ln_neptsimp, ln_smooth_neptvel, rn_tslse, rn_tslsp, &
- ln_neptramp, rn_htrmin, rn_htrmax
- INTEGER :: ios
- !!----------------------------------------------------------------------
- ! Define the (simplified) Neptune parameters
- ! ==========================================
- REWIND( numnam_ref ) ! Namelist namdyn_nept in reference namelist : Simplified Neptune
- READ ( numnam_ref, namdyn_nept, IOSTAT = ios, ERR = 901)
- 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namdyn_nept in reference namelist', lwp )
- REWIND( numnam_cfg ) ! Namelist namdyn_nept in reference namelist : Simplified Neptune
- READ ( numnam_cfg, namdyn_nept, IOSTAT = ios, ERR = 902 )
- 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namdyn_nept in configuration namelist', lwp )
- IF(lwm) WRITE ( numond, namdyn_nept )
- IF(lwp) THEN ! Control print
- WRITE(numout,*)
- WRITE(numout,*) 'dyn_nept_init : Simplified Neptune module'
- WRITE(numout,*) '~~~~~~~~~~~~~'
- WRITE(numout,*) ' --> Reading namelist namdyn_nept parameters:'
- WRITE(numout,*) ' ln_neptsimp = ', ln_neptsimp
- WRITE(numout,*)
- IF( ln_neptsimp ) THEN
- WRITE(numout,*) ' ln_smooth_neptvel = ', ln_smooth_neptvel
- WRITE(numout,*) ' rn_tslse = ', rn_tslse
- WRITE(numout,*) ' rn_tslsp = ', rn_tslsp
- WRITE(numout,*)
- WRITE(numout,*) ' ln_neptramp = ', ln_neptramp
- WRITE(numout,*) ' rn_htrmin = ', rn_htrmin
- WRITE(numout,*) ' rn_htrmax = ', rn_htrmax
- WRITE(numout,*)
- ENDIF
- ENDIF
- !
- IF( .NOT. ln_neptsimp ) RETURN
- ! ! Dynamically allocate local work arrays
- CALL wrk_alloc( jpi, jpj , zht, htn, tscale, tsp, hur_n, hvr_n, hu_n, hv_n )
- CALL wrk_alloc( jpi, jpj, jpk, znmask )
- IF( ln_smooth_neptvel ) THEN
- IF(lwp) WRITE(numout,*) ' --> neptune velocities will be smoothed'
- ELSE
- IF(lwp) WRITE(numout,*) ' --> neptune velocities will not be smoothed'
- ENDIF
- IF( ln_neptramp ) THEN
- IF(lwp) WRITE(numout,*) ' --> ln_neptramp enabled, ramp down Neptune'
- IF(lwp) WRITE(numout,*) ' --> velocity components in shallow water'
- ELSE
- IF(lwp) WRITE(numout,*) ' --> ln_neptramp disabled'
- ENDIF
- !! Perform dynamic allocation of shared module variables
- IF( dynnept_alloc() /= 0 ) CALL ctl_warn('dynnept_alloc: array allocate failed.')
- IF( .not. ln_rstart ) THEN ! If restarting, these arrays are read from the restart file
- zhdivnep(:,:,:) = 0.0_wp
- zmrotnep(:,:,:) = 0.0_wp
- END IF
- ! Computation of nmask: same as fmask, but fmask cannot be used
- ! because it is modified after it is computed in dom_msk
- ! (this can be optimised to save memory, such as merge into next loop)
- DO jk = 1, jpk
- DO jj = 1, jpjm1
- DO ji = 1, fs_jpim1 ! vector loop
- znmask(ji,jj,jk) = tmask(ji,jj ,jk) * tmask(ji+1,jj ,jk) &
- & * tmask(ji,jj+1,jk) * tmask(ji+1,jj+1,jk)
- END DO
- END DO
- END DO
- CALL lbc_lnk( znmask, 'F', 1.0_wp )
- ! now compute zunep, zvnep (renamed from earlier versions)
- zunep(:,:) = 0.0_wp
- zvnep(:,:) = 0.0_wp
- htn(:,:) = 0.0_wp ! ocean depth at F-point
- DO jk = 1, jpk
- htn(:,:) = htn(:,:) + fse3f(:,:,jk) * znmask(:,:,jk)
- END DO
- IF( ln_smooth_neptvel ) THEN
- CALL dyn_nept_smooth_vel( htn, zht, .TRUE. )
- !! overwrites zht with a smoothed version of htn
- ELSE
- zht(:,:) = htn(:,:)
- !! use unsmoothed version of htn
- ENDIF
- CALL lbc_lnk( zht, 'F', 1.0_wp )
- !! Compute tsp, a stream function for the Neptune velocity,
- !! with the usual geophysical sign convention
- !! Then zunep = -latitudinal derivative "-(1/H)*d(tsp)/dy"
- !! zvnep = longitudinal derivative " (1/H)*d(tsp)/dx"
- tsp(:,:) = 0.0_wp
- tscale(:,:) = 0.0_wp
- tscale(:,:) = rn_tslsp + (rn_tslse - rn_tslsp) * &
- ( 0.5_wp + 0.5_wp * COS( 2.0_wp * rad * gphif(:,:) ) )
- tsp (:,:) = -2.0_wp * omega * SIN( rad * gphif(:,:) ) * tscale(:,:) * tscale(:,:) * zht(:,:)
- IF( ln_smooth_neptvel ) THEN
- CALL dyn_nept_smooth_vel( hu, hu_n, .TRUE. )
- !! overwrites hu_n with a smoothed version of hu
- ELSE
- hu_n(:,:) = hu(:,:)
- !! use unsmoothed version of hu
- ENDIF
- CALL lbc_lnk( hu_n, 'U', 1.0_wp )
- hu_n(:,:) = hu_n(:,:) * umask(:,:,1)
- WHERE( hu_n(:,:) == 0.0_wp )
- hur_n(:,:) = 0.0_wp
- ELSEWHERE
- hur_n(:,:) = 1.0_wp / hu_n(:,:)
- END WHERE
- IF( ln_smooth_neptvel ) THEN
- CALL dyn_nept_smooth_vel( hv, hv_n, .TRUE. )
- !! overwrites hv_n with a smoothed version of hv
- ELSE
- hv_n(:,:) = hv(:,:)
- !! use unsmoothed version of hv
- ENDIF
- CALL lbc_lnk( hv_n, 'V', 1.0_wp )
- hv_n(:,:) = hv_n(:,:) * vmask(:,:,1)
- WHERE( hv_n == 0.0_wp )
- hvr_n(:,:) = 0.0_wp
- ELSEWHERE
- hvr_n(:,:) = 1.0_wp / hv_n(:,:)
- END WHERE
- unemin = 1.0e35
- unemax = -1.0e35
- vnemin = 1.0e35
- vnemax = -1.0e35
- hramp = rn_htrmax - rn_htrmin
- DO jj = 2, jpj-1
- DO ji = 2, jpi-1
- if ( umask(ji,jj,1) /= 0.0_wp ) then
- ustar =-1.0_wp/e2u(ji,jj) * hur_n(ji,jj) * ( tsp(ji,jj)-tsp(ji,jj-1) ) * umask(ji,jj,1)
- if ( ln_neptramp ) then
- !! Apply ramp down to velocity component
- if ( hu_n(ji,jj) <= rn_htrmin ) then
- zunep(ji,jj) = 0.0_wp
- else if ( hu_n(ji,jj) >= rn_htrmax ) then
- zunep(ji,jj) = ustar
- else if ( hramp > 0.0_wp ) then
- zunep(ji,jj) = ( hu_n(ji,jj) - rn_htrmin) * ustar/hramp
- endif
- else
- zunep(ji,jj) = ustar
- endif
- else
- zunep(ji,jj) = 0.0_wp
- endif
- if ( vmask(ji,jj,1) /= 0.0_wp ) then
- vstar = 1.0_wp/e1v(ji,jj) * hvr_n(ji,jj) * ( tsp(ji,jj)-tsp(ji-1,jj) ) * vmask(ji,jj,1)
- if ( ln_neptramp ) then
- !! Apply ramp down to velocity component
- if ( hv_n(ji,jj) <= rn_htrmin ) then
- zvnep(ji,jj) = 0.0_wp
- else if ( hv_n(ji,jj) >= rn_htrmax ) then
- zvnep(ji,jj) = vstar
- else if ( hramp > 0.0_wp ) then
- zvnep(ji,jj) = ( hv_n(ji,jj) - rn_htrmin) * vstar/hramp
- endif
- else
- zvnep(ji,jj) = vstar
- endif
- else
- zvnep(ji,jj) = 0.0_wp
- endif
- unemin = min( unemin, zunep(ji,jj) )
- unemax = max( unemax, zunep(ji,jj) )
- vnemin = min( vnemin, zvnep(ji,jj) )
- vnemax = max( vnemax, zvnep(ji,jj) )
- END DO
- END DO
- CALL lbc_lnk( zunep, 'U', -1.0_wp )
- CALL lbc_lnk( zvnep, 'V', -1.0_wp )
- WRITE(numout,*) ' zunep: min, max = ', unemin,unemax
- WRITE(numout,*) ' zvnep: min, max = ', vnemin,vnemax
- WRITE(numout,*)
- !! Compute, once and for all, the horizontal divergence (zhdivnep)
- !! and the curl (zmrotnep) of the Neptune velocity field (zunep, zvnep)
- CALL dyn_nept_div_cur_init
- !! Check the ranges of the computed divergence & vorticity
- zhdivmin = 1.0e35
- zhdivmax = -1.0e35
- zmrotmin = 1.0e35
- zmrotmax = -1.0e35
- hramp = rn_htrmax - rn_htrmin
- DO jk = 1, jpkm1 ! Horizontal slab
- DO jj = 2, jpj-1
- DO ji = 2, jpi-1
- zhdivmin = min( zhdivmin, zhdivnep(ji,jj,jk) )
- zhdivmax = max( zhdivmax, zhdivnep(ji,jj,jk) )
- zmrotmin = min( zmrotmin, zmrotnep(ji,jj,jk) )
- zmrotmax = max( zmrotmax, zmrotnep(ji,jj,jk) )
- END DO
- END DO
- END DO
- WRITE(numout,*) ' zhdivnep: min, max = ', zhdivmin,zhdivmax
- WRITE(numout,*) ' zmrotnep: min, max = ', zmrotmin,zmrotmax
- WRITE(numout,*)
- !! Deallocate temporary workspace arrays, which are all local to
- !! this routine, except where passed as arguments to other routines
- CALL wrk_dealloc( jpi, jpj , zht, htn, tscale, tsp, hur_n, hvr_n, hu_n, hv_n )
- CALL wrk_dealloc( jpi, jpj, jpk, znmask )
- !
- END SUBROUTINE dyn_nept_init
- SUBROUTINE dyn_nept_div_cur_init
- !!----------------------------------------------------------------------
- !! *** ROUTINE dyn_nept_div_cur_init ***
- !!
- !! ** Purpose : compute the horizontal divergence and the relative
- !! vorticity of the time-invariant u* and v* Neptune
- !! effect velocities (called zunep, zvnep)
- !!
- !! ** Method : - Divergence:
- !! - compute the divergence given by :
- !! zhdivnep = 1/(e1t*e2t*e3t) ( di[e2u*e3u zunep] + dj[e1v*e3v zvnep] )
- !! - compute the curl in tensorial formalism:
- !! zmrotnep = 1/(e1f*e2f) ( di[e2v zvnep] - dj[e1u zunep] )
- !! Note: Coastal boundary condition: lateral friction set through
- !! the value of fmask along the coast (see dommsk.F90) and shlat
- !! (namelist parameter)
- !!
- !! ** Action : - compute zhdivnep, the hor. divergence of (u*, v*)
- !! - compute zmrotnep, the rel. vorticity of (u*, v*)
- !!
- !! History : OPA ! 1987-06 (P. Andrich, D. L Hostis) Original code
- !! 4.0 ! 1991-11 (G. Madec)
- !! 6.0 ! 1993-03 (M. Guyon) symetrical conditions
- !! 7.0 ! 1996-01 (G. Madec) s-coordinates
- !! 8.0 ! 1997-06 (G. Madec) lateral boundary cond., lbc
- !! 8.1 ! 1997-08 (J.M. Molines) Open boundaries
- !! 8.2 ! 2000-03 (G. Madec) no slip accurate
- !! NEMO 1.0 ! 2002-09 (G. Madec, E. Durand) Free form, F90
- !! - ! 2005-01 (J. Chanut) Unstructured open boundaries
- !! - ! 2003-08 (G. Madec) merged of cur and div, free form, F90
- !! - ! 2005-01 (J. Chanut, A. Sellar) unstructured open boundaries
- !! 3.3 ! 2010-09 (D.Storkey and E.O'Dea) bug fixes for BDY module
- !! ! 2011-06 (Jeff Blundell, NOCS) Adapt code from divcur.F90
- !! ! to compute Neptune effect fields only
- !!----------------------------------------------------------------------
- !
- INTEGER :: ji, jj, jk ! dummy loop indices
- !!----------------------------------------------------------------------
- !
- IF(lwp) WRITE(numout,*)
- IF(lwp) WRITE(numout,*) 'dyn_nept_div_cur_init :'
- IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~~~~~~~~'
- IF(lwp) WRITE(numout,*) 'horizontal velocity divergence and'
- IF(lwp) WRITE(numout,*) 'relative vorticity of Neptune flow'
- #if defined key_noslip_accurate
- !!----------------------------------------------------------------------
- !! 'key_noslip_accurate' 2nd order centered scheme
- !! 4th order at the coast
- !!----------------------------------------------------------------------
- IF(lwp) WRITE(numout,*)
- IF(lwp) WRITE(numout,*) 'WARNING: key_noslip_accurate option'
- IF(lwp) WRITE(numout,*) 'not implemented in simplified Neptune'
- CALL ctl_warn( ' noslip_accurate option not implemented' )
- #endif
- !!----------------------------------------------------------------------
- !! Default option 2nd order centered schemes
- !!----------------------------------------------------------------------
- ! Apply the div and curl operators to the depth-dependent velocity
- ! field produced by multiplying (zunep, zvnep) by (umask, vmask), exactly
- ! equivalent to the equivalent calculation in the unsimplified code
- ! ! ===============
- DO jk = 1, jpkm1 ! Horizontal slab
- ! ! ===============
- ! ! --------
- ! Horizontal divergence ! div
- ! ! --------
- DO jj = 2, jpjm1
- DO ji = fs_2, fs_jpim1 ! vector opt.
- zhdivnep(ji,jj,jk) = &
- & ( e2u(ji ,jj )*fse3u(ji ,jj ,jk) * zunep(ji ,jj ) * umask(ji ,jj ,jk) &
- & - e2u(ji-1,jj )*fse3u(ji-1,jj ,jk) * zunep(ji-1,jj ) * umask(ji-1,jj ,jk) &
- & + e1v(ji ,jj )*fse3v(ji ,jj ,jk) * zvnep(ji ,jj ) * vmask(ji ,jj ,jk) &
- & - e1v(ji ,jj-1)*fse3v(ji ,jj-1,jk) * zvnep(ji ,jj-1) * vmask(ji ,jj-1,jk) ) &
- & / ( e1t(ji,jj) * e2t(ji,jj) * fse3t(ji,jj,jk) )
- END DO
- END DO
- IF( .NOT. AGRIF_Root() ) THEN
- IF ((nbondi == 1).OR.(nbondi == 2)) zhdivnep(nlci-1 , : ,jk) = 0.0_wp ! east
- IF ((nbondi == -1).OR.(nbondi == 2)) zhdivnep(2 , : ,jk) = 0.0_wp ! west
- IF ((nbondj == 1).OR.(nbondj == 2)) zhdivnep(: ,nlcj-1 ,jk) = 0.0_wp ! north
- IF ((nbondj == -1).OR.(nbondj == 2)) zhdivnep(: ,2 ,jk) = 0.0_wp ! south
- ENDIF
- ! ! --------
- ! relative vorticity ! rot
- ! ! --------
- DO jj = 1, jpjm1
- DO ji = 1, fs_jpim1 ! vector opt.
- zmrotnep(ji,jj,jk) = &
- & ( e2v(ji+1,jj ) * zvnep(ji+1,jj ) * vmask(ji+1,jj ,jk) &
- & - e2v(ji ,jj ) * zvnep(ji ,jj ) * vmask(ji ,jj ,jk) &
- & - e1u(ji ,jj+1) * zunep(ji ,jj+1) * umask(ji ,jj+1,jk) &
- & + e1u(ji ,jj ) * zunep(ji ,jj ) * umask(ji ,jj ,jk) ) &
- & * fmask(ji,jj,jk) / ( e1f(ji,jj) * e2f(ji,jj) )
- END DO
- END DO
- ! ! ===============
- END DO ! End of slab
- ! ! ===============
- ! 4. Lateral boundary conditions on zhdivnep and zmrotnep
- ! ----------------------------------=======-----=======
- CALL lbc_lnk( zhdivnep, 'T', 1. ) ; CALL lbc_lnk( zmrotnep , 'F', 1. ) ! lateral boundary cond. (no sign change)
- !
- END SUBROUTINE dyn_nept_div_cur_init
- SUBROUTINE dyn_nept_cor( kt )
- !!----------------------------------------------------------------------
- !! *** ROUTINE dyn_nept_cor ***
- !!
- !! ** Purpose : Add or subtract the Neptune velocity from the now velocities
- !!
- !! ** Method : First call : kt not equal to lastkt -> subtract zunep, zvnep
- !! Second call: kt equal to lastkt -> add zunep, zvnep
- !!----------------------------------------------------------------------
- INTEGER, INTENT( in ) :: kt ! ocean time-step index
- !!
- INTEGER, SAVE :: lastkt ! store previous kt
- DATA lastkt/-1/ ! initialise previous kt
- !!----------------------------------------------------------------------
- !
- IF( ln_neptsimp ) THEN
- !
- IF( lastkt /= kt ) THEN ! 1st call for this kt: subtract the Neptune velocities zunep, zvnep from un, vn
- CALL dyn_nept_vel( -1 ) ! -1 = subtract
- !
- ELSE ! 2nd call for this kt: add the Neptune velocities zunep, zvnep to un, vn
- CALL dyn_nept_vel( 1 ) ! 1 = add
- !
- ENDIF
- !
- lastkt = kt ! Store kt
- !
- ENDIF
- !
- END SUBROUTINE dyn_nept_cor
- SUBROUTINE dyn_nept_vel( ksign )
- !!----------------------------------------------------------------------
- !! *** ROUTINE dyn_nept_vel ***
- !!
- !! ** Purpose : Add or subtract the Neptune velocity from the now
- !! velocities based on ksign
- !!----------------------------------------------------------------------
- INTEGER, INTENT( in ) :: ksign ! 1 or -1 to add or subtract neptune velocities
- !!
- INTEGER :: jk ! dummy loop index
- !!----------------------------------------------------------------------
- !
- ! Adjust the current velocity un, vn by adding or subtracting the
- ! Neptune velocities zunep, zvnep, as determined by argument ksign
- DO jk=1, jpk
- un(:,:,jk) = un(:,:,jk) + ksign * zunep(:,:) * umask(:,:,jk)
- vn(:,:,jk) = vn(:,:,jk) + ksign * zvnep(:,:) * vmask(:,:,jk)
- END DO
- !
- END SUBROUTINE dyn_nept_vel
- SUBROUTINE dyn_nept_smooth_vel( htold, htnew, ld_option )
- !!----------------------------------------------------------------------
- !! *** ROUTINE dyn_nept_smooth_vel ***
- !!
- !! ** Purpose : Compute smoothed topography field.
- !!
- !! ** Action : - Updates the array htnew (output) with a smoothed
- !! version of the (input) array htold. Form of smoothing
- !! algorithm is controlled by the (logical) argument ld_option.
- !!----------------------------------------------------------------------
- REAL(wp), DIMENSION(jpi,jpj), INTENT(in ) :: htold ! temporary 2D workspace
- LOGICAL , INTENT(in ) :: ld_option ! temporary 2D workspace
- REAL(wp), DIMENSION(jpi,jpj), INTENT(inout) :: htnew ! temporary 2D workspace
- !
- INTEGER :: ji, jj ! dummy loop indices
- INTEGER , POINTER, DIMENSION(:,:) :: nb, iwork
- REAL(wp), POINTER, DIMENSION(:,:) :: work ! temporary 2D workspace
- !!----------------------------------------------------------------------
- !
- CALL wrk_alloc( jpi, jpj, nb, iwork )
- CALL wrk_alloc( jpi, jpj, work )
- !
- iwork(:,:) = 0
- !! iwork is a mask of gridpoints: iwork = 1 => ocean, iwork = 0 => land
- WHERE( htold(:,:) > 0 )
- iwork(:,:) = 1
- htnew(:,:) = htold(:,:)
- ELSEWHERE
- iwork(:,:) = 0
- htnew(:,:) = 0.0_wp
- END WHERE
- !! htnew contains valid ocean depths from htold, or zero
- !! set work to a smoothed/averaged version of htnew; choice controlled by ld_option
- !! nb is set to the sum of the weights of the valid values used in work
- IF( ld_option ) THEN
- !! Apply scale-selective smoothing in determining work from htnew
- DO jj=2,jpj-1
- DO ji=2,jpi-1
- work(ji,jj) = 4.0*htnew( ji , jj ) + &
- & 2.0*htnew(ji+1, jj ) + 2.0*htnew(ji-1, jj ) + &
- & 2.0*htnew( ji ,jj+1) + 2.0*htnew( ji ,jj-1) + &
- & htnew(ji+1,jj+1) + htnew(ji+1,jj-1) + &
- & htnew(ji-1,jj+1) + htnew(ji-1,jj-1)
- nb(ji,jj) = 4 * iwork( ji , jj ) + &
- & 2 * iwork(ji+1, jj ) + 2 * iwork(ji-1, jj ) + &
- & 2 * iwork( ji ,jj+1) + 2 * iwork( ji ,jj-1) + &
- & iwork(ji+1,jj+1) + iwork(ji+1,jj-1) + &
- & iwork(ji-1,jj+1) + iwork(ji-1,jj-1)
- END DO
- END DO
- ELSE
- !! Apply simple 9-point averaging in determining work from htnew
- DO jj=2,jpj-1
- DO ji=2,jpi-1
- work(ji,jj) = htnew( ji , jj ) + &
- & htnew(ji+1, jj ) + htnew(ji-1, jj ) + &
- & htnew( ji ,jj+1) + htnew( ji ,jj-1) + &
- & htnew(ji+1,jj+1) + htnew(ji+1,jj-1) + &
- & htnew(ji-1,jj+1) + htnew(ji-1,jj-1)
- nb(ji,jj) = iwork( ji , jj ) + &
- & iwork(ji+1, jj ) + iwork(ji-1, jj ) + &
- & iwork( ji ,jj+1) + iwork( ji ,jj-1) + &
- & iwork(ji+1,jj+1) + iwork(ji+1,jj-1) + &
- & iwork(ji-1,jj+1) + iwork(ji-1,jj-1)
- END DO
- END DO
- ENDIF
- !! write averaged value of work into htnew,
- !! if average is valid and point is unmasked
- WHERE( (htold(:,:) /= 0.0_wp ) .AND. ( nb(:,:) /= 0 ) )
- htnew(:,:) = work(:,:)/real(nb(:,:))
- ELSEWHERE
- htnew(:,:) = 0.0_wp
- END WHERE
- !! Deallocate temporary workspace arrays, all local to this routine
- CALL wrk_dealloc( jpi, jpj, nb, iwork )
- CALL wrk_dealloc( jpi, jpj, work )
- !
- END SUBROUTINE dyn_nept_smooth_vel
- END MODULE dynnept
|