dynnept.F90 27 KB

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