18 integer,
parameter :: DIST_TYPE_NONE = 0
19 integer,
parameter :: DIST_TYPE_NUM = 1
20 integer,
parameter :: DIST_TYPE_MASS = 2
22 character(len=PMC_MAX_FILENAME_LEN) :: in_prefix, out_filename
23 character(len=PMC_MAX_FILENAME_LEN),
allocatable :: filename_list(:)
24 character(len=1000) :: tmp_str
28 integer :: index, i_repeat, i_part, i_spec, out_unit
29 integer :: i_file, n_file, i_bin, n_bin, dist_type
30 real(kind=dp) :: time, del_t
31 real(kind=dp) :: d_min, d_max, diam, volume
32 character(len=PMC_UUID_LEN) :: uuid, run_uuid
33 real(kind=dp),
allocatable :: diameters(:), num_concs(:), masses(:), hist(:)
34 real(kind=dp),
allocatable :: aero_dist(:,:)
39 opts(1) =
option_s(
"help", .false.,
'h')
40 opts(2) =
option_s(
"num", .false.,
'n')
41 opts(3) =
option_s(
"mass", .false.,
'm')
42 opts(4) =
option_s(
"dmin", .true.,
'N')
43 opts(5) =
option_s(
"dmax", .true.,
'X')
44 opts(6) =
option_s(
"nbin", .true.,
'b')
45 opts(7) =
option_s(
"output", .true.,
'o')
47 dist_type = dist_type_none
54 select case(
getopt(
"hnmN:X:b:o:", opts))
61 if (dist_type /= dist_type_none)
then 63 call die_msg(525113814,
'multiple distribution types selected')
65 dist_type = dist_type_num
67 if (dist_type /= dist_type_none)
then 69 call die_msg(155494931,
'multiple distribution types selected')
71 dist_type = dist_type_mass
89 if (
optind /= command_argument_count())
then 91 call die_msg(533171694,
'expected exactly one non-option prefix argument')
94 call get_command_argument(
optind, in_prefix)
96 if (dist_type == dist_type_none)
then 98 call die_msg(540839314,
'must select distribution type (--num or --mass)')
101 if (out_filename ==
"")
then 102 if (dist_type == dist_type_num)
then 103 out_filename = trim(in_prefix) //
"_aero_size_num.txt" 104 elseif (dist_type == dist_type_mass)
then 105 out_filename = trim(in_prefix) //
"_aero_size_mass.txt" 111 allocate(filename_list(0))
113 n_file =
size(filename_list)
115 "no NetCDF files found with prefix: " // trim(in_prefix))
118 allocate(aero_dist(n_bin, n_file))
121 call input_state(filename_list(i_file), index, time, del_t, i_repeat, &
122 uuid, aero_data=aero_data, aero_state=aero_state)
124 if (i_file == 1)
then 127 call assert_msg(657993562, uuid == run_uuid, &
128 "UUID mismatch between " // trim(filename_list(1)) //
" and " &
129 // trim(filename_list(i_file)))
134 if (dist_type == dist_type_num)
then 136 elseif (dist_type == dist_type_mass)
then 142 aero_dist(:, i_file) = hist
145 write(*,
'(a)')
"Output file: " // trim(out_filename)
146 write(*,
'(a)')
" Each row of output is one size bin." 147 write(*,
'(a)')
" The columns of output are:" 148 write(*,
'(a)')
" column 1: bin center diameter (m)" 149 if (dist_type == dist_type_num)
then 150 write(*,
'(a)')
" column j+1: number concentration at time(j) (#/m^3)" 151 elseif (dist_type == dist_type_mass)
then 152 write(*,
'(a)')
" column j+1: mass concentration at time(j) (kg/m^3)" 154 write(*,
'(a)')
" Diameter bins have logarithmic width:" 155 write(*,
'(a,e20.10)')
" log_width = ln(diam(i+1)) - ln(diam(i)) =", &
160 write(out_unit,
'(e30.15e3)', advance=
'no') diam_grid%centers(i_bin)
162 write(out_unit,
'(e30.15e3)', advance=
'no') aero_dist(i_bin, i_file)
164 write(out_unit,
'(a)')
'' 168 deallocate(filename_list)
169 deallocate(aero_dist)
177 write(*,
'(a)')
'Usage: extract_aero_size [options] <netcdf_prefix>' 179 write(*,
'(a)')
'options are:' 180 write(*,
'(a)')
' -h, --help Print this help message.' 181 write(*,
'(a)')
' -n, --num Output number distribution.' 182 write(*,
'(a)')
' -m, --mass Output mass distribution.' 183 write(*,
'(a)')
' -N, --dmin <D> Minimum diameter (m).' 184 write(*,
'(a)')
' -X, --dmax <D> Maximum diameter (m).' 185 write(*,
'(a)')
' -b, --nbin <N> Number of size bins.' 186 write(*,
'(a)')
' -o, --out <file> Output filename.' 188 write(*,
'(a)')
'Examples:' 189 write(*,
'(a)')
' extract_aero_size --num data_0001' 191 ' extract_aero_size --mass --dmin 1e-8 --dmax 1e-4 data_0001' subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
subroutine die(code)
Error immediately.
subroutine close_file(unit)
Close a file and de-assign the unit.
character function getopt(optstring, longopts)
The aero_particle_t structure and associated subroutines.
The aero_state_t structure and assocated subroutines.
real(kind=dp) function, dimension(bin_grid_size(x_bin_grid)) bin_grid_histogram_1d(x_bin_grid, x_data, weight_data)
Make a histogram with of the given weighted data, scaled by the bin sizes.
subroutine input_filename_list(prefix, filename_list)
Find all NetCDF (.nc) filenames that match the given prefix.
real(kind=dp) function, dimension(aero_state_n_part(aero_state)) aero_state_num_concs(aero_state, aero_data)
Returns the number concentrations of all particles.
subroutine die_msg(code, error_msg)
Error immediately.
Write data in NetCDF format.
real(kind=dp) function, dimension(aero_state_n_part(aero_state)) aero_state_masses(aero_state, aero_data, include, exclude)
Returns the masses of all particles.
The current collection of aerosol particles.
1D grid, either logarithmic or linear.
subroutine bin_grid_make(bin_grid, type, n_bin, min, max)
Generates the bin grid given the range and number of bins.
real(kind=dp) function, dimension(aero_state_n_part(aero_state)) aero_state_diameters(aero_state, aero_data)
Returns the diameters of all particles.
subroutine input_state(filename, index, time, del_t, i_repeat, uuid, aero_data, aero_state, gas_data, gas_state, env_state)
Read the current state.
integer, parameter bin_grid_type_log
Logarithmically spaced bin grid.
subroutine pmc_mpi_finalize()
Shut down MPI.
subroutine open_file_write(filename, unit)
Open a file for writing with an automatically assigned unit and test that it succeeds. The file should be closed with close_file().
subroutine pmc_mpi_init()
Initialize MPI.
Aerosol material properties and associated data.
integer function string_to_integer(string)
Convert a string to an integer.
real(kind=dp) function string_to_real(string)
Convert a string to a real.
Wrapper functions for MPI.