dtauvd.F90 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. MODULE dtauvd
  2. !!======================================================================
  3. !! *** MODULE dtauvd ***
  4. !! Ocean data : read ocean U & V current data from gridded data
  5. !!======================================================================
  6. !! History : 3.5 ! 2013-08 (D. Calvert) Original code
  7. !!----------------------------------------------------------------------
  8. !!----------------------------------------------------------------------
  9. !! dta_uvd_init : read namelist and allocate data structures
  10. !! dta_uvd : read and time-interpolate ocean U & V current data
  11. !!----------------------------------------------------------------------
  12. USE oce ! ocean dynamics and tracers
  13. USE dom_oce ! ocean space and time domain
  14. USE fldread ! read input fields
  15. USE in_out_manager ! I/O manager
  16. USE phycst ! physical constants
  17. USE lib_mpp ! MPP library
  18. USE wrk_nemo ! Memory allocation
  19. USE timing ! Timing
  20. IMPLICIT NONE
  21. PRIVATE
  22. PUBLIC dta_uvd_init ! called by nemogcm.F90
  23. PUBLIC dta_uvd ! called by istate.F90 and dyndmp.90
  24. LOGICAL , PUBLIC :: ln_uvd_init ! Flag to initialise with U & V current data
  25. LOGICAL , PUBLIC :: ln_uvd_dyndmp ! Flag for Newtonian damping toward U & V current data
  26. TYPE(FLD), ALLOCATABLE, DIMENSION(:) :: sf_uvd ! structure for input U & V current (file information and data)
  27. !! * Substitutions
  28. # include "domzgr_substitute.h90"
  29. !!----------------------------------------------------------------------
  30. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  31. !! $Id: dtauvd.F90 2355 2015-05-20 07:11:50Z ufla $
  32. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  33. !!----------------------------------------------------------------------
  34. CONTAINS
  35. SUBROUTINE dta_uvd_init( ld_dyndmp )
  36. !!----------------------------------------------------------------------
  37. !! *** ROUTINE dta_uvd_init ***
  38. !!
  39. !! ** Purpose : initialization of U & V current input data
  40. !!
  41. !! ** Method : - read namc1d_uvd namelist
  42. !! - allocate U & V current data structure
  43. !! - fld_fill data structure with namelist information
  44. !!----------------------------------------------------------------------
  45. LOGICAL, INTENT(in), OPTIONAL :: ld_dyndmp ! force the initialization when dyndmp is used
  46. !
  47. INTEGER :: ierr0, ierr1, ierr2, ierr3 ! temporary integers
  48. !
  49. CHARACTER(len=100) :: cn_dir ! Root directory for location of files to be used
  50. TYPE(FLD_N), DIMENSION(2) :: suv_i ! Combined U & V namelist information
  51. TYPE(FLD_N) :: sn_ucur, sn_vcur ! U & V data namelist information
  52. !!
  53. NAMELIST/namc1d_uvd/ ln_uvd_init, ln_uvd_dyndmp, cn_dir, sn_ucur, sn_vcur
  54. INTEGER :: ios
  55. !!----------------------------------------------------------------------
  56. !
  57. IF( nn_timing == 1 ) CALL timing_start('dta_uvd_init')
  58. !
  59. ierr0 = 0 ; ierr1 = 0 ; ierr2 = 0 ; ierr3 = 0
  60. REWIND( numnam_ref ) ! Namelist namc1d_uvd in reference namelist :
  61. READ ( numnam_ref, namc1d_uvd, IOSTAT = ios, ERR = 901)
  62. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namc1d_uvd in reference namelist', lwp )
  63. REWIND( numnam_cfg ) ! Namelist namc1d_uvd in configuration namelist : Parameters of the run
  64. READ ( numnam_cfg, namc1d_uvd, IOSTAT = ios, ERR = 902 )
  65. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namc1d_uvd in configuration namelist', lwp )
  66. IF(lwm) WRITE ( numond, namc1d_uvd )
  67. ! ! force the initialization when dyndmp is used
  68. IF( PRESENT( ld_dyndmp ) ) ln_uvd_dyndmp = .TRUE.
  69. IF(lwp) THEN ! control print
  70. WRITE(numout,*)
  71. WRITE(numout,*) 'dta_uvd_init : U & V current data '
  72. WRITE(numout,*) '~~~~~~~~~~~~ '
  73. WRITE(numout,*) ' Namelist namc1d_uvd : Set flags'
  74. WRITE(numout,*) ' Initialization of ocean U & V current with input data ln_uvd_init = ', ln_uvd_init
  75. WRITE(numout,*) ' Damping of ocean U & V current toward input data ln_uvd_dyndmp = ', ln_uvd_dyndmp
  76. WRITE(numout,*)
  77. IF( .NOT. ln_uvd_init .AND. .NOT. ln_uvd_dyndmp ) THEN
  78. WRITE(numout,*)
  79. WRITE(numout,*) ' U & V current data not used'
  80. ENDIF
  81. ENDIF
  82. ! ! no initialization when restarting
  83. IF( ln_rstart .AND. ln_uvd_init ) THEN
  84. CALL ctl_warn( 'dta_uvd_init: ocean restart and U & V current data initialization, ', &
  85. & 'we keep the restart U & V current values and set ln_uvd_init to FALSE' )
  86. ln_uvd_init = .FALSE.
  87. ENDIF
  88. !
  89. IF( ln_uvd_init .OR. ln_uvd_dyndmp ) THEN
  90. ! !== allocate the data arrays ==!
  91. ALLOCATE( sf_uvd(2), STAT=ierr0 )
  92. IF( ierr0 > 0 ) THEN
  93. CALL ctl_stop( 'dta_uvd_init: unable to allocate sf_uvd structure' ) ; RETURN
  94. ENDIF
  95. !
  96. ALLOCATE( sf_uvd(1)%fnow(jpi,jpj,jpk) , STAT=ierr0 )
  97. IF( sn_ucur%ln_tint ) ALLOCATE( sf_uvd(1)%fdta(jpi,jpj,jpk,2) , STAT=ierr1 )
  98. ALLOCATE( sf_uvd(2)%fnow(jpi,jpj,jpk) , STAT=ierr2 )
  99. IF( sn_vcur%ln_tint ) ALLOCATE( sf_uvd(2)%fdta(jpi,jpj,jpk,2) , STAT=ierr3 )
  100. !
  101. IF( ierr0 + ierr1 + ierr2 + ierr3 > 0 ) THEN
  102. CALL ctl_stop( 'dta_uvd_init : unable to allocate U & V current data arrays' ) ; RETURN
  103. ENDIF
  104. ! !== fill sf_uvd with sn_ucur, sn_vcur and control print ==!
  105. suv_i(1) = sn_ucur ; suv_i(2) = sn_vcur
  106. CALL fld_fill( sf_uvd, suv_i, cn_dir, 'dta_uvd', 'U & V current data', 'namc1d_uvd' )
  107. !
  108. ENDIF
  109. !
  110. IF( nn_timing == 1 ) CALL timing_stop('dta_uvd_init')
  111. !
  112. END SUBROUTINE dta_uvd_init
  113. SUBROUTINE dta_uvd( kt, puvd )
  114. !!----------------------------------------------------------------------
  115. !! *** ROUTINE dta_uvd ***
  116. !!
  117. !! ** Purpose : provides U & V current data at time step kt
  118. !!
  119. !! ** Method : - call fldread routine
  120. !! - ORCA_R2: make some hand made alterations to the data (EMPTY)
  121. !! - s- or mixed s-zps coordinate: vertical interpolation onto model mesh
  122. !! - zps coordinate: vertical interpolation onto last partial level
  123. !! - ln_uvd_dyndmp=False: deallocate the U & V current data structure,
  124. !! as the data is no longer used
  125. !!
  126. !! ** Action : puvd, U & V current data interpolated onto model mesh at time-step kt
  127. !!----------------------------------------------------------------------
  128. INTEGER , INTENT(in ) :: kt ! ocean time-step
  129. REAL(wp), DIMENSION(jpi,jpj,jpk,2), INTENT( out) :: puvd ! U & V current data
  130. !
  131. INTEGER :: ji, jj, jk, jl, jkk ! dummy loop indicies
  132. INTEGER :: ik, il0, il1, ii0, ii1, ij0, ij1 ! local integers
  133. REAL(wp):: zl, zi ! local floats
  134. REAL(wp), POINTER, DIMENSION(:) :: zup, zvp ! 1D workspace
  135. !!----------------------------------------------------------------------
  136. !
  137. IF( nn_timing == 1 ) CALL timing_start('dta_uvd')
  138. !
  139. CALL fld_read( kt, 1, sf_uvd ) !== read U & V current data at time step kt ==!
  140. !
  141. !
  142. ! !== ORCA_R2 configuration and U & V current damping ==!
  143. IF( cp_cfg == "orca" .AND. jp_cfg == 2 .AND. ln_uvd_dyndmp ) THEN ! some hand made alterations
  144. !!! EMPTY- to be added for running in 3D context !!!
  145. ENDIF
  146. !
  147. puvd(:,:,:,1) = sf_uvd(1)%fnow(:,:,:) ! NO mask
  148. puvd(:,:,:,2) = sf_uvd(2)%fnow(:,:,:)
  149. !
  150. IF( ln_sco ) THEN !== s- or mixed s-zps-coordinate ==!
  151. !
  152. CALL wrk_alloc( jpk, zup, zvp )
  153. !
  154. IF( kt == nit000 .AND. lwp )THEN
  155. WRITE(numout,*)
  156. WRITE(numout,*) 'dta_uvd: interpolate U & V current data onto the s- or mixed s-z-coordinate mesh'
  157. ENDIF
  158. !
  159. DO jj = 1, jpj ! vertical interpolation of U & V current:
  160. DO ji = 1, jpi ! determines the interpolated U & V current profiles at each (i,j) point
  161. DO jk = 1, jpk
  162. zl = fsdept(ji,jj,jk)
  163. IF ( zl < gdept_1d(1 ) ) THEN ! extrapolate above the first level of data
  164. zup(jk) = puvd(ji,jj,1 ,1)
  165. zvp(jk) = puvd(ji,jj,1 ,2)
  166. ELSEIF( zl > gdept_1d(jpk) ) THEN ! extrapolate below the last level of data
  167. zup(jk) = puvd(ji,jj,jpkm1,1)
  168. zvp(jk) = puvd(ji,jj,jpkm1,2)
  169. ELSE ! inbetween : vertical interpolation between jkk & jkk+1
  170. DO jkk = 1, jpkm1 ! when gdept(jkk) < zl < gdept(jkk+1)
  171. IF( (zl-gdept_1d(jkk)) * (zl-gdept_1d(jkk+1)) <= 0._wp ) THEN
  172. zi = ( zl - gdept_1d(jkk) ) / (gdept_1d(jkk+1)-gdept_1d(jkk))
  173. zup(jk) = puvd(ji,jj,jkk,1) + ( puvd(ji,jj,jkk+1,1 ) - puvd(ji,jj,jkk,1) ) * zi
  174. zvp(jk) = puvd(ji,jj,jkk,2) + ( puvd(ji,jj,jkk+1,2 ) - puvd(ji,jj,jkk,2) ) * zi
  175. ENDIF
  176. END DO
  177. ENDIF
  178. END DO
  179. DO jk = 1, jpkm1 ! apply mask
  180. puvd(ji,jj,jk,1) = zup(jk) * umask(ji,jj,jk)
  181. puvd(ji,jj,jk,2) = zvp(jk) * vmask(ji,jj,jk)
  182. END DO
  183. puvd(ji,jj,jpk,1) = 0._wp
  184. puvd(ji,jj,jpk,2) = 0._wp
  185. END DO
  186. END DO
  187. !
  188. CALL wrk_dealloc( jpk, zup, zvp )
  189. !
  190. ELSE !== z- or zps- coordinate ==!
  191. !
  192. puvd(:,:,:,1) = puvd(:,:,:,1) * umask(:,:,:) ! apply mask
  193. puvd(:,:,:,2) = puvd(:,:,:,2) * vmask(:,:,:)
  194. !
  195. IF( ln_zps ) THEN ! zps-coordinate (partial steps) interpolation at the last ocean level
  196. DO jj = 1, jpj
  197. DO ji = 1, jpi
  198. ik = mbkt(ji,jj)
  199. IF( ik > 1 ) THEN
  200. zl = ( gdept_1d(ik) - gdept_0(ji,jj,ik) ) / ( gdept_1d(ik) - gdept_1d(ik-1) )
  201. puvd(ji,jj,ik,1) = (1.-zl) * puvd(ji,jj,ik,1) + zl * puvd(ji,jj,ik-1,1)
  202. puvd(ji,jj,ik,2) = (1.-zl) * puvd(ji,jj,ik,2) + zl * puvd(ji,jj,ik-1,2)
  203. ENDIF
  204. END DO
  205. END DO
  206. ENDIF
  207. !
  208. ENDIF
  209. !
  210. IF( lwp .AND. kt == nit000 ) THEN ! control print
  211. WRITE(numout,*) ' U current '
  212. WRITE(numout,*)
  213. WRITE(numout,*)' level = 1'
  214. CALL prihre( puvd(:,:,1 ,1), jpi, jpj, 1, jpi, 20, 1, jpj, 20, 1., numout )
  215. WRITE(numout,*)' level = ', jpk/2
  216. CALL prihre( puvd(:,:,jpk/2,1), jpi, jpj, 1, jpi, 20, 1, jpj, 20, 1., numout )
  217. WRITE(numout,*)' level = ', jpkm1
  218. CALL prihre( puvd(:,:,jpkm1,1), jpi, jpj, 1, jpi, 20, 1, jpj, 20, 1., numout )
  219. WRITE(numout,*)
  220. WRITE(numout,*) ' V current '
  221. WRITE(numout,*)
  222. WRITE(numout,*)' level = 1'
  223. CALL prihre( puvd(:,:,1 ,2), jpi, jpj, 1, jpi, 20, 1, jpj, 20, 1., numout )
  224. WRITE(numout,*)' level = ', jpk/2
  225. CALL prihre( puvd(:,:,jpk/2,2), jpi, jpj, 1, jpi, 20, 1, jpj, 20, 1., numout )
  226. WRITE(numout,*)' level = ', jpkm1
  227. CALL prihre( puvd(:,:,jpkm1,2), jpi, jpj, 1, jpi, 20, 1, jpj, 20, 1., numout )
  228. WRITE(numout,*)
  229. ENDIF
  230. !
  231. IF( .NOT. ln_uvd_dyndmp ) THEN !== deallocate U & V current structure ==!
  232. ! !== (data used only for initialization) ==!
  233. IF(lwp) WRITE(numout,*) 'dta_uvd: deallocate U & V current arrays as they are only used to initialize the run'
  234. DEALLOCATE( sf_uvd(1)%fnow ) ! U current arrays in the structure
  235. IF( sf_uvd(1)%ln_tint ) DEALLOCATE( sf_uvd(1)%fdta )
  236. DEALLOCATE( sf_uvd(2)%fnow ) ! V current arrays in the structure
  237. IF( sf_uvd(2)%ln_tint ) DEALLOCATE( sf_uvd(2)%fdta )
  238. DEALLOCATE( sf_uvd ) ! the structure itself
  239. ENDIF
  240. !
  241. IF( nn_timing == 1 ) CALL timing_stop('dta_uvd')
  242. !
  243. END SUBROUTINE dta_uvd
  244. !!======================================================================
  245. END MODULE dtauvd