! module_data_cam_mam_aero.F
! adapted from cam3 modal_aero_data.F90 by r.c.easter, june 2010
! Updated to CESM1.0.3 (CAM5.1.01) by Balwinder.Singh@pnnl.gov
!--------------------------------------------------------------
#define WRF_PORT
#if defined ( WRF_CHEM )
# include "../chem/MODAL_AERO_CPP_DEFINES.h"
#else
# define MODAL_AERO
# define MODAL_AERO_3MODE
#endif
module modal_aero_data 24,4
!--------------------------------------------------------------
! ... Basic aerosol mode parameters and arrays
!--------------------------------------------------------------
use shr_kind_mod
, only: r8 => shr_kind_r8
#ifndef WRF_PORT
use constituents
, only: pcnst
#else
use module_cam_support
, only : pcnst => pcnst_runtime
#endif
use radconstants
, only: nswbands, nlwbands
implicit none
save
integer, parameter :: maxd_aspectype = 14
! aerosol mode definitions
!
#if ( defined MODAL_AERO_7MODE )
integer, parameter :: ntot_amode = 7
#elif ( defined MODAL_AERO_3MODE )
integer, parameter :: ntot_amode = 3
#endif
!
! definitions for aerosol chemical components
!
integer, parameter :: ntot_aspectype = 8
character(len=*),parameter :: specname_amode(ntot_aspectype) = (/ 'sulfate ', 'ammonium ', 'nitrate ', &
'p-organic ', 's-organic ', 'black-c ', &
'seasalt ', 'dust ' /)
! set specdens_amode from physprop files via rad_cnst_get_aer_props
!specdens_amode(:ntot_aspectype) = (/1770.0,1770.0,1770.0, 1000.0, 1000.0, 1700.0,1900.0,2600.0 /)
! rce - 06-aug-2007 - changed specmw for almost everything to match mozart
#if ( defined MODAL_AERO_7MODE )
#ifndef WRF_PORT
real(r8), parameter :: specmw_amode(ntot_aspectype) = (/ 96.0, 18.0, 62.0, 12.0, 12.0, 12.0, 58.5, 135.0 /)
#else
real(r8) :: specmw_amode(ntot_aspectype) = (/ 96.0, 18.0, 62.0, 12.0, 12.0, 12.0, 58.5, 135.0 /)
#endif
#elif ( defined MODAL_AERO_3MODE )
#ifndef WRF_PORT
real(r8), parameter :: specmw_amode(ntot_aspectype) = (/ 115.0, 115.0, 62.0, 12.0, 12.0, 12.0, 58.5, 135.0 /)
#else
!Balwinder.Singh@pnnl.gov: For prescribed aerosols, these values are modified in the aerosol initialization subroutine
real(r8) :: specmw_amode(ntot_aspectype) = (/ 115.0, 115.0, 62.0, 12.0, 12.0, 12.0, 58.5, 135.0 /)
#endif
#endif
! input modename_amode, nspec_amode
#if ( defined MODAL_AERO_7MODE )
character(len=*), parameter :: modename_amode(ntot_amode) = (/'accum ', &
'aitken ', &
'primary carbon ', &
'fine seasalt ', &
'fine dust ', &
'coarse seasalt ', &
'coarse dust '/)
#elif ( defined MODAL_AERO_3MODE )
character(len=*), parameter :: modename_amode(ntot_amode) = (/'accum ', &
'aitken ', &
'coarse '/)
#endif
#if ( defined MODAL_AERO_7MODE )
#ifndef WRF_PORT
!Balwinder.Singh@pnnl.gov: For prescribed aerosols, these values are modified in the aerosol initialization subroutine
integer, parameter :: nspec_amode(ntot_amode) = (/ 6, 4, 2, 3, 3, 3, 3 /) ! SS
#else
integer :: nspec_amode(ntot_amode) = (/ 6, 4, 2, 3, 3, 3, 3 /) ! SS
#endif
#elif ( defined MODAL_AERO_3MODE )
#ifndef WRF_PORT
!Balwinder.Singh@pnnl.gov: For prescribed aerosols, these values are modified in the aerosol initialization subroutine
integer, parameter :: nspec_amode(ntot_amode) = (/ 6, 3, 3 /)
#else
integer :: nspec_amode(ntot_amode) = (/ 6, 3, 3 /)
#endif
#endif
integer, parameter :: nspec_amode_max = 6
! input mprognum_amode, mdiagnum_amode, mprogsfc_amode, mcalcwater_amode
#if ( defined MODAL_AERO_7MODE )
integer, parameter :: mprognum_amode(ntot_amode) = (/ 1, 1, 1, 1, 1, 1, 1/)
integer, parameter :: mdiagnum_amode(ntot_amode) = (/ 0, 0, 0, 0, 0, 0, 0/)
integer, parameter :: mprogsfc_amode(ntot_amode) = (/ 0, 0, 0, 0, 0, 0, 0/)
integer, parameter :: mcalcwater_amode(ntot_amode) = (/ 1, 1, 1, 1, 1, 1, 1/)
#elif ( defined MODAL_AERO_3MODE )
integer, parameter :: mprognum_amode(ntot_amode) = (/ 1, 1, 1/)
integer, parameter :: mdiagnum_amode(ntot_amode) = (/ 0, 0, 0/)
integer, parameter :: mprogsfc_amode(ntot_amode) = (/ 0, 0, 0/)
integer, parameter :: mcalcwater_amode(ntot_amode) = (/ 0, 0, 0/)
#endif
! input dgnum_amode, dgnumlo_amode, dgnumhi_amode (units = m)
#if ( defined MODAL_AERO_7MODE )
real(r8), parameter :: dgnum_amode(ntot_amode) = (/ 0.1100e-6, 0.0260e-6, 0.050e-6, 0.200e-6, 0.100e-6, 2.000e-6, 1.000e-6 /)
real(r8), parameter :: dgnumlo_amode(ntot_amode) = (/ 0.0535e-6, 0.0087e-6, 0.010e-6, 0.050e-6, 0.050e-6, 1.000e-6, 0.500e-6 /)
real(r8), parameter :: dgnumhi_amode(ntot_amode) = (/ 0.4400e-6, 0.0520e-6, 0.100e-6, 1.000e-6, 0.500e-6, 4.000e-6, 2.000e-6 /)
#elif ( defined MODAL_AERO_3MODE )
real(r8), parameter :: dgnum_amode(ntot_amode) = (/ 0.1100e-6, 0.0260e-6, 2.000e-6 /)
real(r8), parameter :: dgnumlo_amode(ntot_amode) = (/ 0.0535e-6, 0.0087e-6, 1.000e-6 /)
real(r8), parameter :: dgnumhi_amode(ntot_amode) = (/ 0.4400e-6, 0.0520e-6, 4.000e-6 /)
#endif
! input sigmag_amode, sigmaglo_amode, sigmaghi_amode
#if ( defined MODAL_AERO_7MODE )
real(r8), parameter :: sigmag_amode(ntot_amode) = (/ 1.800, 1.600, 1.600, 2.000, 1.800, 2.000, 1.800 /)
#elif ( defined MODAL_AERO_3MODE )
real(r8), parameter :: sigmag_amode(ntot_amode) = (/ 1.800, 1.600, 1.800 /)
#endif
! input crystalization and deliquescence points
#if ( defined MODAL_AERO_7MODE )
real(r8), parameter :: rhcrystal_amode(ntot_amode) = (/ 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350 /)
real(r8), parameter :: rhdeliques_amode(ntot_amode) = (/ 0.800, 0.800, 0.800, 0.800, 0.800, 0.800, 0.800 /)
#elif ( defined MODAL_AERO_3MODE )
real(r8), parameter :: rhcrystal_amode(ntot_amode) = (/ 0.350, 0.350, 0.350 /)
real(r8), parameter :: rhdeliques_amode(ntot_amode) = (/ 0.800, 0.800, 0.800 /)
#endif
integer :: msectional = -1
integer & !
lspectype_amode( maxd_aspectype, ntot_amode ), & !
lmassptr_amode( maxd_aspectype, ntot_amode ), & !
lmassptrcw_amode( maxd_aspectype, ntot_amode ), & !
numptr_amode( ntot_amode ), & !
numptrcw_amode( ntot_amode )
real(r8) :: & !
alnsg_amode( ntot_amode ), & !
voltonumb_amode( ntot_amode ), & !
voltonumblo_amode( ntot_amode ), & !
voltonumbhi_amode( ntot_amode ), & !
alnv2n_amode( ntot_amode ), & !
alnv2nlo_amode( ntot_amode ), & !
alnv2nhi_amode( ntot_amode ), & !
specdens_amode( maxd_aspectype ), & !
spechygro( maxd_aspectype )
complex & !
specrefndxsw( nswbands, maxd_aspectype ), & !
specrefndxlw( nlwbands, maxd_aspectype )
#ifndef WRF_PORT
character(len=16) :: cnst_name_cw( pcnst )
#else
character(len=16), allocatable :: cnst_name_cw( : )
#endif
character(len=8) :: aodvisname(ntot_amode ), &
ssavisname(ntot_amode )
character(len=48) :: aodvislongname(ntot_amode ), &
ssavislongname(ntot_amode )
character(len=8) :: fnactname(ntot_amode ), &
fmactname(ntot_amode ), &
nactname(ntot_amode )
character(len=48) :: fnactlongname(ntot_amode ), &
fmactlongname(ntot_amode ), &
nactlongname(ntot_amode )
integer & !
lptr_so4_a_amode(ntot_amode), lptr_so4_cw_amode(ntot_amode), & !
lptr_msa_a_amode(ntot_amode), lptr_msa_cw_amode(ntot_amode), & !
lptr_nh4_a_amode(ntot_amode), lptr_nh4_cw_amode(ntot_amode), & !
lptr_no3_a_amode(ntot_amode), lptr_no3_cw_amode(ntot_amode), & !
lptr_pom_a_amode(ntot_amode), lptr_pom_cw_amode(ntot_amode), & !
lptr_soa_a_amode(ntot_amode), lptr_soa_cw_amode(ntot_amode), & !
lptr_bc_a_amode(ntot_amode), lptr_bc_cw_amode(ntot_amode), & !
lptr_nacl_a_amode(ntot_amode), lptr_nacl_cw_amode(ntot_amode),& !
lptr_dust_a_amode(ntot_amode), lptr_dust_cw_amode(ntot_amode),& !
modeptr_accum, modeptr_aitken, & !
modeptr_ufine, modeptr_coarse, & !
modeptr_pcarbon, & !
modeptr_finedust, modeptr_fineseas, & !
modeptr_coardust, modeptr_coarseas
real(r8) :: &
specmw_so4_amode, specdens_so4_amode, &
specmw_nh4_amode, specdens_nh4_amode, &
specmw_no3_amode, specdens_no3_amode, &
specmw_pom_amode, specdens_pom_amode, &
specmw_soa_amode, specdens_soa_amode, &
specmw_bc_amode, specdens_bc_amode, &
specmw_dust_amode, specdens_dust_amode, &
specmw_seasalt_amode, specdens_seasalt_amode
#ifndef WRF_PORT
integer species_class(pcnst) ! indicates species class (
! cldphysics, aerosol, gas )
#else
integer, allocatable:: species_class(:) ! indicates species class (
! cldphysics, aerosol, gas )
#endif
integer spec_class_undefined
parameter ( spec_class_undefined = 0 )
integer spec_class_cldphysics
parameter ( spec_class_cldphysics = 1 )
integer spec_class_aerosol
parameter ( spec_class_aerosol = 2 )
integer spec_class_gas
parameter ( spec_class_gas = 3 )
integer spec_class_other
parameter ( spec_class_other = 4 )
! threshold for reporting negatives from subr qneg3
#ifndef WRF_PORT
real(r8) :: qneg3_worst_thresh_amode(pcnst)
#else
real(r8), allocatable :: qneg3_worst_thresh_amode(:)
#endif
#ifdef WRF_PORT
!Following variables are defined to assist CAMMGMP decoupled from
!CAM MAM package.
character(len=16), allocatable :: cnst_name_cw_mp(:)
integer :: msectional_mp = -1
integer :: modeptr_accum_mp
integer :: modeptr_coarse_mp
integer :: modeptr_coardust_mp !BSINGH - declared for MAM7 complaince
integer :: modeptr_aitken_mp
integer :: ntot_amode_mp = ntot_amode
integer :: numptrcw_amode_mp(ntot_amode)
integer :: lptr_dust_a_amode_mp(ntot_amode)
integer :: lptr_nacl_a_amode_mp(ntot_amode)
integer :: numptr_amode_mp(ntot_amode)
#if ( defined MODAL_AERO_7MODE )
integer :: nspec_amode_mp(ntot_amode) = (/ 6, 4, 2, 3, 3, 3, 3 /) ! SS
#elif ( defined MODAL_AERO_3MODE )
integer :: nspec_amode_mp(ntot_amode) = (/ 6, 3, 3 /)
#endif
integer :: lmassptr_amode_mp(maxd_aspectype, ntot_amode)
integer :: lspectype_amode_mp(maxd_aspectype, ntot_amode)
integer :: lmassptrcw_amode_mp(maxd_aspectype, ntot_amode)
real(r8) :: voltonumb_amode_mp( ntot_amode )
real(r8) :: alnsg_amode_mp( ntot_amode )
real(r8) :: voltonumbhi_amode_mp(ntot_amode)
real(r8) :: voltonumblo_amode_mp(ntot_amode)
real(r8) :: sigmag_amode_mp(ntot_amode) = sigmag_amode(1:ntot_amode)
real(r8) :: dgnum_amode_mp(ntot_amode) = dgnum_amode(1:ntot_amode)
real(r8) :: dgnumlo_amode_mp(ntot_amode) = dgnumlo_amode(1:ntot_amode)
real(r8) :: dgnumhi_amode_mp(ntot_amode) = dgnumhi_amode(ntot_amode)
real(r8) :: specdens_amode_mp( maxd_aspectype )
real(r8) :: specmw_amode_mp(ntot_aspectype)
real(r8) :: spechygro_mp( maxd_aspectype )
#endif
#ifndef WRF_PORT
integer, private :: qqcw(pcnst)=-1 ! Remaps modal_aero indices into pbuf
contains
subroutine qqcw_set_ptr(index, iptr),1
use abortutils, only : endrun
use time_manager, only : is_first_step
use phys_buffer, only : pbuf
integer, intent(in) :: index, iptr
if(index>0 .and. index <= pcnst ) then
qqcw(index)=iptr
else
call endrun
('attempting to set qqcw pointer already defined')
end if
end subroutine qqcw_set_ptr
function qqcw_get_field(index, lchnk, errorhandle),1
use abortutils, only : endrun
use phys_buffer, only : pbuf
integer, intent(in) :: index, lchnk
real(r8), pointer :: qqcw_get_field(:,:)
logical, optional :: errorhandle
if(index>0 .and. index <= pcnst .and. qqcw(index)>0) then
qqcw_get_field => pbuf(qqcw(index))%fld_ptr(1,:,:,lchnk,1)
else if(.not. present(errorhandle)) then
call endrun
('attempt to access undefined qqcw')
else
nullify(qqcw_get_field)
end if
end function qqcw_get_field
#endif
end module modal_aero_data
!----------------------------------------------------------------
!
! maxd_aspectype = maximum allowable number of chemical species
! in each aerosol mode
!
! ntot_amode = number of aerosol modes
! ( ntot_amode_gchm = number of aerosol modes in gchm
! ntot_amode_ccm2 = number of aerosol modes to be made known to ccm2
! These are temporary until multi-mode activation scavenging is going.
! Until then, ntot_amode is set to either ntot_amode_gchm or
! ntot_amode_ccm2 depending on which code is active )
!
! msectional - if positive, moving-center sectional code is utilized,
! and each mode is actually a section.
! msectional_concinit - if positive, special code is used to initialize
! the mixing ratios of all the sections.
!
! nspec_amode(m) = number of chemical species in aerosol mode m
! nspec_amode_ccm2(m) = . . . while in ccm2 code
! nspec_amode_gchm(m) = . . . while in gchm code
! nspec_amode_nontracer(m) = number of "non-tracer" chemical
! species while in gchm code
! lspectype_amode(l,m) = species type/i.d. for chemical species l
! in aerosol mode m. (1=sulfate, others to be defined)
! lmassptr_amode(l,m) = gchm r-array index for the mixing ratio
! (moles-x/mole-air) for chemical species l in aerosol mode m
! that is in clear air or interstitial air (but not in cloud water)
! lmassptrcw_amode(l,m) = gchm r-array index for the mixing ratio
! (moles-x/mole-air) for chemical species l in aerosol mode m
! that is currently bound/dissolved in cloud water
! lwaterptr_amode(m) = gchm r-array index for the mixing ratio
! (moles-water/mole-air) for water associated with aerosol mode m
! that is in clear air or interstitial air
! lkohlercptr_amode(m) = gchm r-array index for the kohler "c" parameter
! for aerosol mode m. This is defined on a per-dry-particle-mass basis:
! c = r(i,j,k,lkohlercptr_amode) * [rhodry * (4*pi/3) * rdry^3]
! numptr_amode(m) = gchm r-array index for the number mixing ratio
! (particles/mole-air) for aerosol mode m that is in clear air or
! interstitial are (but not in cloud water). If zero or negative,
! then number is not being simulated.
! ( numptr_amode_gchm(m) = same thing but for within gchm
! numptr_amode_ccm2(m) = same thing but for within ccm2
! These are temporary, to allow testing number in gchm before ccm2 )
! numptrcw_amode(m) = gchm r-array index for the number mixing ratio
! (particles/mole-air) for aerosol mode m
! that is currently bound/dissolved in cloud water
! lsfcptr_amode(m) = gchm r-array index for the surface area mixing ratio
! (cm^2/mole-air) for aerosol mode m that is in clear air or
! interstitial are (but not in cloud water). If zero or negative,
! then surface area is not being simulated.
! lsfcptrcw_amode(m) = gchm r-array index for the surface area mixing ratio
! (cm^2/mole-air) for aerosol mode m that is currently
! bound/dissolved in cloud water.
! lsigptr_amode(m) = gchm r-array index for sigmag for aerosol mode m
! that is in clear air or interstitial are (but not in cloud water).
! If zero or negative, then the constant sigmag_amode(m) is used.
! lsigptrcw_amode(m) = gchm r-array index for sigmag for aerosol mode m
! that is currently bound/dissolved in cloud water.
! If zero or negative, then the constant sigmag_amode(m) is used.
! lsigptrac_amode(m) = gchm r-array index for sigmag for aerosol mode m
! for combined clear-air/interstial plus bound/dissolved in cloud water.
! If zero or negative, then the constant sigmag_amode(m) is used.
!
! dgnum_amode(m) = geometric dry mean diameter (m) of the number
! distribution for aerosol mode m.
! (Only used when numptr_amode(m) is zero or negative.)
! dgnumlo_amode(m), dgnumhi_amode(m) = lower and upper limits on the
! geometric dry mean diameter (m) of the number distribution
! (Used when mprognum_amode>0, to limit dgnum to reasonable values)
! sigmag_amode(m) = geometric standard deviation for aerosol mode m
! sigmaglo_amode(m), sigmaghi_amode(m) = lower and upper limits on the
! geometric standard deviation of the number distribution
! (Used when mprogsfc_amode>0, to limit sigmag to reasonable values)
! alnsg_amode(m) = alog( sigmag_amode(m) )
! alnsglo_amode(m), alnsghi_amode(m) = alog( sigmaglo/hi_amode(m) )
! voltonumb_amode(m) = ratio of number to volume for mode m
! voltonumblo_amode(m), voltonumbhi_amode(m) = ratio of number to volume
! when dgnum = dgnumlo_amode or dgnumhi_amode, respectively
! voltosfc_amode(m), voltosfclo_amode(m), voltosfchi_amode(m) - ratio of
! surface to volume for mode m (like the voltonumb_amode's)
! alnv2n_amode(m), alnv2nlo_amode(m), alnv2nhi_amode(m) -
! alnv2n_amode(m) = alog( voltonumblo_amode(m) ), ...
! alnv2s_amode(m), alnv2slo_amode(m), alnv2shi_amode(m) -
! alnv2s_amode(m) = alog( voltosfclo_amode(m) ), ...
! rhcrystal_amode(m) = crystalization r.h. for mode m
! rhdeliques_amode(m) = deliquescence r.h. for mode m
! (*** these r.h. values are 0-1 fractions, not 0-100 percentages)
!
! mcalcwater_amode(m) - if positive, water content for mode m will be
! calculated and stored in rclm(k,lwaterptr_amode(m)). Otherwise, no.
! mprognum_amode(m) - if positive, number mixing-ratio for mode m will
! be prognosed. Otherwise, no.
! mdiagnum_amode(m) - if positive, number mixing-ratio for mode m will
! be diagnosed and put into rclm(k,numptr_amode(m)). Otherwise, no.
! mprogsfc_amode(m) - if positive, surface area mixing-ratio for mode m will
! be prognosed, and sigmag will vary temporally and spatially.
! Otherwise, sigmag is constant.
! *** currently surface area is not prognosed when msectional>0 ***
!
! ntot_aspectype = overall number of aerosol chemical species defined (over all modes)
! specdens_amode(l) = dry density (kg/m^3) of aerosol chemical species type l
! specmw_amode(l) = molecular weight (kg/kmol) of aerosol chemical species type l
! specname_amode(l) = name of aerosol chemical species type l
! specrefndxsw(l) = complex refractive index (visible wavelengths)
! of aerosol chemical species type l
! specrefndxlw(l) = complex refractive index (infrared wavelengths)
! of aerosol chemical species type l
! spechygro(l) = hygroscopicity of aerosol chemical species type l
!
! lptr_so4_a_amode(m), lptr_so4_cw_amode(m) = gchm r-array index for the
! mixing ratio for sulfate associated with aerosol mode m
! ("a" and "cw" phases)
! (similar for msa, oc, bc, nacl, dust)
!
! modename_amode(m) = character-variable name for mode m,
! read from mirage2.inp
! modeptr_accum - mode index for the main accumulation mode
! if modeptr_accum = 1, then mode 1 is the main accumulation mode,
! and modename_amode(1) = "accum"
! modeptr_aitken - mode index for the main aitken mode
! if modeptr_aitken = 2, then mode 2 is the main aitken mode,
! and modename_amode(2) = "aitken"
! modeptr_ufine - mode index for the ultrafine mode
! if modeptr_ufine = 3, then mode 3 is the ultrafine mode,
! and modename_amode(3) = "ufine"
! modeptr_coarseas - mode index for the coarse sea-salt mode
! if modeptr_coarseas = 4, then mode 4 is the coarse sea-salt mode,
! and modename_amode(4) = "coarse seasalt"
! modeptr_coardust - mode index for the coarse dust mode
! if modeptr_coardust = 5, then mode 5 is the coarse dust mode,
! and modename_amode(5) = "coarse dust"
!
! specdens_XX_amode = dry density (kg/m^3) of aerosol chemical species type XX
! where XX is so4, om, bc, dust, seasalt
! contains same values as the specdens_amode array
! allows values to be referenced differently
! specmw_XX_amode = molecular weight (kg/kmol) of aerosol chemical species type XX
! contains same values as the specmw_amode array
!
!-----------------------------------------------------------------------
!--------------------------------------------------------------
!
! ... aerosol size information for the current chunk
!
!--------------------------------------------------------------
!
! dgncur = current geometric mean diameters (cm) for number distributions
! dgncur_a - for unactivated particles, dry
! (in physics buffer as DGNUM)
! dgncur_awet - for unactivated particles, wet at grid-cell ambient RH
! (in physics buffer as DGNUMWET)
!
! the dgncur are computed from current mass and number
! mixing ratios in the grid cell, BUT are then adjusted to be within
! the bounds defined by dgnumlo/hi_amode
!
! v2ncur = current (number/volume) ratio based on dgncur and sgcur
! (volume in cm^3/whatever, number in particles/whatever)
! == 1.0 / ( pi/6 * dgncur**3 * exp(4.5*((log(sgcur))**2)) )
! v2ncur_a - for unactivated particles
! (currently just defined locally)
!