agrif_gridsearch.f90 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. !
  2. MODULE agrif_gridsearch
  3. !
  4. USE agrif_modutil
  5. !
  6. !************************************************************************
  7. ! *
  8. ! MODULE AGRIF_GRIDSEARCH *
  9. ! *
  10. !************************************************************************
  11. !
  12. !-----------------------------------------------------------------------
  13. IMPLICIT NONE
  14. !-----------------------------------------------------------------------
  15. ! variables that describe each grid
  16. !-----------------------------------------------------------------------
  17. !
  18. ! integer :: grid1_size,grid2_size,grid1_rank, grid2_rank
  19. ! integer, dimension(:), pointer :: grid1_dims, grid2_dims
  20. ! logical, dimension(:), pointer :: grid1_mask,grid2_mask
  21. ! real*8,dimension(:),pointer :: grid1_center_lat,grid1_center_lon,grid2_center_lat,grid2_center_lon
  22. !
  23. ! real*8,dimension(:,:), pointer :: grid1_bound_box,grid2_bound_box
  24. ! integer, parameter :: num_srch_bins = 90
  25. ! integer,dimension(:,:),pointer :: bin_addr1,bin_addr2
  26. ! real*8, dimension(:,:),pointer :: bin_lats,bin_lons
  27. REAL*8, PARAMETER :: zero = 0.0, &
  28. one = 1.0, &
  29. two = 2.0, &
  30. three = 3.0, &
  31. four = 4.0, &
  32. five = 5.0, &
  33. half = 0.5, &
  34. quart = 0.25, &
  35. bignum = 1.e+20, &
  36. tiny = 1.e-14, &
  37. pi = 3.14159265359, &
  38. pi2 = two*pi, &
  39. pih = half*pi
  40. !
  41. REAL*8, PARAMETER :: deg2rad = pi/180.
  42. !
  43. !
  44. CONTAINS
  45. !
  46. !
  47. SUBROUTINE get_detected_pts(grid1_lat,grid2_lat,grid1_lon,grid2_lon,maskC,maskF,detected_pts)
  48. !
  49. !-----------------------------------------------------------------------
  50. !this routine makes any necessary changes (e.g. for 0,2pi longitude range)
  51. !-----------------------------------------------------------------------
  52. !
  53. REAL*8,DIMENSION(:,:),POINTER :: grid1_lat,grid2_lat,grid1_lon,grid2_lon
  54. LOGICAL, POINTER, DIMENSION(:,:) :: masksrc,maskdst
  55. LOGICAL, DIMENSION(:,:) :: detected_pts
  56. REAL*8,DIMENSION(:,:) :: maskF,maskC
  57. LOGICAL,POINTER,DIMENSION(:) :: detected_pts_1D
  58. REAL*8 :: plat,plon
  59. INTEGER :: lastsrc_add
  60. INTEGER, DIMENSION(4) :: src_add
  61. REAL*8,DIMENSION(4) :: src_lats,src_lons
  62. INTEGER :: grid1_size,grid2_size,grid1_rank, grid2_rank
  63. INTEGER, DIMENSION(:), POINTER :: grid1_dims, grid2_dims
  64. LOGICAL, DIMENSION(:), POINTER :: grid1_mask,grid2_mask
  65. REAL*8,DIMENSION(:),POINTER :: grid1_center_lat,grid1_center_lon,grid2_center_lat,grid2_center_lon
  66. REAL*8,DIMENSION(:,:), POINTER :: grid1_bound_box,grid2_bound_box
  67. ! integer, parameter :: num_srch_bins = 90
  68. INTEGER,DIMENSION(:,:),POINTER :: bin_addr1,bin_addr2
  69. REAL*8, DIMENSION(:,:),POINTER :: bin_lats,bin_lons
  70. REAL*8, PARAMETER :: zero = 0.0, &
  71. one = 1.0, &
  72. two = 2.0, &
  73. three = 3.0, &
  74. four = 4.0, &
  75. five = 5.0, &
  76. half = 0.5, &
  77. quart = 0.25, &
  78. bignum = 1.e+20, &
  79. tiny = 1.e-14, &
  80. pi = 3.14159265359, &
  81. pi2 = two*pi, &
  82. pih = half*pi
  83. REAL*8, PARAMETER :: deg2rad = pi/180.
  84. !
  85. !-----------------------------------------------------------------------
  86. ! local variables
  87. !-----------------------------------------------------------------------
  88. !
  89. INTEGER :: n,nele,i,j,ip1,jp1,n_add,e_add,ne_add,nx,ny
  90. INTEGER :: xpos,ypos,dst_add
  91. !
  92. ! integer mask
  93. !
  94. INTEGER, DIMENSION(:), POINTER :: imask
  95. !
  96. ! lat/lon intervals for search bins
  97. !
  98. REAL*8 :: dlat,dlon
  99. !
  100. ! temps for computing bounding boxes
  101. !
  102. REAL*8, DIMENSION(4) :: tmp_lats, tmp_lons
  103. !
  104. ! write(*,*)'proceed to Bilinear interpolation ...'
  105. !
  106. ALLOCATE(grid1_dims(2),grid2_dims(2))
  107. !
  108. grid1_dims(1) = SIZE(grid1_lat,2)
  109. grid1_dims(2) = SIZE(grid1_lat,1)
  110. grid2_dims(1) = SIZE(grid2_lat,2)
  111. grid2_dims(2) = SIZE(grid2_lat,1)
  112. grid1_size = SIZE(grid1_lat,2) * SIZE(grid1_lat,1)
  113. grid2_size = SIZE(grid2_lat,2) * SIZE(grid2_lat,1)
  114. !
  115. !-----------------------------------------------------------------------
  116. ! allocate grid coordinates/masks and read data
  117. !-----------------------------------------------------------------------
  118. !
  119. ALLOCATE( grid1_bound_box (4,grid1_size),grid2_bound_box (4,grid2_size))
  120. ALLOCATE(detected_pts_1D(grid1_size))
  121. ALLOCATE(masksrc(SIZE(maskC,1),SIZE(maskC,2)))
  122. ALLOCATE(maskdst(SIZE(maskF,1),SIZE(maskF,2)))
  123. !
  124. WHERE(maskC == 1.)
  125. masksrc= .TRUE.
  126. ELSEWHERE
  127. masksrc= .FALSE.
  128. END WHERE
  129. !
  130. WHERE(maskF == 1.)
  131. maskdst= .TRUE.
  132. ELSEWHERE
  133. maskdst= .FALSE.
  134. END WHERE
  135. !
  136. !
  137. !
  138. ! 2D array -> 1D array
  139. !
  140. ALLOCATE(grid1_center_lat(SIZE(grid1_lat,1)*SIZE(grid1_lat,2)))
  141. CALL tab2Dto1D(grid1_lat,grid1_center_lat)
  142. ALLOCATE(grid1_center_lon(SIZE(grid1_lon,1)*SIZE(grid1_lon,2)))
  143. CALL tab2Dto1D(grid1_lon,grid1_center_lon)
  144. ALLOCATE(grid2_center_lat(SIZE(grid2_lat,1)*SIZE(grid2_lat,2)))
  145. CALL tab2Dto1D(grid2_lat,grid2_center_lat)
  146. ALLOCATE(grid2_center_lon(SIZE(grid2_lon,1)*SIZE(grid2_lon,2)))
  147. CALL tab2Dto1D(grid2_lon,grid2_center_lon)
  148. ALLOCATE(grid1_mask(SIZE(grid1_lat,1)*SIZE(grid1_lat,2)))
  149. CALL logtab2Dto1D(masksrc,grid1_mask)
  150. ALLOCATE(grid2_mask(SIZE(grid2_lat,1)*SIZE(grid2_lat,2)))
  151. CALL logtab2Dto1D(maskdst,grid2_mask)
  152. !
  153. !
  154. ! degrees to radian
  155. !
  156. grid1_center_lat = grid1_center_lat*deg2rad
  157. grid1_center_lon = grid1_center_lon*deg2rad
  158. grid2_center_lat = grid2_center_lat*deg2rad
  159. grid2_center_lon = grid2_center_lon*deg2rad
  160. !-----------------------------------------------------------------------
  161. ! convert longitudes to 0,2pi interval
  162. !-----------------------------------------------------------------------
  163. WHERE (grid1_center_lon .GT. pi2) grid1_center_lon = &
  164. grid1_center_lon - pi2
  165. WHERE (grid1_center_lon .LT. zero) grid1_center_lon = &
  166. grid1_center_lon + pi2
  167. WHERE (grid2_center_lon .GT. pi2) grid2_center_lon = &
  168. grid2_center_lon - pi2
  169. WHERE (grid2_center_lon .LT. zero) grid2_center_lon = &
  170. grid2_center_lon + pi2
  171. !-----------------------------------------------------------------------
  172. !
  173. ! make sure input latitude range is within the machine values
  174. ! for +/- pi/2
  175. !
  176. !-----------------------------------------------------------------------
  177. WHERE (grid1_center_lat > pih) grid1_center_lat = pih
  178. WHERE (grid1_center_lat < -pih) grid1_center_lat = -pih
  179. WHERE (grid2_center_lat > pih) grid2_center_lat = pih
  180. WHERE (grid2_center_lat < -pih) grid2_center_lat = -pih
  181. !-----------------------------------------------------------------------
  182. !
  183. ! compute bounding boxes for restricting future grid searches
  184. !
  185. !-----------------------------------------------------------------------
  186. !
  187. nx = grid1_dims(1)
  188. ny = grid1_dims(2)
  189. DO n=1,grid1_size
  190. !*** find N,S and NE points to this grid point
  191. j = (n - 1)/nx +1
  192. i = n - (j-1)*nx
  193. IF (i < nx) THEN
  194. ip1 = i + 1
  195. ELSE
  196. !*** assume cyclic
  197. ip1 = 1
  198. !*** but if it is not, correct
  199. e_add = (j - 1)*nx + ip1
  200. IF (ABS(grid1_center_lat(e_add) - &
  201. grid1_center_lat(n )) > pih) THEN
  202. ip1 = i
  203. ENDIF
  204. ip1=nx
  205. ENDIF
  206. IF (j < ny) THEN
  207. jp1 = j+1
  208. ELSE
  209. !*** assume cyclic
  210. jp1 = 1
  211. !*** but if it is not, correct
  212. n_add = (jp1 - 1)*nx + i
  213. IF (ABS(grid1_center_lat(n_add) - &
  214. grid1_center_lat(n )) > pih) THEN
  215. jp1 = j
  216. ENDIF
  217. jp1=ny
  218. ENDIF
  219. n_add = (jp1 - 1)*nx + i
  220. e_add = (j - 1)*nx + ip1
  221. ne_add = (jp1 - 1)*nx + ip1
  222. !*** find N,S and NE lat/lon coords and check bounding box
  223. tmp_lats(1) = grid1_center_lat(n)
  224. tmp_lats(2) = grid1_center_lat(e_add)
  225. tmp_lats(3) = grid1_center_lat(ne_add)
  226. tmp_lats(4) = grid1_center_lat(n_add)
  227. tmp_lons(1) = grid1_center_lon(n)
  228. tmp_lons(2) = grid1_center_lon(e_add)
  229. tmp_lons(3) = grid1_center_lon(ne_add)
  230. tmp_lons(4) = grid1_center_lon(n_add)
  231. grid1_bound_box(1,n) = MINVAL(tmp_lats)
  232. grid1_bound_box(2,n) = MAXVAL(tmp_lats)
  233. grid1_bound_box(3,n) = MINVAL(tmp_lons)
  234. grid1_bound_box(4,n) = MAXVAL(tmp_lons)
  235. END DO
  236. nx = grid2_dims(1)
  237. ny = grid2_dims(2)
  238. DO n=1,grid2_size
  239. !*** find N,S and NE points to this grid point
  240. j = (n - 1)/nx +1
  241. i = n - (j-1)*nx
  242. IF (i < nx) THEN
  243. ip1 = i + 1
  244. ELSE
  245. !*** assume cyclic
  246. ip1 = 1
  247. !*** but if it is not, correct
  248. e_add = (j - 1)*nx + ip1
  249. IF (ABS(grid2_center_lat(e_add) - &
  250. grid2_center_lat(n )) > pih) THEN
  251. ip1 = i
  252. ENDIF
  253. ENDIF
  254. IF (j < ny) THEN
  255. jp1 = j+1
  256. ELSE
  257. !*** assume cyclic
  258. jp1 = 1
  259. !*** but if it is not, correct
  260. n_add = (jp1 - 1)*nx + i
  261. IF (ABS(grid2_center_lat(n_add) - &
  262. grid2_center_lat(n )) > pih) THEN
  263. jp1 = j
  264. ENDIF
  265. ENDIF
  266. n_add = (jp1 - 1)*nx + i
  267. e_add = (j - 1)*nx + ip1
  268. ne_add = (jp1 - 1)*nx + ip1
  269. !*** find N,S and NE lat/lon coords and check bounding box
  270. tmp_lats(1) = grid2_center_lat(n)
  271. tmp_lats(2) = grid2_center_lat(e_add)
  272. tmp_lats(3) = grid2_center_lat(ne_add)
  273. tmp_lats(4) = grid2_center_lat(n_add)
  274. tmp_lons(1) = grid2_center_lon(n)
  275. tmp_lons(2) = grid2_center_lon(e_add)
  276. tmp_lons(3) = grid2_center_lon(ne_add)
  277. tmp_lons(4) = grid2_center_lon(n_add)
  278. grid2_bound_box(1,n) = MINVAL(tmp_lats)
  279. grid2_bound_box(2,n) = MAXVAL(tmp_lats)
  280. grid2_bound_box(3,n) = MINVAL(tmp_lons)
  281. grid2_bound_box(4,n) = MAXVAL(tmp_lons)
  282. END DO
  283. !
  284. !
  285. !
  286. WHERE (ABS(grid1_bound_box(4,:) - grid1_bound_box(3,:)) > pi)
  287. grid1_bound_box(3,:) = zero
  288. grid1_bound_box(4,:) = pi2
  289. END WHERE
  290. WHERE (ABS(grid2_bound_box(4,:) - grid2_bound_box(3,:)) > pi)
  291. grid2_bound_box(3,:) = zero
  292. grid2_bound_box(4,:) = pi2
  293. END WHERE
  294. !***
  295. !*** try to check for cells that overlap poles
  296. !***
  297. WHERE (grid1_center_lat > grid1_bound_box(2,:)) &
  298. grid1_bound_box(2,:) = pih
  299. WHERE (grid1_center_lat < grid1_bound_box(1,:)) &
  300. grid1_bound_box(1,:) = -pih
  301. WHERE (grid2_center_lat > grid2_bound_box(2,:)) &
  302. grid2_bound_box(2,:) = pih
  303. WHERE (grid2_center_lat < grid2_bound_box(1,:)) &
  304. grid2_bound_box(1,:) = -pih
  305. !-----------------------------------------------------------------------
  306. ! set up and assign address ranges to search bins in order to
  307. ! further restrict later searches
  308. !-----------------------------------------------------------------------
  309. ALLOCATE(bin_addr1(2,90))
  310. ALLOCATE(bin_addr2(2,90))
  311. ALLOCATE(bin_lats (2,90))
  312. ALLOCATE(bin_lons (2,90))
  313. dlat = pi/90
  314. DO n=1,90
  315. bin_lats(1,n) = (n-1)*dlat - pih
  316. bin_lats(2,n) = n*dlat - pih
  317. bin_lons(1,n) = zero
  318. bin_lons(2,n) = pi2
  319. bin_addr1(1,n) = grid1_size + 1
  320. bin_addr1(2,n) = 0
  321. bin_addr2(1,n) = grid2_size + 1
  322. bin_addr2(2,n) = 0
  323. END DO
  324. DO nele=1,grid1_size
  325. DO n=1,90
  326. IF (grid1_bound_box(1,nele) <= bin_lats(2,n) .AND. &
  327. grid1_bound_box(2,nele) >= bin_lats(1,n)) THEN
  328. bin_addr1(1,n) = MIN(nele,bin_addr1(1,n))
  329. bin_addr1(2,n) = MAX(nele,bin_addr1(2,n))
  330. ENDIF
  331. END DO
  332. END DO
  333. DO nele=1,grid2_size
  334. DO n=1,90
  335. IF (grid2_bound_box(1,nele) <= bin_lats(2,n) .AND. &
  336. grid2_bound_box(2,nele) >= bin_lats(1,n)) THEN
  337. bin_addr2(1,n) = MIN(nele,bin_addr2(1,n))
  338. bin_addr2(2,n) = MAX(nele,bin_addr2(2,n))
  339. ENDIF
  340. END DO
  341. END DO
  342. !
  343. ! Call init_remap_vars
  344. !
  345. lastsrc_add=1
  346. detected_pts_1D = .FALSE.
  347. !
  348. DO dst_add = 1, grid2_size
  349. !
  350. plat = grid2_center_lat(dst_add)
  351. plon = grid2_center_lon(dst_add)
  352. !***
  353. !*** find nearest square of grid points on source grid
  354. !***
  355. CALL grid_search_bilin(bin_lons,bin_lats,src_add, src_lats, src_lons, &
  356. plat, plon, grid1_dims, &
  357. grid1_center_lat, grid1_center_lon, &
  358. grid1_bound_box, bin_addr1, bin_addr2,lastsrc_add)
  359. !
  360. IF (src_add(1) > 0) THEN
  361. !
  362. IF(grid2_mask(dst_add)) THEN !mask true on destination grid
  363. DO n=1,4
  364. IF(.NOT. grid1_mask(src_add(n))) THEN
  365. detected_pts_1D(src_add(n)) = .TRUE.
  366. ENDIF
  367. END DO
  368. ENDIF
  369. ENDIF
  370. END DO
  371. !
  372. !
  373. CALL logtab1Dto2D(detected_pts_1D,detected_pts,SIZE(detected_pts,2),SIZE(detected_pts,1))
  374. !
  375. DEALLOCATE(detected_pts_1D,grid1_bound_box,grid2_bound_box)
  376. DEALLOCATE(grid1_center_lon,grid1_center_lat,grid2_center_lon,grid2_center_lat)
  377. DEALLOCATE(grid1_mask,grid2_mask,masksrc,maskdst)
  378. DEALLOCATE(bin_addr1,bin_addr2,bin_lats,bin_lons)
  379. DEALLOCATE(grid1_dims,grid2_dims)
  380. !
  381. !-----------------------------------------------------------------------
  382. END SUBROUTINE get_detected_pts
  383. !**********************************************************************
  384. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  385. !************************************************************************
  386. ! SUBROUTINE GRID_SEARCH_BILIN
  387. !************************************************************************
  388. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  389. !
  390. SUBROUTINE grid_search_bilin(bin_lons,bin_lats,src_add, src_lats, src_lons, &
  391. plat, plon, src_grid_dims, &
  392. src_center_lat, src_center_lon, &
  393. src_grid_bound_box, &
  394. src_bin_add, dst_bin_add,lastsrc_add)
  395. !-----------------------------------------------------------------------
  396. !
  397. ! this routine finds the location of the search point plat, plon
  398. ! in the source grid and returns the corners needed for a bilinear
  399. ! interpolation.
  400. !
  401. !-----------------------------------------------------------------------
  402. !-----------------------------------------------------------------------
  403. ! output variables
  404. !-----------------------------------------------------------------------
  405. !
  406. ! address of each corner point enclosing P
  407. !
  408. INTEGER,DIMENSION(4) :: src_add
  409. REAL*8,DIMENSION(4) :: src_lats,src_lons
  410. !
  411. !-----------------------------------------------------------------------
  412. ! input variables
  413. !-----------------------------------------------------------------------
  414. !
  415. ! latitude, longitude of the search point
  416. !
  417. REAL*8, DIMENSION(:,:) :: bin_lats,bin_lons
  418. REAL*8, INTENT(in) :: plat,plon
  419. !
  420. ! size of each src grid dimension
  421. !
  422. INTEGER, DIMENSION(2), INTENT(in) :: src_grid_dims
  423. !
  424. ! latitude, longitude of each src grid center
  425. !
  426. REAL*8, DIMENSION(:), INTENT(in) :: src_center_lat,src_center_lon
  427. !
  428. ! bound box for source grid
  429. !
  430. REAL*8, DIMENSION(:,:), INTENT(in) :: src_grid_bound_box
  431. !
  432. ! latitude bins for restricting searches
  433. !
  434. INTEGER, DIMENSION(:,:), INTENT(in) ::src_bin_add,dst_bin_add
  435. INTEGER,OPTIONAL :: lastsrc_add
  436. INTEGER :: loopsrc,l1,l2
  437. !
  438. !-----------------------------------------------------------------------
  439. ! local variables
  440. !-----------------------------------------------------------------------
  441. !
  442. INTEGER :: n,next_n,srch_add,nx, ny,min_add, max_add, &
  443. i, j, jp1, ip1, n_add, e_add, ne_add
  444. REAL*8 :: vec1_lat, vec1_lon,vec2_lat, vec2_lon, cross_product, &
  445. cross_product_last,coslat_dst, sinlat_dst, coslon_dst, &
  446. sinlon_dst,dist_min, distance
  447. !-----------------------------------------------------------------------
  448. ! restrict search first using bins
  449. !-----------------------------------------------------------------------
  450. src_add = 0
  451. min_add = SIZE(src_center_lat)
  452. max_add = 1
  453. DO n=1,90
  454. IF (plat >= bin_lats(1,n) .AND. plat <= bin_lats(2,n) .AND. &
  455. plon >= bin_lons(1,n) .AND. plon <= bin_lons(2,n)) THEN
  456. min_add = MIN(min_add, src_bin_add(1,n))
  457. max_add = MAX(max_add, src_bin_add(2,n))
  458. ENDIF
  459. END DO
  460. !-----------------------------------------------------------------------
  461. ! now perform a more detailed search
  462. !-----------------------------------------------------------------------
  463. nx = src_grid_dims(1)
  464. ny = src_grid_dims(2)
  465. loopsrc=0
  466. DO WHILE (loopsrc <= max_add)
  467. l1=MAX(min_add,lastsrc_add-loopsrc)
  468. l2=MIN(max_add,lastsrc_add+loopsrc)
  469. loopsrc = loopsrc+1
  470. srch_loop: DO srch_add = l1,l2,MAX(l2-l1,1)
  471. !*** first check bounding box
  472. IF (plat <= src_grid_bound_box(2,srch_add) .AND. &
  473. plat >= src_grid_bound_box(1,srch_add) .AND. &
  474. plon <= src_grid_bound_box(4,srch_add) .AND. &
  475. plon >= src_grid_bound_box(3,srch_add)) THEN
  476. !***
  477. !*** we are within bounding box so get really serious
  478. !***
  479. !*** determine neighbor addresses
  480. !
  481. j = (srch_add - 1)/nx +1
  482. i = srch_add - (j-1)*nx
  483. !
  484. IF (i < nx) THEN
  485. ip1 = i + 1
  486. ELSE
  487. ip1 = 1
  488. ENDIF
  489. !
  490. IF (j < ny) THEN
  491. jp1 = j+1
  492. ELSE
  493. jp1 = 1
  494. ENDIF
  495. !
  496. n_add = (jp1 - 1)*nx + i
  497. e_add = (j - 1)*nx + ip1
  498. ne_add = (jp1 - 1)*nx + ip1
  499. !
  500. src_lats(1) = src_center_lat(srch_add)
  501. src_lats(2) = src_center_lat(e_add)
  502. src_lats(3) = src_center_lat(ne_add)
  503. src_lats(4) = src_center_lat(n_add)
  504. !
  505. src_lons(1) = src_center_lon(srch_add)
  506. src_lons(2) = src_center_lon(e_add)
  507. src_lons(3) = src_center_lon(ne_add)
  508. src_lons(4) = src_center_lon(n_add)
  509. !
  510. !***
  511. !*** for consistency, we must make sure all lons are in
  512. !*** same 2pi interval
  513. !***
  514. !
  515. vec1_lon = src_lons(1) - plon
  516. IF (vec1_lon > pi) THEN
  517. src_lons(1) = src_lons(1) - pi2
  518. ELSE IF (vec1_lon < -pi) THEN
  519. src_lons(1) = src_lons(1) + pi2
  520. ENDIF
  521. DO n=2,4
  522. vec1_lon = src_lons(n) - src_lons(1)
  523. IF (vec1_lon > pi) THEN
  524. src_lons(n) = src_lons(n) - pi2
  525. ELSE IF (vec1_lon < -pi) THEN
  526. src_lons(n) = src_lons(n) + pi2
  527. ENDIF
  528. END DO
  529. !
  530. corner_loop: DO n=1,4
  531. next_n = MOD(n,4) + 1
  532. !***
  533. !*** here we take the cross product of the vector making
  534. !*** up each box side with the vector formed by the vertex
  535. !*** and search point. if all the cross products are
  536. !*** positive, the point is contained in the box.
  537. !***
  538. vec1_lat = src_lats(next_n) - src_lats(n)
  539. vec1_lon = src_lons(next_n) - src_lons(n)
  540. vec2_lat = plat - src_lats(n)
  541. vec2_lon = plon - src_lons(n)
  542. !***
  543. !*** check for 0,2pi crossings
  544. !***
  545. IF (vec1_lon > three*pih) THEN
  546. vec1_lon = vec1_lon - pi2
  547. ELSE IF (vec1_lon < -three*pih) THEN
  548. vec1_lon = vec1_lon + pi2
  549. ENDIF
  550. IF (vec2_lon > three*pih) THEN
  551. vec2_lon = vec2_lon - pi2
  552. ELSE IF (vec2_lon < -three*pih) THEN
  553. vec2_lon = vec2_lon + pi2
  554. ENDIF
  555. !
  556. cross_product = vec1_lon*vec2_lat - vec2_lon*vec1_lat
  557. !
  558. !***
  559. !*** if cross product is less than zero, this cell
  560. !*** doesn't work
  561. !***
  562. IF (n == 1) cross_product_last = cross_product
  563. IF (cross_product*cross_product_last < zero) &
  564. EXIT corner_loop
  565. cross_product_last = cross_product
  566. !
  567. END DO corner_loop
  568. !***
  569. !*** if cross products all same sign, we found the location
  570. !***
  571. IF (n > 4) THEN
  572. src_add(1) = srch_add
  573. src_add(2) = e_add
  574. src_add(3) = ne_add
  575. src_add(4) = n_add
  576. !
  577. lastsrc_add = srch_add
  578. RETURN
  579. ENDIF
  580. !***
  581. !*** otherwise move on to next cell
  582. !***
  583. ENDIF !bounding box check
  584. END DO srch_loop
  585. ENDDO
  586. !***
  587. !*** if no cell found, point is likely either in a box that
  588. !*** straddles either pole or is outside the grid. fall back
  589. !*** to a distance-weighted average of the four closest
  590. !*** points. go ahead and compute weights here, but store
  591. !*** in src_lats and return -add to prevent the parent
  592. !*** routine from computing bilinear weights
  593. !***
  594. !print *,'Could not find location for ',plat,plon
  595. !print *,'Using nearest-neighbor average for this point'
  596. !
  597. coslat_dst = COS(plat)
  598. sinlat_dst = SIN(plat)
  599. coslon_dst = COS(plon)
  600. sinlon_dst = SIN(plon)
  601. !
  602. dist_min = bignum
  603. src_lats = bignum
  604. DO srch_add = min_add,max_add
  605. distance = ACOS(coslat_dst*COS(src_center_lat(srch_add))* &
  606. (coslon_dst*COS(src_center_lon(srch_add)) + &
  607. sinlon_dst*SIN(src_center_lon(srch_add)))+ &
  608. sinlat_dst*SIN(src_center_lat(srch_add)))
  609. IF (distance < dist_min) THEN
  610. sort_loop: DO n=1,4
  611. IF (distance < src_lats(n)) THEN
  612. DO i=4,n+1,-1
  613. src_add (i) = src_add (i-1)
  614. src_lats(i) = src_lats(i-1)
  615. END DO
  616. src_add (n) = -srch_add
  617. src_lats(n) = distance
  618. dist_min = src_lats(4)
  619. EXIT sort_loop
  620. ENDIF
  621. END DO sort_loop
  622. ENDIF
  623. END DO
  624. !
  625. src_lons = one/(src_lats + tiny)
  626. distance = SUM(src_lons)
  627. src_lats = src_lons/distance
  628. !-----------------------------------------------------------------------
  629. END SUBROUTINE grid_search_bilin
  630. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  631. !************************************************************************
  632. ! SUBROUTINE INIT_REMAP_VARS
  633. !************************************************************************
  634. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  635. !
  636. ! subroutine init_remap_vars
  637. !
  638. !-----------------------------------------------------------------------
  639. !
  640. ! this routine initializes some variables and provides an initial
  641. ! allocation of arrays (fairly large so frequent resizing
  642. ! unnecessary).
  643. !
  644. !-----------------------------------------------------------------------
  645. !
  646. !-----------------------------------------------------------------------
  647. ! determine the number of weights
  648. !-----------------------------------------------------------------------
  649. ! num_wts = 1 ! bilinear interpolation
  650. !-----------------------------------------------------------------------
  651. ! initialize num_links and set max_links to four times the largest
  652. ! of the destination grid sizes initially (can be changed later).
  653. ! set a default resize increment to increase the size of link
  654. ! arrays if the number of links exceeds the initial size
  655. !!-----------------------------------------------------------------------
  656. !
  657. ! num_links_map1 = 0
  658. ! max_links_map1 = 4*grid2_size
  659. ! if (num_maps > 1) then
  660. ! num_links_map2 = 0
  661. ! max_links_map1 = max(4*grid1_size,4*grid2_size)
  662. ! max_links_map2 = max_links_map1
  663. ! endif
  664. !
  665. ! resize_increment = 0.1*max(grid1_size,grid2_size)
  666. !
  667. !-----------------------------------------------------------------------
  668. ! allocate address and weight arrays for mapping 1
  669. !-----------------------------------------------------------------------
  670. !
  671. ! allocate (grid1_add_map1(max_links_map1), &
  672. ! grid2_add_map1(max_links_map1), &
  673. ! wts_map1(num_wts, max_links_map1))
  674. !
  675. ! grid1_add_map1 = 0.
  676. ! grid2_add_map1 = 0.
  677. ! wts_map1 = 0.!
  678. !
  679. !!-----------------------------------------------------------------------
  680. !
  681. ! end subroutine init_remap_vars
  682. END MODULE agrif_gridsearch