PartMC  2.6.1
extract_sectional_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_sectional_aero_size program.
7 
8 !> Read NetCDF sectional output files and write out the aerosol size
9 !> distribution in text format.
11 
12  use pmc_aero_binned
13  use pmc_output
14  use pmc_mpi
15  use getopt_m
16 
17  integer, parameter :: dist_type_none = 0
18  integer, parameter :: dist_type_num = 1
19  integer, parameter :: dist_type_mass = 2
20 
21  character(len=PMC_MAX_FILENAME_LEN) :: in_prefix, out_filename
22  character(len=PMC_MAX_FILENAME_LEN), allocatable :: filename_list(:)
23  type(bin_grid_t) :: bin_grid
24  type(aero_data_t) :: aero_data
25  type(aero_binned_t) :: aero_binned
26  integer :: index, out_unit
27  integer :: i_file, n_file, i_bin, dist_type
28  real(kind=dp) :: time, del_t
29  character(len=PMC_UUID_LEN) :: uuid, run_uuid
30  real(kind=dp), allocatable :: aero_dist(:,:)
31  type(option_s) :: opts(4)
32 
33  call pmc_mpi_init()
34 
35  opts(1) = option_s("help", .false., 'h')
36  opts(2) = option_s("num", .false., 'n')
37  opts(3) = option_s("mass", .false., 'm')
38  opts(4) = option_s("output", .true., 'o')
39 
40  dist_type = dist_type_none
41  out_filename = ""
42 
43  do
44  select case(getopt("hnmo:", opts))
45  case(char(0))
46  exit
47  case('h')
48  call print_help()
49  stop
50  case('n')
51  if (dist_type /= dist_type_none) then
52  call print_help()
53  call die_msg(413086480, 'multiple distribution types selected')
54  end if
55  dist_type = dist_type_num
56  case('m')
57  if (dist_type /= dist_type_none) then
58  call print_help()
59  call die_msg(528866290, 'multiple distribution types selected')
60  end if
61  dist_type = dist_type_mass
62  case('o')
63  out_filename = optarg
64  case( '?' )
65  call print_help()
66  call die_msg(546118086, 'unknown option: ' // trim(optopt))
67  case default
68  call print_help()
69  call die_msg(720731240, 'unhandled option: ' // trim(optopt))
70  end select
71  end do
72 
73  if (optind /= command_argument_count()) then
74  call print_help()
75  call die_msg(699147496, 'expected exactly one non-option prefix argument')
76  end if
77 
78  call get_command_argument(optind, in_prefix)
79 
80  if (dist_type == dist_type_none) then
81  call print_help()
82  call die_msg(576941805, 'must select distribution type (--num or --mass)')
83  end if
84 
85  if (out_filename == "") then
86  if (dist_type == dist_type_num) then
87  out_filename = trim(in_prefix) // "_aero_size_num.txt"
88  elseif (dist_type == dist_type_mass) then
89  out_filename = trim(in_prefix) // "_aero_size_mass.txt"
90  else
91  call die(767619107)
92  end if
93  end if
94 
95  allocate(filename_list(0))
96  call input_filename_list(in_prefix, filename_list)
97  n_file = size(filename_list)
98  call assert_msg(792400289, n_file > 0, &
99  "no NetCDF files found with prefix: " // trim(in_prefix))
100 
101  call input_sectional(filename_list(1), index, time, del_t, uuid, &
102  bin_grid=bin_grid, aero_data=aero_data, aero_binned=aero_binned)
103  run_uuid = uuid
104 
105  allocate(aero_dist(bin_grid_size(bin_grid), n_file))
106 
107  do i_file = 1,n_file
108  call input_sectional(filename_list(i_file), index, time, del_t, uuid, &
109  bin_grid=bin_grid, aero_data=aero_data, aero_binned=aero_binned)
110 
111  call assert_msg(838088000, uuid == run_uuid, &
112  "UUID mismatch between " // trim(filename_list(1)) // " and " &
113  // trim(filename_list(i_file)))
114 
115  if (dist_type == dist_type_num) then
116  aero_dist(:, i_file) = aero_binned%num_conc
117  elseif (dist_type == dist_type_mass) then
118  do i_bin = 1,bin_grid_size(bin_grid)
119  aero_dist(i_bin, i_file) = sum(aero_binned%vol_conc(i_bin, :) &
120  * aero_data%density)
121  end do
122  else
123  call die(141087960)
124  end if
125  end do
126 
127  write(*,'(a)') "Output file: " // trim(out_filename)
128  write(*,'(a)') " Each row of output is one size bin."
129  write(*,'(a)') " The columns of output are:"
130  write(*,'(a)') " column 1: bin center diameter (m)"
131  if (dist_type == dist_type_num) then
132  write(*,'(a)') " column j+1: number concentration at time(j) (#/m^3)"
133  elseif (dist_type == dist_type_mass) then
134  write(*,'(a)') " column j+1: mass concentration at time(j) (kg/m^3)"
135  end if
136  write(*,'(a)') " Diameter bins have logarithmic width:"
137  write(*,'(a,e20.10)') " log_width = ln(diam(i+1)) - ln(diam(i)) =", &
138  bin_grid%widths(1)
139 
140  call open_file_write(out_filename, out_unit)
141  do i_bin = 1,bin_grid_size(bin_grid)
142  write(out_unit, '(e30.15e3)', advance='no') &
143  rad2diam(bin_grid%centers(i_bin))
144  do i_file = 1,n_file
145  write(out_unit, '(e30.15e3)', advance='no') aero_dist(i_bin, i_file)
146  end do
147  write(out_unit, '(a)') ''
148  end do
149  call close_file(out_unit)
150 
151  deallocate(filename_list)
152  deallocate(aero_dist)
153 
154  call pmc_mpi_finalize()
155 
156 contains
157 
158  subroutine print_help()
159 
160  write(*,'(a)') 'Usage: extract_sectional_aero_size [options] ' &
161  // '<netcdf_prefix>'
162  write(*,'(a)') ''
163  write(*,'(a)') 'options are:'
164  write(*,'(a)') ' -h, --help Print this help message.'
165  write(*,'(a)') ' -n, --num Output number distribution.'
166  write(*,'(a)') ' -m, --mass Output mass distribution.'
167  write(*,'(a)') ' -o, --out <file> Output filename.'
168  write(*,'(a)') ''
169  write(*,'(a)') 'Examples:'
170  write(*,'(a)') ' extract_sectional_aero_size --num data_0001'
171  write(*,'(a)') ''
172 
173  end subroutine print_help
174 
175 end program extract_sectional_aero_size
pmc_mpi::pmc_mpi_init
subroutine pmc_mpi_init()
Initialize MPI.
Definition: mpi.F90:56
pmc_util::rad2diam
real(kind=dp) elemental function rad2diam(r)
Convert radius (m) to diameter (m).
Definition: util.F90:252
pmc_mpi
Wrapper functions for MPI.
Definition: mpi.F90:13
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
extract_sectional_aero_size
program extract_sectional_aero_size
Read NetCDF sectional output files and write out the aerosol size distribution in text format.
Definition: extract_sectional_aero_size.F90:10
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_bin_grid::bin_grid_size
elemental integer function bin_grid_size(bin_grid)
Return the number of bins in the grid, or -1 if the bin grid is not allocated.
Definition: bin_grid.F90:51
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_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_output::input_sectional
subroutine input_sectional(filename, index, time, del_t, uuid, bin_grid, aero_data, aero_binned, gas_data, gas_state, env_state)
Input sectional data.
Definition: output.F90:716
pmc_aero_binned
The aero_binned_t structure and associated subroutines.
Definition: aero_binned.F90:9
pmc_aero_binned::aero_binned_t
Aerosol number and volume distributions stored per bin.
Definition: aero_binned.F90:37
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_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