obs_inter_sup.F90 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. MODULE obs_inter_sup
  2. !!=====================================================================
  3. !! *** MODULE obs_inter_sup ***
  4. !! Observation diagnostics: Support for interpolation
  5. !!=====================================================================
  6. !!----------------------------------------------------------------------
  7. !! obs_int_comm_3d : Get 3D interpolation stencil
  8. !! obs_int_comm_2d : Get 2D interpolation stencil
  9. !!---------------------------------------------------------------------
  10. !! * Modules used
  11. USE wrk_nemo ! Memory Allocation
  12. USE par_kind ! Precision variables
  13. USE dom_oce ! Domain variables
  14. USE mpp_map ! Map of processor points
  15. USE lib_mpp ! MPP stuff
  16. USE obs_mpp ! MPP stuff for observations
  17. USE obs_grid ! Grid tools
  18. USE in_out_manager ! I/O stuff
  19. IMPLICIT NONE
  20. !! * Routine accessibility
  21. PRIVATE
  22. PUBLIC obs_int_comm_3d, & ! Get 3D interpolation stencil
  23. & obs_int_comm_2d ! Get 2D interpolation stencil
  24. !!----------------------------------------------------------------------
  25. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  26. !! $Id: obs_inter_sup.F90 3294 2012-01-28 16:44:18Z rblod $
  27. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  28. !!----------------------------------------------------------------------
  29. CONTAINS
  30. SUBROUTINE obs_int_comm_3d( kptsi, kptsj, kobs, kpk, kgrdi, kgrdj, &
  31. & pval, pgval, kproc )
  32. !!----------------------------------------------------------------------
  33. !! *** ROUTINE obs_int_comm_3d ***
  34. !!
  35. !! ** Purpose : Get 3D interpolation stencil
  36. !!
  37. !! ** Method : Either on-demand communication with
  38. !! obs_int_comm_3d_global
  39. !! or local memory with
  40. !! obs_int_comm_3D_local
  41. !! depending on ln_global_grid
  42. !!
  43. !! ** Action :
  44. !!
  45. !! History :
  46. !! ! 08-02 (K. Mogensen) Original code
  47. !!----------------------------------------------------------------------
  48. !! * Arguments
  49. INTEGER, INTENT(IN) :: kptsi ! Number of i horizontal points per stencil
  50. INTEGER, INTENT(IN) :: kptsj ! Number of j horizontal points per stencil
  51. INTEGER, INTENT(IN) :: kobs ! Local number of observations
  52. INTEGER, INTENT(IN) :: kpk ! Number of levels
  53. INTEGER, DIMENSION(kptsi,kptsj,kobs), INTENT(IN) :: &
  54. & kgrdi, & ! i,j indicies for each stencil
  55. & kgrdj
  56. INTEGER, OPTIONAL, DIMENSION(kptsi,kptsj,kobs), INTENT(IN) :: &
  57. & kproc ! Precomputed processor for each i,j,iobs points
  58. REAL(KIND=wp), DIMENSION(jpi,jpj,kpk), INTENT(IN) ::&
  59. & pval ! Local 3D array to extract data from
  60. REAL(KIND=wp), DIMENSION(kptsi,kptsj,kpk,kobs), INTENT(OUT) ::&
  61. & pgval ! Stencil at each point
  62. !! * Local declarations
  63. IF (ln_grid_global) THEN
  64. IF (PRESENT(kproc)) THEN
  65. CALL obs_int_comm_3d_global( kptsi, kptsj, kobs, kpk, kgrdi, &
  66. & kgrdj, pval, pgval, kproc=kproc )
  67. ELSE
  68. CALL obs_int_comm_3d_global( kptsi, kptsj, kobs, kpk, kgrdi, &
  69. & kgrdj, pval, pgval )
  70. ENDIF
  71. ELSE
  72. CALL obs_int_comm_3d_local( kptsi, kptsj, kobs, kpk, kgrdi, kgrdj, &
  73. & pval, pgval )
  74. ENDIF
  75. END SUBROUTINE obs_int_comm_3d
  76. SUBROUTINE obs_int_comm_2d( kptsi, kptsj, kobs, kgrdi, kgrdj, pval, pgval, &
  77. & kproc )
  78. !!----------------------------------------------------------------------
  79. !! *** ROUTINE obs_int_comm_2d ***
  80. !!
  81. !! ** Purpose : Get 2D interpolation stencil
  82. !!
  83. !! ** Method : Call to obs_int_comm_3d
  84. !!
  85. !! ** Action :
  86. !!
  87. !! History :
  88. !! ! 08-02 (K. Mogensen) Original code
  89. !!----------------------------------------------------------------------
  90. !!
  91. !! * Arguments
  92. INTEGER, INTENT(IN) :: kptsi ! Number of i horizontal points per stencil
  93. INTEGER, INTENT(IN) :: kptsj ! Number of j horizontal points per stencil
  94. INTEGER, INTENT(IN) :: kobs ! Local number of observations
  95. INTEGER, DIMENSION(kptsi,kptsj,kobs), INTENT(IN) :: &
  96. & kgrdi, & ! i,j indicies for each stencil
  97. & kgrdj
  98. INTEGER, OPTIONAL, DIMENSION(kptsi,kptsj,kobs), INTENT(IN) :: &
  99. & kproc ! Precomputed processor for each i,j,iobs points
  100. REAL(KIND=wp), DIMENSION(jpi,jpj), INTENT(IN) ::&
  101. & pval ! Local 3D array to extra data from
  102. REAL(KIND=wp), DIMENSION(kptsi,kptsj,kobs), INTENT(OUT) ::&
  103. & pgval ! Stencil at each point
  104. !! * Local declarations
  105. REAL(KIND=wp), POINTER, DIMENSION(:,:,:) :: zval
  106. REAL(KIND=wp), DIMENSION(kptsi,kptsj,1,kobs) ::&
  107. & zgval
  108. ! Check workspace array and set-up pointer
  109. CALL wrk_alloc(jpi,jpj,1,zval)
  110. ! Set up local "3D" buffer
  111. zval(:,:,1) = pval(:,:)
  112. ! Call the 3D version
  113. IF (PRESENT(kproc)) THEN
  114. CALL obs_int_comm_3d( kptsi, kptsj, kobs, 1, kgrdi, kgrdj, zval, &
  115. & zgval, kproc=kproc )
  116. ELSE
  117. CALL obs_int_comm_3d( kptsi, kptsj, kobs, 1, kgrdi, kgrdj, zval, &
  118. & zgval )
  119. ENDIF
  120. ! Copy "3D" data back to 2D
  121. pgval(:,:,:) = zgval(:,:,1,:)
  122. ! 'Release' workspace array back to pool
  123. CALL wrk_dealloc(jpi,jpj,1,zval)
  124. END SUBROUTINE obs_int_comm_2d
  125. SUBROUTINE obs_int_comm_3d_global( kptsi, kptsj, kobs, kpk, kgrdi, kgrdj, &
  126. & pval, pgval, kproc )
  127. !!----------------------------------------------------------------------
  128. !! *** ROUTINE obs_int_comm_3d_global ***
  129. !!
  130. !! ** Purpose : Get 3D interpolation stencil (global version)
  131. !!
  132. !! ** Method : On-demand communication where each processor send its
  133. !! list of (i,j) of points to all processors and receive
  134. !! the corresponding values
  135. !!
  136. !! ** Action :
  137. !!
  138. !! History :
  139. !! ! 08-02 (K. Mogensen) Original code
  140. !!----------------------------------------------------------------------
  141. !! * Arguments
  142. INTEGER, INTENT(IN) :: kptsi ! Number of i horizontal points per stencil
  143. INTEGER, INTENT(IN) :: kptsj ! Number of j horizontal points per stencil
  144. INTEGER, INTENT(IN) :: kobs ! Local number of observations
  145. INTEGER, INTENT(IN) :: kpk ! Number of levels
  146. INTEGER, DIMENSION(kptsi,kptsj,kobs), INTENT(IN) :: &
  147. & kgrdi, & ! i,j indicies for each stencil
  148. & kgrdj
  149. INTEGER, OPTIONAL, DIMENSION(kptsi,kptsj,kobs), INTENT(IN) :: &
  150. & kproc ! Precomputed processor for each i,j,iobs points
  151. REAL(KIND=wp), DIMENSION(jpi,jpj,kpk), INTENT(IN) ::&
  152. & pval ! Local 3D array to extract data from
  153. REAL(KIND=wp), DIMENSION(kptsi,kptsj,kpk,kobs), INTENT(OUT) ::&
  154. & pgval ! Stencil at each point
  155. !! * Local declarations
  156. REAL(KIND=wp), DIMENSION(:,:), ALLOCATABLE :: &
  157. & zsend, &
  158. & zrecv
  159. INTEGER, DIMENSION(:), ALLOCATABLE :: &
  160. & igrdij_send, &
  161. & igrdij_recv
  162. INTEGER, DIMENSION(kptsi,kptsj,kobs) :: &
  163. & iorder, &
  164. & iproc
  165. INTEGER :: nplocal(jpnij)
  166. INTEGER :: npglobal(jpnij)
  167. INTEGER :: ji
  168. INTEGER :: jj
  169. INTEGER :: jk
  170. INTEGER :: jp
  171. INTEGER :: jobs
  172. INTEGER :: it
  173. INTEGER :: itot
  174. INTEGER :: ii
  175. INTEGER :: ij
  176. ! Check valid points
  177. IF ( ( MAXVAL(kgrdi) > jpiglo ) .OR. ( MINVAL(kgrdi) < 1 ) .OR. &
  178. & ( MAXVAL(kgrdj) > jpjglo ) .OR. ( MINVAL(kgrdj) < 1 ) ) THEN
  179. CALL ctl_stop( 'Error in obs_int_comm_3d_global', &
  180. & 'Point outside global domain' )
  181. ENDIF
  182. ! Count number of points on each processors
  183. nplocal(:) = 0
  184. IF (PRESENT(kproc)) THEN
  185. iproc(:,:,:) = kproc(:,:,:)
  186. DO jobs = 1, kobs
  187. DO jj = 1, kptsj
  188. DO ji = 1, kptsi
  189. nplocal(iproc(ji,jj,jobs)) = nplocal(iproc(ji,jj,jobs)) + 1
  190. END DO
  191. END DO
  192. END DO
  193. ELSE
  194. DO jobs = 1, kobs
  195. DO jj = 1, kptsj
  196. DO ji = 1, kptsi
  197. iproc(ji,jj,jobs) = mppmap(kgrdi(ji,jj,jobs),&
  198. & kgrdj(ji,jj,jobs))
  199. nplocal(iproc(ji,jj,jobs)) = nplocal(iproc(ji,jj,jobs)) + 1
  200. END DO
  201. END DO
  202. END DO
  203. ENDIF
  204. ! Send local number of points and receive points on current domain
  205. CALL mpp_alltoall_int( 1, nplocal, npglobal )
  206. ! Allocate message parsing workspace
  207. itot = SUM(npglobal)
  208. ALLOCATE( &
  209. & igrdij_send(kptsi*kptsj*kobs*2), &
  210. & igrdij_recv(itot*2), &
  211. & zsend(kpk,itot), &
  212. & zrecv(kpk,kptsi*kptsj*kobs) &
  213. & )
  214. ! Pack buffers for list of points
  215. it = 0
  216. DO jp = 1, jpnij
  217. DO jobs = 1, kobs
  218. DO jj = 1, kptsj
  219. DO ji = 1, kptsi
  220. IF ( iproc(ji,jj,jobs) == jp ) THEN
  221. it = it + 1
  222. iorder(ji,jj,jobs) = it
  223. igrdij_send(2*it-1) = kgrdi(ji,jj,jobs)
  224. igrdij_send(2*it ) = kgrdj(ji,jj,jobs)
  225. ENDIF
  226. END DO
  227. END DO
  228. END DO
  229. END DO
  230. ! Send and recieve buffers for list of points
  231. CALL mpp_alltoallv_int( igrdij_send, kptsi*kptsj*kobs*2, nplocal(:)*2, &
  232. & igrdij_recv, itot*2, npglobal(:)*2 )
  233. ! Pack interpolation data to be sent
  234. DO ji = 1, itot
  235. ii = mi1(igrdij_recv(2*ji-1))
  236. ij = mj1(igrdij_recv(2*ji))
  237. DO jk = 1, kpk
  238. zsend(jk,ji) = pval(ii,ij,jk)
  239. END DO
  240. END DO
  241. ! Re-adjust sizes
  242. nplocal(:) = kpk*nplocal(:)
  243. npglobal(:) = kpk*npglobal(:)
  244. ! Send and receive data for interpolation stencil
  245. CALL mpp_alltoallv_real( zsend, kpk*itot, npglobal, &
  246. & zrecv, kpk*kptsi*kptsj*kobs, nplocal )
  247. ! Copy the received data into output data structure
  248. DO jobs = 1, kobs
  249. DO jj = 1, kptsj
  250. DO ji = 1, kptsi
  251. it = iorder(ji,jj,jobs)
  252. DO jk = 1, kpk
  253. pgval(ji,jj,jk,jobs) = zrecv(jk,it)
  254. END DO
  255. END DO
  256. END DO
  257. END DO
  258. ! Deallocate message parsing workspace
  259. DEALLOCATE( &
  260. & igrdij_send, &
  261. & igrdij_recv, &
  262. & zsend, &
  263. & zrecv &
  264. & )
  265. END SUBROUTINE obs_int_comm_3d_global
  266. SUBROUTINE obs_int_comm_3d_local( kptsi, kptsj, kobs, kpk, kgrdi, kgrdj, &
  267. & pval, pgval )
  268. !!----------------------------------------------------------------------
  269. !! *** ROUTINE obs_int_comm_3d_global ***
  270. !!
  271. !! ** Purpose : Get 3D interpolation stencil (global version)
  272. !!
  273. !! ** Method : On-demand communication where each processor send its
  274. !! list of (i,j) of points to all processors and receive
  275. !! the corresponding values
  276. !!
  277. !! ** Action :
  278. !!
  279. !! History :
  280. !! ! 08-02 (K. Mogensen) Original code
  281. !!----------------------------------------------------------------------
  282. !! * Arguments
  283. INTEGER, INTENT(IN) :: kptsi ! Number of i horizontal points per stencil
  284. INTEGER, INTENT(IN) :: kptsj ! Number of j horizontal points per stencil
  285. INTEGER, INTENT(IN) :: kobs ! Local number of observations
  286. INTEGER, INTENT(IN) :: kpk ! Number of levels
  287. INTEGER, DIMENSION(kptsi,kptsj,kobs), INTENT(IN) :: &
  288. & kgrdi, & ! i,j indicies for each stencil
  289. & kgrdj
  290. REAL(KIND=wp), DIMENSION(jpi,jpj,kpk), INTENT(IN) ::&
  291. & pval ! Local 3D array to extract data from
  292. REAL(KIND=wp), DIMENSION(kptsi,kptsj,kpk,kobs), INTENT(OUT) ::&
  293. & pgval ! Stencil at each point
  294. !! * Local declarations
  295. INTEGER :: ji
  296. INTEGER :: jj
  297. INTEGER :: jk
  298. INTEGER :: jobs
  299. ! Check valid points
  300. IF ( ( MAXVAL(kgrdi) > jpi ) .OR. ( MINVAL(kgrdi) < 1 ) .OR. &
  301. & ( MAXVAL(kgrdj) > jpj ) .OR. ( MINVAL(kgrdj) < 1 ) ) THEN
  302. CALL ctl_stop( 'Error in obs_int_comm_3d_local', &
  303. & 'Point outside local domain' )
  304. ENDIF
  305. ! Copy local data
  306. DO jobs = 1, kobs
  307. DO jj = 1, kptsj
  308. DO ji = 1, kptsi
  309. DO jk = 1, kpk
  310. pgval(ji,jj,jk,jobs) = &
  311. & pval(kgrdi(ji,jj,jobs),kgrdj(ji,jj,jobs),jk)
  312. END DO
  313. END DO
  314. END DO
  315. END DO
  316. END SUBROUTINE obs_int_comm_3d_local
  317. END MODULE obs_inter_sup