remap_bicubic_reduced.F90 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116
  1. MODULE remap_bicubic_reduced
  2. !-----------------------------------------------------------------------
  3. ! BOP
  4. !
  5. ! !MODULE: remap_bicubic_reduced
  6. !
  7. ! !USES:
  8. USE kinds_mod ! defines common data types
  9. USE constants ! defines common constants
  10. USE grids ! module containing grid info
  11. USE remap_vars ! module containing remap info
  12. USE mod_oasis_flush
  13. ! !PUBLIC TYPES:
  14. IMPLICIT NONE
  15. ! !PUBLIC MEMBER FUNCTIONS:
  16. !
  17. ! !PUBLIC DATA MEMBERS:
  18. ! !DESCRIPTION:
  19. ! This routine computes the weights for a bicubic interpolation
  20. ! with a reduced grid. Computes mappings from grid1 to grid2.
  21. !
  22. ! !REVISION HISTORY:
  23. ! 2002.10.21 J.Ghattas created
  24. !
  25. ! EOP
  26. !-----------------------------------------------------------------------
  27. ! $Id: remap_bicubic_reduced.F90 2826 2010-12-10 11:14:21Z valcke $
  28. ! $Author: valcke $
  29. !-----------------------------------------------------------------------
  30. CONTAINS
  31. !***********************************************************************
  32. !-----------------------------------------------------------------------
  33. ! BOP
  34. !
  35. ! !IROUTINE: remap_bicub_reduced
  36. !
  37. ! !INTERFACE:
  38. SUBROUTINE remap_bicub_reduced(ld_extrapdone)
  39. ! !USES:
  40. ! !RETURN VALUE:
  41. ! !PARAMETERS:
  42. LOGICAL, INTENT(in) :: &
  43. ld_extrapdone ! logical, true if EXTRAP done on field
  44. LOGICAL :: ll_nnei ! true (default) if extra search is done
  45. INTEGER (KIND=int_kind), DIMENSION(4,4) :: &
  46. ila_src_add ! address for source points non-masked
  47. INTEGER (KIND=int_kind), DIMENSION(4) :: &
  48. ila_nbr_found ! nrb of points found on each latitude
  49. INTEGER (KIND=int_kind) :: &
  50. ib_i, & ! iter index
  51. ib_dst_add, & ! destination address, target point
  52. il_count, & ! nbr of latitudes with found points
  53. il_min, il_max, bin ! begin and end for distances calculation
  54. REAL (KIND=dbl_kind), DIMENSION(4,4) :: &
  55. rla_src_lons, & ! longitudes for the points 'ila_src_add'
  56. rla_weight, & ! bicubic weights for the points 'ila_src_add'
  57. rla_wght_lon ! temp. weights
  58. REAL (KIND=dbl_kind), DIMENSION(4) :: &
  59. rla_src_lats, & ! latitudes for the points 'ila_src_add'
  60. rla_lats_temp, & ! temp. latitudes
  61. rla_wght_lat, rla_wght_temp! temp. weights
  62. REAL (KIND=dbl_kind) :: &
  63. rl_plat, rl_plon ! latitude and longitude for destination address
  64. REAL (KIND=dbl_kind) :: & ! variables for distances calculation
  65. rl_coslat_dst, rl_sinlat_dst, &
  66. rl_coslon_dst, rl_sinlon_dst, &
  67. rl_distance, arg
  68. REAL (KIND=dbl_kind), DIMENSION(2) :: &
  69. rla_dist ! lat distances to point cible
  70. INTEGER (KIND=int_kind), DIMENSION(4) :: &
  71. ila_add_dist ! temporary addr. for distances
  72. LOGICAL :: ll_linear ! flag
  73. ! !DESCRIPTION:
  74. ! This routine computes the weights for a bicubic interpolation
  75. ! with a reduced grid. Computes mappings from grid1 to grid2.
  76. !
  77. ! !REVISION HISTORY:
  78. ! 2002.10.21 J.Ghattas created
  79. !
  80. ! EOP
  81. !-----------------------------------------------------------------------
  82. ! $Id: remap_bicubic_reduced.F90 2826 2010-12-10 11:14:21Z valcke $
  83. ! $Author: valcke $
  84. !-----------------------------------------------------------------------
  85. !
  86. IF (nlogprt .GE. 2) THEN
  87. WRITE (UNIT = nulou,FMT = *)' '
  88. WRITE (UNIT = nulou,FMT = *) 'Entering routine remap_bicub_reduced'
  89. CALL OASIS_FLUSH_SCRIP(nulou)
  90. ENDIF
  91. !
  92. ll_nnei = .true.
  93. !
  94. ! Loop over destination grid
  95. !
  96. DO ib_dst_add = 1, grid2_size ! for each target point
  97. ll_linear=.false.
  98. IF (.NOT. grid2_mask(ib_dst_add)) THEN
  99. CYCLE ! target point is masked
  100. END IF
  101. rl_plat = grid2_center_lat(ib_dst_add)
  102. rl_plon = grid2_center_lon(ib_dst_add)
  103. !
  104. ! Search for non-masked points among the closest 16 points
  105. ! on source grid (grid1)
  106. !
  107. CALL grid_search_16_points(ila_src_add, rla_src_lats, rla_src_lons,&
  108. ila_nbr_found, bin, rl_plat, &
  109. rl_plon, ld_extrapdone)
  110. !
  111. ! If there is no point found, search the neaerst
  112. ! non-masked point
  113. !
  114. IF (SUM(ila_nbr_found)==0) THEN
  115. IF (ll_nnei .EQV. .TRUE. ) THEN
  116. IF (nlogprt .GE. 2) THEN
  117. WRITE(nulou,*) ' '
  118. WRITE(nulou,*) &
  119. 'All 16 surrounding source grid points are masked'
  120. WRITE(nulou,*) 'for target point ',ib_dst_add
  121. WRITE(nulou,*) 'with longitude and latitude', rl_plon, rl_plat
  122. WRITE(nulou,*) 'Using the nearest non-masked neighbour.'
  123. WRITE(nulou,*) ' '
  124. CALL OASIS_FLUSH_SCRIP(nulou)
  125. ENDIF
  126. ! Search the nearest point in bin [il_min:il_max]
  127. IF (bin==0 .or. bin==1) THEN
  128. il_min=1
  129. il_max=bin_addr1_r(2,3)
  130. ELSE IF (bin==num_srch_red .or. bin==num_srch_red-1) THEN
  131. il_min=bin_addr1_r(1,num_srch_red-2)
  132. il_max=bin_addr1_r(2,num_srch_red)
  133. ELSE
  134. il_min=bin_addr1_r(1,bin-1)+1
  135. il_max=bin_addr1_r(2,bin+2)
  136. END IF
  137. rl_coslat_dst = COS(rl_plat)
  138. rl_sinlat_dst = SIN(rl_plat)
  139. rl_coslon_dst = COS(rl_plon)
  140. rl_sinlon_dst = SIN(rl_plon)
  141. rla_weight(1,1) = bignum
  142. ila_src_add(1,1) = 0
  143. !cdir novector
  144. DO ib_i=il_min, il_max
  145. IF (grid1_mask(ib_i) .or. ld_extrapdone) THEN
  146. arg = rl_coslat_dst*COS(grid1_center_lat(ib_i))* &
  147. (rl_coslon_dst*COS(grid1_center_lon(ib_i)) + &
  148. rl_sinlon_dst*SIN(grid1_center_lon(ib_i)))+&
  149. rl_sinlat_dst*SIN(grid1_center_lat(ib_i))
  150. IF (arg < -1.0d0) THEN
  151. arg = -1.0d0
  152. ELSE IF (arg > 1.0d0) THEN
  153. arg = 1.0d0
  154. END IF
  155. rl_distance = ACOS(arg)
  156. IF (rl_distance < rla_weight(1,1)) THEN
  157. rla_weight(1,1) = rl_distance
  158. ila_src_add(1,1) = ib_i
  159. END IF
  160. END IF
  161. END DO
  162. rla_weight(:,:) = 0
  163. rla_weight(1,1) = 1
  164. CALL store_link_bicub(ib_dst_add, ila_src_add, rla_weight)
  165. IF (nlogprt .GE. 2) THEN
  166. WRITE(nulou,*) &
  167. 'Nearest non masked neighbour is source point ', &
  168. ila_src_add(1,1)
  169. WRITE(nulou,*) 'with longitude and latitude', &
  170. grid1_center_lon(ila_src_add(1,1)), &
  171. grid1_center_lat(ila_src_add(1,1))
  172. WRITE(nulou,*) ' '
  173. ENDIF
  174. CYCLE
  175. ENDIF
  176. END IF
  177. rla_weight(:,:) = 0
  178. ! if there is only one point found, save it
  179. IF (SUM(ila_nbr_found)==1) THEN
  180. DO ib_i=1,4
  181. IF (ila_nbr_found(ib_i)==1) THEN
  182. rla_weight(ib_i,1)=1
  183. EXIT
  184. END IF
  185. END DO
  186. CALL store_link_bicub(ib_dst_add, ila_src_add, rla_weight)
  187. CYCLE
  188. END IF
  189. ! if there are only 2 points found, distance weighted average
  190. IF (SUM(ila_nbr_found)==2) THEN
  191. rl_coslat_dst = COS(rl_plat)
  192. rl_sinlat_dst = SIN(rl_plat)
  193. rl_coslon_dst = COS(rl_plon)
  194. rl_sinlon_dst = SIN(rl_plon)
  195. rl_distance=0 ! count of total distance
  196. DO ib_i=1,4
  197. IF (ila_nbr_found(ib_i) > 0) THEN
  198. arg = rl_coslat_dst*COS(rla_src_lats(ib_i))* &
  199. (rl_coslon_dst*COS(rla_src_lons(ib_i,1)) + &
  200. rl_sinlon_dst*SIN(rla_src_lons(ib_i,1)))+&
  201. rl_sinlat_dst*SIN(rla_src_lats(ib_i))
  202. IF (arg < -1.0d0) THEN
  203. arg = -1.0d0
  204. ELSE IF (arg > 1.0d0) THEN
  205. arg = 1.0d0
  206. END IF
  207. rla_weight(ib_i,1) = ACOS(arg)
  208. rl_distance = rl_distance+rla_weight(ib_i,1)
  209. IF (ila_nbr_found(ib_i)==2) THEN
  210. arg = rl_coslat_dst*COS(rla_src_lats(ib_i))* &
  211. (rl_coslon_dst*COS(rla_src_lons(ib_i,2)) + &
  212. rl_sinlon_dst*SIN(rla_src_lons(ib_i,2)))+&
  213. rl_sinlat_dst*SIN(rla_src_lats(ib_i))
  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. rla_weight(ib_i,2) = ACOS(arg)
  220. rl_distance = rl_distance+rla_weight(ib_i,2)
  221. END IF
  222. END IF
  223. END DO
  224. rla_weight=rla_weight/rl_distance
  225. CALL store_link_bicub(ib_dst_add, ila_src_add, rla_weight)
  226. CYCLE
  227. END IF
  228. ! Some case exceptional when just one point per line found
  229. IF (ila_nbr_found(1)==1) THEN ! elimination of point
  230. ila_nbr_found(1)=0
  231. ila_src_add(1,1)=0
  232. END IF
  233. IF (ila_nbr_found(4)==1) THEN
  234. ila_nbr_found(4)=0
  235. ila_src_add(4,1)=0
  236. END IF
  237. IF (ila_nbr_found(2)==1 .or. ila_nbr_found(3)==1) THEN
  238. ila_add_dist(:)=4
  239. rla_dist(:)=bignum
  240. ! search for the 2 nearest points or line of points
  241. DO ib_i=1,4
  242. IF (ila_nbr_found(ib_i) > 1) THEN
  243. rl_distance=ABS(rla_src_lats(ib_i)-rl_plat)
  244. ELSE IF (ila_nbr_found(ib_i)==1) THEN
  245. rl_coslat_dst = COS(rl_plat)
  246. rl_sinlat_dst = SIN(rl_plat)
  247. rl_coslon_dst = COS(rl_plon)
  248. rl_sinlon_dst = SIN(rl_plon)
  249. arg = rl_coslat_dst*COS(rla_src_lats(ib_i))* &
  250. (rl_coslon_dst*COS(rla_src_lons(ib_i,1)) + &
  251. rl_sinlon_dst*SIN(rla_src_lons(ib_i,1)))+&
  252. rl_sinlat_dst*SIN(rla_src_lats(ib_i))
  253. IF (arg < -1.0d0) THEN
  254. arg = -1.0d0
  255. ELSE IF (arg > 1.0d0) THEN
  256. arg = 1.0d0
  257. END IF
  258. rl_distance= ACOS(arg)
  259. ELSE
  260. rl_distance=bignum
  261. END IF
  262. IF (rl_distance < rla_dist(1)) THEN
  263. ila_add_dist(2)=ila_add_dist(1)
  264. ila_add_dist(1)=ib_i
  265. rla_dist(2)=rla_dist(1)
  266. rla_dist(1)=rl_distance
  267. ELSE IF (rl_distance < rla_dist(2)) THEN
  268. ila_add_dist(2)=ib_i
  269. rla_dist(2)=rl_distance
  270. END IF
  271. END DO
  272. IF (ila_nbr_found(ila_add_dist(1))>1 .and. &
  273. ila_nbr_found(ila_add_dist(2))>1) THEN
  274. ! linearie
  275. ll_linear=.true.
  276. ELSE
  277. ! do distance weighted averege
  278. rla_wght_lon(:,:)=0
  279. DO ib_i=1,2
  280. SELECT CASE (ila_nbr_found(ila_add_dist(ib_i)))
  281. CASE (4)
  282. CALL calcul_wght_irreg(rla_src_lons(ila_add_dist(ib_i),:),&
  283. rl_plon, rla_wght_lon(ila_add_dist(ib_i),:))
  284. rla_wght_lon(ila_add_dist(ib_i),:)=&
  285. rla_wght_lon(ila_add_dist(ib_i),:)/&
  286. rla_dist(ib_i)
  287. CASE (3)
  288. CALL calcul_wght_3(rla_src_lons(ila_add_dist(ib_i),1:3),&
  289. rl_plon, rla_wght_lon(ila_add_dist(ib_i),1:3))
  290. rla_wght_lon(ila_add_dist(ib_i),1:3)=&
  291. rla_wght_lon(ila_add_dist(ib_i),1:3)/&
  292. rla_dist(ib_i)
  293. CASE (2)
  294. CALL calcul_wght_2(rla_src_lons(ila_add_dist(ib_i),1:2),&
  295. rl_plon, rla_wght_lon(ila_add_dist(ib_i),1:2))
  296. rla_wght_lon(ila_add_dist(ib_i),1:2)=&
  297. rla_wght_lon(ila_add_dist(ib_i),1:2)/&
  298. rla_dist(ib_i)
  299. CASE (1)
  300. rla_wght_lon(ila_add_dist(ib_i),1)=1/rla_dist(ib_i)
  301. END SELECT
  302. END DO
  303. rl_distance=0
  304. DO ib_i=1,4
  305. rl_distance=rl_distance + sum(rla_wght_lon(ib_i,:))
  306. END DO
  307. rla_weight(:,:)=rla_wght_lon(:,:)/rl_distance
  308. CALL store_link_bicub(ib_dst_add, ila_src_add , rla_weight)
  309. CYCLE
  310. END IF
  311. END IF
  312. !
  313. ! Calculation of weights for longitudes
  314. !
  315. rla_wght_lon(:,:)=0
  316. DO ib_i=1,4
  317. SELECT CASE (ila_nbr_found(ib_i))
  318. CASE (4)
  319. CALL calcul_wght_irreg(rla_src_lons(ib_i,:), rl_plon, &
  320. rla_wght_lon(ib_i,:))
  321. CASE (3)
  322. CALL calcul_wght_3(rla_src_lons(ib_i,1:3), rl_plon, &
  323. rla_wght_lon(ib_i,1:3))
  324. CASE (2)
  325. CALL calcul_wght_2(rla_src_lons(ib_i,1:2), rl_plon, &
  326. rla_wght_lon(ib_i,1:2))
  327. END SELECT
  328. END DO
  329. IF (ll_linear) THEN
  330. rla_wght_lat(:)=0
  331. CALL calcul_wght_2(rla_src_lats(ila_add_dist(:)), rl_plat, &
  332. rla_wght_temp(1:2))
  333. rla_wght_lat(ila_add_dist(1))=rla_wght_temp(1)
  334. rla_wght_lat(ila_add_dist(2))=rla_wght_temp(2)
  335. DO ib_i=1,4
  336. rla_weight(ib_i,:)=rla_wght_lat(ib_i)*rla_wght_lon(ib_i,:)
  337. END DO
  338. CALL store_link_bicub(ib_dst_add, ila_src_add , rla_weight)
  339. CYCLE
  340. END IF
  341. !
  342. ! Calculation of weights for latitudes
  343. !
  344. il_count=0
  345. DO ib_i=1,4
  346. IF (ila_nbr_found(ib_i)/=0) THEN
  347. il_count=il_count+1
  348. rla_lats_temp(il_count)=rla_src_lats(ib_i)
  349. END IF
  350. END DO
  351. SELECT CASE (il_count)
  352. CASE (4)
  353. CALL calcul_wght_irreg(rla_lats_temp, rl_plat, rla_wght_temp(:))
  354. CASE (3)
  355. CALL calcul_wght_3(rla_lats_temp(1:3), rl_plat, rla_wght_temp(1:3))
  356. CASE (2)
  357. CALL calcul_wght_2(rla_lats_temp(1:2), rl_plat, rla_wght_temp(1:2))
  358. CASE (1)
  359. rla_wght_temp(1)=1
  360. END SELECT
  361. il_count=0
  362. DO ib_i=1,4
  363. IF (ila_nbr_found(ib_i)/=0) THEN
  364. il_count=il_count+1
  365. rla_wght_lat(ib_i)=rla_wght_temp(il_count)
  366. ELSE
  367. rla_wght_lat(ib_i)=0
  368. END IF
  369. END DO
  370. !
  371. ! Calculation of total weight, elementwise multiplication
  372. !
  373. DO ib_i=1,4
  374. rla_weight(ib_i,:)=rla_wght_lat(ib_i)*rla_wght_lon(ib_i,:)
  375. END DO
  376. CALL store_link_bicub(ib_dst_add, ila_src_add , rla_weight)
  377. END DO
  378. !
  379. IF (nlogprt .GE. 2) THEN
  380. WRITE (UNIT = nulou,FMT = *)' '
  381. WRITE (UNIT = nulou,FMT = *) 'Leaving routine remap_bicub_reduced'
  382. CALL OASIS_FLUSH_SCRIP(nulou)
  383. ENDIF
  384. !
  385. END SUBROUTINE remap_bicub_reduced
  386. !-----------------------------------------------------------------------
  387. ! BOP
  388. !
  389. ! !IROUTINE: grid_search_16_points
  390. !
  391. ! !INTERFACE:
  392. !
  393. SUBROUTINE grid_search_16_points(ida_src_add, rda_src_lats, rda_src_lons,&
  394. ida_nbr_found, bin, rd_plat, &
  395. rd_plon, ld_extrapdone)
  396. !
  397. ! !USES:
  398. !
  399. ! !RETURN VALUE:
  400. !
  401. INTEGER (KIND=int_kind), DIMENSION(4,4), INTENT(out) :: &
  402. ida_src_add ! searched addresses of the unmasked points enclosing
  403. ! target point
  404. REAL (KIND=dbl_kind), DIMENSION(4,4), INTENT(out) :: &
  405. rda_src_lons ! longitudes of the searched points
  406. REAL (KIND=dbl_kind), DIMENSION(4), INTENT(out) :: &
  407. rda_src_lats ! latitudes of the searched points
  408. INTEGER (KIND=int_kind), DIMENSION(4), INTENT(out) :: &
  409. ida_nbr_found ! indicates for each line how many points found
  410. INTEGER (KIND=int_kind), INTENT(out) :: &
  411. bin ! actual bin for target point
  412. !
  413. ! !PARAMETERS:
  414. !
  415. REAL (KIND=dbl_kind), INTENT(in) :: &
  416. rd_plat, & ! latitude of the target point
  417. rd_plon ! longitude of the target point
  418. LOGICAL, INTENT(in) :: ld_extrapdone ! true if extrapolation done
  419. INTEGER (KIND=int_kind) :: &
  420. ib_k, ib_j, ib_i, & ! iteration indices
  421. il_min, il_max, il_inter ! begin and end for actual bin
  422. INTEGER (KIND=int_kind), DIMENSION(4,2) :: &
  423. ila_corners ! temp addresses for bins
  424. !
  425. ! !DESCRIPTION:
  426. ! This routine finds the location of the target point in the source
  427. ! grid and returns those of the 16 nearest points that are unmasked.
  428. ! The source grid is a reduced grid.
  429. !
  430. ! !REVISION HISTORY:
  431. ! 2002.10.21 J.Ghattas created
  432. !
  433. ! EOP
  434. !-----------------------------------------------------------------------
  435. ! $Id: remap_bicubic_reduced.F90 2826 2010-12-10 11:14:21Z valcke $
  436. ! $Author: valcke $
  437. !-----------------------------------------------------------------------
  438. !
  439. ! serch of actual bin
  440. !
  441. IF (rd_plat > bin_lats_r(1,1)) THEN ! norther of the first bin
  442. bin=0
  443. ila_corners(1:2,1:2)= 0
  444. ila_corners(3,1)= bin_addr1_r(1,1)+1
  445. ila_corners(3,2)= bin_addr1_r(2,1)
  446. ila_corners(4,1)= bin_addr1_r(1,2)
  447. ila_corners(4,2)= bin_addr1_r(2,2)
  448. ELSE IF (rd_plat > bin_lats_r(1,2)) THEN ! in the first bin
  449. bin=1
  450. ila_corners(1,1:2)= 0
  451. ila_corners(2,1)= bin_addr1_r(1,1)+1
  452. ila_corners(2,2)= bin_addr1_r(2,1)
  453. ila_corners(3,1)= bin_addr1_r(1,2)
  454. ila_corners(3,2)= bin_addr1_r(2,2)
  455. ila_corners(4,1)= bin_addr1_r(1,3)
  456. ila_corners(4,2)= bin_addr1_r(2,3)
  457. ELSE IF (rd_plat < bin_lats_r(1,num_srch_red)) THEN
  458. ! South of the last complet bin
  459. bin=num_srch_red
  460. ila_corners(1,1) = bin_addr1_r(1,num_srch_red-1)
  461. ila_corners(1,2) = bin_addr1_r(2,num_srch_red-1)
  462. ila_corners(2,1) = bin_addr1_r(1,num_srch_red)
  463. ila_corners(2,2) = bin_addr1_r(2,num_srch_red)
  464. ila_corners(3:4,1:2) = 0
  465. ELSE IF (rd_plat < bin_lats_r(1,num_srch_red-1)) THEN
  466. ! in the last bin which is complet
  467. ! the bin (num_srch_red-1) is the last bin which is complet
  468. bin=num_srch_red-1
  469. ila_corners(1,1) = bin_addr1_r(1,num_srch_red-2)
  470. ila_corners(1,2) = bin_addr1_r(2,num_srch_red-2)
  471. ila_corners(2,1) = bin_addr1_r(1,num_srch_red-1)
  472. ila_corners(2,2) = bin_addr1_r(2,num_srch_red-1)
  473. ila_corners(3,1) = bin_addr1_r(1,num_srch_red)
  474. ila_corners(3,2) = bin_addr1_r(2,num_srch_red)
  475. ila_corners(4,1:2) = 0
  476. ELSE
  477. il_min=2
  478. il_max=num_srch_red-1
  479. DO WHILE (il_min /= il_max-1)
  480. il_inter=(il_max-il_min)/2 + il_min
  481. IF (rd_plat <= bin_lats_r(1,il_min) .and. &
  482. rd_plat > bin_lats_r(1,il_inter)) THEN
  483. il_max=il_inter
  484. ELSE
  485. il_min=il_inter
  486. END IF
  487. END DO
  488. bin=il_min
  489. ila_corners(1,1) = bin_addr1_r(1,bin-1)
  490. ila_corners(1,2) = bin_addr1_r(2,bin-1)
  491. ila_corners(2,1) = bin_addr1_r(1,bin)
  492. ila_corners(2,2) = bin_addr1_r(2,bin)
  493. ila_corners(3,1) = bin_addr1_r(1,bin+1)
  494. ila_corners(3,2) = bin_addr1_r(2,bin+1)
  495. ila_corners(4,1) = bin_addr1_r(1,bin+2)
  496. ila_corners(4,2) = bin_addr1_r(2,bin+2)
  497. IF (ila_corners(1,1)==0) THEN
  498. ila_corners(1,1)=1
  499. END IF
  500. END IF
  501. DO ib_k=1,4
  502. IF (ila_corners(ib_k,1) .NE. 0) &
  503. rda_src_lats(ib_k)= grid1_center_lat(ila_corners(ib_k,1))
  504. ENDDO
  505. !
  506. ! now perform a more detailed search for each line
  507. !
  508. ida_src_add(:,:)=0
  509. ida_nbr_found(:)=0
  510. rda_src_lons(:,:)=0
  511. DO ib_k=1,4 ! for each line of found points
  512. IF (ila_corners(ib_k,1)==0) THEN
  513. CYCLE
  514. END IF
  515. il_min=ila_corners(ib_k,1)
  516. il_max=ila_corners(ib_k,2)
  517. IF (rd_plon < grid1_center_lon(il_min)) THEN
  518. DO ib_j=il_max-1, il_max
  519. IF (grid1_mask(ib_j) .or. ld_extrapdone) THEN
  520. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  521. ida_src_add(ib_k,ida_nbr_found(ib_k)) = ib_j
  522. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  523. grid1_center_lon(ib_j)-pi2
  524. END IF
  525. END DO
  526. DO ib_j=il_min, il_min+1
  527. IF (grid1_mask(ib_j) .or. ld_extrapdone) THEN
  528. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  529. ida_src_add(ib_k,ida_nbr_found(ib_k)) = ib_j
  530. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  531. grid1_center_lon(ib_j)
  532. END IF
  533. END DO
  534. ELSE IF (rd_plon < grid1_center_lon(il_min+1)) THEN
  535. IF (grid1_mask(il_max) .or. ld_extrapdone) THEN
  536. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  537. ida_src_add(ib_k,ida_nbr_found(ib_k)) = il_max
  538. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  539. grid1_center_lon(il_max)-pi2
  540. END IF
  541. DO ib_j=il_min, il_min+2
  542. IF (grid1_mask(ib_j) .or. ld_extrapdone) THEN
  543. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  544. ida_src_add(ib_k,ida_nbr_found(ib_k)) = ib_j
  545. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  546. grid1_center_lon(ib_j)
  547. END IF
  548. END DO
  549. ELSE IF (rd_plon > grid1_center_lon(il_max)) THEN
  550. DO ib_j=il_max-1, il_max
  551. IF (grid1_mask(ib_j) .or. ld_extrapdone) THEN
  552. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  553. ida_src_add(ib_k,ida_nbr_found(ib_k)) = ib_j
  554. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  555. grid1_center_lon(ib_j)
  556. END IF
  557. END DO
  558. DO ib_j=il_min, il_min+1
  559. IF (grid1_mask(ib_j) .or. ld_extrapdone) THEN
  560. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  561. ida_src_add(ib_k,ida_nbr_found(ib_k)) = ib_j
  562. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  563. grid1_center_lon(ib_j)+pi2
  564. END IF
  565. END DO
  566. ELSE IF (rd_plon > grid1_center_lon(il_max-1)) THEN
  567. DO ib_j=il_max-2, il_max
  568. IF (grid1_mask(ib_j) .or. ld_extrapdone) THEN
  569. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  570. ida_src_add(ib_k,ida_nbr_found(ib_k)) = ib_j
  571. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  572. grid1_center_lon(ib_j)
  573. END IF
  574. END DO
  575. IF (grid1_mask(il_min) .or. ld_extrapdone) THEN
  576. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  577. ida_src_add(ib_k,ida_nbr_found(ib_k)) = il_min
  578. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  579. grid1_center_lon(il_min)+pi2
  580. END IF
  581. ELSE
  582. DO WHILE (il_min/=il_max-1)
  583. il_inter=(il_max-il_min)/2 + il_min
  584. IF (rd_plon >= grid1_center_lon(il_min) .and. &
  585. rd_plon < grid1_center_lon(il_inter)) THEN
  586. il_max=il_inter
  587. ELSE
  588. il_min=il_inter
  589. END IF
  590. END DO
  591. DO ib_i= il_min-1, il_min+2
  592. IF (grid1_mask(ib_i) .or. ld_extrapdone) THEN
  593. ida_nbr_found(ib_k)=ida_nbr_found(ib_k)+1
  594. ida_src_add(ib_k,ida_nbr_found(ib_k))=ib_i
  595. rda_src_lons(ib_k,ida_nbr_found(ib_k))= &
  596. grid1_center_lon(ib_i)
  597. END IF
  598. END DO
  599. END IF
  600. END DO
  601. END SUBROUTINE grid_search_16_points
  602. !-----------------------------------------------------------------------
  603. ! BOP
  604. !
  605. ! !IROUTINE: calcul_wght_irreg
  606. !
  607. ! !INTERFACE:
  608. !
  609. SUBROUTINE calcul_wght_irreg(rda_x, rd_pt, rda_wght)
  610. !
  611. ! !USES:
  612. !
  613. ! !RETURN VALUE:
  614. !
  615. REAL (KIND=dbl_kind), DIMENSION(4), INTENT(out) :: &
  616. rda_wght ! array of weights for the points x
  617. !
  618. ! !PARAMETERS:
  619. !
  620. REAL (KIND=dbl_kind), DIMENSION(4), INTENT(in) :: &
  621. rda_x ! array of positions on source grid, lat or lon
  622. REAL (KIND=dbl_kind),INTENT(in) :: &
  623. rd_pt ! position of target point to interpolate
  624. REAL (KIND=dbl_kind) :: &
  625. rl_t1, rl_t2, rl_t3, rl_t4, rl_t5, rl_t6, rl_t7, rl_t8, rl_t9, &
  626. rl_u1, rl_u2, rl_u3, rl_u4, &
  627. rl_k1, rl_k2, rl_k3, &
  628. rl_d1, rl_d2, rl_d3, rl_d4, &
  629. rl_c1, rl_c2, rl_c3, rl_c4, &
  630. rl_b1, rl_b2, rl_b3, rl_b4, &
  631. rl_a1, rl_a2, rl_a3, rl_a4, &
  632. rl_y1, rl_y2, rl_y3, &
  633. rl_a1_y, rl_a2_y, rl_a3_y, rl_a4_y, &
  634. rl_b1_y, rl_b2_y, rl_b3_y, rl_b4_y, &
  635. rl_c1_y, rl_c2_y, rl_c3_y, rl_c4_y
  636. !
  637. ! !DESCRIPTION:
  638. ! Calculates a the weights of four points for a bicubic interpolation.
  639. ! The distances between the points can be irregulier.
  640. !
  641. ! !REVISION HISTORY:
  642. ! 2002.10.21 J.Ghattas created
  643. !
  644. ! EOP
  645. !-----------------------------------------------------------------------
  646. ! $Id: remap_bicubic_reduced.F90 2826 2010-12-10 11:14:21Z valcke $
  647. ! $Author: valcke $
  648. !-----------------------------------------------------------------------
  649. IF (rda_x(1)/=0.and. rda_x(2)/=0 .and. rda_x(3)/=0 .and. rda_x(4)/=0) THEN
  650. rl_t1 = 1/rda_x(1) - 1/rda_x(2)
  651. rl_t2 = 1/rda_x(1)**2 - 1/rda_x(2)**2
  652. rl_t3 = 1/rda_x(1)**3 - 1/rda_x(2)**3
  653. rl_t4 = 1/rda_x(1) - 1/rda_x(3)
  654. rl_t5 = 1/rda_x(1)**2 - 1/rda_x(3)**2
  655. rl_t6 = 1/rda_x(1)**3 - 1/rda_x(3)**3
  656. rl_t7 = 1/rda_x(1) - 1/rda_x(4)
  657. rl_t8 = 1/rda_x(1)**2 - 1/rda_x(4)**2
  658. rl_t9 = 1/rda_x(1)**3 - 1/rda_x(4)**3
  659. rl_u1 = rl_t2/rl_t1 - rl_t5/rl_t4
  660. rl_u2 = rl_t3/rl_t1 - rl_t6/rl_t4
  661. rl_u3 = rl_t2/rl_t1 - rl_t8/rl_t7
  662. rl_u4 = rl_t3/rl_t1 - rl_t9/rl_t7
  663. rl_k1 = (1/(rl_t1*rl_u1)-1/(rl_t1*rl_u3)) / (rl_u2/rl_u1-rl_u4/rl_u3)
  664. rl_k2 = -1/(rl_t4*rl_u1) / (rl_u2/rl_u1-rl_u4/rl_u3)
  665. rl_k3 = 1/(rl_t7*rl_u3) / (rl_u2/rl_u1-rl_u4/rl_u3)
  666. rl_d1=(rl_k1+rl_k2+rl_k3)/rda_x(1)**3
  667. rl_d2 = -rl_k1/rda_x(2)**3
  668. rl_d3 = -rl_k2/rda_x(3)**3
  669. rl_d4 = -rl_k3/rda_x(4)**3
  670. rl_c1 = 1/rl_u1*(1/(rl_t1*rda_x(1)**3)-1/(rl_t4*rda_x(1)**3)- &
  671. rl_u2*rl_d1)
  672. rl_c2 = 1/rl_u1*(1/(-rl_t1*rda_x(2)**3)-rl_u2*rl_d2)
  673. rl_c3 = 1/rl_u1*(1/(rl_t4*rda_x(3)**3)-rl_u2*rl_d3)
  674. rl_c4 = 1/rl_u1*(-rl_u2*rl_d4)
  675. rl_b1 = 1/rl_t1/rda_x(1)**3-rl_t2/rl_t1*rl_c1-rl_t3/rl_t1*rl_d1
  676. rl_b2 = -1/rl_t1/rda_x(2)**3-rl_t2/rl_t1*rl_c2-rl_t3/rl_t1*rl_d2
  677. rl_b3 = -rl_t2/rl_t1*rl_c3-rl_t3/rl_t1*rl_d3
  678. rl_b4 = -rl_t2/rl_t1*rl_c4-rl_t3/rl_t1*rl_d4
  679. rl_a1 = 1/rda_x(1)**3-1/rda_x(1)*rl_b1-1/rda_x(1)**2*rl_c1- &
  680. 1/rda_x(1)**3*rl_d1
  681. rl_a2 = -1/rda_x(1)*rl_b2-1/rda_x(1)**2*rl_c2-1/rda_x(1)**3*rl_d2
  682. rl_a3 = -1/rda_x(1)*rl_b3-1/rda_x(1)**2*rl_c3-1/rda_x(1)**3*rl_d3
  683. rl_a4 = -1/rda_x(1)*rl_b4-1/rda_x(1)**2*rl_c4-1/rda_x(1)**3*rl_d4
  684. ! Weights
  685. rda_wght(1) = rl_a1*rd_pt**3 + rl_b1*rd_pt**2 + rl_c1*rd_pt + rl_d1
  686. rda_wght(2) = rl_a2*rd_pt**3 + rl_b2*rd_pt**2 + rl_c2*rd_pt + rl_d2
  687. rda_wght(3) = rl_a3*rd_pt**3 + rl_b3*rd_pt**2 + rl_c3*rd_pt + rl_d3
  688. rda_wght(4) = rl_a4*rd_pt**3 + rl_b4*rd_pt**2 + rl_c4*rd_pt + rl_d4
  689. ELSE ! there is one point = 0
  690. rl_d1=0; rl_d2=0; rl_d3=0; rl_d4=0
  691. ! Transformation for each case
  692. IF (rda_x(1)==0) THEN
  693. rl_y1=rda_x(2); rl_y2=rda_x(3); rl_y3=rda_x(4)
  694. rl_d1=1
  695. ELSE IF (rda_x(2)==0) THEN
  696. rl_y1=rda_x(1); rl_y2=rda_x(3); rl_y3=rda_x(4)
  697. rl_d2=1
  698. ELSE IF (rda_x(3)==0) THEN
  699. rl_y1=rda_x(1); rl_y2=rda_x(2); rl_y3=rda_x(4)
  700. rl_d3=1
  701. ELSE
  702. rl_y1=rda_x(1); rl_y2=rda_x(2); rl_y3=rda_x(3)
  703. rl_d4=1
  704. END IF
  705. ! Solving the system
  706. rl_t1 = 1/rl_y1-1/rl_y2
  707. rl_t2 = 1/rl_y1**2-1/rl_y2**2
  708. rl_t3 = 1/rl_y1-1/rl_y3
  709. rl_t4 = 1/rl_y1**2-1/rl_y3**2
  710. rl_c1_y =(1/rl_y1**3/rl_t1-1/rl_y1**3/rl_t3)/(rl_t2/rl_t1-rl_t4/rl_t3)
  711. rl_c2_y = -1/rl_y2**3/rl_t1/(rl_t2/rl_t1-rl_t4/rl_t3)
  712. rl_c3_y = 1/rl_y3**3/rl_t3/(rl_t2/rl_t1-rl_t4/rl_t3)
  713. rl_c4_y=(-1/rl_y1**3/rl_t1+1/rl_y2**3/rl_t1+ &
  714. 1/rl_y1**3/rl_t3-1/rl_y3**3/rl_t3)/(rl_t2/rl_t1-rl_t4/rl_t3)
  715. rl_b1_y = 1/rl_y1**3/rl_t1 - rl_c1_y*rl_t2/rl_t1
  716. rl_b2_y = -1/rl_y2**3/rl_t1 - rl_c2_y*rl_t2/rl_t1
  717. rl_b3_y = -rl_c3_y*rl_t2/rl_t1
  718. rl_b4_y = -1/rl_y1**3/rl_t1 + 1/rl_y2**3/rl_t1 - rl_c4_y*rl_t2/rl_t1
  719. rl_a1_y = 1/rl_y1**3 - rl_b1_y/rl_y1 - rl_c1_y/rl_y1**2
  720. rl_a2_y = -rl_b2_y/rl_y1 - rl_c2_y/rl_y1**2
  721. rl_a3_y = -rl_b3_y/rl_y1 - rl_c3_y/rl_y1**2
  722. rl_a4_y = -1/rl_y1**3 - rl_b4_y/rl_y1 - rl_c4_y/rl_y1**2
  723. ! Retransformation
  724. IF (rda_x(1)==0) THEN
  725. rl_a1=rl_a4_y; rl_a2=rl_a1_y; rl_a3=rl_a2_y; rl_a4=rl_a3_y
  726. rl_b1=rl_b4_y; rl_b2=rl_b1_y; rl_b3=rl_b2_y; rl_b4=rl_b3_y
  727. rl_c1=rl_c4_y; rl_c2=rl_c1_y; rl_c3=rl_c2_y; rl_c4=rl_c3_y
  728. ELSE IF (rda_x(2)==0) THEN
  729. rl_a1=rl_a1_y; rl_a2=rl_a4_y; rl_a3=rl_a2_y; rl_a4=rl_a3_y
  730. rl_b1=rl_b1_y; rl_b2=rl_b4_y; rl_b3=rl_b2_y; rl_b4=rl_b3_y
  731. rl_c1=rl_c1_y; rl_c2=rl_c4_y; rl_c3=rl_c2_y; rl_c4=rl_c3_y
  732. ELSE IF (rda_x(3)==0) THEN
  733. rl_a1=rl_a1_y; rl_a2=rl_a2_y; rl_a3=rl_a4_y; rl_a4=rl_a3_y
  734. rl_b1=rl_b1_y; rl_b2=rl_b2_y; rl_b3=rl_b4_y; rl_b4=rl_b3_y
  735. rl_c1=rl_c1_y; rl_c2=rl_c2_y; rl_c3=rl_c4_y; rl_c4=rl_c3_y
  736. ELSE
  737. rl_a1=rl_a1_y; rl_a2=rl_a2_y; rl_a3=rl_a3_y; rl_a4=rl_a4_y
  738. rl_b1=rl_b1_y; rl_b2=rl_b2_y; rl_b3=rl_b3_y; rl_b4=rl_b4_y
  739. rl_c1=rl_c1_y; rl_c2=rl_c2_y; rl_c3=rl_c3_y; rl_c4=rl_c4_y
  740. END IF
  741. ! Weights
  742. rda_wght(1) = rl_a1*rd_pt**3 + rl_b1*rd_pt**2 + rl_c1*rd_pt +rl_d1
  743. rda_wght(2) = rl_a2*rd_pt**3 + rl_b2*rd_pt**2 + rl_c2*rd_pt +rl_d2
  744. rda_wght(3) = rl_a3*rd_pt**3 + rl_b3*rd_pt**2 + rl_c3*rd_pt +rl_d3
  745. rda_wght(4) = rl_a4*rd_pt**3 + rl_b4*rd_pt**2 + rl_c4*rd_pt +rl_d4
  746. END IF
  747. END SUBROUTINE calcul_wght_irreg
  748. !-----------------------------------------------------------------------
  749. ! BOP
  750. !
  751. ! !IROUTINE: calcul_wght_3
  752. !
  753. ! !INTERFACE:
  754. SUBROUTINE calcul_wght_3(rda_x, rd_pt, rda_wght)
  755. ! !USES:
  756. ! !RETURN VALUE:
  757. REAL (KIND=dbl_kind), DIMENSION(3), INTENT(out) :: &
  758. rda_wght ! array of weights for the points x
  759. ! !PARAMETERS:
  760. REAL (KIND=dbl_kind), DIMENSION(3), INTENT(in) :: &
  761. rda_x ! array of positions on source grid, lat or lon
  762. REAL (KIND=dbl_kind), INTENT(in) :: &
  763. rd_pt ! position of target point to interpolate
  764. REAL (KIND=dbl_kind) :: &
  765. rl_c1, rl_c2, rl_c3, &
  766. rl_a1, rl_a2, rl_a3, &
  767. rl_b1, rl_b2, rl_b3, &
  768. rl_t1, rl_t2, rl_t3, rl_t4
  769. ! !DESCRIPTION:
  770. ! Calculates a the weights of 3 points for a parabolic interpolation.
  771. !
  772. ! !REVISION HISTORY:
  773. ! 2002.10.21 J.Ghattas created
  774. !
  775. ! EOP
  776. !-----------------------------------------------------------------------
  777. ! $Id: remap_bicubic_reduced.F90 2826 2010-12-10 11:14:21Z valcke $
  778. ! $Author: valcke $
  779. !-----------------------------------------------------------------------
  780. IF (rda_x(1)/=0 .and. rda_x(2)/=0 .and. rda_x(3)/=0) THEN
  781. rl_t1 = 1/rda_x(1)-1/rda_x(2)
  782. rl_t2 = 1/rda_x(1)**2-1/rda_x(2)**2
  783. rl_t3 = 1/rda_x(1)-1/rda_x(3)
  784. rl_t4 = 1/rda_x(1)**2-1/rda_x(3)**2
  785. rl_c1 = (1/rda_x(1)**2/rl_t1-1/rda_x(1)**2/rl_t3) / &
  786. (rl_t2/rl_t1-rl_t4/rl_t3)
  787. rl_c2 = -1/rda_x(2)**2/rl_t1 / (rl_t2/rl_t1-rl_t4/rl_t3)
  788. rl_c3 = 1/rda_x(3)**2/rl_t3 / (rl_t2/rl_t1-rl_t4/rl_t3)
  789. rl_b1 = 1/rda_x(1)**2/rl_t1 - rl_c1*rl_t2/rl_t1
  790. rl_b2 = -1/rda_x(2)**2/rl_t1 - rl_c2*rl_t2/rl_t1
  791. rl_b3 = - rl_c3*rl_t2/rl_t1
  792. rl_a1 = 1/rda_x(1)**2 - rl_b1/rda_x(1) - rl_c1/rda_x(1)**2
  793. rl_a2 = - rl_b2/rda_x(1) - rl_c2/rda_x(1)**2
  794. rl_a3 = - rl_b3/rda_x(1) - rl_c3/rda_x(1)**2
  795. ELSE IF (rda_x(1)==0) THEN
  796. rl_c1 = 1; rl_c2 = 0; rl_c3 = 0
  797. rl_b1 = (-1/rda_x(2)**2+1/rda_x(3)**2) / (1/rda_x(2)-1/rda_x(3))
  798. rl_b2 = 1/rda_x(2)**2 / (1/rda_x(2)-1/rda_x(3))
  799. rl_b3 = -1/rda_x(3)**2 / (1/rda_x(2)-1/rda_x(3))
  800. rl_a1 = -1/rda_x(2)**2 - rl_b1/rda_x(2)
  801. rl_a2 = 1/rda_x(2)**2 - rl_b2/rda_x(2)
  802. rl_a3 = - rl_b3/rda_x(2)
  803. ELSE IF (rda_x(2)==0) THEN
  804. rl_c1 = 0; rl_c2 = 1; rl_c3 = 0
  805. rl_b1 = 1/rda_x(1)**2 / (1/rda_x(1)-1/rda_x(3))
  806. rl_b2 = (-1/rda_x(1)**2+1/rda_x(3)**2) / (1/rda_x(1)-1/rda_x(3))
  807. rl_b3 = -1/rda_x(3)**2 / (1/rda_x(1)-1/rda_x(3))
  808. rl_a1 = 1/rda_x(1)**2 - rl_b1/rda_x(1)
  809. rl_a2 = -1/rda_x(1)**2 - rl_b2/rda_x(1)
  810. rl_a3 = - rl_b3/rda_x(1)
  811. ELSE !rda_x(3)==0
  812. rl_c1 = 0; rl_c2 = 0; rl_c3 = 1
  813. rl_b1 = 1/rda_x(1)**2 / (1/rda_x(1)-1/rda_x(2))
  814. rl_b2 = -1/rda_x(2)**2 / (1/rda_x(1)-1/rda_x(2))
  815. rl_b3 = (-1/rda_x(1)**2+1/rda_x(2)**2) / (1/rda_x(1)-1/rda_x(2))
  816. rl_a1 = 1/rda_x(1)**2 - rl_b1/rda_x(1)
  817. rl_a2 = - rl_b2/rda_x(1)
  818. rl_a3 = -1/rda_x(1)**2 - rl_b3/rda_x(1)
  819. END IF
  820. ! Weights
  821. rda_wght(1) = rl_a1*rd_pt**2 + rl_b1*rd_pt + rl_c1
  822. rda_wght(2) = rl_a2*rd_pt**2 + rl_b2*rd_pt + rl_c2
  823. rda_wght(3) = rl_a3*rd_pt**2 + rl_b3*rd_pt + rl_c3
  824. END SUBROUTINE calcul_wght_3
  825. !-----------------------------------------------------------------------
  826. ! BOP
  827. !
  828. ! !IROUTINE: calcul_wght_2
  829. !
  830. ! !INTERFACE:
  831. SUBROUTINE calcul_wght_2(rda_x, rd_pt, rda_wght)
  832. ! !USES:
  833. ! !RETURN VALUE:
  834. REAL (KIND=dbl_kind), DIMENSION(2), INTENT(out) :: &
  835. rda_wght ! array of weights for the points x
  836. ! !PARAMETERS:
  837. REAL (KIND=dbl_kind), DIMENSION(2), INTENT(in) :: &
  838. rda_x ! array of positions on source grid, lat or lon
  839. REAL (KIND=dbl_kind), INTENT(in) :: &
  840. rd_pt ! position of target point to interpolate
  841. REAL (KIND=dbl_kind) :: rl_b1, rl_b2, rl_a1, rl_a2
  842. ! !DESCRIPTION:
  843. ! Calculates a the weights of 2 points for a linair interpolation.
  844. !
  845. ! !REVISION HISTORY:
  846. ! 2002.10.21 J.Ghattas created
  847. !
  848. ! EOP
  849. !-----------------------------------------------------------------------
  850. ! $Id: remap_bicubic_reduced.F90 2826 2010-12-10 11:14:21Z valcke $
  851. ! $Author: valcke $
  852. !-----------------------------------------------------------------------
  853. IF (rda_x(1)/=0 .and. rda_x(2)/=0) THEN
  854. rl_b1 = 1/(1-rda_x(1)/rda_x(2))
  855. rl_b2 = -1/(rda_x(2)/rda_x(1)-1)
  856. rl_a1 = 1/rda_x(1) - rl_b1/rda_x(1)
  857. rl_a2 = - rl_b2/rda_x(1)
  858. ELSE IF (rda_x(1)==0) THEN
  859. rl_b1=1; rl_b2=0
  860. rl_a1=-1/rda_x(2)
  861. rl_a2=1/rda_x(2)
  862. ELSE
  863. rl_b1=0; rl_b2=1
  864. rl_a1=1/rda_x(1)
  865. rl_a2=-1/rda_x(1)
  866. END IF
  867. rda_wght(1) = rl_a1*rd_pt + rl_b1
  868. rda_wght(2) = rl_a2*rd_pt + rl_b2
  869. END SUBROUTINE calcul_wght_2
  870. !-----------------------------------------------------------------------
  871. ! BOP
  872. !
  873. ! !IROUTINE: store_link_bicub
  874. !
  875. ! !INTERFACE:
  876. SUBROUTINE store_link_bicub(id_dst_add, ida_src_add, rda_wght)
  877. ! !USES:
  878. ! !RETURN VALUE:
  879. ! !PARAMETERS:
  880. INTEGER (KIND=int_kind), INTENT(in) :: &
  881. id_dst_add ! address on destination grid
  882. INTEGER (KIND=int_kind), DIMENSION(4,4), INTENT(in) :: &
  883. ida_src_add ! addresses for links on source grid
  884. REAL (KIND=dbl_kind), DIMENSION(4,4), INTENT(in) :: &
  885. rda_wght ! array of remapping weights for these links
  886. INTEGER (KIND=int_kind) :: ib_i, &
  887. il_num_links_old ! placeholder for old link number
  888. INTEGER (KIND=int_kind), DIMENSION(16) :: &
  889. ila_src_add ! reshaped addresses
  890. REAL (KIND=dbl_kind), DIMENSION(16) :: &
  891. rla_wght ! reshaped weights
  892. ! !DESCRIPTION:
  893. ! This routine stores the addresses and weights for 16 links associated
  894. ! with one destination point in the appropriate address.
  895. !
  896. ! !REVISION HISTORY:
  897. ! 2002.10.21 J.Ghattas created
  898. !
  899. ! EOP
  900. !-----------------------------------------------------------------------
  901. ! $Id: remap_bicubic_reduced.F90 2826 2010-12-10 11:14:21Z valcke $
  902. ! $Author: valcke $
  903. !-----------------------------------------------------------------------
  904. !
  905. ! Increment number of links and check if remap arrays need
  906. ! to be increased to accomodate the new link. then store the link.
  907. !
  908. il_num_links_old = num_links_map1
  909. num_links_map1 = il_num_links_old + 16
  910. IF (num_links_map1 > max_links_map1) THEN
  911. CALL resize_remap_vars(1,MAX(resize_increment,16))
  912. END IF
  913. ila_src_add=RESHAPE(ida_src_add,(/16/))
  914. rla_wght=RESHAPE(rda_wght,(/16/))
  915. DO ib_i=1,16
  916. grid1_add_map1(il_num_links_old+ib_i) = ila_src_add(ib_i)
  917. grid2_add_map1(il_num_links_old+ib_i) = id_dst_add
  918. wts_map1(1,il_num_links_old+ib_i) = rla_wght(ib_i)
  919. END DO
  920. END SUBROUTINE store_link_bicub
  921. END MODULE remap_bicubic_reduced
  922. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!