remap_gauswgt.f 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. C****
  2. C ************************
  3. C * OASIS MODULE *
  4. C * ------------ *
  5. C ************************
  6. C****
  7. C***********************************************************************
  8. C This module belongs to the SCRIP library. It is a modified version
  9. C of SCRIP 1.4 remap_ditswgt.f in order to weight a neighbour by
  10. C exp[-1/2 * d^^2/sigma^^2] where d is the distance between the source
  11. C and the target points and sigma^^2=VAR*dm^^2, where dm is the
  12. C average distance between the source grid points and VAR is a value
  13. C given by the user.
  14. C
  15. C Additional Modifications:
  16. C - restrict types are written in capital letters
  17. C - bug line 429: bin_lons(3,n) instead of bin_lons(2,n)
  18. C
  19. C Modified by D. Declat, CERFACS 27.06.2002
  20. C***********************************************************************
  21. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  22. !
  23. ! this module contains necessary routines for performing an
  24. ! interpolation using a distance-weighted average of n nearest
  25. ! neighbors.
  26. !
  27. !-----------------------------------------------------------------------
  28. !
  29. ! CVS:$Id: remap_gauswgt.f 2826 2010-12-10 11:14:21Z valcke $
  30. !
  31. ! Copyright (c) 1997, 1998 the Regents of the University of
  32. ! California.
  33. !
  34. ! This software and ancillary information (herein called software)
  35. ! called SCRIP is made available under the terms described here.
  36. ! The software has been approved for release with associated
  37. ! LA-CC Number 98-45.
  38. !
  39. ! Unless otherwise indicated, this software has been authored
  40. ! by an employee or employees of the University of California,
  41. ! operator of the Los Alamos National Laboratory under Contract
  42. ! No. W-7405-ENG-36 with the U.S. Department of Energy. The U.S.
  43. ! Government has rights to use, reproduce, and distribute this
  44. ! software. The public may copy and use this software without
  45. ! charge, provided that this Notice and any statement of authorship
  46. ! are reproduced on all copies. Neither the Government nor the
  47. ! University makes any warranty, express or implied, or assumes
  48. ! any liability or responsibility for the use of this software.
  49. !
  50. ! If software is modified to produce derivative works, such modified
  51. ! software should be clearly marked, so as not to confuse it with
  52. ! the version available from Los Alamos National Laboratory.
  53. !
  54. !***********************************************************************
  55. module remap_gaussian_weight
  56. !-----------------------------------------------------------------------
  57. use kinds_mod ! defines common data types
  58. use constants ! defines common constants
  59. use grids ! module containing grid info
  60. use remap_vars ! module containing remap info
  61. USE mod_oasis_flush
  62. implicit none
  63. !-----------------------------------------------------------------------
  64. !
  65. ! module variables
  66. !
  67. !-----------------------------------------------------------------------
  68. real (kind=dbl_kind), dimension(:), allocatable, save ::
  69. & coslat, sinlat, ! cosine, sine of grid lats (for distance)
  70. & coslon, sinlon, ! cosine, sine of grid lons (for distance)
  71. & wgtstmp ! an array to hold the link weight
  72. !***********************************************************************
  73. contains
  74. !***********************************************************************
  75. subroutine remap_gauswgt (lextrapdone, num_neighbors, rl_varmul)
  76. !-----------------------------------------------------------------------
  77. !
  78. ! this routine computes the inverse-distance weights for a
  79. ! nearest-neighbor interpolation.
  80. !
  81. !-----------------------------------------------------------------------
  82. LOGICAL ::
  83. & lextrapdone ! logical, true if EXTRAP done on field
  84. REAL (kind=real_kind) ::
  85. $ rl_varmul ! Gaussian variance
  86. INTEGER (kind=int_kind) ::
  87. & num_neighbors ! number of neighbours
  88. !-----------------------------------------------------------------------
  89. !
  90. ! local variables
  91. !
  92. !-----------------------------------------------------------------------
  93. logical (kind=log_kind), dimension(num_neighbors) ::
  94. & nbr_mask ! mask at nearest neighbors
  95. integer (kind=int_kind) :: n,
  96. & dst_add, ! destination address
  97. & nmap ! index of current map being computed
  98. integer (kind=int_kind), dimension(num_neighbors) ::
  99. & nbr_add ! source address at nearest neighbors
  100. real (kind=dbl_kind), dimension(num_neighbors) ::
  101. & nbr_dist ! angular distance four nearest neighbors
  102. real (kind=dbl_kind) ::
  103. & coslat_dst, ! cos(lat) of destination grid point
  104. & coslon_dst, ! cos(lon) of destination grid point
  105. & sinlat_dst, ! sin(lat) of destination grid point
  106. & sinlon_dst, ! sin(lon) of destination grid point
  107. & dist_tot, ! sum of neighbor distances (for normalizing)
  108. & dist_average ! average distance between the source points
  109. logical (kind=log_kind) :: ll_allmask
  110. logical (kind=log_kind), PARAMETER :: ll_nnei=.true.
  111. real (kind=dbl_kind) ::
  112. & distance ,plat,plon,src_latsnn, arg ! angular distance
  113. real (kind=dbl_kind), dimension (1) :: wgts_new
  114. integer (kind=int_kind) :: min_add_out, max_add_out,
  115. & srch_add, src_addnn
  116. !-----------------------------------------------------------------------
  117. !
  118. IF (nlogprt .GE. 2) THEN
  119. WRITE (UNIT = nulou,FMT = *)' '
  120. WRITE (UNIT = nulou,FMT = *)'Entering routine remap_gauswgt'
  121. CALL OASIS_FLUSH_SCRIP(nulou)
  122. ENDIF
  123. !-----------------------------------------------------------------------
  124. !
  125. ! compute mappings from grid1 to grid2
  126. !
  127. !-----------------------------------------------------------------------
  128. nmap = 1
  129. !***
  130. !*** allocate wgtstmp to be consistent with store_link interface
  131. !***
  132. allocate (wgtstmp(num_wts))
  133. !***
  134. !*** compute cos, sin of lat/lon on source grid for distance
  135. !*** calculations
  136. !***
  137. allocate (coslat(grid1_size), coslon(grid1_size),
  138. & sinlat(grid1_size), sinlon(grid1_size))
  139. coslat = cos(grid1_center_lat)
  140. coslon = cos(grid1_center_lon)
  141. sinlat = sin(grid1_center_lat)
  142. sinlon = sin(grid1_center_lon)
  143. !***
  144. !*** compute the average of the distances between the source points
  145. !***
  146. call grid_dist_average(grid1_size,
  147. & coslat, coslon,
  148. & sinlat, sinlon,
  149. & dist_average)
  150. !***
  151. !*** loop over destination grid
  152. !***
  153. grid_loop1: do dst_add = 1, grid2_size
  154. if (.not. grid2_mask(dst_add)) cycle grid_loop1
  155. coslat_dst = cos(grid2_center_lat(dst_add))
  156. coslon_dst = cos(grid2_center_lon(dst_add))
  157. sinlat_dst = sin(grid2_center_lat(dst_add))
  158. sinlon_dst = sin(grid2_center_lon(dst_add))
  159. !***
  160. !*** find nearest grid points on source grid and
  161. !*** distances to each point
  162. !***
  163. call grid_search_nbrg(nbr_add, nbr_dist,
  164. & min_add_out, max_add_out,
  165. & grid2_center_lat(dst_add),
  166. & grid2_center_lon(dst_add),
  167. & coslat_dst, coslon_dst,
  168. & sinlat_dst, sinlon_dst,
  169. & bin_addr1,
  170. & dist_average, num_neighbors, rl_varmul)
  171. !***
  172. !*** compute weights based on inverse distance
  173. !*** if mask is false, eliminate those points
  174. !***
  175. src_addnn = zero
  176. dist_tot = zero
  177. do n=1,num_neighbors
  178. if ((grid1_mask(nbr_add(n))) .or.
  179. & (.not. grid1_mask(nbr_add(n)) .and. lextrapdone)) THEN
  180. nbr_dist(n) = one/nbr_dist(n)
  181. dist_tot = dist_tot + nbr_dist(n)
  182. nbr_mask(n) = .true.
  183. else
  184. nbr_mask(n) = .false.
  185. endif
  186. end do
  187. !***
  188. !*** normalize weights and store the link
  189. !***
  190. do n=1,num_neighbors
  191. if (nbr_mask(n)) then
  192. wgtstmp(1) = nbr_dist(n)/dist_tot
  193. call store_link_nbr(nbr_add(n), dst_add, wgtstmp, nmap)
  194. grid2_frac(dst_add) = one
  195. endif
  196. end do
  197. IF (ll_nnei) THEN
  198. ll_allmask= .true.
  199. do n=1,num_neighbors
  200. if (nbr_mask(n)) then
  201. ll_allmask=.false.
  202. endif
  203. end do
  204. if ( ll_allmask) THEN
  205. src_latsnn = bignum
  206. do srch_add = min_add_out,max_add_out
  207. if (grid1_mask(srch_add) .or.
  208. & (.not. grid1_mask(srch_add)
  209. & .and. lextrapdone)) THEN
  210. arg = coslat_dst*cos(grid1_center_lat(srch_add))*
  211. & (coslon_dst*cos(grid1_center_lon(srch_add)) +
  212. & sinlon_dst*sin(grid1_center_lon(srch_add)))+
  213. & sinlat_dst*sin(grid1_center_lat(srch_add))
  214. IF (arg < -1.0d0) THEN
  215. arg = -1.0d0
  216. ELSE IF (arg > 1.0d0) THEN
  217. arg = 1.0d0
  218. END IF
  219. distance=acos(arg)
  220. if (distance < src_latsnn) then
  221. src_addnn = srch_add
  222. src_latsnn = distance
  223. endif
  224. endif
  225. end do
  226. IF (nlogprt .GE. 2) THEN
  227. WRITE(nulou,*)'ll_allmask=true and src_addnn= '
  228. & ,src_addnn
  229. CALL OASIS_FLUSH_SCRIP(nulou)
  230. ENDIF
  231. wgts_new(1) = 1.
  232. grid2_frac(dst_add) = one
  233. call store_link_nbr(src_addnn,dst_add ,wgts_new, nmap)
  234. endif
  235. endif
  236. end do grid_loop1
  237. deallocate (coslat, coslon, sinlat, sinlon)
  238. !-----------------------------------------------------------------------
  239. !
  240. ! compute mappings from grid2 to grid1 if necessary
  241. !
  242. !-----------------------------------------------------------------------
  243. if (num_maps > 1) then
  244. nmap = 2
  245. !***
  246. !*** compute cos, sin of lat/lon on source grid for distance
  247. !*** calculations
  248. !***
  249. allocate (coslat(grid2_size), coslon(grid2_size),
  250. & sinlat(grid2_size), sinlon(grid2_size))
  251. coslat = cos(grid2_center_lat)
  252. coslon = cos(grid2_center_lon)
  253. sinlat = sin(grid2_center_lat)
  254. sinlon = sin(grid2_center_lon)
  255. !***
  256. !*** compute the average of the distances between the source points
  257. !***
  258. call grid_dist_average(grid2_size,
  259. & coslat, coslon,
  260. & sinlat, sinlon,
  261. & dist_average)
  262. !***
  263. !*** loop over destination grid
  264. !***
  265. grid_loop2: do dst_add = 1, grid1_size
  266. if (.not. grid1_mask(dst_add)) cycle grid_loop2
  267. coslat_dst = cos(grid1_center_lat(dst_add))
  268. coslon_dst = cos(grid1_center_lon(dst_add))
  269. sinlat_dst = sin(grid1_center_lat(dst_add))
  270. sinlon_dst = sin(grid1_center_lon(dst_add))
  271. !***
  272. !*** find four nearest grid points on source grid and
  273. !*** distances to each point
  274. !***
  275. call grid_search_nbrg(nbr_add, nbr_dist,
  276. & min_add_out, max_add_out,
  277. & grid1_center_lat(dst_add),
  278. & grid1_center_lon(dst_add),
  279. & coslat_dst, coslon_dst,
  280. & sinlat_dst, sinlon_dst,
  281. & bin_addr2,
  282. & dist_average, num_neighbors, rl_varmul)
  283. !***
  284. !*** compute weights based on inverse distance
  285. !*** if mask is false, eliminate those points
  286. !***
  287. dist_tot = zero
  288. do n=1,num_neighbors
  289. if (grid2_mask(nbr_add(n))) then
  290. nbr_dist(n) = one/nbr_dist(n)
  291. dist_tot = dist_tot + nbr_dist(n)
  292. nbr_mask(n) = .true.
  293. else
  294. nbr_mask(n) = .false.
  295. endif
  296. end do
  297. !***
  298. !*** normalize weights and store the link
  299. !***
  300. do n=1,num_neighbors
  301. if (nbr_mask(n)) then
  302. wgtstmp(1) = nbr_dist(n)/dist_tot
  303. call store_link_nbr(dst_add, nbr_add(n), wgtstmp, nmap)
  304. grid1_frac(dst_add) = one
  305. endif
  306. end do
  307. IF (ll_nnei) THEN
  308. ll_allmask= .true.
  309. do n=1,num_neighbors
  310. if (nbr_mask(n)) then
  311. ll_allmask=.false.
  312. endif
  313. end do
  314. if ( ll_allmask) then
  315. PRINT*, 'll_allmask true',src_addnn
  316. src_latsnn = bignum
  317. do srch_add = min_add_out,max_add_out
  318. if (grid2_mask(srch_add) .or.
  319. & (.not. grid2_mask(srch_add)
  320. & .and. lextrapdone)) THEN
  321. arg = coslat_dst*cos(grid2_center_lat(srch_add))*
  322. & (coslon_dst*cos(grid2_center_lon(srch_add)) +
  323. & sinlon_dst*sin(grid2_center_lon(srch_add)))+
  324. & sinlat_dst*sin(grid2_center_lat(srch_add))
  325. IF (arg < -1.0d0) THEN
  326. arg = -1.0d0
  327. ELSE IF (arg > 1.0d0) THEN
  328. arg = 1.0d0
  329. END IF
  330. distance=acos(arg)
  331. if (distance < src_latsnn) then
  332. src_addnn = srch_add
  333. src_latsnn = distance
  334. endif
  335. endif
  336. end do
  337. wgts_new = 1.
  338. grid1_frac(dst_add) = one
  339. call store_link_nbr(dst_add, src_addnn, wgts_new, nmap)
  340. endif
  341. endif
  342. end do grid_loop2
  343. deallocate (coslat, coslon, sinlat, sinlon)
  344. endif
  345. deallocate(wgtstmp)
  346. !
  347. IF (nlogprt .GE. 2) THEN
  348. WRITE (UNIT = nulou,FMT = *)' '
  349. WRITE (UNIT = nulou,FMT = *)'Leaving routine remap_gauswgt'
  350. CALL OASIS_FLUSH_SCRIP(nulou)
  351. ENDIF
  352. !
  353. !-----------------------------------------------------------------------
  354. end subroutine remap_gauswgt
  355. !***********************************************************************
  356. subroutine grid_search_nbrg(nbr_add, nbr_dist, min_add, max_add,
  357. & plat, plon,
  358. & coslat_dst, coslon_dst, sinlat_dst, sinlon_dst,
  359. & src_bin_add, dst_average,
  360. $ num_neighbors, rl_varmul)
  361. !-----------------------------------------------------------------------
  362. !
  363. ! this routine finds the closest num_neighbor points to a search
  364. ! point and computes a distance to each of the neighbors.
  365. !
  366. !-----------------------------------------------------------------------
  367. !-----------------------------------------------------------------------
  368. !
  369. ! input variables
  370. !
  371. !-----------------------------------------------------------------------
  372. integer (kind=int_kind), dimension(:,:), intent(in) ::
  373. & src_bin_add ! search bins for restricting search
  374. real (kind=dbl_kind), intent(in) ::
  375. & plat, ! latitude of the search point
  376. & plon, ! longitude of the search point
  377. & coslat_dst, ! cos(lat) of the search point
  378. & coslon_dst, ! cos(lon) of the search point
  379. & sinlat_dst, ! sin(lat) of the search point
  380. & sinlon_dst, ! sin(lon) of the search point
  381. & dst_average ! average distance between the source points
  382. REAL (kind=real_kind), intent(in) ::
  383. & rl_varmul ! Gaussian variance
  384. INTEGER (kind=int_kind) ::
  385. & num_neighbors ! number of neighbours
  386. !-----------------------------------------------------------------------
  387. !
  388. ! output variables
  389. !
  390. !-----------------------------------------------------------------------
  391. integer (kind=int_kind), dimension(num_neighbors), intent(out) ::
  392. & nbr_add ! address of each of the closest points
  393. real (kind=dbl_kind), dimension(num_neighbors), intent(out) ::
  394. & nbr_dist ! distance to each of the closest points
  395. integer (kind=int_kind),intent(out) :: min_add, max_add
  396. !-----------------------------------------------------------------------
  397. !
  398. ! local variables
  399. !
  400. !-----------------------------------------------------------------------
  401. integer (kind=int_kind) :: n, nmax, nadd, nchk, ! dummy indices
  402. & nm1, np1, i, j, ip1, im1, jp1, jm1
  403. real (kind=dbl_kind) ::
  404. & distance, arg ! angular distance
  405. real (kind=dbl_kind) ::
  406. & variance ! variance for the gaussian FUNCTION
  407. !-----------------------------------------------------------------------
  408. !
  409. ! loop over source grid and find nearest neighbors
  410. !
  411. !-----------------------------------------------------------------------
  412. !***
  413. !*** restrict the search using search bins
  414. !*** expand the bins to catch neighbors
  415. !***
  416. select case (restrict_type)
  417. case('LATITUDE')
  418. do n=1,num_srch_bins
  419. if (plat >= bin_lats(1,n) .and. plat <= bin_lats(2,n)) then
  420. min_add = src_bin_add(1,n)
  421. max_add = src_bin_add(2,n)
  422. nm1 = max(n-1,1)
  423. np1 = min(n+1,num_srch_bins)
  424. min_add = min(min_add,src_bin_add(1,nm1))
  425. max_add = max(max_add,src_bin_add(2,nm1))
  426. min_add = min(min_add,src_bin_add(1,np1))
  427. max_add = max(max_add,src_bin_add(2,np1))
  428. endif
  429. end do
  430. case('LATLON')
  431. n = 0
  432. nmax = nint(sqrt(real(num_srch_bins)))
  433. do j=1,nmax
  434. jp1 = min(j+1,nmax)
  435. jm1 = max(j-1,1)
  436. do i=1,nmax
  437. ip1 = min(i+1,nmax)
  438. im1 = max(i-1,1)
  439. n = n+1
  440. if (plat >= bin_lats(1,n) .and. plat <= bin_lats(2,n) .and.
  441. & plon >= bin_lons(1,n) .and. plon <= bin_lons(2,n)) then
  442. min_add = src_bin_add(1,n)
  443. max_add = src_bin_add(2,n)
  444. nm1 = (jm1-1)*nmax + im1
  445. np1 = (jp1-1)*nmax + ip1
  446. nm1 = max(nm1,1)
  447. np1 = min(np1,num_srch_bins)
  448. min_add = min(min_add,src_bin_add(1,nm1))
  449. max_add = max(max_add,src_bin_add(2,nm1))
  450. min_add = min(min_add,src_bin_add(1,np1))
  451. max_add = max(max_add,src_bin_add(2,np1))
  452. endif
  453. end do
  454. end do
  455. end select
  456. !***
  457. !*** initialize distance and address arrays
  458. !***
  459. nbr_add = 0
  460. nbr_dist = bignum
  461. variance = rl_varmul*dst_average*dst_average
  462. do nadd=min_add,max_add
  463. !***
  464. !*** find distance to this point
  465. !***
  466. arg = sinlat_dst*sinlat(nadd) +
  467. & coslat_dst*coslat(nadd)*
  468. & (coslon_dst*coslon(nadd) +
  469. & sinlon_dst*sinlon(nadd))
  470. IF (arg < -1.0d0) THEN
  471. arg = -1.0d0
  472. ELSE IF (arg > 1.0d0) THEN
  473. arg = 1.0d0
  474. END IF
  475. distance = acos(arg)
  476. !distance = min(500., distance) !ts-sv
  477. !distance = exp(.5*distance*distance/variance)
  478. !***
  479. !*** store the address and distance if this is one of the
  480. !*** smallest four so far
  481. !***
  482. check_loop: do nchk=1,num_neighbors
  483. if (distance .lt. nbr_dist(nchk)) THEN
  484. do n=num_neighbors,nchk+1,-1
  485. nbr_add(n) = nbr_add(n-1)
  486. nbr_dist(n) = nbr_dist(n-1)
  487. end do
  488. nbr_add(nchk) = nadd
  489. nbr_dist(nchk) = distance
  490. exit check_loop
  491. endif
  492. end do check_loop
  493. end do
  494. exp_loop: do nchk=1,num_neighbors
  495. nbr_dist(nchk) =
  496. & exp(.5*nbr_dist(nchk)*nbr_dist(nchk)/variance)
  497. end do exp_loop
  498. !-----------------------------------------------------------------------
  499. end subroutine grid_search_nbrg
  500. !***********************************************************************
  501. subroutine store_link_nbr(add1, add2, weights, nmap)
  502. !-----------------------------------------------------------------------
  503. !
  504. ! this routine stores the address and weight for this link in
  505. ! the appropriate address and weight arrays and resizes those
  506. ! arrays if necessary.
  507. !
  508. !-----------------------------------------------------------------------
  509. !-----------------------------------------------------------------------
  510. !
  511. ! input variables
  512. !
  513. !-----------------------------------------------------------------------
  514. integer (kind=int_kind), intent(in) ::
  515. & add1, ! address on grid1
  516. & add2, ! address on grid2
  517. & nmap ! identifies which direction for mapping
  518. real (kind=dbl_kind), dimension(:), intent(in) ::
  519. & weights ! array of remapping weights for this link
  520. !-----------------------------------------------------------------------
  521. !
  522. ! increment number of links and check to see if remap arrays need
  523. ! to be increased to accomodate the new link. then store the
  524. ! link.
  525. !
  526. !-----------------------------------------------------------------------
  527. select case (nmap)
  528. case(1)
  529. num_links_map1 = num_links_map1 + 1
  530. if (num_links_map1 > max_links_map1)
  531. & call resize_remap_vars(1,resize_increment)
  532. grid1_add_map1(num_links_map1) = add1
  533. grid2_add_map1(num_links_map1) = add2
  534. wts_map1 (:,num_links_map1) = weights
  535. case(2)
  536. num_links_map2 = num_links_map2 + 1
  537. if (num_links_map2 > max_links_map2)
  538. & call resize_remap_vars(2,resize_increment)
  539. grid1_add_map2(num_links_map2) = add1
  540. grid2_add_map2(num_links_map2) = add2
  541. wts_map2 (:,num_links_map2) = weights
  542. end select
  543. !-----------------------------------------------------------------------
  544. end subroutine store_link_nbr
  545. !***********************************************************************
  546. subroutine grid_dist_average(grid_size,
  547. & coslat_grid, coslon_grid,
  548. & sinlat_grid, sinlon_grid,
  549. & dist_average)
  550. !-----------------------------------------------------------------------
  551. !
  552. ! this routine computes the average distance between the points of a
  553. ! grid.
  554. !
  555. !-----------------------------------------------------------------------
  556. !-----------------------------------------------------------------------
  557. !
  558. ! output variables
  559. !
  560. !-----------------------------------------------------------------------
  561. real (kind=dbl_kind), intent(out) ::
  562. & dist_average ! distance to each of the closest points
  563. !-----------------------------------------------------------------------
  564. !
  565. ! input variables
  566. !
  567. !-----------------------------------------------------------------------
  568. integer (kind=int_kind), intent(in) ::
  569. & grid_size
  570. real (kind=dbl_kind), dimension(:), intent(in) ::
  571. & coslat_grid, ! cos(lat) of the grid points
  572. & coslon_grid, ! cos(lon) of the grid points
  573. & sinlat_grid, ! sin(lat) of the grid points
  574. & sinlon_grid ! sin(lon) of the grid points
  575. REAL (kind=dbl_kind) :: arg
  576. !-----------------------------------------------------------------------
  577. !
  578. ! local variables
  579. !
  580. !-----------------------------------------------------------------------
  581. integer (kind=int_kind) :: i
  582. !
  583. IF (nlogprt .GE. 2) THEN
  584. WRITE (UNIT = nulou,FMT = *)' '
  585. WRITE (UNIT = nulou,FMT = *)
  586. & 'Entering routine remap_dist_average'
  587. CALL OASIS_FLUSH_SCRIP(nulou)
  588. ENDIF
  589. !
  590. !-----------------------------------------------------------------------
  591. !
  592. ! compute the distance over the grid and average
  593. !
  594. !-----------------------------------------------------------------------
  595. dist_average = 0.0
  596. DO i = 1, grid_size
  597. IF (i .eq. 1) THEN
  598. arg = sinlat_grid(grid_size)*sinlat_grid(i) +
  599. & coslat_grid(grid_size)*coslat_grid(i)*
  600. & (coslon_grid(grid_size)*coslon_grid(i) +
  601. & sinlon_grid(grid_size)*sinlon_grid(i))
  602. IF (arg < -1.0d0) THEN
  603. arg = -1.0d0
  604. ELSE IF (arg > 1.0d0) THEN
  605. arg = 1.0d0
  606. END IF
  607. dist_average = dist_average + acos(arg)
  608. arg = sinlat_grid(i)*sinlat_grid(i+1) +
  609. & coslat_grid(i)*coslat_grid(i+1)*
  610. & (coslon_grid(i)*coslon_grid(i+1) +
  611. & sinlon_grid(i)*sinlon_grid(i+1))
  612. IF (arg < -1.0d0) THEN
  613. arg = -1.0d0
  614. ELSE IF (arg > 1.0d0) THEN
  615. arg = 1.0d0
  616. END IF
  617. dist_average = dist_average + acos(arg)
  618. ELSE IF (i .eq. grid_size) THEN
  619. arg = sinlat_grid(i-1)*sinlat_grid(i) +
  620. & coslat_grid(i-1)*coslat_grid(i)*
  621. & (coslon_grid(i-1)*coslon_grid(i) +
  622. & sinlon_grid(i-1)*sinlon_grid(i))
  623. IF (arg < -1.0d0) THEN
  624. arg = -1.0d0
  625. ELSE IF (arg > 1.0d0) THEN
  626. arg = 1.0d0
  627. END IF
  628. dist_average = dist_average + acos(arg)
  629. arg = sinlat_grid(i)*sinlat_grid(1) +
  630. & coslat_grid(i)*coslat_grid(1)*
  631. & (coslon_grid(i)*coslon_grid(1) +
  632. & sinlon_grid(i)*sinlon_grid(1))
  633. IF (arg < -1.0d0) THEN
  634. arg = -1.0d0
  635. ELSE IF (arg > 1.0d0) THEN
  636. arg = 1.0d0
  637. END IF
  638. dist_average = dist_average + acos(arg)
  639. ELSE
  640. arg = sinlat_grid(i-1)*sinlat_grid(i) +
  641. & coslat_grid(i-1)*coslat_grid(i)*
  642. & (coslon_grid(i-1)*coslon_grid(i) +
  643. & sinlon_grid(i-1)*sinlon_grid(i))
  644. IF (arg < -1.0d0) THEN
  645. arg = -1.0d0
  646. ELSE IF (arg > 1.0d0) THEN
  647. arg = 1.0d0
  648. END IF
  649. dist_average = dist_average + acos(arg)
  650. arg = sinlat_grid(i)*sinlat_grid(i+1) +
  651. & coslat_grid(i)*coslat_grid(i+1)*
  652. & (coslon_grid(i)*coslon_grid(i+1) +
  653. & sinlon_grid(i)*sinlon_grid(i+1))
  654. IF (arg < -1.0d0) THEN
  655. arg = -1.0d0
  656. ELSE IF (arg > 1.0d0) THEN
  657. arg = 1.0d0
  658. END IF
  659. dist_average = dist_average + acos(arg)
  660. END IF
  661. END DO
  662. dist_average = dist_average / (2*grid_size)
  663. !
  664. IF (nlogprt .GE. 2) THEN
  665. WRITE (UNIT = nulou,FMT = *)' '
  666. WRITE (UNIT = nulou,FMT = *)
  667. & 'Leaving routine remap_dist_average'
  668. CALL OASIS_FLUSH_SCRIP(nulou)
  669. ENDIF
  670. !
  671. END subroutine grid_dist_average
  672. !***********************************************************************
  673. end module remap_gaussian_weight
  674. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!