PageRenderTime 68ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/WPS/metgrid/src/process_domain_module.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 2839 lines | 1753 code | 456 blank | 630 comment | 397 complexity | 2d29f8bcd4bc0d9d1f57c097777cb2a6 MD5 | raw file
Possible License(s): AGPL-1.0
  1. module process_domain_module
  2. contains
  3. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  4. ! Name: process_domain
  5. !
  6. ! Purpose:
  7. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  8. subroutine process_domain(n, extra_row, extra_col)
  9. use date_pack
  10. use gridinfo_module
  11. use interp_option_module
  12. use misc_definitions_module
  13. use module_debug
  14. use storage_module
  15. implicit none
  16. ! Arguments
  17. integer, intent(in) :: n
  18. logical, intent(in) :: extra_row, extra_col
  19. ! Local variables
  20. integer :: i, t, dyn_opt, &
  21. we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
  22. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  23. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  24. we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
  25. sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  26. idiff, n_times, &
  27. west_east_dim, south_north_dim, bottom_top_dim, map_proj, &
  28. is_water, is_lake, is_ice, is_urban, i_soilwater, &
  29. grid_id, parent_id, i_parent_start, j_parent_start, &
  30. i_parent_end, j_parent_end, parent_grid_ratio, sub_x, sub_y, num_land_cat, process_bdy_width
  31. real :: cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  32. dom_dx, dom_dy, pole_lat, pole_lon
  33. real, dimension(16) :: corner_lats, corner_lons
  34. real, pointer, dimension(:,:) :: landmask
  35. real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
  36. logical, allocatable, dimension(:) :: got_this_field, got_const_field
  37. character (len=19) :: valid_date, temp_date
  38. character (len=128) :: title, mminlu
  39. character (len=128), allocatable, dimension(:) :: output_flags, td_output_flags
  40. ! Compute number of times that we will process
  41. call geth_idts(end_date(n), start_date(n), idiff)
  42. call mprintf((idiff < 0),ERROR,'Ending date is earlier than starting date in namelist for domain %i.', i1=n)
  43. n_times = idiff / interval_seconds
  44. ! Check that the interval evenly divides the range of times to process
  45. call mprintf((mod(idiff, interval_seconds) /= 0),WARN, &
  46. 'In namelist, interval_seconds does not evenly divide '// &
  47. '(end_date - start_date) for domain %i. Only %i time periods '// &
  48. 'will be processed.', i1=n, i2=n_times)
  49. ! Initialize the storage module
  50. call mprintf(.true.,LOGFILE,'Initializing storage module')
  51. call storage_init()
  52. !
  53. ! Do time-independent processing
  54. !
  55. call get_static_fields(n, dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, map_proj, &
  56. we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
  57. we_patch_s, we_patch_e, &
  58. we_patch_stag_s, we_patch_stag_e, &
  59. sn_patch_s, sn_patch_e, &
  60. sn_patch_stag_s, sn_patch_stag_e, &
  61. we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
  62. sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  63. mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
  64. grid_id, parent_id, &
  65. i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
  66. parent_grid_ratio, sub_x, sub_y, &
  67. cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  68. pole_lat, pole_lon, dom_dx, dom_dy, landmask, xlat, xlon, xlat_u, xlon_u, &
  69. xlat_v, xlon_v, corner_lats, corner_lons, title)
  70. allocate(output_flags(num_entries))
  71. allocate(got_const_field(num_entries))
  72. do i=1,num_entries
  73. output_flags(i) = ' '
  74. got_const_field(i) = .false.
  75. end do
  76. ! This call is to process the constant met fields (SST or SEAICE, for example)
  77. ! That we process constant fields is indicated by the first argument
  78. call process_single_met_time(.true., temp_date, n, extra_row, extra_col, xlat, xlon, &
  79. xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
  80. title, dyn_opt, &
  81. west_east_dim, south_north_dim, &
  82. we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
  83. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  84. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  85. we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
  86. sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  87. got_const_field, &
  88. map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
  89. grid_id, parent_id, i_parent_start, &
  90. j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
  91. cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  92. pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
  93. corner_lats, corner_lons, output_flags, 0)
  94. !
  95. ! Begin time-dependent processing
  96. !
  97. allocate(td_output_flags(num_entries))
  98. allocate(got_this_field (num_entries))
  99. ! Loop over all times to be processed for this domain
  100. do t=0,n_times
  101. call geth_newdate(valid_date, trim(start_date(n)), t*interval_seconds)
  102. temp_date = ' '
  103. if (mod(interval_seconds,3600) == 0) then
  104. write(temp_date,'(a13)') valid_date(1:10)//'_'//valid_date(12:13)
  105. else if (mod(interval_seconds,60) == 0) then
  106. write(temp_date,'(a16)') valid_date(1:10)//'_'//valid_date(12:16)
  107. else
  108. write(temp_date,'(a19)') valid_date(1:10)//'_'//valid_date(12:19)
  109. end if
  110. call mprintf(.true.,STDOUT, ' Processing %s', s1=trim(temp_date))
  111. call mprintf(.true.,LOGFILE, 'Preparing to process output time %s', s1=temp_date)
  112. do i=1,num_entries
  113. td_output_flags(i) = output_flags(i)
  114. got_this_field(i) = got_const_field(i)
  115. end do
  116. if (t > 0) then
  117. process_bdy_width = process_only_bdy
  118. else
  119. process_bdy_width = 0
  120. end if
  121. call process_single_met_time(.false., temp_date, n, extra_row, extra_col, xlat, xlon, &
  122. xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
  123. title, dyn_opt, &
  124. west_east_dim, south_north_dim, &
  125. we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
  126. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  127. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  128. we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
  129. sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  130. got_this_field, &
  131. map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
  132. grid_id, parent_id, i_parent_start, &
  133. j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
  134. cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  135. pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
  136. corner_lats, corner_lons, td_output_flags, process_bdy_width)
  137. end do ! Loop over n_times
  138. deallocate(td_output_flags)
  139. deallocate(got_this_field)
  140. deallocate(output_flags)
  141. deallocate(got_const_field)
  142. call storage_delete_all()
  143. end subroutine process_domain
  144. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  145. ! Name: get_static_fields
  146. !
  147. ! Purpose:
  148. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  149. subroutine get_static_fields(n, dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, &
  150. map_proj, &
  151. we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
  152. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  153. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  154. we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
  155. sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  156. mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
  157. grid_id, parent_id, &
  158. i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
  159. parent_grid_ratio, sub_x, sub_y, &
  160. cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  161. pole_lat, pole_lon, dom_dx, dom_dy, landmask, xlat, xlon, xlat_u, xlon_u, &
  162. xlat_v, xlon_v, corner_lats, corner_lons, title)
  163. use gridinfo_module
  164. use input_module
  165. use llxy_module
  166. use parallel_module
  167. use storage_module
  168. use module_debug
  169. implicit none
  170. ! Arguments
  171. integer, intent(in) :: n
  172. integer, intent(inout) :: dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, &
  173. map_proj, &
  174. we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
  175. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  176. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  177. we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
  178. sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  179. is_water, is_lake, is_ice, is_urban, i_soilwater, grid_id, parent_id, &
  180. i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
  181. parent_grid_ratio, sub_x, sub_y, num_land_cat
  182. real, pointer, dimension(:,:) :: landmask
  183. real, intent(inout) :: cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  184. dom_dx, dom_dy, pole_lat, pole_lon
  185. real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
  186. real, dimension(16), intent(out) :: corner_lats, corner_lons
  187. character (len=128), intent(inout) :: title, mminlu
  188. ! Local variables
  189. integer :: istatus, i, j, k, sp1, ep1, sp2, ep2, sp3, ep3, &
  190. lh_mult, rh_mult, bh_mult, th_mult
  191. integer :: we_mem_subgrid_s, we_mem_subgrid_e, &
  192. sn_mem_subgrid_s, sn_mem_subgrid_e
  193. integer :: we_patch_subgrid_s, we_patch_subgrid_e, &
  194. sn_patch_subgrid_s, sn_patch_subgrid_e
  195. real, pointer, dimension(:,:,:) :: real_array
  196. character (len=3) :: memorder
  197. character (len=128) :: grid_type, datestr, cname, stagger, cunits, cdesc
  198. character (len=128), dimension(3) :: dimnames
  199. type (fg_input) :: field
  200. logical :: is_subgrid
  201. ! Initialize the input module to read static input data for this domain
  202. call mprintf(.true.,LOGFILE,'Opening static input file.')
  203. call input_init(n, istatus)
  204. call mprintf((istatus /= 0),ERROR, 'input_init(): Error opening input for domain %i.', i1=n)
  205. ! Read global attributes from the static data input file
  206. call mprintf(.true.,LOGFILE,'Reading static global attributes.')
  207. call read_global_attrs(title, datestr, grid_type, dyn_opt, west_east_dim, &
  208. south_north_dim, bottom_top_dim, &
  209. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  210. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  211. map_proj, mminlu, num_land_cat, &
  212. is_water, is_lake, is_ice, is_urban, i_soilwater, &
  213. grid_id, parent_id, i_parent_start, &
  214. j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
  215. cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, &
  216. truelat2, pole_lat, pole_lon, parent_grid_ratio, &
  217. corner_lats, corner_lons, sub_x, sub_y)
  218. we_dom_s = 1
  219. sn_dom_s = 1
  220. if (grid_type(1:1) == 'C') then
  221. we_dom_e = west_east_dim - 1
  222. sn_dom_e = south_north_dim - 1
  223. else if (grid_type(1:1) == 'E') then
  224. we_dom_e = west_east_dim
  225. sn_dom_e = south_north_dim
  226. end if
  227. ! Given the full dimensions of this domain, find out the range of indices
  228. ! that will be worked on by this processor. This information is given by
  229. ! my_minx, my_miny, my_maxx, my_maxy
  230. call parallel_get_tile_dims(west_east_dim, south_north_dim)
  231. ! Must figure out patch dimensions from info in parallel module
  232. if (nprocs > 1 .and. .not. do_tiled_input) then
  233. we_patch_s = my_minx
  234. we_patch_stag_s = my_minx
  235. we_patch_e = my_maxx - 1
  236. sn_patch_s = my_miny
  237. sn_patch_stag_s = my_miny
  238. sn_patch_e = my_maxy - 1
  239. if (gridtype == 'C') then
  240. if (my_x /= nproc_x - 1) then
  241. we_patch_e = we_patch_e + 1
  242. we_patch_stag_e = we_patch_e
  243. else
  244. we_patch_stag_e = we_patch_e + 1
  245. end if
  246. if (my_y /= nproc_y - 1) then
  247. sn_patch_e = sn_patch_e + 1
  248. sn_patch_stag_e = sn_patch_e
  249. else
  250. sn_patch_stag_e = sn_patch_e + 1
  251. end if
  252. else if (gridtype == 'E') then
  253. we_patch_e = we_patch_e + 1
  254. sn_patch_e = sn_patch_e + 1
  255. we_patch_stag_e = we_patch_e
  256. sn_patch_stag_e = sn_patch_e
  257. end if
  258. end if
  259. ! Compute multipliers for halo width; these must be 0/1
  260. if (my_x /= 0) then
  261. lh_mult = 1
  262. else
  263. lh_mult = 0
  264. end if
  265. if (my_x /= (nproc_x-1)) then
  266. rh_mult = 1
  267. else
  268. rh_mult = 0
  269. end if
  270. if (my_y /= 0) then
  271. bh_mult = 1
  272. else
  273. bh_mult = 0
  274. end if
  275. if (my_y /= (nproc_y-1)) then
  276. th_mult = 1
  277. else
  278. th_mult = 0
  279. end if
  280. we_mem_s = we_patch_s - HALO_WIDTH*lh_mult
  281. we_mem_e = we_patch_e + HALO_WIDTH*rh_mult
  282. sn_mem_s = sn_patch_s - HALO_WIDTH*bh_mult
  283. sn_mem_e = sn_patch_e + HALO_WIDTH*th_mult
  284. we_mem_stag_s = we_patch_stag_s - HALO_WIDTH*lh_mult
  285. we_mem_stag_e = we_patch_stag_e + HALO_WIDTH*rh_mult
  286. sn_mem_stag_s = sn_patch_stag_s - HALO_WIDTH*bh_mult
  287. sn_mem_stag_e = sn_patch_stag_e + HALO_WIDTH*th_mult
  288. ! Initialize a proj_info type for the destination grid projection. This will
  289. ! primarily be used for rotating Earth-relative winds to grid-relative winds
  290. call set_domain_projection(map_proj, stand_lon, truelat1, truelat2, &
  291. dom_dx, dom_dy, dom_dx, dom_dy, west_east_dim, &
  292. south_north_dim, real(west_east_dim)/2., &
  293. real(south_north_dim)/2.,cen_lat, cen_lon, &
  294. cen_lat, cen_lon)
  295. ! Read static fields using the input module; we know that there are no more
  296. ! fields to be read when read_next_field() returns a non-zero status.
  297. istatus = 0
  298. do while (istatus == 0)
  299. call read_next_field(sp1, ep1, sp2, ep2, sp3, ep3, cname, cunits, cdesc, &
  300. memorder, stagger, dimnames, is_subgrid, &
  301. real_array, istatus)
  302. if (istatus == 0) then
  303. call mprintf(.true.,LOGFILE, 'Read in static field %s.',s1=cname)
  304. ! We will also keep copies in core of the lat/lon arrays, for use in
  305. ! interpolation of the met fields to the model grid.
  306. ! For now, we assume that the lat/lon arrays will have known field names
  307. if (index(cname, 'XLAT_M') /= 0 .and. &
  308. len_trim(cname) == len_trim('XLAT_M')) then
  309. allocate(xlat(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
  310. xlat(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
  311. call exchange_halo_r(xlat, &
  312. we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
  313. we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
  314. else if (index(cname, 'XLONG_M') /= 0 .and. &
  315. len_trim(cname) == len_trim('XLONG_M')) then
  316. allocate(xlon(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
  317. xlon(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
  318. call exchange_halo_r(xlon, &
  319. we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
  320. we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
  321. else if (index(cname, 'XLAT_U') /= 0 .and. &
  322. len_trim(cname) == len_trim('XLAT_U')) then
  323. allocate(xlat_u(we_mem_stag_s:we_mem_stag_e,sn_mem_s:sn_mem_e))
  324. xlat_u(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
  325. call exchange_halo_r(xlat_u, &
  326. we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
  327. we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
  328. else if (index(cname, 'XLONG_U') /= 0 .and. &
  329. len_trim(cname) == len_trim('XLONG_U')) then
  330. allocate(xlon_u(we_mem_stag_s:we_mem_stag_e,sn_mem_s:sn_mem_e))
  331. xlon_u(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
  332. call exchange_halo_r(xlon_u, &
  333. we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
  334. we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
  335. else if (index(cname, 'XLAT_V') /= 0 .and. &
  336. len_trim(cname) == len_trim('XLAT_V')) then
  337. allocate(xlat_v(we_mem_s:we_mem_e,sn_mem_stag_s:sn_mem_stag_e))
  338. xlat_v(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(:,:,1)
  339. call exchange_halo_r(xlat_v, &
  340. we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
  341. we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
  342. else if (index(cname, 'XLONG_V') /= 0 .and. &
  343. len_trim(cname) == len_trim('XLONG_V')) then
  344. allocate(xlon_v(we_mem_s:we_mem_e,sn_mem_stag_s:sn_mem_stag_e))
  345. xlon_v(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(:,:,1)
  346. call exchange_halo_r(xlon_v, &
  347. we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
  348. we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
  349. else if (index(cname, 'LANDMASK') /= 0 .and. &
  350. len_trim(cname) == len_trim('LANDMASK')) then
  351. allocate(landmask(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
  352. landmask(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
  353. call exchange_halo_r(landmask, &
  354. we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
  355. we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
  356. end if
  357. we_mem_subgrid_s = (we_mem_s + HALO_WIDTH*lh_mult - 1)*sub_x - HALO_WIDTH*lh_mult + 1
  358. we_mem_subgrid_e = (we_mem_e + (1-rh_mult) - HALO_WIDTH*rh_mult )*sub_x + HALO_WIDTH*rh_mult
  359. we_patch_subgrid_s = (we_patch_s - 1)*sub_x + 1
  360. we_patch_subgrid_e = (we_patch_e + (1-rh_mult) )*sub_x
  361. sn_mem_subgrid_s = (sn_mem_s + HALO_WIDTH*bh_mult - 1)*sub_y - HALO_WIDTH*bh_mult + 1
  362. sn_mem_subgrid_e = (sn_mem_e + (1-th_mult) - HALO_WIDTH*th_mult )*sub_y + HALO_WIDTH*th_mult
  363. sn_patch_subgrid_s = (sn_patch_s - 1)*sub_y + 1
  364. sn_patch_subgrid_e = (sn_patch_e + (1-th_mult) )*sub_y
  365. ! Having read in a field, we write each level individually to the
  366. ! storage module; levels will be reassembled later on when they
  367. ! are written.
  368. do k=sp3,ep3
  369. field%header%sr_x=sub_x
  370. field%header%sr_y=sub_y
  371. field%header%is_subgrid=is_subgrid
  372. field%header%version = 1
  373. field%header%date = start_date(n)
  374. field%header%time_dependent = .false.
  375. field%header%mask_field = .false.
  376. field%header%forecast_hour = 0.0
  377. field%header%fg_source = 'geogrid_model'
  378. field%header%field = cname
  379. field%header%units = cunits
  380. field%header%description = cdesc
  381. field%header%vertical_coord = dimnames(3)
  382. field%header%vertical_level = k
  383. field%header%array_order = memorder
  384. field%header%is_wind_grid_rel = .true.
  385. field%header%array_has_missing_values = .false.
  386. if (gridtype == 'C') then
  387. if (is_subgrid) then
  388. field%map%stagger = M
  389. field%header%dim1(1) = we_mem_subgrid_s
  390. field%header%dim1(2) = we_mem_subgrid_e
  391. field%header%dim2(1) = sn_mem_subgrid_s
  392. field%header%dim2(2) = sn_mem_subgrid_e
  393. else if (trim(stagger) == 'M') then
  394. field%map%stagger = M
  395. field%header%dim1(1) = we_mem_s
  396. field%header%dim1(2) = we_mem_e
  397. field%header%dim2(1) = sn_mem_s
  398. field%header%dim2(2) = sn_mem_e
  399. else if (trim(stagger) == 'U') then
  400. field%map%stagger = U
  401. field%header%dim1(1) = we_mem_stag_s
  402. field%header%dim1(2) = we_mem_stag_e
  403. field%header%dim2(1) = sn_mem_s
  404. field%header%dim2(2) = sn_mem_e
  405. else if (trim(stagger) == 'V') then
  406. field%map%stagger = V
  407. field%header%dim1(1) = we_mem_s
  408. field%header%dim1(2) = we_mem_e
  409. field%header%dim2(1) = sn_mem_stag_s
  410. field%header%dim2(2) = sn_mem_stag_e
  411. end if
  412. else if (gridtype == 'E') then
  413. if (trim(stagger) == 'M') then
  414. field%map%stagger = HH
  415. else if (trim(stagger) == 'V') then
  416. field%map%stagger = VV
  417. end if
  418. field%header%dim1(1) = we_mem_s
  419. field%header%dim1(2) = we_mem_e
  420. field%header%dim2(1) = sn_mem_s
  421. field%header%dim2(2) = sn_mem_e
  422. end if
  423. allocate(field%valid_mask)
  424. if (is_subgrid) then
  425. allocate(field%r_arr(we_mem_subgrid_s:we_mem_subgrid_e,&
  426. sn_mem_subgrid_s:sn_mem_subgrid_e))
  427. field%r_arr(we_patch_subgrid_s:we_patch_subgrid_e,sn_patch_subgrid_s:sn_patch_subgrid_e) = &
  428. real_array(sp1:ep1,sp2:ep2,k)
  429. call exchange_halo_r(field%r_arr, &
  430. we_mem_subgrid_s, we_mem_subgrid_e, sn_mem_subgrid_s, sn_mem_subgrid_e, 1, 1, &
  431. we_patch_subgrid_s, we_patch_subgrid_e, sn_patch_subgrid_s, sn_patch_subgrid_e, 1, 1)
  432. call bitarray_create(field%valid_mask, &
  433. (we_mem_subgrid_e-we_mem_subgrid_s)+1, &
  434. (sn_mem_subgrid_e-sn_mem_subgrid_s)+1)
  435. do j=1,(sn_mem_subgrid_e-sn_mem_subgrid_s)+1
  436. do i=1,(we_mem_subgrid_e-we_mem_subgrid_s)+1
  437. call bitarray_set(field%valid_mask, i, j)
  438. end do
  439. end do
  440. else if (field%map%stagger == M .or. &
  441. field%map%stagger == HH .or. &
  442. field%map%stagger == VV) then
  443. allocate(field%r_arr(we_mem_s:we_mem_e,&
  444. sn_mem_s:sn_mem_e))
  445. field%r_arr(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(sp1:ep1,sp2:ep2,k)
  446. call exchange_halo_r(field%r_arr, &
  447. we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
  448. we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
  449. call bitarray_create(field%valid_mask, &
  450. (we_mem_e-we_mem_s)+1, &
  451. (sn_mem_e-sn_mem_s)+1)
  452. do j=1,(sn_mem_e-sn_mem_s)+1
  453. do i=1,(we_mem_e-we_mem_s)+1
  454. call bitarray_set(field%valid_mask, i, j)
  455. end do
  456. end do
  457. else if (field%map%stagger == U) then
  458. allocate(field%r_arr(we_mem_stag_s:we_mem_stag_e,&
  459. sn_mem_s:sn_mem_e))
  460. field%r_arr(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(sp1:ep1,sp2:ep2,k)
  461. call exchange_halo_r(field%r_arr, &
  462. we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
  463. we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
  464. call bitarray_create(field%valid_mask, &
  465. (we_mem_stag_e-we_mem_stag_s)+1, &
  466. (sn_mem_e-sn_mem_s)+1)
  467. do j=1,(sn_mem_e-sn_mem_s)+1
  468. do i=1,(we_mem_stag_e-we_mem_stag_s)+1
  469. call bitarray_set(field%valid_mask, i, j)
  470. end do
  471. end do
  472. else if (field%map%stagger == V) then
  473. allocate(field%r_arr(we_mem_s:we_mem_e,&
  474. sn_mem_stag_s:sn_mem_stag_e))
  475. field%r_arr(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(sp1:ep1,sp2:ep2,k)
  476. call exchange_halo_r(field%r_arr, &
  477. we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
  478. we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
  479. call bitarray_create(field%valid_mask, &
  480. (we_mem_e-we_mem_s)+1, &
  481. (sn_mem_stag_e-sn_mem_stag_s)+1)
  482. do j=1,(sn_mem_stag_e-sn_mem_stag_s)+1
  483. do i=1,(we_mem_e-we_mem_s)+1
  484. call bitarray_set(field%valid_mask, i, j)
  485. end do
  486. end do
  487. end if
  488. nullify(field%modified_mask)
  489. call storage_put_field(field)
  490. end do
  491. end if
  492. end do
  493. ! Done reading all static fields for this domain
  494. call input_close()
  495. end subroutine get_static_fields
  496. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  497. ! Name: process_single_met_time
  498. !
  499. ! Purpose:
  500. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  501. subroutine process_single_met_time(do_const_processing, &
  502. temp_date, n, extra_row, extra_col, xlat, xlon, &
  503. xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
  504. title, dyn_opt, &
  505. west_east_dim, south_north_dim, &
  506. we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
  507. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  508. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  509. we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
  510. sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  511. got_this_field, &
  512. map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
  513. grid_id, parent_id, i_parent_start, &
  514. j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
  515. cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  516. pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
  517. corner_lats, corner_lons, output_flags, process_bdy_width)
  518. use bitarray_module
  519. use gridinfo_module
  520. use interp_module
  521. use interp_option_module
  522. use llxy_module
  523. use misc_definitions_module
  524. use module_debug
  525. use output_module
  526. use parallel_module
  527. use read_met_module
  528. use rotate_winds_module
  529. use storage_module
  530. implicit none
  531. ! Arguments
  532. logical, intent(in) :: do_const_processing
  533. integer, intent(in) :: n, dyn_opt, west_east_dim, south_north_dim, map_proj, &
  534. we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
  535. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  536. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  537. we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
  538. sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  539. is_water, is_lake, is_ice, is_urban, i_soilwater, &
  540. grid_id, parent_id, i_parent_start, j_parent_start, &
  541. i_parent_end, j_parent_end, parent_grid_ratio, sub_x, sub_y, num_land_cat, &
  542. process_bdy_width
  543. ! BUG: Should we be passing these around as pointers, or just declare them as arrays?
  544. real, pointer, dimension(:,:) :: landmask
  545. real, intent(in) :: dom_dx, dom_dy, cen_lat, moad_cen_lat, cen_lon, stand_lon, &
  546. truelat1, truelat2, pole_lat, pole_lon
  547. real, dimension(16), intent(in) :: corner_lats, corner_lons
  548. real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
  549. logical, intent(in) :: extra_row, extra_col
  550. logical, dimension(:), intent(inout) :: got_this_field
  551. character (len=19), intent(in) :: temp_date
  552. character (len=128), intent(in) :: mminlu
  553. character (len=128), dimension(:), intent(inout) :: output_flags
  554. ! BUG: Move this constant to misc_definitions_module?
  555. integer, parameter :: BDR_WIDTH = 3
  556. ! Local variables
  557. integer :: istatus, iqstatus, fg_idx, idx, idxt, i, j, bottom_top_dim, &
  558. sm1, em1, sm2, em2, sm3, em3, &
  559. sp1, ep1, sp2, ep2, sp3, ep3, &
  560. sd1, ed1, sd2, ed2, sd3, ed3, &
  561. u_idx, bdr_wdth
  562. integer :: nmet_flags
  563. integer :: num_metgrid_soil_levs
  564. integer, pointer, dimension(:) :: soil_levels
  565. real :: rx, ry
  566. real :: threshold
  567. logical :: do_gcell_interp
  568. integer, pointer, dimension(:) :: u_levels, v_levels
  569. real, pointer, dimension(:,:) :: halo_slab
  570. real, pointer, dimension(:,:,:) :: real_array
  571. character (len=19) :: output_date
  572. character (len=128) :: cname, title
  573. character (len=MAX_FILENAME_LEN) :: input_name
  574. character (len=128), allocatable, dimension(:) :: met_flags
  575. type (fg_input) :: field, u_field, v_field
  576. type (met_data) :: fg_data
  577. ! For this time, we need to process all first-guess filename roots. When we
  578. ! hit a root containing a '*', we assume we have hit the end of the list
  579. fg_idx = 1
  580. if (do_const_processing) then
  581. input_name = constants_name(fg_idx)
  582. else
  583. input_name = fg_name(fg_idx)
  584. end if
  585. do while (input_name /= '*')
  586. call mprintf(.true.,STDOUT, ' %s', s1=input_name)
  587. call mprintf(.true.,LOGFILE, 'Getting input fields from %s', s1=input_name)
  588. ! Do a first pass through this fg source to get all mask fields used
  589. ! during interpolation
  590. call get_interp_masks(trim(input_name), do_const_processing, temp_date)
  591. istatus = 0
  592. ! Initialize the module for reading in the met fields
  593. call read_met_init(trim(input_name), do_const_processing, temp_date, istatus)
  594. if (istatus == 0) then
  595. ! Process all fields and levels from the current file; read_next_met_field()
  596. ! will return a non-zero status when there are no more fields to be read.
  597. do while (istatus == 0)
  598. call read_next_met_field(fg_data, istatus)
  599. if (istatus == 0) then
  600. ! Find index into fieldname, interp_method, masked, and fill_missing
  601. ! of the current field
  602. idxt = num_entries + 1
  603. do idx=1,num_entries
  604. if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
  605. (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
  606. got_this_field(idx) = .true.
  607. if (index(input_name,trim(from_input(idx))) /= 0 .or. &
  608. (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
  609. idxt = idx
  610. end if
  611. end if
  612. end do
  613. idx = idxt
  614. if (idx > num_entries) idx = num_entries ! The last entry is a default
  615. ! Do we need to rename this field?
  616. if (output_name(idx) /= ' ') then
  617. fg_data%field = output_name(idx)(1:9)
  618. idxt = num_entries + 1
  619. do idx=1,num_entries
  620. if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
  621. (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
  622. got_this_field(idx) = .true.
  623. if (index(input_name,trim(from_input(idx))) /= 0 .or. &
  624. (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
  625. idxt = idx
  626. end if
  627. end if
  628. end do
  629. idx = idxt
  630. if (idx > num_entries) idx = num_entries ! The last entry is a default
  631. end if
  632. ! Do a simple check to see whether this is a global dataset
  633. ! Note that we do not currently support regional Gaussian grids
  634. if ((fg_data%iproj == PROJ_LATLON .and. abs(fg_data%nx * fg_data%deltalon - 360.) < 0.0001) &
  635. .or. (fg_data%iproj == PROJ_GAUSS)) then
  636. bdr_wdth = BDR_WIDTH
  637. allocate(halo_slab(1-BDR_WIDTH:fg_data%nx+BDR_WIDTH,1:fg_data%ny))
  638. halo_slab(1:fg_data%nx, 1:fg_data%ny) = &
  639. fg_data%slab(1:fg_data%nx, 1:fg_data%ny)
  640. halo_slab(1-BDR_WIDTH:0, 1:fg_data%ny) = &
  641. fg_data%slab(fg_data%nx-BDR_WIDTH+1:fg_data%nx, 1:fg_data%ny)
  642. halo_slab(fg_data%nx+1:fg_data%nx+BDR_WIDTH, 1:fg_data%ny) = &
  643. fg_data%slab(1:BDR_WIDTH, 1:fg_data%ny)
  644. deallocate(fg_data%slab)
  645. else
  646. bdr_wdth = 0
  647. halo_slab => fg_data%slab
  648. nullify(fg_data%slab)
  649. end if
  650. call mprintf(.true.,LOGFILE,'Processing %s at level %f.',s1=fg_data%field,f1=fg_data%xlvl)
  651. call push_source_projection(fg_data%iproj, fg_data%xlonc, fg_data%truelat1, &
  652. fg_data%truelat2, fg_data%dx, fg_data%dy, fg_data%deltalat, &
  653. fg_data%deltalon, fg_data%starti, fg_data%startj, &
  654. fg_data%startlat, fg_data%startlon, earth_radius=fg_data%earth_radius*1000.)
  655. ! Initialize fg_input structure to store the field
  656. field%header%version = 1
  657. field%header%date = fg_data%hdate//' '
  658. if (do_const_processing) then
  659. field%header%time_dependent = .false.
  660. else
  661. field%header%time_dependent = .true.
  662. end if
  663. field%header%forecast_hour = fg_data%xfcst
  664. field%header%fg_source = 'FG'
  665. field%header%field = ' '
  666. field%header%field(1:9) = fg_data%field
  667. field%header%units = ' '
  668. field%header%units(1:25) = fg_data%units
  669. field%header%description = ' '
  670. field%header%description(1:46) = fg_data%desc
  671. call get_z_dim_name(fg_data%field,field%header%vertical_coord)
  672. field%header%vertical_level = nint(fg_data%xlvl)
  673. field%header%sr_x = sub_x
  674. field%header%sr_y = sub_y
  675. field%header%is_subgrid = .false.
  676. field%header%array_order = 'XY '
  677. field%header%is_wind_grid_rel = fg_data%is_wind_grid_rel
  678. field%header%array_has_missing_values = .false.
  679. nullify(field%r_arr)
  680. nullify(field%valid_mask)
  681. nullify(field%modified_mask)
  682. if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
  683. output_flags(idx) = flag_in_output(idx)
  684. end if
  685. ! If we should not output this field, just list it as a mask field
  686. if (output_this_field(idx)) then
  687. field%header%mask_field = .false.
  688. else
  689. field%header%mask_field = .true.
  690. end if
  691. !
  692. ! Before actually doing any interpolation to the model grid, we must check
  693. ! whether we will be using the average_gcell interpolator that averages all
  694. ! source points in each model grid cell
  695. !
  696. do_gcell_interp = .false.
  697. if (index(interp_method(idx),'average_gcell') /= 0) then
  698. call get_gcell_threshold(interp_method(idx), threshold, istatus)
  699. if (istatus == 0) then
  700. if (fg_data%dx == 0. .and. fg_data%dy == 0. .and. &
  701. fg_data%deltalat /= 0. .and. fg_data%deltalon /= 0.) then
  702. fg_data%dx = abs(fg_data%deltalon)
  703. fg_data%dy = abs(fg_data%deltalat)
  704. else
  705. ! BUG: Need to more correctly handle dx/dy in meters.
  706. fg_data%dx = fg_data%dx / 111000. ! Convert meters to approximate degrees
  707. fg_data%dy = fg_data%dy / 111000.
  708. end if
  709. if (gridtype == 'C') then
  710. if (threshold*max(fg_data%dx,fg_data%dy)*111. <= max(dom_dx,dom_dy)/1000.) &
  711. do_gcell_interp = .true.
  712. else if (gridtype == 'E') then
  713. if (threshold*max(fg_data%dx,fg_data%dy) <= max(dom_dx,dom_dy)) &
  714. do_gcell_interp = .true.
  715. end if
  716. end if
  717. end if
  718. ! Interpolate to U staggering
  719. if (output_stagger(idx) == U) then
  720. call storage_query_field(field, iqstatus)
  721. if (iqstatus == 0) then
  722. call storage_get_field(field, iqstatus)
  723. call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
  724. ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
  725. if (associated(field%modified_mask)) then
  726. call bitarray_destroy(field%modified_mask)
  727. nullify(field%modified_mask)
  728. end if
  729. else
  730. allocate(field%valid_mask)
  731. call bitarray_create(field%valid_mask, we_mem_stag_e-we_mem_stag_s+1, sn_mem_e-sn_mem_s+1)
  732. end if
  733. ! Save a copy of the fg_input structure for the U field so that we can find it later
  734. if (is_u_field(idx)) call dup(field, u_field)
  735. allocate(field%modified_mask)
  736. call bitarray_create(field%modified_mask, we_mem_stag_e-we_mem_stag_s+1, sn_mem_e-sn_mem_s+1)
  737. if (do_const_processing .or. field%header%time_dependent) then
  738. call interp_met_field(input_name, fg_data%field, U, M, &
  739. field, xlat_u, xlon_u, we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, &
  740. we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
  741. halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
  742. field%modified_mask, process_bdy_width)
  743. else
  744. call mprintf(.true.,INFORM,' - already processed this field from constant file.')
  745. end if
  746. ! Interpolate to V staggering
  747. else if (output_stagger(idx) == V) then
  748. call storage_query_field(field, iqstatus)
  749. if (iqstatus == 0) then
  750. call storage_get_field(field, iqstatus)
  751. call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
  752. ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
  753. if (associated(field%modified_mask)) then
  754. call bitarray_destroy(field%modified_mask)
  755. nullify(field%modified_mask)
  756. end if
  757. else
  758. allocate(field%valid_mask)
  759. call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_stag_e-sn_mem_stag_s+1)
  760. end if
  761. ! Save a copy of the fg_input structure for the V field so that we can find it later
  762. if (is_v_field(idx)) call dup(field, v_field)
  763. allocate(field%modified_mask)
  764. call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_stag_e-sn_mem_stag_s+1)
  765. if (do_const_processing .or. field%header%time_dependent) then
  766. call interp_met_field(input_name, fg_data%field, V, M, &
  767. field, xlat_v, xlon_v, we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
  768. we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
  769. halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
  770. field%modified_mask, process_bdy_width)
  771. else
  772. call mprintf(.true.,INFORM,' - already processed this field from constant file.')
  773. end if
  774. ! Interpolate to VV staggering
  775. else if (output_stagger(idx) == VV) then
  776. call storage_query_field(field, iqstatus)
  777. if (iqstatus == 0) then
  778. call storage_get_field(field, iqstatus)
  779. call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
  780. ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
  781. if (associated(field%modified_mask)) then
  782. call bitarray_destroy(field%modified_mask)
  783. nullify(field%modified_mask)
  784. end if
  785. else
  786. allocate(field%valid_mask)
  787. call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
  788. end if
  789. ! Save a copy of the fg_input structure for the U field so that we can find it later
  790. if (is_u_field(idx)) call dup(field, u_field)
  791. ! Save a copy of the fg_input structure for the V field so that we can find it later
  792. if (is_v_field(idx)) call dup(field, v_field)
  793. allocate(field%modified_mask)
  794. call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
  795. if (do_const_processing .or. field%header%time_dependent) then
  796. call interp_met_field(input_name, fg_data%field, VV, M, &
  797. field, xlat_v, xlon_v, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
  798. we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
  799. halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
  800. field%modified_mask, process_bdy_width)
  801. else
  802. call mprintf(.true.,INFORM,' - already processed this field from constant file.')
  803. end if
  804. ! All other fields interpolated to M staggering for C grid, H staggering for E grid
  805. else
  806. call storage_query_field(field, iqstatus)
  807. if (iqstatus == 0) then
  808. call storage_get_field(field, iqstatus)
  809. call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
  810. ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
  811. if (associated(field%modified_mask)) then
  812. call bitarray_destroy(field%modified_mask)
  813. nullify(field%modified_mask)
  814. end if
  815. else
  816. allocate(field%valid_mask)
  817. call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
  818. end if
  819. allocate(field%modified_mask)
  820. call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
  821. if (do_const_processing .or. field%header%time_dependent) then
  822. if (gridtype == 'C') then
  823. call interp_met_field(input_name, fg_data%field, M, M, &
  824. field, xlat, xlon, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
  825. we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
  826. halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
  827. field%modified_mask, process_bdy_width, landmask)
  828. else if (gridtype == 'E') then
  829. call interp_met_field(input_name, fg_data%field, HH, M, &
  830. field, xlat, xlon, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
  831. we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
  832. halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
  833. field%modified_mask, process_bdy_width, landmask)
  834. end if
  835. else
  836. call mprintf(.true.,INFORM,' - already processed this field from constant file.')
  837. end if
  838. end if
  839. call bitarray_merge(field%valid_mask, field%modified_mask)
  840. deallocate(halo_slab)
  841. ! Store the interpolated field
  842. call storage_put_field(field)
  843. call pop_source_projection()
  844. end if
  845. end do
  846. call read_met_close()
  847. call push_source_projection(fg_data%iproj, fg_data%xlonc, fg_data%truelat1, &
  848. fg_data%truelat2, fg_data%dx, fg_data%dy, fg_data%deltalat, &
  849. fg_data%deltalon, fg_data%starti, fg_data%startj, &
  850. fg_data%startlat, fg_data%startlon, earth_radius=fg_data%earth_radius*1000.)
  851. !
  852. ! If necessary, rotate winds to earth-relative for this fg source
  853. !
  854. call storage_get_levels(u_field, u_levels)
  855. call storage_get_levels(v_field, v_levels)
  856. if (associated(u_levels) .and. associated(v_levels)) then
  857. u_idx = 1
  858. do u_idx = 1, size(u_levels)
  859. u_field%header%vertical_level = u_levels(u_idx)
  860. call storage_get_field(u_field, istatus)
  861. v_field%header%vertical_level = v_levels(u_idx)
  862. call storage_get_field(v_field, istatus)
  863. if (associated(u_field%modified_mask) .and. &
  864. associated(v_field%modified_mask)) then
  865. if (u_field%header%is_wind_grid_rel) then
  866. if (gridtype == 'C') then
  867. call map_to_met(u_field%r_arr, u_field%modified_mask, &
  868. v_field%r_arr, v_field%modified_mask, &
  869. we_mem_stag_s, sn_mem_s, &
  870. we_mem_stag_e, sn_mem_e, &
  871. we_mem_s, sn_mem_stag_s, &
  872. we_mem_e, sn_mem_stag_e, &
  873. xlon_u, xlon_v, xlat_u, xlat_v)
  874. else if (gridtype == 'E') then
  875. call map_to_met_nmm(u_field%r_arr, u_field%modified_mask, &
  876. v_field%r_arr, v_field%modified_mask, &
  877. we_mem_s, sn_mem_s, &
  878. we_mem_e, sn_mem_e, &
  879. xlat_v, xlon_v)
  880. end if
  881. end if
  882. call bitarray_destroy(u_field%modified_mask)
  883. call bitarray_destroy(v_field%modified_mask)
  884. nullify(u_field%modified_mask)
  885. nullify(v_field%modified_mask)
  886. call storage_put_field(u_field)
  887. call storage_put_field(v_field)
  888. end if
  889. end do
  890. deallocate(u_levels)
  891. deallocate(v_levels)
  892. end if
  893. call pop_source_projection()
  894. else
  895. if (do_const_processing) then
  896. call mprintf(.true.,WARN,'Couldn''t open file %s for input.',s1=input_name)
  897. else
  898. call mprintf(.true.,WARN,'Couldn''t open file %s for input.',s1=trim(input_name)//':'//trim(temp_date))
  899. end if
  900. end if
  901. fg_idx = fg_idx + 1
  902. if (do_const_processing) then
  903. input_name = constants_name(fg_idx)
  904. else
  905. input_name = fg_name(fg_idx)
  906. end if
  907. end do ! while (input_name /= '*')
  908. !
  909. ! Rotate winds from earth-relative to grid-relative
  910. !
  911. call storage_get_levels(u_field, u_levels)
  912. call storage_get_levels(v_field, v_levels)
  913. if (associated(u_levels) .and. associated(v_levels)) then
  914. u_idx = 1
  915. do u_idx = 1, size(u_levels)
  916. u_field%header%vertical_level = u_levels(u_idx)
  917. call storage_get_field(u_field, istatus)
  918. v_field%header%vertical_level = v_levels(u_idx)
  919. call storage_get_field(v_field, istatus)
  920. if (gridtype == 'C') then
  921. call met_to_map(u_field%r_arr, u_field%valid_mask, &
  922. v_field%r_arr, v_field%valid_mask, &
  923. we_mem_stag_s, sn_mem_s, &
  924. we_mem_stag_e, sn_mem_e, &
  925. we_mem_s, sn_mem_stag_s, &
  926. we_mem_e, sn_mem_stag_e, &
  927. xlon_u, xlon_v, xlat_u, xlat_v)
  928. else if (gridtype == 'E') then
  929. call met_to_map_nmm(u_field%r_arr, u_field%valid_mask, &
  930. v_field%r_arr, v_field%valid_mask, &
  931. we_mem_s, sn_mem_s, &
  932. we_mem_e, sn_mem_e, &
  933. xlat_v, xlon_v)
  934. end if
  935. end do
  936. deallocate(u_levels)
  937. deallocate(v_levels)
  938. end if
  939. if (do_const_processing) return
  940. !
  941. ! Now that we have all degribbed fields, we build a 3-d pressure field, and fill in any
  942. ! missing levels in the other 3-d fields
  943. !
  944. call mprintf(.true.,LOGFILE,'Filling missing levels.')
  945. call fill_missing_levels(output_flags)
  946. call mprintf(.true.,LOGFILE,'Creating derived fields.')
  947. call create_derived_fields(gridtype, fg_data%hdate, fg_data%xfcst, &
  948. we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
  949. we_mem_stag_s, we_mem_stag_e, sn_mem_stag_s, sn_mem_stag_e, &
  950. got_this_field, output_flags)
  951. !
  952. ! Check that every mandatory field was found in input data
  953. !
  954. do i=1,num_entries
  955. if (is_mandatory(i) .and. .not. got_this_field(i)) then
  956. call mprintf(.true.,ERROR,'The mandatory field %s was not found in any input data.',s1=fieldname(i))
  957. end if
  958. end do
  959. !
  960. ! Before we begin to write fields, if debug_level is set high enough, we
  961. ! write a table of which fields are available at which levels to the
  962. ! metgrid.log file, and then we check to see if any fields are not
  963. ! completely covered with data.
  964. !
  965. call storage_print_fields()
  966. call find_missing_values()
  967. !
  968. ! All of the processing is now done for this time period for this domain;
  969. ! now we simply output every field from the storage module.
  970. !
  971. title = 'OUTPUT FROM METGRID V3.3'
  972. ! Initialize the output module for this domain and time
  973. call mprintf(.true.,LOGFILE,'Initializing output module.')
  974. output_date = temp_date
  975. if ( .not. nocolons ) then
  976. if (len_trim(temp_date) == 13) then
  977. output_date(14:19) = ':00:00'
  978. else if (len_trim(temp_date) == 16) then
  979. output_date(17:19) = ':00'
  980. end if
  981. else
  982. if (len_trim(temp_date) == 13) then
  983. output_date(14:19) = '_00_00'
  984. else if (len_trim(temp_date) == 16) then
  985. output_date(17:19) = '_00'
  986. end if
  987. endif
  988. call output_init(n, title, output_date, gridtype, dyn_opt, &
  989. corner_lats, corner_lons, &
  990. we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
  991. we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, &
  992. we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
  993. extra_col, extra_row)
  994. call get_bottom_top_dim(bottom_top_dim)
  995. ! Add in a flag to tell real that we have seven new msf fields
  996. nmet_flags = num_entries + 1
  997. allocate(met_flags(nmet_flags))
  998. do i=1,num_entries
  999. met_flags(i) = output_flags(i)
  1000. end do
  1001. if (gridtype == 'C') then
  1002. met_flags(num_entries+1) = 'FLAG_MF_XY'
  1003. else
  1004. met_flags(num_entries+1) = ' '
  1005. end if
  1006. ! Find out how many soil levels or layers we have; this assumes a field named ST
  1007. field % header % field = 'ST'
  1008. nullify(soil_levels)
  1009. call storage_get_levels(field, soil_levels)
  1010. if (.not. associated(soil_levels)) then
  1011. field % header % field = 'SOILT'
  1012. nullify(soil_levels)
  1013. call storage_get_levels(field, soil_levels)
  1014. end if
  1015. if (.not. associated(soil_levels)) then
  1016. field % header % field = 'STC_WPS'
  1017. nullify(soil_levels)
  1018. call storage_get_levels(field, soil_levels)
  1019. end if
  1020. if (associated(soil_levels)) then
  1021. num_metgrid_soil_levs = size(soil_levels)
  1022. deallocate(soil_levels)
  1023. else
  1024. num_metgrid_soil_levs = 0
  1025. end if
  1026. ! First write out global attributes
  1027. call mprintf(.true.,LOGFILE,'Writing global attributes to output.')
  1028. call write_global_attrs(title, output_date, gridtype, dyn_opt, west_east_dim, &
  1029. south_north_dim, bottom_top_dim, &
  1030. we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
  1031. sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
  1032. map_proj, mminlu, num_land_cat, &
  1033. is_water, is_lake, is_ice, is_urban, i_soilwater, &
  1034. grid_id, parent_id, i_parent_start, &
  1035. j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
  1036. cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  1037. pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
  1038. corner_lats, corner_lons, num_metgrid_soil_levs, &
  1039. met_flags, nmet_flags, process_bdy_width)
  1040. deallocate(met_flags)
  1041. call reset_next_field()
  1042. istatus = 0
  1043. ! Now loop over all output fields, writing each to the output module
  1044. do while (istatus == 0)
  1045. call get_next_output_field(cname, real_array, &
  1046. sm1, em1, sm2, em2, sm3, em3, istatus)
  1047. if (istatus == 0) then
  1048. call mprintf(.true.,LOGFILE,'Writing field %s to output.',s1=cname)
  1049. call write_field(sm1, em1, sm2, em2, sm3, em3, &
  1050. cname, output_date, real_array)
  1051. deallocate(real_array)
  1052. end if
  1053. end do
  1054. call mprintf(.true.,LOGFILE,'Closing output file.')
  1055. call output_close()
  1056. ! Free up memory used by met fields for this valid time
  1057. call storage_delete_all_td()
  1058. end subroutine process_single_met_time
  1059. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1060. ! Name: get_interp_masks
  1061. !
  1062. ! Purpose:
  1063. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1064. subroutine get_interp_masks(fg_prefix, is_constants, fg_date)
  1065. use interp_option_module
  1066. use read_met_module
  1067. use storage_module
  1068. implicit none
  1069. ! Arguments
  1070. logical, intent(in) :: is_constants
  1071. character (len=*), intent(in) :: fg_prefix, fg_date
  1072. ! BUG: Move this constant to misc_definitions_module?
  1073. integer, parameter :: BDR_WIDTH = 3
  1074. ! Local variables
  1075. integer :: i, istatus, idx, idxt
  1076. type (fg_input) :: mask_field
  1077. type (met_data) :: fg_data
  1078. istatus = 0
  1079. call read_met_init(fg_prefix, is_constants, fg_date, istatus)
  1080. do while (istatus == 0)
  1081. call read_next_met_field(fg_data, istatus)
  1082. if (istatus == 0) then
  1083. ! Find out which METGRID.TBL entry goes with this field
  1084. idxt = num_entries + 1
  1085. do idx=1,num_entries
  1086. if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
  1087. (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
  1088. if (index(fg_prefix,trim(from_input(idx))) /= 0 .or. &
  1089. (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
  1090. idxt = idx
  1091. end if
  1092. end if
  1093. end do
  1094. idx = idxt
  1095. if (idx > num_entries) idx = num_entries ! The last entry is a default
  1096. ! Do we need to rename this field?
  1097. if (output_name(idx) /= ' ') then
  1098. fg_data%field = output_name(idx)(1:9)
  1099. idxt = num_entries + 1
  1100. do idx=1,num_entries
  1101. if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
  1102. (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
  1103. if (index(fg_prefix,trim(from_input(idx))) /= 0 .or. &
  1104. (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
  1105. idxt = idx
  1106. end if
  1107. end if
  1108. end do
  1109. idx = idxt
  1110. if (idx > num_entries) idx = num_entries ! The last entry is a default
  1111. end if
  1112. do i=1,num_entries
  1113. if (interp_mask(i) /= ' ' .and. (trim(interp_mask(i)) == trim(fg_data%field))) then
  1114. mask_field%header%version = 1
  1115. mask_field%header%date = ' '
  1116. mask_field%header%date = fg_date
  1117. if (is_constants) then
  1118. mask_field%header%time_dependent = .false.
  1119. else
  1120. mask_field%header%time_dependent = .true.
  1121. end if
  1122. mask_field%header%mask_field = .true.
  1123. mask_field%header%forecast_hour = 0.
  1124. mask_field%header%fg_source = 'degribbed met data'
  1125. mask_field%header%field = trim(fg_data%field)//'.mask'
  1126. mask_field%header%units = '-'
  1127. mask_field%header%description = '-'
  1128. mask_field%header%vertical_coord = 'none'
  1129. mask_field%header%vertical_level = 1
  1130. mask_field%header%sr_x = 1
  1131. mask_field%header%sr_y = 1
  1132. mask_field%header%is_subgrid = .false.
  1133. mask_field%header%array_order = 'XY'
  1134. mask_field%header%dim1(1) = 1
  1135. mask_field%header%dim1(2) = fg_data%nx
  1136. mask_field%header%dim2(1) = 1
  1137. mask_field%header%dim2(2) = fg_data%ny
  1138. mask_field%header%is_wind_grid_rel = .true.
  1139. mask_field%header%array_has_missing_values = .false.
  1140. mask_field%map%stagger = M
  1141. ! Do a simple check to see whether this is a global lat/lon dataset
  1142. ! Note that we do not currently support regional Gaussian grids
  1143. if ((fg_data%iproj == PROJ_LATLON .and. abs(fg_data%nx * fg_data%deltalon - 360.) < 0.0001) &
  1144. .or. (fg_data%iproj == PROJ_GAUSS)) then
  1145. allocate(mask_field%r_arr(1-BDR_WIDTH:fg_data%nx+BDR_WIDTH,1:fg_data%ny))
  1146. mask_field%r_arr(1:fg_data%nx, 1:fg_data%ny) = &
  1147. fg_data%slab(1:fg_data%nx, 1:fg_data%ny)
  1148. mask_field%r_arr(1-BDR_WIDTH:0, 1:fg_data%ny) = &
  1149. fg_data%slab(fg_data%nx-BDR_WIDTH+1:fg_data%nx, 1:fg_data%ny)
  1150. mask_field%r_arr(fg_data%nx+1:fg_data%nx+BDR_WIDTH, 1:fg_data%ny) = &
  1151. fg_data%slab(1:BDR_WIDTH, 1:fg_data%ny)
  1152. else
  1153. allocate(mask_field%r_arr(1:fg_data%nx,1:fg_data%ny))
  1154. mask_field%r_arr = fg_data%slab
  1155. end if
  1156. nullify(mask_field%valid_mask)
  1157. nullify(mask_field%modified_mask)
  1158. call storage_put_field(mask_field)
  1159. exit
  1160. end if
  1161. end do
  1162. if (associated(fg_data%slab)) deallocate(fg_data%slab)
  1163. end if
  1164. end do
  1165. call read_met_close()
  1166. end subroutine get_interp_masks
  1167. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1168. ! Name: interp_met_field
  1169. !
  1170. ! Purpose:
  1171. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1172. subroutine interp_met_field(input_name, short_fieldnm, ifieldstagger, istagger, &
  1173. field, xlat, xlon, sm1, em1, sm2, em2, &
  1174. sd1, ed1, sd2, ed2, &
  1175. slab, minx, maxx, miny, maxy, bdr, do_gcell_interp, &
  1176. new_pts, process_bdy_width, landmask)
  1177. use bitarray_module
  1178. use interp_module
  1179. use interp_option_module
  1180. use llxy_module
  1181. use misc_definitions_module
  1182. use storage_module
  1183. implicit none
  1184. ! Arguments
  1185. integer, intent(in) :: ifieldstagger, istagger, &
  1186. sm1, em1, sm2, em2, &
  1187. sd1, ed1, sd2, ed2, &
  1188. minx, maxx, miny, maxy, bdr, &
  1189. process_bdy_width
  1190. real, dimension(minx:maxx,miny:maxy), intent(in) :: slab
  1191. real, dimension(sm1:em1,sm2:em2), intent(in) :: xlat, xlon
  1192. real, dimension(sm1:em1,sm2:em2), intent(in), optional :: landmask
  1193. logical, intent(in) :: do_gcell_interp
  1194. character (len=9), intent(in) :: short_fieldnm
  1195. character (len=MAX_FILENAME_LEN), intent(in) :: input_name
  1196. type (fg_input), intent(inout) :: field
  1197. type (bitarray), intent(inout) :: new_pts
  1198. ! Local variables
  1199. integer :: i, j, idx, idxt, orig_selected_proj, interp_mask_status, &
  1200. interp_land_mask_status, interp_water_mask_status, process_width
  1201. integer, pointer, dimension(:) :: interp_array
  1202. real :: rx, ry, temp
  1203. real, pointer, dimension(:,:) :: data_count
  1204. type (fg_input) :: mask_field, mask_water_field, mask_land_field
  1205. ! Find index into fieldname, interp_method, masked, and fill_missing
  1206. ! of the current field
  1207. idxt = num_entries + 1
  1208. do idx=1,num_entries
  1209. if ((index(fieldname(idx), trim(short_fieldnm)) /= 0) .and. &
  1210. (len_trim(fieldname(idx)) == len_trim(short_fieldnm))) then
  1211. if (index(input_name,trim(from_input(idx))) /= 0 .or. &
  1212. (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
  1213. idxt = idx
  1214. end if
  1215. end if
  1216. end do
  1217. idx = idxt
  1218. if (idx > num_entries) then
  1219. call mprintf(.true.,WARN,'Entry in METGRID.TBL not found for field %s. '// &
  1220. 'Default options will be used for this field!', s1=short_fieldnm)
  1221. idx = num_entries ! The last entry is a default
  1222. end if
  1223. if (process_bdy_width == 0) then
  1224. process_width = max(ed1-sd1+1, ed2-sd2+1)
  1225. else
  1226. process_width = process_bdy_width
  1227. ! Add two extra rows/cols to accommodate staggered fields: one extra row/col for
  1228. ! averaging to mass points in real, and one beyond that for averaging during
  1229. ! wind rotation
  1230. if (ifieldstagger /= M) process_width = process_width + 2
  1231. end if
  1232. field%header%dim1(1) = sm1
  1233. field%header%dim1(2) = em1
  1234. field%header%dim2(1) = sm2
  1235. field%header%dim2(2) = em2
  1236. field%map%stagger = ifieldstagger
  1237. if (.not. associated(field%r_arr)) then
  1238. allocate(field%r_arr(sm1:em1,sm2:em2))
  1239. end if
  1240. interp_mask_status = 1
  1241. interp_land_mask_status = 1
  1242. interp_water_mask_status = 1
  1243. if (interp_mask(idx) /= ' ') then
  1244. mask_field%header%version = 1
  1245. mask_field%header%forecast_hour = 0.
  1246. mask_field%header%field = trim(interp_mask(idx))//'.mask'
  1247. mask_field%header%vertical_coord = 'none'
  1248. mask_field%header%vertical_level = 1
  1249. call storage_get_field(mask_field, interp_mask_status)
  1250. end if
  1251. if (interp_land_mask(idx) /= ' ') then
  1252. mask_land_field%header%version = 1
  1253. mask_land_field%header%forecast_hour = 0.
  1254. mask_land_field%header%field = trim(interp_land_mask(idx))//'.mask'
  1255. mask_land_field%header%vertical_coord = 'none'
  1256. mask_land_field%header%vertical_level = 1
  1257. call storage_get_field(mask_land_field, interp_land_mask_status)
  1258. end if
  1259. if (interp_water_mask(idx) /= ' ') then
  1260. mask_water_field%header%version = 1
  1261. mask_water_field%header%forecast_hour = 0.
  1262. mask_water_field%header%field = trim(interp_water_mask(idx))//'.mask'
  1263. mask_water_field%header%vertical_coord = 'none'
  1264. mask_water_field%header%vertical_level = 1
  1265. call storage_get_field(mask_water_field, interp_water_mask_status)
  1266. end if
  1267. interp_array => interp_array_from_string(interp_method(idx))
  1268. !
  1269. ! Interpolate using average_gcell interpolation method
  1270. !
  1271. if (do_gcell_interp) then
  1272. allocate(data_count(sm1:em1,sm2:em2))
  1273. data_count = 0.
  1274. if (interp_mask_status == 0) then
  1275. call accum_continuous(slab, &
  1276. minx, maxx, miny, maxy, 1, 1, bdr, &
  1277. field%r_arr, data_count, &
  1278. sm1, em1, sm2, em2, 1, 1, &
  1279. istagger, &
  1280. new_pts, missing_value(idx), interp_mask_val(idx), interp_mask_relational(idx), mask_field%r_arr)
  1281. else
  1282. call accum_continuous(slab, &
  1283. minx, maxx, miny, maxy, 1, 1, bdr, &
  1284. field%r_arr, data_count, &
  1285. sm1, em1, sm2, em2, 1, 1, &
  1286. istagger, &
  1287. new_pts, missing_value(idx), -1.) ! The -1 is the maskval, but since we
  1288. ! we do not give an optional mask, no
  1289. ! no need to worry about -1s in data
  1290. end if
  1291. orig_selected_proj = iget_selected_domain()
  1292. call select_domain(SOURCE_PROJ)
  1293. do j=sm2,em2
  1294. do i=sm1,em1
  1295. if (abs(i - sd1) >= process_width .and. (abs(i - ed1) >= process_width) .and. &
  1296. abs(j - sd2) >= process_width .and. (abs(j - ed2) >= process_width)) then
  1297. field%r_arr(i,j) = fill_missing(idx)
  1298. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1299. cycle
  1300. end if
  1301. if (present(landmask)) then
  1302. if (landmask(i,j) /= masked(idx)) then
  1303. if (data_count(i,j) > 0.) then
  1304. field%r_arr(i,j) = field%r_arr(i,j) / data_count(i,j)
  1305. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1306. else
  1307. if (interp_mask_status == 0) then
  1308. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1309. minx, maxx, miny, maxy, bdr, missing_value(idx), &
  1310. mask_relational=interp_mask_relational(idx), &
  1311. mask_val=interp_mask_val(idx), mask_field=mask_field%r_arr)
  1312. else
  1313. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1314. minx, maxx, miny, maxy, bdr, missing_value(idx))
  1315. end if
  1316. if (temp /= missing_value(idx)) then
  1317. field%r_arr(i,j) = temp
  1318. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1319. end if
  1320. end if
  1321. else
  1322. field%r_arr(i,j) = fill_missing(idx)
  1323. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1324. end if
  1325. if (.not. bitarray_test(new_pts, i-sm1+1, j-sm2+1) .and. &
  1326. .not. bitarray_test(field%valid_mask, i-sm1+1, j-sm2+1)) then
  1327. field%r_arr(i,j) = fill_missing(idx)
  1328. ! Assume that if missing fill value is other than default, then user has asked
  1329. ! to fill in any missing values, and we can consider this point to have
  1330. ! received a valid value
  1331. if (fill_missing(idx) /= NAN) call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1332. end if
  1333. else
  1334. if (data_count(i,j) > 0.) then
  1335. field%r_arr(i,j) = field%r_arr(i,j) / data_count(i,j)
  1336. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1337. else
  1338. if (interp_mask_status == 0) then
  1339. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1340. minx, maxx, miny, maxy, bdr, missing_value(idx), &
  1341. mask_relational=interp_mask_relational(idx), &
  1342. mask_val=interp_mask_val(idx), mask_field=mask_field%r_arr)
  1343. else
  1344. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1345. minx, maxx, miny, maxy, bdr, missing_value(idx))
  1346. end if
  1347. if (temp /= missing_value(idx)) then
  1348. field%r_arr(i,j) = temp
  1349. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1350. end if
  1351. end if
  1352. if (.not. bitarray_test(new_pts, i-sm1+1, j-sm2+1) .and. &
  1353. .not. bitarray_test(field%valid_mask, i-sm1+1, j-sm2+1)) then
  1354. field%r_arr(i,j) = fill_missing(idx)
  1355. ! Assume that if missing fill value is other than default, then user has asked
  1356. ! to fill in any missing values, and we can consider this point to have
  1357. ! received a valid value
  1358. if (fill_missing(idx) /= NAN) call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1359. end if
  1360. end if
  1361. end do
  1362. end do
  1363. call select_domain(orig_selected_proj)
  1364. deallocate(data_count)
  1365. !
  1366. ! No average_gcell interpolation method
  1367. !
  1368. else
  1369. orig_selected_proj = iget_selected_domain()
  1370. call select_domain(SOURCE_PROJ)
  1371. do j=sm2,em2
  1372. do i=sm1,em1
  1373. if (abs(i - sd1) >= process_width .and. (abs(i - ed1) >= process_width) .and. &
  1374. abs(j - sd2) >= process_width .and. (abs(j - ed2) >= process_width)) then
  1375. field%r_arr(i,j) = fill_missing(idx)
  1376. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1377. cycle
  1378. end if
  1379. if (present(landmask)) then
  1380. if (masked(idx) == MASKED_BOTH) then
  1381. if (landmask(i,j) == 0) then ! WATER POINT
  1382. if (interp_land_mask_status == 0) then
  1383. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1384. minx, maxx, miny, maxy, bdr, missing_value(idx), &
  1385. mask_relational=interp_land_mask_relational(idx), &
  1386. mask_val=interp_land_mask_val(idx), mask_field=mask_land_field%r_arr)
  1387. else
  1388. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1389. minx, maxx, miny, maxy, bdr, missing_value(idx))
  1390. end if
  1391. else if (landmask(i,j) == 1) then ! LAND POINT
  1392. if (interp_water_mask_status == 0) then
  1393. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1394. minx, maxx, miny, maxy, bdr, missing_value(idx), &
  1395. mask_relational=interp_water_mask_relational(idx), &
  1396. mask_val=interp_water_mask_val(idx), mask_field=mask_water_field%r_arr)
  1397. else
  1398. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1399. minx, maxx, miny, maxy, bdr, missing_value(idx))
  1400. end if
  1401. end if
  1402. else if (landmask(i,j) /= masked(idx)) then
  1403. if (interp_mask_status == 0) then
  1404. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1405. minx, maxx, miny, maxy, bdr, missing_value(idx), &
  1406. mask_relational=interp_mask_relational(idx), &
  1407. mask_val=interp_mask_val(idx), mask_field=mask_field%r_arr)
  1408. else
  1409. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1410. minx, maxx, miny, maxy, bdr, missing_value(idx))
  1411. end if
  1412. else
  1413. temp = missing_value(idx)
  1414. end if
  1415. ! No landmask for this field
  1416. else
  1417. if (interp_mask_status == 0) then
  1418. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1419. minx, maxx, miny, maxy, bdr, missing_value(idx), &
  1420. mask_relational=interp_mask_relational(idx), &
  1421. mask_val=interp_mask_val(idx), mask_field=mask_field%r_arr)
  1422. else
  1423. temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, slab, &
  1424. minx, maxx, miny, maxy, bdr, missing_value(idx))
  1425. end if
  1426. end if
  1427. if (temp /= missing_value(idx)) then
  1428. field%r_arr(i,j) = temp
  1429. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1430. else if (present(landmask)) then
  1431. if (landmask(i,j) == masked(idx)) then
  1432. field%r_arr(i,j) = fill_missing(idx)
  1433. call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1434. end if
  1435. end if
  1436. if (.not. bitarray_test(new_pts, i-sm1+1, j-sm2+1) .and. &
  1437. .not. bitarray_test(field%valid_mask, i-sm1+1, j-sm2+1)) then
  1438. field%r_arr(i,j) = fill_missing(idx)
  1439. ! Assume that if missing fill value is other than default, then user has asked
  1440. ! to fill in any missing values, and we can consider this point to have
  1441. ! received a valid value
  1442. if (fill_missing(idx) /= NAN) call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
  1443. end if
  1444. end do
  1445. end do
  1446. call select_domain(orig_selected_proj)
  1447. end if
  1448. deallocate(interp_array)
  1449. end subroutine interp_met_field
  1450. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1451. ! Name: interp_to_latlon
  1452. !
  1453. ! Purpose:
  1454. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1455. function interp_to_latlon(rlat, rlon, istagger, interp_method_list, slab, &
  1456. minx, maxx, miny, maxy, bdr, source_missing_value, &
  1457. mask_field, mask_relational, mask_val)
  1458. use interp_module
  1459. use llxy_module
  1460. implicit none
  1461. ! Arguments
  1462. integer, intent(in) :: minx, maxx, miny, maxy, bdr, istagger
  1463. integer, dimension(:), intent(in) :: interp_method_list
  1464. real, intent(in) :: rlat, rlon, source_missing_value
  1465. real, dimension(minx:maxx,miny:maxy), intent(in) :: slab
  1466. real, intent(in), optional :: mask_val
  1467. real, dimension(minx:maxx,miny:maxy), intent(in), optional :: mask_field
  1468. character(len=1), intent(in), optional :: mask_relational
  1469. ! Return value
  1470. real :: interp_to_latlon
  1471. ! Local variables
  1472. real :: rx, ry
  1473. interp_to_latlon = source_missing_value
  1474. call lltoxy(rlat, rlon, rx, ry, istagger)
  1475. if (rx >= minx+bdr-0.5 .and. rx <= maxx-bdr+0.5) then
  1476. if (present(mask_field) .and. present(mask_val) .and. present (mask_relational)) then
  1477. interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, 1, 1, source_missing_value, &
  1478. interp_method_list, 1, mask_relational, mask_val, mask_field)
  1479. else if (present(mask_field) .and. present(mask_val)) then
  1480. interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, 1, 1, source_missing_value, &
  1481. interp_method_list, 1, maskval=mask_val, mask_array=mask_field)
  1482. else
  1483. interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, 1, 1, source_missing_value, &
  1484. interp_method_list, 1)
  1485. end if
  1486. else
  1487. interp_to_latlon = source_missing_value
  1488. end if
  1489. if (interp_to_latlon == source_missing_value) then
  1490. ! Try a lon in the range 0. to 360.; all lons in the xlon
  1491. ! array should be in the range -180. to 180.
  1492. if (rlon < 0.) then
  1493. call lltoxy(rlat, rlon+360., rx, ry, istagger)
  1494. if (rx >= minx+bdr-0.5 .and. rx <= maxx-bdr+0.5) then
  1495. if (present(mask_field) .and. present(mask_val) .and. present(mask_relational)) then
  1496. interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, &
  1497. 1, 1, source_missing_value, &
  1498. interp_method_list, 1, mask_relational, mask_val, mask_field)
  1499. else if (present(mask_field) .and. present(mask_val)) then
  1500. interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, &
  1501. 1, 1, source_missing_value, &
  1502. interp_method_list, 1, maskval=mask_val, mask_array=mask_field)
  1503. else
  1504. interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, &
  1505. 1, 1, source_missing_value, &
  1506. interp_method_list, 1)
  1507. end if
  1508. else
  1509. interp_to_latlon = source_missing_value
  1510. end if
  1511. end if
  1512. end if
  1513. return
  1514. end function interp_to_latlon
  1515. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1516. ! Name: get_bottom_top_dim
  1517. !
  1518. ! Purpose:
  1519. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1520. subroutine get_bottom_top_dim(bottom_top_dim)
  1521. use interp_option_module
  1522. use list_module
  1523. use storage_module
  1524. implicit none
  1525. ! Arguments
  1526. integer, intent(out) :: bottom_top_dim
  1527. ! Local variables
  1528. integer :: i, j
  1529. integer, pointer, dimension(:) :: field_levels
  1530. character (len=32) :: z_dim
  1531. type (fg_input), pointer, dimension(:) :: headers
  1532. type (list) :: temp_levels
  1533. ! Initialize a list to store levels that are found for 3-d fields
  1534. call list_init(temp_levels)
  1535. ! Get a list of all time-dependent fields (given by their headers) from
  1536. ! the storage module
  1537. call storage_get_td_headers(headers)
  1538. !
  1539. ! Given headers of all fields, we first build a list of all possible levels
  1540. ! for 3-d met fields (excluding sea-level, though).
  1541. !
  1542. do i=1,size(headers)
  1543. call get_z_dim_name(headers(i)%header%field, z_dim)
  1544. ! We only want to consider 3-d met fields
  1545. if (z_dim(1:18) == 'num_metgrid_levels') then
  1546. ! Find out what levels the current field has
  1547. call storage_get_levels(headers(i), field_levels)
  1548. do j=1,size(field_levels)
  1549. ! If this level has not yet been encountered, add it to our list
  1550. if (.not. list_search(temp_levels, ikey=field_levels(j), ivalue=field_levels(j))) then
  1551. if (field_levels(j) /= 201300) then
  1552. call list_insert(temp_levels, ikey=field_levels(j), ivalue=field_levels(j))
  1553. end if
  1554. end if
  1555. end do
  1556. deallocate(field_levels)
  1557. end if
  1558. end do
  1559. bottom_top_dim = list_length(temp_levels)
  1560. call list_destroy(temp_levels)
  1561. deallocate(headers)
  1562. end subroutine get_bottom_top_dim
  1563. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1564. ! Name: fill_missing_levels
  1565. !
  1566. ! Purpose:
  1567. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1568. subroutine fill_missing_levels(output_flags)
  1569. use interp_option_module
  1570. use list_module
  1571. use module_debug
  1572. use module_mergesort
  1573. use storage_module
  1574. implicit none
  1575. ! Arguments
  1576. character (len=128), dimension(:), intent(inout) :: output_flags
  1577. ! Local variables
  1578. integer :: i, ii, j, ix, jx, k, lower, upper, temp, istatus
  1579. integer, pointer, dimension(:) :: union_levels, field_levels
  1580. real, pointer, dimension(:) :: r_union_levels
  1581. character (len=128) :: clevel
  1582. type (fg_input) :: lower_field, upper_field, new_field, search_field
  1583. type (fg_input), pointer, dimension(:) :: headers, all_headers
  1584. type (list) :: temp_levels
  1585. type (list_item), pointer, dimension(:) :: keys
  1586. ! Initialize a list to store levels that are found for 3-d fields
  1587. call list_init(temp_levels)
  1588. ! Get a list of all fields (given by their headers) from the storage module
  1589. call storage_get_td_headers(headers)
  1590. call storage_get_all_headers(all_headers)
  1591. !
  1592. ! Given headers of all fields, we first build a list of all possible levels
  1593. ! for 3-d met fields (excluding sea-level, though).
  1594. !
  1595. do i=1,size(headers)
  1596. ! Find out what levels the current field has
  1597. call storage_get_levels(headers(i), field_levels)
  1598. do j=1,size(field_levels)
  1599. ! If this level has not yet been encountered, add it to our list
  1600. if (.not. list_search(temp_levels, ikey=field_levels(j), ivalue=field_levels(j))) then
  1601. if (field_levels(j) /= 201300) then
  1602. call list_insert(temp_levels, ikey=field_levels(j), ivalue=field_levels(j))
  1603. end if
  1604. end if
  1605. end do
  1606. deallocate(field_levels)
  1607. end do
  1608. if (list_length(temp_levels) > 0) then
  1609. !
  1610. ! With all possible levels stored in a list, get an array of levels, sorted
  1611. ! in decreasing order
  1612. !
  1613. i = 0
  1614. allocate(union_levels(list_length(temp_levels)))
  1615. do while (list_length(temp_levels) > 0)
  1616. i = i + 1
  1617. call list_get_first_item(temp_levels, ikey=union_levels(i), ivalue=temp)
  1618. end do
  1619. call mergesort(union_levels, 1, size(union_levels))
  1620. allocate(r_union_levels(size(union_levels)))
  1621. do i=1,size(union_levels)
  1622. r_union_levels(i) = real(union_levels(i))
  1623. end do
  1624. !
  1625. ! With a sorted, complete list of levels, we need
  1626. ! to go back and fill in missing levels for each 3-d field
  1627. !
  1628. do i=1,size(headers)
  1629. !
  1630. ! Find entry in METGRID.TBL for this field, if one exists; if it does, then the
  1631. ! entry may tell us how to get values for the current field at the missing level
  1632. !
  1633. do ii=1,num_entries
  1634. if (fieldname(ii) == headers(i)%header%field) exit
  1635. end do
  1636. if (ii <= num_entries) then
  1637. call dup(headers(i),new_field)
  1638. nullify(new_field%valid_mask)
  1639. nullify(new_field%modified_mask)
  1640. call fill_field(new_field, ii, output_flags, r_union_levels)
  1641. end if
  1642. end do
  1643. deallocate(union_levels)
  1644. deallocate(r_union_levels)
  1645. deallocate(headers)
  1646. call storage_get_td_headers(headers)
  1647. !
  1648. ! Now we may need to vertically interpolate to missing values in 3-d fields
  1649. !
  1650. do i=1,size(headers)
  1651. call storage_get_levels(headers(i), field_levels)
  1652. ! If this isn't a 3-d array, nothing to do
  1653. if (size(field_levels) > 1) then
  1654. do k=1,size(field_levels)
  1655. call dup(headers(i),search_field)
  1656. search_field%header%vertical_level = field_levels(k)
  1657. call storage_get_field(search_field,istatus)
  1658. if (istatus == 0) then
  1659. JLOOP: do jx=search_field%header%dim2(1),search_field%header%dim2(2)
  1660. ILOOP: do ix=search_field%header%dim1(1),search_field%header%dim1(2)
  1661. if (.not. bitarray_test(search_field%valid_mask, &
  1662. ix-search_field%header%dim1(1)+1, &
  1663. jx-search_field%header%dim2(1)+1)) then
  1664. call dup(search_field, lower_field)
  1665. do lower=k-1,1,-1
  1666. lower_field%header%vertical_level = field_levels(lower)
  1667. call storage_get_field(lower_field,istatus)
  1668. if (bitarray_test(lower_field%valid_mask, &
  1669. ix-search_field%header%dim1(1)+1, &
  1670. jx-search_field%header%dim2(1)+1)) &
  1671. exit
  1672. end do
  1673. call dup(search_field, upper_field)
  1674. do upper=k+1,size(field_levels)
  1675. upper_field%header%vertical_level = field_levels(upper)
  1676. call storage_get_field(upper_field,istatus)
  1677. if (bitarray_test(upper_field%valid_mask, &
  1678. ix-search_field%header%dim1(1)+1, &
  1679. jx-search_field%header%dim2(1)+1)) &
  1680. exit
  1681. end do
  1682. if (upper <= size(field_levels) .and. lower >= 1) then
  1683. search_field%r_arr(ix,jx) = real(abs(field_levels(upper)-field_levels(k))) &
  1684. / real(abs(field_levels(upper)-field_levels(lower))) &
  1685. * lower_field%r_arr(ix,jx) &
  1686. + real(abs(field_levels(k)-field_levels(lower))) &
  1687. / real(abs(field_levels(upper)-field_levels(lower))) &
  1688. * upper_field%r_arr(ix,jx)
  1689. call bitarray_set(search_field%valid_mask, &
  1690. ix-search_field%header%dim1(1)+1, &
  1691. jx-search_field%header%dim2(1)+1)
  1692. end if
  1693. end if
  1694. end do ILOOP
  1695. end do JLOOP
  1696. else
  1697. call mprintf(.true.,ERROR, &
  1698. 'This is bad, could not get %s at level %i.', &
  1699. s1=trim(search_field%header%field), i1=field_levels(k))
  1700. end if
  1701. end do
  1702. end if
  1703. deallocate(field_levels)
  1704. end do
  1705. end if
  1706. call list_destroy(temp_levels)
  1707. deallocate(all_headers)
  1708. deallocate(headers)
  1709. end subroutine fill_missing_levels
  1710. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1711. ! Name: create_derived_fields
  1712. !
  1713. ! Purpose:
  1714. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1715. subroutine create_derived_fields(arg_gridtype, hdate, xfcst, &
  1716. we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
  1717. we_mem_stag_s, we_mem_stag_e, sn_mem_stag_s, sn_mem_stag_e, &
  1718. created_this_field, output_flags)
  1719. use interp_option_module
  1720. use list_module
  1721. use module_mergesort
  1722. use storage_module
  1723. implicit none
  1724. ! Arguments
  1725. integer, intent(in) :: we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
  1726. we_mem_stag_s, we_mem_stag_e, sn_mem_stag_s, sn_mem_stag_e
  1727. real, intent(in) :: xfcst
  1728. logical, dimension(:), intent(inout) :: created_this_field
  1729. character (len=1), intent(in) :: arg_gridtype
  1730. character (len=24), intent(in) :: hdate
  1731. character (len=128), dimension(:), intent(inout) :: output_flags
  1732. ! Local variables
  1733. integer :: idx, i, j, istatus
  1734. type (fg_input) :: field
  1735. ! Initialize fg_input structure to store the field
  1736. field%header%version = 1
  1737. field%header%date = hdate//' '
  1738. field%header%time_dependent = .true.
  1739. field%header%mask_field = .false.
  1740. field%header%forecast_hour = xfcst
  1741. field%header%fg_source = 'Derived from FG'
  1742. field%header%field = ' '
  1743. field%header%units = ' '
  1744. field%header%description = ' '
  1745. field%header%vertical_level = 0
  1746. field%header%sr_x = 1
  1747. field%header%sr_y = 1
  1748. field%header%is_subgrid = .false.
  1749. field%header%array_order = 'XY '
  1750. field%header%is_wind_grid_rel = .true.
  1751. field%header%array_has_missing_values = .false.
  1752. nullify(field%r_arr)
  1753. nullify(field%valid_mask)
  1754. nullify(field%modified_mask)
  1755. !
  1756. ! Check each entry in METGRID.TBL to see whether it is a derive field
  1757. !
  1758. do idx=1,num_entries
  1759. if (is_derived_field(idx)) then
  1760. created_this_field(idx) = .true.
  1761. call mprintf(.true.,INFORM,'Going to create the field %s',s1=fieldname(idx))
  1762. ! Intialize more fields in storage structure
  1763. field%header%field = fieldname(idx)
  1764. call get_z_dim_name(fieldname(idx),field%header%vertical_coord)
  1765. field%map%stagger = output_stagger(idx)
  1766. if (arg_gridtype == 'E') then
  1767. field%header%dim1(1) = we_mem_s
  1768. field%header%dim1(2) = we_mem_e
  1769. field%header%dim2(1) = sn_mem_s
  1770. field%header%dim2(2) = sn_mem_e
  1771. else if (arg_gridtype == 'C') then
  1772. if (output_stagger(idx) == M) then
  1773. field%header%dim1(1) = we_mem_s
  1774. field%header%dim1(2) = we_mem_e
  1775. field%header%dim2(1) = sn_mem_s
  1776. field%header%dim2(2) = sn_mem_e
  1777. else if (output_stagger(idx) == U) then
  1778. field%header%dim1(1) = we_mem_stag_s
  1779. field%header%dim1(2) = we_mem_stag_e
  1780. field%header%dim2(1) = sn_mem_s
  1781. field%header%dim2(2) = sn_mem_e
  1782. else if (output_stagger(idx) == V) then
  1783. field%header%dim1(1) = we_mem_s
  1784. field%header%dim1(2) = we_mem_e
  1785. field%header%dim2(1) = sn_mem_stag_s
  1786. field%header%dim2(2) = sn_mem_stag_e
  1787. end if
  1788. end if
  1789. call fill_field(field, idx, output_flags)
  1790. end if
  1791. end do
  1792. end subroutine create_derived_fields
  1793. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1794. ! Name: fill_field
  1795. !
  1796. ! Purpose:
  1797. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1798. subroutine fill_field(field, idx, output_flags, all_level_list)
  1799. use interp_option_module
  1800. use list_module
  1801. use module_mergesort
  1802. use storage_module
  1803. implicit none
  1804. ! Arguments
  1805. integer, intent(in) :: idx
  1806. type (fg_input), intent(inout) :: field
  1807. character (len=128), dimension(:), intent(inout) :: output_flags
  1808. real, dimension(:), intent(in), optional :: all_level_list
  1809. ! Local variables
  1810. integer :: i, j, istatus, isrclevel
  1811. integer, pointer, dimension(:) :: all_list
  1812. real :: rfillconst, rlevel, rsrclevel
  1813. type (fg_input) :: query_field
  1814. type (list_item), pointer, dimension(:) :: keys
  1815. character (len=128) :: asrcname
  1816. logical :: filled_all_lev
  1817. filled_all_lev = .false.
  1818. !
  1819. ! Get a list of all levels to be filled for this field
  1820. !
  1821. keys => list_get_keys(fill_lev_list(idx))
  1822. do i=1,list_length(fill_lev_list(idx))
  1823. !
  1824. ! First handle a specification for levels "all"
  1825. !
  1826. if (trim(keys(i)%ckey) == 'all') then
  1827. ! We only want to fill all levels if we haven't already filled "all" of them
  1828. if (.not. filled_all_lev) then
  1829. filled_all_lev = .true.
  1830. query_field%header%time_dependent = .true.
  1831. query_field%header%field = ' '
  1832. nullify(query_field%r_arr)
  1833. nullify(query_field%valid_mask)
  1834. nullify(query_field%modified_mask)
  1835. ! See if we are filling this level with a constant
  1836. call get_constant_fill_lev(keys(i)%cvalue, rfillconst, istatus)
  1837. if (istatus == 0) then
  1838. if (present(all_level_list)) then
  1839. do j=1,size(all_level_list)
  1840. call create_level(field, real(all_level_list(j)), idx, output_flags, rfillconst=rfillconst)
  1841. end do
  1842. else
  1843. query_field%header%field = level_template(idx)
  1844. nullify(all_list)
  1845. call storage_get_levels(query_field, all_list)
  1846. if (associated(all_list)) then
  1847. do j=1,size(all_list)
  1848. call create_level(field, real(all_list(j)), idx, output_flags, rfillconst=rfillconst)
  1849. end do
  1850. deallocate(all_list)
  1851. end if
  1852. end if
  1853. ! Else see if we are filling this level with a constant equal
  1854. ! to the value of the level
  1855. else if (trim(keys(i)%cvalue) == 'vertical_index') then
  1856. if (present(all_level_list)) then
  1857. do j=1,size(all_level_list)
  1858. call create_level(field, real(all_level_list(j)), idx, output_flags, &
  1859. rfillconst=real(all_level_list(j)))
  1860. end do
  1861. else
  1862. query_field%header%field = level_template(idx)
  1863. nullify(all_list)
  1864. call storage_get_levels(query_field, all_list)
  1865. if (associated(all_list)) then
  1866. do j=1,size(all_list)
  1867. call create_level(field, real(all_list(j)), idx, output_flags, rfillconst=real(all_list(j)))
  1868. end do
  1869. deallocate(all_list)
  1870. end if
  1871. end if
  1872. ! Else, we assume that it is a field from which we are copying levels
  1873. else
  1874. if (present(all_level_list)) then
  1875. do j=1,size(all_level_list)
  1876. call create_level(field, real(all_level_list(j)), idx, output_flags, &
  1877. asrcname=keys(i)%cvalue, rsrclevel=real(all_level_list(j)))
  1878. end do
  1879. else
  1880. query_field%header%field = keys(i)%cvalue ! Use same levels as source field, not level_template
  1881. nullify(all_list)
  1882. call storage_get_levels(query_field, all_list)
  1883. if (associated(all_list)) then
  1884. do j=1,size(all_list)
  1885. call create_level(field, real(all_list(j)), idx, output_flags, &
  1886. asrcname=keys(i)%cvalue, rsrclevel=real(all_list(j)))
  1887. end do
  1888. deallocate(all_list)
  1889. else
  1890. ! If the field doesn't have any levels (or does not exist) then we have not
  1891. ! really filled all levels at this point.
  1892. filled_all_lev = .false.
  1893. end if
  1894. end if
  1895. end if
  1896. end if
  1897. !
  1898. ! Handle individually specified levels
  1899. !
  1900. else
  1901. read(keys(i)%ckey,*) rlevel
  1902. ! See if we are filling this level with a constant
  1903. call get_constant_fill_lev(keys(i)%cvalue, rfillconst, istatus)
  1904. if (istatus == 0) then
  1905. call create_level(field, rlevel, idx, output_flags, rfillconst=rfillconst)
  1906. ! Otherwise, we are filling from another level
  1907. else
  1908. call get_fill_src_level(keys(i)%cvalue, asrcname, isrclevel)
  1909. rsrclevel = real(isrclevel)
  1910. call create_level(field, rlevel, idx, output_flags, &
  1911. asrcname=asrcname, rsrclevel=rsrclevel)
  1912. end if
  1913. end if
  1914. end do
  1915. if (associated(keys)) deallocate(keys)
  1916. end subroutine fill_field
  1917. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1918. ! Name: create_level
  1919. !
  1920. ! Purpose:
  1921. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1922. subroutine create_level(field_template, rlevel, idx, output_flags, &
  1923. rfillconst, asrcname, rsrclevel)
  1924. use storage_module
  1925. use interp_option_module
  1926. implicit none
  1927. ! Arguments
  1928. type (fg_input), intent(inout) :: field_template
  1929. real, intent(in) :: rlevel
  1930. integer, intent(in) :: idx
  1931. character (len=128), dimension(:), intent(inout) :: output_flags
  1932. real, intent(in), optional :: rfillconst, rsrclevel
  1933. character (len=128), intent(in), optional :: asrcname
  1934. ! Local variables
  1935. integer :: i, j, istatus
  1936. integer :: sm1,em1,sm2,em2
  1937. type (fg_input) :: query_field
  1938. !
  1939. ! Check to make sure optional arguments are sane
  1940. !
  1941. if (present(rfillconst) .and. (present(asrcname) .or. present(rsrclevel))) then
  1942. call mprintf(.true.,ERROR,'A call to create_level() cannot be given specifications '// &
  1943. 'for both a constant fill value and a source level.')
  1944. else if ((present(asrcname) .and. .not. present(rsrclevel)) .or. &
  1945. (.not. present(asrcname) .and. present(rsrclevel))) then
  1946. call mprintf(.true.,ERROR,'Neither or both of optional arguments asrcname and '// &
  1947. 'rsrclevel must be specified to subroutine create_level().')
  1948. else if (.not. present(rfillconst) .and. &
  1949. .not. present(asrcname) .and. &
  1950. .not. present(rsrclevel)) then
  1951. call mprintf(.true.,ERROR,'A call to create_level() must be given either a specification '// &
  1952. 'for a constant fill value or a source level.')
  1953. end if
  1954. query_field%header%time_dependent = .true.
  1955. query_field%header%field = field_template%header%field
  1956. query_field%header%vertical_level = rlevel
  1957. nullify(query_field%r_arr)
  1958. nullify(query_field%valid_mask)
  1959. nullify(query_field%modified_mask)
  1960. call storage_query_field(query_field, istatus)
  1961. if (istatus == 0) then
  1962. call mprintf(.true.,INFORM,'%s at level %f already exists; leaving it alone.', &
  1963. s1=field_template%header%field, f1=rlevel)
  1964. return
  1965. end if
  1966. sm1 = field_template%header%dim1(1)
  1967. em1 = field_template%header%dim1(2)
  1968. sm2 = field_template%header%dim2(1)
  1969. em2 = field_template%header%dim2(2)
  1970. !
  1971. ! Handle constant fill value case
  1972. !
  1973. if (present(rfillconst)) then
  1974. field_template%header%vertical_level = rlevel
  1975. allocate(field_template%r_arr(sm1:em1,sm2:em2))
  1976. allocate(field_template%valid_mask)
  1977. allocate(field_template%modified_mask)
  1978. call bitarray_create(field_template%valid_mask, em1-sm1+1, em2-sm2+1)
  1979. call bitarray_create(field_template%modified_mask, em1-sm1+1, em2-sm2+1)
  1980. field_template%r_arr = rfillconst
  1981. do j=sm2,em2
  1982. do i=sm1,em1
  1983. call bitarray_set(field_template%valid_mask, i-sm1+1, j-sm2+1)
  1984. end do
  1985. end do
  1986. call storage_put_field(field_template)
  1987. if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
  1988. output_flags(idx) = flag_in_output(idx)
  1989. end if
  1990. !
  1991. ! Handle source field and source level case
  1992. !
  1993. else if (present(asrcname) .and. present(rsrclevel)) then
  1994. query_field%header%field = ' '
  1995. query_field%header%field = asrcname
  1996. query_field%header%vertical_level = rsrclevel
  1997. ! Check to see whether the requested source field exists at the requested level
  1998. call storage_query_field(query_field, istatus)
  1999. if (istatus == 0) then
  2000. ! Read in requested field at requested level
  2001. call storage_get_field(query_field, istatus)
  2002. if ((query_field%header%dim1(1) /= field_template%header%dim1(1)) .or. &
  2003. (query_field%header%dim1(2) /= field_template%header%dim1(2)) .or. &
  2004. (query_field%header%dim2(1) /= field_template%header%dim2(1)) .or. &
  2005. (query_field%header%dim2(2) /= field_template%header%dim2(2))) then
  2006. call mprintf(.true.,ERROR,'Dimensions for %s do not match those of %s. This is '// &
  2007. 'probably because the staggerings of the fields do not match.', &
  2008. s1=query_field%header%field, s2=field_template%header%field)
  2009. end if
  2010. field_template%header%vertical_level = rlevel
  2011. allocate(field_template%r_arr(sm1:em1,sm2:em2))
  2012. allocate(field_template%valid_mask)
  2013. allocate(field_template%modified_mask)
  2014. call bitarray_create(field_template%valid_mask, em1-sm1+1, em2-sm2+1)
  2015. call bitarray_create(field_template%modified_mask, em1-sm1+1, em2-sm2+1)
  2016. field_template%r_arr = query_field%r_arr
  2017. ! We should retain information about which points in the field are valid
  2018. do j=sm2,em2
  2019. do i=sm1,em1
  2020. if (bitarray_test(query_field%valid_mask, i-sm1+1, j-sm2+1)) then
  2021. call bitarray_set(field_template%valid_mask, i-sm1+1, j-sm2+1)
  2022. end if
  2023. end do
  2024. end do
  2025. call storage_put_field(field_template)
  2026. if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
  2027. output_flags(idx) = flag_in_output(idx)
  2028. end if
  2029. else
  2030. call mprintf(.true.,INFORM,'Couldn''t find %s at level %f to fill level %f of %s.', &
  2031. s1=asrcname,f1=rsrclevel,f2=rlevel,s2=field_template%header%field)
  2032. end if
  2033. end if
  2034. end subroutine create_level
  2035. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2036. ! Name: accum_continuous
  2037. !
  2038. ! Purpose: Sum up all of the source data points whose nearest neighbor in the
  2039. ! model grid is the specified model grid point.
  2040. !
  2041. ! NOTE: When processing the source tile, those source points that are
  2042. ! closest to a different model grid point will be added to the totals for
  2043. ! such grid points; thus, an entire source tile will be processed at a time.
  2044. ! This routine really processes for all model grid points that are
  2045. ! within a source tile, and not just for a single grid point.
  2046. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2047. subroutine accum_continuous(src_array, &
  2048. src_min_x, src_max_x, src_min_y, src_max_y, src_min_z, src_max_z, bdr_width, &
  2049. dst_array, n, &
  2050. start_i, end_i, start_j, end_j, start_k, end_k, &
  2051. istagger, &
  2052. new_pts, msgval, maskval, mask_relational, mask_array, sr_x, sr_y)
  2053. use bitarray_module
  2054. use misc_definitions_module
  2055. implicit none
  2056. ! Arguments
  2057. integer, intent(in) :: start_i, end_i, start_j, end_j, start_k, end_k, istagger, &
  2058. src_min_x, src_max_x, src_min_y, src_max_y, src_min_z, src_max_z, bdr_width
  2059. real, intent(in) :: maskval, msgval
  2060. real, dimension(src_min_x:src_max_x, src_min_y:src_max_y, src_min_z:src_max_z), intent(in) :: src_array
  2061. real, dimension(start_i:end_i, start_j:end_j, start_k:end_k), intent(inout) :: dst_array, n
  2062. real, dimension(src_min_x:src_max_x, src_min_y:src_max_y), intent(in), optional :: mask_array
  2063. integer, intent(in), optional :: sr_x, sr_y
  2064. type (bitarray), intent(inout) :: new_pts
  2065. character(len=1), intent(in), optional :: mask_relational
  2066. ! Local variables
  2067. integer :: i, j
  2068. integer, pointer, dimension(:,:,:) :: where_maps_to
  2069. real :: rsr_x, rsr_y
  2070. rsr_x = 1.0
  2071. rsr_y = 1.0
  2072. if (present(sr_x)) rsr_x = real(sr_x)
  2073. if (present(sr_y)) rsr_y = real(sr_y)
  2074. allocate(where_maps_to(src_min_x:src_max_x,src_min_y:src_max_y,2))
  2075. do i=src_min_x,src_max_x
  2076. do j=src_min_y,src_max_y
  2077. where_maps_to(i,j,1) = NOT_PROCESSED
  2078. end do
  2079. end do
  2080. call process_continuous_block(src_array, where_maps_to, &
  2081. src_min_x, src_min_y, src_min_z, src_max_x, src_max_y, src_max_z, &
  2082. src_min_x+bdr_width, src_min_y, src_min_z, &
  2083. src_max_x-bdr_width, src_max_y, src_max_z, &
  2084. dst_array, n, start_i, end_i, start_j, end_j, start_k, end_k, &
  2085. istagger, &
  2086. new_pts, rsr_x, rsr_y, msgval, maskval, mask_relational, mask_array)
  2087. deallocate(where_maps_to)
  2088. end subroutine accum_continuous
  2089. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2090. ! Name: process_continuous_block
  2091. !
  2092. ! Purpose: To recursively process a subarray of continuous data, adding the
  2093. ! points in a block to the sum for their nearest grid point. The nearest
  2094. ! neighbor may be estimated in some cases; for example, if the four corners
  2095. ! of a subarray all have the same nearest grid point, all elements in the
  2096. ! subarray are added to that grid point.
  2097. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2098. recursive subroutine process_continuous_block(tile_array, where_maps_to, &
  2099. src_min_x, src_min_y, src_min_z, src_max_x, src_max_y, src_max_z, &
  2100. min_i, min_j, min_k, max_i, max_j, max_k, &
  2101. dst_array, n, &
  2102. start_x, end_x, start_y, end_y, start_z, end_z, &
  2103. istagger, &
  2104. new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
  2105. use bitarray_module
  2106. use llxy_module
  2107. use misc_definitions_module
  2108. implicit none
  2109. ! Arguments
  2110. integer, intent(in) :: min_i, min_j, min_k, max_i, max_j, max_k, &
  2111. src_min_x, src_min_y, src_min_z, src_max_x, src_max_y, src_max_z, &
  2112. start_x, end_x, start_y, end_y, start_z, end_z, istagger
  2113. integer, dimension(src_min_x:src_max_x,src_min_y:src_max_y,2), intent(inout) :: where_maps_to
  2114. real, intent(in) :: sr_x, sr_y, maskval, msgval
  2115. real, dimension(src_min_x:src_max_x,src_min_y:src_max_y,src_min_z:src_max_z), intent(in) :: tile_array
  2116. real, dimension(src_min_x:src_max_x,src_min_y:src_max_y), intent(in), optional :: mask_array
  2117. real, dimension(start_x:end_x,start_y:end_y,start_z:end_z), intent(inout) :: dst_array, n
  2118. type (bitarray), intent(inout) :: new_pts
  2119. character(len=1), intent(in), optional :: mask_relational
  2120. ! Local variables
  2121. integer :: orig_selected_domain, x_dest, y_dest, i, j, k, center_i, center_j
  2122. real :: lat_corner, lon_corner, rx, ry
  2123. ! Compute the model grid point that the corners of the rectangle to be
  2124. ! processed map to
  2125. ! Lower-left corner
  2126. if (where_maps_to(min_i,min_j,1) == NOT_PROCESSED) then
  2127. orig_selected_domain = iget_selected_domain()
  2128. call select_domain(SOURCE_PROJ)
  2129. call xytoll(real(min_i), real(min_j), lat_corner, lon_corner, istagger)
  2130. call select_domain(1)
  2131. call lltoxy(lat_corner, lon_corner, rx, ry, istagger)
  2132. rx = (rx - 1.0)*sr_x + 1.0
  2133. ry = (ry - 1.0)*sr_y + 1.0
  2134. call select_domain(orig_selected_domain)
  2135. if (real(start_x) <= rx .and. rx <= real(end_x) .and. &
  2136. real(start_y) <= ry .and. ry <= real(end_y)) then
  2137. where_maps_to(min_i,min_j,1) = nint(rx)
  2138. where_maps_to(min_i,min_j,2) = nint(ry)
  2139. else
  2140. where_maps_to(min_i,min_j,1) = OUTSIDE_DOMAIN
  2141. end if
  2142. end if
  2143. ! Upper-left corner
  2144. if (where_maps_to(min_i,max_j,1) == NOT_PROCESSED) then
  2145. orig_selected_domain = iget_selected_domain()
  2146. call select_domain(SOURCE_PROJ)
  2147. call xytoll(real(min_i), real(max_j), lat_corner, lon_corner, istagger)
  2148. call select_domain(1)
  2149. call lltoxy(lat_corner, lon_corner, rx, ry, istagger)
  2150. rx = (rx - 1.0)*sr_x + 1.0
  2151. ry = (ry - 1.0)*sr_y + 1.0
  2152. call select_domain(orig_selected_domain)
  2153. if (real(start_x) <= rx .and. rx <= real(end_x) .and. &
  2154. real(start_y) <= ry .and. ry <= real(end_y)) then
  2155. where_maps_to(min_i,max_j,1) = nint(rx)
  2156. where_maps_to(min_i,max_j,2) = nint(ry)
  2157. else
  2158. where_maps_to(min_i,max_j,1) = OUTSIDE_DOMAIN
  2159. end if
  2160. end if
  2161. ! Upper-right corner
  2162. if (where_maps_to(max_i,max_j,1) == NOT_PROCESSED) then
  2163. orig_selected_domain = iget_selected_domain()
  2164. call select_domain(SOURCE_PROJ)
  2165. call xytoll(real(max_i), real(max_j), lat_corner, lon_corner, istagger)
  2166. call select_domain(1)
  2167. call lltoxy(lat_corner, lon_corner, rx, ry, istagger)
  2168. rx = (rx - 1.0)*sr_x + 1.0
  2169. ry = (ry - 1.0)*sr_y + 1.0
  2170. call select_domain(orig_selected_domain)
  2171. if (real(start_x) <= rx .and. rx <= real(end_x) .and. &
  2172. real(start_y) <= ry .and. ry <= real(end_y)) then
  2173. where_maps_to(max_i,max_j,1) = nint(rx)
  2174. where_maps_to(max_i,max_j,2) = nint(ry)
  2175. else
  2176. where_maps_to(max_i,max_j,1) = OUTSIDE_DOMAIN
  2177. end if
  2178. end if
  2179. ! Lower-right corner
  2180. if (where_maps_to(max_i,min_j,1) == NOT_PROCESSED) then
  2181. orig_selected_domain = iget_selected_domain()
  2182. call select_domain(SOURCE_PROJ)
  2183. call xytoll(real(max_i), real(min_j), lat_corner, lon_corner, istagger)
  2184. call select_domain(1)
  2185. call lltoxy(lat_corner, lon_corner, rx, ry, istagger)
  2186. rx = (rx - 1.0)*sr_x + 1.0
  2187. ry = (ry - 1.0)*sr_y + 1.0
  2188. call select_domain(orig_selected_domain)
  2189. if (real(start_x) <= rx .and. rx <= real(end_x) .and. &
  2190. real(start_y) <= ry .and. ry <= real(end_y)) then
  2191. where_maps_to(max_i,min_j,1) = nint(rx)
  2192. where_maps_to(max_i,min_j,2) = nint(ry)
  2193. else
  2194. where_maps_to(max_i,min_j,1) = OUTSIDE_DOMAIN
  2195. end if
  2196. end if
  2197. ! If all four corners map to same model grid point, accumulate the
  2198. ! entire rectangle
  2199. if (where_maps_to(min_i,min_j,1) == where_maps_to(min_i,max_j,1) .and. &
  2200. where_maps_to(min_i,min_j,1) == where_maps_to(max_i,max_j,1) .and. &
  2201. where_maps_to(min_i,min_j,1) == where_maps_to(max_i,min_j,1) .and. &
  2202. where_maps_to(min_i,min_j,2) == where_maps_to(min_i,max_j,2) .and. &
  2203. where_maps_to(min_i,min_j,2) == where_maps_to(max_i,max_j,2) .and. &
  2204. where_maps_to(min_i,min_j,2) == where_maps_to(max_i,min_j,2) .and. &
  2205. where_maps_to(min_i,min_j,1) /= OUTSIDE_DOMAIN) then
  2206. x_dest = where_maps_to(min_i,min_j,1)
  2207. y_dest = where_maps_to(min_i,min_j,2)
  2208. ! If this grid point was already given a value from higher-priority source data,
  2209. ! there is nothing to do.
  2210. ! if (.not. bitarray_test(processed_pts, x_dest-start_x+1, y_dest-start_y+1)) then
  2211. ! If this grid point has never been given a value by this level of source data,
  2212. ! initialize the point
  2213. if (.not. bitarray_test(new_pts, x_dest-start_x+1, y_dest-start_y+1)) then
  2214. do k=min_k,max_k
  2215. dst_array(x_dest,y_dest,k) = 0.
  2216. end do
  2217. end if
  2218. ! Sum all the points whose nearest neighbor is this grid point
  2219. if (present(mask_array) .and. present(mask_relational)) then
  2220. do i=min_i,max_i
  2221. do j=min_j,max_j
  2222. do k=min_k,max_k
  2223. ! Ignore masked/missing values in the source data
  2224. if (tile_array(i,j,k) /= msgval) then
  2225. if (mask_relational == ' ' .and. mask_array(i,j) /= maskval) then
  2226. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2227. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2228. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2229. else if (mask_relational == '<' .and. mask_array(i,j) >= maskval) then
  2230. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2231. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2232. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2233. else if (mask_relational == '>' .and. mask_array(i,j) <= maskval) then
  2234. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2235. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2236. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2237. end if
  2238. end if
  2239. end do
  2240. end do
  2241. end do
  2242. else if (present(mask_array)) then
  2243. do i=min_i,max_i
  2244. do j=min_j,max_j
  2245. do k=min_k,max_k
  2246. ! Ignore masked/missing values in the source data
  2247. if ((tile_array(i,j,k) /= msgval) .and. &
  2248. (mask_array(i,j) /= maskval)) then
  2249. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2250. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2251. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2252. end if
  2253. end do
  2254. end do
  2255. end do
  2256. else
  2257. do i=min_i,max_i
  2258. do j=min_j,max_j
  2259. do k=min_k,max_k
  2260. ! Ignore masked/missing values in the source data
  2261. if ((tile_array(i,j,k) /= msgval)) then
  2262. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2263. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2264. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2265. end if
  2266. end do
  2267. end do
  2268. end do
  2269. end if
  2270. ! end if
  2271. ! Rectangle is a square of four points, and we can simply deal with each of the points
  2272. else if (((max_i - min_i + 1) <= 2) .and. ((max_j - min_j + 1) <= 2)) then
  2273. do i=min_i,max_i
  2274. do j=min_j,max_j
  2275. x_dest = where_maps_to(i,j,1)
  2276. y_dest = where_maps_to(i,j,2)
  2277. if (x_dest /= OUTSIDE_DOMAIN) then
  2278. ! if (.not. bitarray_test(processed_pts, x_dest-start_x+1, y_dest-start_y+1)) then
  2279. if (.not. bitarray_test(new_pts, x_dest-start_x+1, y_dest-start_y+1)) then
  2280. do k=min_k,max_k
  2281. dst_array(x_dest,y_dest,k) = 0.
  2282. end do
  2283. end if
  2284. if (present(mask_array) .and. present(mask_relational)) then
  2285. do k=min_k,max_k
  2286. ! Ignore masked/missing values
  2287. if (tile_array(i,j,k) /= msgval) then
  2288. if (mask_relational == ' ' .and. mask_array(i,j) /= maskval) then
  2289. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2290. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2291. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2292. else if (mask_relational == '<' .and. mask_array(i,j) >= maskval) then
  2293. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2294. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2295. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2296. else if (mask_relational == '>' .and. mask_array(i,j) <= maskval) then
  2297. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2298. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2299. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2300. end if
  2301. end if
  2302. end do
  2303. else if (present(mask_array)) then
  2304. do k=min_k,max_k
  2305. ! Ignore masked/missing values
  2306. if ((tile_array(i,j,k) /= msgval) .and. &
  2307. (mask_array(i,j) /= maskval)) then
  2308. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2309. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2310. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2311. end if
  2312. end do
  2313. else
  2314. do k=min_k,max_k
  2315. ! Ignore masked/missing values
  2316. if ((tile_array(i,j,k) /= msgval)) then
  2317. dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
  2318. n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
  2319. call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
  2320. end if
  2321. end do
  2322. end if
  2323. ! end if
  2324. end if
  2325. end do
  2326. end do
  2327. ! Not all corners map to the same grid point, and the rectangle contains more than
  2328. ! four points
  2329. else
  2330. center_i = (max_i + min_i)/2
  2331. center_j = (max_j + min_j)/2
  2332. ! Recursively process lower-left rectangle
  2333. call process_continuous_block(tile_array, where_maps_to, &
  2334. src_min_x, src_min_y, src_min_z, &
  2335. src_max_x, src_max_y, src_max_z, &
  2336. min_i, min_j, min_k, &
  2337. center_i, center_j, max_k, &
  2338. dst_array, n, &
  2339. start_x, end_x, start_y, end_y, start_z, end_z, &
  2340. istagger, &
  2341. new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
  2342. if (center_i < max_i) then
  2343. ! Recursively process lower-right rectangle
  2344. call process_continuous_block(tile_array, where_maps_to, &
  2345. src_min_x, src_min_y, src_min_z, &
  2346. src_max_x, src_max_y, src_max_z, &
  2347. center_i+1, min_j, min_k, max_i, &
  2348. center_j, max_k, &
  2349. dst_array, n, &
  2350. start_x, end_x, start_y, &
  2351. end_y, start_z, end_z, &
  2352. istagger, &
  2353. new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
  2354. end if
  2355. if (center_j < max_j) then
  2356. ! Recursively process upper-left rectangle
  2357. call process_continuous_block(tile_array, where_maps_to, &
  2358. src_min_x, src_min_y, src_min_z, &
  2359. src_max_x, src_max_y, src_max_z, &
  2360. min_i, center_j+1, min_k, center_i, &
  2361. max_j, max_k, &
  2362. dst_array, n, &
  2363. start_x, end_x, start_y, &
  2364. end_y, start_z, end_z, &
  2365. istagger, &
  2366. new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
  2367. end if
  2368. if (center_i < max_i .and. center_j < max_j) then
  2369. ! Recursively process upper-right rectangle
  2370. call process_continuous_block(tile_array, where_maps_to, &
  2371. src_min_x, src_min_y, src_min_z, &
  2372. src_max_x, src_max_y, src_max_z, &
  2373. center_i+1, center_j+1, min_k, max_i, &
  2374. max_j, max_k, &
  2375. dst_array, n, &
  2376. start_x, end_x, start_y, &
  2377. end_y, start_z, end_z, &
  2378. istagger, &
  2379. new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
  2380. end if
  2381. end if
  2382. end subroutine process_continuous_block
  2383. end module process_domain_module