PartMC 2.1.3
nucleate.F90
Go to the documentation of this file.
00001 ! Copyright (C) 2010, 2011 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 pmc_nucleate module.
00007 
00008 !> Aerosol nucleation functions.
00009 module pmc_nucleate
00010 
00011   use pmc_env_state
00012   use pmc_bin_grid
00013   use pmc_aero_state
00014   use pmc_aero_data
00015   use pmc_gas_data
00016   use pmc_gas_state
00017 
00018   !> Type code for unknown or invalid nucleation type.
00019   integer, parameter :: NUCLEATE_TYPE_INVALID   = 0
00020   !> Type code for H2SO4 to SO4 nucleation with quadratic rate.
00021   integer, parameter :: NUCLEATE_TYPE_SULF_ACID = 1
00022   
00023 contains
00024 
00025 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00026 
00027   !> Do nucleation of the type given by the first argument.
00028   subroutine nucleate(nucleate_type, bin_grid, env_state, gas_data, &
00029        aero_data, aero_weight, aero_state, gas_state, del_t)
00030 
00031     !> Type of nucleation.
00032     integer, intent(in) :: nucleate_type
00033     !> Bin grid.
00034     type(bin_grid_t), intent(in) :: bin_grid
00035     !> Environment state.
00036     type(env_state_t), intent(in) :: env_state
00037     !> Gas data.
00038     type(gas_data_t), intent(in) :: gas_data
00039     !> Aerosol data.
00040     type(aero_data_t), intent(in) :: aero_data
00041     !> Aerosol weight.
00042     type(aero_weight_t), intent(in) :: aero_weight
00043     !> Aerosol state.
00044     type(aero_state_t), intent(inout) :: aero_state
00045     !> Gas state.
00046     type(gas_state_t), intent(inout) :: gas_state
00047     !> Time to perform nucleation for.
00048     real(kind=dp), intent(in) :: del_t
00049 
00050     if (nucleate_type == NUCLEATE_TYPE_SULF_ACID) then
00051        call nucleate_sulf_acid(bin_grid, env_state, gas_data, aero_data, &
00052             aero_weight, aero_state, gas_state, del_t)
00053     else
00054        call die_msg(983831728, &
00055             "unknown nucleation type: " &
00056             // trim(integer_to_string(nucleate_type)))
00057     end if
00058 
00059   end subroutine nucleate
00060 
00061 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00062 
00063   !> Nucleate sulfuric acid into aerosol particles, using a power-law
00064   !> dependence, for time \c del_t.
00065   !!
00066   !! The modeled emission rate is \f$ J = K H^2 \f$, where \f$H\f$ is
00067   !! the concentration of \f$ \rm H_2SO_4 \f$ and \f$K\f$ is a
00068   !! constant coefficient.
00069   !!
00070   !! The reference is:
00071   !!
00072   !! C. Kuang, P. H. McMurry, A. V. McCormick, and F. L. Eisele
00073   !! (2008), Dependence of nucleation rates on sulfuric acid vapor
00074   !! concentration in diverse atmospheric locations,
00075   !! <i>J. Geophys. Res.</i>, 113, D10209, doi:<a
00076   !! href="http://dx.doi.org/10.1029/2007JD009253">10.1029/2007JD009253</a>.
00077   subroutine nucleate_sulf_acid(bin_grid, env_state, gas_data, aero_data, &
00078        aero_weight, aero_state, gas_state, del_t)
00079 
00080     !> Bin grid.
00081     type(bin_grid_t), intent(in) :: bin_grid
00082     !> Environment state.
00083     type(env_state_t), intent(in) :: env_state
00084     !> Gas data.
00085     type(gas_data_t), intent(in) :: gas_data
00086     !> Aerosol data.
00087     type(aero_data_t), intent(in) :: aero_data
00088     !> Aerosol weight.
00089     type(aero_weight_t), intent(in) :: aero_weight
00090     !> Aerosol state.
00091     type(aero_state_t), intent(inout) :: aero_state
00092     !> Gas state.
00093     type(gas_state_t), intent(inout) :: gas_state
00094     !> Time to perform nucleation for.
00095     real(kind=dp), intent(in) :: del_t
00096 
00097     real(kind=dp), parameter :: nucleate_coeff = 1d-18 ! K (m^3 s^{-1})
00098     real(kind=dp), parameter :: nucleate_diam = 1d-9   ! diameter of new
00099                                                        ! particles (m)
00100 
00101     integer :: i_gas_h2so4, i_aero_so4, n_samp, i_samp, i_bin
00102     real(kind=dp) :: sulf_acid_conc, nucleate_rate, n_samp_avg
00103     real(kind=dp) :: total_so4_vol, vol, h2so4_removed_conc
00104     real(kind=dp) :: nucleate_comp_vol
00105     type(aero_particle_t) :: aero_particle
00106 
00107     ! look up the species numbers
00108     i_gas_h2so4 = gas_data_spec_by_name(gas_data, "H2SO4")
00109     call assert_msg(886839228, i_gas_h2so4 > 0, &
00110          "nucleate_sulf_acid requires H2SO4 as a gas species")
00111     i_aero_so4 = aero_data_spec_by_name(aero_data, "SO4")
00112     call assert_msg(551966998, i_aero_so4 > 0, &
00113          "nucleate_sulf_acid requires SO4 as an aerosol species")
00114 
00115     ! H2SO4 concentration in molecules / m^3
00116     sulf_acid_conc = env_state_ppb_to_conc(env_state, &
00117          gas_state%mix_rat(i_gas_h2so4))
00118 
00119     ! particle nucleation rate in (particles m^{-3} s^{-1})
00120     nucleate_rate = nucleate_coeff * sulf_acid_conc**2
00121 
00122     ! computational volume at the size of nucleated particles (only
00123     ! valid for mono-disperse nucleation)
00124     nucleate_comp_vol = aero_state%comp_vol &
00125          / aero_weight_value(aero_weight, nucleate_diam / 2d0)
00126 
00127     ! determine number of nucleated particles
00128     n_samp_avg = nucleate_rate * nucleate_comp_vol * del_t
00129     n_samp = rand_poisson(n_samp_avg)
00130 
00131     ! create the particles
00132     call aero_particle_allocate_size(aero_particle, aero_data%n_spec, &
00133          aero_data%n_source)
00134     total_so4_vol = 0d0
00135     do i_samp = 1,n_samp
00136        vol = diam2vol(nucleate_diam)
00137        total_so4_vol = total_so4_vol + vol
00138 
00139        aero_particle%vol(i_aero_so4) = vol
00140        call aero_particle_new_id(aero_particle)
00141        call aero_particle_set_create_time(aero_particle, &
00142             env_state%elapsed_time)
00143        i_bin = aero_particle_in_bin(aero_particle, bin_grid)
00144        call aero_state_add_particle(aero_state, i_bin, aero_particle)
00145     end do
00146     call aero_particle_deallocate(aero_particle)
00147 
00148     ! remove gases that formed new particles
00149     h2so4_removed_conc = &
00150          total_so4_vol * aero_data%density(i_aero_so4) &
00151          / aero_data%molec_weight(i_aero_so4) & ! moles of SO4
00152          * const%avagadro &                     ! molecules of SO4
00153          / nucleate_comp_vol                    ! molecules / m^3
00154     gas_state%mix_rat(i_gas_h2so4) = gas_state%mix_rat(i_gas_h2so4) &
00155          - env_state_conc_to_ppb(env_state, h2so4_removed_conc)
00156     if (gas_state%mix_rat(i_gas_h2so4) < 0d0) then
00157        gas_state%mix_rat(i_gas_h2so4) = 0d0
00158     end if
00159 
00160   end subroutine nucleate_sulf_acid
00161 
00162 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00163 
00164   subroutine spec_file_read_nucleate_type(file, nucleate_type)
00165 
00166     !> Spec file.
00167     type(spec_file_t), intent(inout) :: file
00168     !> Aerosol weight.
00169     integer, intent(out) :: nucleate_type
00170 
00171     character(len=SPEC_LINE_MAX_VAR_LEN) :: nucleate_type_name
00172 
00173     !> \page input_format_nucleate Input File Format: Nucleation Parameterization
00174     !!
00175     !! The nucleation parameterization is specified by the parameter:
00176     !!   - \b nucleate (string): the type of nucleation
00177     !!     parameterization --- must be one of: "none" for no
00178     !!     nucleation; or "sulf_acid" for the nucleate_sulf_acid()
00179     !!     parameterization
00180     !!
00181     !! See also:
00182     !!   - \ref spec_file_format --- the input file text format
00183 
00184     call spec_file_read_string(file, 'nucleate', nucleate_type_name)
00185     if (nucleate_type_name == 'sulf_acid') then
00186        nucleate_type = NUCLEATE_TYPE_SULF_ACID
00187     else
00188        call spec_file_die_msg(707263678, file, "unknown nucleate type: " &
00189             // trim(nucleate_type_name))
00190     end if
00191 
00192   end subroutine spec_file_read_nucleate_type
00193 
00194 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00195 
00196 end module pmc_nucleate