dynspg.F90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. MODULE dynspg
  2. !!======================================================================
  3. !! *** MODULE dynspg ***
  4. !! Ocean dynamics: surface pressure gradient control
  5. !!======================================================================
  6. !! History : 1.0 ! 2005-12 (C. Talandier, G. Madec, V. Garnier) Original code
  7. !! 3.2 ! 2009-07 (R. Benshila) Suppression of rigid-lid option
  8. !!----------------------------------------------------------------------
  9. !!----------------------------------------------------------------------
  10. !! dyn_spg : update the dynamics trend with the lateral diffusion
  11. !! dyn_spg_ctl : initialization, namelist read, and parameters control
  12. !!----------------------------------------------------------------------
  13. USE oce ! ocean dynamics and tracers variables
  14. USE dom_oce ! ocean space and time domain variables
  15. USE c1d ! 1D vertical configuration
  16. USE phycst ! physical constants
  17. USE sbc_oce ! surface boundary condition: ocean
  18. USE sbcapr ! surface boundary condition: atmospheric pressure
  19. USE dynspg_oce ! surface pressure gradient variables
  20. USE dynspg_exp ! surface pressure gradient (dyn_spg_exp routine)
  21. USE dynspg_ts ! surface pressure gradient (dyn_spg_ts routine)
  22. USE dynspg_flt ! surface pressure gradient (dyn_spg_flt routine)
  23. USE dynadv ! dynamics: vector invariant versus flux form
  24. USE dynhpg, ONLY: ln_dynhpg_imp
  25. USE sbctide
  26. USE updtide
  27. USE trd_oce ! trends: ocean variables
  28. USE trddyn ! trend manager: dynamics
  29. !
  30. USE prtctl ! Print control (prt_ctl routine)
  31. USE in_out_manager ! I/O manager
  32. USE lib_mpp ! MPP library
  33. USE solver ! solver initialization
  34. USE wrk_nemo ! Memory Allocation
  35. USE timing ! Timing
  36. IMPLICIT NONE
  37. PRIVATE
  38. PUBLIC dyn_spg ! routine called by step module
  39. PUBLIC dyn_spg_init ! routine called by opa module
  40. INTEGER :: nspg = 0 ! type of surface pressure gradient scheme defined from lk_dynspg_...
  41. !! * Substitutions
  42. # include "domzgr_substitute.h90"
  43. # include "vectopt_loop_substitute.h90"
  44. !!----------------------------------------------------------------------
  45. !! NEMO/OPA 3.2 , LODYC-IPSL (2009)
  46. !! $Id: dynspg.F90 4990 2014-12-15 16:42:49Z timgraham $
  47. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  48. !!----------------------------------------------------------------------
  49. CONTAINS
  50. SUBROUTINE dyn_spg( kt, kindic )
  51. !!----------------------------------------------------------------------
  52. !! *** ROUTINE dyn_spg ***
  53. !!
  54. !! ** Purpose : achieve the momentum time stepping by computing the
  55. !! last trend, the surface pressure gradient including the
  56. !! atmospheric pressure forcing (ln_apr_dyn=T), and performing
  57. !! the Leap-Frog integration.
  58. !!gm In the current version only the filtered solution provide
  59. !!gm the after velocity, in the 2 other (ua,va) are still the trends
  60. !!
  61. !! ** Method : Three schemes:
  62. !! - explicit computation : the spg is evaluated at now
  63. !! - filtered computation : the Roulet & madec (2000) technique is used
  64. !! - split-explicit computation: a time splitting technique is used
  65. !!
  66. !! ln_apr_dyn=T : the atmospheric pressure forcing is applied
  67. !! as the gradient of the inverse barometer ssh:
  68. !! apgu = - 1/rau0 di[apr] = 0.5*grav di[ssh_ib+ssh_ibb]
  69. !! apgv = - 1/rau0 dj[apr] = 0.5*grav dj[ssh_ib+ssh_ibb]
  70. !! Note that as all external forcing a time averaging over a two rdt
  71. !! period is used to prevent the divergence of odd and even time step.
  72. !!
  73. !! N.B. : When key_esopa is used all the scheme are tested, regardless
  74. !! of the physical meaning of the results.
  75. !!----------------------------------------------------------------------
  76. !
  77. INTEGER, INTENT(in ) :: kt ! ocean time-step index
  78. INTEGER, INTENT( out) :: kindic ! solver flag
  79. !
  80. INTEGER :: ji, jj, jk ! dummy loop indices
  81. REAL(wp) :: z2dt, zg_2, zintp, zgrau0r ! temporary scalar
  82. REAL(wp), POINTER, DIMENSION(:,:,:) :: ztrdu, ztrdv
  83. REAL(wp), POINTER, DIMENSION(:,:) :: zpice
  84. !!----------------------------------------------------------------------
  85. !
  86. IF( nn_timing == 1 ) CALL timing_start('dyn_spg')
  87. !
  88. !!gm NOTA BENE : the dynspg_exp and dynspg_ts should be modified so that
  89. !!gm they return the after velocity, not the trends (as in trazdf_imp...)
  90. !!gm In this case, change/simplify dynnxt
  91. IF( l_trddyn ) THEN ! temporary save of ta and sa trends
  92. CALL wrk_alloc( jpi, jpj, jpk, ztrdu, ztrdv )
  93. ztrdu(:,:,:) = ua(:,:,:)
  94. ztrdv(:,:,:) = va(:,:,:)
  95. ENDIF
  96. IF( ln_apr_dyn & ! atmos. pressure
  97. .OR. ( .NOT.lk_dynspg_ts .AND. (ln_tide_pot .AND. lk_tide) ) & ! tide potential (no time slitting)
  98. .OR. nn_ice_embd == 2 ) THEN ! embedded sea-ice
  99. !
  100. DO jj = 2, jpjm1
  101. DO ji = fs_2, fs_jpim1 ! vector opt.
  102. spgu(ji,jj) = 0._wp
  103. spgv(ji,jj) = 0._wp
  104. END DO
  105. END DO
  106. !
  107. IF( ln_apr_dyn .AND. (.NOT. lk_dynspg_ts) ) THEN !== Atmospheric pressure gradient (added later in time-split case) ==!
  108. zg_2 = grav * 0.5
  109. DO jj = 2, jpjm1 ! gradient of Patm using inverse barometer ssh
  110. DO ji = fs_2, fs_jpim1 ! vector opt.
  111. spgu(ji,jj) = spgu(ji,jj) + zg_2 * ( ssh_ib (ji+1,jj) - ssh_ib (ji,jj) &
  112. & + ssh_ibb(ji+1,jj) - ssh_ibb(ji,jj) ) /e1u(ji,jj)
  113. spgv(ji,jj) = spgv(ji,jj) + zg_2 * ( ssh_ib (ji,jj+1) - ssh_ib (ji,jj) &
  114. & + ssh_ibb(ji,jj+1) - ssh_ibb(ji,jj) ) /e2v(ji,jj)
  115. END DO
  116. END DO
  117. ENDIF
  118. !
  119. ! !== tide potential forcing term ==!
  120. IF( .NOT.lk_dynspg_ts .AND. ( ln_tide_pot .AND. lk_tide ) ) THEN ! N.B. added directly at sub-time-step in ts-case
  121. !
  122. CALL upd_tide( kt ) ! update tide potential
  123. !
  124. DO jj = 2, jpjm1 ! add tide potential forcing
  125. DO ji = fs_2, fs_jpim1 ! vector opt.
  126. spgu(ji,jj) = spgu(ji,jj) + grav * ( pot_astro(ji+1,jj) - pot_astro(ji,jj) ) / e1u(ji,jj)
  127. spgv(ji,jj) = spgv(ji,jj) + grav * ( pot_astro(ji,jj+1) - pot_astro(ji,jj) ) / e2v(ji,jj)
  128. END DO
  129. END DO
  130. ENDIF
  131. !
  132. IF( nn_ice_embd == 2 ) THEN !== embedded sea ice: Pressure gradient due to snow-ice mass ==!
  133. CALL wrk_alloc( jpi, jpj, zpice )
  134. !
  135. zintp = REAL( MOD( kt-1, nn_fsbc ) ) / REAL( nn_fsbc )
  136. zgrau0r = - grav * r1_rau0
  137. zpice(:,:) = ( zintp * snwice_mass(:,:) + ( 1.- zintp ) * snwice_mass_b(:,:) ) * zgrau0r
  138. DO jj = 2, jpjm1
  139. DO ji = fs_2, fs_jpim1 ! vector opt.
  140. spgu(ji,jj) = spgu(ji,jj) + ( zpice(ji+1,jj) - zpice(ji,jj) ) / e1u(ji,jj)
  141. spgv(ji,jj) = spgv(ji,jj) + ( zpice(ji,jj+1) - zpice(ji,jj) ) / e2v(ji,jj)
  142. END DO
  143. END DO
  144. !
  145. CALL wrk_dealloc( jpi, jpj, zpice )
  146. ENDIF
  147. !
  148. DO jk = 1, jpkm1 !== Add all terms to the general trend
  149. DO jj = 2, jpjm1
  150. DO ji = fs_2, fs_jpim1 ! vector opt.
  151. ua(ji,jj,jk) = ua(ji,jj,jk) + spgu(ji,jj)
  152. va(ji,jj,jk) = va(ji,jj,jk) + spgv(ji,jj)
  153. END DO
  154. END DO
  155. END DO
  156. !!gm add here a call to dyn_trd for ice pressure gradient, the surf pressure trends ????
  157. ENDIF
  158. SELECT CASE ( nspg ) ! compute surf. pressure gradient trend and add it to the general trend
  159. !
  160. CASE ( 0 ) ; CALL dyn_spg_exp( kt ) ! explicit
  161. CASE ( 1 ) ; CALL dyn_spg_ts ( kt ) ! time-splitting
  162. CASE ( 2 ) ; CALL dyn_spg_flt( kt, kindic ) ! filtered
  163. !
  164. CASE ( -1 ) ! esopa: test all possibility with control print
  165. CALL dyn_spg_exp( kt )
  166. CALL prt_ctl( tab3d_1=ua, clinfo1=' spg0 - Ua: ', mask1=umask, &
  167. & tab3d_2=va, clinfo2= ' Va: ', mask2=vmask, clinfo3='dyn' )
  168. CALL dyn_spg_ts ( kt )
  169. CALL prt_ctl( tab3d_1=ua, clinfo1=' spg1 - Ua: ', mask1=umask, &
  170. & tab3d_2=va, clinfo2= ' Va: ', mask2=vmask, clinfo3='dyn' )
  171. CALL dyn_spg_flt( kt, kindic )
  172. CALL prt_ctl( tab3d_1=ua, clinfo1=' spg2 - Ua: ', mask1=umask, &
  173. & tab3d_2=va, clinfo2= ' Va: ', mask2=vmask, clinfo3='dyn' )
  174. END SELECT
  175. !
  176. IF( l_trddyn ) THEN ! save the surface pressure gradient trends for further diagnostics
  177. SELECT CASE ( nspg )
  178. CASE ( 0, 1 )
  179. ztrdu(:,:,:) = ua(:,:,:) - ztrdu(:,:,:)
  180. ztrdv(:,:,:) = va(:,:,:) - ztrdv(:,:,:)
  181. CASE( 2 )
  182. z2dt = 2. * rdt
  183. IF( neuler == 0 .AND. kt == nit000 ) z2dt = rdt
  184. ztrdu(:,:,:) = ( ua(:,:,:) - ub(:,:,:) ) / z2dt - ztrdu(:,:,:)
  185. ztrdv(:,:,:) = ( va(:,:,:) - vb(:,:,:) ) / z2dt - ztrdv(:,:,:)
  186. END SELECT
  187. CALL trd_dyn( ztrdu, ztrdv, jpdyn_spg, kt )
  188. !
  189. CALL wrk_dealloc( jpi, jpj, jpk, ztrdu, ztrdv )
  190. ENDIF
  191. ! ! print mean trends (used for debugging)
  192. IF(ln_ctl) CALL prt_ctl( tab3d_1=ua, clinfo1=' spg - Ua: ', mask1=umask, &
  193. & tab3d_2=va, clinfo2= ' Va: ', mask2=vmask, clinfo3='dyn' )
  194. !
  195. IF( nn_timing == 1 ) CALL timing_stop('dyn_spg')
  196. !
  197. END SUBROUTINE dyn_spg
  198. SUBROUTINE dyn_spg_init
  199. !!---------------------------------------------------------------------
  200. !! *** ROUTINE dyn_spg_init ***
  201. !!
  202. !! ** Purpose : Control the consistency between cpp options for
  203. !! surface pressure gradient schemes
  204. !!----------------------------------------------------------------------
  205. INTEGER :: ioptio
  206. !!----------------------------------------------------------------------
  207. !
  208. IF( nn_timing == 1 ) CALL timing_start('dyn_spg_init')
  209. !
  210. IF(lwp) THEN ! Control print
  211. WRITE(numout,*)
  212. WRITE(numout,*) 'dyn_spg_init : choice of the surface pressure gradient scheme'
  213. WRITE(numout,*) '~~~~~~~~~~~'
  214. WRITE(numout,*) ' Explicit free surface lk_dynspg_exp = ', lk_dynspg_exp
  215. WRITE(numout,*) ' Free surface with time splitting lk_dynspg_ts = ', lk_dynspg_ts
  216. WRITE(numout,*) ' Filtered free surface cst volume lk_dynspg_flt = ', lk_dynspg_flt
  217. ENDIF
  218. IF( lk_dynspg_ts ) CALL dyn_spg_ts_init( nit000 )
  219. ! (do it now, to set nn_baro, used to allocate some arrays later on)
  220. ! ! allocate dyn_spg arrays
  221. IF( lk_dynspg_ts ) THEN
  222. IF( dynspg_oce_alloc() /= 0 ) CALL ctl_stop('STOP', 'dyn_spg_init: failed to allocate dynspg_oce arrays')
  223. IF( dyn_spg_ts_alloc() /= 0 ) CALL ctl_stop('STOP', 'dyn_spg_init: failed to allocate dynspg_ts arrays')
  224. IF ((neuler/=0).AND.(ln_bt_fw)) CALL ts_rst( nit000, 'READ' )
  225. ENDIF
  226. ! ! Control of surface pressure gradient scheme options
  227. ioptio = 0
  228. IF(lk_dynspg_exp) ioptio = ioptio + 1
  229. IF(lk_dynspg_ts ) ioptio = ioptio + 1
  230. IF(lk_dynspg_flt) ioptio = ioptio + 1
  231. !
  232. IF( ( ioptio > 1 .AND. .NOT. lk_esopa ) .OR. ( ioptio == 0 .AND. .NOT. lk_c1d ) ) &
  233. & CALL ctl_stop( ' Choose only one surface pressure gradient scheme with a key cpp' )
  234. IF( ( lk_dynspg_ts .OR. lk_dynspg_exp ) .AND. ln_isfcav ) &
  235. & CALL ctl_stop( ' dynspg_ts and dynspg_exp not tested with ice shelf cavity ' )
  236. !
  237. IF( lk_esopa ) nspg = -1
  238. IF( lk_dynspg_exp) nspg = 0
  239. IF( lk_dynspg_ts ) nspg = 1
  240. IF( lk_dynspg_flt) nspg = 2
  241. !
  242. IF( lk_esopa ) nspg = -1
  243. !
  244. IF(lwp) THEN
  245. WRITE(numout,*)
  246. IF( nspg == -1 ) WRITE(numout,*) ' ESOPA test All scheme used'
  247. IF( nspg == 0 ) WRITE(numout,*) ' explicit free surface'
  248. IF( nspg == 1 ) WRITE(numout,*) ' free surface with time splitting scheme'
  249. IF( nspg == 2 ) WRITE(numout,*) ' filtered free surface'
  250. ENDIF
  251. #if defined key_dynspg_flt || defined key_esopa
  252. CALL solver_init( nit000 ) ! Elliptic solver initialisation
  253. #endif
  254. ! ! Control of timestep choice
  255. IF( lk_dynspg_ts .OR. lk_dynspg_exp ) THEN
  256. IF( nn_cla == 1 ) CALL ctl_stop( 'Crossland advection not implemented for this free surface formulation' )
  257. ENDIF
  258. ! ! Control of hydrostatic pressure choice
  259. IF( lk_dynspg_ts .AND. ln_dynhpg_imp ) THEN
  260. CALL ctl_stop( 'Semi-implicit hpg not compatible with time splitting' )
  261. ENDIF
  262. !
  263. IF( nn_timing == 1 ) CALL timing_stop('dyn_spg_init')
  264. !
  265. END SUBROUTINE dyn_spg_init
  266. !!======================================================================
  267. END MODULE dynspg