PartMC
2.2.0
|
00001 ! Copyright (C) 2009-2011 Matthew West 00002 ! Licensed under the GNU General Public License version 2 or (at your 00003 ! option) any later version. See the file COPYING for details. 00004 00005 !> \file 00006 !> The extract_aero_size program. 00007 00008 !> Read NetCDF output files and write out the aerosol number or mass 00009 !> size distributions in text format. 00010 program extract_aero_size 00011 00012 use pmc_aero_state 00013 use pmc_aero_particle 00014 use pmc_output 00015 use pmc_mpi 00016 use getopt_m 00017 00018 integer, parameter :: DIST_TYPE_NONE = 0 00019 integer, parameter :: DIST_TYPE_NUM = 1 00020 integer, parameter :: DIST_TYPE_MASS = 2 00021 00022 character(len=PMC_MAX_FILENAME_LEN) :: in_prefix, out_filename 00023 character(len=PMC_MAX_FILENAME_LEN), allocatable :: filename_list(:) 00024 character(len=1000) :: tmp_str 00025 type(bin_grid_t) :: diam_grid 00026 type(aero_data_t) :: aero_data 00027 type(aero_state_t) :: aero_state 00028 integer :: index, i_repeat, i_part, i_spec, out_unit 00029 integer :: i_file, n_file, i_bin, n_bin, dist_type 00030 real(kind=dp) :: time, del_t 00031 type(aero_particle_t), pointer :: aero_particle 00032 real(kind=dp) :: d_min, d_max, diam, volume, log_width 00033 character(len=PMC_UUID_LEN) :: uuid, run_uuid 00034 real(kind=dp), allocatable :: diameters(:), num_concs(:), masses(:), hist(:) 00035 real(kind=dp), allocatable :: aero_dist(:,:) 00036 type(option_s) :: opts(7) 00037 00038 call pmc_mpi_init() 00039 00040 opts(1) = option_s("help", .false., 'h') 00041 opts(2) = option_s("num", .false., 'n') 00042 opts(3) = option_s("mass", .false., 'm') 00043 opts(4) = option_s("dmin", .true., 'N') 00044 opts(5) = option_s("dmax", .true., 'X') 00045 opts(6) = option_s("nbin", .true., 'b') 00046 opts(7) = option_s("output", .true., 'o') 00047 00048 dist_type = DIST_TYPE_NONE 00049 d_min = 1d-10 00050 d_max = 1d-3 00051 n_bin = 100 00052 out_filename = "" 00053 00054 do 00055 select case(getopt("hnmN:X:b:o:", opts)) 00056 case(char(0)) 00057 exit 00058 case('h') 00059 call print_help() 00060 stop 00061 case('n') 00062 if (dist_type /= DIST_TYPE_NONE) then 00063 call print_help() 00064 call die_msg(525113814, 'multiple distribution types selected') 00065 end if 00066 dist_type = DIST_TYPE_NUM 00067 case('m') 00068 if (dist_type /= DIST_TYPE_NONE) then 00069 call print_help() 00070 call die_msg(155494931, 'multiple distribution types selected') 00071 end if 00072 dist_type = DIST_TYPE_MASS 00073 case('N') 00074 d_min = string_to_real(optarg) 00075 case('X') 00076 d_max = string_to_real(optarg) 00077 case('b') 00078 n_bin = string_to_integer(optarg) 00079 case('o') 00080 out_filename = optarg 00081 case( '?' ) 00082 call print_help() 00083 call die_msg(956456220, 'unknown option: ' // trim(optopt)) 00084 case default 00085 call print_help() 00086 call die_msg(203991511, 'unhandled option: ' // trim(optopt)) 00087 end select 00088 end do 00089 00090 if (optind /= command_argument_count()) then 00091 call print_help() 00092 call die_msg(533171694, 'expected exactly one non-option prefix argument') 00093 end if 00094 00095 call get_command_argument(optind, in_prefix) 00096 00097 if (dist_type == DIST_TYPE_NONE) then 00098 call print_help() 00099 call die_msg(540839314, 'must select distribution type (--num or --mass)') 00100 end if 00101 00102 if (out_filename == "") then 00103 if (dist_type == DIST_TYPE_NUM) then 00104 out_filename = trim(in_prefix) // "_aero_size_num.txt" 00105 elseif (dist_type == DIST_TYPE_MASS) then 00106 out_filename = trim(in_prefix) // "_aero_size_mass.txt" 00107 else 00108 call die(545030852) 00109 end if 00110 end if 00111 00112 call bin_grid_allocate(diam_grid) 00113 call aero_data_allocate(aero_data) 00114 call aero_state_allocate(aero_state) 00115 00116 allocate(filename_list(0)) 00117 call input_filename_list(in_prefix, filename_list) 00118 n_file = size(filename_list) 00119 call assert_msg(875939143, n_file > 0, & 00120 "no NetCDF files found with prefix: " // trim(in_prefix)) 00121 00122 call bin_grid_make(diam_grid, n_bin, d_min, d_max) 00123 allocate(aero_dist(n_bin, n_file)) 00124 allocate(hist(n_bin)) 00125 allocate(diameters(0)) 00126 allocate(num_concs(0)) 00127 allocate(masses(0)) 00128 00129 do i_file = 1,n_file 00130 call input_state(filename_list(i_file), index, time, del_t, i_repeat, & 00131 uuid, aero_data=aero_data, aero_state=aero_state) 00132 00133 if (i_file == 1) then 00134 run_uuid = uuid 00135 else 00136 call assert_msg(657993562, uuid == run_uuid, & 00137 "UUID mismatch between " // trim(filename_list(1)) // " and " & 00138 // trim(filename_list(i_file))) 00139 end if 00140 00141 call aero_state_diameters(aero_state, diameters) 00142 call aero_state_num_concs(aero_state, num_concs) 00143 if (dist_type == DIST_TYPE_NUM) then 00144 call bin_grid_histogram_1d(diam_grid, diameters, num_concs, hist) 00145 elseif (dist_type == DIST_TYPE_MASS) then 00146 call aero_state_masses(aero_state, aero_data, masses) 00147 call bin_grid_histogram_1d(diam_grid, diameters, num_concs * masses, & 00148 hist) 00149 else 00150 call die(123323238) 00151 end if 00152 aero_dist(:, i_file) = hist 00153 end do 00154 00155 write(*,'(a)') "Output file: " // trim(out_filename) 00156 write(*,'(a)') " Each row of output is one size bin." 00157 write(*,'(a)') " The columns of output are:" 00158 write(*,'(a)') " column 1: bin center diameter (m)" 00159 if (dist_type == DIST_TYPE_NUM) then 00160 write(*,'(a)') " column j+1: number concentration at time(j) (#/m^3)" 00161 elseif (dist_type == DIST_TYPE_MASS) then 00162 write(*,'(a)') " column j+1: mass concentration at time(j) (kg/m^3)" 00163 end if 00164 write(*,'(a)') " Diameter bins have logarithmic width:" 00165 write(*,'(a,e20.10)') " log_width = ln(diam(i+1)) - ln(diam(i)) =", & 00166 diam_grid%log_width 00167 00168 call open_file_write(out_filename, out_unit) 00169 do i_bin = 1,n_bin 00170 write(out_unit, '(e30.15e3)', advance='no') & 00171 diam_grid%center_radius(i_bin) 00172 do i_file = 1,n_file 00173 write(out_unit, '(e30.15e3)', advance='no') aero_dist(i_bin, i_file) 00174 end do 00175 write(out_unit, '(a)') '' 00176 end do 00177 call close_file(out_unit) 00178 00179 deallocate(filename_list) 00180 deallocate(aero_dist) 00181 deallocate(hist) 00182 deallocate(diameters) 00183 deallocate(num_concs) 00184 deallocate(masses) 00185 call bin_grid_allocate(diam_grid) 00186 call aero_data_deallocate(aero_data) 00187 call aero_state_deallocate(aero_state) 00188 00189 call pmc_mpi_finalize() 00190 00191 contains 00192 00193 subroutine print_help() 00194 00195 write(*,'(a)') 'Usage: extract_aero_size [options] <netcdf_prefix>' 00196 write(*,'(a)') '' 00197 write(*,'(a)') 'options are:' 00198 write(*,'(a)') ' -h, --help Print this help message.' 00199 write(*,'(a)') ' -n, --num Output number distribution.' 00200 write(*,'(a)') ' -m, --mass Output mass distribution.' 00201 write(*,'(a)') ' -N, --dmin <D> Minimum diameter (m).' 00202 write(*,'(a)') ' -X, --dmax <D> Maximum diameter (m).' 00203 write(*,'(a)') ' -b, --nbin <N> Number of size bins.' 00204 write(*,'(a)') ' -o, --out <file> Output filename.' 00205 write(*,'(a)') '' 00206 write(*,'(a)') 'Examples:' 00207 write(*,'(a)') ' extract_aero_size --num data_0001' 00208 write(*,'(a)') & 00209 ' extract_aero_size --mass --dmin 1e-8 --dmax 1e-4 data_0001' 00210 write(*,'(a)') '' 00211 00212 end subroutine print_help 00213 00214 end program extract_aero_size