14 use version_control,
only : swb_version, git_commit_hash_string, &
15 git_branch_string, compile_date, &
16 compile_time, system_name
18 use iso_fortran_env,
only : output_unit, compiler_options, &
24 character (len=256) :: command_arg_str
25 character (len=256) :: temp_string, sub_string
26 character (len=70),
allocatable :: usage_string(:)
28 integer (c_int) :: inumargs
29 character (len=256) :: sversionstring
30 character (len=256) :: sgithashstring
31 character (len=256) :: sprogramname
32 character (len=256) :: scompilationdatestring
33 character (len=256) :: scompilationsystemstring
34 character (len=:),
allocatable :: start_date_string
35 character (len=:),
allocatable :: end_date_string
36 integer (c_int) :: icount
37 integer (c_int) :: iindex
38 integer (c_int),
allocatable ::iindex_array(:)
39 real (c_double) :: start_date_dbl
40 real (c_double) :: end_date_dbl
41 integer (c_int) :: month_index
49 allocate( swbstats%ncfile_in )
51 inumargs = command_argument_count()
53 sprogramname =
" SWB Statistics Calculator (SWBSTATS2), a companion to"
54 sversionstring =
" Soil Water Balance Code version "//trim( swb_version )
55 scompilationdatestring =
" compilation date : " &
56 //trim(compile_date)//
" "//trim(compile_time)
57 scompilationsystemstring =
" compiled on : "//trim(system_name)
59 if ( (system_name .containssimilar.
"Windows") &
60 .or. (system_name .containssimilar.
"Mingw") )
then
66 sgithashstring =
" Git branch and commit hash : " &
67 //trim( adjustl(git_branch_string ) ) &
68 //
", "//trim( git_commit_hash_string )
70 icount = max( len_trim( sversionstring ), len_trim( sgithashstring ) )
71 icount = max( icount, len_trim( scompilationsystemstring ) )
72 icount = max( icount, len_trim( sprogramname) )
74 write(unit=*, fmt=
"(/,a)") repeat(
"-",icount + 4)
75 write(unit=*, fmt=
"(a,/)") trim( sprogramname )
76 write(unit=*,fmt=
"(a,/)") trim( sversionstring )
77 write(unit=*,fmt=
"(a)") trim( scompilationdatestring )
78 write(unit=*,fmt=
"(a)") trim( scompilationsystemstring )
79 write(unit=*,fmt=
"(a)") trim( sgithashstring )
80 write(unit=*, fmt=
"(a,/)") repeat(
"-",icount + 4)
82 if(inumargs == 0 )
then
85 scompilerflags = compiler_options()
86 scompilerversion = compiler_version()
87 write(unit=*,fmt=
"(a,/)")
"Compiled with: gfortran ("//trim(scompilerversion)//
")"
88 write(unit=*,fmt=
"(a)")
"Compiler flags:"
89 write(unit=*,fmt=
"(a)")
"-------------------------------"
90 write(unit=*,fmt=
"(a,/)") trim(scompilerflags)
93#ifdef __INTEL_COMPILER
94 write(unit=*,fmt=
"(a)")
"Compiled with: Intel Fortran version " &
96 write(unit=*,fmt=
"(a,/)")
"Compiler build date:"//trim(
ascharacter(__intel_compiler_build_date))
99 allocate(usage_string(50))
102 "usage: swbstats2 [options] netcdf_file_name ", &
106 " [ --output_prefix= ] ", &
107 " text to place in front of the default output filename(s) ", &
108 " [ --annual_statistics ] ", &
109 " calculate statistics for every calendar year between start and end", &
110 " [ --monthly_statistics ] ", &
111 " calculate statistics for every month between start and end ", &
112 " [ --daily_statistics ] ", &
113 " calculate statistics for every day between start and end ", &
114 " [ --annualize_sums ] ", &
115 " express sums on an annual basis (e.g. inches per year) ", &
116 " [ --report_as_volume ] ", &
117 " express statistics as a volume (cubic meters) ", &
118 " [ --report_in_meters ] ", &
119 " express output statistics in *meters* ", &
121 " dates over which statistics should be calculated, ", &
122 " with start date and end date formatted as yyyy-mm-dd,yyyy-mm-dd ", &
123 " [ --stress_period_file= ] ", &
124 " comma-delimited file containing stress period start and ", &
125 " end date, with header labels and comments starting with'#': ", &
126 " id,start_date,end_date ", &
127 " #2,1870-01-01,1898-12-31 ", &
128 " 5,1920-01-01,1925-12-31 ", &
129 " 6,1925-01-01,1930-12-31 ", &
130 " [ --comparison_scale_factor= ] ", &
131 " value to multiply comparison grid by before calculating statistics", &
132 " [ --comparison_grid= ] ", &
133 " name of real-valued grid to compare SWB output against ", &
134 " [ --comparison_period_file= ] ", &
135 " comma-delimited file containing comparison period start and ", &
136 " end date, with header labels and comments starting with'#': ", &
137 " id,start_date,end_date,comparison_grid_filename ", &
138 " #2,1870-01-01,1898-12-31,comparison_file_period_2.asc ", &
139 " 5,1920-01-01,1925-12-31,comparison_file_period_5.asc ", &
140 " 6,1925-01-01,1930-12-31,comparison_file_period_6.asc ", &
141 " [ --zone_grid= ] ", &
142 " name of integer-valued grid for which zonal statistics are desired", &
143 " [ --zone_period_file= ] ", &
144 " comma-delimited file containing calculation period start and ", &
145 " end date, with header labels and comments starting with'#': ", &
146 " id,start_date,end_date,zone_grid_filename ", &
147 " #2,1870-01-01,1898-12-31,zone_grid_file_period_2.asc ", &
148 " 5,1920-01-01,1925-12-31,zone_grid_file_period_5.asc ", &
149 " 6,1925-01-01,1930-12-31,zone_grid_file_period_6.asc ", &
150 " [ --{no_}netcdf_output ] ", &
151 " toggle whether netCDF file is target for gridded output ", &
152 " [ --{no_}arcgrid_output ] ", &
153 " toggle whether an ASCII Arc Grid is target for gridded output " &
156 do iindex=1,ubound(usage_string,1)
157 write(unit=*, fmt=
"(a)") trim(usage_string(iindex))
167 call swbstats%slice_start_date%setDateFormat(
"YYYY-MM-DD")
168 call swbstats%slice_end_date%setDateFormat(
"YYYY-MM-DD")
169 swbstats%filename_modifier_string =
""
171 do iindex=1, inumargs
173 call get_command_argument( iindex, command_arg_str )
175 if ( command_arg_str .containssimilar.
"comparison_scale_factor" )
then
177 sub_string =
right(command_arg_str, substring=
"=")
178 swbstats%comparison_grid_conversion_factor =
asfloat(sub_string)
180 elseif ( command_arg_str .containssimilar.
"output_prefix" )
then
182 sub_string =
right(command_arg_str, substring=
"=")
183 swbstats%output_file_prefix = trim(sub_string)
185 elseif ( command_arg_str .containssimilar.
"annual_statistics" )
then
188 swbstats%filename_modifier_string =
"YEARLY"
190 elseif ( command_arg_str .containssimilar.
"daily_statistics" )
then
193 swbstats%filename_modifier_string =
"DAILY"
195 elseif ( command_arg_str .containssimilar.
"monthly_statistics" )
then
198 swbstats%filename_modifier_string =
"MONTHLY"
200 elseif ( command_arg_str .containssimilar.
"dump_options" )
then
202 swbstats%dump_options_to_screen =
true
204 elseif ( command_arg_str .containssimilar.
"report_as_volume" )
then
206 swbstats%report_as_volume =
true
208 elseif ( command_arg_str .containssimilar.
"report_in_meters" )
then
210 swbstats%report_in_meters =
true
212 elseif ( command_arg_str .containssimilar.
"annualize_sums" )
then
214 swbstats%annualize_stats =
true
216 elseif ( command_arg_str .containssimilar.
"stress_period_file" )
then
219 swbstats%stress_period_filename =
right(command_arg_str, substring=
"=")
220 call swbstats%read_date_range_file( &
221 csv_filename=swbstats%stress_period_filename, &
222 date_range_id_list=swbstats%date_range_id_list, &
223 start_date_list=swbstats%start_date_list, &
224 end_date_list=swbstats%end_date_list )
225 swbstats%filename_modifier_string =
"STRESS_PERIOD_STATS"
227 elseif ( command_arg_str .containssimilar.
"zone_period_file" )
then
230 swbstats%multiple_zone_grids =
true
231 swbstats%calc_zonal_stats =
true
232 swbstats%write_csv =
true
234 swbstats%zone_period_filename =
right(command_arg_str, substring=
"=")
235 call swbstats%read_zone_period_file( &
236 csv_filename=swbstats%zone_period_filename , &
237 date_range_id_list=swbstats%date_range_id_list, &
238 start_date_list=swbstats%start_date_list, &
239 end_date_list=swbstats%end_date_list, &
240 zonal_stats_grid_file_list=swbstats%zone_grid_file_list )
242 elseif ( command_arg_str .containssimilar.
"comparison_period_file" )
then
245 swbstats%multiple_comparison_grids =
true
246 swbstats%compare_to_obs_values =
true
247 swbstats%write_csv =
true
248 swbstats%filename_modifier_string =
"COMPARISON_PERIOD_STATS"
250 swbstats%comparison_period_filename =
right(command_arg_str, substring=
"=")
251 call swbstats%read_comparison_period_file( &
252 csv_filename=swbstats%comparison_period_filename, &
253 date_range_id_list=swbstats%date_range_id_list, &
254 start_date_list=swbstats%start_date_list, &
255 end_date_list=swbstats%end_date_list, &
256 comparison_grid_file_list=swbstats%comparison_grid_file_list )
258 elseif ( command_arg_str .containssimilar.
"slice" )
then
260 sub_string =
right(command_arg_str, substring=
"=")
261 start_date_string =
left(sub_string, substring=
",")
262 end_date_string =
right(sub_string, substring=
",")
266 call swbstats%slice_start_date%parseDate(start_date_string)
267 call swbstats%slice_start_date%calcGregorianDate()
269 call swbstats%slice_end_date%parseDate(end_date_string)
270 call swbstats%slice_end_date%calcGregorianDate()
271 swbstats%filename_modifier_string =
"SLICE_STATS--" &
272 //swbstats%slice_start_date%prettydate()//
"_to_" &
273 //swbstats%slice_end_date%prettydate()
275 elseif ( command_arg_str .containssimilar.
"zone_grid=" )
then
277 swbstats%zone_grid_filename =
right(command_arg_str, substring=
"=")
278 swbstats%calc_zonal_stats =
true
279 swbstats%write_csv =
true
281 elseif ( command_arg_str .containssimilar.
"zone_grid2=" )
then
283 swbstats%zone_grid2_filename =
right(command_arg_str, substring=
"=")
284 swbstats%calc_zonal_stats =
true
285 swbstats%write_csv =
true
287 elseif ( command_arg_str .containssimilar.
"comparison_grid" )
then
289 swbstats%comparison_grid_filename =
right(command_arg_str, substring=
"=")
290 swbstats%compare_to_obs_values =
true
291 swbstats%write_csv =
true
293 elseif ( command_arg_str .strapprox.
"--netcdf_output")
then
297 elseif ( command_arg_str .strapprox.
"--no_netcdf_output" )
then
301 elseif ( command_arg_str .strapprox.
"--arcgrid_output" )
then
305 elseif ( command_arg_str .strapprox.
"--no_arcgrid_output" )
then
309 elseif ( command_arg_str .contains.
"--" )
then
312 print *,
"Unknown swbstats2 option: "//
squote(command_arg_str)//
"."
318 swbstats%netcdf_input_filename = trim(command_arg_str)
321 swbstats%netcdf_input_filename, &
322 guess_z_var_name=
true )
325 start_date_dbl = real( swbstats%ncfile_in%iFirstDayJD, c_double )
326 end_date_dbl = real( swbstats%ncfile_in%iLastDayJD, c_double )
329 call swbstats%data_start_date%setJulianDate(start_date_dbl)
330 call swbstats%data_start_date%calcGregorianDate()
331 call swbstats%data_end_date%setJulianDate(end_date_dbl)
332 call swbstats%data_end_date%calcGregorianDate()
334 swbstats%netcdf_input_file_is_open =
true
340 if (.not. swbstats%netcdf_input_file_is_open) &
341 stop(
"No netCDF file was specified or there was an error opening the file.")
349 variable_name=
"crs", &
350 attribute_name_list=name_list, &
351 attribute_value_list=value_list )
354 iindex_array = name_list%which(
"proj4_string")
355 temp_string = value_list%get( iindex_array(1) )
356 swbstats%target_proj4_string = trim(temp_string)
358 swbstats%netcdf_variable_name_string = trim(swbstats%ncfile_in%pNC_VAR(
nc_z)%sVariableName)
362 ncfile=swbstats%ncfile_in, &
363 variable_name=swbstats%netcdf_variable_name_string, &
364 attribute_name_list=name_list, &
365 attribute_value_list=value_list )
368 iindex_array = name_list%which(
"units")
369 swbstats%netcdf_variable_units_string = value_list%get( iindex_array(1) )
372 call swbstats%create_working_grids()
374 call rstat%initialize(nx=swbstats%ncfile_in%iNX, &
375 ny=swbstats%ncfile_in%iNY, &
376 x0=swbstats%ncfile_in%rX(0), &
377 y0=swbstats%ncfile_in%rY(0), &
378 x1=swbstats%ncfile_in%rX(1), &
379 y1=swbstats%ncfile_in%rY(1), &
380 nodata_value=-9999._c_double)
386 call swbstats%create_date_list_for_annual_statistics()
390 call swbstats%create_date_list_for_monthly_statistics()
391 call swbstats%create_monthly_working_grids()
396 call mon_stat(month_index)%initialize(nx=swbstats%ncfile_in%iNX, &
397 ny=swbstats%ncfile_in%iNY, &
398 x0=swbstats%ncfile_in%rX(0), &
399 y0=swbstats%ncfile_in%rY(0), &
400 x1=swbstats%ncfile_in%rX(1), &
401 y1=swbstats%ncfile_in%rY(1), &
402 nodata_value=-9999._c_double)
408 call swbstats%create_date_list_for_daily_statistics()
412 if (swbstats%report_in_meters)
then
415 if (swbstats%netcdf_variable_units_string .containssimilar.
"inch")
then
416 swbstats%unit_conversion_factor = 0.0254_c_double
417 elseif (swbstats%netcdf_variable_units_string .containssimilar.
"cm")
then
418 swbstats%unit_conversion_factor = 0.01_c_double
419 elseif (swbstats%netcdf_variable_units_string .containssimilar.
"mm")
then
420 swbstats%unit_conversion_factor = 0.001_c_double
422 call die(
"Was attempting to determine the output unit conversion factor," &
423 //
" but the netCDF variable has units of " &
424 //
squote(swbstats%netcdf_variable_units_string)//
", which cannot" &
425 //
" be converted to units of 'meters'.")
428 swbstats%filename_modifier_string = trim(swbstats%filename_modifier_string) &
434 if (swbstats%report_as_volume)
then
436 if (swbstats%report_as_volume)
then
437 if (swbstats%target_proj4_string .containssimilar.
"units=m")
then
438 swbstats%length_conversion_factor = 1.0_c_double
439 elseif (swbstats%target_proj4_string .containssimilar.
"units=us-ft")
then
440 swbstats%length_conversion_factor = 0.3048006096012192_c_double
441 elseif (swbstats%target_proj4_string .containssimilar.
"units=ft")
then
442 swbstats%length_conversion_factor = 0.3048_c_double
444 call die(
"Was attempting to define length conversion factor, but no units " &
445 //
"information found in input PROJ4 string.")
447 swbstats%grid_cell_area_sq_meters = (swbstats%grd_native%rGridCellSize &
448 * swbstats%length_conversion_factor)**2
449 swbstats%output_conversion_factor = swbstats%grid_cell_area_sq_meters &
450 * swbstats%unit_conversion_factor
452 swbstats%output_conversion_factor = swbstats%unit_conversion_factor
455 swbstats%filename_modifier_string = trim(swbstats%filename_modifier_string) &
460 call assert(.not. (swbstats%report_as_volume .and. swbstats%report_in_meters), &
461 "Cannot use '--report_as_volume' and '--report_in_meters' in the same" &
464 if (swbstats%compare_to_obs_values)
then
465 call swbstats%initialize_comparison_grid(grid_filename=swbstats%comparison_grid_filename)
471 if ( swbstats%slice_start_date < swbstats%data_start_date ) &
472 swbstats%slice_start_date = swbstats%data_start_date
473 if ( swbstats%slice_end_date > swbstats%data_end_date ) &
474 swbstats%slice_end_date = swbstats%data_end_date
476 call sim_dt%initialize( swbstats%slice_start_date, swbstats%slice_end_date )
477 call swbstats%create_date_list_for_period_statistics( swbstats%slice_start_date, swbstats%slice_end_date )
483 call sim_dt%initialize( swbstats%data_start_date, swbstats%data_end_date )
484 call swbstats%create_date_list_for_period_statistics( swbstats%data_start_date, swbstats%data_end_date )
487 call sim_dt%initialize( swbstats%data_start_date, swbstats%data_end_date )
491 if (swbstats%calc_zonal_stats)
then
492 if (.not. swbstats%multiple_zone_grids)
then
493 call swbstats%initialize_zone_grid(grid_filename=swbstats%zone_grid_filename)
494 call swbstats%get_unique_int(swbstats%grd_zone%pGrdBase%iData, swbstats%unique_zone_list)
496 if (len_trim(swbstats%zone_grid2_filename) > 0)
then
497 call swbstats%initialize_secondary_zone_grid(grid_filename=swbstats%zone_grid2_filename)
498 call swbstats%get_unique_int(swbstats%grd_zone2%pGrdBase%iData, swbstats%unique_zone2_list)
503 if (
allocated( swbstats%output_file_prefix) )
then
504 temp_string = trim(swbstats%output_file_prefix)//
"__zonal_stats__"//trim(swbstats%netcdf_variable_name_string)//
".csv"
506 temp_string =
"zonal_stats__"//trim(swbstats%netcdf_variable_name_string)//
".csv"
509 call swbstats%open_zonal_stats_output_file(trim(temp_string))
515 swbstats%date_range_string = swbstats%data_start_date%prettydate() &
516 //
"_to_"//swbstats%data_end_date%prettydate()
522 if (swbstats%dump_options_to_screen)
call swbstats%print_all_options()
545 do iindex=1, swbstats%date_range_id_list%count
548 call swbstats%slice_start_date%setDateFormat(
"YYYY-MM-DD")
549 call swbstats%slice_end_date%setDateFormat(
"YYYY-MM-DD")
553 start_date_string = swbstats%start_date_list%get( iindex )
554 end_date_string = swbstats%end_date_list%get( iindex )
557 call swbstats%slice_start_date%parseDate( start_date_string )
558 call swbstats%slice_end_date%parseDate( end_date_string )
561 swbstats%slice_range_string = swbstats%slice_start_date%prettydate() &
562 //
"_to_"//swbstats%slice_end_date%prettydate()
564 write(*,fmt=
"(a)")
""
565 write(*,fmt=
"(a)")
"Processing slice: ", swbstats%slice_start_date%prettydate() &
566 //
" to "//swbstats%slice_end_date%prettydate()
567 write(*,fmt=
"(a)") repeat(
"-", 70)
573 call swbstats%calculate_slice_statistics( start_date=swbstats%slice_start_date, &
574 end_date=swbstats%slice_end_date, &
583 call swbstats%calculate_monthly_statistics(month_num=swbstats%slice_start_date%iMonth, finalize=
false)
586 if (swbstats%multiple_comparison_grids)
then
587 swbstats%comparison_grid_filename = swbstats%comparison_grid_file_list%get( iindex )
588 call swbstats%initialize_comparison_grid(grid_filename=swbstats%comparison_grid_filename)
591 if (swbstats%multiple_zone_grids)
then
592 swbstats%zone_grid_filename = swbstats%zone_grid_file_list%get( iindex )
593 call swbstats%initialize_zone_grid(grid_filename=swbstats%zone_grid_filename)
597 start_date=swbstats%slice_start_date, &
598 end_date=swbstats%slice_end_date)
601 start_date=swbstats%slice_start_date, &
602 end_date=swbstats%slice_end_date, &
603 date_range_string=swbstats%slice_range_string, &
604 output_file_prefix=swbstats%output_file_prefix)
606 if (swbstats%calc_zonal_stats)
then
607 if ( len_trim(swbstats%zone_grid2_filename) > 0)
then
609 if (
associated(swbstats%grd_comparison) )
then
611 call swbstats%output_zonal_stats( &
612 start_date=swbstats%slice_start_date, &
613 end_date=swbstats%slice_end_date, &
615 zone_ids=swbstats%grd_zone%pGrdBase%iData, &
616 unique_zone_list=swbstats%unique_zone_list, &
617 zone2_ids=swbstats%grd_zone2%pGrdBase%iData, &
618 unique_zone2_list=swbstats%unique_zone2_list, &
619 comparison_values=swbstats%grd_comparison%pGrdBase%dpData, &
620 funit=swbstats%zonal_stats_output_file%unit() )
623 call swbstats%output_zonal_stats( &
624 start_date=swbstats%slice_start_date, &
625 end_date=swbstats%slice_end_date, &
627 zone_ids=swbstats%grd_zone%pGrdBase%iData, &
628 unique_zone_list=swbstats%unique_zone_list, &
629 zone2_ids=swbstats%grd_zone2%pGrdBase%iData, &
630 unique_zone2_list=swbstats%unique_zone2_list, &
631 funit=swbstats%zonal_stats_output_file%unit() )
636 if (
associated(swbstats%grd_comparison) )
then
637 call swbstats%output_zonal_stats( &
638 start_date=swbstats%slice_start_date, &
639 end_date=swbstats%slice_end_date, &
641 zone_ids=swbstats%grd_zone%pGrdBase%iData, &
642 unique_zone_list=swbstats%unique_zone_list, &
643 comparison_values=swbstats%grd_comparison%pGrdBase%dpData, &
644 funit=swbstats%zonal_stats_output_file%unit() )
647 call swbstats%output_zonal_stats( &
648 start_date=swbstats%slice_start_date, &
649 end_date=swbstats%slice_end_date, &
651 zone_ids=swbstats%grd_zone%pGrdBase%iData, &
652 unique_zone_list=swbstats%unique_zone_list, &
653 funit=swbstats%zonal_stats_output_file%unit() )
668 call swbstats%calculate_monthly_statistics(month_num=swbstats%slice_start_date%iMonth, finalize=
true)
670 date_range_string=swbstats%date_range_string, &
671 output_file_prefix=swbstats%output_file_prefix)
674 if (swbstats%write_csv)
call swbstats%zonal_stats_output_file%close()
678 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
logical(c_bool), parameter, public false
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