15 use version_control,
only : swb_version, git_commit_hash_string, &
16 git_branch_string, compile_date, &
17 compile_time, system_name
19 use iso_fortran_env,
only : output_unit, compiler_options, &
25 character (len=256) :: command_arg_str
26 character (len=256) :: temp_string, sub_string
27 character (len=70),
allocatable :: usage_string(:)
29 integer (c_int) :: inumargs
30 character (len=1024) :: scompilerflags
31 character (len=256) :: scompilerversion
32 character (len=256) :: sversionstring
33 character (len=256) :: sgithashstring
34 character (len=256) :: sprogramname
35 character (len=256) :: scompilationdatestring
36 character (len=256) :: scompilationsystemstring
37 character (len=:),
allocatable :: start_date_string
38 character (len=:),
allocatable :: end_date_string
39 integer (c_int) :: icount
40 integer (c_int) :: iindex
41 integer (c_int),
allocatable ::iindex_array(:)
42 integer (c_int) :: ilen
43 real (c_double) :: start_date_dbl
44 real (c_double) :: end_date_dbl
45 integer (c_int) :: time_bnds_varid
46 integer (c_int) :: month_index
48 logical (c_bool) :: netcdf_active =
false
55 allocate( swbstats%ncfile_in )
57 inumargs = command_argument_count()
59 sprogramname =
" SWB Statistics Calculator (SWBSTATS2), a companion to"
60 sversionstring =
" Soil Water Balance Code version "//trim( swb_version )
61 scompilationdatestring =
" compilation date : " &
62 //trim(compile_date)//
" "//trim(compile_time)
63 scompilationsystemstring =
" compiled on : "//trim(system_name)
65 if ( (system_name .containssimilar.
"Windows") &
66 .or. (system_name .containssimilar.
"Mingw") )
then
72 sgithashstring =
" Git branch and commit hash : " &
73 //trim( adjustl(git_branch_string ) ) &
74 //
", "//trim( git_commit_hash_string )
76 icount = max( len_trim( sversionstring ), len_trim( sgithashstring ) )
77 icount = max( icount, len_trim( scompilationsystemstring ) )
78 icount = max( icount, len_trim( sprogramname) )
80 write(unit=*, fmt=
"(/,a)") repeat(
"-",icount + 4)
81 write(unit=*, fmt=
"(a,/)") trim( sprogramname )
82 write(unit=*,fmt=
"(a,/)") trim( sversionstring )
83 write(unit=*,fmt=
"(a)") trim( scompilationdatestring )
84 write(unit=*,fmt=
"(a)") trim( scompilationsystemstring )
85 write(unit=*,fmt=
"(a)") trim( sgithashstring )
86 write(unit=*, fmt=
"(a,/)") repeat(
"-",icount + 4)
88 if(inumargs == 0 )
then
91 scompilerflags = compiler_options()
92 scompilerversion = compiler_version()
93 write(unit=*,fmt=
"(a,/)")
"Compiled with: gfortran ("//trim(scompilerversion)//
")"
94 write(unit=*,fmt=
"(a)")
"Compiler flags:"
95 write(unit=*,fmt=
"(a)")
"-------------------------------"
96 write(unit=*,fmt=
"(a,/)") trim(scompilerflags)
99#ifdef __INTEL_COMPILER
100 write(unit=*,fmt=
"(a)")
"Compiled with: Intel Fortran version " &
102 write(unit=*,fmt=
"(a,/)")
"Compiler build date:"//trim(
ascharacter(__intel_compiler_build_date))
105 allocate(usage_string(50))
108 "usage: swbstats2 [options] netcdf_file_name ", &
112 " [ --output_prefix= ] ", &
113 " text to place in front of the default output filename(s) ", &
114 " [ --annual_statistics ] ", &
115 " calculate statistics for every calendar year between start and end", &
116 " [ --monthly_statistics ] ", &
117 " calculate statistics for every month between start and end ", &
118 " [ --daily_statistics ] ", &
119 " calculate statistics for every day between start and end ", &
120 " [ --annualize_sums ] ", &
121 " express sums on an annual basis (e.g. inches per year) ", &
122 " [ --report_as_volume ] ", &
123 " express statistics as a volume (cubic meters) ", &
124 " [ --report_in_meters ] ", &
125 " express output statistics in *meters* ", &
127 " dates over which statistics should be calculated, ", &
128 " with start date and end date formatted as yyyy-mm-dd,yyyy-mm-dd ", &
129 " [ --stress_period_file= ] ", &
130 " comma-delimited file containing stress period start and ", &
131 " end date, with header labels and comments starting with'#': ", &
132 " id,start_date,end_date ", &
133 " #2,1870-01-01,1898-12-31 ", &
134 " 5,1920-01-01,1925-12-31 ", &
135 " 6,1925-01-01,1930-12-31 ", &
136 " [ --comparison_scale_factor= ] ", &
137 " value to multiply comparison grid by before calculating statistics", &
138 " [ --comparison_grid= ] ", &
139 " name of real-valued grid to compare SWB output against ", &
140 " [ --comparison_period_file= ] ", &
141 " comma-delimited file containing comparison period start and ", &
142 " end date, with header labels and comments starting with'#': ", &
143 " id,start_date,end_date,comparison_grid_filename ", &
144 " #2,1870-01-01,1898-12-31,comparison_file_period_2.asc ", &
145 " 5,1920-01-01,1925-12-31,comparison_file_period_5.asc ", &
146 " 6,1925-01-01,1930-12-31,comparison_file_period_6.asc ", &
147 " [ --zone_grid= ] ", &
148 " name of integer-valued grid for which zonal statistics are desired", &
149 " [ --zone_period_file= ] ", &
150 " comma-delimited file containing calculation period start and ", &
151 " end date, with header labels and comments starting with'#': ", &
152 " id,start_date,end_date,zone_grid_filename ", &
153 " #2,1870-01-01,1898-12-31,zone_grid_file_period_2.asc ", &
154 " 5,1920-01-01,1925-12-31,zone_grid_file_period_5.asc ", &
155 " 6,1925-01-01,1930-12-31,zone_grid_file_period_6.asc ", &
156 " [ --{no_}netcdf_output ] ", &
157 " toggle whether netCDF file is target for gridded output ", &
158 " [ --{no_}arcgrid_output ] ", &
159 " toggle whether an ASCII Arc Grid is target for gridded output " &
162 do iindex=1,ubound(usage_string,1)
163 write(unit=*, fmt=
"(a)") trim(usage_string(iindex))
173 call swbstats%slice_start_date%setDateFormat(
"YYYY-MM-DD")
174 call swbstats%slice_end_date%setDateFormat(
"YYYY-MM-DD")
175 swbstats%filename_modifier_string =
""
177 do iindex=1, inumargs
179 call get_command_argument( iindex, command_arg_str )
181 if ( command_arg_str .containssimilar.
"comparison_scale_factor" )
then
183 sub_string =
right(command_arg_str, substring=
"=")
184 swbstats%comparison_grid_conversion_factor =
asfloat(sub_string)
186 elseif ( command_arg_str .containssimilar.
"output_prefix" )
then
188 sub_string =
right(command_arg_str, substring=
"=")
189 swbstats%output_file_prefix = trim(sub_string)
191 elseif ( command_arg_str .containssimilar.
"annual_statistics" )
then
194 swbstats%filename_modifier_string =
"YEARLY"
196 elseif ( command_arg_str .containssimilar.
"daily_statistics" )
then
199 swbstats%filename_modifier_string =
"DAILY"
201 elseif ( command_arg_str .containssimilar.
"monthly_statistics" )
then
204 swbstats%filename_modifier_string =
"MONTHLY"
206 elseif ( command_arg_str .containssimilar.
"dump_options" )
then
208 swbstats%dump_options_to_screen =
true
210 elseif ( command_arg_str .containssimilar.
"report_as_volume" )
then
212 swbstats%report_as_volume =
true
214 elseif ( command_arg_str .containssimilar.
"report_in_meters" )
then
216 swbstats%report_in_meters =
true
218 elseif ( command_arg_str .containssimilar.
"annualize_sums" )
then
220 swbstats%annualize_stats =
true
222 elseif ( command_arg_str .containssimilar.
"stress_period_file" )
then
225 swbstats%stress_period_filename =
right(command_arg_str, substring=
"=")
226 call swbstats%read_date_range_file( &
227 csv_filename=swbstats%stress_period_filename, &
228 date_range_id_list=swbstats%date_range_id_list, &
229 start_date_list=swbstats%start_date_list, &
230 end_date_list=swbstats%end_date_list )
231 swbstats%filename_modifier_string =
"STRESS_PERIOD_STATS"
233 elseif ( command_arg_str .containssimilar.
"zone_period_file" )
then
236 swbstats%multiple_zone_grids =
true
237 swbstats%calc_zonal_stats =
true
238 swbstats%write_csv =
true
240 swbstats%zone_period_filename =
right(command_arg_str, substring=
"=")
241 call swbstats%read_zone_period_file( &
242 csv_filename=swbstats%zone_period_filename , &
243 date_range_id_list=swbstats%date_range_id_list, &
244 start_date_list=swbstats%start_date_list, &
245 end_date_list=swbstats%end_date_list, &
246 zonal_stats_grid_file_list=swbstats%zone_grid_file_list )
248 elseif ( command_arg_str .containssimilar.
"comparison_period_file" )
then
251 swbstats%multiple_comparison_grids =
true
252 swbstats%compare_to_obs_values =
true
253 swbstats%write_csv =
true
254 swbstats%filename_modifier_string =
"COMPARISON_PERIOD_STATS"
256 swbstats%comparison_period_filename =
right(command_arg_str, substring=
"=")
257 call swbstats%read_comparison_period_file( &
258 csv_filename=swbstats%comparison_period_filename, &
259 date_range_id_list=swbstats%date_range_id_list, &
260 start_date_list=swbstats%start_date_list, &
261 end_date_list=swbstats%end_date_list, &
262 comparison_grid_file_list=swbstats%comparison_grid_file_list )
264 elseif ( command_arg_str .containssimilar.
"slice" )
then
266 sub_string =
right(command_arg_str, substring=
"=")
267 start_date_string =
left(sub_string, substring=
",")
268 end_date_string =
right(sub_string, substring=
",")
272 call swbstats%slice_start_date%parseDate(start_date_string)
273 call swbstats%slice_start_date%calcGregorianDate()
275 call swbstats%slice_end_date%parseDate(end_date_string)
276 call swbstats%slice_end_date%calcGregorianDate()
277 swbstats%filename_modifier_string =
"SLICE_STATS--" &
278 //swbstats%slice_start_date%prettydate()//
"_to_" &
279 //swbstats%slice_end_date%prettydate()
281 elseif ( command_arg_str .containssimilar.
"zone_grid=" )
then
283 swbstats%zone_grid_filename =
right(command_arg_str, substring=
"=")
284 swbstats%calc_zonal_stats =
true
285 swbstats%write_csv =
true
287 elseif ( command_arg_str .containssimilar.
"zone_grid2=" )
then
289 swbstats%zone_grid2_filename =
right(command_arg_str, substring=
"=")
290 swbstats%calc_zonal_stats =
true
291 swbstats%write_csv =
true
293 elseif ( command_arg_str .containssimilar.
"comparison_grid" )
then
295 swbstats%comparison_grid_filename =
right(command_arg_str, substring=
"=")
296 swbstats%compare_to_obs_values =
true
297 swbstats%write_csv =
true
299 elseif ( command_arg_str .strapprox.
"--netcdf_output")
then
303 elseif ( command_arg_str .strapprox.
"--no_netcdf_output" )
then
307 elseif ( command_arg_str .strapprox.
"--arcgrid_output" )
then
311 elseif ( command_arg_str .strapprox.
"--no_arcgrid_output" )
then
315 elseif ( command_arg_str .contains.
"--" )
then
318 print *,
"Unknown swbstats2 option: "//
squote(command_arg_str)//
"."
324 swbstats%netcdf_input_filename = trim(command_arg_str)
327 swbstats%netcdf_input_filename, &
328 guess_z_var_name=
true )
331 start_date_dbl = real( swbstats%ncfile_in%iFirstDayJD, c_double )
332 end_date_dbl = real( swbstats%ncfile_in%iLastDayJD, c_double )
335 call swbstats%data_start_date%setJulianDate(start_date_dbl)
336 call swbstats%data_start_date%calcGregorianDate()
337 call swbstats%data_end_date%setJulianDate(end_date_dbl)
338 call swbstats%data_end_date%calcGregorianDate()
340 swbstats%netcdf_input_file_is_open =
true
346 if (.not. swbstats%netcdf_input_file_is_open) &
347 stop(
"No netCDF file was specified or there was an error opening the file.")
355 variable_name=
"crs", &
356 attribute_name_list=name_list, &
357 attribute_value_list=value_list )
360 iindex_array = name_list%which(
"proj4_string")
361 temp_string = value_list%get( iindex_array(1) )
362 swbstats%target_proj4_string = trim(temp_string)
364 swbstats%netcdf_variable_name_string = trim(swbstats%ncfile_in%pNC_VAR(
nc_z)%sVariableName)
368 ncfile=swbstats%ncfile_in, &
369 variable_name=swbstats%netcdf_variable_name_string, &
370 attribute_name_list=name_list, &
371 attribute_value_list=value_list )
374 iindex_array = name_list%which(
"units")
375 swbstats%netcdf_variable_units_string = value_list%get( iindex_array(1) )
378 call swbstats%create_working_grids()
380 call rstat%initialize(nx=swbstats%ncfile_in%iNX, &
381 ny=swbstats%ncfile_in%iNY, &
382 x0=swbstats%ncfile_in%rX(0), &
383 y0=swbstats%ncfile_in%rY(0), &
384 x1=swbstats%ncfile_in%rX(1), &
385 y1=swbstats%ncfile_in%rY(1), &
386 nodata_value=-9999._c_double)
392 call swbstats%create_date_list_for_annual_statistics()
396 call swbstats%create_date_list_for_monthly_statistics()
397 call swbstats%create_monthly_working_grids()
402 call mon_stat(month_index)%initialize(nx=swbstats%ncfile_in%iNX, &
403 ny=swbstats%ncfile_in%iNY, &
404 x0=swbstats%ncfile_in%rX(0), &
405 y0=swbstats%ncfile_in%rY(0), &
406 x1=swbstats%ncfile_in%rX(1), &
407 y1=swbstats%ncfile_in%rY(1), &
408 nodata_value=-9999._c_double)
414 call swbstats%create_date_list_for_daily_statistics()
418 if (swbstats%report_in_meters)
then
421 if (swbstats%netcdf_variable_units_string .containssimilar.
"inch")
then
422 swbstats%unit_conversion_factor = 0.0254_c_double
423 elseif (swbstats%netcdf_variable_units_string .containssimilar.
"cm")
then
424 swbstats%unit_conversion_factor = 0.01_c_double
425 elseif (swbstats%netcdf_variable_units_string .containssimilar.
"mm")
then
426 swbstats%unit_conversion_factor = 0.001_c_double
428 call die(
"Was attempting to determine the output unit conversion factor," &
429 //
" but the netCDF variable has units of " &
430 //
squote(swbstats%netcdf_variable_units_string)//
", which cannot" &
431 //
" be converted to units of 'meters'.")
434 swbstats%filename_modifier_string = trim(swbstats%filename_modifier_string) &
440 if (swbstats%report_as_volume)
then
442 if (swbstats%report_as_volume)
then
443 if (swbstats%target_proj4_string .containssimilar.
"units=m")
then
444 swbstats%length_conversion_factor = 1.0_c_double
445 elseif (swbstats%target_proj4_string .containssimilar.
"units=us-ft")
then
446 swbstats%length_conversion_factor = 0.3048006096012192_c_double
447 elseif (swbstats%target_proj4_string .containssimilar.
"units=ft")
then
448 swbstats%length_conversion_factor = 0.3048_c_double
450 call die(
"Was attempting to define length conversion factor, but no units " &
451 //
"information found in input PROJ4 string.")
453 swbstats%grid_cell_area_sq_meters = (swbstats%grd_native%rGridCellSize &
454 * swbstats%length_conversion_factor)**2
455 swbstats%output_conversion_factor = swbstats%grid_cell_area_sq_meters &
456 * swbstats%unit_conversion_factor
458 swbstats%output_conversion_factor = swbstats%unit_conversion_factor
461 swbstats%filename_modifier_string = trim(swbstats%filename_modifier_string) &
466 call assert(.not. (swbstats%report_as_volume .and. swbstats%report_in_meters), &
467 "Cannot use '--report_as_volume' and '--report_in_meters' in the same" &
470 if (swbstats%compare_to_obs_values)
then
471 call swbstats%initialize_comparison_grid(grid_filename=swbstats%comparison_grid_filename)
477 if ( swbstats%slice_start_date < swbstats%data_start_date ) &
478 swbstats%slice_start_date = swbstats%data_start_date
479 if ( swbstats%slice_end_date > swbstats%data_end_date ) &
480 swbstats%slice_end_date = swbstats%data_end_date
482 call sim_dt%initialize( swbstats%slice_start_date, swbstats%slice_end_date )
483 call swbstats%create_date_list_for_period_statistics( swbstats%slice_start_date, swbstats%slice_end_date )
489 call sim_dt%initialize( swbstats%data_start_date, swbstats%data_end_date )
490 call swbstats%create_date_list_for_period_statistics( swbstats%data_start_date, swbstats%data_end_date )
493 call sim_dt%initialize( swbstats%data_start_date, swbstats%data_end_date )
497 if (swbstats%calc_zonal_stats)
then
498 if (.not. swbstats%multiple_zone_grids)
then
499 call swbstats%initialize_zone_grid(grid_filename=swbstats%zone_grid_filename)
500 call swbstats%get_unique_int(swbstats%grd_zone%pGrdBase%iData, swbstats%unique_zone_list)
502 if (len_trim(swbstats%zone_grid2_filename) > 0)
then
503 call swbstats%initialize_secondary_zone_grid(grid_filename=swbstats%zone_grid2_filename)
504 call swbstats%get_unique_int(swbstats%grd_zone2%pGrdBase%iData, swbstats%unique_zone2_list)
509 if (
allocated( swbstats%output_file_prefix) )
then
510 temp_string = trim(swbstats%output_file_prefix)//
"__zonal_stats__"//trim(swbstats%netcdf_variable_name_string)//
".csv"
512 temp_string =
"zonal_stats__"//trim(swbstats%netcdf_variable_name_string)//
".csv"
515 call swbstats%open_zonal_stats_output_file(trim(temp_string))
521 swbstats%date_range_string = swbstats%data_start_date%prettydate() &
522 //
"_to_"//swbstats%data_end_date%prettydate()
528 if (swbstats%dump_options_to_screen)
call swbstats%print_all_options()
563 do iindex=1, swbstats%date_range_id_list%count
566 call swbstats%slice_start_date%setDateFormat(
"YYYY-MM-DD")
567 call swbstats%slice_end_date%setDateFormat(
"YYYY-MM-DD")
571 start_date_string = swbstats%start_date_list%get( iindex )
572 end_date_string = swbstats%end_date_list%get( iindex )
575 call swbstats%slice_start_date%parseDate( start_date_string )
576 call swbstats%slice_end_date%parseDate( end_date_string )
579 swbstats%slice_range_string = swbstats%slice_start_date%prettydate() &
580 //
"_to_"//swbstats%slice_end_date%prettydate()
582 write(*,fmt=
"(a)")
""
583 write(*,fmt=
"(a)")
"Processing slice: ", swbstats%slice_start_date%prettydate() &
584 //
" to "//swbstats%slice_end_date%prettydate()
585 write(*,fmt=
"(a)") repeat(
"-", 70)
591 call swbstats%calculate_slice_statistics( start_date=swbstats%slice_start_date, &
592 end_date=swbstats%slice_end_date, &
601 call swbstats%calculate_monthly_statistics(month_num=swbstats%slice_start_date%iMonth, finalize=
false)
604 if (swbstats%multiple_comparison_grids)
then
605 swbstats%comparison_grid_filename = swbstats%comparison_grid_file_list%get( iindex )
606 call swbstats%initialize_comparison_grid(grid_filename=swbstats%comparison_grid_filename)
609 if (swbstats%multiple_zone_grids)
then
610 swbstats%zone_grid_filename = swbstats%zone_grid_file_list%get( iindex )
611 call swbstats%initialize_zone_grid(grid_filename=swbstats%zone_grid_filename)
615 start_date=swbstats%slice_start_date, &
616 end_date=swbstats%slice_end_date)
619 start_date=swbstats%slice_start_date, &
620 end_date=swbstats%slice_end_date, &
621 date_range_string=swbstats%slice_range_string, &
622 output_file_prefix=swbstats%output_file_prefix)
624 if (swbstats%calc_zonal_stats)
then
625 if ( len_trim(swbstats%zone_grid2_filename) > 0)
then
627 if (
associated(swbstats%grd_comparison) )
then
629 call swbstats%output_zonal_stats( &
630 start_date=swbstats%slice_start_date, &
631 end_date=swbstats%slice_end_date, &
633 zone_ids=swbstats%grd_zone%pGrdBase%iData, &
634 unique_zone_list=swbstats%unique_zone_list, &
635 zone2_ids=swbstats%grd_zone2%pGrdBase%iData, &
636 unique_zone2_list=swbstats%unique_zone2_list, &
637 comparison_values=swbstats%grd_comparison%pGrdBase%dpData, &
638 funit=swbstats%zonal_stats_output_file%unit() )
641 call swbstats%output_zonal_stats( &
642 start_date=swbstats%slice_start_date, &
643 end_date=swbstats%slice_end_date, &
645 zone_ids=swbstats%grd_zone%pGrdBase%iData, &
646 unique_zone_list=swbstats%unique_zone_list, &
647 zone2_ids=swbstats%grd_zone2%pGrdBase%iData, &
648 unique_zone2_list=swbstats%unique_zone2_list, &
649 funit=swbstats%zonal_stats_output_file%unit() )
654 if (
associated(swbstats%grd_comparison) )
then
655 call swbstats%output_zonal_stats( &
656 start_date=swbstats%slice_start_date, &
657 end_date=swbstats%slice_end_date, &
659 zone_ids=swbstats%grd_zone%pGrdBase%iData, &
660 unique_zone_list=swbstats%unique_zone_list, &
661 comparison_values=swbstats%grd_comparison%pGrdBase%dpData, &
662 funit=swbstats%zonal_stats_output_file%unit() )
665 call swbstats%output_zonal_stats( &
666 start_date=swbstats%slice_start_date, &
667 end_date=swbstats%slice_end_date, &
669 zone_ids=swbstats%grd_zone%pGrdBase%iData, &
670 unique_zone_list=swbstats%unique_zone_list, &
671 funit=swbstats%zonal_stats_output_file%unit() )
686 call swbstats%calculate_monthly_statistics(month_num=swbstats%slice_start_date%iMonth, finalize=
true)
688 date_range_string=swbstats%date_range_string, &
689 output_file_prefix=swbstats%output_file_prefix)
692 if (swbstats%write_csv)
call swbstats%zonal_stats_output_file%close()
696 if (swbstats%dump_options_to_screen)
call swbstats%print_all_options()
This module contains physical constants and convenience functions aimed at performing unit conversion...
logical(c_bool), parameter, public true
character(len=1) os_native_path_delimiter
type(bounds_t), public bnds
logical(c_bool), parameter, public false
integer(c_int), parameter datatype_float
integer(c_int), parameter datatype_int
This module contains the DATETIME_T class and associated time and date-related routines,...
subroutine, public die(smessage, smodule, iline, shints, scalledby, icalledbyline)
Provides support for input and output of gridded ASCII data, as well as for creation and destruction ...
Provide support for use of netCDF files as input for time-varying, gridded meteorlogic data,...
subroutine, public netcdf_get_attribute_list_for_variable(ncfile, variable_name, attribute_name_list, attribute_value_list)
subroutine, public netcdf_open_and_prepare_for_merging(ncfile, sfilename, guess_z_var_name)
integer(c_int), parameter, public nc_z
type(date_range_t), public sim_dt
type(running_stats_t) rstat
type(file_collection_t), dimension(39) output_files
type(running_stats_t), dimension(12) mon_stat
@ calc_period_slice_single
@ calc_period_slice_multiple