scripinterp_mod.F90 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. ! **************************************************************************
  2. module scripinterp_mod
  3. ! ==========================================================================
  4. use kinds_mod ! defines common data types
  5. use constants ! defines common constants
  6. use iounits ! I/O unit manager
  7. use netcdf
  8. use netcdf_mod ! netcdf I/O stuff
  9. use grids ! module containing grid info
  10. use remap_vars ! module containing remapping info
  11. use remap_mod ! module containing remapping routines
  12. use remap_read ! routines for reading remap files
  13. implicit none
  14. real(kind=dbl_kind), dimension(:), allocatable :: &
  15. grid_out
  16. integer(kind=int_kind) :: & ! netCDF ids for files and arrays
  17. ncstat, nc_outfile_id, nc_infile_id
  18. integer (kind=int_kind), dimension(4) :: &
  19. input_dims, input_dimids, input_count
  20. real (kind=dbl_kind), dimension(:), allocatable :: &
  21. scale
  22. integer (kind=int_kind), dimension(:), allocatable :: &
  23. nc_xysize_id, nc_gridsize_id, nc_gridsize, &
  24. nc_variable_id
  25. integer :: nc_lon_id, nc_lat_id, nc_array_id
  26. character (char_len) :: &
  27. map_name ! name for mapping from grid1 to grid2
  28. character (1), parameter :: &
  29. separator = '|'
  30. ! - input namelist variables
  31. character (char_len) :: &
  32. input_file, & ! filename containing input fields
  33. interp_file, & ! filename containing remap data (map1)
  34. input_name ! name of variable to grid
  35. integer (kind=int_kind), dimension(4) :: &
  36. input_stride, & ! how much of input array to process
  37. input_start, & ! where to start
  38. input_stop ! and where to stop
  39. character (char_len), dimension(4) :: &
  40. input_vars ! input variables to be copied
  41. ! - output namelist variables
  42. character (char_len) :: &
  43. output_file, & ! filename for test results
  44. output_mode, & ! 'create' or 'append'
  45. output_name, & ! name of new grid variable
  46. output_lat, & ! as it says
  47. output_lon, & ! as it says
  48. output_ydir ! choose to invert output arrays in y direction
  49. character (char_len), dimension(4) :: &
  50. output_dims, & ! name of new grid variable
  51. output_vars ! variables to copy
  52. character (char_len), dimension(10) :: &
  53. output_attributes, & ! attributes of stuff in output file
  54. output_scaling ! scaling factor to apply to input data to get
  55. ! correct units in output file
  56. contains
  57. ! ==========================================================================
  58. subroutine process_grid(nm_in)
  59. !-----------------------------------------------------------------------
  60. ! - dummy variables
  61. character (char_len) :: &
  62. nm_in ! name of input namelist file
  63. !-----------------------------------------------------------------------
  64. ! - local variables
  65. integer (kind=int_kind), dimension(4) :: &
  66. astart, acount, plus_one
  67. integer (kind=int_kind), dimension(3) :: &
  68. write_dims
  69. integer (kind=int_kind) :: &
  70. i1, i2, jdim, n, nx, ny, nloop, &
  71. nc_input_id, nc_input_rank, &
  72. vstart, vstride, numv
  73. real (kind=dbl_kind), dimension(:), allocatable :: &
  74. grid1_array
  75. real (kind=dbl_kind), dimension(:,:), allocatable :: &
  76. var_out
  77. plus_one(:) = 1
  78. !-----------------------------------------------------------------------
  79. call read_mappings(nm_in)
  80. !-----------------------------------------------------------------------
  81. ! - read input grid
  82. ! - WARNING - lots of assumptions here at the moment
  83. ncstat = nf90_open( input_file, NF90_NOWRITE, nc_infile_id )
  84. call netcdf_error_handler(ncstat,"open")
  85. ncstat = nf90_inq_varid( nc_infile_id, input_name, nc_input_id )
  86. call netcdf_error_handler(ncstat,"inq_varid")
  87. input_dims(:) = 0
  88. ncstat = nf90_inquire_variable( nc_infile_id, nc_input_id, &
  89. ndims=nc_input_rank, dimids=input_dimids(:) )
  90. call netcdf_error_handler(ncstat,"inquire_variable")
  91. do jdim = 1,nc_input_rank
  92. ncstat = nf90_inquire_dimension(nc_infile_id, &
  93. input_dimids(jdim), len=input_dims(jdim) )
  94. call netcdf_error_handler(ncstat,"inquire_dimension")
  95. enddo
  96. ! - dimids seem to be returned in storage order so the outer dimension of
  97. ! - the array as described by the netcdf file becomes the first dimension
  98. ! - as far as f90 is concerned (confused? you will be!)
  99. do jdim = 1,nc_input_rank
  100. if (input_stop(jdim) == 0) then
  101. input_stop(jdim) = input_dims(jdim)
  102. endif
  103. input_count(jdim) = input_stop(jdim) - input_start(jdim) + 1
  104. enddo
  105. ! - rashly we assume x followed by y
  106. nx = input_dims(1)
  107. ny = input_dims(2)
  108. write(*,fmt='("Input grid dimensions are:",2i6)') nx, ny
  109. if (nx*ny /= grid1_size) then
  110. write(6,*) "mismatch between input grid and remap data"
  111. stop
  112. endif
  113. ! - calculate number of horizontal slices to process
  114. ! - at the moment this is not very general and will only work with 3 dimensions
  115. acount(1:nc_input_rank) = &
  116. (input_stop(1:nc_input_rank)-input_start(1:nc_input_rank)+1) / &
  117. input_stride(1:nc_input_rank)
  118. nloop = 1
  119. do jdim = 1,nc_input_rank
  120. nloop = nloop*acount(jdim)
  121. enddo
  122. nloop = nloop/grid1_size
  123. write(6,*) "total slices requested: ",nloop
  124. vstart = input_start(nc_input_rank) ! ie extra var has outer dimension
  125. vstride = input_stride(nc_input_rank)
  126. ! - in general we cant read in the whole array so do it slice by slice
  127. ! - slow but sure
  128. write(6,*) "allocating input and output grids"
  129. allocate( grid1_array(grid1_size))
  130. allocate( grid_out(grid2_size) )
  131. numv = 0
  132. do n = 1,4
  133. if (trim(input_vars(n)) /= '-' .and. &
  134. trim(output_vars(n)) /= '-') numv = numv + 1
  135. enddo
  136. write_dims(1) = grid2_dims(1)
  137. write_dims(2) = grid2_dims(2)
  138. write_dims(3) = nloop
  139. call define_grid(write_dims(1:3) , 2+numv)
  140. astart(:) = input_start(:)
  141. astart(3) = astart(3) - input_stride(3)
  142. acount(:) = 1
  143. acount(1) = nx
  144. acount(2) = ny
  145. do n = 1,nloop
  146. write(6,*) "processing slice: ",n
  147. astart(3) = astart(3) + input_stride(3)
  148. ncstat = nf90_get_var(nc_infile_id, nc_input_id, grid1_array, &
  149. start=astart(1:nc_input_rank), &
  150. count=acount(1:nc_input_rank))
  151. call netcdf_error_handler(ncstat,"get_var")
  152. call calculate_grid(grid1_array, grid_out)
  153. call write_grid(grid_out, n, write_dims(1:2) , 2)
  154. enddo
  155. ! ---------------------------------------------------------------------
  156. ! - now for any extra variables to copy
  157. if (numv > 0) then
  158. write(6,*) "reading ",numv," extra variables"
  159. allocate( var_out(nloop,numv) )
  160. do n = 1,numv
  161. write(6,*) "looking for variable: ",trim(input_vars(n))
  162. ncstat = nf90_inq_varid( nc_infile_id, trim(input_vars(n)), nc_input_id )
  163. call netcdf_error_handler(ncstat,"inq_varid")
  164. input_dims(:) = 0
  165. ncstat = nf90_inquire_variable( nc_infile_id, nc_input_id, &
  166. ndims=nc_input_rank, dimids=input_dimids(:) )
  167. call netcdf_error_handler(ncstat,"inquire_variable")
  168. if (nc_input_rank /= 1) then
  169. write(6,*) 'sorry, only rank 1 variables can be copied'
  170. cycle
  171. endif
  172. ncstat = nf90_inquire_dimension(nc_infile_id, &
  173. input_dimids(1), len=input_dims(1) )
  174. call netcdf_error_handler(ncstat,"inquire_dimension")
  175. ncstat = nf90_get_var(nc_infile_id, nc_input_id, var_out(1:nloop,n), &
  176. start=(/ vstart /), stride=(/ vstride /))
  177. call netcdf_error_handler(ncstat,"get_var")
  178. enddo
  179. call write_extra(var_out, numv+2)
  180. deallocate(var_out)
  181. endif
  182. ncstat = nf90_close(nc_outfile_id)
  183. call netcdf_error_handler(ncstat,"out close")
  184. ncstat = nf90_close(nc_infile_id)
  185. call netcdf_error_handler(ncstat,"in close")
  186. ! ---------------------------------------------------------------------
  187. deallocate( grid1_array, grid_out)
  188. ! ---------------------------------------------------------------------
  189. end subroutine process_grid
  190. ! ==========================================================================
  191. subroutine define_grid(thedims, therank)
  192. !-----------------------------------------------------------------------
  193. ! - dummy variables
  194. integer (kind=int_kind) :: &
  195. therank
  196. integer (kind=int_kind), dimension(therank) :: &
  197. thedims
  198. !-----------------------------------------------------------------------
  199. ! - local variables
  200. integer :: &
  201. k, n, ilon, ilat, icolon, i1, i2, natt, nvar, id, jd, kd, nd
  202. character (char_len) :: &
  203. aname, vname, att
  204. real (kind=dbl_kind) :: s
  205. ! - netcdf variables
  206. integer :: xtype
  207. !-----------------------------------------------------------------------
  208. ! - define grid size dimensions
  209. allocate(nc_xysize_id(grid2_rank))
  210. allocate(nc_gridsize_id(therank))
  211. allocate(nc_gridsize(therank))
  212. allocate(nc_variable_id(therank-2))
  213. !-----------------------------------------------------------------------
  214. ! - setup a NetCDF file for output
  215. xtype = NF90_FLOAT
  216. write(6,*) 'creating output file'
  217. ncstat = nf90_create (output_file, NF90_CLOBBER, nc_outfile_id)
  218. call netcdf_error_handler(ncstat,"create")
  219. write(6,*) 'setting global attributes'
  220. ncstat = nf90_put_att(nc_outfile_id, NF90_GLOBAL, 'title', map_name)
  221. call netcdf_error_handler(ncstat,"put_att")
  222. write(6,*) 'setting dimensions'
  223. do n=1,therank
  224. if (n .eq. therank .and. therank .gt. 2) then
  225. write(6,*) ' unlimited dim ',trim(output_dims(n)),' size: ',thedims(n)
  226. ncstat = nf90_def_dim (nc_outfile_id, output_dims(n), NF90_UNLIMITED, &
  227. nc_gridsize_id(n))
  228. else
  229. write(6,*) ' dim ',trim(output_dims(n)),' size: ',thedims(n)
  230. ncstat = nf90_def_dim (nc_outfile_id, output_dims(n), thedims(n), &
  231. nc_gridsize_id(n))
  232. endif
  233. call netcdf_error_handler(ncstat,"def_dim")
  234. end do
  235. nc_gridsize(:) = thedims(1:therank)
  236. ! - at the moment there is an assumption here that the ordering is (lon,lat)
  237. ilon = 1
  238. ilat = 2
  239. nc_xysize_id(1) = nc_gridsize_id(ilon)
  240. nc_xysize_id(2) = nc_gridsize_id(ilat)
  241. ! ----------------------------------------------------------------
  242. ! - define grid center longitude array
  243. write(6,*) 'defining longitude variable'
  244. ncstat = nf90_def_var (nc_outfile_id, output_lon, &
  245. xtype, nc_xysize_id, &
  246. nc_lon_id)
  247. call netcdf_error_handler(ncstat,"def_var")
  248. ncstat = nf90_put_att (nc_outfile_id, nc_lon_id, 'units', 'degrees')
  249. call netcdf_error_handler(ncstat,"put_att")
  250. ! ----------------------------------------------------------------
  251. ! - define grid center latitude array
  252. write(6,*) 'defining latitude variable'
  253. ncstat = nf90_def_var (nc_outfile_id, output_lat, &
  254. xtype, nc_xysize_id, &
  255. nc_lat_id)
  256. call netcdf_error_handler(ncstat,"def_var")
  257. ncstat = nf90_put_att (nc_outfile_id, nc_lat_id, 'units', 'degrees')
  258. call netcdf_error_handler(ncstat,"put_att")
  259. ! ----------------------------------------------------------------
  260. ! - define copy variables array
  261. write(6,*) 'defining copy variables'
  262. do n = 3,therank
  263. ncstat = nf90_def_var (nc_outfile_id, output_vars(n-2), &
  264. xtype, nc_gridsize_id(n), &
  265. nc_variable_id(n-2))
  266. call netcdf_error_handler(ncstat,"def_var")
  267. enddo
  268. ! ----------------------------------------------------------------
  269. ! - define output array
  270. write(6,*) 'defining grid variable'
  271. ncstat = nf90_def_var (nc_outfile_id, output_name, &
  272. xtype, nc_gridsize_id, &
  273. nc_array_id)
  274. call netcdf_error_handler(ncstat,"def_var")
  275. ! ----------------------------------------------------------------
  276. ! - output attributes has to come after all other definitions
  277. ! - this code currently a bit murky, needs a rewrite
  278. ncstat = nf90_inquire (nc_outfile_id, nVariables=nvar)
  279. call netcdf_error_handler(ncstat,"inquire")
  280. do n = 1,10
  281. att = trim(output_attributes(n))
  282. natt = len(att)
  283. if (att /= '-') then
  284. i1 = index(att,separator)
  285. aname = att(1:i1-1)
  286. do k = 1,nvar
  287. ncstat = nf90_inquire_variable(nc_outfile_id, k, vname)
  288. call netcdf_error_handler(ncstat,"inquire_variable")
  289. if (vname == aname) then
  290. i2 = index(att,separator,.true.)
  291. ncstat = nf90_put_att (nc_outfile_id, k, &
  292. att(i1+1:i2-1), att(i2+1:natt))
  293. call netcdf_error_handler(ncstat,"put_att")
  294. exit ! from innermost do
  295. endif
  296. enddo
  297. endif
  298. enddo
  299. ! output scaling
  300. allocate (scale(nvar))
  301. scale(:) = 1.0
  302. do n = 1,10
  303. att = trim(output_scaling(n))
  304. natt = len(att)
  305. if (att /= '-') then
  306. i1 = index(att,separator)
  307. aname = att(1:i1-1)
  308. do k = 1,nvar
  309. ncstat = nf90_inquire_variable(nc_outfile_id, k, vname)
  310. call netcdf_error_handler(ncstat,"inquire_variable")
  311. if (vname == aname) then
  312. i2 = index(att,separator,.true.)
  313. read(att(i2+1:natt),*) scale(k)
  314. call netcdf_error_handler(ncstat,"put_att")
  315. exit ! from innermost do
  316. endif
  317. enddo
  318. endif
  319. enddo
  320. ! ----------------------------------------------------------------
  321. ! - end definition stage
  322. ncstat = nf90_enddef(nc_outfile_id)
  323. call netcdf_error_handler(ncstat,"enddef")
  324. end subroutine define_grid
  325. ! ==========================================================================
  326. subroutine write_grid(thegrid, thelevel, thedims, therank)
  327. !-----------------------------------------------------------------------
  328. ! - dummy variables
  329. integer (kind=int_kind), intent(in) :: &
  330. therank, thelevel
  331. real (kind=dbl_kind), dimension(:), intent(in) :: &
  332. thegrid
  333. integer (kind=int_kind), dimension(therank) :: &
  334. thedims
  335. !-----------------------------------------------------------------------
  336. ! - local variables
  337. integer :: &
  338. k, n, ilon, ilat, icolon, j1, j2, dj, natt, nvar, id, jd, kd, nd
  339. character (char_len) :: &
  340. aname, vname, att
  341. real (kind=dbl_kind), dimension(:,:,:), allocatable :: &
  342. data
  343. real (kind=dbl_kind) :: s
  344. real (kind=dbl_kind), parameter :: todeg = 57.295779513082323
  345. integer (kind=int_kind), dimension(3) :: &
  346. start
  347. ! - netcdf variables
  348. integer :: xtype
  349. !-----------------------------------------------------------------------
  350. ! - write results to NetCDF file
  351. allocate (data(thedims(1),thedims(2),1))
  352. if (output_ydir .eq. 'invert') then
  353. j1 = thedims(2)
  354. j2 = 1
  355. dj = -1
  356. else
  357. j1 = 1
  358. j2 = thedims(2)
  359. dj = 1
  360. endif
  361. if (thelevel .eq. 1) then
  362. ! - grid center latitude array
  363. write(6,*) 'writing latitude variable'
  364. s = scale(nc_lat_id)
  365. nd = 0
  366. do jd = j1,j2,dj
  367. do id =1,thedims(1)
  368. nd = nd + 1
  369. data(id,jd,1) = s*todeg*grid2_center_lat(nd)
  370. enddo
  371. enddo
  372. ncstat = nf90_put_var(nc_outfile_id, nc_lat_id, data(:,:,1))
  373. call netcdf_error_handler(ncstat,"put_var")
  374. ! - grid center longitude array
  375. write(6,*) 'writing longitude variable'
  376. s = scale(nc_lon_id)
  377. nd = 0
  378. do jd = j1,j2,dj
  379. do id =1,thedims(1)
  380. nd = nd + 1
  381. data(id,jd,1) = s*todeg*grid2_center_lon(nd)
  382. enddo
  383. enddo
  384. ncstat = nf90_put_var(nc_outfile_id, nc_lon_id, data(:,:,1))
  385. call netcdf_error_handler(ncstat,"put_var")
  386. endif
  387. !-----------------------------------------------------------------------
  388. ! - new grid
  389. write(6,*) 'writing grid variable'
  390. n = therank
  391. s = scale(nc_array_id)
  392. nd = 0
  393. do jd = j1,j2,dj
  394. do id =1,thedims(1)
  395. nd = nd + 1
  396. data(id,jd,1) = thegrid(nd)
  397. enddo
  398. enddo
  399. write(6,*) 'scaling data '
  400. data(:,:,1) = s*data(:,:,1)
  401. start(:) = (/ 1, 1, thelevel /)
  402. ncstat = nf90_put_var(nc_outfile_id, nc_array_id, data, start)
  403. call netcdf_error_handler(ncstat,"put_var")
  404. deallocate(data)
  405. end subroutine write_grid
  406. ! ==========================================================================
  407. subroutine write_extra(thevars, therank)
  408. real (kind=dbl_kind), dimension(:,:), intent(in) :: &
  409. thevars
  410. real (kind=dbl_kind), dimension(:), allocatable :: &
  411. thedata
  412. integer (kind=int_kind), intent(in) :: &
  413. therank
  414. real (kind=dbl_kind) :: s
  415. integer :: n
  416. allocate( thedata(size(thevars,1)) )
  417. ! - copy variable arrays
  418. write(6,*) 'writing copy variables'
  419. do n = 3,therank
  420. s = scale(nc_variable_id(n-2))
  421. thedata(:) = s*thevars(:,n-2)
  422. ncstat = nf90_put_var(nc_outfile_id, nc_variable_id(n-2), thedata)
  423. call netcdf_error_handler(ncstat,"put_var")
  424. enddo
  425. deallocate( thedata )
  426. end subroutine write_extra
  427. ! ==========================================================================
  428. subroutine close_grid()
  429. ! close netCDF file
  430. write(6,*) 'closing file'
  431. ncstat = nf90_close(nc_outfile_id)
  432. call netcdf_error_handler(ncstat,"close")
  433. end subroutine close_grid
  434. ! ==========================================================================
  435. subroutine read_mappings(nm_in)
  436. !-----------------------------------------------------------------------
  437. ! - dummy variables
  438. character (char_len) :: &
  439. nm_in ! name of input namelist file
  440. !-----------------------------------------------------------------------
  441. ! - local variables
  442. character (char_len) :: &
  443. dim_name ! netCDF dimension name
  444. integer (kind=int_kind) :: &
  445. iunit ! unit number for namelist file
  446. !-----------------------------------------------------------------------
  447. ! - namelist block
  448. namelist /interp_inputs/ input_file, interp_file, input_name, &
  449. input_stride, input_start, input_stop, &
  450. input_vars
  451. namelist /interp_outputs/ output_dims, output_file, output_mode, output_name, &
  452. output_lat, output_lon, output_ydir, &
  453. output_scaling, output_vars, output_attributes
  454. !-----------------------------------------------------------------------
  455. ! - read namelist for file and mapping info
  456. input_stride(:) = 1
  457. input_start(:) = 1
  458. input_stop(:) = 0
  459. output_scaling(:) = '-'
  460. input_vars(:) = '-'
  461. output_lon = '-'
  462. output_lat = '-'
  463. output_vars(:) = '-'
  464. output_ydir = 'none'
  465. output_attributes(:) = '-'
  466. call get_unit(iunit)
  467. open(iunit, file=nm_in, status='old', form='formatted')
  468. read(iunit, nml=interp_inputs)
  469. read(iunit, nml=interp_outputs)
  470. call release_unit(iunit)
  471. write(*,nml=interp_inputs)
  472. write(*,nml=interp_outputs)
  473. if (trim(output_mode) == "create") then
  474. if (trim(output_lon) == '-' .or. trim(output_lat) == '-') then
  475. write(6,*) 'if creating, need to supply lon and lat names'
  476. stop
  477. endif
  478. endif
  479. !-----------------------------------------------------------------------
  480. ! - read remapping data
  481. ! - via the scrip package this sets variables:
  482. ! grid1_size, grid2_size: sizes of input and output grids
  483. ! grid1_mask, grid2_mask: masks
  484. ! grid1_rank, grid2_rank: ranks
  485. call read_remap(map_name, interp_file)
  486. end subroutine read_mappings
  487. ! ==========================================================================
  488. subroutine calculate_grid(grid1_array, grid2_array)
  489. !-----------------------------------------------------------------------
  490. ! - dummy variables
  491. real (kind=dbl_kind), intent(in), dimension(:) :: &
  492. grid1_array
  493. real (kind=dbl_kind), intent(out), dimension(:) :: &
  494. grid2_array
  495. !-----------------------------------------------------------------------
  496. ! - local variables
  497. integer (kind=int_kind), dimension(:), allocatable :: &
  498. grid1_imask, grid2_imask, grid2_count
  499. real (kind=dbl_kind), dimension(:), allocatable :: &
  500. grid1_tmp, &
  501. grad1_lat, &
  502. grad1_lon, &
  503. grad1_latlon, &
  504. grad1_lat_zero, &
  505. grad1_lon_zero, &
  506. grid2_tmp1, &
  507. grid2_tmp2
  508. real (kind=dbl_kind) :: &
  509. delew, delns ! variables for computing bicub gradients
  510. integer (kind=int_kind) :: &
  511. i,j,n,imin,imax,idiff, &
  512. ip1,im1,jp1,jm1,nx,ny, & ! for computing bicub gradients
  513. in,is,ie,iw,ine,inw,ise,isw
  514. logical, parameter :: lat_gradient = .false.
  515. write(6,*) 'starting'
  516. !-----------------------------------------------------------------------
  517. ! - allocate arrays
  518. allocate (grid1_tmp (grid1_size), &
  519. grad1_lat (grid1_size), &
  520. grad1_lon (grid1_size), &
  521. grad1_lat_zero (grid1_size), &
  522. grad1_lon_zero (grid1_size), &
  523. grid1_imask (grid1_size), &
  524. grid2_tmp1 (grid2_size), &
  525. grid2_tmp2 (grid2_size), &
  526. grid2_imask (grid2_size), &
  527. grid2_count (grid2_size))
  528. write(6,*) 'allocated'
  529. write(6,*) grid1_size,grid2_size
  530. grid1_imask(:) = 1
  531. grid2_imask(:) = 1
  532. where (grid1_mask)
  533. grid1_imask = 1
  534. elsewhere
  535. grid1_imask = 0
  536. endwhere
  537. where (grid2_mask)
  538. grid2_imask = 1
  539. elsewhere
  540. grid2_imask = 0
  541. endwhere
  542. write(6,*) 'masked'
  543. grad1_lat_zero = zero
  544. grad1_lon_zero = zero
  545. nx = input_dims(1)
  546. ny = input_dims(2)
  547. write(6,*) nx,ny
  548. !-----------------------------------------------------------------------
  549. ! - if bicubic, we need 3 gradients in logical space
  550. if (map_type == map_type_bicubic) then
  551. write(6,*) 'bicubic'
  552. write(6,*) grid1_size
  553. allocate (grad1_latlon (grid1_size))
  554. do n=1,grid1_size
  555. grad1_lat(n) = zero
  556. grad1_lon(n) = zero
  557. grad1_latlon(n) = zero
  558. ! if (n.ge.8000) write(6,*) 0,grid1_mask(n),nx
  559. if (grid1_mask(n)) then
  560. delew = half
  561. delns = half
  562. j = (n-1)/nx + 1
  563. i = n - (j-1)*nx
  564. ip1 = i+1
  565. im1 = i-1
  566. jp1 = j+1
  567. jm1 = j-1
  568. if (ip1 > nx) ip1 = ip1 - nx
  569. if (im1 < 1 ) im1 = nx
  570. if (jp1 > ny) then
  571. jp1 = j
  572. delns = one
  573. endif
  574. if (jm1 < 1 ) then
  575. jm1 = j
  576. delns = one
  577. endif
  578. in = (jp1-1)*nx + i
  579. is = (jm1-1)*nx + i
  580. ie = (j -1)*nx + ip1
  581. iw = (j -1)*nx + im1
  582. ine = (jp1-1)*nx + ip1
  583. inw = (jp1-1)*nx + im1
  584. ise = (jm1-1)*nx + ip1
  585. isw = (jm1-1)*nx + im1
  586. ! - compute i-gradient
  587. if (.not. grid1_mask(ie)) then
  588. ie = n
  589. delew = one
  590. endif
  591. if (.not. grid1_mask(iw)) then
  592. iw = n
  593. delew = one
  594. endif
  595. grad1_lat(n) = delew*(grid1_array(ie) - grid1_array(iw))
  596. ! if (n.ge.8000) write(6,*) 1,grad1_lat(n)
  597. ! - compute j-gradient
  598. if (.not. grid1_mask(in)) then
  599. in = n
  600. delns = one
  601. endif
  602. if (.not. grid1_mask(is)) then
  603. is = n
  604. delns = one
  605. endif
  606. grad1_lon(n) = delns*(grid1_array(in) - grid1_array(is))
  607. ! if (n.ge.8000) write(6,*) 2,grad1_lon(n)
  608. ! - compute ij-gradient
  609. delew = half
  610. if (jp1 == j .or. jm1 == j) then
  611. delns = one
  612. else
  613. delns = half
  614. endif
  615. if (.not. grid1_mask(ine)) then
  616. if (in /= n) then
  617. ine = in
  618. delew = one
  619. else if (ie /= n) then
  620. ine = ie
  621. inw = iw
  622. if (inw == n) delew = one
  623. delns = one
  624. else
  625. ine = n
  626. inw = iw
  627. delew = one
  628. delns = one
  629. endif
  630. endif
  631. if (.not. grid1_mask(inw)) then
  632. if (in /= n) then
  633. inw = in
  634. delew = one
  635. else if (iw /= n) then
  636. inw = iw
  637. ine = ie
  638. if (ie == n) delew = one
  639. delns = one
  640. else
  641. inw = n
  642. ine = ie
  643. delew = one
  644. delns = one
  645. endif
  646. endif
  647. grad1_lat_zero(n) = delew*(grid1_array(ine) - grid1_array(inw))
  648. ! if (n.ge.8000) write(6,*) 3,grad1_lat_zero(n)
  649. if (.not. grid1_mask(ise)) then
  650. if (is /= n) then
  651. ise = is
  652. delew = one
  653. else if (ie /= n) then
  654. ise = ie
  655. isw = iw
  656. if (isw == n) delew = one
  657. delns = one
  658. else
  659. ise = n
  660. isw = iw
  661. delew = one
  662. delns = one
  663. endif
  664. endif
  665. if (.not. grid1_mask(isw)) then
  666. if (is /= n) then
  667. isw = is
  668. delew = one
  669. else if (iw /= n) then
  670. isw = iw
  671. ise = ie
  672. if (ie == n) delew = one
  673. delns = one
  674. else
  675. isw = n
  676. ise = ie
  677. delew = one
  678. delns = one
  679. endif
  680. endif
  681. grad1_lon_zero(n) = delew*(grid1_array(ise) - grid1_array(isw))
  682. grad1_latlon(n) = delns*(grad1_lat_zero(n) - grad1_lon_zero(n))
  683. ! if (n.ge.8000) write(6,*) 4,grad1_lon_zero(n),grad1_latlon(n)
  684. endif
  685. enddo
  686. write(6,*) 'remapping'
  687. call remap(grid2_array, wts_map1, grid2_add_map1, grid1_add_map1, &
  688. grid1_array, src_grad1=grad1_lat, &
  689. src_grad2=grad1_lon, src_grad3=grad1_latlon)
  690. print *,'Third order mapping from grid1 to grid2:'
  691. print *,'----------------------------------------'
  692. print *,'Grid1 min,max: ',minval(grid1_array),maxval(grid1_array)
  693. print *,'Grid2 min,max: ',minval(grid2_array ),maxval(grid2_array )
  694. ! - Conservation Test
  695. print *,'Conservation:'
  696. print *,'Grid1 Integral = ',sum(grid1_array*grid1_area*grid1_frac)
  697. print *,'Grid2 Integral = ',sum(grid2_array *grid2_area*grid2_frac)
  698. !-----------------------------------------------------------------------
  699. ! - a first-order map from grid1 to grid2
  700. else if (map_type /= map_type_conserv .AND.map_type /= map_type_bicubic) then
  701. write(6,*) 'bilinear or conservative'
  702. call remap(grid2_array, wts_map1, grid2_add_map1, grid1_add_map1,grid1_array)
  703. print *,'First order mapping from grid1 to grid2:'
  704. print *,'----------------------------------------'
  705. print *,'Grid1 min,max: ',minval(grid1_array),maxval(grid1_array)
  706. print *,'Grid2 min,max: ',minval(grid2_array ),maxval(grid2_array )
  707. ! - Conservation Test
  708. print *,'Conservation:'
  709. print *,'Grid1 Integral = ',sum(grid1_array*grid1_area*grid1_frac)
  710. print *,'Grid2 Integral = ',sum(grid2_array *grid2_area*grid2_frac)
  711. !-----------------------------------------------------------------------
  712. ! - conservative mappings:
  713. ! - a second-order map from grid1 to grid2 with only lat grads
  714. else if (map_type == map_type_conserv .AND. lat_gradient) then
  715. call remap(grid2_array, wts_map1, grid2_add_map1, grid1_add_map1, &
  716. grid1_array, src_grad1=grad1_lat,src_grad2=grad1_lon_zero)
  717. select case (norm_opt)
  718. case (norm_opt_none)
  719. grid2_tmp2 = grid2_frac*grid2_area
  720. where (grid2_tmp2 /= zero)
  721. grid2_array = grid2_array/grid2_tmp2
  722. elsewhere
  723. grid2_array = zero
  724. end where
  725. case (norm_opt_frcarea)
  726. case (norm_opt_dstarea)
  727. where (grid2_frac /= zero)
  728. grid2_array = grid2_array/grid2_frac
  729. elsewhere
  730. grid2_array = zero
  731. end where
  732. end select
  733. print *,'Second order mapping from grid1 to grid2 (lat only):'
  734. print *,'----------------------------------------'
  735. print *,'Grid1 min,max: ',minval(grid1_array),maxval(grid1_array)
  736. print *,'Grid2 min,max: ',minval(grid2_array ),maxval(grid2_array )
  737. ! - Conservation Test
  738. print *,'Conservation:'
  739. print *,'Grid1 Integral = ',sum(grid1_array*grid1_area*grid1_frac)
  740. print *,'Grid2 Integral = ',sum(grid2_array*grid2_area*grid2_frac)
  741. !-----------------------------------------------------------------------
  742. ! - conservative mappings:
  743. ! - a second-order map from grid1 to grid2 both gradients
  744. else if (map_type == map_type_conserv .AND..NOT. lat_gradient) then
  745. call remap(grid2_array,wts_map1,grid2_add_map1,grid1_add_map1, &
  746. grid1_array, src_grad1=grad1_lat,src_grad2=grad1_lon)
  747. select case (norm_opt)
  748. case (norm_opt_none)
  749. grid2_tmp2 = grid2_frac*grid2_area
  750. where (grid2_tmp2 /= zero)
  751. grid2_array = grid2_array/grid2_tmp2
  752. elsewhere
  753. grid2_array = zero
  754. end where
  755. case (norm_opt_frcarea)
  756. case (norm_opt_dstarea)
  757. where (grid2_frac /= zero)
  758. grid2_array = grid2_array/grid2_frac
  759. elsewhere
  760. grid2_array = zero
  761. end where
  762. end select
  763. print *,'Second order mapping from grid1 to grid2:'
  764. print *,'-----------------------------------------'
  765. print *,'Grid1 min,max: ',minval(grid1_array),maxval(grid1_array)
  766. print *,'Grid2 min,max: ',minval(grid2_array ),maxval(grid2_array )
  767. ! - Conservation Test
  768. print *,'Conservation:'
  769. print *,'Grid1 Integral = ',sum(grid1_array*grid1_area*grid1_frac)
  770. print *,'Grid2 Integral = ',sum(grid2_array*grid2_area*grid2_frac)
  771. endif
  772. !-----------------------------------------------------------------------
  773. ! calculate some statistics
  774. grid2_count = zero
  775. grid2_tmp1 = zero
  776. grid2_tmp2 = zero
  777. print *,'number of sparse matrix entries ',num_links_map1
  778. do n=1,num_links_map1
  779. grid2_count(grid2_add_map1(n)) = grid2_count(grid2_add_map1(n)) + 1
  780. if (wts_map1(1,n) > one .or. wts_map1(1,n) < zero) then
  781. grid2_tmp1(grid2_add_map1(n)) = grid2_tmp1(grid2_add_map1(n)) + 1
  782. grid2_tmp2(grid2_add_map1(n)) = max(abs(wts_map1(1,n)),grid2_tmp2(grid2_add_map1(n)) )
  783. endif
  784. end do
  785. do n=1,grid2_size
  786. if (grid2_tmp1(n) > zero) print *,n,grid2_tmp2(n)
  787. end do
  788. imin = minval(grid2_count, mask=(grid2_count > 0))
  789. imax = maxval(grid2_count)
  790. idiff = (imax - imin)/10 + 1
  791. print *,'total number of dest cells ',grid2_size
  792. print *,'number of cells participating in remap ',count(grid2_count > zero)
  793. print *,'min no of entries/row = ',imin
  794. print *,'max no of entries/row = ',imax
  795. imax = imin + idiff
  796. do n=1,10
  797. print *,'num of rows with entries between ',imin,' - ',imax-1, &
  798. count(grid2_count >= imin .and. grid2_count < imax)
  799. imin = imin + idiff
  800. imax = imax + idiff
  801. end do
  802. !-----------------------------------------------------------------------
  803. ! - deallocate arrays
  804. deallocate (grid1_tmp, grad1_lat, grad1_lon, &
  805. grad1_lat_zero, grad1_lon_zero, grid1_imask, &
  806. grid2_tmp1, grid2_tmp2, &
  807. grid2_imask, grid2_count)
  808. end subroutine calculate_grid
  809. ! ==========================================================================
  810. end module scripinterp_mod