1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2 ! Module: source_data_module
5 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
6 module source_data_module
11 use misc_definitions_module
14 integer, parameter :: RETURN_LANDMASK = 0, &
15 RETURN_DOMCAT_LM = 1, &
18 RETURN_FIELDNAME = 4, &
22 integer, parameter :: MAX_LANDMASK_CATEGORIES = 100
25 integer :: num_entries
26 integer :: next_field = 1
27 integer :: output_field_state = RETURN_LANDMASK
28 integer, pointer, dimension(:) :: source_proj, source_wordsize, source_endian, source_fieldtype, &
29 source_dest_fieldtype, source_priority, source_tile_x, source_tile_y, &
30 source_tile_z, source_tile_z_start, source_tile_z_end, source_tile_bdr, &
31 source_category_min, source_category_max, source_smooth_option, &
32 source_smooth_passes, source_output_stagger, source_row_order
33 integer :: source_iswater, source_islake, source_isice, source_isurban, source_isoilwater
34 real, pointer, dimension(:) :: source_dx, source_dy, source_known_x, source_known_y, &
35 source_known_lat, source_known_lon, source_masked, source_truelat1, source_truelat2, &
36 source_stdlon, source_scale_factor, source_missing_value, source_fill_missing
37 character (len=128), pointer, dimension(:) :: source_fieldname, source_path, source_interp_string, &
38 source_dominant_category, source_dominant_only, source_dfdx, source_dfdy, &
39 source_z_dim_name, source_units, source_descr
40 character (len=128) :: source_mminlu
41 logical, pointer, dimension(:) :: is_proj, is_wordsize, is_endian, is_fieldtype, &
42 is_dest_fieldtype, is_priority, is_tile_x, is_tile_y, is_tile_z, &
43 is_tile_z_start, is_tile_z_end, is_tile_bdr, is_category_min, &
44 is_category_max, is_masked, &
45 is_dx, is_dy, is_known_x, is_known_y, &
46 is_known_lat, is_known_lon, is_truelat1, is_truelat2, is_stdlon, &
47 is_scale_factor, is_fieldname, is_path, is_dominant_category, &
48 is_dominant_only, is_dfdx, is_dfdy, is_z_dim_name, &
49 is_smooth_option, is_smooth_passes, is_signed, is_missing_value, &
50 is_fill_missing, is_halt_missing, is_output_stagger, is_row_order, &
51 is_units, is_descr, is_subgrid
53 type (list), pointer, dimension(:) :: source_res_path, source_interp_option, source_landmask_land, &
55 type (hashtable) :: bad_files ! Track which files produce errors when we try to open them
56 type (hashtable) :: duplicate_fnames ! Remember which output fields we have returned
62 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
66 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
67 subroutine get_datalist()
75 integer, parameter :: BUFSIZE = 256
78 integer :: nparams, idx, eos, ispace, comma, i, j, funit
79 logical :: have_specification, is_used
80 character (len=128) :: res_string, path_string, interp_string, landmask_string
81 character (len=BUFSIZE) :: buffer
87 inquire(unit=funit, opened=is_used)
88 if (.not. is_used) exit
90 open(funit,file=trim(opt_geogrid_tbl_path)//'GEOGRID.TBL',form='formatted',status='old',err=1000)
93 ! We will first go through the file to determine how many field
94 ! specifications there are
96 10 read(funit,'(a)',end=20,err=1001) buffer
99 ! Is this line a comment?
100 if (buffer(1:1) == '#') then
102 ! Are we beginning a new field specification?
103 else if (index(buffer,'=====') /= 0) then
104 if (nparams > 0) num_entries = num_entries + 1
108 eos = index(buffer,'#')
109 if (eos /= 0) buffer(eos:BUFSIZE) = ' '
111 ! Does this line contain at least one parameter specification?
112 if (index(buffer,'=') /= 0) then
113 nparams = nparams + 1
120 ! In case the last entry ended without a ======== line
121 if (nparams > 0) num_entries = num_entries + 1
123 call mprintf(.true.,STDOUT,'Parsed %i entries in GEOGRID.TBL', i1=num_entries)
126 ! Now that we know how many fields the user has specified, allocate
127 ! the properly sized arrays
129 allocate(source_wordsize(num_entries))
130 allocate(source_endian(num_entries))
131 allocate(source_fieldtype(num_entries))
132 allocate(source_dest_fieldtype(num_entries))
133 allocate(source_proj(num_entries))
134 allocate(source_priority(num_entries))
135 allocate(source_dx(num_entries))
136 allocate(source_dy(num_entries))
137 allocate(source_known_x(num_entries))
138 allocate(source_known_y(num_entries))
139 allocate(source_known_lat(num_entries))
140 allocate(source_known_lon(num_entries))
141 allocate(source_truelat1(num_entries))
142 allocate(source_truelat2(num_entries))
143 allocate(source_stdlon(num_entries))
144 allocate(source_fieldname(num_entries))
145 allocate(source_path(num_entries))
146 allocate(source_interp_string(num_entries))
147 allocate(source_tile_x(num_entries))
148 allocate(source_tile_y(num_entries))
149 allocate(source_tile_z(num_entries))
150 allocate(source_tile_z_start(num_entries))
151 allocate(source_tile_z_end(num_entries))
152 allocate(source_category_min(num_entries))
153 allocate(source_category_max(num_entries))
154 allocate(source_tile_bdr(num_entries))
155 allocate(source_masked(num_entries))
156 allocate(source_output_stagger(num_entries))
157 allocate(source_row_order(num_entries))
158 allocate(source_dominant_category(num_entries))
159 allocate(source_dominant_only(num_entries))
160 allocate(source_dfdx(num_entries))
161 allocate(source_dfdy(num_entries))
162 allocate(source_scale_factor(num_entries))
163 allocate(source_z_dim_name(num_entries))
164 allocate(source_units(num_entries))
165 allocate(source_descr(num_entries))
166 allocate(source_smooth_option(num_entries))
167 allocate(source_smooth_passes(num_entries))
168 allocate(source_missing_value(num_entries))
169 allocate(source_fill_missing(num_entries))
170 allocate(source_res_path(num_entries))
171 allocate(source_interp_option(num_entries))
172 allocate(source_landmask_land(num_entries))
173 allocate(source_landmask_water(num_entries))
175 call list_init(source_res_path(i))
176 call list_init(source_interp_option(i))
177 call list_init(source_landmask_land(i))
178 call list_init(source_landmask_water(i))
181 allocate(is_wordsize(num_entries))
182 allocate(is_endian(num_entries))
183 allocate(is_fieldtype(num_entries))
184 allocate(is_dest_fieldtype(num_entries))
185 allocate(is_proj(num_entries))
186 allocate(is_priority(num_entries))
187 allocate(is_dx(num_entries))
188 allocate(is_dy(num_entries))
189 allocate(is_known_x(num_entries))
190 allocate(is_known_y(num_entries))
191 allocate(is_known_lat(num_entries))
192 allocate(is_known_lon(num_entries))
193 allocate(is_truelat1(num_entries))
194 allocate(is_truelat2(num_entries))
195 allocate(is_stdlon(num_entries))
196 allocate(is_fieldname(num_entries))
197 allocate(is_path(num_entries))
198 allocate(is_tile_x(num_entries))
199 allocate(is_tile_y(num_entries))
200 allocate(is_tile_z(num_entries))
201 allocate(is_tile_z_start(num_entries))
202 allocate(is_tile_z_end(num_entries))
203 allocate(is_category_min(num_entries))
204 allocate(is_category_max(num_entries))
205 allocate(is_tile_bdr(num_entries))
206 allocate(is_masked(num_entries))
207 allocate(is_halt_missing(num_entries))
208 allocate(is_output_stagger(num_entries))
209 allocate(is_row_order(num_entries))
210 allocate(is_dominant_category(num_entries))
211 allocate(is_dominant_only(num_entries))
212 allocate(is_dfdx(num_entries))
213 allocate(is_dfdy(num_entries))
214 allocate(is_scale_factor(num_entries))
215 allocate(is_z_dim_name(num_entries))
216 allocate(is_units(num_entries))
217 allocate(is_descr(num_entries))
218 allocate(is_smooth_option(num_entries))
219 allocate(is_smooth_passes(num_entries))
220 allocate(is_signed(num_entries))
221 allocate(is_missing_value(num_entries))
222 allocate(is_fill_missing(num_entries))
223 allocate(is_subgrid(num_entries))
228 source_dest_fieldtype=0
242 source_interp_string=' '
246 source_tile_z_start=0
248 source_category_min=0
249 source_category_max=0
252 source_output_stagger=0
254 source_dominant_category=' '
255 source_dominant_only=' '
258 source_scale_factor=0
259 source_z_dim_name=' '
262 source_smooth_option=0
263 source_smooth_passes=0
264 source_missing_value=0
265 source_fill_missing=0
270 is_dest_fieldtype=.false.
287 is_tile_z_start=.false.
288 is_tile_z_end=.false.
289 is_category_min=.false.
290 is_category_max=.false.
293 is_halt_missing=.false.
294 is_output_stagger=.false.
296 is_dominant_category=.false.
297 is_dominant_only=.false.
300 is_scale_factor=.false.
301 is_z_dim_name=.false.
304 is_smooth_option=.false.
305 is_smooth_passes=.false.
307 is_missing_value=.false.
308 is_fill_missing=.false.
311 write(source_mminlu,'(a4)') 'USGS'
316 source_isoilwater = 14
319 ! Actually read and save the specifications
324 read(funit,'(a)',end=40,err=1001) buffer
327 ! Is this line a comment?
328 if (buffer(1:1) == '#') then
331 ! Are we beginning a new field specification?
332 else if (index(buffer,'=====') /= 0) then !{
333 if (nparams > 0) i = i + 1
335 if (i <= num_entries) then
336 !BUG: Are these initializations needed now that we've added initializations for
337 ! all options after their initial allocation above?
339 is_masked(i) = .false.
340 is_halt_missing(i) = .false.
341 is_output_stagger(i) = .false.
342 is_dominant_category(i) = .false.
343 is_dominant_only(i) = .false.
346 is_dest_fieldtype(i) = .false.
347 is_priority(i) = .false.
348 is_z_dim_name(i) = .false.
349 is_smooth_option(i) = .false.
350 is_smooth_passes(i) = .false.
351 is_fill_missing(i) = .false.
352 is_subgrid(i) = .false.
356 ! Check whether the current line is a comment
357 if (buffer(1:1) /= '#') then
358 have_specification = .true.
360 have_specification = .false.
363 ! If only part of the line is a comment, just turn the comment into spaces
364 eos = index(buffer,'#')
365 if (eos /= 0) buffer(eos:BUFSIZE) = ' '
367 do while (have_specification) !{
369 ! If this line has no semicolon, it may contain a single specification,
370 ! so we set have_specification = .false. to prevent the line from being
371 ! processed again and "pretend" that the last character was a semicolon
372 eos = index(buffer,';')
374 have_specification = .false.
378 idx = index(buffer(1:eos-1),'=')
380 if (idx /= 0) then !{
381 nparams = nparams + 1
383 if (index('name',trim(buffer(1:idx-1))) /= 0) then
385 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
388 is_fieldname(i) = .true.
389 source_fieldname(i) = ' '
390 source_fieldname(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
392 else if (index('priority',trim(buffer(1:idx-1))) /= 0) then
393 is_priority(i) = .true.
394 read(buffer(idx+1:eos-1),'(i10)') source_priority(i)
396 else if (index('dest_type',trim(buffer(1:idx-1))) /= 0) then
397 if (index('continuous',trim(buffer(idx+1:eos-1))) /= 0) then
398 is_dest_fieldtype(i) = .true.
399 source_dest_fieldtype(i) = CONTINUOUS
400 else if (index('categorical',trim(buffer(idx+1:eos-1))) /= 0) then
401 is_dest_fieldtype(i) = .true.
402 source_dest_fieldtype(i) = CATEGORICAL
405 else if (index('interp_option',trim(buffer(1:idx-1))) /= 0) then
407 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
411 interp_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
412 ispace = index(interp_string,':')
413 if (ispace /= 0) then
414 write(res_string,'(a)') interp_string(1:ispace-1)
416 res_string = 'default'
418 write(interp_string,'(a)') trim(interp_string(ispace+1:128))
419 if (list_search(source_interp_option(i), ckey=res_string, cvalue=interp_string)) then
420 call mprintf(.true., WARN, &
421 'In GEOGRID.TBL entry %i, multiple interpolation methods are '// &
422 'given for resolution %s. %s will be used.', &
423 i1=i, s1=trim(res_string), s2=trim(interp_string))
425 call list_insert(source_interp_option(i), ckey=res_string, cvalue=interp_string)
428 else if (index('smooth_option',trim(buffer(1:idx-1))) /= 0) then
429 if ((index('1-2-1',trim(buffer(idx+1:eos-1))) /= 0) .and. &
430 (len_trim(buffer(idx+1:eos-1)) == len('1-2-1'))) then
431 is_smooth_option(i) = .true.
432 source_smooth_option(i) = ONETWOONE
433 else if ((index('smth-desmth',trim(buffer(idx+1:eos-1))) /= 0) .and. &
434 (len_trim(buffer(idx+1:eos-1)) == len('smth-desmth'))) then
435 is_smooth_option(i) = .true.
436 source_smooth_option(i) = SMTHDESMTH
437 else if ((index('smth-desmth_special',trim(buffer(idx+1:eos-1))) /= 0) .and. &
438 (len_trim(buffer(idx+1:eos-1)) == len('smth-desmth_special'))) then
439 is_smooth_option(i) = .true.
440 source_smooth_option(i) = SMTHDESMTH_SPECIAL
443 else if (index('smooth_passes',trim(buffer(1:idx-1))) /= 0) then
444 is_smooth_passes(i) = .true.
445 read(buffer(idx+1:eos-1),'(i10)') source_smooth_passes(i)
447 else if (index('rel_path',trim(buffer(1:idx-1))) /= 0) then
449 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
453 path_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
454 if (path_string(ispace-idx-1:ispace-idx-1) /= '/') &
455 path_string(ispace-idx:ispace-idx) = '/'
456 if (path_string(1:1) == '/') then
457 path_string(1:127) = path_string(2:128)
458 path_string(128:128) = ' '
460 ispace = index(path_string,':')
461 if (ispace /= 0) then
462 write(res_string,'(a)') path_string(1:ispace-1)
464 res_string = 'default'
466 write(path_string,'(a)') trim(geog_data_path)//trim(path_string(ispace+1:128))
467 if (list_search(source_res_path(i), ckey=res_string, cvalue=path_string)) then
468 call mprintf(.true., WARN, &
469 'In GEOGRID.TBL entry %i, multiple paths are given for '// &
470 'resolution %s. %s will be used.', &
471 i1=i, s1=trim(res_string), s2=trim(path_string))
473 call list_insert(source_res_path(i), ckey=res_string, cvalue=path_string)
476 else if (index('abs_path',trim(buffer(1:idx-1))) /= 0) then
478 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
482 path_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
483 if (path_string(ispace-idx-1:ispace-idx-1) /= '/') &
484 path_string(ispace-idx:ispace-idx) = '/'
485 ispace = index(path_string,':')
486 if (ispace /= 0) then
487 write(res_string,'(a)') path_string(1:ispace-1)
489 res_string = 'default'
491 write(path_string,'(a)') trim(path_string(ispace+1:128))
492 if (list_search(source_res_path(i), ckey=res_string, cvalue=path_string)) then
493 call mprintf(.true., WARN, &
494 'In GEOGRID.TBL entry %i, multiple paths are given for '// &
495 'resolution %s. %s will be used.', &
496 i1=i, s1=trim(res_string), s2=trim(path_string))
498 call list_insert(source_res_path(i), ckey=res_string, cvalue=path_string)
501 else if (index('output_stagger',trim(buffer(1:idx-1))) /= 0) then
502 if (index('M',trim(buffer(idx+1:eos-1))) /= 0) then
503 is_output_stagger(i) = .true.
504 source_output_stagger(i) = M
505 else if (index('U',trim(buffer(idx+1:eos-1))) /= 0) then
506 is_output_stagger(i) = .true.
507 source_output_stagger(i) = U
508 else if (index('V',trim(buffer(idx+1:eos-1))) /= 0) then
509 is_output_stagger(i) = .true.
510 source_output_stagger(i) = V
511 else if (index('HH',trim(buffer(idx+1:eos-1))) /= 0) then
512 is_output_stagger(i) = .true.
513 source_output_stagger(i) = HH
514 else if (index('VV',trim(buffer(idx+1:eos-1))) /= 0) then
515 is_output_stagger(i) = .true.
516 source_output_stagger(i) = VV
519 else if ((index('landmask_water',trim(buffer(1:idx-1))) /= 0) .and. &
520 (len_trim(buffer(1:idx-1)) == 14)) then
522 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
525 landmask_string = ' '
526 landmask_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
527 ispace = index(landmask_string,':')
528 if (ispace /= 0) then
529 write(res_string,'(a)') landmask_string(1:ispace-1)
531 res_string = 'default'
533 write(landmask_string,'(a)') trim(landmask_string(ispace+1:128))
534 if (list_search(source_landmask_water(i), ckey=res_string, cvalue=landmask_string)) then
535 call mprintf(.true., WARN, &
536 'In GEOGRID.TBL entry %i, multiple landmask category specifications are given for '// &
537 'resolution %s. %s will be used.', &
538 i1=i, s1=trim(res_string), s2=trim(landmask_string))
540 call list_insert(source_landmask_water(i), ckey=res_string, cvalue=landmask_string)
543 else if ((index('landmask_land',trim(buffer(1:idx-1))) /= 0) .and. &
544 (len_trim(buffer(1:idx-1)) == 13)) then
546 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
549 landmask_string = ' '
550 landmask_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
551 ispace = index(landmask_string,':')
552 if (ispace /= 0) then
553 write(res_string,'(a)') landmask_string(1:ispace-1)
555 res_string = 'default'
557 write(landmask_string,'(a)') trim(landmask_string(ispace+1:128))
558 if (list_search(source_landmask_land(i), ckey=res_string, cvalue=landmask_string)) then
559 call mprintf(.true., WARN, &
560 'In GEOGRID.TBL entry %i, multiple landmask category specifications are given for '// &
561 'resolution %s. %s will be used.', &
562 i1=i, s1=trim(res_string), s2=trim(landmask_string))
564 call list_insert(source_landmask_land(i), ckey=res_string, cvalue=landmask_string)
567 else if ((index('masked',trim(buffer(1:idx-1))) /= 0) .and. &
568 (len_trim(buffer(1:idx-1)) == 6)) then
569 if (index('water',trim(buffer(idx+1:eos-1))) /= 0) then
570 is_masked(i) = .true.
571 source_masked(i) = 0.
572 else if (index('land',trim(buffer(idx+1:eos-1))) /= 0) then
573 is_masked(i) = .true.
574 source_masked(i) = 1.
577 else if (index('fill_missing',trim(buffer(1:idx-1))) /= 0) then
578 is_fill_missing(i) = .true.
579 read(buffer(idx+1:eos-1),*) source_fill_missing(i)
581 else if (index('halt_on_missing',trim(buffer(1:idx-1))) /= 0) then
582 if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
583 is_halt_missing(i) = .true.
584 else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
585 is_halt_missing(i) = .false.
588 else if (index('dominant_category',trim(buffer(1:idx-1))) /= 0) then
590 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
593 is_dominant_category(i) = .true.
594 source_dominant_category(i) = ' '
595 source_dominant_category(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
597 else if (index('dominant_only',trim(buffer(1:idx-1))) /= 0) then
599 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
602 is_dominant_only(i) = .true.
603 source_dominant_only(i) = ' '
604 source_dominant_only(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
606 else if (index('df_dx',trim(buffer(1:idx-1))) /= 0) then
608 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
613 source_dfdx(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
615 else if (index('df_dy',trim(buffer(1:idx-1))) /= 0) then
617 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
622 source_dfdy(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
624 else if (index('z_dim_name',trim(buffer(1:idx-1))) /= 0) then
626 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
629 is_z_dim_name(i) = .true.
630 source_z_dim_name(i) = ' '
631 source_z_dim_name(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
633 else if (index('subgrid',trim(buffer(1:idx-1))) /= 0) then
634 if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
635 is_subgrid(i) = .true.
636 else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
637 is_subgrid(i) = .false.
641 call mprintf(.true., WARN, 'In GEOGRID.TBL, unrecognized option %s in '// &
642 'entry %i.',i1=idx, s1=buffer(i:idx-1))
646 end if !} index(buffer(1:eos-1),'=') /= 0
648 buffer = buffer(eos+1:BUFSIZE)
649 end do ! while eos /= 0 }
651 end if !} index(buffer, '=====') /= 0
656 ! Check the user specifications for gross errors
657 if ( .not. check_data_specification() ) then
658 call datalist_destroy()
659 call mprintf(.true.,ERROR,'Errors were found in either index files or GEOGRID.TBL.')
662 call hash_init(bad_files)
666 1000 call mprintf(.true.,ERROR,'Could not open GEOGRID.TBL')
668 1001 call mprintf(.true.,ERROR,'Encountered error while reading GEOGRID.TBL')
670 end subroutine get_datalist
673 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
674 ! Name: get_source_params
676 ! Purpose: For each field, this routine reads in the metadata in the index file
677 ! for the first available resolution of data specified by res_string. Also
678 ! based on res_string, this routine sets the interpolation sequence for the
679 ! field. This routine should be called prior to processing a field for each
681 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
682 subroutine get_source_params(res_string)
689 integer, parameter :: BUFSIZE = 256
692 character (len=128), intent(in) :: res_string
695 integer :: idx, i, is, ie, ispace, eos, iquoted, funit
696 character (len=128) :: temp_data, temp_interp
697 character (len=256) :: test_fname
698 character (len=BUFSIZE) :: buffer
699 logical :: have_specification, is_used
701 ! For each entry in the GEOGRID.TBL file
704 ! Initialize metadata
705 is_wordsize(idx) = .false.
706 is_endian(idx) = .false.
707 is_row_order(idx) = .false.
708 is_fieldtype(idx) = .false.
709 is_proj(idx) = .false.
712 is_known_x(idx) = .false.
713 is_known_y(idx) = .false.
714 is_known_lat(idx) = .false.
715 is_known_lon(idx) = .false.
716 is_truelat1(idx) = .false.
717 is_truelat2(idx) = .false.
718 is_stdlon(idx) = .false.
719 is_tile_x(idx) = .false.
720 is_tile_y(idx) = .false.
721 is_tile_z(idx) = .false.
722 is_tile_z_start(idx) = .false.
723 is_tile_z_end(idx) = .false.
724 is_category_min(idx) = .false.
725 is_category_max(idx) = .false.
726 is_tile_bdr(idx) = .false.
727 is_fieldname(idx) = .false.
728 is_scale_factor(idx) = .false.
729 is_units(idx) = .false.
730 is_descr(idx) = .false.
731 is_signed(idx) = .false.
732 is_missing_value(idx) = .false.
735 ! Set the interpolator sequence for the field to be the first value in res_string that matches
736 ! the resolution keyword for an interp_sequence specification
738 ie = index(res_string(is:128),'+') - 1
739 if (ie <= 0) ie = 128
740 temp_interp = res_string(is:ie)
741 do while (.not. list_search(source_interp_option(idx), ckey=temp_interp, cvalue=source_interp_string(idx)) &
743 call mprintf(.true., INFORM, 'For %s, couldn''t find interpolator sequence for '// &
745 s1=trim(source_fieldname(idx)), s2=trim(temp_interp))
747 ie = is + index(res_string(is:128),'+') - 2
748 if (ie - is <= 0) ie = 128
749 temp_interp = res_string(is:ie)
753 temp_interp = 'default'
754 if (list_search(source_interp_option(idx), ckey=temp_interp, cvalue=source_interp_string(idx))) then
755 call mprintf(.true., INFORM, 'Using default interpolator sequence for %s.', &
756 s1=trim(source_fieldname(idx)))
758 call mprintf(.true., ERROR, 'Could not find interpolator sequence for requested resolution for %s.'// &
759 ' The sources specified in namelist.wps is not listed in GEOGRID.TBL.', &
760 s1=trim(source_fieldname(idx)))
763 call mprintf(.true., INFORM, 'Using %s interpolator sequence for %s.', &
764 s1=temp_interp, s2=trim(source_fieldname(idx)))
767 ! Set the data source for the field to be the first value in res_string that matches
768 ! the resolution keyword for an abs_path or rel_path specification
770 ie = index(res_string(is:128),'+') - 1
771 if (ie <= 0) ie = 128
772 temp_data = res_string(is:ie)
773 do while (.not. list_search(source_res_path(idx), ckey=temp_data, cvalue=source_path(idx)) &
775 call mprintf(.true., INFORM, 'For %s, couldn''t find %s data source.', &
776 s1=trim(source_fieldname(idx)), s2=trim(temp_data))
778 ie = is + index(res_string(is:128),'+') - 2
779 if (ie - is <= 0) ie = 128
780 temp_data = res_string(is:ie)
784 temp_data = 'default'
785 if (list_search(source_res_path(idx), ckey=temp_data, cvalue=source_path(idx))) then
786 call mprintf(.true., INFORM, 'Using default data source for %s.', &
787 s1=trim(source_fieldname(idx)))
789 call mprintf(.true., ERROR, 'Could not find data resolution for requested resolution for %s. '// &
790 'The source specified in namelist.wps is not listed in GEOGRID.TBL.', &
791 s1=trim(source_fieldname(idx)))
794 call mprintf(.true., INFORM, 'Using %s data source for %s.', &
795 s1=temp_data, s2=trim(source_fieldname(idx)))
798 call mprintf(trim(temp_data) /= trim(temp_interp),WARN,'For %s, using %s data source with %s interpolation sequence.', &
799 s1=source_fieldname(idx), s2=temp_data, s3=temp_interp)
801 write(test_fname, '(a)') trim(source_path(idx))//'index'
804 ! Open the index file for the data source for this field, and read in metadata specs
807 inquire(unit=funit, opened=is_used)
808 if (.not. is_used) exit
810 open(funit,file=trim(test_fname),form='formatted',status='old',err=1000)
813 read(funit,'(a)',end=40, err=1001) buffer
816 ! Is this line a comment?
817 if (buffer(1:1) == '#') then
821 have_specification = .true.
823 ! If only part of the line is a comment, just turn the comment into spaces
824 eos = index(buffer,'#')
825 if (eos /= 0) buffer(eos:BUFSIZE) = ' '
827 do while (have_specification) !{
829 ! If this line has no semicolon, it may contain a single specification,
830 ! so we set have_specification = .false. to prevent the line from being
831 ! processed again and pretend that the last character was a semicolon
832 eos = index(buffer,';')
834 have_specification = .false.
838 i = index(buffer(1:eos-1),'=')
842 if (index('projection',trim(buffer(1:i-1))) /= 0) then
843 if (index('lambert',trim(buffer(i+1:eos-1))) /= 0) then
844 is_proj(idx) = .true.
845 source_proj(idx) = PROJ_LC
846 else if (index('polar_wgs84',trim(buffer(i+1:eos-1))) /= 0 .and. &
847 len_trim('polar_wgs84') == len_trim(buffer(i+1:eos-1))) then
848 is_proj(idx) = .true.
849 source_proj(idx) = PROJ_PS_WGS84
850 else if (index('albers_nad83',trim(buffer(i+1:eos-1))) /= 0 .and. &
851 len_trim('albers_nad83') == len_trim(buffer(i+1:eos-1))) then
852 is_proj(idx) = .true.
853 source_proj(idx) = PROJ_ALBERS_NAD83
854 else if (index('polar',trim(buffer(i+1:eos-1))) /= 0 .and. &
855 len_trim('polar') == len_trim(buffer(i+1:eos-1))) then
856 is_proj(idx) = .true.
857 source_proj(idx) = PROJ_PS
858 else if (index('mercator',trim(buffer(i+1:eos-1))) /= 0) then
859 is_proj(idx) = .true.
860 source_proj(idx) = PROJ_MERC
861 else if (index('regular_ll',trim(buffer(i+1:eos-1))) /= 0) then
862 is_proj(idx) = .true.
863 source_proj(idx) = PROJ_LATLON
866 else if (index('type',trim(buffer(1:i-1))) /= 0) then
867 if (index('continuous',trim(buffer(i+1:eos-1))) /= 0) then
868 is_fieldtype(idx) = .true.
869 source_fieldtype(idx) = CONTINUOUS
870 else if (index('categorical',trim(buffer(i+1:eos-1))) /= 0) then
871 is_fieldtype(idx) = .true.
872 source_fieldtype(idx) = CATEGORICAL
875 else if (index('signed',trim(buffer(1:i-1))) /= 0) then
876 if (index('yes',trim(buffer(i+1:eos-1))) /= 0) then
877 is_signed(idx) = .true.
878 else if (index('no',trim(buffer(i+1:eos-1))) /= 0) then
879 is_signed(idx) = .false.
882 else if (index('units',trim(buffer(1:i-1))) /= 0) then
885 do while (((ispace < eos) .and. (buffer(ispace:ispace) /= ' ')) .or. (iquoted == 1))
886 if (buffer(ispace:ispace) == '"' .or. buffer(ispace:ispace) == '''') iquoted = mod(iquoted+1,2)
889 is_units(idx) = .true.
890 source_units(idx) = ' '
891 if (buffer(i+1:i+1) == '"' .or. buffer(i+1:i+1) == '''') i = i + 1
892 if (buffer(ispace-1:ispace-1) == '"' .or. buffer(ispace-1:ispace-1) == '''') ispace = ispace - 1
893 source_units(idx)(1:ispace-i) = buffer(i+1:ispace-1)
895 else if (index('description',trim(buffer(1:i-1))) /= 0) then
898 do while (((ispace < eos) .and. (buffer(ispace:ispace) /= ' ')) .or. (iquoted == 1))
899 if (buffer(ispace:ispace) == '"' .or. buffer(ispace:ispace) == '''') iquoted = mod(iquoted+1,2)
902 is_descr(idx) = .true.
903 source_descr(idx) = ' '
904 if (buffer(i+1:i+1) == '"' .or. buffer(i+1:i+1) == '''') i = i + 1
905 if (buffer(ispace-1:ispace-1) == '"' .or. buffer(ispace-1:ispace-1) == '''') ispace = ispace - 1
906 source_descr(idx)(1:ispace-i) = buffer(i+1:ispace-1)
908 else if (index('mminlu',trim(buffer(1:i-1))) /= 0) then
911 do while (((ispace < eos) .and. (buffer(ispace:ispace) /= ' ')) .or. (iquoted == 1))
912 if (buffer(ispace:ispace) == '"' .or. buffer(ispace:ispace) == '''') iquoted = mod(iquoted+1,2)
915 if (buffer(i+1:i+1) == '"' .or. buffer(i+1:i+1) == '''') i = i + 1
916 if (buffer(ispace-1:ispace-1) == '"' .or. buffer(ispace-1:ispace-1) == '''') ispace = ispace - 1
917 source_mminlu(1:ispace-i) = buffer(i+1:ispace-1)
919 else if (index('iswater',trim(buffer(1:i-1))) /= 0) then
920 read(buffer(i+1:eos-1),*) source_iswater
922 else if (index('islake',trim(buffer(1:i-1))) /= 0) then
923 read(buffer(i+1:eos-1),*) source_islake
925 else if (index('isice',trim(buffer(1:i-1))) /= 0) then
926 read(buffer(i+1:eos-1),*) source_isice
928 else if (index('isurban',trim(buffer(1:i-1))) /= 0) then
929 read(buffer(i+1:eos-1),*) source_isurban
931 else if (index('isoilwater',trim(buffer(1:i-1))) /= 0) then
932 read(buffer(i+1:eos-1),*) source_isoilwater
934 else if (index('dx',trim(buffer(1:i-1))) /= 0) then
936 read(buffer(i+1:eos-1),*) source_dx(idx)
938 else if (index('dy',trim(buffer(1:i-1))) /= 0) then
940 read(buffer(i+1:eos-1),*) source_dy(idx)
942 else if (index('known_x',trim(buffer(1:i-1))) /= 0) then
943 is_known_x(idx) = .true.
944 read(buffer(i+1:eos-1),*) source_known_x(idx)
946 else if (index('known_y',trim(buffer(1:i-1))) /= 0) then
947 is_known_y(idx) = .true.
948 read(buffer(i+1:eos-1),*) source_known_y(idx)
950 else if (index('known_lat',trim(buffer(1:i-1))) /= 0) then
951 is_known_lat(idx) = .true.
952 read(buffer(i+1:eos-1),*) source_known_lat(idx)
954 else if (index('known_lon',trim(buffer(1:i-1))) /= 0) then
955 is_known_lon(idx) = .true.
956 read(buffer(i+1:eos-1),*) source_known_lon(idx)
958 else if (index('stdlon',trim(buffer(1:i-1))) /= 0) then
959 is_stdlon(idx) = .true.
960 read(buffer(i+1:eos-1),*) source_stdlon(idx)
962 else if (index('truelat1',trim(buffer(1:i-1))) /= 0) then
963 is_truelat1(idx) = .true.
964 read(buffer(i+1:eos-1),*) source_truelat1(idx)
966 else if (index('truelat2',trim(buffer(1:i-1))) /= 0) then
967 is_truelat2(idx) = .true.
968 read(buffer(i+1:eos-1),*) source_truelat2(idx)
970 else if (index('wordsize',trim(buffer(1:i-1))) /= 0) then
971 is_wordsize(idx) = .true.
972 read(buffer(i+1:eos-1),'(i10)') source_wordsize(idx)
974 else if (index('endian',trim(buffer(1:i-1))) /= 0) then
975 if (index('big',trim(buffer(i+1:eos-1))) /= 0) then
976 is_endian(idx) = .true.
977 source_endian(idx) = BIG_ENDIAN
978 else if (index('little',trim(buffer(i+1:eos-1))) /= 0) then
979 is_endian(idx) = .true.
980 source_endian(idx) = LITTLE_ENDIAN
982 call mprintf(.true.,WARN,'Invalid value for keyword ''endian'' '// &
983 'specified in index file. BIG_ENDIAN will be used.')
986 else if (index('row_order',trim(buffer(1:i-1))) /= 0) then
987 if (index('bottom_top',trim(buffer(i+1:eos-1))) /= 0) then
988 is_row_order(idx) = .true.
989 source_row_order(idx) = BOTTOM_TOP
990 else if (index('top_bottom',trim(buffer(i+1:eos-1))) /= 0) then
991 is_row_order(idx) = .true.
992 source_row_order(idx) = TOP_BOTTOM
995 else if (index('tile_x',trim(buffer(1:i-1))) /= 0) then
996 is_tile_x(idx) = .true.
997 read(buffer(i+1:eos-1),'(i10)') source_tile_x(idx)
999 else if (index('tile_y',trim(buffer(1:i-1))) /= 0) then
1000 is_tile_y(idx) = .true.
1001 read(buffer(i+1:eos-1),'(i10)') source_tile_y(idx)
1003 else if (index('tile_z',trim(buffer(1:i-1))) /= 0) then
1004 is_tile_z(idx) = .true.
1005 read(buffer(i+1:eos-1),'(i10)') source_tile_z(idx)
1007 else if (index('tile_z_start',trim(buffer(1:i-1))) /= 0) then
1008 is_tile_z_start(idx) = .true.
1009 read(buffer(i+1:eos-1),'(i10)') source_tile_z_start(idx)
1011 else if (index('tile_z_end',trim(buffer(1:i-1))) /= 0) then
1012 is_tile_z_end(idx) = .true.
1013 read(buffer(i+1:eos-1),'(i10)') source_tile_z_end(idx)
1015 else if (index('category_min',trim(buffer(1:i-1))) /= 0) then
1016 is_category_min(idx) = .true.
1017 read(buffer(i+1:eos-1),'(i10)') source_category_min(idx)
1019 else if (index('category_max',trim(buffer(1:i-1))) /= 0) then
1020 is_category_max(idx) = .true.
1021 read(buffer(i+1:eos-1),'(i10)') source_category_max(idx)
1023 else if (index('tile_bdr',trim(buffer(1:i-1))) /= 0) then
1024 is_tile_bdr(idx) = .true.
1025 read(buffer(i+1:eos-1),'(i10)') source_tile_bdr(idx)
1027 else if (index('missing_value',trim(buffer(1:i-1))) /= 0) then
1028 is_missing_value(idx) = .true.
1029 read(buffer(i+1:eos-1),*) source_missing_value(idx)
1031 else if (index('scale_factor',trim(buffer(1:i-1))) /= 0) then
1032 is_scale_factor(idx) = .true.
1033 read(buffer(i+1:eos-1),*) source_scale_factor(idx)
1036 call mprintf(.true., WARN, 'In %s, unrecognized option %s in entry %i.', &
1037 s1=trim(test_fname), s2=buffer(i:i-1), i1=i)
1041 end if !} index(buffer(1:eos-1),'=') /= 0
1043 buffer = buffer(eos+1:BUFSIZE)
1044 end do ! while eos /= 0 }
1046 end if !} index(buffer, '=====') /= 0
1056 1000 call mprintf(.true.,ERROR,'Could not open %s', s1=trim(test_fname))
1057 1001 call mprintf(.true.,ERROR,'Encountered error while reading %s', s1=trim(test_fname))
1059 end subroutine get_source_params
1062 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1063 ! Name: datalist_destroy()
1065 ! Purpose: This routine deallocates any memory that was allocated by the
1066 ! get_datalist() subroutine.
1067 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1068 subroutine datalist_destroy()
1075 if (associated(source_wordsize)) then
1076 deallocate(source_wordsize)
1077 deallocate(source_endian)
1078 deallocate(source_fieldtype)
1079 deallocate(source_dest_fieldtype)
1080 deallocate(source_proj)
1081 deallocate(source_priority)
1082 deallocate(source_dx)
1083 deallocate(source_dy)
1084 deallocate(source_known_x)
1085 deallocate(source_known_y)
1086 deallocate(source_known_lat)
1087 deallocate(source_known_lon)
1088 deallocate(source_truelat1)
1089 deallocate(source_truelat2)
1090 deallocate(source_stdlon)
1091 deallocate(source_fieldname)
1092 deallocate(source_path)
1093 deallocate(source_interp_string)
1094 deallocate(source_tile_x)
1095 deallocate(source_tile_y)
1096 deallocate(source_tile_z)
1097 deallocate(source_tile_z_start)
1098 deallocate(source_tile_z_end)
1099 deallocate(source_tile_bdr)
1100 deallocate(source_category_min)
1101 deallocate(source_category_max)
1102 deallocate(source_masked)
1103 deallocate(source_output_stagger)
1104 deallocate(source_row_order)
1105 deallocate(source_dominant_category)
1106 deallocate(source_dominant_only)
1107 deallocate(source_dfdx)
1108 deallocate(source_dfdy)
1109 deallocate(source_scale_factor)
1110 deallocate(source_z_dim_name)
1111 deallocate(source_smooth_option)
1112 deallocate(source_smooth_passes)
1113 deallocate(source_units)
1114 deallocate(source_descr)
1115 deallocate(source_missing_value)
1116 deallocate(source_fill_missing)
1118 call list_destroy(source_res_path(i))
1119 call list_destroy(source_interp_option(i))
1120 call list_destroy(source_landmask_land(i))
1121 call list_destroy(source_landmask_water(i))
1123 deallocate(source_res_path)
1124 deallocate(source_interp_option)
1125 deallocate(source_landmask_land)
1126 deallocate(source_landmask_water)
1128 deallocate(is_wordsize)
1129 deallocate(is_endian)
1130 deallocate(is_fieldtype)
1131 deallocate(is_dest_fieldtype)
1133 deallocate(is_priority)
1136 deallocate(is_known_x)
1137 deallocate(is_known_y)
1138 deallocate(is_known_lat)
1139 deallocate(is_known_lon)
1140 deallocate(is_truelat1)
1141 deallocate(is_truelat2)
1142 deallocate(is_stdlon)
1143 deallocate(is_fieldname)
1145 deallocate(is_tile_x)
1146 deallocate(is_tile_y)
1147 deallocate(is_tile_z)
1148 deallocate(is_tile_z_start)
1149 deallocate(is_tile_z_end)
1150 deallocate(is_tile_bdr)
1151 deallocate(is_category_min)
1152 deallocate(is_category_max)
1153 deallocate(is_masked)
1154 deallocate(is_halt_missing)
1155 deallocate(is_output_stagger)
1156 deallocate(is_row_order)
1157 deallocate(is_dominant_category)
1158 deallocate(is_dominant_only)
1161 deallocate(is_scale_factor)
1162 deallocate(is_z_dim_name)
1163 deallocate(is_smooth_option)
1164 deallocate(is_smooth_passes)
1165 deallocate(is_signed)
1166 deallocate(is_units)
1167 deallocate(is_descr)
1168 deallocate(is_missing_value)
1169 deallocate(is_fill_missing)
1172 call hash_destroy(bad_files)
1174 end subroutine datalist_destroy
1177 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1178 ! Name: reset_next_field
1180 ! Purpose: To reset the pointer to the next field in the list of fields
1181 ! specified by the user.
1182 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1183 subroutine reset_next_field()
1189 end subroutine reset_next_field
1192 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1193 ! Name: get_next_fieldname
1195 ! Purpose: Calling this routine results in field_name being set to the name of
1196 ! the field currently pointed to. If istatus /= 0 upon return, an error
1197 ! occurred, and the value of field_name is undefined.
1198 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1199 subroutine get_next_fieldname(field_name, istatus)
1204 integer, intent(out) :: istatus
1205 character (len=128), intent(out) :: field_name
1209 if (next_field <= num_entries) then
1211 field_name = source_fieldname(next_field)
1212 next_field = next_field + 1
1217 end subroutine get_next_fieldname
1220 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1221 ! Name: get_next_output_fieldname
1224 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1225 recursive subroutine get_next_output_fieldname(nest_num, field_name, ndims, &
1227 istagger, memorder, dimnames, units, &
1228 description, sr_x, sr_y, istatus)
1234 #include "wrf_io_flags.h"
1237 integer, intent(in) :: nest_num
1238 integer, intent(out) :: istatus, ndims, istagger, min_cat, max_cat
1239 integer, intent(out) :: sr_x, sr_y
1240 character (len=128), intent(out) :: memorder, field_name, units, description
1241 character (len=128), dimension(3), intent(out) :: dimnames
1244 integer :: temp_fieldtype
1245 integer, dimension(MAX_LANDMASK_CATEGORIES) :: landmask
1246 logical :: is_water_mask, is_dom_only
1247 character (len=128) :: domcat_name, dfdx_name, dfdy_name
1248 character (len=256) :: temphash
1252 if (output_field_state == RETURN_LANDMASK) then
1253 call hash_init(duplicate_fnames)
1254 call get_landmask_field(geog_data_res(nest_num), field_name, is_water_mask, landmask, istatus)
1255 if (istatus == 0) then
1256 temphash(129:256) = ' '
1257 temphash(1:128) = field_name(1:128)
1258 call hash_insert(duplicate_fnames, temphash)
1259 call get_domcategory_name(field_name, domcat_name, is_dom_only, istatus)
1260 ! We will only save the dominant category
1261 if (is_dom_only .and. (istatus == 0)) then
1262 output_field_state = RETURN_DOMCAT_LM
1263 call get_next_output_fieldname(nest_num, field_name, ndims, &
1264 min_cat, max_cat, istagger, &
1265 memorder, dimnames, units, description, &
1266 sr_x, sr_y, istatus)
1272 temp_fieldtype = iget_fieldtype(field_name, istatus)
1273 if (istatus == 0) then
1274 if (temp_fieldtype == CONTINUOUS) then
1275 call get_max_levels(field_name, min_cat, max_cat, istatus)
1276 else if (temp_fieldtype == CATEGORICAL) then
1277 call get_max_categories(field_name, min_cat, max_cat, istatus)
1279 if (max_cat - min_cat > 0) ndims = 3
1281 call get_output_stagger(field_name, istagger, istatus)
1282 if (istagger == M) then
1283 dimnames(1) = 'west_east'
1284 dimnames(2) = 'south_north'
1285 else if (istagger == U) then
1286 dimnames(1) = 'west_east_stag'
1287 dimnames(2) = 'south_north'
1288 else if (istagger == V) then
1289 dimnames(1) = 'west_east'
1290 dimnames(2) = 'south_north_stag'
1291 else if (istagger == HH) then
1292 dimnames(1) = 'west_east'
1293 dimnames(2) = 'south_north'
1294 else if (istagger == VV) then
1295 dimnames(1) = 'west_east'
1296 dimnames(2) = 'south_north'
1298 if (ndims == 2) then
1301 else if (ndims == 3) then
1303 call get_z_dim_name(field_name, dimnames(3), istatus)
1309 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1310 call get_source_units(field_name, 1, units, istatus)
1311 if (istatus /= 0) units = '-'
1312 call get_source_descr(field_name, 1, description, istatus)
1313 if (istatus /= 0) description = '-'
1315 output_field_state = RETURN_DOMCAT_LM
1318 output_field_state = RETURN_FIELDNAME
1319 call get_next_output_fieldname(nest_num, field_name, ndims, &
1320 min_cat, max_cat, istagger, &
1321 memorder, dimnames, units, description, &
1322 sr_x, sr_y, istatus)
1326 else if (output_field_state == RETURN_FIELDNAME) then
1327 call get_next_fieldname(field_name, istatus)
1328 temphash(129:256) = ' '
1329 temphash(1:128) = field_name(1:128)
1330 if (istatus == 0 .and. (.not. hash_search(duplicate_fnames, temphash))) then
1331 call hash_insert(duplicate_fnames, temphash)
1332 call get_domcategory_name(field_name, domcat_name, is_dom_only, istatus)
1333 ! We will only save the dominant category
1334 if (is_dom_only .and. (istatus == 0)) then
1335 output_field_state = RETURN_DOMCAT
1336 call get_next_output_fieldname(nest_num, field_name, ndims, &
1337 min_cat, max_cat, istagger, &
1338 memorder, dimnames, units, description, &
1339 sr_x, sr_y, istatus)
1342 ! Return the fractional field
1347 temp_fieldtype = iget_fieldtype(field_name, istatus)
1348 if (istatus == 0) then
1349 if (temp_fieldtype == CONTINUOUS) then
1350 call get_max_levels(field_name, min_cat, max_cat, istatus)
1351 else if (temp_fieldtype == CATEGORICAL) then
1352 call get_max_categories(field_name, min_cat, max_cat, istatus)
1354 if (max_cat - min_cat > 0) ndims = 3
1356 call get_output_stagger(field_name, istagger, istatus)
1357 if (istagger == M) then
1358 dimnames(1) = 'west_east'
1359 dimnames(2) = 'south_north'
1360 else if (istagger == U) then
1361 dimnames(1) = 'west_east_stag'
1362 dimnames(2) = 'south_north'
1363 else if (istagger == V) then
1364 dimnames(1) = 'west_east'
1365 dimnames(2) = 'south_north_stag'
1366 else if (istagger == HH) then
1367 dimnames(1) = 'west_east'
1368 dimnames(2) = 'south_north'
1369 else if (istagger == VV) then
1370 dimnames(1) = 'west_east'
1371 dimnames(2) = 'south_north'
1373 if (ndims == 2) then
1376 else if (ndims == 3) then
1378 call get_z_dim_name(field_name, dimnames(3), istatus)
1384 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1385 call get_source_units(field_name, 1, units, istatus)
1386 if (istatus /= 0) units = '-'
1387 call get_source_descr(field_name, 1, description, istatus)
1388 if (istatus /= 0) description = '-'
1390 output_field_state = RETURN_DOMCAT
1392 else if (istatus /= 0) then
1393 output_field_state = RETURN_LANDMASK
1394 call hash_destroy(duplicate_fnames)
1396 else if (hash_search(duplicate_fnames, temphash)) then
1397 call get_next_output_fieldname(nest_num, field_name, ndims, &
1398 min_cat, max_cat, istagger, &
1399 memorder, dimnames, units, description, &
1400 sr_x, sr_y, istatus)
1404 else if (output_field_state == RETURN_DOMCAT .or. &
1405 output_field_state == RETURN_DOMCAT_LM ) then
1406 if (output_field_state == RETURN_DOMCAT) then
1407 next_field = next_field - 1
1408 call get_next_fieldname(field_name, istatus)
1410 call get_landmask_field(geog_data_res(nest_num), field_name, is_water_mask, landmask, istatus)
1412 if (istatus == 0) then
1413 call get_domcategory_name(field_name, domcat_name, is_dom_only, istatus)
1414 if (istatus == 0) then
1418 call get_output_stagger(field_name, istagger, istatus)
1419 if (istagger == M) then
1420 dimnames(1) = 'west_east'
1421 dimnames(2) = 'south_north'
1422 else if (istagger == U) then
1423 dimnames(1) = 'west_east_stag'
1424 dimnames(2) = 'south_north'
1425 else if (istagger == V) then
1426 dimnames(1) = 'west_east'
1427 dimnames(2) = 'south_north_stag'
1428 else if (istagger == HH) then
1429 dimnames(1) = 'west_east'
1430 dimnames(2) = 'south_north'
1431 else if (istagger == VV) then
1432 dimnames(1) = 'west_east'
1433 dimnames(2) = 'south_north'
1438 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1439 field_name = domcat_name
1441 description = 'Dominant category'
1442 if (output_field_state == RETURN_DOMCAT) then
1443 output_field_state = RETURN_DFDX
1445 output_field_state = RETURN_DFDX_LM
1448 if (output_field_state == RETURN_DOMCAT) then
1449 output_field_state = RETURN_DFDX
1451 output_field_state = RETURN_DFDX_LM
1453 call get_next_output_fieldname(nest_num, field_name, ndims, &
1454 min_cat, max_cat, istagger, &
1455 memorder, dimnames, units, description, &
1456 sr_x, sr_y, istatus)
1460 call mprintf(.true., ERROR, 'get_next_output_fieldname(): In state DOMCAT, '// &
1461 'but no field name is found.')
1464 else if (output_field_state == RETURN_DFDX .or. &
1465 output_field_state == RETURN_DFDX_LM) then
1466 if (output_field_state == RETURN_DFDX) then
1467 next_field = next_field - 1
1468 call get_next_fieldname(field_name, istatus)
1470 call get_landmask_field(geog_data_res(nest_num), field_name, is_water_mask, landmask, istatus)
1472 if (istatus == 0) then
1473 call get_dfdx_name(field_name, dfdx_name, istatus)
1474 if (istatus == 0) then
1478 temp_fieldtype = iget_fieldtype(field_name, istatus)
1479 if (istatus == 0) then
1480 if (temp_fieldtype == CONTINUOUS) then
1481 call get_max_levels(field_name, min_cat, max_cat, istatus)
1482 else if (temp_fieldtype == CATEGORICAL) then
1483 call get_max_categories(field_name, min_cat, max_cat, istatus)
1485 if (max_cat - min_cat > 0) ndims = 3
1487 call get_output_stagger(field_name, istagger, istatus)
1488 if (istagger == M) then
1489 dimnames(1) = 'west_east'
1490 dimnames(2) = 'south_north'
1491 else if (istagger == U) then
1492 dimnames(1) = 'west_east_stag'
1493 dimnames(2) = 'south_north'
1494 else if (istagger == V) then
1495 dimnames(1) = 'west_east'
1496 dimnames(2) = 'south_north_stag'
1497 else if (istagger == HH) then
1498 dimnames(1) = 'west_east'
1499 dimnames(2) = 'south_north'
1500 else if (istagger == VV) then
1501 dimnames(1) = 'west_east'
1502 dimnames(2) = 'south_north'
1504 if (ndims == 2) then
1507 else if (ndims == 3) then
1509 call get_z_dim_name(field_name, dimnames(3), istatus)
1515 field_name = dfdx_name
1518 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1519 description = 'df/dx'
1520 if (output_field_state == RETURN_DFDX) then
1521 output_field_state = RETURN_DFDY
1523 output_field_state = RETURN_DFDY_LM
1526 if (output_field_state == RETURN_DFDX) then
1527 output_field_state = RETURN_DFDY
1529 output_field_state = RETURN_DFDY_LM
1531 call get_next_output_fieldname(nest_num, field_name, ndims, &
1532 min_cat, max_cat, istagger, &
1533 memorder, dimnames, units, description, &
1534 sr_x, sr_y, istatus)
1538 call mprintf(.true., ERROR, 'get_next_output_fieldname(): In state DFDX, '// &
1539 'but no field name is found.')
1542 else if (output_field_state == RETURN_DFDY .or. &
1543 output_field_state == RETURN_DFDY_LM) then
1544 if (output_field_state == RETURN_DFDY) then
1545 next_field = next_field - 1
1546 call get_next_fieldname(field_name, istatus)
1548 call get_landmask_field(geog_data_res(nest_num), field_name, is_water_mask, landmask, istatus)
1550 if (istatus == 0) then
1551 call get_dfdy_name(field_name, dfdy_name, istatus)
1552 if (istatus == 0) then
1556 temp_fieldtype = iget_fieldtype(field_name, istatus)
1557 if (istatus == 0) then
1558 if (temp_fieldtype == CONTINUOUS) then
1559 call get_max_levels(field_name, min_cat, max_cat, istatus)
1560 else if (temp_fieldtype == CATEGORICAL) then
1561 call get_max_categories(field_name, min_cat, max_cat, istatus)
1563 if (max_cat - min_cat > 0) ndims = 3
1565 call get_output_stagger(field_name, istagger, istatus)
1566 if (istagger == M) then
1567 dimnames(1) = 'west_east'
1568 dimnames(2) = 'south_north'
1569 else if (istagger == U) then
1570 dimnames(1) = 'west_east_stag'
1571 dimnames(2) = 'south_north'
1572 else if (istagger == V) then
1573 dimnames(1) = 'west_east'
1574 dimnames(2) = 'south_north_stag'
1575 else if (istagger == HH) then
1576 dimnames(1) = 'west_east'
1577 dimnames(2) = 'south_north'
1578 else if (istagger == VV) then
1579 dimnames(1) = 'west_east'
1580 dimnames(2) = 'south_north'
1582 if (ndims == 2) then
1585 else if (ndims == 3) then
1587 call get_z_dim_name(field_name, dimnames(3), istatus)
1594 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1595 field_name = dfdy_name
1597 description = 'df/dy'
1598 output_field_state = RETURN_FIELDNAME
1600 output_field_state = RETURN_FIELDNAME
1601 call get_next_output_fieldname(nest_num, field_name, ndims, &
1602 min_cat, max_cat, istagger, &
1603 memorder, dimnames, units, description, &
1604 sr_x, sr_y, istatus)
1608 call mprintf(.true., ERROR, 'get_next_output_fieldname(): In state DFDY, but no '// &
1609 'field name is found.')
1614 end subroutine get_next_output_fieldname
1617 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1618 ! Name: get_landmask_field
1620 ! Purpose: To return the name of the field from which the landmask is to be
1621 ! computed. If no error occurs, is_water_mask is .true. if the landmask
1622 ! value specifies the value of water, and .false. if the landmask value
1623 ! specifies the value of land.
1624 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1625 subroutine get_landmask_field(res_string, landmask_name, is_water_mask, landmask, istatus)
1630 character (len=128), intent(in) :: res_string
1631 integer, dimension(:), intent(out) :: landmask
1632 integer, intent(out) :: istatus
1633 logical, intent(out) :: is_water_mask
1634 character (len=128), intent(out) :: landmask_name
1640 integer :: is, ie, sos, eos, comma
1641 character (len=128) :: temp_res, mask_cat_string
1645 do idx=1,num_entries
1647 if (list_length(source_landmask_land(idx)) > 0) then
1649 ie = index(res_string(is:128),'+') - 1
1650 if (ie <= 0) ie = 128
1651 temp_res = res_string(is:ie)
1652 do while (.not. list_search(source_landmask_land(idx), ckey=temp_res, cvalue=mask_cat_string) &
1655 ie = is + index(res_string(is:128),'+') - 2
1656 if (ie - is <= 0) ie = 128
1657 temp_res = res_string(is:ie)
1661 temp_res = 'default'
1662 if (list_search(source_landmask_land(idx), ckey=temp_res, cvalue=mask_cat_string)) then
1663 is_water_mask = .false.
1664 landmask_name = source_fieldname(idx)
1668 is_water_mask = .false.
1669 landmask_name = source_fieldname(idx)
1675 ! Note: The following cannot be an else-if, since different resolutions of data may
1676 ! specify, alternately, a land or a water mask, and in general we need to search
1679 if (list_length(source_landmask_water(idx)) > 0) then
1681 ie = index(res_string(is:128),'+') - 1
1682 if (ie <= 0) ie = 128
1683 temp_res = res_string(is:ie)
1684 do while (.not. list_search(source_landmask_water(idx), ckey=temp_res, cvalue=mask_cat_string) &
1687 ie = is + index(res_string(is:128),'+') - 2
1688 if (ie - is <= 0) ie = 128
1689 temp_res = res_string(is:ie)
1693 temp_res = 'default'
1694 if (list_search(source_landmask_water(idx), ckey=temp_res, cvalue=mask_cat_string)) then
1695 is_water_mask = .true.
1696 landmask_name = source_fieldname(idx)
1700 is_water_mask = .true.
1701 landmask_name = source_fieldname(idx)
1706 if (istatus == 0) then
1710 comma = index(mask_cat_string(sos+1:eos-1),',')
1711 do while (comma > 0 .and. j < MAX_LANDMASK_CATEGORIES)
1712 read(mask_cat_string(sos+1:sos+comma-1),'(i10)') landmask(j)
1714 comma = index(mask_cat_string(sos+1:eos-1),',')
1717 read(mask_cat_string(sos+1:eos-1),'(i10)') landmask(j)
1719 if (j <= MAX_LANDMASK_CATEGORIES) then ! Terminate list with a flag value
1720 landmask(j) = INVALID
1727 end subroutine get_landmask_field
1730 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1731 ! Name: get_missing_value
1733 ! Pupose: Return the value used in the source data to indicate missing data.
1734 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1735 subroutine get_missing_value(fieldnm, ilevel, rmissing, istatus)
1740 integer, intent(in) :: ilevel
1741 integer, intent(out) :: istatus
1742 real, intent(out) :: rmissing
1743 character (len=128), intent(in) :: fieldnm
1750 do idx=1,num_entries
1751 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1752 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
1753 (source_priority(idx) == ilevel)) then
1755 if (is_missing_value(idx)) then
1756 rmissing = source_missing_value(idx)
1764 end subroutine get_missing_value
1767 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1768 ! Name: get_source_units
1770 ! Pupose: Return a string giving the units of the specified source data.
1771 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1772 subroutine get_source_units(fieldnm, ilevel, cunits, istatus)
1777 integer, intent(in) :: ilevel
1778 integer, intent(out) :: istatus
1779 character (len=128), intent(in) :: fieldnm
1780 character (len=128), intent(out) :: cunits
1787 do idx=1,num_entries
1788 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1789 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
1790 (source_priority(idx) == ilevel)) then
1792 if (is_units(idx)) then
1793 cunits = source_units(idx)
1801 end subroutine get_source_units
1804 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1805 ! Name: get_source_descr
1807 ! Pupose: Return a string giving a description of the specified source data.
1808 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1809 subroutine get_source_descr(fieldnm, ilevel, descr, istatus)
1814 integer, intent(in) :: ilevel
1815 integer, intent(out) :: istatus
1816 character (len=128), intent(in) :: fieldnm
1817 character (len=128), intent(out) :: descr
1824 do idx=1,num_entries
1825 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1826 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
1827 (source_priority(idx) == ilevel)) then
1829 if (is_units(idx)) then
1830 descr = source_descr(idx)
1838 end subroutine get_source_descr
1841 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1842 ! Name: get_missing_fill_value
1844 ! Pupose: Return the value to fill missing points with.
1845 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1846 subroutine get_missing_fill_value(fieldnm, rmissing, istatus)
1851 integer, intent(out) :: istatus
1852 real, intent(out) :: rmissing
1853 character (len=128), intent(in) :: fieldnm
1860 do idx=1,num_entries
1861 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1862 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) ) then
1864 if (is_fill_missing(idx)) then
1865 rmissing = source_fill_missing(idx)
1873 end subroutine get_missing_fill_value
1876 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1877 ! Name: get_halt_on_missing
1879 ! Pupose: Returns 1 if the program should halt upon encountering a missing
1880 ! value in the final output field, and 0 otherwise.
1881 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1882 subroutine get_halt_on_missing(fieldnm, halt, istatus)
1887 integer, intent(out) :: istatus
1888 logical, intent(out) :: halt
1889 character (len=128), intent(in) :: fieldnm
1897 do idx=1,num_entries
1898 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1899 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) ) then
1901 if (is_halt_missing(idx)) halt = .true.
1906 end subroutine get_halt_on_missing
1909 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1910 ! Name: get_masked_value
1912 ! Pupose: If the field is to be masked by the landmask, returns 0 if the field
1913 ! is masked over water and 1 if the field is masked over land. If no mask is
1914 ! to be applied, -1 is returned.
1915 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1916 subroutine get_masked_value(fieldnm, ilevel, masked, istatus)
1921 integer, intent(in) :: ilevel
1922 integer, intent(out) :: istatus
1923 real, intent(out) :: masked
1924 character (len=128), intent(in) :: fieldnm
1932 do idx=1,num_entries
1933 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1934 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
1935 (source_priority(idx) == ilevel)) then
1937 if (is_masked(idx)) then
1938 masked = source_masked(idx)
1945 end subroutine get_masked_value
1948 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1949 ! Name: get_max_levels
1951 ! Purpose: Returns the number of levels for the field given by fieldnm.
1952 ! The number of levels will generally be specified for continuous fields,
1953 ! whereas min/max category will generally be specified for categorical ones.
1954 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1955 subroutine get_max_levels(fieldnm, min_level, max_level, istatus)
1960 integer, intent(out) :: min_level, max_level, istatus
1961 character (len=128), intent(in) :: fieldnm
1965 logical :: have_found_field
1967 have_found_field = .false.
1970 do idx=1,num_entries
1971 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1972 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
1974 if (is_dest_fieldtype(idx) .and. (source_dest_fieldtype(idx) /= CONTINUOUS)) then
1975 call mprintf(.true., WARN, 'In GEOGRID.TBL, destination field type for %s is '// &
1976 'not continuous and min/max levels specified.', s1=trim(fieldnm))
1978 if (.not. have_found_field) then
1979 if (is_tile_z_start(idx) .and. is_tile_z_end(idx)) then
1980 have_found_field = .true.
1982 min_level = source_tile_z_start(idx)
1983 max_level = source_tile_z_end(idx)
1984 else if (is_tile_z(idx)) then
1985 have_found_field = .true.
1988 max_level = source_tile_z(idx)
1991 if (.not. (is_tile_z_start(idx) .and. is_tile_z_end(idx))) then
1992 if (is_tile_z_start(idx) .or. is_tile_z_end(idx)) then
1993 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of tile_z_start '// &
1994 'and tile_z_end specified for entry %i.',i1=idx)
1998 if (is_tile_z_start(idx) .and. is_tile_z_end(idx)) then
1999 if (source_tile_z_start(idx) < min_level) min_level = source_tile_z_start(idx)
2000 if (source_tile_z_end(idx) > max_level) max_level = source_tile_z_end(idx)
2001 else if (is_tile_z(idx)) then
2002 if (min_level > 1) min_level = 1
2003 if (source_tile_z(idx) > max_level) max_level = source_tile_z(idx)
2006 if (.not. (is_tile_z_start(idx) .and. is_tile_z_end(idx))) then
2007 if (is_tile_z_start(idx) .or. is_tile_z_end(idx)) then
2008 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of tile_z_start '// &
2009 'and tile_z_end specified for entry %i.',i1=idx)
2017 end subroutine get_max_levels
2020 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2021 ! Name: get_source_levels
2023 ! Purpose: Return the min and max z-index for the source data for fieldname
2024 ! at a specified priority level (compared with the min/max level over
2025 ! all priority levels, as given by get_max_levels).
2026 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2027 subroutine get_source_levels(fieldnm, ilevel, min_level, max_level, istatus)
2032 integer, intent(in) :: ilevel
2033 integer, intent(out) :: min_level, max_level, istatus
2034 character (len=128), intent(in) :: fieldnm
2041 do idx=1,num_entries
2042 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2043 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2044 if (ilevel == source_priority(idx)) then
2046 if (is_tile_z_start(idx) .and. is_tile_z_end(idx)) then
2048 min_level = source_tile_z_start(idx)
2049 max_level = source_tile_z_end(idx)
2050 else if (is_tile_z(idx)) then
2053 max_level = source_tile_z(idx)
2056 if (.not. (is_tile_z_start(idx) .and. is_tile_z_end(idx))) then
2057 if (is_tile_z_start(idx) .or. is_tile_z_end(idx)) then
2058 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of tile_z_start '// &
2059 'and tile_z_end specified for entry %i.',i1=idx)
2067 end subroutine get_source_levels
2070 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2071 ! Name: get_max_categories
2073 ! Purpose: Returns the minimum category and the maximum category for the field
2075 ! Min/max category will generally be specified for categorical fields,
2076 ! whereas the number of levels will generally be specified for continuous
2078 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2079 subroutine get_max_categories(fieldnm, min_category, max_category, istatus)
2084 integer, intent(out) :: min_category, max_category, istatus
2085 character (len=128), intent(in) :: fieldnm
2089 logical :: have_found_field
2091 have_found_field = .false.
2094 do idx=1,num_entries
2095 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2096 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2098 if (is_dest_fieldtype(idx) .and. (source_dest_fieldtype(idx) /= CATEGORICAL)) then
2099 call mprintf(.true., WARN, &
2100 'In GEOGRID.TBL, cannot get min/max categories for continuous '// &
2101 'field %s at entry %i. Perhaps the user has requested to '// &
2102 'perform a strange operation on the field.', s1=trim(fieldnm), i1=idx)
2104 if (.not. have_found_field) then
2105 if (is_category_min(idx) .and. is_category_max(idx)) then
2106 have_found_field = .true.
2108 min_category = source_category_min(idx)
2109 max_category = source_category_max(idx)
2110 else if (is_category_min(idx) .or. is_category_max(idx)) then
2111 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of min_category and '// &
2112 'max_category specified for entry %i.',i1=idx)
2115 if (is_category_min(idx) .and. is_category_max(idx)) then
2116 if (source_category_min(idx) < min_category) min_category = source_category_min(idx)
2117 if (source_category_max(idx) > max_category) max_category = source_category_max(idx)
2118 else if (is_category_min(idx) .or. is_category_max(idx)) then
2119 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of min_category and '// &
2120 'max_category specified for entry %i.',i1=idx)
2127 end subroutine get_max_categories
2130 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2131 ! Name: get_source_categories
2133 ! Purpose: Return the min and max category for the source data for fieldname
2134 ! at a specified priority level (compared with the min/max category over
2135 ! all priority levels, as given by get_max_categories).
2136 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2137 subroutine get_source_categories(fieldnm, ilevel, min_category, max_category, istatus)
2142 integer, intent(in) :: ilevel
2143 integer, intent(out) :: min_category, max_category, istatus
2144 character (len=128), intent(in) :: fieldnm
2151 do idx=1,num_entries
2152 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2153 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2154 if (ilevel == source_priority(idx)) then
2156 if (is_category_min(idx) .and. is_category_max(idx)) then
2158 min_category = source_category_min(idx)
2159 max_category = source_category_max(idx)
2160 else if (is_category_min(idx) .or. is_category_max(idx)) then
2161 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of min_category '// &
2162 'and max_category specified for entry %i.',i1=idx)
2169 end subroutine get_source_categories
2172 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2173 ! Name: get_domcategory_name
2176 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2177 subroutine get_domcategory_name(fieldnm, domcat_name, ldominant_only, istatus)
2182 integer, intent(out) :: istatus
2183 logical, intent(out) :: ldominant_only
2184 character (len=128), intent(in) :: fieldnm
2185 character (len=128), intent(out) :: domcat_name
2191 ldominant_only = .false.
2193 do idx=1,num_entries
2194 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2195 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2197 if (is_dominant_category(idx)) then
2198 domcat_name = source_dominant_category(idx)
2200 if (is_dominant_only(idx)) then
2201 call mprintf(.true., WARN, 'In GEOGRID.TBL, both dominant_category and '// &
2202 'dominant_only are specified in entry %i. Using specification '// &
2203 'for dominant_category.',i1=idx)
2204 is_dominant_only(idx) = .false.
2208 else if (is_dominant_only(idx)) then
2209 domcat_name = source_dominant_only(idx)
2210 ldominant_only = .true.
2218 end subroutine get_domcategory_name
2221 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2222 ! Name: get_dfdx_name
2225 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2226 subroutine get_dfdx_name(fieldnm, dfdx_name, istatus)
2231 integer, intent(out) :: istatus
2232 character (len=128), intent(in) :: fieldnm
2233 character (len=128), intent(out) :: dfdx_name
2240 do idx=1,num_entries
2241 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2242 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2244 if (is_dfdx(idx)) then
2245 dfdx_name = source_dfdx(idx)
2253 end subroutine get_dfdx_name
2256 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2257 ! Name: get_dfdy_name
2260 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2261 subroutine get_dfdy_name(fieldnm, dfdy_name, istatus)
2266 integer, intent(out) :: istatus
2267 character (len=128), intent(in) :: fieldnm
2268 character (len=128), intent(out) :: dfdy_name
2275 do idx=1,num_entries
2276 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2277 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2279 if (is_dfdy(idx)) then
2280 dfdy_name = source_dfdy(idx)
2288 end subroutine get_dfdy_name
2291 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2292 ! Name: get_z_dim_name
2295 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2296 subroutine get_z_dim_name(fieldnm, z_dim, istatus)
2301 integer, intent(out) :: istatus
2302 character (len=128), intent(in) :: fieldnm
2303 character (len=128), intent(out) :: z_dim
2310 do idx=1,num_entries
2311 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2312 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2313 if (is_z_dim_name(idx)) then
2314 z_dim = source_z_dim_name(idx)
2321 end subroutine get_z_dim_name
2324 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2325 ! Name: get_field_scale_factor
2328 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2329 subroutine get_field_scale_factor(fieldnm, ilevel, scale_factor, istatus)
2334 integer, intent(in) :: ilevel
2335 integer, intent(out) :: istatus
2336 real, intent(out) :: scale_factor
2337 character (len=128), intent(in) :: fieldnm
2344 do idx=1,num_entries
2345 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2346 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
2347 (ilevel == source_priority(idx))) then
2349 if (is_scale_factor(idx)) then
2350 scale_factor = source_scale_factor(idx)
2357 end subroutine get_field_scale_factor
2360 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2361 ! Name: get_output_stagger
2364 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2365 subroutine get_output_stagger(fieldnm, istagger, istatus)
2372 integer, intent(out) :: istatus, istagger
2373 character (len=128), intent(in) :: fieldnm
2379 do idx=1,num_entries
2380 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2381 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2383 if (is_output_stagger(idx)) then
2385 istagger = source_output_stagger(idx)
2388 if (gridtype == 'C') then
2392 else if (gridtype == 'E') then
2402 end subroutine get_output_stagger
2405 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2406 ! Name: get_subgrid_dim_name
2409 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2410 subroutine get_subgrid_dim_name(nest_num, field_name, dimnames, &
2411 sub_x, sub_y, istatus)
2416 integer, intent(in) :: nest_num
2417 integer, intent(out) :: sub_x, sub_y, istatus
2418 character(len=128), intent(in) :: field_name
2419 character(len=128), dimension(2), intent(inout) :: dimnames
2420 integer :: idx, nlen
2426 do idx=1,num_entries
2427 if ((index(source_fieldname(idx),trim(field_name)) /= 0) .and. &
2428 (len_trim(source_fieldname(idx)) == len_trim(field_name))) then
2429 if (is_subgrid(idx)) then
2431 if (is_output_stagger(idx)) then
2432 call mprintf(.true.,ERROR,'Cannot use subgrids on variables with staggered grids')
2434 dimnames(1) = trim(dimnames(1))//"_subgrid"
2435 dimnames(2) = trim(dimnames(2))//"_subgrid"
2436 sub_x = subgrid_ratio_x(nest_num)
2437 sub_y = subgrid_ratio_y(nest_num)
2442 end subroutine get_subgrid_dim_name
2445 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2446 ! Name: get_interp_option
2449 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2450 subroutine get_interp_option(fieldnm, ilevel, interp_opt, istatus)
2455 integer, intent(in) :: ilevel
2456 integer, intent(out) :: istatus
2457 character (len=128), intent(in) :: fieldnm
2458 character (len=128), intent(out) :: interp_opt
2464 do idx=1,num_entries
2465 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2466 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2467 if (ilevel == source_priority(idx)) then
2469 interp_opt = source_interp_string(idx)
2477 end subroutine get_interp_option
2480 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2481 ! Name: get_gcel_threshold
2484 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2485 subroutine get_gcell_threshold(interp_opt, threshold, istatus)
2490 integer, intent(out) :: istatus
2491 real, intent(out) :: threshold
2492 character (len=128), intent(in) :: interp_opt
2495 integer :: i, p1, p2
2500 i = index(interp_opt,'average_gcell')
2502 ! Move the "average_gcell" option to the beginning
2507 ! Check for a threshold
2508 p1 = index(interp_opt(i:128),'(')
2509 p2 = index(interp_opt(i:128),')')
2510 if (p1 /= 0 .and. p2 /= 0) then
2511 read(interp_opt(p1+1:p2-1),*,err=1000) threshold
2513 call mprintf(.true., WARN, 'Problem with specified threshold '// &
2514 'for average_gcell interp option. Setting threshold to 0.0.')
2522 1000 call mprintf(.true., ERROR, 'Threshold option to average_gcell interpolator '// &
2523 'must be a real number, enclosed in parentheses immediately '// &
2524 'after keyword "average_gcell"')
2526 end subroutine get_gcell_threshold
2529 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2530 ! Name: get_smooth_option
2533 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2534 subroutine get_smooth_option(fieldnm, smooth_opt, smooth_passes, istatus)
2539 integer, intent(out) :: istatus, smooth_opt, smooth_passes
2540 character (len=128), intent(in) :: fieldnm
2547 do idx=1,num_entries
2548 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2549 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2551 if (is_smooth_option(idx)) then
2553 smooth_opt = source_smooth_option(idx)
2555 if (is_smooth_passes(idx)) then
2556 smooth_passes = source_smooth_passes(idx)
2567 end subroutine get_smooth_option
2570 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2571 ! Name: iget_fieldtype
2574 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2575 function iget_fieldtype(fieldnm, istatus)
2580 integer, intent(out) :: istatus
2581 character (len=128), intent(in) :: fieldnm
2587 integer :: iget_fieldtype
2591 do idx=1,num_entries
2592 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2593 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2595 if (is_dest_fieldtype(idx)) then
2596 iget_fieldtype = source_dest_fieldtype(idx)
2604 end function iget_fieldtype
2607 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2608 ! Name: iget_source_fieldtype
2610 ! Purpose: Given a resolution, in degrees, and the name of a field, this
2611 ! function returns the type (categorical, continuous, etc.) of the source
2612 ! data that will be used. This may, in general, depend on the field name
2613 ! and the resolution; for example, near 30 second resolution, land use data
2614 ! may come from a categorical field, whereas for lower resolutions, it may
2615 ! come from arrays of land use fractions for each category.
2616 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2617 function iget_source_fieldtype(fieldnm, ilevel, istatus)
2622 integer, intent(in) :: ilevel
2623 integer, intent(out) :: istatus
2624 character (len=128), intent(in) :: fieldnm
2627 integer :: iget_source_fieldtype
2632 ! Find information about the source tiles for the specified fieldname
2634 do idx=1,num_entries
2635 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2636 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2637 if (ilevel == source_priority(idx)) then
2639 iget_source_fieldtype = source_fieldtype(idx)
2645 end function iget_source_fieldtype
2648 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2649 ! Name: get_data_tile
2652 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2653 subroutine get_data_tile(xlat, xlon, ilevel, field_name, &
2654 file_name, array, start_x_dim, end_x_dim, start_y_dim, &
2655 end_y_dim, start_z_dim, end_z_dim, npts_bdr, &
2661 integer, intent(in) :: ilevel
2662 integer, intent(out) :: istatus
2663 integer, intent(out) :: start_x_dim, end_x_dim, &
2664 start_y_dim, end_y_dim, &
2665 start_z_dim, end_z_dim, &
2667 real, intent(in) :: xlat, xlon ! Location that tile should contain
2668 real, pointer, dimension(:,:,:) :: array ! The array to be allocated by this routine
2669 character (len=128), intent(in) :: field_name
2670 character (len=256), intent(out) :: file_name
2674 integer :: local_wordsize, local_endian, sign_convention, irow_order, strlen
2675 integer :: xdim,ydim,zdim
2677 real, allocatable, dimension(:) :: temprow
2679 call get_tile_fname(file_name, xlat, xlon, ilevel, field_name, istatus)
2681 if (index(file_name, 'OUTSIDE') /= 0) then
2684 else if (hash_search(bad_files, file_name)) then
2689 call get_tile_dimensions(xlat, xlon, start_x_dim, end_x_dim, start_y_dim, end_y_dim, &
2690 start_z_dim, end_z_dim, npts_bdr, local_wordsize, local_endian, &
2691 sign_convention, ilevel, field_name, istatus)
2693 xdim = (end_x_dim-start_x_dim+1)
2694 ydim = (end_y_dim-start_y_dim+1)
2695 zdim = (end_z_dim-start_z_dim+1)
2697 if (associated(array)) deallocate(array)
2698 allocate(array(xdim,ydim,zdim))
2700 call get_row_order(field_name, ilevel, irow_order, istatus)
2701 if (istatus /= 0) irow_order = BOTTOM_TOP
2703 call s_len(file_name,strlen)
2707 call read_geogrid(file_name, strlen, array, xdim, ydim, zdim, &
2708 sign_convention, local_endian, scalefac, local_wordsize, istatus)
2710 if (irow_order == TOP_BOTTOM) then
2711 allocate(temprow(xdim))
2714 if (ydim-j+1 <= j) exit
2715 temprow(1:xdim) = array(1:xdim,j,k)
2716 array(1:xdim,j,k) = array(1:xdim,ydim-j+1,k)
2717 array(1:xdim,ydim-j+1,k) = temprow(1:xdim)
2723 if (istatus /= 0) then
2724 start_x_dim = INVALID
2725 start_y_dim = INVALID
2729 call hash_insert(bad_files, file_name)
2732 end subroutine get_data_tile
2735 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2736 ! Name: get_row_order
2737 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2738 subroutine get_row_order(fieldnm, ilevel, irow_order, istatus)
2743 integer, intent(in) :: ilevel
2744 character (len=128), intent(in) :: fieldnm
2745 integer, intent(out) :: irow_order, istatus
2751 do idx=1,num_entries
2752 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2753 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2754 if (ilevel == source_priority(idx)) then
2755 if (is_row_order(idx)) then
2756 irow_order = source_row_order(idx)
2764 end subroutine get_row_order
2767 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2768 ! Name: get_tile_dimensions
2769 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2770 subroutine get_tile_dimensions(xlat, xlon, start_x_dim, end_x_dim, start_y_dim, end_y_dim, &
2771 start_z_dim, end_z_dim, npts_bdr, bytes_per_datum, endianness, &
2772 sign_convention, ilevel, fieldnm, istatus)
2779 integer, intent(in) :: ilevel
2780 integer, intent(out) :: start_x_dim, end_x_dim, &
2781 start_y_dim, end_y_dim, &
2782 start_z_dim, end_z_dim, &
2784 bytes_per_datum, endianness, &
2785 sign_convention, istatus
2786 real, intent(in) :: xlat, xlon
2787 character (len=128), intent(in) :: fieldnm
2790 integer :: idx, current_domain
2794 do idx=1,num_entries
2795 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2796 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2797 if (ilevel == source_priority(idx)) then
2804 if (istatus /= 0) then
2815 current_domain = iget_selected_domain()
2816 call select_domain(SOURCE_PROJ)
2817 call lltoxy(xlat, xlon, rx, ry, M)
2818 call select_domain(current_domain)
2820 start_x_dim = source_tile_x(idx) * nint(real(floor((rx-0.5) / real(source_tile_x(idx))))) + 1
2821 end_x_dim = start_x_dim + source_tile_x(idx) - 1
2823 start_y_dim = source_tile_y(idx) * nint(real(floor((ry-0.5) / real(source_tile_y(idx))))) + 1
2824 end_y_dim = start_y_dim + source_tile_y(idx) - 1
2826 if (is_tile_z_start(idx) .and. is_tile_z_end(idx)) then
2827 start_z_dim = source_tile_z_start(idx)
2828 end_z_dim = source_tile_z_end(idx)
2829 else if (is_tile_z(idx)) then
2831 end_z_dim = source_tile_z(idx)
2834 if (.not. (is_tile_z_start(idx) .and. is_tile_z_end(idx))) then
2835 if (is_tile_z_start(idx) .or. is_tile_z_end(idx)) then
2836 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of tile_z_start and '// &
2837 'tile_z_end specified for entry %i.',i1=idx)
2841 if (is_tile_bdr(idx)) then
2842 npts_bdr = source_tile_bdr(idx)
2847 start_x_dim = start_x_dim - npts_bdr
2848 end_x_dim = end_x_dim + npts_bdr
2849 start_y_dim = start_y_dim - npts_bdr
2850 end_y_dim = end_y_dim + npts_bdr
2852 if (is_wordsize(idx)) then
2853 bytes_per_datum = source_wordsize(idx)
2856 call mprintf(.true.,ERROR,'In GEOGRID.TBL, no wordsize specified for data in entry %i.',i1=idx)
2859 if (is_endian(idx)) then
2860 endianness = source_endian(idx)
2862 endianness = BIG_ENDIAN
2865 if (is_signed(idx)) then
2871 end subroutine get_tile_dimensions
2874 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2875 ! Name: get_tile_fname
2878 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2879 subroutine get_tile_fname(test_fname, xlat, xlon, ilevel, fieldname, istatus)
2887 integer, intent(in) :: ilevel
2888 integer, intent(out) :: istatus
2889 real, intent(in) :: xlat, xlon
2890 character (len=*), intent(in) :: fieldname
2891 character (len=256), intent(out) :: test_fname
2894 integer :: current_domain, idx
2898 write(test_fname, '(a)') 'TILE.OUTSIDE.DOMAIN'
2900 do idx=1,num_entries
2901 if ((index(source_fieldname(idx),trim(fieldname)) /= 0) .and. &
2902 (len_trim(source_fieldname(idx)) == len_trim(fieldname))) then
2903 if (ilevel == source_priority(idx)) then
2910 if (istatus /= 0) return
2912 current_domain = iget_selected_domain()
2913 call select_domain(SOURCE_PROJ)
2914 call lltoxy(xlat, xlon, rx, ry, M)
2915 call select_domain(current_domain)
2917 ! rx = real(source_tile_x(idx)) * real(floor((rx-0.5*source_dx(idx))/ real(source_tile_x(idx)))) + 1.0
2918 ! ry = real(source_tile_y(idx)) * real(floor((ry-0.5*source_dy(idx))/ real(source_tile_y(idx)))) + 1.0
2919 rx = real(source_tile_x(idx)) * real(floor((rx-0.5) / real(source_tile_x(idx)))) + 1.0
2920 ry = real(source_tile_y(idx)) * real(floor((ry-0.5) / real(source_tile_y(idx)))) + 1.0
2922 if (rx > 0. .and. ry > 0.) then
2923 write(test_fname, '(a,i5.5,a1,i5.5,a1,i5.5,a1,i5.5)') trim(source_path(idx)), &
2924 nint(rx),'-',nint(rx)+source_tile_x(idx)-1,'.',nint(ry),'-',nint(ry)+source_tile_y(idx)-1
2927 end subroutine get_tile_fname
2930 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2931 ! Name: get_source_resolution
2934 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2935 subroutine get_source_resolution(fieldnm, ilevel, src_dx, src_dy, istatus)
2940 integer, intent(in) :: ilevel
2941 integer, intent(out) :: istatus
2942 real, intent(out) :: src_dx, src_dy
2943 character (len=*), intent(in) :: fieldnm
2949 do idx=1,num_entries
2950 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2951 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2952 if (ilevel == source_priority(idx)) then
2953 if (is_dx(idx) .and. is_dy(idx)) then
2954 src_dx = source_dx(idx)
2955 src_dy = source_dy(idx)
2956 if (source_proj(idx) /= PROJ_LATLON) then
2957 src_dx = src_dx / 111000.
2958 src_dy = src_dy / 111000.
2967 end subroutine get_source_resolution
2970 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2971 ! Name: get_data_projection
2973 ! Purpose: To acquire the parameters necessary in defining the grid on which
2974 ! the user-specified data for field 'fieldnm' are given.
2976 ! NOTES: If the routine successfully acquires values for all necessary
2977 ! parameters, istatus is set to 0. In case of an error,
2978 ! OR IF THE USER HAS NOT SPECIFIED A TILE OF DATA FOR FIELDNM,
2979 ! istatus is set to 1.
2980 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2981 subroutine get_data_projection(fieldnm, iproj, stand_lon, truelat1, truelat2, &
2982 dxkm, dykm, known_x, known_y, known_lat, known_lon, ilevel, istatus)
2987 integer, intent(in) :: ilevel
2988 integer, intent(out) :: iproj, istatus
2989 real, intent(out) :: stand_lon, truelat1, truelat2, dxkm, dykm, &
2990 known_x, known_y, known_lat, known_lon
2991 character (len=*), intent(in) :: fieldnm
2997 do idx=1,num_entries
2998 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2999 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
3000 if (ilevel == source_priority(idx)) then
3002 if (is_proj(idx)) then
3003 iproj = source_proj(idx)
3006 call mprintf(.true., ERROR, &
3007 'In GEOGRID.TBL, no specification for projection in entry %i.',i1=idx)
3009 if (is_known_x(idx)) then
3010 known_x = source_known_x(idx)
3013 call mprintf(.true., ERROR, &
3014 'In GEOGRID.TBL, no specification for known_x in entry %i.',i1=idx)
3016 if (is_known_y(idx)) then
3017 known_y = source_known_y(idx)
3020 call mprintf(.true., ERROR, &
3021 'In GEOGRID.TBL, no specification for known_y in entry %i.',i1=idx)
3023 if (is_known_lat(idx)) then
3024 known_lat = source_known_lat(idx)
3027 call mprintf(.true., ERROR, &
3028 'In GEOGRID.TBL, no specification for known_lat in entry %i.',i1=idx)
3030 if (is_known_lon(idx)) then
3031 known_lon = source_known_lon(idx)
3034 call mprintf(.true., ERROR, &
3035 'In GEOGRID.TBL, no specification for known_lon in entry %i.',i1=idx)
3037 if (is_truelat1(idx)) then
3038 truelat1 = source_truelat1(idx)
3039 else if (is_proj(idx) .and. source_proj(idx) /= PROJ_LATLON) then
3041 call mprintf(.true., WARN, &
3042 'In GEOGRID.TBL, no specification for truelat1 in entry %i.',i1=idx)
3044 if (is_truelat2(idx)) then
3045 truelat2 = source_truelat2(idx)
3046 else if (is_proj(idx) .and. source_proj(idx) /= PROJ_LATLON) then
3048 call mprintf(.true., WARN, &
3049 'In GEOGRID.TBL, no specification for truelat2 in entry %i.',i1=idx)
3051 if (is_stdlon(idx)) then
3052 stand_lon = source_stdlon(idx)
3053 else if (is_proj(idx) .and. source_proj(idx) /= PROJ_LATLON) then
3055 call mprintf(.true., WARN, &
3056 'In GEOGRID.TBL, no specification for stdlon in entry %i.',i1=idx)
3058 if (is_dx(idx)) then
3059 dxkm = source_dx(idx)
3062 call mprintf(.true., ERROR, &
3063 'In GEOGRID.TBL, no specification for dx in entry %i.',i1=idx)
3065 if (is_dy(idx)) then
3066 dykm = source_dy(idx)
3069 call mprintf(.true., ERROR, &
3070 'In GEOGRID.TBL, no specification for dy in entry %i.',i1=idx)
3077 end subroutine get_data_projection
3080 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3081 ! Name: check_data_specification
3083 ! Purpose: To check for obvious errors in the user source data specifications.
3084 ! Returns .true. if specification passes all checks, and .false. otherwise.
3085 ! For failing checks, diagnostic messages are printed.
3086 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3087 function check_data_specification( )
3092 logical :: check_data_specification
3095 integer :: i, j, istatus
3096 integer, pointer, dimension(:) :: priorities
3098 logical :: begin_priority, halt
3099 character (len=128) :: cur_name
3101 check_data_specification = .false.
3103 ! Check that each specification has a name, priority level, and path
3105 if (.not. is_fieldname(i)) then
3106 call mprintf(.true., ERROR, &
3107 'In GEOGRID.TBL, specification %i does not have a name.',i1=i)
3109 if (.not. is_priority(i)) then
3110 call mprintf(.true., ERROR, &
3111 'In GEOGRID.TBL, specification %i does not have a priority.',i1=i)
3113 if (list_length(source_res_path(i)) == 0) then
3114 call mprintf(.true., ERROR, &
3115 'In GEOGRID.TBL, no path (relative or absolute) is specified '// &
3116 'for entry %i.',i1=i)
3120 ! The fill_missing and halt_on_missing options are mutually exclusive
3122 call get_halt_on_missing(source_fieldname(i), halt, istatus)
3123 call get_missing_fill_value(source_fieldname(i), rmissing, istatus)
3124 if (halt .and. (istatus == 0)) then
3125 call mprintf(.true., ERROR, 'In GEOGRID.TBL, the halt_on_missing and fill_missing '// &
3126 'options are mutually exclusive, but both are given for field %s', &
3127 s1=trim(source_fieldname(i)))
3131 ! Check that the field from which landmask is calculated is not output on a staggering
3133 if (list_length(source_landmask_land(i)) > 0 .or. list_length(source_landmask_water(i)) > 0) then
3134 if (is_output_stagger(i)) then
3135 if (source_output_stagger(i) /= M) then
3136 call mprintf(.true., ERROR, 'In GEOGRID.TBL, landmask cannot be derived from '// &
3137 'a field that is computed on a staggered grid at entry %i.',i1=i)
3143 ! Also check that any field that is to be masked by the landmask is not output on a staggering
3145 if (is_masked(i) .and. is_output_stagger(i)) then
3146 if (source_output_stagger(i) /= M) then
3147 call mprintf(.true., ERROR, 'In GEOGRID.TBL, landmask cannot be used with '// &
3148 'a field that is computed on a staggered grid at entry %i.',i1=i)
3153 allocate(priorities(num_entries))
3155 ! Now check that priorities for each source are unique and in the interval [1,n], n <= num_entries
3158 cur_name = source_fieldname(i)
3160 if (source_fieldname(j) == cur_name) then
3162 if (source_priority(j) > num_entries .or. source_priority(j) < 1) then
3163 call mprintf(.true., ERROR, 'In GEOGRID.TBL, priorities for %s do not '// &
3164 'form a sequence 1,2,...,n.', s1=trim(cur_name))
3167 if (priorities(source_priority(j)) == 1) then
3168 call mprintf(.true., ERROR, 'In GEOGRID.TBL, more than one entry for %s '// &
3169 'has priority %i.', s1=trim(cur_name), i1=source_priority(j))
3172 priorities(source_priority(j)) = 1
3179 begin_priority = .false.
3180 do j=num_entries,1,-1
3181 if (.not.begin_priority .and. priorities(j) == 1) then
3182 begin_priority = .true.
3183 else if (begin_priority .and. priorities(j) == 0) then
3184 call mprintf(.true., ERROR, 'In GEOGRID.TBL, no entry for %s has '// &
3185 'priority %i, but an entry has priority %i.', &
3186 s1=trim(cur_name), i1=j, i2=j+1)
3191 deallocate(priorities)
3193 ! Units must match for all priority levels of a field
3195 if (source_priority(i) == 1) then
3197 if ((source_fieldname(i) == source_fieldname(j)) .and. &
3198 (source_units(i) /= source_units(j))) then
3199 call mprintf(.true., ERROR, 'In GEOGRID.TBL, units for %s at entry %i '// &
3200 'do not match units at entry %i (%s)', &
3201 s1=trim(source_fieldname(i)), i1=j, i2=i, s2=trim(source_units(i)))
3207 ! Make sure that user has not asked to calculate landmask from a continuous field
3209 if (is_dest_fieldtype(i)) then
3210 if (source_dest_fieldtype(i) == CONTINUOUS) then
3211 if (list_length(source_landmask_water(i)) > 0 .or. list_length(source_landmask_land(i)) > 0) then
3212 call mprintf(.true., ERROR, 'In GEOGRID.TBL, landmask cannot be '// &
3213 'calculated from a continuous destination field at entry %i.',i1=i)
3219 ! If either min_category or max_category is specified, then both must be specified
3221 if (is_category_min(i) .or. is_category_max(i)) then
3222 if (.not. is_category_min(i)) then
3223 call mprintf(.true., ERROR, 'In GEOGRID.TBL, for index file of data at '// &
3224 'entry %i, category_max is specified, but category_min is '// &
3225 'not. Both must be specified.',i1=i)
3226 else if (.not. is_category_max(i)) then
3227 call mprintf(.true., ERROR, 'In GEOGRID.TBL, for index file of data at '// &
3228 'entry %i, category_min is specified, but category_max is '// &
3229 'not. Both must be specified.',i1=i)
3234 ! For continuous data, (category_max - category_min + 1) should equal tile_z
3236 if (is_fieldtype(i)) then
3237 if (source_fieldtype(i) == CONTINUOUS) then
3238 if (is_category_max(i) .and. is_category_min(i) .and. is_tile_z(i)) then
3239 if (source_tile_z(i) /= (source_category_max(i) - source_category_min(i) + 1)) then
3240 call mprintf(.true., ERROR, 'In GEOGRID.TBL, tile_z must equal '// &
3241 '(category_max - category_min + 1) at entry %i.',i1=i)
3243 else if (is_category_max(i) .and. is_category_min(i) .and. &
3244 is_tile_z_start(i) .and. is_tile_z_end(i)) then
3245 if (source_tile_z_end(i) /= source_category_max(i) .or. &
3246 source_tile_z_start(i) /= source_category_min(i)) then
3247 call mprintf(.true., ERROR, 'In GEOGRID.TBL, tile_z_end must equal '// &
3248 'category_max, and tile_z_start must equal category_min '// &
3249 'at entry %i.',i1=i)
3256 ! Make sure that user has not named a dominant category or computed slope field
3257 ! the same as a fractional field
3259 if (source_dominant_category(i) == source_fieldname(i)) then
3260 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant category cannot have '// &
3261 'the same name as the field at entry %i.',i1=i)
3265 if (.not. is_dominant_only(i)) then
3266 if (is_dfdx(j)) then
3267 if (source_dfdx(j) == source_fieldname(i)) then
3268 call mprintf(.true., ERROR, 'In GEOGRID.TBL, field name at entry %i '// &
3269 'cannot have the same name as the slope field df_dx at entry %i.', &
3273 if (is_dfdy(j)) then
3274 if (source_dfdy(j) == source_fieldname(i)) then
3275 call mprintf(.true., ERROR, 'In GEOGRID.TBL, field name at entry %i '// &
3276 'cannot have the same name as the slope field df_dy at entry %i.', &
3280 if (is_dfdx(j) .and. is_dominant_category(i)) then
3281 if (source_dfdx(j) == source_dominant_category(i)) then
3282 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant field name at '// &
3283 'entry %i cannot have the same name as the slope field df_dx '// &
3284 'at entry %i.',i1=i, i2=j)
3287 if (is_dfdy(j) .and. is_dominant_category(i)) then
3288 if (source_dfdy(j) == source_dominant_category(i)) then
3289 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant field name at '// &
3290 'entry %i cannot have the same name as the slope field '// &
3291 'df_dy at entry %i.',i1=i, i2=j)
3295 if (is_dfdx(j)) then
3296 if (source_dfdx(j) == source_dominant_only(i)) then
3297 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant field name at '// &
3298 'entry %i cannot have the same name as the slope field '// &
3299 'df_dx at entry %i.',i1=i, i2=j)
3302 if (is_dfdy(j)) then
3303 if (source_dfdy(j) == source_dominant_only(i)) then
3304 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant field name at '// &
3305 'entry %i cannot have the same name as the slope field '// &
3306 'df_dy at entry %i.',i1=i, i2=j)
3311 if (is_dfdx(i)) then
3312 if (is_dfdx(j)) then
3313 if (source_dfdx(j) == source_dfdx(i)) then
3314 call mprintf(.true., ERROR, 'In GEOGRID.TBL, slope field df_dx at '// &
3315 'entry %i cannot have the same name as the slope '// &
3316 'field df_dx at entry %i.',i1=i, i2=j)
3319 if (is_dfdy(j)) then
3320 if (source_dfdy(j) == source_dfdx(i)) then
3321 call mprintf(.true., ERROR, 'In GEOGRID.TBL, slope field df_dx at '// &
3322 'entry %i cannot have the same name as the slope field '// &
3323 'df_dy at entry %i.',i1=i, i2=j)
3327 if (is_dfdy(i)) then
3328 if (is_dfdx(j)) then
3329 if (source_dfdx(j) == source_dfdy(i)) then
3330 call mprintf(.true., ERROR, 'In GEOGRID.TBL, slope field df_dy at '// &
3331 'entry %i cannot have the same name as the slope field '// &
3332 'df_dx at entry %i.',i1=i, i2=j)
3335 if (is_dfdy(j)) then
3336 if (source_dfdy(j) == source_dfdy(i)) then
3337 call mprintf(.true., ERROR, 'In GEOGRID.TBL, slope field df_dy at '// &
3338 'entry %i cannot have the same name as the slope field '// &
3339 'df_dy at entry %i.',i1=i, i2=j)
3343 if (is_dominant_category(i)) then
3344 if (source_dominant_category(i) == source_fieldname(j)) then ! Possible exception
3345 if (.not. (is_dominant_only(j) .and. (source_dominant_category(i) /= source_dominant_only(j)))) then
3346 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant category at '// &
3347 'entry %i cannot have the same name as the field at '// &
3348 'entry %i.',i1=i, i2=j)
3350 else if (is_dominant_category(j) .and. &
3351 (source_dominant_category(i) == source_dominant_category(j))) then
3352 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant category at entry '// &
3353 '%i cannot have the same name as dominant category at '// &
3354 'entry %i.',i1=i, i2=j)
3355 else if (is_dominant_only(j) .and. &
3356 (source_dominant_category(i) == source_dominant_only(j))) then
3357 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant category at '// &
3358 'entry %i cannot have the same name as dominant_only '// &
3359 'category at entry %i.',i1=i, i2=j)
3361 else if (is_dominant_only(i)) then
3362 if (source_dominant_only(i) == source_fieldname(j)) then ! Possible exception
3363 if (.not. (is_dominant_only(j) .and. (source_dominant_only(i) /= source_dominant_only(j)))) then
3364 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant_only category '// &
3365 'at entry %i cannot have the same name as the field at '// &
3366 'entry %i.',i1=i, i2=j)
3368 else if (is_dominant_category(j) .and. &
3369 (source_dominant_only(i) == source_dominant_category(j))) then
3370 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant_only category '// &
3371 'at entry %i cannot have the same name as dominant '// &
3372 'category at entry %i.',i1=i, i2=j)
3373 else if (is_dominant_only(j) .and. &
3374 (source_dominant_only(i) == source_dominant_only(j))) then
3375 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant_only category '// &
3376 'at entry %i cannot have the same name as dominant_only '// &
3377 'category at entry %i.',i1=i, i2=j)
3384 check_data_specification = .true.
3385 end function check_data_specification
3388 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3391 ! Purpose: This routine receives a fortran string, and returns the number of
3392 ! characters in the string before the first "space" is encountered. It
3393 ! considers ascii characters 33 to 126 to be valid characters, and ascii
3394 ! 0 to 32, and 127 to be "space" characters.
3395 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3396 subroutine s_len(string, s_length)
3401 character (len=*), intent(in) :: string
3402 integer, intent(out) :: s_length
3405 integer :: i, len_str, aval
3410 len_str = len(string)
3412 do while ((i .le. len_str) .and. (.not. space))
3413 aval = ichar(string(i:i))
3414 if ((aval .lt. 33) .or. (aval .gt. 126)) then
3421 end subroutine s_len
3423 end module source_data_module