PartMC  2.3.0
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  call bin_grid_allocate(bin_grid)
96  call aero_data_allocate(aero_data)
97  call aero_binned_allocate(aero_binned)
98 
99  allocate(filename_list(0))
100  call input_filename_list(in_prefix, filename_list)
101  n_file = size(filename_list)
102  call assert_msg(792400289, n_file > 0, &
103  "no NetCDF files found with prefix: " // trim(in_prefix))
104 
105  call input_sectional(filename_list(1), index, time, del_t, uuid, &
106  bin_grid=bin_grid, aero_data=aero_data, aero_binned=aero_binned)
107  run_uuid = uuid
108 
109  allocate(aero_dist(bin_grid%n_bin, n_file))
110 
111  do i_file = 1,n_file
112  call input_sectional(filename_list(i_file), index, time, del_t, uuid, &
113  bin_grid=bin_grid, aero_data=aero_data, aero_binned=aero_binned)
114 
115  call assert_msg(838088000, uuid == run_uuid, &
116  "UUID mismatch between " // trim(filename_list(1)) // " and " &
117  // trim(filename_list(i_file)))
118 
119  if (dist_type == dist_type_num) then
120  aero_dist(:, i_file) = aero_binned%num_conc
121  elseif (dist_type == dist_type_mass) then
122  do i_bin = 1,bin_grid%n_bin
123  aero_dist(i_bin, i_file) = sum(aero_binned%vol_conc(i_bin, :) &
124  * aero_data%density)
125  end do
126  else
127  call die(141087960)
128  end if
129  end do
130 
131  write(*,'(a)') "Output file: " // trim(out_filename)
132  write(*,'(a)') " Each row of output is one size bin."
133  write(*,'(a)') " The columns of output are:"
134  write(*,'(a)') " column 1: bin center diameter (m)"
135  if (dist_type == dist_type_num) then
136  write(*,'(a)') " column j+1: number concentration at time(j) (#/m^3)"
137  elseif (dist_type == dist_type_mass) then
138  write(*,'(a)') " column j+1: mass concentration at time(j) (kg/m^3)"
139  end if
140  write(*,'(a)') " Diameter bins have logarithmic width:"
141  write(*,'(a,e20.10)') " log_width = ln(diam(i+1)) - ln(diam(i)) =", &
142  bin_grid%widths(1)
143 
144  call open_file_write(out_filename, out_unit)
145  do i_bin = 1,bin_grid%n_bin
146  write(out_unit, '(e30.15e3)', advance='no') &
147  rad2diam(bin_grid%centers(i_bin))
148  do i_file = 1,n_file
149  write(out_unit, '(e30.15e3)', advance='no') aero_dist(i_bin, i_file)
150  end do
151  write(out_unit, '(a)') ''
152  end do
153  call close_file(out_unit)
154 
155  deallocate(filename_list)
156  deallocate(aero_dist)
157  call bin_grid_allocate(bin_grid)
158  call aero_data_deallocate(aero_data)
159  call aero_binned_deallocate(aero_binned)
160 
161  call pmc_mpi_finalize()
162 
163 contains
164 
165  subroutine print_help()
166 
167  write(*,'(a)') 'Usage: extract_sectional_aero_size [options] ' &
168  // '<netcdf_prefix>'
169  write(*,'(a)') ''
170  write(*,'(a)') 'options are:'
171  write(*,'(a)') ' -h, --help Print this help message.'
172  write(*,'(a)') ' -n, --num Output number distribution.'
173  write(*,'(a)') ' -m, --mass Output mass distribution.'
174  write(*,'(a)') ' -o, --out <file> Output filename.'
175  write(*,'(a)') ''
176  write(*,'(a)') 'Examples:'
177  write(*,'(a)') ' extract_sectional_aero_size --num data_0001'
178  write(*,'(a)') ''
179 
180  end subroutine print_help
181 
182 end program extract_sectional_aero_size
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:133
character function getopt(optstring, longopts)
Definition: getopt.F90:131
subroutine input_filename_list(prefix, filename_list)
Find all NetCDF (.nc) filenames that match the given prefix.
Definition: output.F90:580
subroutine close_file(unit)
Close a file and de-assign the unit.
Definition: util.F90:225
real(kind=dp) elemental function rad2diam(r)
Convert radius (m) to diameter (m).
Definition: util.F90:262
subroutine aero_binned_deallocate(aero_binned)
Free internal memory in an aero_binned_t structure.
Definition: aero_binned.F90:79
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:76
subroutine aero_binned_allocate(aero_binned)
Allocate an aero_binned_t.
Definition: aero_binned.F90:47
subroutine pmc_mpi_finalize()
Shut down MPI.
Definition: mpi.F90:88
subroutine pmc_mpi_init()
Initialize MPI.
Definition: mpi.F90:55
subroutine bin_grid_allocate(bin_grid)
Allocates a bin_grid.
Definition: bin_grid.F90:51
program extract_sectional_aero_size
Read NetCDF sectional output files and write out the aerosol size distribution in text format...
subroutine aero_data_deallocate(aero_data)
Frees all storage.
Definition: aero_data.F90:116
Wrapper functions for MPI.
Definition: mpi.F90:13
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:727
1D grid, either logarithmic or linear.
Definition: bin_grid.F90:33
subroutine die(code)
Error immediately.
Definition: util.F90:121
subroutine print_help()
The aero_binned_t structure and associated subroutines.
Definition: aero_binned.F90:9
subroutine aero_data_allocate(aero_data)
Allocate storage for aero_data.
Definition: aero_data.F90:69
Aerosol material properties and associated data.
Definition: aero_data.F90:40
Write data in NetCDF format.
Definition: output.F90:68
Aerosol number and volume distributions stored per bin.
Definition: aero_binned.F90:33
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().
Definition: util.F90:205