PartMC  2.6.1
extract_aero_size.F90
Go to the documentation of this file.
1 ! Copyright (C) 2009-2012 Matthew West
2 ! Licensed under the GNU General Public License version 2 or (at your
3 ! option) any later version. See the file COPYING for details.
4 
5 !> \file
6 !> The extract_aero_size program.
7 
8 !> Read NetCDF output files and write out the aerosol number or mass
9 !> size distributions in text format.
11 
12  use pmc_aero_state
14  use pmc_output
15  use pmc_mpi
16  use getopt_m
17 
18  integer, parameter :: dist_type_none = 0
19  integer, parameter :: dist_type_num = 1
20  integer, parameter :: dist_type_mass = 2
21 
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
25  type(bin_grid_t) :: diam_grid
26  type(aero_data_t) :: aero_data
27  type(aero_state_t) :: aero_state
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(:,:)
35  type(option_s) :: opts(7)
36 
37  call pmc_mpi_init()
38 
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')
46 
47  dist_type = dist_type_none
48  d_min = 1d-10
49  d_max = 1d-3
50  n_bin = 100
51  out_filename = ""
52 
53  do
54  select case(getopt("hnmN:X:b:o:", opts))
55  case(char(0))
56  exit
57  case('h')
58  call print_help()
59  stop
60  case('n')
61  if (dist_type /= dist_type_none) then
62  call print_help()
63  call die_msg(525113814, 'multiple distribution types selected')
64  end if
65  dist_type = dist_type_num
66  case('m')
67  if (dist_type /= dist_type_none) then
68  call print_help()
69  call die_msg(155494931, 'multiple distribution types selected')
70  end if
71  dist_type = dist_type_mass
72  case('N')
73  d_min = string_to_real(optarg)
74  case('X')
75  d_max = string_to_real(optarg)
76  case('b')
77  n_bin = string_to_integer(optarg)
78  case('o')
79  out_filename = optarg
80  case( '?' )
81  call print_help()
82  call die_msg(956456220, 'unknown option: ' // trim(optopt))
83  case default
84  call print_help()
85  call die_msg(203991511, 'unhandled option: ' // trim(optopt))
86  end select
87  end do
88 
89  if (optind /= command_argument_count()) then
90  call print_help()
91  call die_msg(533171694, 'expected exactly one non-option prefix argument')
92  end if
93 
94  call get_command_argument(optind, in_prefix)
95 
96  if (dist_type == dist_type_none) then
97  call print_help()
98  call die_msg(540839314, 'must select distribution type (--num or --mass)')
99  end if
100 
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"
106  else
107  call die(545030852)
108  end if
109  end if
110 
111  allocate(filename_list(0))
112  call input_filename_list(in_prefix, filename_list)
113  n_file = size(filename_list)
114  call assert_msg(554271458, n_file > 0, &
115  "no NetCDF files found with prefix: " // trim(in_prefix))
116 
117  call bin_grid_make(diam_grid, bin_grid_type_log, n_bin, d_min, d_max)
118  allocate(aero_dist(n_bin, n_file))
119 
120  do i_file = 1,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)
123 
124  if (i_file == 1) then
125  run_uuid = uuid
126  else
127  call assert_msg(657993562, uuid == run_uuid, &
128  "UUID mismatch between " // trim(filename_list(1)) // " and " &
129  // trim(filename_list(i_file)))
130  end if
131 
132  diameters = aero_state_diameters(aero_state, aero_data)
133  num_concs = aero_state_num_concs(aero_state, aero_data)
134  if (dist_type == dist_type_num) then
135  hist = bin_grid_histogram_1d(diam_grid, diameters, num_concs)
136  elseif (dist_type == dist_type_mass) then
137  masses = aero_state_masses(aero_state, aero_data)
138  hist = bin_grid_histogram_1d(diam_grid, diameters, num_concs * masses)
139  else
140  call die(123323238)
141  end if
142  aero_dist(:, i_file) = hist
143  end do
144 
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)"
153  end if
154  write(*,'(a)') " Diameter bins have logarithmic width:"
155  write(*,'(a,e20.10)') " log_width = ln(diam(i+1)) - ln(diam(i)) =", &
156  diam_grid%widths(1)
157 
158  call open_file_write(out_filename, out_unit)
159  do i_bin = 1,n_bin
160  write(out_unit, '(e30.15e3)', advance='no') diam_grid%centers(i_bin)
161  do i_file = 1,n_file
162  write(out_unit, '(e30.15e3)', advance='no') aero_dist(i_bin, i_file)
163  end do
164  write(out_unit, '(a)') ''
165  end do
166  call close_file(out_unit)
167 
168  deallocate(filename_list)
169  deallocate(aero_dist)
170 
171  call pmc_mpi_finalize()
172 
173 contains
174 
175  subroutine print_help()
176 
177  write(*,'(a)') 'Usage: extract_aero_size [options] <netcdf_prefix>'
178  write(*,'(a)') ''
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.'
187  write(*,'(a)') ''
188  write(*,'(a)') 'Examples:'
189  write(*,'(a)') ' extract_aero_size --num data_0001'
190  write(*,'(a)') &
191  ' extract_aero_size --mass --dmin 1e-8 --dmax 1e-4 data_0001'
192  write(*,'(a)') ''
193 
194  end subroutine print_help
195 
196 end program extract_aero_size
pmc_mpi::pmc_mpi_init
subroutine pmc_mpi_init()
Initialize MPI.
Definition: mpi.F90:56
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
pmc_output::input_state
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.
Definition: output.F90:498
pmc_aero_particle
The aero_particle_t structure and associated subroutines.
Definition: aero_particle.F90:9
extract_aero_size
program extract_aero_size
Read NetCDF output files and write out the aerosol number or mass size distributions in text format.
Definition: extract_aero_size.F90:10
pmc_util::open_file_write
subroutine open_file_write(filename, unit)
Open a file for writing with an automatically assigned unit and test that it succeeds....
Definition: util.F90:206
getopt_m::getopt
character function getopt(optstring, longopts)
Definition: getopt.F90:132
pmc_util::die_msg
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:134
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
getopt_m::optarg
character(len=80) optarg
Definition: getopt.F90:92
pmc_util::string_to_integer
integer function string_to_integer(string)
Convert a string to an integer.
Definition: util.F90:688
pmc_aero_state
The aero_state_t structure and assocated subroutines.
Definition: aero_state.F90:9
pmc_mpi::pmc_mpi_finalize
subroutine pmc_mpi_finalize()
Shut down MPI.
Definition: mpi.F90:89
getopt_m::option_s
Definition: getopt.F90:97
pmc_util::assert_msg
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:77
getopt_m
Definition: getopt.F90:90
pmc_aero_state::aero_state_num_concs
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.
Definition: aero_state.F90:1190
pmc_aero_data::aero_data_t
Aerosol material properties and associated data.
Definition: aero_data.F90:49
pmc_output
Write data in NetCDF format.
Definition: output.F90:68
getopt_m::optind
integer optind
Definition: getopt.F90:94
pmc_bin_grid::bin_grid_histogram_1d
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.
Definition: bin_grid.F90:174
pmc_aero_state::aero_state_masses
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.
Definition: aero_state.F90:1133
pmc_util::die
subroutine die(code)
Error immediately.
Definition: util.F90:122
getopt_m::optopt
character optopt
Definition: getopt.F90:93
pmc_util::close_file
subroutine close_file(unit)
Close a file and de-assign the unit.
Definition: util.F90:226
pmc_bin_grid::bin_grid_t
1D grid, either logarithmic or linear.
Definition: bin_grid.F90:33
print_help
subroutine print_help()
Definition: extract_aero_particles.F90:109
pmc_bin_grid::bin_grid_type_log
integer, parameter bin_grid_type_log
Logarithmically spaced bin grid.
Definition: bin_grid.F90:23
pmc_bin_grid::bin_grid_make
subroutine bin_grid_make(bin_grid, type, n_bin, min, max)
Generates the bin grid given the range and number of bins.
Definition: bin_grid.F90:84
pmc_aero_state::aero_state_t
The current collection of aerosol particles.
Definition: aero_state.F90:63
pmc_aero_state::aero_state_diameters
real(kind=dp) function, dimension(aero_state_n_part(aero_state)) aero_state_diameters(aero_state, aero_data, include, exclude)
Returns the diameters of all particles.
Definition: aero_state.F90:993
pmc_output::input_filename_list
subroutine input_filename_list(prefix, filename_list)
Find all NetCDF (.nc) filenames that match the given prefix.
Definition: output.F90:568
string_to_real
real(kind=dp) function string_to_real(string)
Convert a string to a real.
Definition: numeric_average.F90:108