1 module process_domain_module
7 type (mpas_mesh_type), save :: mpas_source_mesh
8 type (target_mesh_type), save :: wrf_target_mesh_m, wrf_target_mesh_u, wrf_target_mesh_v
9 type (remap_info_type), save :: remap_info_m, remap_info_u, remap_info_v
10 real, dimension(:,:), allocatable, target :: xlat_rad, xlon_rad, xlat_u_rad, xlon_u_rad, xlat_v_rad, xlon_v_rad
14 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
15 ! Name: process_domain
18 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
19 subroutine process_domain(n, extra_row, extra_col)
23 use interp_option_module
24 use misc_definitions_module
31 integer, intent(in) :: n
32 logical, intent(in) :: extra_row, extra_col
36 integer :: i, t, dyn_opt, &
37 we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
38 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
39 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
40 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
41 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
43 west_east_dim, south_north_dim, bottom_top_dim, map_proj, &
44 is_water, is_lake, is_ice, is_urban, i_soilwater, &
45 grid_id, parent_id, i_parent_start, j_parent_start, &
46 i_parent_end, j_parent_end, parent_grid_ratio, sub_x, sub_y, num_land_cat, process_bdy_width
47 real :: cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
48 dom_dx, dom_dy, pole_lat, pole_lon
49 real, dimension(16) :: corner_lats, corner_lons
50 real, pointer, dimension(:,:) :: landmask
51 real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
52 logical, allocatable, dimension(:) :: got_this_field, got_const_field
53 character (len=19) :: valid_date, temp_date
54 character (len=128) :: title, mminlu
55 character (len=128), allocatable, dimension(:) :: output_flags, td_output_flags
56 character (len=128), dimension(:), pointer :: geogrid_flags
58 ! CWH Initialize local pointer variables
66 nullify(geogrid_flags)
68 ! Compute number of times that we will process
69 call geth_idts(end_date(n), start_date(n), idiff)
70 call mprintf((idiff < 0),ERROR,'Ending date is earlier than starting date in namelist for domain %i.', i1=n)
72 n_times = idiff / interval_seconds
74 ! Check that the interval evenly divides the range of times to process
75 call mprintf((mod(idiff, interval_seconds) /= 0),WARN, &
76 'In namelist, interval_seconds does not evenly divide '// &
77 '(end_date - start_date) for domain %i. Only %i time periods '// &
78 'will be processed.', i1=n, i2=n_times)
80 ! Initialize the storage module
81 call mprintf(.true.,LOGFILE,'Initializing storage module')
85 ! Do time-independent processing
87 call get_static_fields(n, dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, map_proj, &
88 we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
89 we_patch_s, we_patch_e, &
90 we_patch_stag_s, we_patch_stag_e, &
91 sn_patch_s, sn_patch_e, &
92 sn_patch_stag_s, sn_patch_stag_e, &
93 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
94 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
95 mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
97 i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
98 parent_grid_ratio, sub_x, sub_y, &
99 cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
100 pole_lat, pole_lon, dom_dx, dom_dy, landmask, xlat, xlon, xlat_u, xlon_u, &
101 xlat_v, xlon_v, corner_lats, corner_lons, title, geogrid_flags)
104 allocate(output_flags(num_entries))
105 allocate(got_const_field(num_entries))
108 output_flags(i) = ' '
109 got_const_field(i) = .false.
112 ! This call is to process the constant met fields (SST or SEAICE, for example)
113 ! That we process constant fields is indicated by the first argument
114 call process_single_met_time(.true., temp_date, n, extra_row, extra_col, xlat, xlon, &
115 xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
117 west_east_dim, south_north_dim, &
118 we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
119 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
120 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
121 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
122 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
124 map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
125 grid_id, parent_id, i_parent_start, &
126 j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
127 cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
128 pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
129 corner_lats, corner_lons, output_flags, geogrid_flags, 0)
132 ! Begin time-dependent processing
135 allocate(td_output_flags(num_entries))
136 allocate(got_this_field (num_entries))
138 ! Loop over all times to be processed for this domain
141 call geth_newdate(valid_date, trim(start_date(n)), t*interval_seconds)
144 if (mod(interval_seconds,3600) == 0) then
145 write(temp_date,'(a13)') valid_date(1:10)//'_'//valid_date(12:13)
146 else if (mod(interval_seconds,60) == 0) then
147 write(temp_date,'(a16)') valid_date(1:10)//'_'//valid_date(12:16)
149 write(temp_date,'(a19)') valid_date(1:10)//'_'//valid_date(12:19)
152 call mprintf(.true.,STDOUT, ' Processing %s', s1=trim(temp_date))
153 call mprintf(.true.,LOGFILE, 'Preparing to process output time %s', s1=temp_date)
156 td_output_flags(i) = output_flags(i)
157 got_this_field(i) = got_const_field(i)
161 process_bdy_width = process_only_bdy
163 process_bdy_width = 0
166 call process_single_met_time(.false., temp_date, n, extra_row, extra_col, xlat, xlon, &
167 xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
169 west_east_dim, south_north_dim, &
170 we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
171 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
172 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
173 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
174 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
176 map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
177 grid_id, parent_id, i_parent_start, &
178 j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
179 cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
180 pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
181 corner_lats, corner_lons, td_output_flags, geogrid_flags, process_bdy_width)
183 end do ! Loop over n_times
186 deallocate(td_output_flags)
187 deallocate(got_this_field)
189 deallocate(output_flags)
190 deallocate(got_const_field)
192 if (associated(geogrid_flags)) deallocate(geogrid_flags)
194 call storage_delete_all()
196 istatus = mpas_mesh_free(mpas_source_mesh)
198 if (allocated(xlat_rad)) deallocate(xlat_rad)
199 if (allocated(xlon_rad)) deallocate(xlon_rad)
200 if (allocated(xlat_u_rad)) deallocate(xlat_u_rad)
201 if (allocated(xlon_u_rad)) deallocate(xlon_u_rad)
202 if (allocated(xlat_v_rad)) deallocate(xlat_v_rad)
203 if (allocated(xlon_v_rad)) deallocate(xlon_v_rad)
204 istatus = target_mesh_free(wrf_target_mesh_m)
205 istatus = target_mesh_free(wrf_target_mesh_u)
206 istatus = target_mesh_free(wrf_target_mesh_v)
208 istatus = remap_info_free(remap_info_m)
209 istatus = remap_info_free(remap_info_u)
210 istatus = remap_info_free(remap_info_v)
212 end subroutine process_domain
215 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
216 ! Name: get_static_fields
219 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
220 subroutine get_static_fields(n, dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, &
222 we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
223 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
224 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
225 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
226 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
227 mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
228 grid_id, parent_id, &
229 i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
230 parent_grid_ratio, sub_x, sub_y, &
231 cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
232 pole_lat, pole_lon, dom_dx, dom_dy, landmask, xlat, xlon, xlat_u, xlon_u, &
233 xlat_v, xlon_v, corner_lats, corner_lons, title, geogrid_flags)
246 integer, intent(in) :: n
247 integer, intent(inout) :: dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, &
249 we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
250 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
251 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
252 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
253 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
254 is_water, is_lake, is_ice, is_urban, i_soilwater, grid_id, parent_id, &
255 i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
256 parent_grid_ratio, sub_x, sub_y, num_land_cat
257 real, pointer, dimension(:,:) :: landmask
258 real, intent(inout) :: cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
259 dom_dx, dom_dy, pole_lat, pole_lon
260 real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
261 real, dimension(16), intent(out) :: corner_lats, corner_lons
262 character (len=128), intent(inout) :: title, mminlu
263 character (len=128), dimension(:), pointer :: geogrid_flags
266 integer :: istatus, i, j, k, sp1, ep1, sp2, ep2, sp3, ep3, &
267 lh_mult, rh_mult, bh_mult, th_mult, subx, suby
268 integer :: we_mem_subgrid_s, we_mem_subgrid_e, &
269 sn_mem_subgrid_s, sn_mem_subgrid_e
270 integer :: we_patch_subgrid_s, we_patch_subgrid_e, &
271 sn_patch_subgrid_s, sn_patch_subgrid_e
272 real, pointer, dimension(:,:,:) :: real_array
273 character (len=3) :: memorder
274 character (len=128) :: grid_type, datestr, cname, stagger, cunits, cdesc, ctemp
275 character (len=128), dimension(3) :: dimnames
276 type (fg_input) :: field
277 type (list) :: static_list, flag_list
278 type (list_item), dimension(:), pointer :: static_list_array
280 call list_init(static_list)
282 ! CWH Initialize local pointer variables
285 ! Initialize the input module to read static input data for this domain
286 call mprintf(.true.,LOGFILE,'Opening static input file.')
287 call input_init(n, istatus)
288 call mprintf((istatus /= 0),ERROR, 'input_init(): Error opening input for domain %i.', i1=n)
290 ! Read global attributes from the static data input file
291 call mprintf(.true.,LOGFILE,'Reading static global attributes.')
292 call read_global_attrs(title, datestr, grid_type, dyn_opt, west_east_dim, &
293 south_north_dim, bottom_top_dim, &
294 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
295 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
296 map_proj, mminlu, num_land_cat, &
297 is_water, is_lake, is_ice, is_urban, i_soilwater, &
298 grid_id, parent_id, i_parent_start, &
299 j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
300 cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, &
301 truelat2, pole_lat, pole_lon, parent_grid_ratio, &
302 corner_lats, corner_lons, sub_x, sub_y)
306 if (grid_type(1:1) == 'C') then
307 we_dom_e = west_east_dim - 1
308 sn_dom_e = south_north_dim - 1
309 else if (grid_type(1:1) == 'E') then
310 we_dom_e = west_east_dim
311 sn_dom_e = south_north_dim
314 ! Given the full dimensions of this domain, find out the range of indices
315 ! that will be worked on by this processor. This information is given by
316 ! my_minx, my_miny, my_maxx, my_maxy
317 call parallel_get_tile_dims(west_east_dim, south_north_dim)
319 ! Must figure out patch dimensions from info in parallel module
320 if (nprocs > 1 .and. .not. do_tiled_input) then
323 we_patch_stag_s = my_minx
324 we_patch_e = my_maxx - 1
326 sn_patch_stag_s = my_miny
327 sn_patch_e = my_maxy - 1
329 if (gridtype == 'C') then
330 if (my_x /= nproc_x - 1) then
331 we_patch_e = we_patch_e + 1
332 we_patch_stag_e = we_patch_e
334 we_patch_stag_e = we_patch_e + 1
336 if (my_y /= nproc_y - 1) then
337 sn_patch_e = sn_patch_e + 1
338 sn_patch_stag_e = sn_patch_e
340 sn_patch_stag_e = sn_patch_e + 1
342 else if (gridtype == 'E') then
343 we_patch_e = we_patch_e + 1
344 sn_patch_e = sn_patch_e + 1
345 we_patch_stag_e = we_patch_e
346 sn_patch_stag_e = sn_patch_e
351 ! Compute multipliers for halo width; these must be 0/1
357 if (my_x /= (nproc_x-1)) then
367 if (my_y /= (nproc_y-1)) then
373 we_mem_s = we_patch_s - HALO_WIDTH*lh_mult
374 we_mem_e = we_patch_e + HALO_WIDTH*rh_mult
375 sn_mem_s = sn_patch_s - HALO_WIDTH*bh_mult
376 sn_mem_e = sn_patch_e + HALO_WIDTH*th_mult
377 we_mem_stag_s = we_patch_stag_s - HALO_WIDTH*lh_mult
378 we_mem_stag_e = we_patch_stag_e + HALO_WIDTH*rh_mult
379 sn_mem_stag_s = sn_patch_stag_s - HALO_WIDTH*bh_mult
380 sn_mem_stag_e = sn_patch_stag_e + HALO_WIDTH*th_mult
382 ! Initialize a proj_info type for the destination grid projection. This will
383 ! primarily be used for rotating Earth-relative winds to grid-relative winds
384 call set_domain_projection(map_proj, stand_lon, truelat1, truelat2, &
385 dom_dx, dom_dy, dom_dx, dom_dy, west_east_dim, &
386 south_north_dim, real(west_east_dim)/2., &
387 real(south_north_dim)/2.,cen_lat, cen_lon, &
390 ! Read static fields using the input module; we know that there are no more
391 ! fields to be read when read_next_field() returns a non-zero status.
393 do while (istatus == 0)
394 call read_next_field(sp1, ep1, sp2, ep2, sp3, ep3, cname, cunits, cdesc, &
395 memorder, stagger, dimnames, subx, suby, &
397 if (istatus == 0) then
399 call mprintf(.true.,LOGFILE, 'Read in static field %s.',s1=cname)
400 call list_insert(static_list, ckey=cname, cvalue=cname)
402 ! We will also keep copies in core of the lat/lon arrays, for use in
403 ! interpolation of the met fields to the model grid.
404 ! For now, we assume that the lat/lon arrays will have known field names
405 if (index(cname, 'XLAT_M') /= 0 .and. &
406 len_trim(cname) == len_trim('XLAT_M')) then
407 allocate(xlat(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
408 xlat(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
409 call exchange_halo_r(xlat, &
410 we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
411 we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
413 else if (index(cname, 'XLONG_M') /= 0 .and. &
414 len_trim(cname) == len_trim('XLONG_M')) then
415 allocate(xlon(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
416 xlon(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
417 call exchange_halo_r(xlon, &
418 we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
419 we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
421 else if (index(cname, 'XLAT_U') /= 0 .and. &
422 len_trim(cname) == len_trim('XLAT_U')) then
423 allocate(xlat_u(we_mem_stag_s:we_mem_stag_e,sn_mem_s:sn_mem_e))
424 xlat_u(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
425 call exchange_halo_r(xlat_u, &
426 we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
427 we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
429 else if (index(cname, 'XLONG_U') /= 0 .and. &
430 len_trim(cname) == len_trim('XLONG_U')) then
431 allocate(xlon_u(we_mem_stag_s:we_mem_stag_e,sn_mem_s:sn_mem_e))
432 xlon_u(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
433 call exchange_halo_r(xlon_u, &
434 we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
435 we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
437 else if (index(cname, 'XLAT_V') /= 0 .and. &
438 len_trim(cname) == len_trim('XLAT_V')) then
439 allocate(xlat_v(we_mem_s:we_mem_e,sn_mem_stag_s:sn_mem_stag_e))
440 xlat_v(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(:,:,1)
441 call exchange_halo_r(xlat_v, &
442 we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
443 we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
445 else if (index(cname, 'XLONG_V') /= 0 .and. &
446 len_trim(cname) == len_trim('XLONG_V')) then
447 allocate(xlon_v(we_mem_s:we_mem_e,sn_mem_stag_s:sn_mem_stag_e))
448 xlon_v(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(:,:,1)
449 call exchange_halo_r(xlon_v, &
450 we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
451 we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
453 else if (index(cname, 'LANDMASK') /= 0 .and. &
454 len_trim(cname) == len_trim('LANDMASK')) then
455 allocate(landmask(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
456 landmask(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
457 call exchange_halo_r(landmask, &
458 we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
459 we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
464 we_mem_subgrid_s = (we_mem_s + HALO_WIDTH*lh_mult - 1)*subx - HALO_WIDTH*lh_mult + 1
465 we_mem_subgrid_e = (we_mem_e + (1-rh_mult) - HALO_WIDTH*rh_mult )*subx + HALO_WIDTH*rh_mult
466 we_patch_subgrid_s = (we_patch_s - 1)*subx + 1
467 we_patch_subgrid_e = (we_patch_e + (1-rh_mult) )*subx
470 sn_mem_subgrid_s = (sn_mem_s + HALO_WIDTH*bh_mult - 1)*suby - HALO_WIDTH*bh_mult + 1
471 sn_mem_subgrid_e = (sn_mem_e + (1-th_mult) - HALO_WIDTH*th_mult )*suby + HALO_WIDTH*th_mult
472 sn_patch_subgrid_s = (sn_patch_s - 1)*suby + 1
473 sn_patch_subgrid_e = (sn_patch_e + (1-th_mult) )*suby
476 ! Having read in a field, we write each level individually to the
477 ! storage module; levels will be reassembled later on when they
480 field%header%sr_x=subx
481 field%header%sr_y=suby
482 field%header%version = 1
483 field%header%date = start_date(n)
484 field%header%time_dependent = .false.
485 field%header%mask_field = .false.
486 field%header%constant_field = .false.
487 field%header%forecast_hour = 0.0
488 field%header%fg_source = 'geogrid_model'
489 field%header%field = cname
490 field%header%units = cunits
491 field%header%description = cdesc
492 field%header%vertical_coord = dimnames(3)
493 field%header%vertical_level = k
494 field%header%array_order = memorder
495 field%header%is_wind_grid_rel = .true.
496 field%header%array_has_missing_values = .false.
497 if (gridtype == 'C') then
498 if (subx > 1 .or. suby > 1) then
499 field%map%stagger = M
500 field%header%dim1(1) = we_mem_subgrid_s
501 field%header%dim1(2) = we_mem_subgrid_e
502 field%header%dim2(1) = sn_mem_subgrid_s
503 field%header%dim2(2) = sn_mem_subgrid_e
504 else if (trim(stagger) == 'M') then
505 field%map%stagger = M
506 field%header%dim1(1) = we_mem_s
507 field%header%dim1(2) = we_mem_e
508 field%header%dim2(1) = sn_mem_s
509 field%header%dim2(2) = sn_mem_e
510 else if (trim(stagger) == 'U') then
511 field%map%stagger = U
512 field%header%dim1(1) = we_mem_stag_s
513 field%header%dim1(2) = we_mem_stag_e
514 field%header%dim2(1) = sn_mem_s
515 field%header%dim2(2) = sn_mem_e
516 else if (trim(stagger) == 'V') then
517 field%map%stagger = V
518 field%header%dim1(1) = we_mem_s
519 field%header%dim1(2) = we_mem_e
520 field%header%dim2(1) = sn_mem_stag_s
521 field%header%dim2(2) = sn_mem_stag_e
522 else if (trim(stagger) == 'CORNER') then
523 field%map%stagger = CORNER
524 field%header%dim1(1) = we_mem_stag_s
525 field%header%dim1(2) = we_mem_stag_e
526 field%header%dim2(1) = sn_mem_stag_s
527 field%header%dim2(2) = sn_mem_stag_e
529 else if (gridtype == 'E') then
530 if (trim(stagger) == 'M') then
531 field%map%stagger = HH
532 else if (trim(stagger) == 'V') then
533 field%map%stagger = VV
535 field%header%dim1(1) = we_mem_s
536 field%header%dim1(2) = we_mem_e
537 field%header%dim2(1) = sn_mem_s
538 field%header%dim2(2) = sn_mem_e
541 allocate(field%valid_mask)
543 if (subx > 1 .or. suby > 1) then
544 allocate(field%r_arr(we_mem_subgrid_s:we_mem_subgrid_e,&
545 sn_mem_subgrid_s:sn_mem_subgrid_e))
546 field%r_arr(we_patch_subgrid_s:we_patch_subgrid_e,sn_patch_subgrid_s:sn_patch_subgrid_e) = &
547 real_array(sp1:ep1,sp2:ep2,k)
548 call exchange_halo_r(field%r_arr, &
549 we_mem_subgrid_s, we_mem_subgrid_e, sn_mem_subgrid_s, sn_mem_subgrid_e, 1, 1, &
550 we_patch_subgrid_s, we_patch_subgrid_e, sn_patch_subgrid_s, sn_patch_subgrid_e, 1, 1)
551 call bitarray_create(field%valid_mask, &
552 (we_mem_subgrid_e-we_mem_subgrid_s)+1, &
553 (sn_mem_subgrid_e-sn_mem_subgrid_s)+1)
554 do j=1,(sn_mem_subgrid_e-sn_mem_subgrid_s)+1
555 do i=1,(we_mem_subgrid_e-we_mem_subgrid_s)+1
556 call bitarray_set(field%valid_mask, i, j)
560 else if (field%map%stagger == M .or. &
561 field%map%stagger == HH .or. &
562 field%map%stagger == VV) then
563 allocate(field%r_arr(we_mem_s:we_mem_e,&
565 field%r_arr(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(sp1:ep1,sp2:ep2,k)
566 call exchange_halo_r(field%r_arr, &
567 we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
568 we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
569 call bitarray_create(field%valid_mask, &
570 (we_mem_e-we_mem_s)+1, &
571 (sn_mem_e-sn_mem_s)+1)
572 do j=1,(sn_mem_e-sn_mem_s)+1
573 do i=1,(we_mem_e-we_mem_s)+1
574 call bitarray_set(field%valid_mask, i, j)
577 else if (field%map%stagger == U) then
578 allocate(field%r_arr(we_mem_stag_s:we_mem_stag_e,&
580 field%r_arr(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(sp1:ep1,sp2:ep2,k)
581 call exchange_halo_r(field%r_arr, &
582 we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
583 we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
584 call bitarray_create(field%valid_mask, &
585 (we_mem_stag_e-we_mem_stag_s)+1, &
586 (sn_mem_e-sn_mem_s)+1)
587 do j=1,(sn_mem_e-sn_mem_s)+1
588 do i=1,(we_mem_stag_e-we_mem_stag_s)+1
589 call bitarray_set(field%valid_mask, i, j)
592 else if (field%map%stagger == V) then
593 allocate(field%r_arr(we_mem_s:we_mem_e,&
594 sn_mem_stag_s:sn_mem_stag_e))
595 field%r_arr(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(sp1:ep1,sp2:ep2,k)
596 call exchange_halo_r(field%r_arr, &
597 we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
598 we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
599 call bitarray_create(field%valid_mask, &
600 (we_mem_e-we_mem_s)+1, &
601 (sn_mem_stag_e-sn_mem_stag_s)+1)
602 do j=1,(sn_mem_stag_e-sn_mem_stag_s)+1
603 do i=1,(we_mem_e-we_mem_s)+1
604 call bitarray_set(field%valid_mask, i, j)
607 else if (field%map%stagger == CORNER) then
608 allocate(field%r_arr(we_mem_stag_s:we_mem_stag_e,&
609 sn_mem_stag_s:sn_mem_stag_e))
610 field%r_arr(we_patch_stag_s:we_patch_stag_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(sp1:ep1,sp2:ep2,k)
611 call exchange_halo_r(field%r_arr, &
612 we_mem_stag_s, we_mem_stag_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
613 we_patch_stag_s, we_patch_stag_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
614 call bitarray_create(field%valid_mask, &
615 (we_mem_stag_e-we_mem_stag_s)+1, &
616 (sn_mem_stag_e-sn_mem_stag_s)+1)
617 do j=1,(sn_mem_stag_e-sn_mem_stag_s)+1
618 do i=1,(we_mem_stag_e-we_mem_stag_s)+1
619 call bitarray_set(field%valid_mask, i, j)
624 nullify(field%modified_mask)
626 call storage_put_field(field)
630 end if ! if (istatus == 0)
631 end do ! do while (istatus == 0)
633 static_list_array => list_get_keys(static_list)
634 call list_init(flag_list)
635 do i=1,size(static_list_array)
637 ctemp = 'FLAG_'//trim(static_list_array(i)%ckey)
638 call ext_get_dom_ti_integer_scalar(ctemp, istatus, suppress_errors=.true.)
639 if (istatus == 1) call list_insert(flag_list, ckey=ctemp, cvalue=ctemp)
641 deallocate(static_list_array)
642 call list_destroy(static_list)
644 ! Done reading all static fields for this domain
647 static_list_array => list_get_keys(flag_list)
648 allocate(geogrid_flags(size(static_list_array)))
649 do i=1,size(static_list_array)
650 geogrid_flags(i) = static_list_array(i)%ckey
652 deallocate(static_list_array)
654 call list_destroy(flag_list)
656 end subroutine get_static_fields
659 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
660 ! Name: process_single_met_time
663 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
664 subroutine process_single_met_time(do_const_processing, &
665 temp_date, n, extra_row, extra_col, xlat, xlon, &
666 xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
668 west_east_dim, south_north_dim, &
669 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
670 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
671 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
672 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
673 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
675 map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
676 grid_id, parent_id, i_parent_start, &
677 j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
678 cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
679 pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
680 corner_lats, corner_lons, output_flags, geogrid_flags, process_bdy_width)
685 use interp_option_module
687 use misc_definitions_module
692 use rotate_winds_module
698 logical, intent(in) :: do_const_processing
699 integer, intent(in) :: n, dyn_opt, west_east_dim, south_north_dim, map_proj, &
700 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
701 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
702 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
703 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
704 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
705 is_water, is_lake, is_ice, is_urban, i_soilwater, &
706 grid_id, parent_id, i_parent_start, j_parent_start, &
707 i_parent_end, j_parent_end, parent_grid_ratio, sub_x, sub_y, num_land_cat, &
709 ! BUG: Should we be passing these around as pointers, or just declare them as arrays?
710 real, pointer, dimension(:,:) :: landmask
711 real, intent(in) :: dom_dx, dom_dy, cen_lat, moad_cen_lat, cen_lon, stand_lon, &
712 truelat1, truelat2, pole_lat, pole_lon
713 real, dimension(16), intent(in) :: corner_lats, corner_lons
714 real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
715 logical, intent(in) :: extra_row, extra_col
716 logical, dimension(:), intent(inout) :: got_this_field
717 character (len=19), intent(in) :: temp_date
718 character (len=128), intent(in) :: mminlu
719 character (len=128), dimension(:), intent(inout) :: output_flags
720 character (len=128), dimension(:), pointer :: geogrid_flags
722 ! BUG: Move this constant to misc_definitions_module?
723 integer, parameter :: BDR_WIDTH = 3
726 integer :: istatus, fg_idx, idx, idxt, i, j, bottom_top_dim, &
727 sm1, em1, sm2, em2, sm3, em3, &
728 sp1, ep1, sp2, ep2, sp3, ep3, &
729 sd1, ed1, sd2, ed2, sd3, ed3, &
731 integer :: nmet_flags
732 integer :: num_metgrid_soil_levs
733 integer, pointer, dimension(:) :: soil_levels
735 integer, pointer, dimension(:) :: u_levels, v_levels
736 real, pointer, dimension(:,:,:) :: real_array
737 character (len=19) :: output_date
738 character (len=128) :: cname, title
739 character (len=MAX_FILENAME_LEN) :: input_name
740 character (len=128), allocatable, dimension(:) :: met_flags
741 type (fg_input) :: field, u_field, v_field
742 type (met_data) :: fg_data
744 ! CWH Initialize local pointer variables
751 ! For this time, we need to process all first-guess filename roots. When we
752 ! hit a root containing a '*', we assume we have hit the end of the list
754 if (do_const_processing) then
755 input_name = constants_name(fg_idx)
757 input_name = fg_name(fg_idx)
759 do while (input_name /= '*')
761 call mprintf(.true.,STDOUT, ' %s', s1=input_name)
762 call mprintf(.true.,LOGFILE, 'Getting input fields from %s', s1=input_name)
764 if (index(input_name, 'mpas:') == 1) then
765 call process_mpas_fields(input_name, do_const_processing, temp_date, fg_data, got_this_field, &
766 landmask, process_bdy_width, &
769 xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v, &
770 output_flags, west_east_dim, south_north_dim, &
771 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
772 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
773 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
774 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
775 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e )
777 call process_intermediate_fields(input_name, do_const_processing, temp_date, fg_data, got_this_field, &
778 landmask, process_bdy_width, &
781 xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v, &
782 output_flags, west_east_dim, south_north_dim, &
783 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
784 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
785 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
786 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
787 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e )
791 if (do_const_processing) then
792 input_name = constants_name(fg_idx)
794 input_name = fg_name(fg_idx)
796 end do ! while (input_name /= '*')
799 ! Rotate winds from earth-relative to grid-relative
802 call storage_get_levels(u_field, u_levels)
803 call storage_get_levels(v_field, v_levels)
805 if (associated(u_levels) .and. associated(v_levels)) then
807 do u_idx = 1, size(u_levels)
808 u_field%header%vertical_level = u_levels(u_idx)
809 call storage_get_field(u_field, istatus)
810 v_field%header%vertical_level = v_levels(u_idx)
811 call storage_get_field(v_field, istatus)
813 if (gridtype == 'C') then
814 call met_to_map(u_field%r_arr, u_field%valid_mask, &
815 v_field%r_arr, v_field%valid_mask, &
816 we_mem_stag_s, sn_mem_s, &
817 we_mem_stag_e, sn_mem_e, &
818 we_mem_s, sn_mem_stag_s, &
819 we_mem_e, sn_mem_stag_e, &
820 xlon_u, xlon_v, xlat_u, xlat_v)
821 else if (gridtype == 'E') then
822 call met_to_map_nmm(u_field%r_arr, u_field%valid_mask, &
823 v_field%r_arr, v_field%valid_mask, &
824 we_mem_s, sn_mem_s, &
825 we_mem_e, sn_mem_e, &
836 if (do_const_processing) return
839 ! Now that we have all degribbed fields, we build a 3-d pressure field, and fill in any
840 ! missing levels in the other 3-d fields
842 call mprintf(.true.,LOGFILE,'Filling missing levels.')
843 call fill_missing_levels(output_flags)
845 call mprintf(.true.,LOGFILE,'Creating derived fields.')
846 call create_derived_fields(gridtype, fg_data%hdate, fg_data%xfcst, &
847 we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
848 we_mem_stag_s, we_mem_stag_e, sn_mem_stag_s, sn_mem_stag_e, &
849 got_this_field, output_flags)
852 ! Derive some MPAS fields from others, e.g., TT from theta and pressure
854 call derive_mpas_fields()
857 ! Check that every mandatory field was found in input data
860 if (is_mandatory(i) .and. .not. got_this_field(i)) then
861 call mprintf(.true.,ERROR,'The mandatory field %s was not found in any input data.',s1=fieldname(i))
866 ! Before we begin to write fields, if debug_level is set high enough, we
867 ! write a table of which fields are available at which levels to the
868 ! metgrid.log file, and then we check to see if any fields are not
869 ! completely covered with data.
871 call storage_print_fields()
872 call find_missing_values()
875 ! All of the processing is now done for this time period for this domain;
876 ! now we simply output every field from the storage module.
879 title = 'OUTPUT FROM METGRID V4.4'
881 ! Initialize the output module for this domain and time
882 call mprintf(.true.,LOGFILE,'Initializing output module.')
883 output_date = temp_date
884 if ( .not. nocolons ) then
885 if (len_trim(temp_date) == 13) then
886 output_date(14:19) = ':00:00'
887 else if (len_trim(temp_date) == 16) then
888 output_date(17:19) = ':00'
891 if (len_trim(temp_date) == 13) then
892 output_date(14:19) = '_00_00'
893 else if (len_trim(temp_date) == 16) then
894 output_date(17:19) = '_00'
898 call output_init(n, title, output_date, gridtype, dyn_opt, &
899 corner_lats, corner_lons, &
900 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
901 we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, &
902 we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
903 extra_col, extra_row)
905 call get_bottom_top_dim(bottom_top_dim)
907 ! Add in a flag to tell real that we have seven new msf fields
908 nmet_flags = num_entries + 1
909 if (associated(geogrid_flags)) nmet_flags = nmet_flags + size(geogrid_flags)
910 allocate(met_flags(nmet_flags))
912 met_flags(i) = output_flags(i)
914 if (gridtype == 'C') then
915 met_flags(num_entries+1) = 'FLAG_MF_XY'
917 met_flags(num_entries+1) = ' '
919 if (associated(geogrid_flags)) then
920 do i=1,size(geogrid_flags)
921 met_flags(num_entries+1+i) = geogrid_flags(i)
925 ! Find out how many soil levels or layers we have; this assumes a field named ST
926 field % header % field = 'ST'
928 call storage_get_levels(field, soil_levels)
930 if (.not. associated(soil_levels)) then
931 field % header % field = 'SOILT'
933 call storage_get_levels(field, soil_levels)
936 if (.not. associated(soil_levels)) then
937 field % header % field = 'STC_WPS'
939 call storage_get_levels(field, soil_levels)
942 if (associated(soil_levels)) then
943 num_metgrid_soil_levs = size(soil_levels)
944 deallocate(soil_levels)
946 num_metgrid_soil_levs = 0
949 ! First write out global attributes
950 call mprintf(.true.,LOGFILE,'Writing global attributes to output.')
951 call write_global_attrs(title, output_date, gridtype, dyn_opt, west_east_dim, &
952 south_north_dim, bottom_top_dim, &
953 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
954 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
955 map_proj, mminlu, num_land_cat, &
956 is_water, is_lake, is_ice, is_urban, i_soilwater, &
957 grid_id, parent_id, i_parent_start, &
958 j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
959 cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
960 pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
961 corner_lats, corner_lons, num_metgrid_soil_levs, &
962 met_flags, nmet_flags, process_bdy_width)
964 deallocate(met_flags)
966 call reset_next_field()
970 ! Now loop over all output fields, writing each to the output module
971 do while (istatus == 0)
972 call get_next_output_field(cname, real_array, &
973 sm1, em1, sm2, em2, sm3, em3, istatus)
974 if (istatus == 0) then
976 call mprintf(.true.,LOGFILE,'Writing field %s to output.',s1=cname)
977 call write_field(sm1, em1, sm2, em2, sm3, em3, &
978 cname, output_date, real_array)
979 deallocate(real_array)
985 call mprintf(.true.,LOGFILE,'Closing output file.')
988 ! Free up memory used by met fields for this valid time
989 call storage_delete_all_td()
991 end subroutine process_single_met_time
994 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
995 ! Name: process_intermediate_fields
998 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
999 subroutine process_intermediate_fields(input_name, do_const_processing, temp_date, fg_data, got_this_field, &
1000 landmask, process_bdy_width, &
1003 xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v, &
1004 output_flags, west_east_dim, south_north_dim, &
1005 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1006 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
1007 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
1008 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
1009 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e )
1014 use interp_option_module
1016 use misc_definitions_module
1021 use rotate_winds_module
1026 ! BUG: Move this constant to misc_definitions_module?
1027 integer, parameter :: BDR_WIDTH = 3
1029 character (len=*), intent(inout) :: input_name
1030 logical, intent(in) :: do_const_processing
1031 character (len=*), intent(in) :: temp_date
1032 type (met_data), intent(inout) :: fg_data
1033 logical, dimension(:), intent(inout) :: got_this_field
1034 real, pointer, dimension(:,:) :: landmask
1035 integer, intent(in) :: process_bdy_width
1036 type (fg_input), intent(inout) :: u_field, v_field
1037 character (len=128), dimension(:), intent(inout) :: output_flags
1038 real, intent(in) :: dom_dx, dom_dy
1039 real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
1040 integer, intent(in) :: west_east_dim, south_north_dim, &
1041 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1042 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
1043 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
1044 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
1045 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e
1048 integer :: idx, idxt, u_idx
1051 real, pointer, dimension(:,:) :: halo_slab => null()
1052 integer, pointer, dimension(:) :: u_levels => null()
1053 integer, pointer, dimension(:) :: v_levels => null()
1055 logical :: do_gcell_interp
1056 type (fg_input) :: field
1059 ! Do a first pass through this fg source to get all mask fields used
1060 ! during interpolation
1061 call get_interp_masks(trim(input_name), do_const_processing, temp_date)
1065 ! Initialize the module for reading in the met fields
1066 call read_met_init(trim(input_name), do_const_processing, temp_date, istatus)
1068 if (istatus == 0) then
1070 ! Process all fields and levels from the current file; read_next_met_field()
1071 ! will return a non-zero status when there are no more fields to be read.
1072 do while (istatus == 0)
1074 call read_next_met_field(fg_data, istatus)
1076 if (istatus == 0) then
1078 ! Find index into fieldname, interp_method, masked, and fill_missing
1079 ! of the current field
1080 idxt = num_entries + 1
1081 do idx=1,num_entries
1082 if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
1083 (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
1085 got_this_field(idx) = .true.
1087 if (index(input_name,trim(from_input(idx))) /= 0 .or. &
1088 (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
1095 if (idx > num_entries) idx = num_entries ! The last entry is a default
1097 ! Do we need to rename this field?
1098 if (output_name(idx) /= ' ') then
1099 fg_data%field = output_name(idx)(1:9)
1101 idxt = num_entries + 1
1102 do idx=1,num_entries
1103 if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
1104 (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
1106 got_this_field(idx) = .true.
1108 if (index(input_name,trim(from_input(idx))) /= 0 .or. &
1109 (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
1116 if (idx > num_entries) idx = num_entries ! The last entry is a default
1119 ! Do a simple check to see whether this is a global dataset
1120 ! Note that we do not currently support regional Gaussian grids
1121 if ((fg_data%iproj == PROJ_LATLON .and. abs(fg_data%nx * fg_data%deltalon - 360.) < 0.0001) &
1122 .or. (fg_data%iproj == PROJ_GAUSS)) then
1123 bdr_wdth = BDR_WIDTH
1124 allocate(halo_slab(1-BDR_WIDTH:fg_data%nx+BDR_WIDTH,1:fg_data%ny))
1126 halo_slab(1:fg_data%nx, 1:fg_data%ny) = &
1127 fg_data%slab(1:fg_data%nx, 1:fg_data%ny)
1129 halo_slab(1-BDR_WIDTH:0, 1:fg_data%ny) = &
1130 fg_data%slab(fg_data%nx-BDR_WIDTH+1:fg_data%nx, 1:fg_data%ny)
1132 halo_slab(fg_data%nx+1:fg_data%nx+BDR_WIDTH, 1:fg_data%ny) = &
1133 fg_data%slab(1:BDR_WIDTH, 1:fg_data%ny)
1135 deallocate(fg_data%slab)
1138 halo_slab => fg_data%slab
1139 nullify(fg_data%slab)
1142 call mprintf(.true.,LOGFILE,'Processing %s at level %f.',s1=fg_data%field,f1=fg_data%xlvl)
1144 call push_source_projection(fg_data%iproj, fg_data%xlonc, fg_data%truelat1, &
1145 fg_data%truelat2, fg_data%dx, fg_data%dy, fg_data%deltalat, &
1146 fg_data%deltalon, fg_data%starti, fg_data%startj, &
1147 fg_data%startlat, fg_data%startlon, &
1148 fg_data%pole_lat, fg_data%pole_lon, &
1149 fg_data%centerlat, fg_data%centerlon, &
1150 real(fg_data%nx+1)/2., real(fg_data%ny+1)/2., &
1151 earth_radius=fg_data%earth_radius*1000.)
1153 ! Initialize fg_input structure to store the field
1154 field%header%version = 1
1155 field%header%date = fg_data%hdate//' '
1156 if (do_const_processing) then
1157 field%header%time_dependent = .false.
1158 field%header%constant_field = .true.
1160 field%header%time_dependent = .true.
1161 field%header%constant_field = .false.
1163 field%header%forecast_hour = fg_data%xfcst
1164 field%header%fg_source = 'FG'
1165 field%header%field = ' '
1166 field%header%field(1:9) = fg_data%field
1167 field%header%units = ' '
1168 field%header%units(1:25) = fg_data%units
1169 field%header%description = ' '
1170 field%header%description(1:46) = fg_data%desc
1171 call get_z_dim_name(fg_data%field,field%header%vertical_coord)
1172 field%header%vertical_level = nint(fg_data%xlvl)
1173 field%header%sr_x = 1
1174 field%header%sr_y = 1
1175 field%header%array_order = 'XY '
1176 field%header%is_wind_grid_rel = fg_data%is_wind_grid_rel
1177 field%header%array_has_missing_values = .false.
1178 nullify(field%r_arr)
1179 nullify(field%valid_mask)
1180 nullify(field%modified_mask)
1182 if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
1183 output_flags(idx) = flag_in_output(idx)
1186 ! If we should not output this field, just list it as a mask field
1187 if (output_this_field(idx)) then
1188 field%header%mask_field = .false.
1190 field%header%mask_field = .true.
1194 ! Before actually doing any interpolation to the model grid, we must check
1195 ! whether we will be using the average_gcell interpolator that averages all
1196 ! source points in each model grid cell
1198 do_gcell_interp = .false.
1199 if (index(interp_method(idx),'average_gcell') /= 0) then
1201 call get_gcell_threshold(interp_method(idx), threshold, istatus)
1202 if (istatus == 0) then
1203 if (fg_data%dx == 0. .and. fg_data%dy == 0. .and. &
1204 fg_data%deltalat /= 0. .and. fg_data%deltalon /= 0.) then
1205 fg_data%dx = abs(fg_data%deltalon)
1206 fg_data%dy = abs(fg_data%deltalat)
1208 ! BUG: Need to more correctly handle dx/dy in meters.
1209 fg_data%dx = fg_data%dx / 111000. ! Convert meters to approximate degrees
1210 fg_data%dy = fg_data%dy / 111000.
1212 if (gridtype == 'C') then
1213 if (threshold*max(fg_data%dx,fg_data%dy)*111. <= max(dom_dx,dom_dy)/1000.) &
1214 do_gcell_interp = .true.
1215 else if (gridtype == 'E') then
1216 if (threshold*max(fg_data%dx,fg_data%dy) <= max(dom_dx,dom_dy)) &
1217 do_gcell_interp = .true.
1222 ! Interpolate to U staggering
1223 if (output_stagger(idx) == U) then
1225 call storage_query_field(field, iqstatus)
1226 if (iqstatus == 0) then
1227 call storage_get_field(field, iqstatus)
1228 call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
1229 ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
1230 if (associated(field%modified_mask)) then
1231 call bitarray_destroy(field%modified_mask)
1232 nullify(field%modified_mask)
1235 allocate(field%valid_mask)
1236 call bitarray_create(field%valid_mask, we_mem_stag_e-we_mem_stag_s+1, sn_mem_e-sn_mem_s+1)
1239 ! Save a copy of the fg_input structure for the U field so that we can find it later
1240 if (is_u_field(idx)) call dup(field, u_field)
1242 allocate(field%modified_mask)
1243 call bitarray_create(field%modified_mask, we_mem_stag_e-we_mem_stag_s+1, sn_mem_e-sn_mem_s+1)
1245 if (do_const_processing .or. field%header%time_dependent) then
1246 call interp_met_field(input_name, fg_data%field, U, M, &
1247 field, xlat_u, xlon_u, we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, &
1248 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1249 halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
1250 field%modified_mask, process_bdy_width)
1252 call mprintf(.true.,INFORM,' - already processed this field from constant file.')
1255 ! Interpolate to V staggering
1256 else if (output_stagger(idx) == V) then
1258 call storage_query_field(field, iqstatus)
1259 if (iqstatus == 0) then
1260 call storage_get_field(field, iqstatus)
1261 call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
1262 ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
1263 if (associated(field%modified_mask)) then
1264 call bitarray_destroy(field%modified_mask)
1265 nullify(field%modified_mask)
1268 allocate(field%valid_mask)
1269 call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_stag_e-sn_mem_stag_s+1)
1272 ! Save a copy of the fg_input structure for the V field so that we can find it later
1273 if (is_v_field(idx)) call dup(field, v_field)
1275 allocate(field%modified_mask)
1276 call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_stag_e-sn_mem_stag_s+1)
1278 if (do_const_processing .or. field%header%time_dependent) then
1279 call interp_met_field(input_name, fg_data%field, V, M, &
1280 field, xlat_v, xlon_v, we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
1281 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1282 halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
1283 field%modified_mask, process_bdy_width)
1285 call mprintf(.true.,INFORM,' - already processed this field from constant file.')
1288 ! Interpolate to VV staggering
1289 else if (output_stagger(idx) == VV) then
1291 call storage_query_field(field, iqstatus)
1292 if (iqstatus == 0) then
1293 call storage_get_field(field, iqstatus)
1294 call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
1295 ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
1296 if (associated(field%modified_mask)) then
1297 call bitarray_destroy(field%modified_mask)
1298 nullify(field%modified_mask)
1301 allocate(field%valid_mask)
1302 call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
1305 ! Save a copy of the fg_input structure for the U field so that we can find it later
1306 if (is_u_field(idx)) call dup(field, u_field)
1308 ! Save a copy of the fg_input structure for the V field so that we can find it later
1309 if (is_v_field(idx)) call dup(field, v_field)
1311 allocate(field%modified_mask)
1312 call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
1314 if (do_const_processing .or. field%header%time_dependent) then
1315 call interp_met_field(input_name, fg_data%field, VV, M, &
1316 field, xlat_v, xlon_v, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
1317 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1318 halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
1319 field%modified_mask, process_bdy_width)
1321 call mprintf(.true.,INFORM,' - already processed this field from constant file.')
1324 ! All other fields interpolated to M staggering for C grid, H staggering for E grid
1327 call storage_query_field(field, iqstatus)
1328 if (iqstatus == 0) then
1329 call storage_get_field(field, iqstatus)
1330 call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
1331 ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
1332 if (associated(field%modified_mask)) then
1333 call bitarray_destroy(field%modified_mask)
1334 nullify(field%modified_mask)
1337 allocate(field%valid_mask)
1338 call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
1341 allocate(field%modified_mask)
1342 call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
1344 if (do_const_processing .or. field%header%time_dependent) then
1345 if (gridtype == 'C') then
1346 call interp_met_field(input_name, fg_data%field, M, M, &
1347 field, xlat, xlon, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
1348 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1349 halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
1350 field%modified_mask, process_bdy_width, landmask)
1352 else if (gridtype == 'E') then
1353 call interp_met_field(input_name, fg_data%field, HH, M, &
1354 field, xlat, xlon, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
1355 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1356 halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
1357 field%modified_mask, process_bdy_width, landmask)
1360 call mprintf(.true.,INFORM,' - already processed this field from constant file.')
1365 call bitarray_merge(field%valid_mask, field%modified_mask)
1367 deallocate(halo_slab)
1369 ! Store the interpolated field
1370 call storage_put_field(field)
1372 call pop_source_projection()
1377 call read_met_close()
1379 call push_source_projection(fg_data%iproj, fg_data%xlonc, fg_data%truelat1, &
1380 fg_data%truelat2, fg_data%dx, fg_data%dy, fg_data%deltalat, &
1381 fg_data%deltalon, fg_data%starti, fg_data%startj, &
1382 fg_data%startlat, fg_data%startlon, &
1383 fg_data%pole_lat, fg_data%pole_lon, &
1384 fg_data%centerlat, fg_data%centerlon, &
1385 real(fg_data%nx+1)/2., real(fg_data%ny+1)/2., &
1386 earth_radius=fg_data%earth_radius*1000.)
1389 ! If necessary, rotate winds to earth-relative for this fg source
1392 call storage_get_levels(u_field, u_levels)
1393 call storage_get_levels(v_field, v_levels)
1395 if (associated(u_levels) .and. associated(v_levels)) then
1397 do u_idx = 1, size(u_levels)
1398 u_field%header%vertical_level = u_levels(u_idx)
1399 call storage_get_field(u_field, istatus)
1400 v_field%header%vertical_level = v_levels(u_idx)
1401 call storage_get_field(v_field, istatus)
1403 if (associated(u_field%modified_mask) .and. &
1404 associated(v_field%modified_mask)) then
1406 if (u_field%header%is_wind_grid_rel) then
1407 if (gridtype == 'C') then
1408 call map_to_met(u_field%r_arr, u_field%modified_mask, &
1409 v_field%r_arr, v_field%modified_mask, &
1410 we_mem_stag_s, sn_mem_s, &
1411 we_mem_stag_e, sn_mem_e, &
1412 we_mem_s, sn_mem_stag_s, &
1413 we_mem_e, sn_mem_stag_e, &
1414 xlon_u, xlon_v, xlat_u, xlat_v)
1415 else if (gridtype == 'E') then
1416 call map_to_met_nmm(u_field%r_arr, u_field%modified_mask, &
1417 v_field%r_arr, v_field%modified_mask, &
1418 we_mem_s, sn_mem_s, &
1419 we_mem_e, sn_mem_e, &
1424 call bitarray_destroy(u_field%modified_mask)
1425 call bitarray_destroy(v_field%modified_mask)
1426 nullify(u_field%modified_mask)
1427 nullify(v_field%modified_mask)
1428 call storage_put_field(u_field)
1429 call storage_put_field(v_field)
1434 deallocate(u_levels)
1435 deallocate(v_levels)
1439 call pop_source_projection()
1442 if (do_const_processing) then
1443 call mprintf(.true.,WARN,'Couldn''t open file %s for input.',s1=input_name)
1445 call mprintf(.true.,WARN,'Couldn''t open file %s for input.',s1=trim(input_name)//':'//trim(temp_date))
1449 end subroutine process_intermediate_fields
1452 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1453 ! Name: process_mpas_fields
1456 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1457 subroutine process_mpas_fields(input_name, do_const_processing, temp_date, fg_data, got_this_field, &
1458 landmask, process_bdy_width, &
1461 xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v, &
1462 output_flags, west_east_dim, south_north_dim, &
1463 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1464 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
1465 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
1466 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
1467 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e )
1472 use interp_option_module
1475 use misc_definitions_module
1479 use rotate_winds_module
1486 ! BUG: Move this constant to misc_definitions_module?
1487 integer, parameter :: BDR_WIDTH = 3
1489 character (len=*), intent(inout) :: input_name
1490 logical, intent(in) :: do_const_processing
1491 character (len=*), intent(in) :: temp_date
1492 type (met_data), intent(inout) :: fg_data
1493 logical, dimension(:), intent(inout) :: got_this_field
1494 real, pointer, dimension(:,:) :: landmask
1495 integer, intent(in) :: process_bdy_width
1496 type (fg_input), intent(inout) :: u_field, v_field
1497 character (len=128), dimension(:), intent(inout) :: output_flags
1498 real, intent(in) :: dom_dx, dom_dy
1499 real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
1500 integer, intent(in) :: west_east_dim, south_north_dim, &
1501 we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
1502 we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
1503 sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
1504 we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
1505 sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e
1507 real, parameter :: deg2rad = asin(1.0) / 90.0
1513 character (len=MAX_FILENAME_LEN) :: mpas_filename
1515 type (input_handle_type) :: mpas_handle
1516 type (input_field_type) :: mpas_field
1517 type (target_field_type) :: wrf_field
1518 type (fg_input) :: field_to_store
1520 strlen = len_trim(input_name)
1521 if (do_const_processing) then
1522 write(mpas_filename,'(a)') input_name(6:strlen)
1524 write(mpas_filename,'(a)') input_name(6:strlen)//'.'//trim(temp_date)//'.nc'
1526 call mprintf(.true.,LOGFILE,'Processing MPAS fields from file %s',s1=mpas_filename)
1529 ! If we do not already have mesh information, get that now...
1531 if (.not. mpas_source_mesh % valid) then
1532 if (mpas_mesh_setup(mpas_filename, mpas_source_mesh) /= 0) then
1533 call mprintf(.true.,ERROR, 'Error setting up MPAS mesh %s with scan_input_open', s1=mpas_filename)
1538 ! If we have not already defined the WRF grid, do that now...
1540 if (.not. wrf_target_mesh_m % valid) then
1541 allocate(xlat_rad(size(xlat,1), size(xlat,2)))
1542 allocate(xlon_rad(size(xlat,1), size(xlat,2)))
1543 xlat_rad(:,:) = xlat(:,:) * deg2rad
1544 xlon_rad(:,:) = xlon(:,:) * deg2rad
1545 call mprintf(.true.,LOGFILE,'Need to set up WRF target mass-grid')
1546 if (target_mesh_setup(wrf_target_mesh_m, lat2d=xlat_rad, lon2d=xlon_rad) /= 0) then
1547 call mprintf(.true.,ERROR, 'Error setting up WRF target grid')
1550 call mprintf(.true.,LOGFILE,'Also computing remapping weights...')
1551 if (remap_info_setup(mpas_source_mesh, wrf_target_mesh_m, remap_info_m) /= 0) then
1552 call mprintf(.true.,ERROR, 'Error computing remapping weights from MPAS to WRF grid')
1555 call mprintf(.true.,LOGFILE,'Already set up WRF target mass-grid')
1558 if (.not. wrf_target_mesh_u % valid) then
1559 allocate(xlat_u_rad(size(xlat_u,1), size(xlat_u,2)))
1560 allocate(xlon_u_rad(size(xlat_u,1), size(xlat_u,2)))
1561 xlat_u_rad(:,:) = xlat_u(:,:) * deg2rad
1562 xlon_u_rad(:,:) = xlon_u(:,:) * deg2rad
1563 call mprintf(.true.,LOGFILE,'Need to set up WRF target U-grid')
1564 if (target_mesh_setup(wrf_target_mesh_u, lat2d=xlat_u_rad, lon2d=xlon_u_rad) /= 0) then
1565 call mprintf(.true.,ERROR, 'Error setting up WRF target grid')
1568 call mprintf(.true.,LOGFILE,'Also computing remapping weights...')
1569 if (remap_info_setup(mpas_source_mesh, wrf_target_mesh_u, remap_info_u) /= 0) then
1570 call mprintf(.true.,ERROR, 'Error computing remapping weights from MPAS to WRF grid')
1573 call mprintf(.true.,LOGFILE,'Already set up WRF target U-grid')
1576 if (.not. wrf_target_mesh_v % valid) then
1577 allocate(xlat_v_rad(size(xlat_v,1), size(xlat_v,2)))
1578 allocate(xlon_v_rad(size(xlat_v,1), size(xlat_v,2)))
1579 xlat_v_rad(:,:) = xlat_v(:,:) * deg2rad
1580 xlon_v_rad(:,:) = xlon_v(:,:) * deg2rad
1581 call mprintf(.true.,LOGFILE,'Need to set up WRF target V-grid')
1582 if (target_mesh_setup(wrf_target_mesh_v, lat2d=xlat_v_rad, lon2d=xlon_v_rad) /= 0) then
1583 call mprintf(.true.,ERROR, 'Error setting up WRF target grid')
1586 call mprintf(.true.,LOGFILE,'Also computing remapping weights...')
1587 if (remap_info_setup(mpas_source_mesh, wrf_target_mesh_v, remap_info_v) /= 0) then
1588 call mprintf(.true.,ERROR, 'Error computing remapping weights from MPAS to WRF grid')
1591 call mprintf(.true.,LOGFILE,'Already set up WRF target V-grid')
1595 if (scan_input_open(mpas_filename, mpas_handle, nRecords) /= 0) then
1596 call mprintf(.true.,ERROR, 'Error opening %s with scan_input_open', s1=mpas_filename)
1600 ! Initialize fg_input structure to store the field
1601 field_to_store%header%version = 1
1602 field_to_store%header%date = '?'
1603 if (do_const_processing) then
1604 field_to_store%header%time_dependent = .false.
1605 field_to_store%header%constant_field = .true.
1607 field_to_store%header%time_dependent = .true.
1608 field_to_store%header%constant_field = .false.
1610 field_to_store%header%forecast_hour = 0.0
1611 field_to_store%header%fg_source = 'MPAS'
1612 field_to_store%header%field = ' '
1613 field_to_store%header%field(1:9) = '?'
1614 field_to_store%header%units = ' '
1615 field_to_store%header%units(1:25) = '?'
1616 field_to_store%header%description = ' '
1617 field_to_store%header%description(1:46) = '?'
1618 field_to_store%header%vertical_coord = 'z_dim_name'
1619 field_to_store%header%vertical_level = 0
1620 field_to_store%header%sr_x = 1
1621 field_to_store%header%sr_y = 1
1622 field_to_store%header%array_order = 'XY '
1623 field_to_store%header%is_wind_grid_rel = .false.
1624 field_to_store%header%array_has_missing_values = .false.
1625 nullify(field_to_store%r_arr)
1626 nullify(field_to_store%valid_mask)
1627 nullify(field_to_store%modified_mask)
1629 ! If we should not output this field, just list it as a mask field
1630 !??? if (output_this_field(idx)) then
1631 field_to_store%header%mask_field = .false.
1633 !??? field%header%mask_field = .true.
1637 do while (scan_input_next_field(mpas_handle, mpas_field) == 0)
1639 if (can_remap_field(mpas_field)) then
1641 ! Here, rename a few MPAS fields that would be difficult to treat
1642 ! with METGRID.TBL options; principally, these are surface fields
1643 ! that have different names from their upper-air counterparts.
1644 if (trim(mpas_field % name) == 'u10') then
1645 mpas_field % name = 'uReconstructZonal'
1646 else if (trim(mpas_field % name) == 'v10') then
1647 mpas_field % name = 'uReconstructMeridional'
1648 else if (trim(mpas_field % name) == 'q2') then
1649 mpas_field % name = 'qv'
1650 else if (trim(mpas_field % name) == 't2m') then
1651 mpas_field % name = 'theta'
1654 ! Mark this MPAS field as "gotten" for any later checks
1655 ! on mandatory fields
1656 idx = mpas_name_to_idx(trim(mpas_field % name))
1658 got_this_field(idx) = .true.
1659 if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
1660 output_flags(idx) = flag_in_output(idx)
1663 istat = scan_input_free_field(mpas_field)
1667 istat = scan_input_read_field(mpas_field, frame=1)
1669 field_to_store%map%stagger = mpas_output_stagger(mpas_field % name)
1670 if (field_to_store%map%stagger == M) then
1671 field_to_store%header%dim1(1) = we_mem_s
1672 field_to_store%header%dim1(2) = we_mem_e
1673 field_to_store%header%dim2(1) = sn_mem_s
1674 field_to_store%header%dim2(2) = sn_mem_e
1676 if (masked(idx) == MASKED_WATER) then
1677 istat = remap_field(remap_info_m, mpas_field, wrf_field, masked=.true.)
1679 istat = remap_field(remap_info_m, mpas_field, wrf_field, masked=.false.)
1682 istat = remap_field(remap_info_m, mpas_field, wrf_field, masked=.false.)
1684 else if (field_to_store%map%stagger == U) then
1685 field_to_store%header%dim1(1) = we_mem_stag_s
1686 field_to_store%header%dim1(2) = we_mem_stag_e
1687 field_to_store%header%dim2(1) = sn_mem_s
1688 field_to_store%header%dim2(2) = sn_mem_e
1689 istat = remap_field(remap_info_u, mpas_field, wrf_field)
1690 else if (field_to_store%map%stagger == V) then
1691 field_to_store%header%dim1(1) = we_mem_s
1692 field_to_store%header%dim1(2) = we_mem_e
1693 field_to_store%header%dim2(1) = sn_mem_stag_s
1694 field_to_store%header%dim2(2) = sn_mem_stag_e
1695 istat = remap_field(remap_info_v, mpas_field, wrf_field)
1697 call mprintf(.true.,ERROR, 'Cannot handle requested output stagger %i for MPAS field %s ...', &
1698 i1=field_to_store%map%stagger, s1=trim(mpas_field % name))
1701 if (wrf_field % ndims == 3 .and. trim(wrf_field % dimnames(1)) == 'nVertLevels') then ! 3-d MPAS atmosphere field
1702 field_to_store % header % field = mpas_to_intermediate_name(mpas_field % name)
1704 ! If no match in the METGRID.TBL was found for this MPAS field, just use the MPAS name
1705 if (len_trim(field_to_store % header % field) == 0) then
1706 field_to_store % header % field = trim(mpas_field % name)
1709 field_to_store % header % vertical_coord = 'num_mpas_levels'
1710 do k=1,wrf_field % dimlens(1)
1711 allocate(field_to_store % r_arr(wrf_field % dimlens(2), wrf_field % dimlens(3)))
1712 allocate(field_to_store % valid_mask)
1713 call bitarray_create(field_to_store % valid_mask, wrf_field % dimlens(2), wrf_field % dimlens(3))
1714 do j=1,wrf_field % dimlens(3)
1715 do i=1,wrf_field % dimlens(2)
1716 call bitarray_set(field_to_store % valid_mask, i, j)
1719 field_to_store % header % vertical_level = k
1721 if (wrf_field % xtype == FIELD_TYPE_REAL) then
1722 field_to_store % r_arr(:,:) = wrf_field % array3r(k,:,:)
1723 else if (wrf_field % xtype == FIELD_TYPE_DOUBLE) then
1724 field_to_store % r_arr(:,:) = wrf_field % array3d(k,:,:)
1727 ! The u_field and v_field are used later by calling code to
1728 ! determine which fields represent the x- and y-components of
1729 ! horizonal wind velocity for the purposes of wind rotation
1730 if (trim(mpas_field % name) == 'uReconstructZonal') then
1731 call dup(field_to_store, u_field)
1733 if (trim(mpas_field % name) == 'uReconstructMeridional') then
1734 call dup(field_to_store, v_field)
1737 call storage_put_field(field_to_store)
1740 else if (wrf_field % ndims == 3 .and. trim(wrf_field % dimnames(1)) == 'nVertLevelsP1') then ! 3-d MPAS atmosphere field
1741 field_to_store % header % field = mpas_to_intermediate_name(mpas_field % name)
1743 ! If no match in the METGRID.TBL was found for this MPAS field, just use the MPAS name
1744 if (len_trim(field_to_store % header % field) == 0) then
1745 field_to_store % header % field = trim(mpas_field % name)
1748 ! Handle surface level
1749 field_to_store % header % vertical_coord = 'none'
1750 allocate(field_to_store % r_arr(wrf_field % dimlens(2), wrf_field % dimlens(3)))
1751 allocate(field_to_store % valid_mask)
1752 call bitarray_create(field_to_store % valid_mask, wrf_field % dimlens(2), wrf_field % dimlens(3))
1753 do j=1,wrf_field % dimlens(3)
1754 do i=1,wrf_field % dimlens(2)
1755 call bitarray_set(field_to_store % valid_mask, i, j)
1758 field_to_store % header % vertical_level = 200100.0
1760 if (wrf_field % xtype == FIELD_TYPE_REAL) then
1761 field_to_store % r_arr(:,:) = wrf_field % array3r(1,:,:)
1762 else if (wrf_field % xtype == FIELD_TYPE_DOUBLE) then
1763 field_to_store % r_arr(:,:) = wrf_field % array3d(1,:,:)
1766 call storage_put_field(field_to_store)
1768 ! Handle all other layers
1769 field_to_store % header % vertical_coord = 'num_mpas_levels'
1770 do k=1,wrf_field % dimlens(1) - 1
1771 allocate(field_to_store % r_arr(wrf_field % dimlens(2), wrf_field % dimlens(3)))
1772 allocate(field_to_store % valid_mask)
1773 call bitarray_create(field_to_store % valid_mask, wrf_field % dimlens(2), wrf_field % dimlens(3))
1774 do j=1,wrf_field % dimlens(3)
1775 do i=1,wrf_field % dimlens(2)
1776 call bitarray_set(field_to_store % valid_mask, i, j)
1779 field_to_store % header % vertical_level = k
1781 ! Average to layer midpoint
1782 if (wrf_field % xtype == FIELD_TYPE_REAL) then
1783 field_to_store % r_arr(:,:) = 0.5 * (wrf_field % array3r(k,:,:) + wrf_field % array3r(k+1,:,:))
1784 else if (wrf_field % xtype == FIELD_TYPE_DOUBLE) then
1785 field_to_store % r_arr(:,:) = 0.5 * (wrf_field % array3d(k,:,:) + wrf_field % array3d(k+1,:,:))
1788 call storage_put_field(field_to_store)
1791 ! Special case: zgrid field also provides SOILHGT
1792 if (trim(mpas_field % name) == 'zgrid') then
1793 field_to_store % header % field = 'SOILHGT'
1795 allocate(field_to_store % r_arr(wrf_field % dimlens(2), wrf_field % dimlens(3)))
1796 allocate(field_to_store % valid_mask)
1797 call bitarray_create(field_to_store % valid_mask, wrf_field % dimlens(2), wrf_field % dimlens(3))
1798 do j=1,wrf_field % dimlens(3)
1799 do i=1,wrf_field % dimlens(2)
1800 call bitarray_set(field_to_store % valid_mask, i, j)
1803 field_to_store % header % vertical_level = 200100.0
1805 if (wrf_field % xtype == FIELD_TYPE_REAL) then
1806 field_to_store % r_arr(:,:) = wrf_field % array3r(1,:,:)
1807 else if (wrf_field % xtype == FIELD_TYPE_DOUBLE) then
1808 field_to_store % r_arr(:,:) = wrf_field % array3d(1,:,:)
1811 call storage_put_field(field_to_store)
1813 do idx=1,num_entries
1814 if (trim(fieldname(idx)) == 'SOILHGT') then
1815 got_this_field(idx) = .true.
1816 if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
1817 output_flags(idx) = flag_in_output(idx)
1824 else if (wrf_field % ndims == 3 .and. trim(wrf_field % dimnames(1)) == 'nSoilLevels') then ! 3-d MPAS soil field
1826 field_to_store % header % vertical_coord = 'none'
1827 if (trim(mpas_field % name) == 'tslb') then
1828 do k=1,wrf_field % dimlens(1)
1830 field_to_store % header % field = 'ST000010'
1831 else if (k == 2) then
1832 field_to_store % header % field = 'ST010040'
1833 else if (k == 3) then
1834 field_to_store % header % field = 'ST040100'
1835 else if (k == 4) then
1836 field_to_store % header % field = 'ST100200'
1838 call mprintf(.true.,ERROR, 'Too many soil layers in MPAS soil field %s ...', s1=trim(mpas_field % name))
1840 allocate(field_to_store % r_arr(wrf_field % dimlens(2), wrf_field % dimlens(3)))
1841 allocate(field_to_store % valid_mask)
1842 call bitarray_create(field_to_store % valid_mask, wrf_field % dimlens(2), wrf_field % dimlens(3))
1843 do j=1,wrf_field % dimlens(3)
1844 do i=1,wrf_field % dimlens(2)
1845 call bitarray_set(field_to_store % valid_mask, i, j)
1848 field_to_store % header % vertical_level = 200100.0
1850 if (wrf_field % xtype == FIELD_TYPE_REAL) then
1851 field_to_store % r_arr(:,:) = wrf_field % array3r(k,:,:)
1852 else if (wrf_field % xtype == FIELD_TYPE_DOUBLE) then
1853 field_to_store % r_arr(:,:) = wrf_field % array3d(k,:,:)
1857 if (masked(idx) == MASKED_WATER) then
1858 where (landmask(:,:) == 0) field_to_store % r_arr(:,:) = fill_missing(idx)
1862 call storage_put_field(field_to_store)
1864 else if (trim(mpas_field % name) == 'smois') then
1865 do k=1,wrf_field % dimlens(1)
1867 field_to_store % header % field = 'SM000010'
1868 else if (k == 2) then
1869 field_to_store % header % field = 'SM010040'
1870 else if (k == 3) then
1871 field_to_store % header % field = 'SM040100'
1872 else if (k == 4) then
1873 field_to_store % header % field = 'SM100200'
1875 call mprintf(.true.,ERROR, 'Too many soil layers in MPAS soil field %s ...', s1=trim(mpas_field % name))
1877 allocate(field_to_store % r_arr(wrf_field % dimlens(2), wrf_field % dimlens(3)))
1878 allocate(field_to_store % valid_mask)
1879 call bitarray_create(field_to_store % valid_mask, wrf_field % dimlens(2), wrf_field % dimlens(3))
1880 do j=1,wrf_field % dimlens(3)
1881 do i=1,wrf_field % dimlens(2)
1882 call bitarray_set(field_to_store % valid_mask, i, j)
1885 field_to_store % header % vertical_level = 200100.0
1887 if (wrf_field % xtype == FIELD_TYPE_REAL) then
1888 field_to_store % r_arr(:,:) = wrf_field % array3r(k,:,:)
1889 else if (wrf_field % xtype == FIELD_TYPE_DOUBLE) then
1890 field_to_store % r_arr(:,:) = wrf_field % array3d(k,:,:)
1894 if (masked(idx) == MASKED_WATER) then
1895 where (landmask(:,:) == 0) field_to_store % r_arr(:,:) = fill_missing(idx)
1899 call storage_put_field(field_to_store)
1902 call mprintf(.true.,WARN, 'Skipping unknown MPAS soil field %s ...', s1=trim(mpas_field % name))
1905 else if (wrf_field % ndims == 2) then ! 2-d MPAS field
1906 field_to_store % header % field = mpas_to_intermediate_name(mpas_field % name)
1908 ! If no match in the METGRID.TBL was found for this MPAS field, just use the MPAS name
1909 if (len_trim(field_to_store % header % field) == 0) then
1910 field_to_store % header % field = trim(mpas_field % name)
1913 field_to_store % header % vertical_coord = 'none'
1914 allocate(field_to_store % r_arr(wrf_field % dimlens(1), wrf_field % dimlens(2)))
1915 allocate(field_to_store % valid_mask)
1916 call bitarray_create(field_to_store % valid_mask, wrf_field % dimlens(1), wrf_field % dimlens(2))
1917 do j=1,wrf_field % dimlens(2)
1918 do i=1,wrf_field % dimlens(1)
1919 call bitarray_set(field_to_store % valid_mask, i, j)
1922 field_to_store % header % vertical_level = 200100.0
1924 if (wrf_field % xtype == FIELD_TYPE_REAL) then
1925 field_to_store % r_arr(:,:) = wrf_field % array2r(:,:)
1926 else if (wrf_field % xtype == FIELD_TYPE_DOUBLE) then
1927 field_to_store % r_arr(:,:) = wrf_field % array2d(:,:)
1931 if (masked(idx) == MASKED_WATER) then
1932 where (landmask(:,:) == 0) field_to_store % r_arr(:,:) = fill_missing(idx)
1936 call storage_put_field(field_to_store)
1939 istat = free_target_field(wrf_field)
1942 istat = scan_input_free_field(mpas_field)
1945 if (scan_input_close(mpas_handle) /= 0) then
1946 call mprintf(.true.,ERROR, 'Error closing %s with scan_input_close', s1=mpas_filename)
1949 end subroutine process_mpas_fields
1952 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1953 ! Name: derive_mpas_fields
1956 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1957 subroutine derive_mpas_fields()
1962 use interp_option_module
1965 use misc_definitions_module
1969 use rotate_winds_module
1973 use constants_module
1979 integer, pointer, dimension(:) :: theta_levels => null()
1980 integer, pointer, dimension(:) :: pressure_levels => null()
1981 real, pointer, dimension(:,:) :: exner => null()
1982 type (fg_input) :: theta_field
1983 type (fg_input) :: pressure_field
1986 ! Derive TT from theta and pressure
1988 theta_field%header%time_dependent = .true.
1989 theta_field%header%constant_field = .false.
1990 theta_field%header%field = 'TT'
1991 theta_field%header%vertical_level = 0
1992 nullify(theta_field%r_arr)
1993 nullify(theta_field%valid_mask)
1994 nullify(theta_field%modified_mask)
1996 pressure_field%header%time_dependent = .true.
1997 pressure_field%header%constant_field = .false.
1998 pressure_field%header%field = 'PRESSURE'
1999 pressure_field%header%vertical_level = 0
2000 nullify(pressure_field%r_arr)
2001 nullify(pressure_field%valid_mask)
2002 nullify(pressure_field%modified_mask)
2004 call storage_get_levels(theta_field, theta_levels)
2005 call storage_get_levels(pressure_field, pressure_levels)
2007 if (associated(theta_levels) .and. associated(pressure_levels)) then
2008 ! call mprintf(.true.,LOGFILE, 'Computing MPAS TT field from theta and pressure...')
2010 if (size(theta_levels) == size(pressure_levels)) then
2011 do k = 1, size(theta_levels)
2012 theta_field % header % vertical_level = theta_levels(k)
2013 call storage_get_field(theta_field, istatus)
2014 if (trim(theta_field % header % fg_source) /= 'MPAS') then
2017 if (istatus /= 0) then
2018 call mprintf(.true.,ERROR, 'Could not get MPAS theta field at level %i', i1=theta_levels(k))
2022 pressure_field % header % vertical_level = pressure_levels(k)
2023 call storage_get_field(pressure_field, istatus)
2024 if (trim(pressure_field % header % fg_source) /= 'MPAS') then
2027 if (istatus /= 0) then
2028 call mprintf(.true.,ERROR, 'Could not get MPAS pressure field at level %i', i1=theta_levels(k))
2032 ! Compute temperature
2033 call mprintf(.true.,LOGFILE, 'Computing TT at level %i for MPAS dataset', i1=theta_levels(k))
2034 if (.not. associated(exner)) then
2035 allocate(exner(size(theta_field % r_arr, 1), size(theta_field % r_arr, 2)))
2037 exner(:,:) = (pressure_field % r_arr(:,:) / P0)**(RD/CP)
2038 theta_field % r_arr(:,:) = theta_field % r_arr(:,:) * exner(:,:)
2040 call storage_put_field(theta_field)
2043 ! call mprintf(.true.,ERROR, 'The MPAS theta and pressure fields do not have the same number of levels!')
2046 deallocate(theta_levels)
2047 deallocate(pressure_levels)
2048 if (associated(exner)) then
2053 end subroutine derive_mpas_fields
2056 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2057 ! Name: get_interp_masks
2060 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2061 subroutine get_interp_masks(fg_prefix, is_constants, fg_date)
2063 use interp_option_module
2070 logical, intent(in) :: is_constants
2071 character (len=*), intent(in) :: fg_prefix, fg_date
2073 ! BUG: Move this constant to misc_definitions_module?
2074 integer, parameter :: BDR_WIDTH = 3
2077 integer :: i, istatus, idx, idxt
2078 type (fg_input) :: mask_field
2079 type (met_data) :: fg_data
2083 call read_met_init(fg_prefix, is_constants, fg_date, istatus)
2085 do while (istatus == 0)
2087 call read_next_met_field(fg_data, istatus)
2089 if (istatus == 0) then
2091 ! Find out which METGRID.TBL entry goes with this field
2092 idxt = num_entries + 1
2093 do idx=1,num_entries
2094 if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
2095 (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
2097 if (index(fg_prefix,trim(from_input(idx))) /= 0 .or. &
2098 (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
2105 if (idx > num_entries) idx = num_entries ! The last entry is a default
2107 ! Do we need to rename this field?
2108 if (output_name(idx) /= ' ') then
2109 fg_data%field = output_name(idx)(1:9)
2111 idxt = num_entries + 1
2112 do idx=1,num_entries
2113 if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
2114 (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
2116 if (index(fg_prefix,trim(from_input(idx))) /= 0 .or. &
2117 (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
2124 if (idx > num_entries) idx = num_entries ! The last entry is a default
2128 if (interp_mask(i) /= ' ' .and. (trim(interp_mask(i)) == trim(fg_data%field))) then
2130 mask_field%header%version = 1
2131 mask_field%header%date = ' '
2132 mask_field%header%date = fg_date
2133 if (is_constants) then
2134 mask_field%header%time_dependent = .false.
2135 mask_field%header%constant_field = .true.
2137 mask_field%header%time_dependent = .true.
2138 mask_field%header%constant_field = .false.
2140 mask_field%header%mask_field = .true.
2141 mask_field%header%forecast_hour = 0.
2142 mask_field%header%fg_source = 'degribbed met data'
2143 mask_field%header%field = trim(fg_data%field)//'.mask'
2144 mask_field%header%units = '-'
2145 mask_field%header%description = '-'
2146 mask_field%header%vertical_coord = 'none'
2147 mask_field%header%vertical_level = 1
2148 mask_field%header%sr_x = 1
2149 mask_field%header%sr_y = 1
2150 mask_field%header%array_order = 'XY'
2151 mask_field%header%dim1(1) = 1
2152 mask_field%header%dim1(2) = fg_data%nx
2153 mask_field%header%dim2(1) = 1
2154 mask_field%header%dim2(2) = fg_data%ny
2155 mask_field%header%is_wind_grid_rel = .true.
2156 mask_field%header%array_has_missing_values = .false.
2157 mask_field%map%stagger = M
2159 ! Do a simple check to see whether this is a global lat/lon dataset
2160 ! Note that we do not currently support regional Gaussian grids
2161 if ((fg_data%iproj == PROJ_LATLON .and. abs(fg_data%nx * fg_data%deltalon - 360.) < 0.0001) &
2162 .or. (fg_data%iproj == PROJ_GAUSS)) then
2163 allocate(mask_field%r_arr(1-BDR_WIDTH:fg_data%nx+BDR_WIDTH,1:fg_data%ny))
2165 mask_field%r_arr(1:fg_data%nx, 1:fg_data%ny) = &
2166 fg_data%slab(1:fg_data%nx, 1:fg_data%ny)
2168 mask_field%r_arr(1-BDR_WIDTH:0, 1:fg_data%ny) = &
2169 fg_data%slab(fg_data%nx-BDR_WIDTH+1:fg_data%nx, 1:fg_data%ny)
2171 mask_field%r_arr(fg_data%nx+1:fg_data%nx+BDR_WIDTH, 1:fg_data%ny) = &
2172 fg_data%slab(1:BDR_WIDTH, 1:fg_data%ny)
2175 allocate(mask_field%r_arr(1:fg_data%nx,1:fg_data%ny))
2176 mask_field%r_arr = fg_data%slab
2179 nullify(mask_field%valid_mask)
2180 nullify(mask_field%modified_mask)
2182 call storage_put_field(mask_field)
2189 if (associated(fg_data%slab)) deallocate(fg_data%slab)
2195 call read_met_close()
2197 end subroutine get_interp_masks
2200 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2201 ! Name: interp_met_field
2204 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2205 subroutine interp_met_field(input_name, short_fieldnm, ifieldstagger, istagger, &
2206 field, xlat, xlon, sm1, em1, sm2, em2, &
2207 sd1, ed1, sd2, ed2, &
2208 slab, minx, maxx, miny, maxy, bdr, do_gcell_interp, &
2209 new_pts, process_bdy_width, landmask)
2213 use interp_option_module
2215 use misc_definitions_module
2221 integer, intent(in) :: ifieldstagger, istagger, &
2222 sm1, em1, sm2, em2, &
2223 sd1, ed1, sd2, ed2, &
2224 minx, maxx, miny, maxy, bdr, &
2226 real, dimension(minx:maxx,miny:maxy), intent(in) :: slab
2227 real, dimension(sm1:em1,sm2:em2), intent(in) :: xlat, xlon
2228 real, dimension(sm1:em1,sm2:em2), intent(in), optional :: landmask
2229 logical, intent(in) :: do_gcell_interp
2230 character (len=9), intent(in) :: short_fieldnm
2231 character (len=MAX_FILENAME_LEN), intent(in) :: input_name
2232 type (fg_input), intent(inout) :: field
2233 type (bitarray), intent(inout) :: new_pts
2236 integer :: i, j, idx, idxt, orig_selected_proj, interp_mask_status, &
2237 interp_land_mask_status, interp_water_mask_status, process_width
2238 integer, pointer, dimension(:) :: interp_array, interp_opts
2239 real :: rx, ry, temp
2240 real, pointer, dimension(:,:) :: data_count
2241 type (fg_input) :: mask_field, mask_water_field, mask_land_field
2243 real, dimension(sm1:em1,sm2:em2) :: r_arr_cur_source
2246 ! CWH Initialize local pointer variables
2247 nullify(interp_array)
2248 nullify(interp_opts)
2251 ! Find index into fieldname, interp_method, masked, and fill_missing
2252 ! of the current field
2253 idxt = num_entries + 1
2254 do idx=1,num_entries
2255 if ((index(fieldname(idx), trim(short_fieldnm)) /= 0) .and. &
2256 (len_trim(fieldname(idx)) == len_trim(short_fieldnm))) then
2257 if (index(input_name,trim(from_input(idx))) /= 0 .or. &
2258 (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
2264 if (idx > num_entries) then
2265 call mprintf(.true.,WARN,'Entry in METGRID.TBL not found for field %s. '// &
2266 'Default options will be used for this field!', s1=short_fieldnm)
2267 idx = num_entries ! The last entry is a default
2270 if (process_bdy_width == 0) then
2271 process_width = max(ed1-sd1+1, ed2-sd2+1)
2273 process_width = process_bdy_width
2274 ! Add two extra rows/cols to accommodate staggered fields: one extra row/col for
2275 ! averaging to mass points in real, and one beyond that for averaging during
2277 if (ifieldstagger /= M) process_width = process_width + 2
2280 field%header%dim1(1) = sm1
2281 field%header%dim1(2) = em1
2282 field%header%dim2(1) = sm2
2283 field%header%dim2(2) = em2
2284 field%map%stagger = ifieldstagger
2285 if (.not. associated(field%r_arr)) then
2286 allocate(field%r_arr(sm1:em1,sm2:em2))
2289 interp_mask_status = 1
2290 interp_land_mask_status = 1
2291 interp_water_mask_status = 1
2293 if (interp_mask(idx) /= ' ') then
2294 mask_field%header%version = 1
2295 mask_field%header%forecast_hour = 0.
2296 mask_field%header%field = trim(interp_mask(idx))//'.mask'
2297 mask_field%header%vertical_coord = 'none'
2298 mask_field%header%vertical_level = 1
2300 call storage_get_field(mask_field, interp_mask_status)
2303 if (interp_land_mask(idx) /= ' ') then
2304 mask_land_field%header%version = 1
2305 mask_land_field%header%forecast_hour = 0.
2306 mask_land_field%header%field = trim(interp_land_mask(idx))//'.mask'
2307 mask_land_field%header%vertical_coord = 'none'
2308 mask_land_field%header%vertical_level = 1
2310 call storage_get_field(mask_land_field, interp_land_mask_status)
2313 if (interp_water_mask(idx) /= ' ') then
2314 mask_water_field%header%version = 1
2315 mask_water_field%header%forecast_hour = 0.
2316 mask_water_field%header%field = trim(interp_water_mask(idx))//'.mask'
2317 mask_water_field%header%vertical_coord = 'none'
2318 mask_water_field%header%vertical_level = 1
2320 call storage_get_field(mask_water_field, interp_water_mask_status)
2324 interp_array => interp_array_from_string(interp_method(idx))
2325 interp_opts => interp_options_from_string(interp_method(idx))
2329 ! Interpolate using average_gcell interpolation method
2331 if (do_gcell_interp) then
2333 !If a lower priority source of the current field has already been read
2334 !in, the results of that input are currently in field%r_arr
2335 !Pass COPY of field%r_arr into accum_continous because in accum_continuous
2336 !it will set the input variable to zero over points covered by the
2337 !current source and then determine the appropriate value to place at
2338 !that point. This will overwrite data already put in field%r_arr by
2339 !lower priority sources.
2340 !This is problematic if the current source results in missing values
2341 !over parts of the area covered by the current source where a lower
2342 !priority source has already provided a value. In this case, if one
2343 !passes in field%r_arr, it will overwrite the value provided by the
2344 !lower priority source with zero.
2345 r_arr_cur_source = field%r_arr
2347 allocate(data_count(sm1:em1,sm2:em2))
2350 if (interp_mask_status == 0) then
2351 call accum_continuous(slab, &
2352 minx, maxx, miny, maxy, 1, 1, bdr, &
2354 !Pass COPY of field%r_arr instead of field%r_arr itself
2355 !field%r_arr, data_count, &
2356 r_arr_cur_source, data_count, &
2358 sm1, em1, sm2, em2, 1, 1, &
2360 new_pts, missing_value(idx), interp_mask_val(idx), interp_mask_relational(idx), mask_field%r_arr)
2362 call accum_continuous(slab, &
2363 minx, maxx, miny, maxy, 1, 1, bdr, &
2365 !Pass COPY of field%r_arr instead of field%r_arr itself
2366 !field%r_arr, data_count, &
2367 r_arr_cur_source, data_count, &
2369 sm1, em1, sm2, em2, 1, 1, &
2371 new_pts, missing_value(idx), -1.) ! The -1 is the maskval, but since we
2372 ! we do not give an optional mask, no
2373 ! no need to worry about -1s in data
2376 orig_selected_proj = iget_selected_domain()
2377 call select_domain(SOURCE_PROJ)
2381 if (abs(i - sd1) >= process_width .and. (abs(i - ed1) >= process_width) .and. &
2382 abs(j - sd2) >= process_width .and. (abs(j - ed2) >= process_width)) then
2383 field%r_arr(i,j) = fill_missing(idx)
2384 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2388 if (present(landmask)) then
2390 if (landmask(i,j) /= masked(idx)) then
2391 if (data_count(i,j) > 0.) then
2393 !accum_continuous is now passed a copy of field%r_arr (r_arr_cur_source)
2394 !instead of field%r_arr itself so that it does not set
2395 !field%r_arr to zero where the input source is marked as missing
2396 !field%r_arr(i,j) = field%r_arr(i,j) / data_count(i,j)
2397 field%r_arr(i,j) = r_arr_cur_source(i,j) / data_count(i,j)
2399 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2402 if (interp_mask_status == 0) then
2403 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2404 minx, maxx, miny, maxy, bdr, missing_value(idx), &
2405 mask_relational=interp_mask_relational(idx), &
2406 mask_val=interp_mask_val(idx), mask_field=mask_field%r_arr)
2408 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2409 minx, maxx, miny, maxy, bdr, missing_value(idx))
2412 if (temp /= missing_value(idx)) then
2413 field%r_arr(i,j) = temp
2414 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2419 field%r_arr(i,j) = fill_missing(idx)
2420 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2423 if (.not. bitarray_test(new_pts, i-sm1+1, j-sm2+1) .and. &
2424 .not. bitarray_test(field%valid_mask, i-sm1+1, j-sm2+1)) then
2425 field%r_arr(i,j) = fill_missing(idx)
2427 ! Assume that if missing fill value is other than default, then user has asked
2428 ! to fill in any missing values, and we can consider this point to have
2429 ! received a valid value
2430 if (fill_missing(idx) /= NAN) call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2435 if (data_count(i,j) > 0.) then
2437 !accum_continuous is now passed a copy of field%r_arr (r_arr_cur_source)
2438 !instead of field%r_arr itself so that it does not set
2439 !field%r_arr to zero where the input source is marked as missing
2440 !field%r_arr(i,j) = field%r_arr(i,j) / data_count(i,j)
2441 field%r_arr(i,j) = r_arr_cur_source(i,j) / data_count(i,j)
2443 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2446 if (interp_mask_status == 0) then
2447 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2448 minx, maxx, miny, maxy, bdr, missing_value(idx), &
2449 mask_relational=interp_mask_relational(idx), &
2450 mask_val=interp_mask_val(idx), mask_field=mask_field%r_arr)
2452 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2453 minx, maxx, miny, maxy, bdr, missing_value(idx))
2456 if (temp /= missing_value(idx)) then
2457 field%r_arr(i,j) = temp
2458 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2463 if (.not. bitarray_test(new_pts, i-sm1+1, j-sm2+1) .and. &
2464 .not. bitarray_test(field%valid_mask, i-sm1+1, j-sm2+1)) then
2465 field%r_arr(i,j) = fill_missing(idx)
2467 ! Assume that if missing fill value is other than default, then user has asked
2468 ! to fill in any missing values, and we can consider this point to have
2469 ! received a valid value
2470 if (fill_missing(idx) /= NAN) call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2477 call select_domain(orig_selected_proj)
2478 deallocate(data_count)
2481 ! No average_gcell interpolation method
2485 orig_selected_proj = iget_selected_domain()
2486 call select_domain(SOURCE_PROJ)
2490 if (abs(i - sd1) >= process_width .and. (abs(i - ed1) >= process_width) .and. &
2491 abs(j - sd2) >= process_width .and. (abs(j - ed2) >= process_width)) then
2492 field%r_arr(i,j) = fill_missing(idx)
2493 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2497 if (present(landmask)) then
2499 if (masked(idx) == MASKED_BOTH) then
2501 if (landmask(i,j) == 0) then ! WATER POINT
2503 if (interp_land_mask_status == 0) then
2504 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2505 minx, maxx, miny, maxy, bdr, missing_value(idx), &
2506 mask_relational=interp_land_mask_relational(idx), &
2507 mask_val=interp_land_mask_val(idx), mask_field=mask_land_field%r_arr)
2509 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2510 minx, maxx, miny, maxy, bdr, missing_value(idx))
2513 else if (landmask(i,j) == 1) then ! LAND POINT
2515 if (interp_water_mask_status == 0) then
2516 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2517 minx, maxx, miny, maxy, bdr, missing_value(idx), &
2518 mask_relational=interp_water_mask_relational(idx), &
2519 mask_val=interp_water_mask_val(idx), mask_field=mask_water_field%r_arr)
2521 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2522 minx, maxx, miny, maxy, bdr, missing_value(idx))
2527 else if (landmask(i,j) /= masked(idx)) then
2529 if (interp_mask_status == 0) then
2530 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2531 minx, maxx, miny, maxy, bdr, missing_value(idx), &
2532 mask_relational=interp_mask_relational(idx), &
2533 mask_val=interp_mask_val(idx), mask_field=mask_field%r_arr)
2535 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2536 minx, maxx, miny, maxy, bdr, missing_value(idx))
2540 temp = missing_value(idx)
2543 ! No landmask for this field
2546 if (interp_mask_status == 0) then
2547 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2548 minx, maxx, miny, maxy, bdr, missing_value(idx), &
2549 mask_relational=interp_mask_relational(idx), &
2550 mask_val=interp_mask_val(idx), mask_field=mask_field%r_arr)
2552 temp = interp_to_latlon(xlat(i,j), xlon(i,j), istagger, interp_array, interp_opts, slab, &
2553 minx, maxx, miny, maxy, bdr, missing_value(idx))
2558 if (temp /= missing_value(idx)) then
2559 field%r_arr(i,j) = temp
2560 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2561 else if (present(landmask)) then
2562 if (landmask(i,j) == masked(idx)) then
2563 field%r_arr(i,j) = fill_missing(idx)
2564 call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2568 if (.not. bitarray_test(new_pts, i-sm1+1, j-sm2+1) .and. &
2569 .not. bitarray_test(field%valid_mask, i-sm1+1, j-sm2+1)) then
2570 field%r_arr(i,j) = fill_missing(idx)
2572 ! Assume that if missing fill value is other than default, then user has asked
2573 ! to fill in any missing values, and we can consider this point to have
2574 ! received a valid value
2575 if (fill_missing(idx) /= NAN) call bitarray_set(new_pts, i-sm1+1, j-sm2+1)
2580 call select_domain(orig_selected_proj)
2583 deallocate(interp_array)
2584 deallocate(interp_opts)
2586 end subroutine interp_met_field
2589 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2590 ! Name: interp_to_latlon
2593 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2594 function interp_to_latlon(rlat, rlon, istagger, interp_method_list, interp_opt_list, slab, &
2595 minx, maxx, miny, maxy, bdr, source_missing_value, &
2596 mask_field, mask_relational, mask_val)
2604 integer, intent(in) :: minx, maxx, miny, maxy, bdr, istagger
2605 integer, dimension(:), intent(in) :: interp_method_list
2606 integer, dimension(:), intent(in) :: interp_opt_list
2607 real, intent(in) :: rlat, rlon, source_missing_value
2608 real, dimension(minx:maxx,miny:maxy), intent(in) :: slab
2609 real, intent(in), optional :: mask_val
2610 real, dimension(minx:maxx,miny:maxy), intent(in), optional :: mask_field
2611 character(len=1), intent(in), optional :: mask_relational
2614 real :: interp_to_latlon
2619 interp_to_latlon = source_missing_value
2621 call lltoxy(rlat, rlon, rx, ry, istagger)
2622 if (rx >= minx+bdr-0.5 .and. rx <= maxx-bdr+0.5) then
2623 if (present(mask_field) .and. present(mask_val) .and. present (mask_relational)) then
2624 interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, 1, 1, source_missing_value, &
2625 interp_method_list, interp_opt_list, 1, mask_relational, mask_val, mask_field)
2626 else if (present(mask_field) .and. present(mask_val)) then
2627 interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, 1, 1, source_missing_value, &
2628 interp_method_list, interp_opt_list, 1, maskval=mask_val, mask_array=mask_field)
2630 interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, 1, 1, source_missing_value, &
2631 interp_method_list, interp_opt_list, 1)
2634 interp_to_latlon = source_missing_value
2637 if (interp_to_latlon == source_missing_value) then
2639 ! Try a lon in the range 0. to 360.; all lons in the xlon
2640 ! array should be in the range -180. to 180.
2642 call lltoxy(rlat, rlon+360., rx, ry, istagger)
2643 if (rx >= minx+bdr-0.5 .and. rx <= maxx-bdr+0.5) then
2644 if (present(mask_field) .and. present(mask_val) .and. present(mask_relational)) then
2645 interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, &
2646 1, 1, source_missing_value, &
2647 interp_method_list, interp_opt_list, 1, &
2648 mask_relational, mask_val, mask_field)
2649 else if (present(mask_field) .and. present(mask_val)) then
2650 interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, &
2651 1, 1, source_missing_value, &
2652 interp_method_list, interp_opt_list, 1, &
2653 maskval=mask_val, mask_array=mask_field)
2655 interp_to_latlon = interp_sequence(rx, ry, 1, slab, minx, maxx, miny, maxy, &
2656 1, 1, source_missing_value, &
2657 interp_method_list, interp_opt_list, 1)
2660 interp_to_latlon = source_missing_value
2669 end function interp_to_latlon
2672 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2673 ! Name: get_bottom_top_dim
2676 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2677 subroutine get_bottom_top_dim(bottom_top_dim)
2679 use interp_option_module
2686 integer, intent(out) :: bottom_top_dim
2690 integer, pointer, dimension(:) :: field_levels
2691 character (len=32) :: z_dim
2692 type (fg_input), pointer, dimension(:) :: headers
2693 type (list) :: temp_levels
2695 !CWH Initialize local pointer variables
2696 nullify(field_levels)
2699 ! Initialize a list to store levels that are found for 3-d fields
2700 call list_init(temp_levels)
2702 ! Get a list of all time-dependent fields (given by their headers) from
2703 ! the storage module
2704 call storage_get_td_headers(headers)
2707 ! Given headers of all fields, we first build a list of all possible levels
2708 ! for 3-d met fields (excluding sea-level, though).
2710 do i=1,size(headers)
2711 call get_z_dim_name(headers(i)%header%field, z_dim)
2713 ! We only want to consider 3-d met fields
2714 if (z_dim(1:18) == 'num_metgrid_levels') then
2716 ! Find out what levels the current field has
2717 call storage_get_levels(headers(i), field_levels)
2718 do j=1,size(field_levels)
2720 ! If this level has not yet been encountered, add it to our list
2721 if (.not. list_search(temp_levels, ikey=field_levels(j), ivalue=field_levels(j))) then
2722 if (field_levels(j) /= 201300) then
2723 call list_insert(temp_levels, ikey=field_levels(j), ivalue=field_levels(j))
2729 deallocate(field_levels)
2735 bottom_top_dim = list_length(temp_levels)
2737 call list_destroy(temp_levels)
2740 end subroutine get_bottom_top_dim
2743 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2744 ! Name: fill_missing_levels
2747 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2748 subroutine fill_missing_levels(output_flags)
2750 use interp_option_module
2753 use module_mergesort
2759 character (len=128), dimension(:), intent(inout) :: output_flags
2762 integer :: i, ii, j, ix, jx, k, lower, upper, temp, istatus
2763 integer, pointer, dimension(:) :: union_levels, field_levels
2764 real, pointer, dimension(:) :: r_union_levels
2765 character (len=128) :: clevel
2766 type (fg_input) :: lower_field, upper_field, new_field, search_field
2767 type (fg_input), pointer, dimension(:) :: headers, all_headers
2768 type (list) :: temp_levels
2769 type (list_item), pointer, dimension(:) :: keys
2771 ! CWH Initialize local pointer variables
2772 nullify(union_levels)
2773 nullify(field_levels)
2774 nullify(r_union_levels)
2776 nullify(all_headers)
2779 ! Initialize a list to store levels that are found for 3-d fields
2780 call list_init(temp_levels)
2782 ! Get a list of all fields (given by their headers) from the storage module
2783 call storage_get_td_headers(headers)
2784 call storage_get_all_headers(all_headers)
2787 ! Given headers of all fields, we first build a list of all possible levels
2788 ! for 3-d met fields (excluding sea-level, though).
2790 do i=1,size(headers)
2792 ! Find out what levels the current field has
2793 call storage_get_levels(headers(i), field_levels)
2794 do j=1,size(field_levels)
2796 ! If this level has not yet been encountered, add it to our list
2797 if (.not. list_search(temp_levels, ikey=field_levels(j), ivalue=field_levels(j))) then
2798 if (field_levels(j) /= 201300) then
2799 call list_insert(temp_levels, ikey=field_levels(j), ivalue=field_levels(j))
2805 deallocate(field_levels)
2809 if (list_length(temp_levels) > 0) then
2812 ! With all possible levels stored in a list, get an array of levels, sorted
2813 ! in decreasing order
2816 allocate(union_levels(list_length(temp_levels)))
2817 do while (list_length(temp_levels) > 0)
2819 call list_get_first_item(temp_levels, ikey=union_levels(i), ivalue=temp)
2821 call mergesort(union_levels, 1, size(union_levels))
2823 allocate(r_union_levels(size(union_levels)))
2824 do i=1,size(union_levels)
2825 r_union_levels(i) = real(union_levels(i))
2829 ! With a sorted, complete list of levels, we need
2830 ! to go back and fill in missing levels for each 3-d field
2832 do i=1,size(headers)
2835 ! Find entry in METGRID.TBL for this field, if one exists; if it does, then the
2836 ! entry may tell us how to get values for the current field at the missing level
2839 if (fieldname(ii) == headers(i)%header%field) exit
2841 if (ii <= num_entries) then
2842 call dup(headers(i),new_field)
2843 nullify(new_field%valid_mask)
2844 nullify(new_field%modified_mask)
2845 call fill_field(new_field, ii, output_flags, r_union_levels)
2850 deallocate(union_levels)
2851 deallocate(r_union_levels)
2854 call storage_get_td_headers(headers)
2857 ! Now we may need to vertically interpolate to missing values in 3-d fields
2859 do i=1,size(headers)
2861 call storage_get_levels(headers(i), field_levels)
2863 ! If this isn't a 3-d array, nothing to do
2864 if (size(field_levels) > 1) then
2866 do k=1,size(field_levels)
2867 call dup(headers(i),search_field)
2868 search_field%header%vertical_level = field_levels(k)
2869 call storage_get_field(search_field,istatus)
2870 if (istatus == 0) then
2871 JLOOP: do jx=search_field%header%dim2(1),search_field%header%dim2(2)
2872 ILOOP: do ix=search_field%header%dim1(1),search_field%header%dim1(2)
2873 if (.not. bitarray_test(search_field%valid_mask, &
2874 ix-search_field%header%dim1(1)+1, &
2875 jx-search_field%header%dim2(1)+1)) then
2877 call dup(search_field, lower_field)
2879 lower_field%header%vertical_level = field_levels(lower)
2880 call storage_get_field(lower_field,istatus)
2881 if (bitarray_test(lower_field%valid_mask, &
2882 ix-search_field%header%dim1(1)+1, &
2883 jx-search_field%header%dim2(1)+1)) &
2888 call dup(search_field, upper_field)
2889 do upper=k+1,size(field_levels)
2890 upper_field%header%vertical_level = field_levels(upper)
2891 call storage_get_field(upper_field,istatus)
2892 if (bitarray_test(upper_field%valid_mask, &
2893 ix-search_field%header%dim1(1)+1, &
2894 jx-search_field%header%dim2(1)+1)) &
2898 if (upper <= size(field_levels) .and. lower >= 1) then
2899 search_field%r_arr(ix,jx) = real(abs(field_levels(upper)-field_levels(k))) &
2900 / real(abs(field_levels(upper)-field_levels(lower))) &
2901 * lower_field%r_arr(ix,jx) &
2902 + real(abs(field_levels(k)-field_levels(lower))) &
2903 / real(abs(field_levels(upper)-field_levels(lower))) &
2904 * upper_field%r_arr(ix,jx)
2905 call bitarray_set(search_field%valid_mask, &
2906 ix-search_field%header%dim1(1)+1, &
2907 jx-search_field%header%dim2(1)+1)
2913 call mprintf(.true.,ERROR, &
2914 'This is bad, could not get %s at level %i.', &
2915 s1=trim(search_field%header%field), i1=field_levels(k))
2921 deallocate(field_levels)
2927 call list_destroy(temp_levels)
2928 deallocate(all_headers)
2931 end subroutine fill_missing_levels
2934 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2935 ! Name: create_derived_fields
2938 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2939 subroutine create_derived_fields(arg_gridtype, hdate, xfcst, &
2940 we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
2941 we_mem_stag_s, we_mem_stag_e, sn_mem_stag_s, sn_mem_stag_e, &
2942 created_this_field, output_flags)
2944 use interp_option_module
2946 use module_mergesort
2952 integer, intent(in) :: we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
2953 we_mem_stag_s, we_mem_stag_e, sn_mem_stag_s, sn_mem_stag_e
2954 real, intent(in) :: xfcst
2955 logical, dimension(:), intent(inout) :: created_this_field
2956 character (len=1), intent(in) :: arg_gridtype
2957 character (len=24), intent(in) :: hdate
2958 character (len=128), dimension(:), intent(inout) :: output_flags
2961 integer :: idx, i, j, istatus
2962 type (fg_input) :: field
2964 ! Initialize fg_input structure to store the field
2965 field%header%version = 1
2966 field%header%date = hdate//' '
2967 field%header%time_dependent = .true.
2968 field%header%mask_field = .false.
2969 field%header%constant_field = .false.
2970 field%header%forecast_hour = xfcst
2971 field%header%fg_source = 'Derived from FG'
2972 field%header%field = ' '
2973 field%header%units = ' '
2974 field%header%description = ' '
2975 field%header%vertical_level = 0
2976 field%header%sr_x = 1
2977 field%header%sr_y = 1
2978 field%header%array_order = 'XY '
2979 field%header%is_wind_grid_rel = .true.
2980 field%header%array_has_missing_values = .false.
2981 nullify(field%r_arr)
2982 nullify(field%valid_mask)
2983 nullify(field%modified_mask)
2986 ! Check each entry in METGRID.TBL to see whether it is a derive field
2988 do idx=1,num_entries
2989 if (is_derived_field(idx)) then
2991 created_this_field(idx) = .true.
2993 call mprintf(.true.,INFORM,'Going to create the field %s',s1=fieldname(idx))
2995 ! Intialize more fields in storage structure
2996 field%header%field = fieldname(idx)
2997 call get_z_dim_name(fieldname(idx),field%header%vertical_coord)
2998 field%map%stagger = output_stagger(idx)
2999 if (arg_gridtype == 'E') then
3000 field%header%dim1(1) = we_mem_s
3001 field%header%dim1(2) = we_mem_e
3002 field%header%dim2(1) = sn_mem_s
3003 field%header%dim2(2) = sn_mem_e
3004 else if (arg_gridtype == 'C') then
3005 if (output_stagger(idx) == M) then
3006 field%header%dim1(1) = we_mem_s
3007 field%header%dim1(2) = we_mem_e
3008 field%header%dim2(1) = sn_mem_s
3009 field%header%dim2(2) = sn_mem_e
3010 else if (output_stagger(idx) == U) then
3011 field%header%dim1(1) = we_mem_stag_s
3012 field%header%dim1(2) = we_mem_stag_e
3013 field%header%dim2(1) = sn_mem_s
3014 field%header%dim2(2) = sn_mem_e
3015 else if (output_stagger(idx) == V) then
3016 field%header%dim1(1) = we_mem_s
3017 field%header%dim1(2) = we_mem_e
3018 field%header%dim2(1) = sn_mem_stag_s
3019 field%header%dim2(2) = sn_mem_stag_e
3023 call fill_field(field, idx, output_flags)
3029 end subroutine create_derived_fields
3032 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3036 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3037 subroutine fill_field(field, idx, output_flags, all_level_list)
3039 use interp_option_module
3041 use module_mergesort
3047 integer, intent(in) :: idx
3048 type (fg_input), intent(inout) :: field
3049 character (len=128), dimension(:), intent(inout) :: output_flags
3050 real, dimension(:), intent(in), optional :: all_level_list
3053 integer :: i, j, istatus, isrclevel
3054 integer, pointer, dimension(:) :: all_list
3055 real :: rfillconst, rlevel, rsrclevel
3056 type (fg_input) :: query_field
3057 type (list_item), pointer, dimension(:) :: keys
3058 character (len=128) :: asrcname
3059 logical :: filled_all_lev
3061 !CWH Initialize local pointer variables
3065 filled_all_lev = .false.
3068 ! Get a list of all levels to be filled for this field
3070 keys => list_get_keys(fill_lev_list(idx))
3072 do i=1,list_length(fill_lev_list(idx))
3075 ! First handle a specification for levels "all"
3077 if (trim(keys(i)%ckey) == 'all') then
3079 ! We only want to fill all levels if we haven't already filled "all" of them
3080 if (.not. filled_all_lev) then
3082 filled_all_lev = .true.
3084 query_field%header%time_dependent = .true.
3085 query_field%header%field = ' '
3086 nullify(query_field%r_arr)
3087 nullify(query_field%valid_mask)
3088 nullify(query_field%modified_mask)
3090 ! See if we are filling this level with a constant
3091 call get_constant_fill_lev(keys(i)%cvalue, rfillconst, istatus)
3092 if (istatus == 0) then
3093 if (present(all_level_list)) then
3094 do j=1,size(all_level_list)
3095 call create_level(field, real(all_level_list(j)), idx, output_flags, rfillconst=rfillconst)
3098 query_field%header%field = level_template(idx)
3100 call storage_get_levels(query_field, all_list)
3101 if (associated(all_list)) then
3102 do j=1,size(all_list)
3103 call create_level(field, real(all_list(j)), idx, output_flags, rfillconst=rfillconst)
3105 deallocate(all_list)
3109 ! Else see if we are filling this level with a constant equal
3110 ! to the value of the level
3111 else if (trim(keys(i)%cvalue) == 'vertical_index') then
3112 if (present(all_level_list)) then
3113 do j=1,size(all_level_list)
3114 call create_level(field, real(all_level_list(j)), idx, output_flags, &
3115 rfillconst=real(all_level_list(j)))
3118 query_field%header%field = level_template(idx)
3120 call storage_get_levels(query_field, all_list)
3121 if (associated(all_list)) then
3122 do j=1,size(all_list)
3123 call create_level(field, real(all_list(j)), idx, output_flags, rfillconst=real(all_list(j)))
3125 deallocate(all_list)
3129 ! Else, we assume that it is a field from which we are copying levels
3131 if (present(all_level_list)) then
3132 do j=1,size(all_level_list)
3133 call create_level(field, real(all_level_list(j)), idx, output_flags, &
3134 asrcname=keys(i)%cvalue, rsrclevel=real(all_level_list(j)))
3137 query_field%header%field = keys(i)%cvalue ! Use same levels as source field, not level_template
3139 call storage_get_levels(query_field, all_list)
3140 if (associated(all_list)) then
3141 do j=1,size(all_list)
3142 call create_level(field, real(all_list(j)), idx, output_flags, &
3143 asrcname=keys(i)%cvalue, rsrclevel=real(all_list(j)))
3145 deallocate(all_list)
3149 ! If the field doesn't have any levels (or does not exist) then we have not
3150 ! really filled all levels at this point.
3151 filled_all_lev = .false.
3159 ! Handle individually specified levels
3163 read(keys(i)%ckey,*) rlevel
3165 ! See if we are filling this level with a constant
3166 call get_constant_fill_lev(keys(i)%cvalue, rfillconst, istatus)
3167 if (istatus == 0) then
3168 call create_level(field, rlevel, idx, output_flags, rfillconst=rfillconst)
3170 ! Otherwise, we are filling from another level
3172 call get_fill_src_level(keys(i)%cvalue, asrcname, isrclevel)
3173 rsrclevel = real(isrclevel)
3174 call create_level(field, rlevel, idx, output_flags, &
3175 asrcname=asrcname, rsrclevel=rsrclevel)
3181 if (associated(keys)) deallocate(keys)
3183 end subroutine fill_field
3186 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3187 ! Name: create_level
3190 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3191 subroutine create_level(field_template, rlevel, idx, output_flags, &
3192 rfillconst, asrcname, rsrclevel)
3195 use interp_option_module
3200 type (fg_input), intent(inout) :: field_template
3201 real, intent(in) :: rlevel
3202 integer, intent(in) :: idx
3203 character (len=128), dimension(:), intent(inout) :: output_flags
3204 real, intent(in), optional :: rfillconst, rsrclevel
3205 character (len=128), intent(in), optional :: asrcname
3208 integer :: i, j, istatus
3209 integer :: sm1,em1,sm2,em2
3210 type (fg_input) :: query_field
3213 ! Check to make sure optional arguments are sane
3215 if (present(rfillconst) .and. (present(asrcname) .or. present(rsrclevel))) then
3216 call mprintf(.true.,ERROR,'A call to create_level() cannot be given specifications '// &
3217 'for both a constant fill value and a source level.')
3219 else if ((present(asrcname) .and. .not. present(rsrclevel)) .or. &
3220 (.not. present(asrcname) .and. present(rsrclevel))) then
3221 call mprintf(.true.,ERROR,'Neither or both of optional arguments asrcname and '// &
3222 'rsrclevel must be specified to subroutine create_level().')
3224 else if (.not. present(rfillconst) .and. &
3225 .not. present(asrcname) .and. &
3226 .not. present(rsrclevel)) then
3227 call mprintf(.true.,ERROR,'A call to create_level() must be given either a specification '// &
3228 'for a constant fill value or a source level.')
3231 query_field%header%time_dependent = .true.
3232 query_field%header%field = field_template%header%field
3233 query_field%header%vertical_level = rlevel
3234 nullify(query_field%r_arr)
3235 nullify(query_field%valid_mask)
3236 nullify(query_field%modified_mask)
3238 call storage_query_field(query_field, istatus)
3239 if (istatus == 0) then
3240 call mprintf(.true.,INFORM,'%s at level %f already exists; leaving it alone.', &
3241 s1=field_template%header%field, f1=rlevel)
3245 sm1 = field_template%header%dim1(1)
3246 em1 = field_template%header%dim1(2)
3247 sm2 = field_template%header%dim2(1)
3248 em2 = field_template%header%dim2(2)
3251 ! Handle constant fill value case
3253 if (present(rfillconst)) then
3255 field_template%header%vertical_level = rlevel
3256 allocate(field_template%r_arr(sm1:em1,sm2:em2))
3257 allocate(field_template%valid_mask)
3258 allocate(field_template%modified_mask)
3259 call bitarray_create(field_template%valid_mask, em1-sm1+1, em2-sm2+1)
3260 call bitarray_create(field_template%modified_mask, em1-sm1+1, em2-sm2+1)
3262 field_template%r_arr = rfillconst
3266 call bitarray_set(field_template%valid_mask, i-sm1+1, j-sm2+1)
3270 call storage_put_field(field_template)
3272 if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
3273 output_flags(idx) = flag_in_output(idx)
3277 ! Handle source field and source level case
3279 else if (present(asrcname) .and. present(rsrclevel)) then
3281 query_field%header%field = ' '
3282 query_field%header%field = asrcname
3283 query_field%header%vertical_level = rsrclevel
3285 ! Check to see whether the requested source field exists at the requested level
3286 call storage_query_field(query_field, istatus)
3288 if (istatus == 0) then
3290 ! Read in requested field at requested level
3291 call storage_get_field(query_field, istatus)
3292 if ((query_field%header%dim1(1) /= field_template%header%dim1(1)) .or. &
3293 (query_field%header%dim1(2) /= field_template%header%dim1(2)) .or. &
3294 (query_field%header%dim2(1) /= field_template%header%dim2(1)) .or. &
3295 (query_field%header%dim2(2) /= field_template%header%dim2(2))) then
3296 call mprintf(.true.,ERROR,'Dimensions for %s do not match those of %s. This is '// &
3297 'probably because the staggerings of the fields do not match.', &
3298 s1=query_field%header%field, s2=field_template%header%field)
3301 field_template%header%vertical_level = rlevel
3302 allocate(field_template%r_arr(sm1:em1,sm2:em2))
3303 allocate(field_template%valid_mask)
3304 allocate(field_template%modified_mask)
3305 call bitarray_create(field_template%valid_mask, em1-sm1+1, em2-sm2+1)
3306 call bitarray_create(field_template%modified_mask, em1-sm1+1, em2-sm2+1)
3308 field_template%r_arr = query_field%r_arr
3310 ! We should retain information about which points in the field are valid
3313 if (bitarray_test(query_field%valid_mask, i-sm1+1, j-sm2+1)) then
3314 call bitarray_set(field_template%valid_mask, i-sm1+1, j-sm2+1)
3319 call storage_put_field(field_template)
3321 if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
3322 output_flags(idx) = flag_in_output(idx)
3326 call mprintf(.true.,INFORM,'Couldn''t find %s at level %f to fill level %f of %s.', &
3327 s1=asrcname,f1=rsrclevel,f2=rlevel,s2=field_template%header%field)
3332 end subroutine create_level
3335 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3336 ! Name: accum_continuous
3338 ! Purpose: Sum up all of the source data points whose nearest neighbor in the
3339 ! model grid is the specified model grid point.
3341 ! NOTE: When processing the source tile, those source points that are
3342 ! closest to a different model grid point will be added to the totals for
3343 ! such grid points; thus, an entire source tile will be processed at a time.
3344 ! This routine really processes for all model grid points that are
3345 ! within a source tile, and not just for a single grid point.
3346 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3347 subroutine accum_continuous(src_array, &
3348 src_min_x, src_max_x, src_min_y, src_max_y, src_min_z, src_max_z, bdr_width, &
3350 start_i, end_i, start_j, end_j, start_k, end_k, &
3352 new_pts, msgval, maskval, mask_relational, mask_array, sr_x, sr_y)
3355 use misc_definitions_module
3360 integer, intent(in) :: start_i, end_i, start_j, end_j, start_k, end_k, istagger, &
3361 src_min_x, src_max_x, src_min_y, src_max_y, src_min_z, src_max_z, bdr_width
3362 real, intent(in) :: maskval, msgval
3363 real, dimension(src_min_x:src_max_x, src_min_y:src_max_y, src_min_z:src_max_z), intent(in) :: src_array
3364 real, dimension(start_i:end_i, start_j:end_j, start_k:end_k), intent(inout) :: dst_array, n
3365 real, dimension(src_min_x:src_max_x, src_min_y:src_max_y), intent(in), optional :: mask_array
3366 integer, intent(in), optional :: sr_x, sr_y
3367 type (bitarray), intent(inout) :: new_pts
3368 character(len=1), intent(in), optional :: mask_relational
3372 integer, pointer, dimension(:,:,:) :: where_maps_to
3373 real :: rsr_x, rsr_y
3377 if (present(sr_x)) rsr_x = real(sr_x)
3378 if (present(sr_y)) rsr_y = real(sr_y)
3380 allocate(where_maps_to(src_min_x:src_max_x,src_min_y:src_max_y,2))
3381 do i=src_min_x,src_max_x
3382 do j=src_min_y,src_max_y
3383 where_maps_to(i,j,1) = NOT_PROCESSED
3387 call process_continuous_block(src_array, where_maps_to, &
3388 src_min_x, src_min_y, src_min_z, src_max_x, src_max_y, src_max_z, &
3389 src_min_x+bdr_width, src_min_y, src_min_z, &
3390 src_max_x-bdr_width, src_max_y, src_max_z, &
3391 dst_array, n, start_i, end_i, start_j, end_j, start_k, end_k, &
3393 new_pts, rsr_x, rsr_y, msgval, maskval, mask_relational, mask_array)
3395 deallocate(where_maps_to)
3397 end subroutine accum_continuous
3400 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3401 ! Name: process_continuous_block
3403 ! Purpose: To recursively process a subarray of continuous data, adding the
3404 ! points in a block to the sum for their nearest grid point. The nearest
3405 ! neighbor may be estimated in some cases; for example, if the four corners
3406 ! of a subarray all have the same nearest grid point, all elements in the
3407 ! subarray are added to that grid point.
3408 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3409 recursive subroutine process_continuous_block(tile_array, where_maps_to, &
3410 src_min_x, src_min_y, src_min_z, src_max_x, src_max_y, src_max_z, &
3411 min_i, min_j, min_k, max_i, max_j, max_k, &
3413 start_x, end_x, start_y, end_y, start_z, end_z, &
3415 new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
3419 use misc_definitions_module
3424 integer, intent(in) :: min_i, min_j, min_k, max_i, max_j, max_k, &
3425 src_min_x, src_min_y, src_min_z, src_max_x, src_max_y, src_max_z, &
3426 start_x, end_x, start_y, end_y, start_z, end_z, istagger
3427 integer, dimension(src_min_x:src_max_x,src_min_y:src_max_y,2), intent(inout) :: where_maps_to
3428 real, intent(in) :: sr_x, sr_y, maskval, msgval
3429 real, dimension(src_min_x:src_max_x,src_min_y:src_max_y,src_min_z:src_max_z), intent(in) :: tile_array
3430 real, dimension(src_min_x:src_max_x,src_min_y:src_max_y), intent(in), optional :: mask_array
3431 real, dimension(start_x:end_x,start_y:end_y,start_z:end_z), intent(inout) :: dst_array, n
3432 type (bitarray), intent(inout) :: new_pts
3433 character(len=1), intent(in), optional :: mask_relational
3436 integer :: orig_selected_domain, x_dest, y_dest, i, j, k, center_i, center_j
3437 real :: lat_corner, lon_corner, rx, ry
3439 ! Compute the model grid point that the corners of the rectangle to be
3442 if (where_maps_to(min_i,min_j,1) == NOT_PROCESSED) then
3443 orig_selected_domain = iget_selected_domain()
3444 call select_domain(SOURCE_PROJ)
3445 call xytoll(real(min_i), real(min_j), lat_corner, lon_corner, istagger)
3446 call select_domain(1)
3447 call lltoxy(lat_corner, lon_corner, rx, ry, istagger)
3448 rx = (rx - 0.5)*sr_x + 0.5
3449 ry = (ry - 0.5)*sr_y + 0.5
3450 call select_domain(orig_selected_domain)
3451 if (real(start_x) <= rx .and. rx <= real(end_x) .and. &
3452 real(start_y) <= ry .and. ry <= real(end_y)) then
3453 where_maps_to(min_i,min_j,1) = nint(rx)
3454 where_maps_to(min_i,min_j,2) = nint(ry)
3456 where_maps_to(min_i,min_j,1) = OUTSIDE_DOMAIN
3461 if (where_maps_to(min_i,max_j,1) == NOT_PROCESSED) then
3462 orig_selected_domain = iget_selected_domain()
3463 call select_domain(SOURCE_PROJ)
3464 call xytoll(real(min_i), real(max_j), lat_corner, lon_corner, istagger)
3465 call select_domain(1)
3466 call lltoxy(lat_corner, lon_corner, rx, ry, istagger)
3467 rx = (rx - 0.5)*sr_x + 0.5
3468 ry = (ry - 0.5)*sr_y + 0.5
3469 call select_domain(orig_selected_domain)
3470 if (real(start_x) <= rx .and. rx <= real(end_x) .and. &
3471 real(start_y) <= ry .and. ry <= real(end_y)) then
3472 where_maps_to(min_i,max_j,1) = nint(rx)
3473 where_maps_to(min_i,max_j,2) = nint(ry)
3475 where_maps_to(min_i,max_j,1) = OUTSIDE_DOMAIN
3479 ! Upper-right corner
3480 if (where_maps_to(max_i,max_j,1) == NOT_PROCESSED) then
3481 orig_selected_domain = iget_selected_domain()
3482 call select_domain(SOURCE_PROJ)
3483 call xytoll(real(max_i), real(max_j), lat_corner, lon_corner, istagger)
3484 call select_domain(1)
3485 call lltoxy(lat_corner, lon_corner, rx, ry, istagger)
3486 rx = (rx - 0.5)*sr_x + 0.5
3487 ry = (ry - 0.5)*sr_y + 0.5
3488 call select_domain(orig_selected_domain)
3489 if (real(start_x) <= rx .and. rx <= real(end_x) .and. &
3490 real(start_y) <= ry .and. ry <= real(end_y)) then
3491 where_maps_to(max_i,max_j,1) = nint(rx)
3492 where_maps_to(max_i,max_j,2) = nint(ry)
3494 where_maps_to(max_i,max_j,1) = OUTSIDE_DOMAIN
3498 ! Lower-right corner
3499 if (where_maps_to(max_i,min_j,1) == NOT_PROCESSED) then
3500 orig_selected_domain = iget_selected_domain()
3501 call select_domain(SOURCE_PROJ)
3502 call xytoll(real(max_i), real(min_j), lat_corner, lon_corner, istagger)
3503 call select_domain(1)
3504 call lltoxy(lat_corner, lon_corner, rx, ry, istagger)
3505 rx = (rx - 0.5)*sr_x + 0.5
3506 ry = (ry - 0.5)*sr_y + 0.5
3507 call select_domain(orig_selected_domain)
3508 if (real(start_x) <= rx .and. rx <= real(end_x) .and. &
3509 real(start_y) <= ry .and. ry <= real(end_y)) then
3510 where_maps_to(max_i,min_j,1) = nint(rx)
3511 where_maps_to(max_i,min_j,2) = nint(ry)
3513 where_maps_to(max_i,min_j,1) = OUTSIDE_DOMAIN
3517 ! If all four corners map to same model grid point, accumulate the
3519 if (where_maps_to(min_i,min_j,1) == where_maps_to(min_i,max_j,1) .and. &
3520 where_maps_to(min_i,min_j,1) == where_maps_to(max_i,max_j,1) .and. &
3521 where_maps_to(min_i,min_j,1) == where_maps_to(max_i,min_j,1) .and. &
3522 where_maps_to(min_i,min_j,2) == where_maps_to(min_i,max_j,2) .and. &
3523 where_maps_to(min_i,min_j,2) == where_maps_to(max_i,max_j,2) .and. &
3524 where_maps_to(min_i,min_j,2) == where_maps_to(max_i,min_j,2) .and. &
3525 where_maps_to(min_i,min_j,1) /= OUTSIDE_DOMAIN) then
3526 x_dest = where_maps_to(min_i,min_j,1)
3527 y_dest = where_maps_to(min_i,min_j,2)
3529 ! If this grid point was already given a value from higher-priority source data,
3530 ! there is nothing to do.
3531 ! if (.not. bitarray_test(processed_pts, x_dest-start_x+1, y_dest-start_y+1)) then
3533 ! If this grid point has never been given a value by this level of source data,
3534 ! initialize the point
3535 if (.not. bitarray_test(new_pts, x_dest-start_x+1, y_dest-start_y+1)) then
3537 dst_array(x_dest,y_dest,k) = 0.
3541 ! Sum all the points whose nearest neighbor is this grid point
3542 if (present(mask_array) .and. present(mask_relational)) then
3546 ! Ignore masked/missing values in the source data
3547 if (tile_array(i,j,k) /= msgval) then
3548 if (mask_relational == ' ' .and. mask_array(i,j) /= maskval) then
3549 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3550 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3551 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3552 else if (mask_relational == '<' .and. mask_array(i,j) >= maskval) then
3553 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3554 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3555 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3556 else if (mask_relational == '>' .and. mask_array(i,j) <= maskval) then
3557 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3558 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3559 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3565 else if (present(mask_array)) then
3569 ! Ignore masked/missing values in the source data
3570 if ((tile_array(i,j,k) /= msgval) .and. &
3571 (mask_array(i,j) /= maskval)) then
3572 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3573 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3574 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3583 ! Ignore masked/missing values in the source data
3584 if ((tile_array(i,j,k) /= msgval)) then
3585 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3586 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3587 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3596 ! Rectangle is a square of four points, and we can simply deal with each of the points
3597 else if (((max_i - min_i + 1) <= 2) .and. ((max_j - min_j + 1) <= 2)) then
3600 x_dest = where_maps_to(i,j,1)
3601 y_dest = where_maps_to(i,j,2)
3603 if (x_dest /= OUTSIDE_DOMAIN) then
3605 ! if (.not. bitarray_test(processed_pts, x_dest-start_x+1, y_dest-start_y+1)) then
3606 if (.not. bitarray_test(new_pts, x_dest-start_x+1, y_dest-start_y+1)) then
3608 dst_array(x_dest,y_dest,k) = 0.
3612 if (present(mask_array) .and. present(mask_relational)) then
3614 ! Ignore masked/missing values
3615 if (tile_array(i,j,k) /= msgval) then
3616 if (mask_relational == ' ' .and. mask_array(i,j) /= maskval) then
3617 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3618 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3619 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3620 else if (mask_relational == '<' .and. mask_array(i,j) >= maskval) then
3621 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3622 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3623 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3624 else if (mask_relational == '>' .and. mask_array(i,j) <= maskval) then
3625 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3626 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3627 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3631 else if (present(mask_array)) then
3633 ! Ignore masked/missing values
3634 if ((tile_array(i,j,k) /= msgval) .and. &
3635 (mask_array(i,j) /= maskval)) then
3636 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3637 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3638 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3643 ! Ignore masked/missing values
3644 if ((tile_array(i,j,k) /= msgval)) then
3645 dst_array(x_dest,y_dest,k) = dst_array(x_dest,y_dest,k) + tile_array(i,j,k)
3646 n(x_dest,y_dest,k) = n(x_dest,y_dest,k) + 1.0
3647 call bitarray_set(new_pts, x_dest-start_x+1, y_dest-start_y+1)
3657 ! Not all corners map to the same grid point, and the rectangle contains more than
3660 center_i = (max_i + min_i)/2
3661 center_j = (max_j + min_j)/2
3663 ! Recursively process lower-left rectangle
3664 call process_continuous_block(tile_array, where_maps_to, &
3665 src_min_x, src_min_y, src_min_z, &
3666 src_max_x, src_max_y, src_max_z, &
3667 min_i, min_j, min_k, &
3668 center_i, center_j, max_k, &
3670 start_x, end_x, start_y, end_y, start_z, end_z, &
3672 new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
3674 if (center_i < max_i) then
3675 ! Recursively process lower-right rectangle
3676 call process_continuous_block(tile_array, where_maps_to, &
3677 src_min_x, src_min_y, src_min_z, &
3678 src_max_x, src_max_y, src_max_z, &
3679 center_i+1, min_j, min_k, max_i, &
3682 start_x, end_x, start_y, &
3683 end_y, start_z, end_z, &
3685 new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
3688 if (center_j < max_j) then
3689 ! Recursively process upper-left rectangle
3690 call process_continuous_block(tile_array, where_maps_to, &
3691 src_min_x, src_min_y, src_min_z, &
3692 src_max_x, src_max_y, src_max_z, &
3693 min_i, center_j+1, min_k, center_i, &
3696 start_x, end_x, start_y, &
3697 end_y, start_z, end_z, &
3699 new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
3702 if (center_i < max_i .and. center_j < max_j) then
3703 ! Recursively process upper-right rectangle
3704 call process_continuous_block(tile_array, where_maps_to, &
3705 src_min_x, src_min_y, src_min_z, &
3706 src_max_x, src_max_y, src_max_z, &
3707 center_i+1, center_j+1, min_k, max_i, &
3710 start_x, end_x, start_y, &
3711 end_y, start_z, end_z, &
3713 new_pts, sr_x, sr_y, msgval, maskval, mask_relational, mask_array)
3717 end subroutine process_continuous_block
3719 end module process_domain_module