obs_grd_bruteforce.h90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. SUBROUTINE obs_grd_bruteforce( kpi, kpj, kpiglo, kpjglo, &
  2. & kldi, klei, kldj, klej, &
  3. & kmyproc, ktotproc, &
  4. & pglam, pgphi, pmask, &
  5. & kobs, plam, pphi, kobsi, kobsj, &
  6. & kproc)
  7. !!----------------------------------------------------------------------
  8. !! *** ROUTINE obs_grd_bruteforce ***
  9. !!
  10. !! ** Purpose : Search gridpoints to find the grid box containing
  11. !! the observations
  12. !!
  13. !! ** Method : Call to linquad
  14. !!
  15. !! ** Action : Return kproc holding the observation and kiobsi,kobsj
  16. !! valid on kproc=kmyproc processor only.
  17. !!
  18. !! History :
  19. !! ! 2001-11 (N. Daget, A. Weaver)
  20. !! ! 2006-03 (A. Weaver) NEMOVAR migration.
  21. !! ! 2006-05 (K. Mogensen) Moved to to separate routine.
  22. !! ! 2007-10 (A. Vidard) Bug fix in wrap around checks; cleanup
  23. !!----------------------------------------------------------------------
  24. !! * Arguments
  25. INTEGER, INTENT(IN) :: kpi ! Number of local longitudes
  26. INTEGER, INTENT(IN) :: kpj ! Number of local latitudes
  27. INTEGER, INTENT(IN) :: kpiglo ! Number of global longitudes
  28. INTEGER, INTENT(IN) :: kpjglo ! Number of global latitudes
  29. INTEGER, INTENT(IN) :: kldi ! Start of inner domain in i
  30. INTEGER, INTENT(IN) :: klei ! End of inner domain in i
  31. INTEGER, INTENT(IN) :: kldj ! Start of inner domain in j
  32. INTEGER, INTENT(IN) :: klej ! End of inner domain in j
  33. INTEGER, INTENT(IN) :: kmyproc ! Processor number for MPP
  34. INTEGER, INTENT(IN) :: ktotproc ! Total number of processors
  35. REAL(KIND=wp), DIMENSION(kpi,kpj), INTENT(IN) :: &
  36. & pglam, & ! Grid point longitude
  37. & pgphi, & ! Grid point latitude
  38. & pmask ! Grid point mask
  39. INTEGER,INTENT(IN) :: kobs ! Size of the observation arrays
  40. REAL(KIND=wp), DIMENSION(kobs), INTENT(IN) :: &
  41. & plam, & ! Longitude of obsrvations
  42. & pphi ! Latitude of observations
  43. INTEGER, DIMENSION(kobs), INTENT(OUT) :: &
  44. & kobsi, & ! I-index of observations
  45. & kobsj, & ! J-index of observations
  46. & kproc ! Processor number of observations
  47. !! * Local declarations
  48. REAL(wp), DIMENSION(:), ALLOCATABLE :: &
  49. & zplam, zpphi
  50. REAL(wp) :: zlammax
  51. REAL(wp) :: zlam
  52. INTEGER :: ji
  53. INTEGER :: jj
  54. INTEGER :: jk
  55. INTEGER :: jo
  56. INTEGER :: jlon
  57. INTEGER :: jlat
  58. INTEGER :: joffset
  59. INTEGER :: jostride
  60. REAL(KIND=wp), DIMENSION(:,:), ALLOCATABLE :: &
  61. & zlamg, &
  62. & zphig, &
  63. & zmskg, &
  64. & zphitmax,&
  65. & zphitmin,&
  66. & zlamtmax,&
  67. & zlamtmin
  68. LOGICAL, DIMENSION(:,:), ALLOCATABLE :: &
  69. & llinvalidcell
  70. REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: &
  71. & zlamtm, &
  72. & zphitm
  73. !-----------------------------------------------------------------------
  74. ! Define grid setup for grid search
  75. !-----------------------------------------------------------------------
  76. IF (ln_grid_global) THEN
  77. jlon = kpiglo
  78. jlat = kpjglo
  79. joffset = kmyproc
  80. jostride = ktotproc
  81. ELSE
  82. jlon = kpi
  83. jlat = kpj
  84. joffset = 0
  85. jostride = 1
  86. ENDIF
  87. !-----------------------------------------------------------------------
  88. ! Set up data for grid search
  89. !-----------------------------------------------------------------------
  90. ALLOCATE( &
  91. & zlamg(jlon,jlat), &
  92. & zphig(jlon,jlat), &
  93. & zmskg(jlon,jlat), &
  94. & zphitmax(jlon-1,jlat-1), &
  95. & zphitmin(jlon-1,jlat-1), &
  96. & zlamtmax(jlon-1,jlat-1), &
  97. & zlamtmin(jlon-1,jlat-1), &
  98. & llinvalidcell(jlon-1,jlat-1), &
  99. & zlamtm(4,jlon-1,jlat-1), &
  100. & zphitm(4,jlon-1,jlat-1) &
  101. & )
  102. !-----------------------------------------------------------------------
  103. ! Copy data to local arrays
  104. !-----------------------------------------------------------------------
  105. IF (ln_grid_global) THEN
  106. zlamg(:,:) = -1.e+10
  107. zphig(:,:) = -1.e+10
  108. zmskg(:,:) = -1.e+10
  109. DO jj = kldj, klej
  110. DO ji = kldi, klei
  111. zlamg(mig(ji),mjg(jj)) = pglam(ji,jj)
  112. zphig(mig(ji),mjg(jj)) = pgphi(ji,jj)
  113. zmskg(mig(ji),mjg(jj)) = pmask(ji,jj)
  114. END DO
  115. END DO
  116. CALL mpp_global_max( zlamg )
  117. CALL mpp_global_max( zphig )
  118. CALL mpp_global_max( zmskg )
  119. ELSE
  120. DO jj = 1, jlat
  121. DO ji = 1, jlon
  122. zlamg(ji,jj) = pglam(ji,jj)
  123. zphig(ji,jj) = pgphi(ji,jj)
  124. zmskg(ji,jj) = pmask(ji,jj)
  125. END DO
  126. END DO
  127. ENDIF
  128. !-----------------------------------------------------------------------
  129. ! Copy longitudes and latitudes
  130. !-----------------------------------------------------------------------
  131. ALLOCATE( &
  132. & zplam(kobs), &
  133. & zpphi(kobs) &
  134. & )
  135. DO jo = 1, kobs
  136. zplam(jo) = plam(jo)
  137. zpphi(jo) = pphi(jo)
  138. END DO
  139. !-----------------------------------------------------------------------
  140. ! Set default values for output
  141. !-----------------------------------------------------------------------
  142. kproc(:) = -1
  143. kobsi(:) = -1
  144. kobsj(:) = -1
  145. !-----------------------------------------------------------------------
  146. ! Copy grid positions to temporary arrays and renormalize to 0 to 360.
  147. !-----------------------------------------------------------------------
  148. DO jj = 1, jlat-1
  149. DO ji = 1, jlon-1
  150. zlamtm(1,ji,jj) = zlamg(ji ,jj )
  151. zphitm(1,ji,jj) = zphig(ji ,jj )
  152. zlamtm(2,ji,jj) = zlamg(ji+1,jj )
  153. zphitm(2,ji,jj) = zphig(ji+1,jj )
  154. zlamtm(3,ji,jj) = zlamg(ji+1,jj+1)
  155. zphitm(3,ji,jj) = zphig(ji+1,jj+1)
  156. zlamtm(4,ji,jj) = zlamg(ji ,jj+1)
  157. zphitm(4,ji,jj) = zphig(ji ,jj+1)
  158. END DO
  159. END DO
  160. WHERE ( zlamtm(:,:,:) < 0.0_wp )
  161. zlamtm(:,:,:) = zlamtm(:,:,:) + 360.0_wp
  162. END WHERE
  163. WHERE ( zlamtm(:,:,:) > 360.0_wp )
  164. zlamtm(:,:,:) = zlamtm(:,:,:) - 360.0_wp
  165. END WHERE
  166. !-----------------------------------------------------------------------
  167. ! Handle case of the wraparound; beware, not working with orca180
  168. !-----------------------------------------------------------------------
  169. DO jj = 1, jlat-1
  170. DO ji = 1, jlon-1
  171. zlammax = MAXVAL( zlamtm(:,ji,jj) )
  172. WHERE (zlammax - zlamtm(:, ji, jj) > 180 ) &
  173. & zlamtm(:,ji,jj) = zlamtm(:,ji,jj) + 360._wp
  174. zphitmax(ji,jj) = MAXVAL(zphitm(:,ji,jj))
  175. zphitmin(ji,jj) = MINVAL(zphitm(:,ji,jj))
  176. zlamtmax(ji,jj) = MAXVAL(zlamtm(:,ji,jj))
  177. zlamtmin(ji,jj) = MINVAL(zlamtm(:,ji,jj))
  178. END DO
  179. END DO
  180. !-----------------------------------------------------------------------
  181. ! Search for boxes with only land points mark them invalid
  182. !-----------------------------------------------------------------------
  183. llinvalidcell(:,:) = .FALSE.
  184. DO jj = 1, jlat-1
  185. DO ji = 1, jlon-1
  186. llinvalidcell(ji,jj) = &
  187. & zmskg(ji ,jj ) == 0.0_wp .AND. &
  188. & zmskg(ji+1,jj ) == 0.0_wp .AND. &
  189. & zmskg(ji+1,jj+1) == 0.0_wp .AND. &
  190. & zmskg(ji ,jj+1) == 0.0_wp
  191. END DO
  192. END DO
  193. !------------------------------------------------------------------------
  194. ! Master loop for grid search
  195. !------------------------------------------------------------------------
  196. DO jo = 1+joffset, kobs, jostride
  197. !---------------------------------------------------------------------
  198. ! Ensure that all observation longtiudes are between 0 and 360
  199. !---------------------------------------------------------------------
  200. IF ( zplam(jo) < 0.0_wp ) zplam(jo) = zplam(jo) + 360.0_wp
  201. IF ( zplam(jo) > 360.0_wp ) zplam(jo) = zplam(jo) - 360.0_wp
  202. !---------------------------------------------------------------------
  203. ! Find observations which are on within 1e-6 of a grid point
  204. !---------------------------------------------------------------------
  205. gridloop: DO jj = 1, jlat-1
  206. DO ji = 1, jlon-1
  207. IF ( ABS( zphig(ji,jj) - zpphi(jo) ) < 1e-6 ) THEN
  208. zlam = zlamg(ji,jj)
  209. IF ( zlam < 0.0_wp ) zlam = zlam + 360.0_wp
  210. IF ( zlam > 360.0_wp ) zlam = zlam - 360.0_wp
  211. IF ( ABS( zlam - zplam(jo) ) < 1e-6 ) THEN
  212. IF ( llinvalidcell(ji,jj) ) THEN
  213. kproc(jo) = kmyproc + 1000000
  214. kobsi(jo) = ji + 1
  215. kobsj(jo) = jj + 1
  216. CYCLE
  217. ELSE
  218. kproc(jo) = kmyproc
  219. kobsi(jo) = ji + 1
  220. kobsj(jo) = jj + 1
  221. EXIT gridloop
  222. ENDIF
  223. ENDIF
  224. ENDIF
  225. END DO
  226. END DO gridloop
  227. !---------------------------------------------------------------------
  228. ! Ensure that all observation longtiudes are between -180 and 180
  229. !---------------------------------------------------------------------
  230. IF ( zplam(jo) > 180 ) zplam(jo) = zplam(jo) - 360.0_wp
  231. !---------------------------------------------------------------------
  232. ! Do coordinate search using brute force.
  233. ! - For land points kproc is set to number of the processor + 1000000
  234. ! and we continue the search.
  235. ! - For ocean points kproc is set to the number of the processor
  236. ! and we stop the search.
  237. !---------------------------------------------------------------------
  238. IF ( kproc(jo) == -1 ) THEN
  239. ! Normal case
  240. gridpoints : DO jj = 1, jlat-1
  241. DO ji = 1, jlon-1
  242. IF ( ( zplam(jo) > zlamtmax(ji,jj) ) .OR. &
  243. & ( zplam(jo) < zlamtmin(ji,jj) ) ) CYCLE
  244. IF ( ABS( zpphi(jo) ) < 85 ) THEN
  245. IF ( ( zpphi(jo) > zphitmax(ji,jj) ) .OR. &
  246. & ( zpphi(jo) < zphitmin(ji,jj) ) ) CYCLE
  247. ENDIF
  248. IF ( linquad( zplam(jo), zpphi(jo), &
  249. & zlamtm(:,ji,jj), zphitm(:,ji,jj) ) ) THEN
  250. IF ( llinvalidcell(ji,jj) ) THEN
  251. kproc(jo) = kmyproc + 1000000
  252. kobsi(jo) = ji + 1
  253. kobsj(jo) = jj + 1
  254. CYCLE
  255. ELSE
  256. kproc(jo) = kmyproc
  257. kobsi(jo) = ji + 1
  258. kobsj(jo) = jj + 1
  259. EXIT gridpoints
  260. ENDIF
  261. ENDIF
  262. END DO
  263. END DO gridpoints
  264. ENDIF
  265. ! In case of failure retry for obs. longtiude + 360.
  266. IF ( kproc(jo) == -1 ) THEN
  267. gridpoints_greenwich : DO jj = 1, jlat-1
  268. DO ji = 1, jlon-1
  269. IF ( ( zplam(jo)+360.0_wp > zlamtmax(ji,jj) ) .OR. &
  270. & ( zplam(jo)+360.0_wp < zlamtmin(ji,jj) ) ) CYCLE
  271. IF ( ABS( zpphi(jo) ) < 85 ) THEN
  272. IF ( ( zpphi(jo) > zphitmax(ji,jj) ) .OR. &
  273. & ( zpphi(jo) < zphitmin(ji,jj) ) ) CYCLE
  274. ENDIF
  275. IF ( linquad( zplam(jo)+360.0_wp, zpphi(jo), &
  276. & zlamtm(:,ji,jj), zphitm(:,ji,jj) ) ) THEN
  277. IF ( llinvalidcell(ji,jj) ) THEN
  278. kproc(jo) = kmyproc + 1000000
  279. kobsi(jo) = ji + 1
  280. kobsj(jo) = jj + 1
  281. CYCLE
  282. ELSE
  283. kproc(jo) = kmyproc
  284. kobsi(jo) = ji + 1
  285. kobsj(jo) = jj + 1
  286. EXIT gridpoints_greenwich
  287. ENDIF
  288. ENDIF
  289. END DO
  290. END DO gridpoints_greenwich
  291. ENDIF
  292. END DO
  293. !----------------------------------------------------------------------
  294. ! Synchronize kproc on all processors
  295. !----------------------------------------------------------------------
  296. IF ( ln_grid_global ) THEN
  297. CALL obs_mpp_max_integer( kproc, kobs )
  298. CALL obs_mpp_max_integer( kobsi, kobs )
  299. CALL obs_mpp_max_integer( kobsj, kobs )
  300. ELSE
  301. CALL obs_mpp_find_obs_proc( kproc, kobsi, kobsj, kobs )
  302. ENDIF
  303. WHERE( kproc(:) >= 1000000 )
  304. kproc(:) = kproc(:) - 1000000
  305. END WHERE
  306. DEALLOCATE( &
  307. & zlamg, &
  308. & zphig, &
  309. & zmskg, &
  310. & zphitmax, &
  311. & zphitmin, &
  312. & zlamtmax, &
  313. & zlamtmin, &
  314. & llinvalidcell, &
  315. & zlamtm, &
  316. & zphitm, &
  317. & zplam, &
  318. & zpphi &
  319. & )
  320. END SUBROUTINE obs_grd_bruteforce