PartMC  2.2.1
extract_aero_size.F90
Go to the documentation of this file.
00001 ! Copyright (C) 2009-2012 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(554271458, 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