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, source_output_flag
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, is_output_flag
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))
174 allocate(source_output_flag(num_entries))
176 call list_init(source_res_path(i))
177 call list_init(source_interp_option(i))
178 call list_init(source_landmask_land(i))
179 call list_init(source_landmask_water(i))
182 allocate(is_wordsize(num_entries))
183 allocate(is_endian(num_entries))
184 allocate(is_fieldtype(num_entries))
185 allocate(is_dest_fieldtype(num_entries))
186 allocate(is_proj(num_entries))
187 allocate(is_priority(num_entries))
188 allocate(is_dx(num_entries))
189 allocate(is_dy(num_entries))
190 allocate(is_known_x(num_entries))
191 allocate(is_known_y(num_entries))
192 allocate(is_known_lat(num_entries))
193 allocate(is_known_lon(num_entries))
194 allocate(is_truelat1(num_entries))
195 allocate(is_truelat2(num_entries))
196 allocate(is_stdlon(num_entries))
197 allocate(is_fieldname(num_entries))
198 allocate(is_path(num_entries))
199 allocate(is_tile_x(num_entries))
200 allocate(is_tile_y(num_entries))
201 allocate(is_tile_z(num_entries))
202 allocate(is_tile_z_start(num_entries))
203 allocate(is_tile_z_end(num_entries))
204 allocate(is_category_min(num_entries))
205 allocate(is_category_max(num_entries))
206 allocate(is_tile_bdr(num_entries))
207 allocate(is_masked(num_entries))
208 allocate(is_halt_missing(num_entries))
209 allocate(is_output_stagger(num_entries))
210 allocate(is_row_order(num_entries))
211 allocate(is_dominant_category(num_entries))
212 allocate(is_dominant_only(num_entries))
213 allocate(is_dfdx(num_entries))
214 allocate(is_dfdy(num_entries))
215 allocate(is_scale_factor(num_entries))
216 allocate(is_z_dim_name(num_entries))
217 allocate(is_units(num_entries))
218 allocate(is_descr(num_entries))
219 allocate(is_smooth_option(num_entries))
220 allocate(is_smooth_passes(num_entries))
221 allocate(is_signed(num_entries))
222 allocate(is_missing_value(num_entries))
223 allocate(is_fill_missing(num_entries))
224 allocate(is_subgrid(num_entries))
225 allocate(is_output_flag(num_entries))
230 source_dest_fieldtype=0
244 source_interp_string=' '
248 source_tile_z_start=0
250 source_category_min=0
251 source_category_max=0
254 source_output_stagger=0
256 source_dominant_category=' '
257 source_dominant_only=' '
260 source_scale_factor=0
261 source_z_dim_name=' '
264 source_smooth_option=0
265 source_smooth_passes=0
266 source_missing_value=0
267 source_fill_missing=0
268 source_output_flag=' '
273 is_dest_fieldtype=.false.
290 is_tile_z_start=.false.
291 is_tile_z_end=.false.
292 is_category_min=.false.
293 is_category_max=.false.
296 is_halt_missing=.false.
297 is_output_stagger=.false.
299 is_dominant_category=.false.
300 is_dominant_only=.false.
303 is_scale_factor=.false.
304 is_z_dim_name=.false.
307 is_smooth_option=.false.
308 is_smooth_passes=.false.
310 is_missing_value=.false.
311 is_fill_missing=.false.
313 is_output_flag=.false.
315 write(source_mminlu,'(a4)') 'USGS'
320 source_isoilwater = 14
323 ! Actually read and save the specifications
328 read(funit,'(a)',end=40,err=1001) buffer
331 ! Is this line a comment?
332 if (buffer(1:1) == '#') then
335 ! Are we beginning a new field specification?
336 else if (index(buffer,'=====') /= 0) then !{
337 if (nparams > 0) i = i + 1
339 if (i <= num_entries) then
340 !BUG: Are these initializations needed now that we've added initializations for
341 ! all options after their initial allocation above?
343 is_masked(i) = .false.
344 is_halt_missing(i) = .false.
345 is_output_stagger(i) = .false.
346 is_dominant_category(i) = .false.
347 is_dominant_only(i) = .false.
350 is_dest_fieldtype(i) = .false.
351 is_priority(i) = .false.
352 is_z_dim_name(i) = .false.
353 is_smooth_option(i) = .false.
354 is_smooth_passes(i) = .false.
355 is_fill_missing(i) = .false.
356 is_subgrid(i) = .false.
357 is_output_flag(i) = .false.
361 ! Check whether the current line is a comment
362 if (buffer(1:1) /= '#') then
363 have_specification = .true.
365 have_specification = .false.
368 ! If only part of the line is a comment, just turn the comment into spaces
369 eos = index(buffer,'#')
370 if (eos /= 0) buffer(eos:BUFSIZE) = ' '
372 do while (have_specification) !{
374 ! If this line has no semicolon, it may contain a single specification,
375 ! so we set have_specification = .false. to prevent the line from being
376 ! processed again and "pretend" that the last character was a semicolon
377 eos = index(buffer,';')
379 have_specification = .false.
383 idx = index(buffer(1:eos-1),'=')
385 if (idx /= 0) then !{
386 nparams = nparams + 1
388 if (index('name',trim(buffer(1:idx-1))) /= 0) then
390 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
393 is_fieldname(i) = .true.
394 source_fieldname(i) = ' '
395 source_fieldname(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
397 else if (index('priority',trim(buffer(1:idx-1))) /= 0) then
398 is_priority(i) = .true.
399 read(buffer(idx+1:eos-1),'(i10)') source_priority(i)
401 else if (index('dest_type',trim(buffer(1:idx-1))) /= 0) then
402 if (index('continuous',trim(buffer(idx+1:eos-1))) /= 0) then
403 is_dest_fieldtype(i) = .true.
404 source_dest_fieldtype(i) = CONTINUOUS
405 else if (index('categorical',trim(buffer(idx+1:eos-1))) /= 0) then
406 is_dest_fieldtype(i) = .true.
407 source_dest_fieldtype(i) = CATEGORICAL
410 else if (index('interp_option',trim(buffer(1:idx-1))) /= 0) then
412 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
416 interp_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
417 ispace = index(interp_string,':')
418 if (ispace /= 0) then
419 write(res_string,'(a)') interp_string(1:ispace-1)
421 res_string = 'default'
423 write(interp_string,'(a)') trim(interp_string(ispace+1:128))
424 if (list_search(source_interp_option(i), ckey=res_string, cvalue=interp_string)) then
425 call mprintf(.true., WARN, &
426 'In GEOGRID.TBL entry %i, multiple interpolation methods are '// &
427 'given for resolution %s. %s will be used.', &
428 i1=i, s1=trim(res_string), s2=trim(interp_string))
430 call list_insert(source_interp_option(i), ckey=res_string, cvalue=interp_string)
433 else if (index('smooth_option',trim(buffer(1:idx-1))) /= 0) then
434 if ((index('1-2-1',trim(buffer(idx+1:eos-1))) /= 0) .and. &
435 (len_trim(buffer(idx+1:eos-1)) == len('1-2-1'))) then
436 is_smooth_option(i) = .true.
437 source_smooth_option(i) = ONETWOONE
438 else if ((index('smth-desmth',trim(buffer(idx+1:eos-1))) /= 0) .and. &
439 (len_trim(buffer(idx+1:eos-1)) == len('smth-desmth'))) then
440 is_smooth_option(i) = .true.
441 source_smooth_option(i) = SMTHDESMTH
442 else if ((index('smth-desmth_special',trim(buffer(idx+1:eos-1))) /= 0) .and. &
443 (len_trim(buffer(idx+1:eos-1)) == len('smth-desmth_special'))) then
444 is_smooth_option(i) = .true.
445 source_smooth_option(i) = SMTHDESMTH_SPECIAL
448 else if (index('smooth_passes',trim(buffer(1:idx-1))) /= 0) then
449 is_smooth_passes(i) = .true.
450 read(buffer(idx+1:eos-1),'(i10)') source_smooth_passes(i)
452 else if (index('rel_path',trim(buffer(1:idx-1))) /= 0) then
454 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
458 path_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
459 if (path_string(ispace-idx-1:ispace-idx-1) /= '/') &
460 path_string(ispace-idx:ispace-idx) = '/'
461 if (path_string(1:1) == '/') then
462 path_string(1:127) = path_string(2:128)
463 path_string(128:128) = ' '
465 ispace = index(path_string,':')
466 if (ispace /= 0) then
467 write(res_string,'(a)') path_string(1:ispace-1)
469 res_string = 'default'
471 write(path_string,'(a)') trim(geog_data_path)//trim(path_string(ispace+1:128))
472 if (list_search(source_res_path(i), ckey=res_string, cvalue=path_string)) then
473 call mprintf(.true., WARN, &
474 'In GEOGRID.TBL entry %i, multiple paths are given for '// &
475 'resolution %s. %s will be used.', &
476 i1=i, s1=trim(res_string), s2=trim(path_string))
478 call list_insert(source_res_path(i), ckey=res_string, cvalue=path_string)
481 else if (index('abs_path',trim(buffer(1:idx-1))) /= 0) then
483 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
487 path_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
488 if (path_string(ispace-idx-1:ispace-idx-1) /= '/') &
489 path_string(ispace-idx:ispace-idx) = '/'
490 ispace = index(path_string,':')
491 if (ispace /= 0) then
492 write(res_string,'(a)') path_string(1:ispace-1)
494 res_string = 'default'
496 write(path_string,'(a)') trim(path_string(ispace+1:128))
497 if (list_search(source_res_path(i), ckey=res_string, cvalue=path_string)) then
498 call mprintf(.true., WARN, &
499 'In GEOGRID.TBL entry %i, multiple paths are given for '// &
500 'resolution %s. %s will be used.', &
501 i1=i, s1=trim(res_string), s2=trim(path_string))
503 call list_insert(source_res_path(i), ckey=res_string, cvalue=path_string)
506 else if (index('output_stagger',trim(buffer(1:idx-1))) /= 0) then
507 if (index('M',trim(buffer(idx+1:eos-1))) /= 0) then
508 is_output_stagger(i) = .true.
509 source_output_stagger(i) = M
510 else if (index('U',trim(buffer(idx+1:eos-1))) /= 0) then
511 is_output_stagger(i) = .true.
512 source_output_stagger(i) = U
513 else if (index('V',trim(buffer(idx+1:eos-1))) /= 0) then
514 is_output_stagger(i) = .true.
515 source_output_stagger(i) = V
516 else if (index('HH',trim(buffer(idx+1:eos-1))) /= 0) then
517 is_output_stagger(i) = .true.
518 source_output_stagger(i) = HH
519 else if (index('VV',trim(buffer(idx+1:eos-1))) /= 0) then
520 is_output_stagger(i) = .true.
521 source_output_stagger(i) = VV
524 else if ((index('landmask_water',trim(buffer(1:idx-1))) /= 0) .and. &
525 (len_trim(buffer(1:idx-1)) == 14)) then
527 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
530 landmask_string = ' '
531 landmask_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
532 ispace = index(landmask_string,':')
533 if (ispace /= 0) then
534 write(res_string,'(a)') landmask_string(1:ispace-1)
536 res_string = 'default'
538 write(landmask_string,'(a)') trim(landmask_string(ispace+1:128))
539 if (list_search(source_landmask_water(i), ckey=res_string, cvalue=landmask_string)) then
540 call mprintf(.true., WARN, &
541 'In GEOGRID.TBL entry %i, multiple landmask category specifications are given for '// &
542 'resolution %s. %s will be used.', &
543 i1=i, s1=trim(res_string), s2=trim(landmask_string))
545 call list_insert(source_landmask_water(i), ckey=res_string, cvalue=landmask_string)
548 else if ((index('landmask_land',trim(buffer(1:idx-1))) /= 0) .and. &
549 (len_trim(buffer(1:idx-1)) == 13)) then
551 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
554 landmask_string = ' '
555 landmask_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
556 ispace = index(landmask_string,':')
557 if (ispace /= 0) then
558 write(res_string,'(a)') landmask_string(1:ispace-1)
560 res_string = 'default'
562 write(landmask_string,'(a)') trim(landmask_string(ispace+1:128))
563 if (list_search(source_landmask_land(i), ckey=res_string, cvalue=landmask_string)) then
564 call mprintf(.true., WARN, &
565 'In GEOGRID.TBL entry %i, multiple landmask category specifications are given for '// &
566 'resolution %s. %s will be used.', &
567 i1=i, s1=trim(res_string), s2=trim(landmask_string))
569 call list_insert(source_landmask_land(i), ckey=res_string, cvalue=landmask_string)
572 else if ((index('masked',trim(buffer(1:idx-1))) /= 0) .and. &
573 (len_trim(buffer(1:idx-1)) == 6)) then
574 if (index('water',trim(buffer(idx+1:eos-1))) /= 0) then
575 is_masked(i) = .true.
576 source_masked(i) = 0.
577 else if (index('land',trim(buffer(idx+1:eos-1))) /= 0) then
578 is_masked(i) = .true.
579 source_masked(i) = 1.
582 else if (index('fill_missing',trim(buffer(1:idx-1))) /= 0) then
583 is_fill_missing(i) = .true.
584 read(buffer(idx+1:eos-1),*) source_fill_missing(i)
586 else if (index('halt_on_missing',trim(buffer(1:idx-1))) /= 0) then
587 if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
588 is_halt_missing(i) = .true.
589 else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
590 is_halt_missing(i) = .false.
593 else if (index('dominant_category',trim(buffer(1:idx-1))) /= 0) then
595 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
598 is_dominant_category(i) = .true.
599 source_dominant_category(i) = ' '
600 source_dominant_category(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
602 else if (index('dominant_only',trim(buffer(1:idx-1))) /= 0) then
604 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
607 is_dominant_only(i) = .true.
608 source_dominant_only(i) = ' '
609 source_dominant_only(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
611 else if (index('df_dx',trim(buffer(1:idx-1))) /= 0) then
613 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
618 source_dfdx(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
620 else if (index('df_dy',trim(buffer(1:idx-1))) /= 0) then
622 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
627 source_dfdy(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
629 else if (index('z_dim_name',trim(buffer(1:idx-1))) /= 0) then
631 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
634 is_z_dim_name(i) = .true.
635 source_z_dim_name(i) = ' '
636 source_z_dim_name(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
638 else if (index('subgrid',trim(buffer(1:idx-1))) /= 0) then
639 if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
640 is_subgrid(i) = .true.
641 else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
642 is_subgrid(i) = .false.
645 else if (index('flag_in_output',trim(buffer(1:idx-1))) /= 0) then
647 do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
650 is_output_flag(i) = .true.
651 source_output_flag(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
654 call mprintf(.true., WARN, 'In GEOGRID.TBL, unrecognized option %s in '// &
655 'entry %i.',i1=idx, s1=buffer(i:idx-1))
659 end if !} index(buffer(1:eos-1),'=') /= 0
661 buffer = buffer(eos+1:BUFSIZE)
662 end do ! while eos /= 0 }
664 end if !} index(buffer, '=====') /= 0
669 ! Check the user specifications for gross errors
670 if ( .not. check_data_specification() ) then
671 call datalist_destroy()
672 call mprintf(.true.,ERROR,'Errors were found in either index files or GEOGRID.TBL.')
675 call hash_init(bad_files)
679 1000 call mprintf(.true.,ERROR,'Could not open GEOGRID.TBL')
681 1001 call mprintf(.true.,ERROR,'Encountered error while reading GEOGRID.TBL')
683 end subroutine get_datalist
686 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
687 ! Name: get_source_params
689 ! Purpose: For each field, this routine reads in the metadata in the index file
690 ! for the first available resolution of data specified by res_string. Also
691 ! based on res_string, this routine sets the interpolation sequence for the
692 ! field. This routine should be called prior to processing a field for each
694 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
695 subroutine get_source_params(res_string)
702 integer, parameter :: BUFSIZE = 256
705 character (len=128), intent(in) :: res_string
708 integer :: idx, i, is, ie, ispace, eos, iquoted, funit
709 character (len=128) :: temp_data, temp_interp
710 character (len=256) :: test_fname
711 character (len=BUFSIZE) :: buffer
712 logical :: have_specification, is_used
714 ! For each entry in the GEOGRID.TBL file
717 ! Initialize metadata
718 is_wordsize(idx) = .false.
719 is_endian(idx) = .false.
720 is_row_order(idx) = .false.
721 is_fieldtype(idx) = .false.
722 is_proj(idx) = .false.
725 is_known_x(idx) = .false.
726 is_known_y(idx) = .false.
727 is_known_lat(idx) = .false.
728 is_known_lon(idx) = .false.
729 is_truelat1(idx) = .false.
730 is_truelat2(idx) = .false.
731 is_stdlon(idx) = .false.
732 is_tile_x(idx) = .false.
733 is_tile_y(idx) = .false.
734 is_tile_z(idx) = .false.
735 is_tile_z_start(idx) = .false.
736 is_tile_z_end(idx) = .false.
737 is_category_min(idx) = .false.
738 is_category_max(idx) = .false.
739 is_tile_bdr(idx) = .false.
740 is_fieldname(idx) = .false.
741 is_scale_factor(idx) = .false.
742 is_units(idx) = .false.
743 is_descr(idx) = .false.
744 is_signed(idx) = .false.
745 is_missing_value(idx) = .false.
748 ! Set the interpolator sequence for the field to be the first value in res_string that matches
749 ! the resolution keyword for an interp_sequence specification
751 ie = index(res_string(is:128),'+') - 1
752 if (ie <= 0) ie = 128
753 temp_interp = res_string(is:ie)
754 do while (.not. list_search(source_interp_option(idx), ckey=temp_interp, cvalue=source_interp_string(idx)) &
756 call mprintf(.true., INFORM, 'For %s, couldn''t find interpolator sequence for '// &
758 s1=trim(source_fieldname(idx)), s2=trim(temp_interp))
760 ie = is + index(res_string(is:128),'+') - 2
761 if (ie - is <= 0) ie = 128
762 temp_interp = res_string(is:ie)
766 temp_interp = 'default'
767 if (list_search(source_interp_option(idx), ckey=temp_interp, cvalue=source_interp_string(idx))) then
768 call mprintf(.true., INFORM, 'Using default interpolator sequence for %s.', &
769 s1=trim(source_fieldname(idx)))
771 call mprintf(.true., ERROR, 'Could not find interpolator sequence for requested resolution for %s.'// &
772 ' The sources specified in namelist.wps is not listed in GEOGRID.TBL.', &
773 s1=trim(source_fieldname(idx)))
776 call mprintf(.true., INFORM, 'Using %s interpolator sequence for %s.', &
777 s1=temp_interp, s2=trim(source_fieldname(idx)))
780 ! Set the data source for the field to be the first value in res_string that matches
781 ! the resolution keyword for an abs_path or rel_path specification
783 ie = index(res_string(is:128),'+') - 1
784 if (ie <= 0) ie = 128
785 temp_data = res_string(is:ie)
786 do while (.not. list_search(source_res_path(idx), ckey=temp_data, cvalue=source_path(idx)) &
788 call mprintf(.true., INFORM, 'For %s, couldn''t find %s data source.', &
789 s1=trim(source_fieldname(idx)), s2=trim(temp_data))
791 ie = is + index(res_string(is:128),'+') - 2
792 if (ie - is <= 0) ie = 128
793 temp_data = res_string(is:ie)
797 temp_data = 'default'
798 if (list_search(source_res_path(idx), ckey=temp_data, cvalue=source_path(idx))) then
799 call mprintf(.true., INFORM, 'Using default data source for %s.', &
800 s1=trim(source_fieldname(idx)))
802 call mprintf(.true., ERROR, 'Could not find data resolution for requested resolution for %s. '// &
803 'The source specified in namelist.wps is not listed in GEOGRID.TBL.', &
804 s1=trim(source_fieldname(idx)))
807 call mprintf(.true., INFORM, 'Using %s data source for %s.', &
808 s1=temp_data, s2=trim(source_fieldname(idx)))
811 call mprintf(trim(temp_data) /= trim(temp_interp),WARN,'For %s, using %s data source with %s interpolation sequence.', &
812 s1=source_fieldname(idx), s2=temp_data, s3=temp_interp)
814 write(test_fname, '(a)') trim(source_path(idx))//'index'
817 ! Open the index file for the data source for this field, and read in metadata specs
820 inquire(unit=funit, opened=is_used)
821 if (.not. is_used) exit
823 open(funit,file=trim(test_fname),form='formatted',status='old',err=1000)
826 read(funit,'(a)',end=40, err=1001) buffer
829 ! Is this line a comment?
830 if (buffer(1:1) == '#') then
834 have_specification = .true.
836 ! If only part of the line is a comment, just turn the comment into spaces
837 eos = index(buffer,'#')
838 if (eos /= 0) buffer(eos:BUFSIZE) = ' '
840 do while (have_specification) !{
842 ! If this line has no semicolon, it may contain a single specification,
843 ! so we set have_specification = .false. to prevent the line from being
844 ! processed again and pretend that the last character was a semicolon
845 eos = index(buffer,';')
847 have_specification = .false.
851 i = index(buffer(1:eos-1),'=')
855 if (index('projection',trim(buffer(1:i-1))) /= 0) then
856 if (index('lambert',trim(buffer(i+1:eos-1))) /= 0) then
857 is_proj(idx) = .true.
858 source_proj(idx) = PROJ_LC
859 else if (index('polar_wgs84',trim(buffer(i+1:eos-1))) /= 0 .and. &
860 len_trim('polar_wgs84') == len_trim(buffer(i+1:eos-1))) then
861 is_proj(idx) = .true.
862 source_proj(idx) = PROJ_PS_WGS84
863 else if (index('albers_nad83',trim(buffer(i+1:eos-1))) /= 0 .and. &
864 len_trim('albers_nad83') == len_trim(buffer(i+1:eos-1))) then
865 is_proj(idx) = .true.
866 source_proj(idx) = PROJ_ALBERS_NAD83
867 else if (index('polar',trim(buffer(i+1:eos-1))) /= 0 .and. &
868 len_trim('polar') == len_trim(buffer(i+1:eos-1))) then
869 is_proj(idx) = .true.
870 source_proj(idx) = PROJ_PS
871 else if (index('mercator',trim(buffer(i+1:eos-1))) /= 0) then
872 is_proj(idx) = .true.
873 source_proj(idx) = PROJ_MERC
874 else if (index('regular_ll',trim(buffer(i+1:eos-1))) /= 0) then
875 is_proj(idx) = .true.
876 source_proj(idx) = PROJ_LATLON
879 else if (index('type',trim(buffer(1:i-1))) /= 0) then
880 if (index('continuous',trim(buffer(i+1:eos-1))) /= 0) then
881 is_fieldtype(idx) = .true.
882 source_fieldtype(idx) = CONTINUOUS
883 else if (index('categorical',trim(buffer(i+1:eos-1))) /= 0) then
884 is_fieldtype(idx) = .true.
885 source_fieldtype(idx) = CATEGORICAL
888 else if (index('signed',trim(buffer(1:i-1))) /= 0) then
889 if (index('yes',trim(buffer(i+1:eos-1))) /= 0) then
890 is_signed(idx) = .true.
891 else if (index('no',trim(buffer(i+1:eos-1))) /= 0) then
892 is_signed(idx) = .false.
895 else if (index('units',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_units(idx) = .true.
903 source_units(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_units(idx)(1:ispace-i) = buffer(i+1:ispace-1)
908 else if (index('description',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 is_descr(idx) = .true.
916 source_descr(idx) = ' '
917 if (buffer(i+1:i+1) == '"' .or. buffer(i+1:i+1) == '''') i = i + 1
918 if (buffer(ispace-1:ispace-1) == '"' .or. buffer(ispace-1:ispace-1) == '''') ispace = ispace - 1
919 source_descr(idx)(1:ispace-i) = buffer(i+1:ispace-1)
921 else if (index('mminlu',trim(buffer(1:i-1))) /= 0) then
924 do while (((ispace < eos) .and. (buffer(ispace:ispace) /= ' ')) .or. (iquoted == 1))
925 if (buffer(ispace:ispace) == '"' .or. buffer(ispace:ispace) == '''') iquoted = mod(iquoted+1,2)
928 if (buffer(i+1:i+1) == '"' .or. buffer(i+1:i+1) == '''') i = i + 1
929 if (buffer(ispace-1:ispace-1) == '"' .or. buffer(ispace-1:ispace-1) == '''') ispace = ispace - 1
930 source_mminlu(1:ispace-i) = buffer(i+1:ispace-1)
932 else if (index('iswater',trim(buffer(1:i-1))) /= 0) then
933 read(buffer(i+1:eos-1),*) source_iswater
935 else if (index('islake',trim(buffer(1:i-1))) /= 0) then
936 read(buffer(i+1:eos-1),*) source_islake
938 else if (index('isice',trim(buffer(1:i-1))) /= 0) then
939 read(buffer(i+1:eos-1),*) source_isice
941 else if (index('isurban',trim(buffer(1:i-1))) /= 0) then
942 read(buffer(i+1:eos-1),*) source_isurban
944 else if (index('isoilwater',trim(buffer(1:i-1))) /= 0) then
945 read(buffer(i+1:eos-1),*) source_isoilwater
947 else if (index('dx',trim(buffer(1:i-1))) /= 0) then
949 read(buffer(i+1:eos-1),*) source_dx(idx)
951 else if (index('dy',trim(buffer(1:i-1))) /= 0) then
953 read(buffer(i+1:eos-1),*) source_dy(idx)
955 else if (index('known_x',trim(buffer(1:i-1))) /= 0) then
956 is_known_x(idx) = .true.
957 read(buffer(i+1:eos-1),*) source_known_x(idx)
959 else if (index('known_y',trim(buffer(1:i-1))) /= 0) then
960 is_known_y(idx) = .true.
961 read(buffer(i+1:eos-1),*) source_known_y(idx)
963 else if (index('known_lat',trim(buffer(1:i-1))) /= 0) then
964 is_known_lat(idx) = .true.
965 read(buffer(i+1:eos-1),*) source_known_lat(idx)
967 else if (index('known_lon',trim(buffer(1:i-1))) /= 0) then
968 is_known_lon(idx) = .true.
969 read(buffer(i+1:eos-1),*) source_known_lon(idx)
971 else if (index('stdlon',trim(buffer(1:i-1))) /= 0) then
972 is_stdlon(idx) = .true.
973 read(buffer(i+1:eos-1),*) source_stdlon(idx)
975 else if (index('truelat1',trim(buffer(1:i-1))) /= 0) then
976 is_truelat1(idx) = .true.
977 read(buffer(i+1:eos-1),*) source_truelat1(idx)
979 else if (index('truelat2',trim(buffer(1:i-1))) /= 0) then
980 is_truelat2(idx) = .true.
981 read(buffer(i+1:eos-1),*) source_truelat2(idx)
983 else if (index('wordsize',trim(buffer(1:i-1))) /= 0) then
984 is_wordsize(idx) = .true.
985 read(buffer(i+1:eos-1),'(i10)') source_wordsize(idx)
987 else if (index('endian',trim(buffer(1:i-1))) /= 0) then
988 if (index('big',trim(buffer(i+1:eos-1))) /= 0) then
989 is_endian(idx) = .true.
990 source_endian(idx) = BIG_ENDIAN
991 else if (index('little',trim(buffer(i+1:eos-1))) /= 0) then
992 is_endian(idx) = .true.
993 source_endian(idx) = LITTLE_ENDIAN
995 call mprintf(.true.,WARN,'Invalid value for keyword ''endian'' '// &
996 'specified in index file. BIG_ENDIAN will be used.')
999 else if (index('row_order',trim(buffer(1:i-1))) /= 0) then
1000 if (index('bottom_top',trim(buffer(i+1:eos-1))) /= 0) then
1001 is_row_order(idx) = .true.
1002 source_row_order(idx) = BOTTOM_TOP
1003 else if (index('top_bottom',trim(buffer(i+1:eos-1))) /= 0) then
1004 is_row_order(idx) = .true.
1005 source_row_order(idx) = TOP_BOTTOM
1008 else if (index('tile_x',trim(buffer(1:i-1))) /= 0) then
1009 is_tile_x(idx) = .true.
1010 read(buffer(i+1:eos-1),'(i10)') source_tile_x(idx)
1012 else if (index('tile_y',trim(buffer(1:i-1))) /= 0) then
1013 is_tile_y(idx) = .true.
1014 read(buffer(i+1:eos-1),'(i10)') source_tile_y(idx)
1016 else if (index('tile_z',trim(buffer(1:i-1))) /= 0) then
1017 is_tile_z(idx) = .true.
1018 read(buffer(i+1:eos-1),'(i10)') source_tile_z(idx)
1020 else if (index('tile_z_start',trim(buffer(1:i-1))) /= 0) then
1021 is_tile_z_start(idx) = .true.
1022 read(buffer(i+1:eos-1),'(i10)') source_tile_z_start(idx)
1024 else if (index('tile_z_end',trim(buffer(1:i-1))) /= 0) then
1025 is_tile_z_end(idx) = .true.
1026 read(buffer(i+1:eos-1),'(i10)') source_tile_z_end(idx)
1028 else if (index('category_min',trim(buffer(1:i-1))) /= 0) then
1029 is_category_min(idx) = .true.
1030 read(buffer(i+1:eos-1),'(i10)') source_category_min(idx)
1032 else if (index('category_max',trim(buffer(1:i-1))) /= 0) then
1033 is_category_max(idx) = .true.
1034 read(buffer(i+1:eos-1),'(i10)') source_category_max(idx)
1036 else if (index('tile_bdr',trim(buffer(1:i-1))) /= 0) then
1037 is_tile_bdr(idx) = .true.
1038 read(buffer(i+1:eos-1),'(i10)') source_tile_bdr(idx)
1040 else if (index('missing_value',trim(buffer(1:i-1))) /= 0) then
1041 is_missing_value(idx) = .true.
1042 read(buffer(i+1:eos-1),*) source_missing_value(idx)
1044 else if (index('scale_factor',trim(buffer(1:i-1))) /= 0) then
1045 is_scale_factor(idx) = .true.
1046 read(buffer(i+1:eos-1),*) source_scale_factor(idx)
1049 call mprintf(.true., WARN, 'In %s, unrecognized option %s in entry %i.', &
1050 s1=trim(test_fname), s2=buffer(i:i-1), i1=i)
1054 end if !} index(buffer(1:eos-1),'=') /= 0
1056 buffer = buffer(eos+1:BUFSIZE)
1057 end do ! while eos /= 0 }
1059 end if !} index(buffer, '=====') /= 0
1069 1000 call mprintf(.true.,ERROR,'Could not open %s', s1=trim(test_fname))
1070 1001 call mprintf(.true.,ERROR,'Encountered error while reading %s', s1=trim(test_fname))
1072 end subroutine get_source_params
1075 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1076 ! Name: datalist_destroy()
1078 ! Purpose: This routine deallocates any memory that was allocated by the
1079 ! get_datalist() subroutine.
1080 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1081 subroutine datalist_destroy()
1088 if (associated(source_wordsize)) then
1089 deallocate(source_wordsize)
1090 deallocate(source_endian)
1091 deallocate(source_fieldtype)
1092 deallocate(source_dest_fieldtype)
1093 deallocate(source_proj)
1094 deallocate(source_priority)
1095 deallocate(source_dx)
1096 deallocate(source_dy)
1097 deallocate(source_known_x)
1098 deallocate(source_known_y)
1099 deallocate(source_known_lat)
1100 deallocate(source_known_lon)
1101 deallocate(source_truelat1)
1102 deallocate(source_truelat2)
1103 deallocate(source_stdlon)
1104 deallocate(source_fieldname)
1105 deallocate(source_path)
1106 deallocate(source_interp_string)
1107 deallocate(source_tile_x)
1108 deallocate(source_tile_y)
1109 deallocate(source_tile_z)
1110 deallocate(source_tile_z_start)
1111 deallocate(source_tile_z_end)
1112 deallocate(source_tile_bdr)
1113 deallocate(source_category_min)
1114 deallocate(source_category_max)
1115 deallocate(source_masked)
1116 deallocate(source_output_stagger)
1117 deallocate(source_row_order)
1118 deallocate(source_dominant_category)
1119 deallocate(source_dominant_only)
1120 deallocate(source_dfdx)
1121 deallocate(source_dfdy)
1122 deallocate(source_scale_factor)
1123 deallocate(source_z_dim_name)
1124 deallocate(source_smooth_option)
1125 deallocate(source_smooth_passes)
1126 deallocate(source_units)
1127 deallocate(source_descr)
1128 deallocate(source_missing_value)
1129 deallocate(source_fill_missing)
1131 call list_destroy(source_res_path(i))
1132 call list_destroy(source_interp_option(i))
1133 call list_destroy(source_landmask_land(i))
1134 call list_destroy(source_landmask_water(i))
1136 deallocate(source_res_path)
1137 deallocate(source_interp_option)
1138 deallocate(source_landmask_land)
1139 deallocate(source_landmask_water)
1140 deallocate(source_output_flag)
1142 deallocate(is_wordsize)
1143 deallocate(is_endian)
1144 deallocate(is_fieldtype)
1145 deallocate(is_dest_fieldtype)
1147 deallocate(is_priority)
1150 deallocate(is_known_x)
1151 deallocate(is_known_y)
1152 deallocate(is_known_lat)
1153 deallocate(is_known_lon)
1154 deallocate(is_truelat1)
1155 deallocate(is_truelat2)
1156 deallocate(is_stdlon)
1157 deallocate(is_fieldname)
1159 deallocate(is_tile_x)
1160 deallocate(is_tile_y)
1161 deallocate(is_tile_z)
1162 deallocate(is_tile_z_start)
1163 deallocate(is_tile_z_end)
1164 deallocate(is_tile_bdr)
1165 deallocate(is_category_min)
1166 deallocate(is_category_max)
1167 deallocate(is_masked)
1168 deallocate(is_halt_missing)
1169 deallocate(is_output_stagger)
1170 deallocate(is_row_order)
1171 deallocate(is_dominant_category)
1172 deallocate(is_dominant_only)
1175 deallocate(is_scale_factor)
1176 deallocate(is_z_dim_name)
1177 deallocate(is_smooth_option)
1178 deallocate(is_smooth_passes)
1179 deallocate(is_signed)
1180 deallocate(is_units)
1181 deallocate(is_descr)
1182 deallocate(is_missing_value)
1183 deallocate(is_fill_missing)
1184 deallocate(is_subgrid)
1185 deallocate(is_output_flag)
1188 call hash_destroy(bad_files)
1190 end subroutine datalist_destroy
1193 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1194 ! Name: reset_next_field
1196 ! Purpose: To reset the pointer to the next field in the list of fields
1197 ! specified by the user.
1198 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1199 subroutine reset_next_field()
1205 end subroutine reset_next_field
1208 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1209 ! Name: get_next_fieldname
1211 ! Purpose: Calling this routine results in field_name being set to the name of
1212 ! the field currently pointed to. If istatus /= 0 upon return, an error
1213 ! occurred, and the value of field_name is undefined.
1214 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1215 subroutine get_next_fieldname(field_name, istatus)
1220 integer, intent(out) :: istatus
1221 character (len=128), intent(out) :: field_name
1225 if (next_field <= num_entries) then
1227 field_name = source_fieldname(next_field)
1228 next_field = next_field + 1
1233 end subroutine get_next_fieldname
1236 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1237 ! Name: get_next_output_fieldname
1240 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1241 recursive subroutine get_next_output_fieldname(nest_num, field_name, ndims, &
1243 istagger, memorder, dimnames, units, &
1244 description, sr_x, sr_y, istatus)
1250 #include "wrf_io_flags.h"
1253 integer, intent(in) :: nest_num
1254 integer, intent(out) :: istatus, ndims, istagger, min_cat, max_cat
1255 integer, intent(out) :: sr_x, sr_y
1256 character (len=128), intent(out) :: memorder, field_name, units, description
1257 character (len=128), dimension(3), intent(out) :: dimnames
1260 integer :: temp_fieldtype
1261 integer, dimension(MAX_LANDMASK_CATEGORIES) :: landmask
1262 logical :: is_water_mask, is_dom_only
1263 character (len=128) :: domcat_name, dfdx_name, dfdy_name
1264 character (len=256) :: temphash
1268 if (output_field_state == RETURN_LANDMASK) then
1269 call hash_init(duplicate_fnames)
1270 call get_landmask_field(geog_data_res(nest_num), field_name, is_water_mask, landmask, istatus)
1271 if (istatus == 0) then
1272 temphash(129:256) = ' '
1273 temphash(1:128) = field_name(1:128)
1274 call hash_insert(duplicate_fnames, temphash)
1275 call get_domcategory_name(field_name, domcat_name, is_dom_only, istatus)
1276 ! We will only save the dominant category
1277 if (is_dom_only .and. (istatus == 0)) then
1278 output_field_state = RETURN_DOMCAT_LM
1279 call get_next_output_fieldname(nest_num, field_name, ndims, &
1280 min_cat, max_cat, istagger, &
1281 memorder, dimnames, units, description, &
1282 sr_x, sr_y, istatus)
1288 temp_fieldtype = iget_fieldtype(field_name, istatus)
1289 if (istatus == 0) then
1290 if (temp_fieldtype == CONTINUOUS) then
1291 call get_max_levels(field_name, min_cat, max_cat, istatus)
1292 else if (temp_fieldtype == CATEGORICAL) then
1293 call get_max_categories(field_name, min_cat, max_cat, istatus)
1295 if (max_cat - min_cat > 0) ndims = 3
1297 call get_output_stagger(field_name, istagger, istatus)
1298 if (istagger == M) then
1299 dimnames(1) = 'west_east'
1300 dimnames(2) = 'south_north'
1301 else if (istagger == U) then
1302 dimnames(1) = 'west_east_stag'
1303 dimnames(2) = 'south_north'
1304 else if (istagger == V) then
1305 dimnames(1) = 'west_east'
1306 dimnames(2) = 'south_north_stag'
1307 else if (istagger == HH) then
1308 dimnames(1) = 'west_east'
1309 dimnames(2) = 'south_north'
1310 else if (istagger == VV) then
1311 dimnames(1) = 'west_east'
1312 dimnames(2) = 'south_north'
1314 if (ndims == 2) then
1317 else if (ndims == 3) then
1319 call get_z_dim_name(field_name, dimnames(3), istatus)
1325 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1326 call get_source_units(field_name, 1, units, istatus)
1327 if (istatus /= 0) units = '-'
1328 call get_source_descr(field_name, 1, description, istatus)
1329 if (istatus /= 0) description = '-'
1331 output_field_state = RETURN_DOMCAT_LM
1334 output_field_state = RETURN_FIELDNAME
1335 call get_next_output_fieldname(nest_num, field_name, ndims, &
1336 min_cat, max_cat, istagger, &
1337 memorder, dimnames, units, description, &
1338 sr_x, sr_y, istatus)
1342 else if (output_field_state == RETURN_FIELDNAME) then
1343 call get_next_fieldname(field_name, istatus)
1344 temphash(129:256) = ' '
1345 temphash(1:128) = field_name(1:128)
1346 if (istatus == 0 .and. (.not. hash_search(duplicate_fnames, temphash))) then
1347 call hash_insert(duplicate_fnames, temphash)
1348 call get_domcategory_name(field_name, domcat_name, is_dom_only, istatus)
1349 ! We will only save the dominant category
1350 if (is_dom_only .and. (istatus == 0)) then
1351 output_field_state = RETURN_DOMCAT
1352 call get_next_output_fieldname(nest_num, field_name, ndims, &
1353 min_cat, max_cat, istagger, &
1354 memorder, dimnames, units, description, &
1355 sr_x, sr_y, istatus)
1358 ! Return the fractional field
1363 temp_fieldtype = iget_fieldtype(field_name, istatus)
1364 if (istatus == 0) then
1365 if (temp_fieldtype == CONTINUOUS) then
1366 call get_max_levels(field_name, min_cat, max_cat, istatus)
1367 else if (temp_fieldtype == CATEGORICAL) then
1368 call get_max_categories(field_name, min_cat, max_cat, istatus)
1370 if (max_cat - min_cat > 0) ndims = 3
1372 call get_output_stagger(field_name, istagger, istatus)
1373 if (istagger == M) then
1374 dimnames(1) = 'west_east'
1375 dimnames(2) = 'south_north'
1376 else if (istagger == U) then
1377 dimnames(1) = 'west_east_stag'
1378 dimnames(2) = 'south_north'
1379 else if (istagger == V) then
1380 dimnames(1) = 'west_east'
1381 dimnames(2) = 'south_north_stag'
1382 else if (istagger == HH) then
1383 dimnames(1) = 'west_east'
1384 dimnames(2) = 'south_north'
1385 else if (istagger == VV) then
1386 dimnames(1) = 'west_east'
1387 dimnames(2) = 'south_north'
1389 if (ndims == 2) then
1392 else if (ndims == 3) then
1394 call get_z_dim_name(field_name, dimnames(3), istatus)
1400 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1401 call get_source_units(field_name, 1, units, istatus)
1402 if (istatus /= 0) units = '-'
1403 call get_source_descr(field_name, 1, description, istatus)
1404 if (istatus /= 0) description = '-'
1406 output_field_state = RETURN_DOMCAT
1408 else if (istatus /= 0) then
1409 output_field_state = RETURN_LANDMASK
1410 call hash_destroy(duplicate_fnames)
1412 else if (hash_search(duplicate_fnames, temphash)) then
1413 call get_next_output_fieldname(nest_num, field_name, ndims, &
1414 min_cat, max_cat, istagger, &
1415 memorder, dimnames, units, description, &
1416 sr_x, sr_y, istatus)
1420 else if (output_field_state == RETURN_DOMCAT .or. &
1421 output_field_state == RETURN_DOMCAT_LM ) then
1422 if (output_field_state == RETURN_DOMCAT) then
1423 next_field = next_field - 1
1424 call get_next_fieldname(field_name, istatus)
1426 call get_landmask_field(geog_data_res(nest_num), field_name, is_water_mask, landmask, istatus)
1428 if (istatus == 0) then
1429 call get_domcategory_name(field_name, domcat_name, is_dom_only, istatus)
1430 if (istatus == 0) then
1434 call get_output_stagger(field_name, istagger, istatus)
1435 if (istagger == M) then
1436 dimnames(1) = 'west_east'
1437 dimnames(2) = 'south_north'
1438 else if (istagger == U) then
1439 dimnames(1) = 'west_east_stag'
1440 dimnames(2) = 'south_north'
1441 else if (istagger == V) then
1442 dimnames(1) = 'west_east'
1443 dimnames(2) = 'south_north_stag'
1444 else if (istagger == HH) then
1445 dimnames(1) = 'west_east'
1446 dimnames(2) = 'south_north'
1447 else if (istagger == VV) then
1448 dimnames(1) = 'west_east'
1449 dimnames(2) = 'south_north'
1454 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1455 field_name = domcat_name
1457 description = 'Dominant category'
1458 if (output_field_state == RETURN_DOMCAT) then
1459 output_field_state = RETURN_DFDX
1461 output_field_state = RETURN_DFDX_LM
1464 if (output_field_state == RETURN_DOMCAT) then
1465 output_field_state = RETURN_DFDX
1467 output_field_state = RETURN_DFDX_LM
1469 call get_next_output_fieldname(nest_num, field_name, ndims, &
1470 min_cat, max_cat, istagger, &
1471 memorder, dimnames, units, description, &
1472 sr_x, sr_y, istatus)
1476 call mprintf(.true., ERROR, 'get_next_output_fieldname(): In state DOMCAT, '// &
1477 'but no field name is found.')
1480 else if (output_field_state == RETURN_DFDX .or. &
1481 output_field_state == RETURN_DFDX_LM) then
1482 if (output_field_state == RETURN_DFDX) then
1483 next_field = next_field - 1
1484 call get_next_fieldname(field_name, istatus)
1486 call get_landmask_field(geog_data_res(nest_num), field_name, is_water_mask, landmask, istatus)
1488 if (istatus == 0) then
1489 call get_dfdx_name(field_name, dfdx_name, istatus)
1490 if (istatus == 0) then
1494 temp_fieldtype = iget_fieldtype(field_name, istatus)
1495 if (istatus == 0) then
1496 if (temp_fieldtype == CONTINUOUS) then
1497 call get_max_levels(field_name, min_cat, max_cat, istatus)
1498 else if (temp_fieldtype == CATEGORICAL) then
1499 call get_max_categories(field_name, min_cat, max_cat, istatus)
1501 if (max_cat - min_cat > 0) ndims = 3
1503 call get_output_stagger(field_name, istagger, istatus)
1504 if (istagger == M) then
1505 dimnames(1) = 'west_east'
1506 dimnames(2) = 'south_north'
1507 else if (istagger == U) then
1508 dimnames(1) = 'west_east_stag'
1509 dimnames(2) = 'south_north'
1510 else if (istagger == V) then
1511 dimnames(1) = 'west_east'
1512 dimnames(2) = 'south_north_stag'
1513 else if (istagger == HH) then
1514 dimnames(1) = 'west_east'
1515 dimnames(2) = 'south_north'
1516 else if (istagger == VV) then
1517 dimnames(1) = 'west_east'
1518 dimnames(2) = 'south_north'
1520 if (ndims == 2) then
1523 else if (ndims == 3) then
1525 call get_z_dim_name(field_name, dimnames(3), istatus)
1531 field_name = dfdx_name
1534 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1535 description = 'df/dx'
1536 if (output_field_state == RETURN_DFDX) then
1537 output_field_state = RETURN_DFDY
1539 output_field_state = RETURN_DFDY_LM
1542 if (output_field_state == RETURN_DFDX) then
1543 output_field_state = RETURN_DFDY
1545 output_field_state = RETURN_DFDY_LM
1547 call get_next_output_fieldname(nest_num, field_name, ndims, &
1548 min_cat, max_cat, istagger, &
1549 memorder, dimnames, units, description, &
1550 sr_x, sr_y, istatus)
1554 call mprintf(.true., ERROR, 'get_next_output_fieldname(): In state DFDX, '// &
1555 'but no field name is found.')
1558 else if (output_field_state == RETURN_DFDY .or. &
1559 output_field_state == RETURN_DFDY_LM) then
1560 if (output_field_state == RETURN_DFDY) then
1561 next_field = next_field - 1
1562 call get_next_fieldname(field_name, istatus)
1564 call get_landmask_field(geog_data_res(nest_num), field_name, is_water_mask, landmask, istatus)
1566 if (istatus == 0) then
1567 call get_dfdy_name(field_name, dfdy_name, istatus)
1568 if (istatus == 0) then
1572 temp_fieldtype = iget_fieldtype(field_name, istatus)
1573 if (istatus == 0) then
1574 if (temp_fieldtype == CONTINUOUS) then
1575 call get_max_levels(field_name, min_cat, max_cat, istatus)
1576 else if (temp_fieldtype == CATEGORICAL) then
1577 call get_max_categories(field_name, min_cat, max_cat, istatus)
1579 if (max_cat - min_cat > 0) ndims = 3
1581 call get_output_stagger(field_name, istagger, istatus)
1582 if (istagger == M) then
1583 dimnames(1) = 'west_east'
1584 dimnames(2) = 'south_north'
1585 else if (istagger == U) then
1586 dimnames(1) = 'west_east_stag'
1587 dimnames(2) = 'south_north'
1588 else if (istagger == V) then
1589 dimnames(1) = 'west_east'
1590 dimnames(2) = 'south_north_stag'
1591 else if (istagger == HH) then
1592 dimnames(1) = 'west_east'
1593 dimnames(2) = 'south_north'
1594 else if (istagger == VV) then
1595 dimnames(1) = 'west_east'
1596 dimnames(2) = 'south_north'
1598 if (ndims == 2) then
1601 else if (ndims == 3) then
1603 call get_z_dim_name(field_name, dimnames(3), istatus)
1610 call get_subgrid_dim_name(nest_num, field_name, dimnames(1:2), sr_x, sr_y, istatus)
1611 field_name = dfdy_name
1613 description = 'df/dy'
1614 output_field_state = RETURN_FIELDNAME
1616 output_field_state = RETURN_FIELDNAME
1617 call get_next_output_fieldname(nest_num, field_name, ndims, &
1618 min_cat, max_cat, istagger, &
1619 memorder, dimnames, units, description, &
1620 sr_x, sr_y, istatus)
1624 call mprintf(.true., ERROR, 'get_next_output_fieldname(): In state DFDY, but no '// &
1625 'field name is found.')
1630 end subroutine get_next_output_fieldname
1633 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1634 ! Name: get_landmask_field
1636 ! Purpose: To return the name of the field from which the landmask is to be
1637 ! computed. If no error occurs, is_water_mask is .true. if the landmask
1638 ! value specifies the value of water, and .false. if the landmask value
1639 ! specifies the value of land.
1640 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1641 subroutine get_landmask_field(res_string, landmask_name, is_water_mask, landmask, istatus)
1646 character (len=128), intent(in) :: res_string
1647 integer, dimension(:), intent(out) :: landmask
1648 integer, intent(out) :: istatus
1649 logical, intent(out) :: is_water_mask
1650 character (len=128), intent(out) :: landmask_name
1656 integer :: is, ie, sos, eos, comma
1657 character (len=128) :: temp_res, mask_cat_string
1661 do idx=1,num_entries
1663 if (list_length(source_landmask_land(idx)) > 0) then
1665 ie = index(res_string(is:128),'+') - 1
1666 if (ie <= 0) ie = 128
1667 temp_res = res_string(is:ie)
1668 do while (.not. list_search(source_landmask_land(idx), ckey=temp_res, cvalue=mask_cat_string) &
1671 ie = is + index(res_string(is:128),'+') - 2
1672 if (ie - is <= 0) ie = 128
1673 temp_res = res_string(is:ie)
1677 temp_res = 'default'
1678 if (list_search(source_landmask_land(idx), ckey=temp_res, cvalue=mask_cat_string)) then
1679 is_water_mask = .false.
1680 landmask_name = source_fieldname(idx)
1684 is_water_mask = .false.
1685 landmask_name = source_fieldname(idx)
1691 ! Note: The following cannot be an else-if, since different resolutions of data may
1692 ! specify, alternately, a land or a water mask, and in general we need to search
1695 if (list_length(source_landmask_water(idx)) > 0) then
1697 ie = index(res_string(is:128),'+') - 1
1698 if (ie <= 0) ie = 128
1699 temp_res = res_string(is:ie)
1700 do while (.not. list_search(source_landmask_water(idx), ckey=temp_res, cvalue=mask_cat_string) &
1703 ie = is + index(res_string(is:128),'+') - 2
1704 if (ie - is <= 0) ie = 128
1705 temp_res = res_string(is:ie)
1709 temp_res = 'default'
1710 if (list_search(source_landmask_water(idx), ckey=temp_res, cvalue=mask_cat_string)) then
1711 is_water_mask = .true.
1712 landmask_name = source_fieldname(idx)
1716 is_water_mask = .true.
1717 landmask_name = source_fieldname(idx)
1722 if (istatus == 0) then
1726 comma = index(mask_cat_string(sos+1:eos-1),',')
1727 do while (comma > 0 .and. j < MAX_LANDMASK_CATEGORIES)
1728 read(mask_cat_string(sos+1:sos+comma-1),'(i10)') landmask(j)
1730 comma = index(mask_cat_string(sos+1:eos-1),',')
1733 read(mask_cat_string(sos+1:eos-1),'(i10)') landmask(j)
1735 if (j <= MAX_LANDMASK_CATEGORIES) then ! Terminate list with a flag value
1736 landmask(j) = INVALID
1743 end subroutine get_landmask_field
1746 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1747 ! Name: get_missing_value
1749 ! Pupose: Return the value used in the source data to indicate missing data.
1750 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1751 subroutine get_missing_value(fieldnm, ilevel, rmissing, istatus)
1756 integer, intent(in) :: ilevel
1757 integer, intent(out) :: istatus
1758 real, intent(out) :: rmissing
1759 character (len=128), intent(in) :: fieldnm
1766 do idx=1,num_entries
1767 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1768 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
1769 (source_priority(idx) == ilevel)) then
1771 if (is_missing_value(idx)) then
1772 rmissing = source_missing_value(idx)
1780 end subroutine get_missing_value
1783 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1784 ! Name: get_source_units
1786 ! Pupose: Return a string giving the units of the specified source data.
1787 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1788 subroutine get_source_units(fieldnm, ilevel, cunits, istatus)
1793 integer, intent(in) :: ilevel
1794 integer, intent(out) :: istatus
1795 character (len=128), intent(in) :: fieldnm
1796 character (len=128), intent(out) :: cunits
1803 do idx=1,num_entries
1804 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1805 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
1806 (source_priority(idx) == ilevel)) then
1808 if (is_units(idx)) then
1809 cunits = source_units(idx)
1817 end subroutine get_source_units
1820 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1821 ! Name: get_source_descr
1823 ! Pupose: Return a string giving a description of the specified source data.
1824 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1825 subroutine get_source_descr(fieldnm, ilevel, descr, istatus)
1830 integer, intent(in) :: ilevel
1831 integer, intent(out) :: istatus
1832 character (len=128), intent(in) :: fieldnm
1833 character (len=128), intent(out) :: descr
1840 do idx=1,num_entries
1841 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1842 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
1843 (source_priority(idx) == ilevel)) then
1845 if (is_units(idx)) then
1846 descr = source_descr(idx)
1854 end subroutine get_source_descr
1857 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1858 ! Name: get_missing_fill_value
1860 ! Pupose: Return the value to fill missing points with.
1861 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1862 subroutine get_missing_fill_value(fieldnm, rmissing, istatus)
1867 integer, intent(out) :: istatus
1868 real, intent(out) :: rmissing
1869 character (len=128), intent(in) :: fieldnm
1876 do idx=1,num_entries
1877 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1878 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) ) then
1880 if (is_fill_missing(idx)) then
1881 rmissing = source_fill_missing(idx)
1889 end subroutine get_missing_fill_value
1892 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1893 ! Name: get_halt_on_missing
1895 ! Pupose: Returns 1 if the program should halt upon encountering a missing
1896 ! value in the final output field, and 0 otherwise.
1897 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1898 subroutine get_halt_on_missing(fieldnm, halt, istatus)
1903 integer, intent(out) :: istatus
1904 logical, intent(out) :: halt
1905 character (len=128), intent(in) :: fieldnm
1913 do idx=1,num_entries
1914 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1915 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) ) then
1917 if (is_halt_missing(idx)) halt = .true.
1922 end subroutine get_halt_on_missing
1925 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1926 ! Name: get_masked_value
1928 ! Pupose: If the field is to be masked by the landmask, returns 0 if the field
1929 ! is masked over water and 1 if the field is masked over land. If no mask is
1930 ! to be applied, -1 is returned.
1931 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1932 subroutine get_masked_value(fieldnm, ilevel, masked, istatus)
1937 integer, intent(in) :: ilevel
1938 integer, intent(out) :: istatus
1939 real, intent(out) :: masked
1940 character (len=128), intent(in) :: fieldnm
1948 do idx=1,num_entries
1949 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1950 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
1951 (source_priority(idx) == ilevel)) then
1953 if (is_masked(idx)) then
1954 masked = source_masked(idx)
1961 end subroutine get_masked_value
1964 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1965 ! Name: get_max_levels
1967 ! Purpose: Returns the number of levels for the field given by fieldnm.
1968 ! The number of levels will generally be specified for continuous fields,
1969 ! whereas min/max category will generally be specified for categorical ones.
1970 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1971 subroutine get_max_levels(fieldnm, min_level, max_level, istatus)
1976 integer, intent(out) :: min_level, max_level, istatus
1977 character (len=128), intent(in) :: fieldnm
1981 logical :: have_found_field
1983 have_found_field = .false.
1986 do idx=1,num_entries
1987 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
1988 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
1990 if (is_dest_fieldtype(idx) .and. (source_dest_fieldtype(idx) /= CONTINUOUS)) then
1991 call mprintf(.true., WARN, 'In GEOGRID.TBL, destination field type for %s is '// &
1992 'not continuous and min/max levels specified.', s1=trim(fieldnm))
1994 if (.not. have_found_field) then
1995 if (is_tile_z_start(idx) .and. is_tile_z_end(idx)) then
1996 have_found_field = .true.
1998 min_level = source_tile_z_start(idx)
1999 max_level = source_tile_z_end(idx)
2000 else if (is_tile_z(idx)) then
2001 have_found_field = .true.
2004 max_level = source_tile_z(idx)
2007 if (.not. (is_tile_z_start(idx) .and. is_tile_z_end(idx))) then
2008 if (is_tile_z_start(idx) .or. is_tile_z_end(idx)) then
2009 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of tile_z_start '// &
2010 'and tile_z_end specified for entry %i.',i1=idx)
2014 if (is_tile_z_start(idx) .and. is_tile_z_end(idx)) then
2015 if (source_tile_z_start(idx) < min_level) min_level = source_tile_z_start(idx)
2016 if (source_tile_z_end(idx) > max_level) max_level = source_tile_z_end(idx)
2017 else if (is_tile_z(idx)) then
2018 if (min_level > 1) min_level = 1
2019 if (source_tile_z(idx) > max_level) max_level = source_tile_z(idx)
2022 if (.not. (is_tile_z_start(idx) .and. is_tile_z_end(idx))) then
2023 if (is_tile_z_start(idx) .or. is_tile_z_end(idx)) then
2024 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of tile_z_start '// &
2025 'and tile_z_end specified for entry %i.',i1=idx)
2033 end subroutine get_max_levels
2036 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2037 ! Name: get_source_levels
2039 ! Purpose: Return the min and max z-index for the source data for fieldname
2040 ! at a specified priority level (compared with the min/max level over
2041 ! all priority levels, as given by get_max_levels).
2042 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2043 subroutine get_source_levels(fieldnm, ilevel, min_level, max_level, istatus)
2048 integer, intent(in) :: ilevel
2049 integer, intent(out) :: min_level, max_level, istatus
2050 character (len=128), intent(in) :: fieldnm
2057 do idx=1,num_entries
2058 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2059 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2060 if (ilevel == source_priority(idx)) then
2062 if (is_tile_z_start(idx) .and. is_tile_z_end(idx)) then
2064 min_level = source_tile_z_start(idx)
2065 max_level = source_tile_z_end(idx)
2066 else if (is_tile_z(idx)) then
2069 max_level = source_tile_z(idx)
2072 if (.not. (is_tile_z_start(idx) .and. is_tile_z_end(idx))) then
2073 if (is_tile_z_start(idx) .or. is_tile_z_end(idx)) then
2074 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of tile_z_start '// &
2075 'and tile_z_end specified for entry %i.',i1=idx)
2083 end subroutine get_source_levels
2086 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2087 ! Name: get_max_categories
2089 ! Purpose: Returns the minimum category and the maximum category for the field
2091 ! Min/max category will generally be specified for categorical fields,
2092 ! whereas the number of levels will generally be specified for continuous
2094 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2095 subroutine get_max_categories(fieldnm, min_category, max_category, istatus)
2100 integer, intent(out) :: min_category, max_category, istatus
2101 character (len=128), intent(in) :: fieldnm
2105 logical :: have_found_field
2107 have_found_field = .false.
2110 do idx=1,num_entries
2111 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2112 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2114 if (is_dest_fieldtype(idx) .and. (source_dest_fieldtype(idx) /= CATEGORICAL)) then
2115 call mprintf(.true., WARN, &
2116 'In GEOGRID.TBL, cannot get min/max categories for continuous '// &
2117 'field %s at entry %i. Perhaps the user has requested to '// &
2118 'perform a strange operation on the field.', s1=trim(fieldnm), i1=idx)
2120 if (.not. have_found_field) then
2121 if (is_category_min(idx) .and. is_category_max(idx)) then
2122 have_found_field = .true.
2124 min_category = source_category_min(idx)
2125 max_category = source_category_max(idx)
2126 else if (is_category_min(idx) .or. is_category_max(idx)) then
2127 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of min_category and '// &
2128 'max_category specified for entry %i.',i1=idx)
2131 if (is_category_min(idx) .and. is_category_max(idx)) then
2132 if (source_category_min(idx) < min_category) min_category = source_category_min(idx)
2133 if (source_category_max(idx) > max_category) max_category = source_category_max(idx)
2134 else if (is_category_min(idx) .or. is_category_max(idx)) then
2135 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of min_category and '// &
2136 'max_category specified for entry %i.',i1=idx)
2143 end subroutine get_max_categories
2146 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2147 ! Name: get_source_categories
2149 ! Purpose: Return the min and max category for the source data for fieldname
2150 ! at a specified priority level (compared with the min/max category over
2151 ! all priority levels, as given by get_max_categories).
2152 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2153 subroutine get_source_categories(fieldnm, ilevel, min_category, max_category, istatus)
2158 integer, intent(in) :: ilevel
2159 integer, intent(out) :: min_category, max_category, istatus
2160 character (len=128), intent(in) :: fieldnm
2167 do idx=1,num_entries
2168 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2169 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2170 if (ilevel == source_priority(idx)) then
2172 if (is_category_min(idx) .and. is_category_max(idx)) then
2174 min_category = source_category_min(idx)
2175 max_category = source_category_max(idx)
2176 else if (is_category_min(idx) .or. is_category_max(idx)) then
2177 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of min_category '// &
2178 'and max_category specified for entry %i.',i1=idx)
2185 end subroutine get_source_categories
2188 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2189 ! Name: get_domcategory_name
2192 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2193 subroutine get_domcategory_name(fieldnm, domcat_name, ldominant_only, istatus)
2198 integer, intent(out) :: istatus
2199 logical, intent(out) :: ldominant_only
2200 character (len=128), intent(in) :: fieldnm
2201 character (len=128), intent(out) :: domcat_name
2207 ldominant_only = .false.
2209 do idx=1,num_entries
2210 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2211 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2213 if (is_dominant_category(idx)) then
2214 domcat_name = source_dominant_category(idx)
2216 if (is_dominant_only(idx)) then
2217 call mprintf(.true., WARN, 'In GEOGRID.TBL, both dominant_category and '// &
2218 'dominant_only are specified in entry %i. Using specification '// &
2219 'for dominant_category.',i1=idx)
2220 is_dominant_only(idx) = .false.
2224 else if (is_dominant_only(idx)) then
2225 domcat_name = source_dominant_only(idx)
2226 ldominant_only = .true.
2234 end subroutine get_domcategory_name
2237 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2238 ! Name: get_dfdx_name
2241 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2242 subroutine get_dfdx_name(fieldnm, dfdx_name, istatus)
2247 integer, intent(out) :: istatus
2248 character (len=128), intent(in) :: fieldnm
2249 character (len=128), intent(out) :: dfdx_name
2256 do idx=1,num_entries
2257 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2258 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2260 if (is_dfdx(idx)) then
2261 dfdx_name = source_dfdx(idx)
2269 end subroutine get_dfdx_name
2272 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2273 ! Name: get_dfdy_name
2276 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2277 subroutine get_dfdy_name(fieldnm, dfdy_name, istatus)
2282 integer, intent(out) :: istatus
2283 character (len=128), intent(in) :: fieldnm
2284 character (len=128), intent(out) :: dfdy_name
2291 do idx=1,num_entries
2292 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2293 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2295 if (is_dfdy(idx)) then
2296 dfdy_name = source_dfdy(idx)
2304 end subroutine get_dfdy_name
2307 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2308 ! Name: get_z_dim_name
2311 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2312 subroutine get_z_dim_name(fieldnm, z_dim, istatus)
2317 integer, intent(out) :: istatus
2318 character (len=128), intent(in) :: fieldnm
2319 character (len=128), intent(out) :: z_dim
2326 do idx=1,num_entries
2327 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2328 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2329 if (is_z_dim_name(idx)) then
2330 z_dim = source_z_dim_name(idx)
2337 end subroutine get_z_dim_name
2340 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2341 ! Name: get_field_scale_factor
2344 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2345 subroutine get_field_scale_factor(fieldnm, ilevel, scale_factor, istatus)
2350 integer, intent(in) :: ilevel
2351 integer, intent(out) :: istatus
2352 real, intent(out) :: scale_factor
2353 character (len=128), intent(in) :: fieldnm
2360 do idx=1,num_entries
2361 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2362 (len_trim(source_fieldname(idx)) == len_trim(fieldnm)) .and. &
2363 (ilevel == source_priority(idx))) then
2365 if (is_scale_factor(idx)) then
2366 scale_factor = source_scale_factor(idx)
2373 end subroutine get_field_scale_factor
2376 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2377 ! Name: get_output_stagger
2380 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2381 subroutine get_output_stagger(fieldnm, istagger, istatus)
2388 integer, intent(out) :: istatus, istagger
2389 character (len=128), intent(in) :: fieldnm
2395 do idx=1,num_entries
2396 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2397 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2399 if (is_output_stagger(idx)) then
2401 istagger = source_output_stagger(idx)
2404 if (gridtype == 'C') then
2408 else if (gridtype == 'E') then
2418 end subroutine get_output_stagger
2421 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2422 ! Name: get_subgrid_dim_name
2425 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2426 subroutine get_subgrid_dim_name(nest_num, field_name, dimnames, &
2427 sub_x, sub_y, istatus)
2432 integer, intent(in) :: nest_num
2433 integer, intent(out) :: sub_x, sub_y, istatus
2434 character(len=128), intent(in) :: field_name
2435 character(len=128), dimension(2), intent(inout) :: dimnames
2436 integer :: idx, nlen
2442 do idx=1,num_entries
2443 if ((index(source_fieldname(idx),trim(field_name)) /= 0) .and. &
2444 (len_trim(source_fieldname(idx)) == len_trim(field_name))) then
2445 if (is_subgrid(idx)) then
2447 if (is_output_stagger(idx)) then
2448 call mprintf(.true.,ERROR,'Cannot use subgrids on variables with staggered grids')
2450 dimnames(1) = trim(dimnames(1))//"_subgrid"
2451 dimnames(2) = trim(dimnames(2))//"_subgrid"
2452 sub_x = subgrid_ratio_x(nest_num)
2453 sub_y = subgrid_ratio_y(nest_num)
2458 end subroutine get_subgrid_dim_name
2461 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2462 ! Name: get_output_flag
2465 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2466 subroutine get_output_flag(fieldnm, output_flag, istatus)
2471 integer, intent(out) :: istatus
2472 character (len=*), intent(in) :: fieldnm
2473 character (len=128), intent(out) :: output_flag
2480 do idx=1,num_entries
2481 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2482 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2484 if (is_output_flag(idx)) then
2485 output_flag = source_output_flag(idx)
2493 end subroutine get_output_flag
2496 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2497 ! Name: get_interp_option
2500 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2501 subroutine get_interp_option(fieldnm, ilevel, interp_opt, istatus)
2506 integer, intent(in) :: ilevel
2507 integer, intent(out) :: istatus
2508 character (len=128), intent(in) :: fieldnm
2509 character (len=128), intent(out) :: interp_opt
2515 do idx=1,num_entries
2516 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2517 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2518 if (ilevel == source_priority(idx)) then
2520 interp_opt = source_interp_string(idx)
2528 end subroutine get_interp_option
2531 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2532 ! Name: get_gcel_threshold
2535 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2536 subroutine get_gcell_threshold(interp_opt, threshold, istatus)
2541 integer, intent(out) :: istatus
2542 real, intent(out) :: threshold
2543 character (len=128), intent(in) :: interp_opt
2546 integer :: i, p1, p2
2551 i = index(interp_opt,'average_gcell')
2553 ! Move the "average_gcell" option to the beginning
2558 ! Check for a threshold
2559 p1 = index(interp_opt(i:128),'(')
2560 p2 = index(interp_opt(i:128),')')
2561 if (p1 /= 0 .and. p2 /= 0) then
2562 read(interp_opt(p1+1:p2-1),*,err=1000) threshold
2564 call mprintf(.true., WARN, 'Problem with specified threshold '// &
2565 'for average_gcell interp option. Setting threshold to 0.0.')
2573 1000 call mprintf(.true., ERROR, 'Threshold option to average_gcell interpolator '// &
2574 'must be a real number, enclosed in parentheses immediately '// &
2575 'after keyword "average_gcell"')
2577 end subroutine get_gcell_threshold
2580 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2581 ! Name: get_smooth_option
2584 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2585 subroutine get_smooth_option(fieldnm, smooth_opt, smooth_passes, istatus)
2590 integer, intent(out) :: istatus, smooth_opt, smooth_passes
2591 character (len=128), intent(in) :: fieldnm
2598 do idx=1,num_entries
2599 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2600 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2602 if (is_smooth_option(idx)) then
2604 smooth_opt = source_smooth_option(idx)
2606 if (is_smooth_passes(idx)) then
2607 smooth_passes = source_smooth_passes(idx)
2618 end subroutine get_smooth_option
2621 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2622 ! Name: iget_fieldtype
2625 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2626 function iget_fieldtype(fieldnm, istatus)
2631 integer, intent(out) :: istatus
2632 character (len=128), intent(in) :: fieldnm
2638 integer :: iget_fieldtype
2642 do idx=1,num_entries
2643 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2644 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2646 if (is_dest_fieldtype(idx)) then
2647 iget_fieldtype = source_dest_fieldtype(idx)
2655 end function iget_fieldtype
2658 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2659 ! Name: iget_source_fieldtype
2661 ! Purpose: Given a resolution, in degrees, and the name of a field, this
2662 ! function returns the type (categorical, continuous, etc.) of the source
2663 ! data that will be used. This may, in general, depend on the field name
2664 ! and the resolution; for example, near 30 second resolution, land use data
2665 ! may come from a categorical field, whereas for lower resolutions, it may
2666 ! come from arrays of land use fractions for each category.
2667 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2668 function iget_source_fieldtype(fieldnm, ilevel, istatus)
2673 integer, intent(in) :: ilevel
2674 integer, intent(out) :: istatus
2675 character (len=128), intent(in) :: fieldnm
2678 integer :: iget_source_fieldtype
2683 ! Find information about the source tiles for the specified fieldname
2685 do idx=1,num_entries
2686 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2687 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2688 if (ilevel == source_priority(idx)) then
2690 iget_source_fieldtype = source_fieldtype(idx)
2696 end function iget_source_fieldtype
2699 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2700 ! Name: get_data_tile
2703 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2704 subroutine get_data_tile(xlat, xlon, ilevel, field_name, &
2705 file_name, array, start_x_dim, end_x_dim, start_y_dim, &
2706 end_y_dim, start_z_dim, end_z_dim, npts_bdr, &
2712 integer, intent(in) :: ilevel
2713 integer, intent(out) :: istatus
2714 integer, intent(out) :: start_x_dim, end_x_dim, &
2715 start_y_dim, end_y_dim, &
2716 start_z_dim, end_z_dim, &
2718 real, intent(in) :: xlat, xlon ! Location that tile should contain
2719 real, pointer, dimension(:,:,:) :: array ! The array to be allocated by this routine
2720 character (len=128), intent(in) :: field_name
2721 character (len=256), intent(out) :: file_name
2725 integer :: local_wordsize, local_endian, sign_convention, irow_order, strlen
2726 integer :: xdim,ydim,zdim
2728 real, allocatable, dimension(:) :: temprow
2730 call get_tile_fname(file_name, xlat, xlon, ilevel, field_name, istatus)
2732 if (index(file_name, 'OUTSIDE') /= 0) then
2735 else if (hash_search(bad_files, file_name)) then
2740 call get_tile_dimensions(xlat, xlon, start_x_dim, end_x_dim, start_y_dim, end_y_dim, &
2741 start_z_dim, end_z_dim, npts_bdr, local_wordsize, local_endian, &
2742 sign_convention, ilevel, field_name, istatus)
2744 xdim = (end_x_dim-start_x_dim+1)
2745 ydim = (end_y_dim-start_y_dim+1)
2746 zdim = (end_z_dim-start_z_dim+1)
2748 if (associated(array)) deallocate(array)
2749 allocate(array(xdim,ydim,zdim))
2751 call get_row_order(field_name, ilevel, irow_order, istatus)
2752 if (istatus /= 0) irow_order = BOTTOM_TOP
2754 call s_len(file_name,strlen)
2758 call read_geogrid(file_name, strlen, array, xdim, ydim, zdim, &
2759 sign_convention, local_endian, scalefac, local_wordsize, istatus)
2761 if (irow_order == TOP_BOTTOM) then
2762 allocate(temprow(xdim))
2765 if (ydim-j+1 <= j) exit
2766 temprow(1:xdim) = array(1:xdim,j,k)
2767 array(1:xdim,j,k) = array(1:xdim,ydim-j+1,k)
2768 array(1:xdim,ydim-j+1,k) = temprow(1:xdim)
2774 if (istatus /= 0) then
2775 start_x_dim = INVALID
2776 start_y_dim = INVALID
2780 call hash_insert(bad_files, file_name)
2783 end subroutine get_data_tile
2786 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2787 ! Name: get_row_order
2788 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2789 subroutine get_row_order(fieldnm, ilevel, irow_order, istatus)
2794 integer, intent(in) :: ilevel
2795 character (len=128), intent(in) :: fieldnm
2796 integer, intent(out) :: irow_order, istatus
2802 do idx=1,num_entries
2803 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2804 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2805 if (ilevel == source_priority(idx)) then
2806 if (is_row_order(idx)) then
2807 irow_order = source_row_order(idx)
2815 end subroutine get_row_order
2818 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2819 ! Name: get_tile_dimensions
2820 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2821 subroutine get_tile_dimensions(xlat, xlon, start_x_dim, end_x_dim, start_y_dim, end_y_dim, &
2822 start_z_dim, end_z_dim, npts_bdr, bytes_per_datum, endianness, &
2823 sign_convention, ilevel, fieldnm, istatus)
2830 integer, intent(in) :: ilevel
2831 integer, intent(out) :: start_x_dim, end_x_dim, &
2832 start_y_dim, end_y_dim, &
2833 start_z_dim, end_z_dim, &
2835 bytes_per_datum, endianness, &
2836 sign_convention, istatus
2837 real, intent(in) :: xlat, xlon
2838 character (len=128), intent(in) :: fieldnm
2841 integer :: idx, current_domain
2845 do idx=1,num_entries
2846 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
2847 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
2848 if (ilevel == source_priority(idx)) then
2855 if (istatus /= 0) then
2866 current_domain = iget_selected_domain()
2867 call select_domain(SOURCE_PROJ)
2868 call lltoxy(xlat, xlon, rx, ry, M)
2869 call select_domain(current_domain)
2871 start_x_dim = source_tile_x(idx) * nint(real(floor((rx-0.5) / real(source_tile_x(idx))))) + 1
2872 end_x_dim = start_x_dim + source_tile_x(idx) - 1
2874 start_y_dim = source_tile_y(idx) * nint(real(floor((ry-0.5) / real(source_tile_y(idx))))) + 1
2875 end_y_dim = start_y_dim + source_tile_y(idx) - 1
2877 if (is_tile_z_start(idx) .and. is_tile_z_end(idx)) then
2878 start_z_dim = source_tile_z_start(idx)
2879 end_z_dim = source_tile_z_end(idx)
2880 else if (is_tile_z(idx)) then
2882 end_z_dim = source_tile_z(idx)
2885 if (.not. (is_tile_z_start(idx) .and. is_tile_z_end(idx))) then
2886 if (is_tile_z_start(idx) .or. is_tile_z_end(idx)) then
2887 call mprintf(.true., ERROR, 'In GEOGRID.TBL, only one of tile_z_start and '// &
2888 'tile_z_end specified for entry %i.',i1=idx)
2892 if (is_tile_bdr(idx)) then
2893 npts_bdr = source_tile_bdr(idx)
2898 start_x_dim = start_x_dim - npts_bdr
2899 end_x_dim = end_x_dim + npts_bdr
2900 start_y_dim = start_y_dim - npts_bdr
2901 end_y_dim = end_y_dim + npts_bdr
2903 if (is_wordsize(idx)) then
2904 bytes_per_datum = source_wordsize(idx)
2907 call mprintf(.true.,ERROR,'In GEOGRID.TBL, no wordsize specified for data in entry %i.',i1=idx)
2910 if (is_endian(idx)) then
2911 endianness = source_endian(idx)
2913 endianness = BIG_ENDIAN
2916 if (is_signed(idx)) then
2922 end subroutine get_tile_dimensions
2925 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2926 ! Name: get_tile_fname
2929 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2930 subroutine get_tile_fname(test_fname, xlat, xlon, ilevel, fieldname, istatus)
2938 integer, intent(in) :: ilevel
2939 integer, intent(out) :: istatus
2940 real, intent(in) :: xlat, xlon
2941 character (len=*), intent(in) :: fieldname
2942 character (len=256), intent(out) :: test_fname
2945 integer :: current_domain, idx
2949 write(test_fname, '(a)') 'TILE.OUTSIDE.DOMAIN'
2951 do idx=1,num_entries
2952 if ((index(source_fieldname(idx),trim(fieldname)) /= 0) .and. &
2953 (len_trim(source_fieldname(idx)) == len_trim(fieldname))) then
2954 if (ilevel == source_priority(idx)) then
2961 if (istatus /= 0) return
2963 current_domain = iget_selected_domain()
2964 call select_domain(SOURCE_PROJ)
2965 call lltoxy(xlat, xlon, rx, ry, M)
2966 call select_domain(current_domain)
2968 ! rx = real(source_tile_x(idx)) * real(floor((rx-0.5*source_dx(idx))/ real(source_tile_x(idx)))) + 1.0
2969 ! ry = real(source_tile_y(idx)) * real(floor((ry-0.5*source_dy(idx))/ real(source_tile_y(idx)))) + 1.0
2970 rx = real(source_tile_x(idx)) * real(floor((rx-0.5) / real(source_tile_x(idx)))) + 1.0
2971 ry = real(source_tile_y(idx)) * real(floor((ry-0.5) / real(source_tile_y(idx)))) + 1.0
2973 if (rx > 0. .and. ry > 0.) then
2974 write(test_fname, '(a,i5.5,a1,i5.5,a1,i5.5,a1,i5.5)') trim(source_path(idx)), &
2975 nint(rx),'-',nint(rx)+source_tile_x(idx)-1,'.',nint(ry),'-',nint(ry)+source_tile_y(idx)-1
2978 end subroutine get_tile_fname
2981 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2982 ! Name: get_source_resolution
2985 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2986 subroutine get_source_resolution(fieldnm, ilevel, src_dx, src_dy, istatus)
2991 integer, intent(in) :: ilevel
2992 integer, intent(out) :: istatus
2993 real, intent(out) :: src_dx, src_dy
2994 character (len=*), intent(in) :: fieldnm
3000 do idx=1,num_entries
3001 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
3002 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
3003 if (ilevel == source_priority(idx)) then
3004 if (is_dx(idx) .and. is_dy(idx)) then
3005 src_dx = source_dx(idx)
3006 src_dy = source_dy(idx)
3007 if (source_proj(idx) /= PROJ_LATLON) then
3008 src_dx = src_dx / 111000.
3009 src_dy = src_dy / 111000.
3018 end subroutine get_source_resolution
3021 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3022 ! Name: get_data_projection
3024 ! Purpose: To acquire the parameters necessary in defining the grid on which
3025 ! the user-specified data for field 'fieldnm' are given.
3027 ! NOTES: If the routine successfully acquires values for all necessary
3028 ! parameters, istatus is set to 0. In case of an error,
3029 ! OR IF THE USER HAS NOT SPECIFIED A TILE OF DATA FOR FIELDNM,
3030 ! istatus is set to 1.
3031 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3032 subroutine get_data_projection(fieldnm, iproj, stand_lon, truelat1, truelat2, &
3033 dxkm, dykm, known_x, known_y, known_lat, known_lon, ilevel, istatus)
3038 integer, intent(in) :: ilevel
3039 integer, intent(out) :: iproj, istatus
3040 real, intent(out) :: stand_lon, truelat1, truelat2, dxkm, dykm, &
3041 known_x, known_y, known_lat, known_lon
3042 character (len=*), intent(in) :: fieldnm
3048 do idx=1,num_entries
3049 if ((index(source_fieldname(idx),trim(fieldnm)) /= 0) .and. &
3050 (len_trim(source_fieldname(idx)) == len_trim(fieldnm))) then
3051 if (ilevel == source_priority(idx)) then
3053 if (is_proj(idx)) then
3054 iproj = source_proj(idx)
3057 call mprintf(.true., ERROR, &
3058 'In GEOGRID.TBL, no specification for projection in entry %i.',i1=idx)
3060 if (is_known_x(idx)) then
3061 known_x = source_known_x(idx)
3064 call mprintf(.true., ERROR, &
3065 'In GEOGRID.TBL, no specification for known_x in entry %i.',i1=idx)
3067 if (is_known_y(idx)) then
3068 known_y = source_known_y(idx)
3071 call mprintf(.true., ERROR, &
3072 'In GEOGRID.TBL, no specification for known_y in entry %i.',i1=idx)
3074 if (is_known_lat(idx)) then
3075 known_lat = source_known_lat(idx)
3078 call mprintf(.true., ERROR, &
3079 'In GEOGRID.TBL, no specification for known_lat in entry %i.',i1=idx)
3081 if (is_known_lon(idx)) then
3082 known_lon = source_known_lon(idx)
3085 call mprintf(.true., ERROR, &
3086 'In GEOGRID.TBL, no specification for known_lon in entry %i.',i1=idx)
3088 if (is_truelat1(idx)) then
3089 truelat1 = source_truelat1(idx)
3090 else if (is_proj(idx) .and. source_proj(idx) /= PROJ_LATLON) then
3092 call mprintf(.true., WARN, &
3093 'In GEOGRID.TBL, no specification for truelat1 in entry %i.',i1=idx)
3095 if (is_truelat2(idx)) then
3096 truelat2 = source_truelat2(idx)
3097 else if (is_proj(idx) .and. source_proj(idx) /= PROJ_LATLON) then
3099 call mprintf(.true., WARN, &
3100 'In GEOGRID.TBL, no specification for truelat2 in entry %i.',i1=idx)
3102 if (is_stdlon(idx)) then
3103 stand_lon = source_stdlon(idx)
3104 else if (is_proj(idx) .and. source_proj(idx) /= PROJ_LATLON) then
3106 call mprintf(.true., WARN, &
3107 'In GEOGRID.TBL, no specification for stdlon in entry %i.',i1=idx)
3109 if (is_dx(idx)) then
3110 dxkm = source_dx(idx)
3113 call mprintf(.true., ERROR, &
3114 'In GEOGRID.TBL, no specification for dx in entry %i.',i1=idx)
3116 if (is_dy(idx)) then
3117 dykm = source_dy(idx)
3120 call mprintf(.true., ERROR, &
3121 'In GEOGRID.TBL, no specification for dy in entry %i.',i1=idx)
3128 end subroutine get_data_projection
3131 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3132 ! Name: check_data_specification
3134 ! Purpose: To check for obvious errors in the user source data specifications.
3135 ! Returns .true. if specification passes all checks, and .false. otherwise.
3136 ! For failing checks, diagnostic messages are printed.
3137 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3138 function check_data_specification( )
3143 logical :: check_data_specification
3146 integer :: i, j, istatus
3147 integer, pointer, dimension(:) :: priorities
3149 logical :: begin_priority, halt
3150 character (len=128) :: cur_name
3152 check_data_specification = .false.
3154 ! Check that each specification has a name, priority level, and path
3156 if (.not. is_fieldname(i)) then
3157 call mprintf(.true., ERROR, &
3158 'In GEOGRID.TBL, specification %i does not have a name.',i1=i)
3160 if (.not. is_priority(i)) then
3161 call mprintf(.true., ERROR, &
3162 'In GEOGRID.TBL, specification %i does not have a priority.',i1=i)
3164 if (list_length(source_res_path(i)) == 0) then
3165 call mprintf(.true., ERROR, &
3166 'In GEOGRID.TBL, no path (relative or absolute) is specified '// &
3167 'for entry %i.',i1=i)
3171 ! The fill_missing and halt_on_missing options are mutually exclusive
3173 call get_halt_on_missing(source_fieldname(i), halt, istatus)
3174 call get_missing_fill_value(source_fieldname(i), rmissing, istatus)
3175 if (halt .and. (istatus == 0)) then
3176 call mprintf(.true., ERROR, 'In GEOGRID.TBL, the halt_on_missing and fill_missing '// &
3177 'options are mutually exclusive, but both are given for field %s', &
3178 s1=trim(source_fieldname(i)))
3182 ! Check that the field from which landmask is calculated is not output on a staggering
3184 if (list_length(source_landmask_land(i)) > 0 .or. list_length(source_landmask_water(i)) > 0) then
3185 if (is_output_stagger(i)) then
3186 if (source_output_stagger(i) /= M) then
3187 call mprintf(.true., ERROR, 'In GEOGRID.TBL, landmask cannot be derived from '// &
3188 'a field that is computed on a staggered grid at entry %i.',i1=i)
3194 ! Also check that any field that is to be masked by the landmask is not output on a staggering
3196 if (is_masked(i) .and. is_output_stagger(i)) then
3197 if (source_output_stagger(i) /= M) then
3198 call mprintf(.true., ERROR, 'In GEOGRID.TBL, landmask cannot be used with '// &
3199 'a field that is computed on a staggered grid at entry %i.',i1=i)
3204 allocate(priorities(num_entries))
3206 ! Now check that priorities for each source are unique and in the interval [1,n], n <= num_entries
3209 cur_name = source_fieldname(i)
3211 if (source_fieldname(j) == cur_name) then
3213 if (source_priority(j) > num_entries .or. source_priority(j) < 1) then
3214 call mprintf(.true., ERROR, 'In GEOGRID.TBL, priorities for %s do not '// &
3215 'form a sequence 1,2,...,n.', s1=trim(cur_name))
3218 if (priorities(source_priority(j)) == 1) then
3219 call mprintf(.true., ERROR, 'In GEOGRID.TBL, more than one entry for %s '// &
3220 'has priority %i.', s1=trim(cur_name), i1=source_priority(j))
3223 priorities(source_priority(j)) = 1
3230 begin_priority = .false.
3231 do j=num_entries,1,-1
3232 if (.not.begin_priority .and. priorities(j) == 1) then
3233 begin_priority = .true.
3234 else if (begin_priority .and. priorities(j) == 0) then
3235 call mprintf(.true., ERROR, 'In GEOGRID.TBL, no entry for %s has '// &
3236 'priority %i, but an entry has priority %i.', &
3237 s1=trim(cur_name), i1=j, i2=j+1)
3242 deallocate(priorities)
3244 ! Units must match for all priority levels of a field
3246 if (source_priority(i) == 1) then
3248 if ((source_fieldname(i) == source_fieldname(j)) .and. &
3249 (source_units(i) /= source_units(j))) then
3250 call mprintf(.true., ERROR, 'In GEOGRID.TBL, units for %s at entry %i '// &
3251 'do not match units at entry %i (%s)', &
3252 s1=trim(source_fieldname(i)), i1=j, i2=i, s2=trim(source_units(i)))
3258 ! Make sure that user has not asked to calculate landmask from a continuous field
3260 if (is_dest_fieldtype(i)) then
3261 if (source_dest_fieldtype(i) == CONTINUOUS) then
3262 if (list_length(source_landmask_water(i)) > 0 .or. list_length(source_landmask_land(i)) > 0) then
3263 call mprintf(.true., ERROR, 'In GEOGRID.TBL, landmask cannot be '// &
3264 'calculated from a continuous destination field at entry %i.',i1=i)
3270 ! If either min_category or max_category is specified, then both must be specified
3272 if (is_category_min(i) .or. is_category_max(i)) then
3273 if (.not. is_category_min(i)) then
3274 call mprintf(.true., ERROR, 'In GEOGRID.TBL, for index file of data at '// &
3275 'entry %i, category_max is specified, but category_min is '// &
3276 'not. Both must be specified.',i1=i)
3277 else if (.not. is_category_max(i)) then
3278 call mprintf(.true., ERROR, 'In GEOGRID.TBL, for index file of data at '// &
3279 'entry %i, category_min is specified, but category_max is '// &
3280 'not. Both must be specified.',i1=i)
3285 ! For continuous data, (category_max - category_min + 1) should equal tile_z
3287 if (is_fieldtype(i)) then
3288 if (source_fieldtype(i) == CONTINUOUS) then
3289 if (is_category_max(i) .and. is_category_min(i) .and. is_tile_z(i)) then
3290 if (source_tile_z(i) /= (source_category_max(i) - source_category_min(i) + 1)) then
3291 call mprintf(.true., ERROR, 'In GEOGRID.TBL, tile_z must equal '// &
3292 '(category_max - category_min + 1) at entry %i.',i1=i)
3294 else if (is_category_max(i) .and. is_category_min(i) .and. &
3295 is_tile_z_start(i) .and. is_tile_z_end(i)) then
3296 if (source_tile_z_end(i) /= source_category_max(i) .or. &
3297 source_tile_z_start(i) /= source_category_min(i)) then
3298 call mprintf(.true., ERROR, 'In GEOGRID.TBL, tile_z_end must equal '// &
3299 'category_max, and tile_z_start must equal category_min '// &
3300 'at entry %i.',i1=i)
3307 ! Make sure that user has not named a dominant category or computed slope field
3308 ! the same as a fractional field
3310 if (source_dominant_category(i) == source_fieldname(i)) then
3311 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant category cannot have '// &
3312 'the same name as the field at entry %i.',i1=i)
3316 if (.not. is_dominant_only(i)) then
3317 if (is_dfdx(j)) then
3318 if (source_dfdx(j) == source_fieldname(i)) then
3319 call mprintf(.true., ERROR, 'In GEOGRID.TBL, field name at entry %i '// &
3320 'cannot have the same name as the slope field df_dx at entry %i.', &
3324 if (is_dfdy(j)) then
3325 if (source_dfdy(j) == source_fieldname(i)) then
3326 call mprintf(.true., ERROR, 'In GEOGRID.TBL, field name at entry %i '// &
3327 'cannot have the same name as the slope field df_dy at entry %i.', &
3331 if (is_dfdx(j) .and. is_dominant_category(i)) then
3332 if (source_dfdx(j) == source_dominant_category(i)) then
3333 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant field name at '// &
3334 'entry %i cannot have the same name as the slope field df_dx '// &
3335 'at entry %i.',i1=i, i2=j)
3338 if (is_dfdy(j) .and. is_dominant_category(i)) then
3339 if (source_dfdy(j) == source_dominant_category(i)) then
3340 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant field name at '// &
3341 'entry %i cannot have the same name as the slope field '// &
3342 'df_dy at entry %i.',i1=i, i2=j)
3346 if (is_dfdx(j)) then
3347 if (source_dfdx(j) == source_dominant_only(i)) then
3348 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant field name at '// &
3349 'entry %i cannot have the same name as the slope field '// &
3350 'df_dx at entry %i.',i1=i, i2=j)
3353 if (is_dfdy(j)) then
3354 if (source_dfdy(j) == source_dominant_only(i)) then
3355 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant field name at '// &
3356 'entry %i cannot have the same name as the slope field '// &
3357 'df_dy at entry %i.',i1=i, i2=j)
3362 if (is_dfdx(i)) then
3363 if (is_dfdx(j)) then
3364 if (source_dfdx(j) == source_dfdx(i)) then
3365 call mprintf(.true., ERROR, 'In GEOGRID.TBL, slope field df_dx at '// &
3366 'entry %i cannot have the same name as the slope '// &
3367 'field df_dx at entry %i.',i1=i, i2=j)
3370 if (is_dfdy(j)) then
3371 if (source_dfdy(j) == source_dfdx(i)) then
3372 call mprintf(.true., ERROR, 'In GEOGRID.TBL, slope field df_dx at '// &
3373 'entry %i cannot have the same name as the slope field '// &
3374 'df_dy at entry %i.',i1=i, i2=j)
3378 if (is_dfdy(i)) then
3379 if (is_dfdx(j)) then
3380 if (source_dfdx(j) == source_dfdy(i)) then
3381 call mprintf(.true., ERROR, 'In GEOGRID.TBL, slope field df_dy at '// &
3382 'entry %i cannot have the same name as the slope field '// &
3383 'df_dx at entry %i.',i1=i, i2=j)
3386 if (is_dfdy(j)) then
3387 if (source_dfdy(j) == source_dfdy(i)) then
3388 call mprintf(.true., ERROR, 'In GEOGRID.TBL, slope field df_dy at '// &
3389 'entry %i cannot have the same name as the slope field '// &
3390 'df_dy at entry %i.',i1=i, i2=j)
3394 if (is_dominant_category(i)) then
3395 if (source_dominant_category(i) == source_fieldname(j)) then ! Possible exception
3396 if (.not. (is_dominant_only(j) .and. (source_dominant_category(i) /= source_dominant_only(j)))) then
3397 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant category at '// &
3398 'entry %i cannot have the same name as the field at '// &
3399 'entry %i.',i1=i, i2=j)
3401 else if (is_dominant_category(j) .and. &
3402 (source_dominant_category(i) == source_dominant_category(j))) then
3403 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant category at entry '// &
3404 '%i cannot have the same name as dominant category at '// &
3405 'entry %i.',i1=i, i2=j)
3406 else if (is_dominant_only(j) .and. &
3407 (source_dominant_category(i) == source_dominant_only(j))) then
3408 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant category at '// &
3409 'entry %i cannot have the same name as dominant_only '// &
3410 'category at entry %i.',i1=i, i2=j)
3412 else if (is_dominant_only(i)) then
3413 if (source_dominant_only(i) == source_fieldname(j)) then ! Possible exception
3414 if (.not. (is_dominant_only(j) .and. (source_dominant_only(i) /= source_dominant_only(j)))) then
3415 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant_only category '// &
3416 'at entry %i cannot have the same name as the field at '// &
3417 'entry %i.',i1=i, i2=j)
3419 else if (is_dominant_category(j) .and. &
3420 (source_dominant_only(i) == source_dominant_category(j))) then
3421 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant_only category '// &
3422 'at entry %i cannot have the same name as dominant '// &
3423 'category at entry %i.',i1=i, i2=j)
3424 else if (is_dominant_only(j) .and. &
3425 (source_dominant_only(i) == source_dominant_only(j))) then
3426 call mprintf(.true., ERROR, 'In GEOGRID.TBL, dominant_only category '// &
3427 'at entry %i cannot have the same name as dominant_only '// &
3428 'category at entry %i.',i1=i, i2=j)
3435 check_data_specification = .true.
3436 end function check_data_specification
3439 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3442 ! Purpose: This routine receives a fortran string, and returns the number of
3443 ! characters in the string before the first "space" is encountered. It
3444 ! considers ascii characters 33 to 126 to be valid characters, and ascii
3445 ! 0 to 32, and 127 to be "space" characters.
3446 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3447 subroutine s_len(string, s_length)
3452 character (len=*), intent(in) :: string
3453 integer, intent(out) :: s_length
3456 integer :: i, len_str, aval
3461 len_str = len(string)
3463 do while ((i .le. len_str) .and. (.not. space))
3464 aval = ichar(string(i:i))
3465 if ((aval .lt. 33) .or. (aval .gt. 126)) then
3472 end subroutine s_len
3474 end module source_data_module