scrip_use_extrap.f 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. !-----------------------------------------------------------------------
  2. !
  3. ! This script interpolates a (time, latitude, longitude) netcdf file
  4. ! using the interpolation weights computed by SCRIP :
  5. ! Spherical Coordinate Remapping and Interpolation Package
  6. ! and then extrapolates using the nearest neighbour method
  7. !
  8. ! The arguments are passed through a namelist named scrip_use_in:
  9. !&remap_inputs
  10. ! remap_wgt = 'Weights from SCRIP'
  11. ! infile = 'input netcdf file'
  12. ! invertlat = TRUE/FALSE : should the latitudes be reverted ?
  13. ! var = 'netcdf variable name'
  14. ! fromregular = TRUE/FALSE : is the input grid regular ?
  15. ! outfile = 'output netcdf file'
  16. !/
  17. !
  18. ! History : Virginie Guemas - Initial version - 2011
  19. !-----------------------------------------------------------------------
  20. program scrip_use_extrap
  21. !-----------------------------------------------------------------------
  22. use kinds_mod ! defines common data types
  23. use constants ! defines common constants
  24. use iounits ! I/O unit manager
  25. use netcdf_mod ! netcdf I/O stuff
  26. use grids ! module containing grid info
  27. use remap_vars ! module containing remapping info
  28. use remap_mod ! module containing remapping routines
  29. use remap_read ! routines for reading remap files
  30. use read_input_file ! routines to read file to interpolate
  31. implicit none
  32. !-----------------------------------------------------------------------
  33. !
  34. ! input namelist variables
  35. !
  36. !-----------------------------------------------------------------------
  37. character (char_len) ::
  38. & remap_wgt, ! filename containing remap data (map1)
  39. & infile, ! filename containing input field
  40. & var, ! var name in infile
  41. & outfile ! filename to output interpolated field
  42. logical :: fromregular
  43. namelist /remap_inputs/ remap_wgt, infile, invertlat, var,
  44. & fromregular, outfile
  45. !-----------------------------------------------------------------------
  46. !
  47. ! local variables
  48. !
  49. !-----------------------------------------------------------------------
  50. character (char_len) ::
  51. & map_name ! name for mapping from grid1 to grid2
  52. integer (kind=int_kind) :: ! netCDF ids for files and arrays
  53. & ncstat, nc_outfile_id,
  54. & nc_dstgrdcntrlat_id, nc_dstgrdcntrlon_id,
  55. & nc_dstarray1_id, nc_dstarray1a_id, nc_dstarray2_id,
  56. & nc_vartime_id, nc_srcarray_id
  57. integer (kind=int_kind), dimension(:), allocatable ::
  58. & nc_grid2size_id, nc_grid1size_id
  59. !-----------------------------------------------------------------------
  60. character (char_len) ::
  61. & dim_name, attname ! netCDF dimension name
  62. integer (kind=int_kind) :: i,j,n,imin,imax,idiff,
  63. & ip1,im1,jp1,jm1,nx,ny, ! for computing bicub gradients
  64. & in,is,ie,iw,ine,inw,ise,isw,jatt,
  65. & iunit,jtime ! unit number for namelist file
  66. integer (kind=int_kind), dimension(:), allocatable ::
  67. & grid1_imask, grid2_imask, grid2_count,neighbour
  68. real (kind=dbl_kind) ::
  69. & delew, delns, ! variables for computing bicub gradients
  70. & length, ! length scale for cosine hill test field
  71. & dist_min,distance ! Extrapolation
  72. real (kind=dbl_kind), dimension(:), allocatable ::
  73. & grid1_tmp,
  74. & grad1_lat,
  75. & grad1_lon,
  76. & grad1_latlon,
  77. & grad1_lat_zero,
  78. & grad1_lon_zero,
  79. & grid2_array,
  80. & grid2_err,
  81. & grid2_tmp,
  82. & grid1_mask_grid2,
  83. & dstcoslon,
  84. & dstcoslat,
  85. & srccoslon,
  86. & srccoslat,
  87. & dstsinlon,
  88. & dstsinlat,
  89. & srcsinlon,
  90. & srcsinlat
  91. !-----------------------------------------------------------------------
  92. !
  93. ! read namelist for file and mapping info
  94. !
  95. !-----------------------------------------------------------------------
  96. call get_unit(iunit)
  97. open(iunit, file='scrip_use_in', status='old', form='formatted')
  98. read(iunit, nml=remap_inputs)
  99. call release_unit(iunit)
  100. write(*,nml=remap_inputs)
  101. !-----------------------------------------------------------------------
  102. !
  103. ! read remapping data
  104. !
  105. !-----------------------------------------------------------------------
  106. call read_remap(map_name, remap_wgt)
  107. !-----------------------------------------------------------------------
  108. !
  109. ! read input file
  110. !
  111. !-----------------------------------------------------------------------
  112. call read_input(infile, var)
  113. !-----------------------------------------------------------------------
  114. !
  115. ! allocate arrays
  116. !
  117. !-----------------------------------------------------------------------
  118. allocate (grid1_tmp (grid1_size),
  119. & grad1_lat (grid1_size),
  120. & grad1_lon (grid1_size),
  121. & grad1_latlon (grid1_size),
  122. & grad1_lat_zero (grid1_size),
  123. & grad1_lon_zero (grid1_size),
  124. & grid1_imask (grid1_size),
  125. & grid2_array (grid2_size),
  126. & grid2_err (grid2_size),
  127. & grid2_tmp (grid2_size),
  128. & grid2_imask (grid2_size),
  129. & grid2_count (grid2_size),
  130. & grid1_mask_grid2(grid2_size))
  131. where (grid1_mask)
  132. grid1_imask = 1
  133. elsewhere
  134. grid1_imask = 0
  135. endwhere
  136. where (grid2_mask)
  137. grid2_imask = 1
  138. elsewhere
  139. grid2_imask = 0
  140. endwhere
  141. allocate (srccoslon (grid1_size),
  142. & srcsinlon (grid1_size),
  143. & srccoslat (grid1_size),
  144. & srcsinlat (grid1_size),
  145. & dstcoslon (grid2_size),
  146. & dstsinlon (grid2_size),
  147. & dstcoslat (grid2_size),
  148. & dstsinlat (grid2_size),
  149. & neighbour (grid2_size))
  150. dstcoslon = cos(grid2_center_lon*pi/180)
  151. dstsinlon = sin(grid2_center_lon*pi/180)
  152. srccoslon = cos(grid1_center_lon*pi/180)
  153. srcsinlon = sin(grid1_center_lon*pi/180)
  154. dstcoslat = cos(grid2_center_lat*pi/180)
  155. dstsinlat = sin(grid2_center_lat*pi/180)
  156. srccoslat = cos(grid1_center_lat*pi/180)
  157. srcsinlat = sin(grid1_center_lat*pi/180)
  158. !-----------------------------------------------------------------------
  159. !
  160. ! setup a NetCDF file for output
  161. !
  162. !-----------------------------------------------------------------------
  163. !***
  164. !*** create netCDF dataset
  165. !***
  166. ncstat = nf_create (outfile, NF_CLOBBER, nc_outfile_id)
  167. call netcdf_error_handler(ncstat)
  168. ncstat = nf_put_att_text (nc_outfile_id, NF_GLOBAL, 'title',
  169. & len_trim(map_name), map_name)
  170. call netcdf_error_handler(ncstat)
  171. !***
  172. !*** define grid size dimensions
  173. !***
  174. allocate( nc_grid2size_id(grid2_rank+1))
  175. allocate( nc_grid1size_id(grid1_rank+1))
  176. ncstat = nf_def_dim (nc_outfile_id, 'x',
  177. & grid2_dims(1), nc_grid2size_id(1))
  178. call netcdf_error_handler(ncstat)
  179. ncstat = nf_def_dim (nc_outfile_id, 'y',
  180. & grid2_dims(2), nc_grid2size_id(2))
  181. call netcdf_error_handler(ncstat)
  182. ncstat = nf_def_dim (nc_outfile_id, 'inx',
  183. & grid1_dims(1), nc_grid1size_id(1))
  184. call netcdf_error_handler(ncstat)
  185. ncstat = nf_def_dim (nc_outfile_id, 'iny',
  186. & grid1_dims(2), nc_grid1size_id(2))
  187. call netcdf_error_handler(ncstat)
  188. !***
  189. !*** Create time dimension
  190. !***
  191. ncstat = nf_def_dim (nc_outfile_id, 'time',
  192. & NF_UNLIMITED, nc_grid2size_id(3))
  193. call netcdf_error_handler(ncstat)
  194. nc_grid1size_id(3)=nc_grid2size_id(3)
  195. ncstat = nf_def_var (nc_outfile_id, 'time',
  196. & NF_DOUBLE, 1, nc_grid2size_id(3), nc_vartime_id)
  197. call netcdf_error_handler(ncstat)
  198. if ( nc_time_id > -1 ) then
  199. if ( natts >= 1 ) then
  200. do jatt = 1,natts
  201. ncstat = nf_inq_attname(nc_infile_id, nc_time_id, jatt,
  202. & attname)
  203. call netcdf_error_handler(ncstat)
  204. ncstat = nf_copy_att(nc_infile_id, nc_time_id, attname,
  205. & nc_outfile_id, nc_vartime_id)
  206. enddo
  207. endif
  208. endif
  209. !***
  210. !*** define grid center latitude array
  211. !***
  212. ncstat = nf_def_var (nc_outfile_id, 'latitude',
  213. & NF_DOUBLE, grid2_rank, nc_grid2size_id
  214. & (1:grid2_rank), nc_dstgrdcntrlat_id)
  215. call netcdf_error_handler(ncstat)
  216. ncstat = nf_put_att_text (nc_outfile_id, nc_dstgrdcntrlat_id,
  217. & 'units', 7, 'degrees')
  218. call netcdf_error_handler(ncstat)
  219. !***
  220. !*** define grid center longitude array
  221. !***
  222. ncstat = nf_def_var (nc_outfile_id, 'longitude',
  223. & NF_DOUBLE, grid2_rank, nc_grid2size_id
  224. & (1:grid2_rank), nc_dstgrdcntrlon_id)
  225. call netcdf_error_handler(ncstat)
  226. ncstat = nf_put_att_text (nc_outfile_id, nc_dstgrdcntrlon_id,
  227. & 'units', 7, 'degrees')
  228. call netcdf_error_handler(ncstat)
  229. !***
  230. !*** define source array
  231. !***
  232. ncstat = nf_def_var (nc_outfile_id, 'input',
  233. & NF_DOUBLE, (grid1_rank+1), nc_grid1size_id,
  234. & nc_srcarray_id)
  235. call netcdf_error_handler(ncstat)
  236. ncstat = nf_put_att_double (nc_outfile_id, nc_srcarray_id,
  237. & 'missing_value', NF_DOUBLE,1,dble(1e20))
  238. call netcdf_error_handler(ncstat)
  239. !***
  240. !*** define destination arrays
  241. !***
  242. ncstat = nf_def_var (nc_outfile_id, var,
  243. & NF_DOUBLE, ( grid2_rank + 1 ),
  244. & nc_grid2size_id, nc_dstarray1_id )
  245. call netcdf_error_handler(ncstat)
  246. ncstat = nf_put_att_double (nc_outfile_id, nc_dstarray1_id,
  247. & 'missing_value', NF_DOUBLE,1,dble(1e20))
  248. call netcdf_error_handler(ncstat)
  249. if ( nvaratts >= 1 ) then
  250. do jatt = 1,nvaratts
  251. ncstat = nf_inq_attname(nc_infile_id, nc_invar_id, jatt,
  252. & attname)
  253. call netcdf_error_handler(ncstat)
  254. if ((attname .ne. '_FillValue') .and. (attname .ne.
  255. & 'missing_value') ) then
  256. ncstat = nf_copy_att(nc_infile_id, nc_invar_id, attname,
  257. & nc_outfile_id, nc_dstarray1_id)
  258. call netcdf_error_handler(ncstat)
  259. endif
  260. enddo
  261. endif
  262. if ( nglobatts >= 1 ) then
  263. do jatt = 1,nglobatts
  264. ncstat = nf_inq_attname(nc_infile_id, NF_GLOBAL, jatt,
  265. & attname)
  266. call netcdf_error_handler(ncstat)
  267. ncstat = nf_copy_att(nc_infile_id, NF_GLOBAL, attname,
  268. & nc_outfile_id, NF_GLOBAL)
  269. call netcdf_error_handler(ncstat)
  270. enddo
  271. endif
  272. ncstat = nf_close(nc_infile_id)
  273. call netcdf_error_handler(ncstat)
  274. !***
  275. !*** end definition stage
  276. !***
  277. ncstat = nf_enddef(nc_outfile_id)
  278. call netcdf_error_handler(ncstat)
  279. !-----------------------------------------------------------------------
  280. !
  281. ! write some grid info
  282. !
  283. !-----------------------------------------------------------------------
  284. !***
  285. !*** write grid center latitude array
  286. !***
  287. ncstat = nf_put_var_double(nc_outfile_id, nc_dstgrdcntrlat_id,
  288. & grid2_center_lat*180./pi)
  289. call netcdf_error_handler(ncstat)
  290. !***
  291. !*** write grid center longitude array
  292. !***
  293. ncstat = nf_put_var_double(nc_outfile_id, nc_dstgrdcntrlon_id,
  294. & grid2_center_lon*180./pi)
  295. call netcdf_error_handler(ncstat)
  296. !-----------------------------------------------------------------------
  297. !
  298. ! Interpolate the input mask
  299. !
  300. !-----------------------------------------------------------------------
  301. call remap(grid1_mask_grid2, wts_map1, grid2_add_map1,
  302. & grid1_add_map1, real(grid1_imask,kind=dbl_kind))
  303. !-----------------------------------------------------------------------
  304. !
  305. ! Prepare extrapolation
  306. !
  307. !-----------------------------------------------------------------------
  308. neighbour = 0
  309. do n = 1,grid2_size
  310. if ( grid2_imask(n)<0.5 .or. grid1_mask_grid2(n) == 0. ) then
  311. dist_min = 1e20
  312. do j = 1,grid1_size
  313. if ( grid1_imask(j) == 1 ) then
  314. distance = acos(dstcoslat(n)*srccoslat(j)*
  315. & (dstcoslon(n)*srccoslon(j)+dstsinlon(n)*srcsinlon(j))
  316. & +dstsinlat(n)*srcsinlat(j))
  317. if ( distance < dist_min ) then
  318. dist_min = distance
  319. neighbour(n) = j
  320. end if
  321. end if
  322. end do
  323. end if
  324. end do
  325. !-----------------------------------------------------------------------
  326. !
  327. ! Write time dimension
  328. !
  329. !-----------------------------------------------------------------------
  330. do jtime = 1,ntime
  331. ncstat = nf_put_vara_double(nc_outfile_id, nc_vartime_id,
  332. & jtime, 1, time(jtime))
  333. call netcdf_error_handler(ncstat)
  334. !-----------------------------------------------------------------------
  335. !
  336. ! if bicubic or 2nd-order conservative, 3 gradients needed in space
  337. !
  338. !-----------------------------------------------------------------------
  339. if ( fromregular .and. (map_type == map_type_bicubic .or.
  340. & map_type == map_type_conserv) ) then
  341. nx = grid1_dims(1)
  342. ny = grid1_dims(2)
  343. do n=1,grid1_size
  344. grad1_lat(n) = zero
  345. grad1_lon(n) = zero
  346. grad1_latlon(n) = zero
  347. if (grid1_mask(n)) then
  348. delew = half
  349. delns = half
  350. j = (n-1)/nx + 1
  351. i = n - (j-1)*nx
  352. ip1 = i+1
  353. im1 = i-1
  354. jp1 = j+1
  355. jm1 = j-1
  356. if (ip1 > nx) ip1 = ip1 - nx
  357. if (im1 < 1 ) im1 = nx
  358. if (jp1 > ny) then
  359. jp1 = j
  360. delns = one
  361. endif
  362. if (jm1 < 1 ) then
  363. jm1 = j
  364. delns = one
  365. endif
  366. in = (jp1-1)*nx + i
  367. is = (jm1-1)*nx + i
  368. ie = (j -1)*nx + ip1
  369. iw = (j -1)*nx + im1
  370. ine = (jp1-1)*nx + ip1
  371. inw = (jp1-1)*nx + im1
  372. ise = (jm1-1)*nx + ip1
  373. isw = (jm1-1)*nx + im1
  374. !*** compute i-gradient
  375. if (.not. grid1_mask(ie)) then
  376. ie = n
  377. delew = one
  378. endif
  379. if (.not. grid1_mask(iw)) then
  380. iw = n
  381. delew = one
  382. endif
  383. grad1_lat(n) = delew*(grid1_array(ie,jtime) -
  384. & grid1_array(iw,jtime))
  385. !*** compute j-gradient
  386. if (.not. grid1_mask(in)) then
  387. in = n
  388. delns = one
  389. endif
  390. if (.not. grid1_mask(is)) then
  391. is = n
  392. delns = one
  393. endif
  394. grad1_lon(n) = delns*(grid1_array(in,jtime) -
  395. & grid1_array(is,jtime))
  396. !*** compute ij-gradient
  397. delew = half
  398. if (jp1 == j .or. jm1 == j) then
  399. delns = one
  400. else
  401. delns = half
  402. endif
  403. if (.not. grid1_mask(ine)) then
  404. if (in /= n) then
  405. ine = in
  406. delew = one
  407. else if (ie /= n) then
  408. ine = ie
  409. inw = iw
  410. if (inw == n) delew = one
  411. delns = one
  412. else
  413. ine = n
  414. inw = iw
  415. delew = one
  416. delns = one
  417. endif
  418. endif
  419. if (.not. grid1_mask(inw)) then
  420. if (in /= n) then
  421. inw = in
  422. delew = one
  423. else if (iw /= n) then
  424. inw = iw
  425. ine = ie
  426. if (ie == n) delew = one
  427. delns = one
  428. else
  429. inw = n
  430. ine = ie
  431. delew = one
  432. delns = one
  433. endif
  434. endif
  435. grad1_lat_zero(n) = delew*(grid1_array(ine,jtime) -
  436. & grid1_array(inw,jtime))
  437. if (.not. grid1_mask(ise)) then
  438. if (is /= n) then
  439. ise = is
  440. delew = one
  441. else if (ie /= n) then
  442. ise = ie
  443. isw = iw
  444. if (isw == n) delew = one
  445. delns = one
  446. else
  447. ise = n
  448. isw = iw
  449. delew = one
  450. delns = one
  451. endif
  452. endif
  453. if (.not. grid1_mask(isw)) then
  454. if (is /= n) then
  455. isw = is
  456. delew = one
  457. else if (iw /= n) then
  458. isw = iw
  459. ise = ie
  460. if (ie == n) delew = one
  461. delns = one
  462. else
  463. isw = n
  464. ise = ie
  465. delew = one
  466. delns = one
  467. endif
  468. endif
  469. grad1_lon_zero(n) = delew*(grid1_array(ise,jtime) -
  470. & grid1_array(isw,jtime))
  471. grad1_latlon(n) = delns*(grad1_lat_zero(n) -
  472. & grad1_lon_zero(n))
  473. endif
  474. enddo
  475. endif
  476. !-----------------------------------------------------------------------
  477. !
  478. ! remapping from grid1 to grid2
  479. !
  480. !-----------------------------------------------------------------------
  481. grad1_lat_zero = zero
  482. grad1_lon_zero = zero
  483. if (map_type == map_type_bicubic) then
  484. if (fromregular) then
  485. call remap(grid2_tmp, wts_map1, grid2_add_map1,
  486. & grid1_add_map1, grid1_array(:,jtime),
  487. & src_grad1=grad1_lat,
  488. & src_grad2=grad1_lon,
  489. & src_grad3=grad1_latlon)
  490. else
  491. print*,"Input grid is not regular, bicubic interpolation "
  492. stop" is not possible : We stop "
  493. endif
  494. elseif (map_type == map_type_conserv .and. fromregular ) then
  495. call remap(grid2_tmp,wts_map1,grid2_add_map1,grid1_add_map1,
  496. & grid1_array(:,jtime), src_grad1=grad1_lat,
  497. & src_grad2=grad1_lon)
  498. else
  499. call remap(grid2_tmp, wts_map1, grid2_add_map1, grid1_add_map1,
  500. & grid1_array(:,jtime))
  501. endif
  502. if (map_type == map_type_conserv) then
  503. select case (norm_opt)
  504. case (norm_opt_none)
  505. grid2_err = grid2_frac*grid2_area
  506. where (grid2_err /= zero)
  507. grid2_tmp = grid2_tmp/grid2_err
  508. else where
  509. grid2_tmp = zero
  510. end where
  511. case (norm_opt_frcarea)
  512. case (norm_opt_dstarea)
  513. where (grid2_frac /= zero)
  514. grid2_tmp = grid2_tmp/grid2_frac
  515. else where
  516. grid2_tmp = zero
  517. end where
  518. end select
  519. end if
  520. !-----------------------------------------------------------------------
  521. !
  522. ! extrapolation
  523. !
  524. !-----------------------------------------------------------------------
  525. !
  526. do n = 1,grid2_size
  527. if ( grid2_imask(n)<0.5 .or. grid1_mask_grid2(n) == 0. ) then
  528. if ( neighbour(n) > 0 ) then
  529. grid2_tmp(n) = grid1_array(neighbour(n),jtime)
  530. else
  531. grid2_tmp(n) = 1e20
  532. end if
  533. end if
  534. end do
  535. !-----------------------------------------------------------------------
  536. !
  537. ! write results to NetCDF file
  538. !
  539. !-----------------------------------------------------------------------
  540. ncstat = nf_put_vara_double(nc_outfile_id, nc_dstarray1_id,
  541. & (/1, 1, jtime/), (/grid2_dims, 1/), grid2_tmp )
  542. call netcdf_error_handler(ncstat)
  543. where (grid1_imask<0.5)
  544. grid1_array(:,jtime)=1e20
  545. end where
  546. ncstat = nf_put_vara_double(nc_outfile_id, nc_srcarray_id,
  547. & (/1, 1, jtime/), (/grid1_dims, 1/), grid1_array(:,jtime))
  548. call netcdf_error_handler(ncstat)
  549. enddo
  550. !-----------------------------------------------------------------------
  551. !
  552. ! close netCDF file
  553. !
  554. !-----------------------------------------------------------------------
  555. ncstat = nf_close(nc_outfile_id)
  556. call netcdf_error_handler(ncstat)
  557. !-----------------------------------------------------------------------
  558. end program scrip_use_extrap
  559. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!