LCOV - code coverage report
Current view: top level - chemistry/modal_aero - aero_model.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 580 708 81.9 %
Date: 2024-12-17 22:39:59 Functions: 12 18 66.7 %

          Line data    Source code
       1             : !===============================================================================
       2             : ! Modal Aerosol Model
       3             : !===============================================================================
       4             : module aero_model
       5             :   use shr_kind_mod,   only: r8 => shr_kind_r8
       6             :   use constituents,   only: pcnst, cnst_name, cnst_get_ind
       7             :   use ppgrid,         only: pcols, pver, pverp
       8             :   use phys_control,   only: phys_getopts, cam_physpkg_is
       9             :   use cam_abortutils, only: endrun
      10             :   use cam_logfile,    only: iulog
      11             :   use perf_mod,       only: t_startf, t_stopf
      12             :   use camsrfexch,     only: cam_in_t, cam_out_t
      13             :   use aerodep_flx,    only: aerodep_flx_prescribed
      14             :   use physics_types,  only: physics_state, physics_ptend, physics_ptend_init
      15             :   use physics_buffer, only: physics_buffer_desc
      16             :   use physics_buffer, only: pbuf_get_field, pbuf_get_index, pbuf_set_field
      17             :   use physconst,      only: gravit, rair, rhoh2o
      18             :   use spmd_utils,     only: masterproc
      19             :   use infnan,         only: nan, assignment(=)
      20             : 
      21             :   use cam_history,    only: outfld, fieldname_len
      22             :   use chem_mods,      only: gas_pcnst, adv_mass
      23             :   use mo_tracname,    only: solsym
      24             : 
      25             :   use modal_aero_data,only: cnst_name_cw, lptr_so4_cw_amode
      26             :   use modal_aero_data,only: ntot_amode, modename_amode, nspec_max
      27             : 
      28             :   use ref_pres,       only: top_lev => clim_modal_aero_top_lev
      29             : 
      30             :   use modal_aero_wateruptake, only: modal_strat_sulfate
      31             :   use mo_setsox,              only: setsox, has_sox
      32             :   use modal_aerosol_properties_mod, only: modal_aerosol_properties
      33             : 
      34             :   implicit none
      35             :   private
      36             : 
      37             :   public :: aero_model_readnl
      38             :   public :: aero_model_register
      39             :   public :: aero_model_init
      40             :   public :: aero_model_gasaerexch ! create, grow, change, and shrink aerosols.
      41             :   public :: aero_model_drydep     ! aerosol dry deposition and sediment
      42             :   public :: aero_model_wetdep     ! aerosol wet removal
      43             :   public :: aero_model_emissions  ! aerosol emissions
      44             :   public :: aero_model_surfarea  ! tropopspheric aerosol wet surface area for chemistry
      45             :   public :: aero_model_strat_surfarea ! stratospheric aerosol wet surface area for chemistry
      46             : 
      47             :   public :: calc_1_impact_rate
      48             :   public :: nimptblgrow_mind, nimptblgrow_maxd
      49             : 
      50             :   ! Accessor functions
      51             :   public ::  get_scavimptblvol, get_scavimptblnum, get_dlndg_nimptblgrow
      52             : 
      53             :   ! Misc private data
      54             : 
      55             :   ! number of modes
      56             :   integer :: nmodes
      57             :   integer :: pblh_idx            = 0
      58             :   integer :: dgnum_idx           = 0
      59             :   integer :: dgnumwet_idx        = 0
      60             :   integer :: rate1_cw2pr_st_idx  = 0
      61             : 
      62             :   integer :: wetdens_ap_idx      = 0
      63             :   integer :: qaerwat_idx         = 0
      64             : 
      65             :   integer :: fracis_idx          = 0
      66             :   integer :: prain_idx           = 0
      67             :   integer :: rprddp_idx          = 0
      68             :   integer :: rprdsh_idx          = 0
      69             :   integer :: nevapr_shcu_idx     = 0
      70             :   integer :: nevapr_dpcu_idx     = 0
      71             : 
      72             :   integer :: sulfeq_idx = -1
      73             : 
      74             :   integer :: nh3_ndx    = 0
      75             :   integer :: nh4_ndx    = 0
      76             : 
      77             :   ! variables for table lookup of aerosol impaction/interception scavenging rates
      78             :   integer, parameter :: nimptblgrow_mind=-7, nimptblgrow_maxd=12
      79             :   real(r8) :: dlndg_nimptblgrow
      80             :   real(r8),allocatable :: scavimptblnum(:,:)
      81             :   real(r8),allocatable :: scavimptblvol(:,:)
      82             : 
      83             :   ! for surf_area_dens
      84             :   integer,allocatable :: num_idx(:)
      85             :   integer,allocatable :: index_tot_mass(:,:)
      86             :   integer,allocatable :: index_chm_mass(:,:)
      87             : 
      88             :   integer :: ndx_h2so4
      89             :   character(len=fieldname_len), allocatable :: dgnum_name(:), dgnumwet_name(:)
      90             : 
      91             :   ! Namelist variables
      92             :   character(len=16) :: drydep_list(pcnst) = ' '
      93             :   real(r8)          :: seasalt_emis_scale
      94             : 
      95             :   integer :: ndrydep = 0
      96             :   integer,allocatable :: drydep_indices(:)
      97             :   logical :: drydep_lq(pcnst)
      98             : 
      99             :   logical :: modal_accum_coarse_exch = .false.
     100             : 
     101             :   type(modal_aerosol_properties), pointer :: aero_props=>null()
     102             : 
     103             : contains
     104             : 
     105             :   !=============================================================================
     106             :   ! reads aerosol namelist options
     107             :   !=============================================================================
     108        1536 :   subroutine aero_model_readnl(nlfile)
     109             : 
     110             :     use namelist_utils,  only: find_group_name
     111             :     use units,           only: getunit, freeunit
     112             :     use mpishorthand
     113             :     use aero_wetdep_cam, only: aero_wetdep_readnl
     114             : 
     115             :     character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
     116             : 
     117             :     ! Local variables
     118             :     integer :: unitn, ierr
     119             :     character(len=*), parameter :: subname = 'aero_model_readnl'
     120             : 
     121             :     ! Namelist variables
     122             :     character(len=16) :: aer_drydep_list(pcnst) = ' '
     123             : 
     124             :     namelist /aerosol_nl/ aer_drydep_list, modal_strat_sulfate, modal_accum_coarse_exch, seasalt_emis_scale
     125             : 
     126             :     !-----------------------------------------------------------------------------
     127             : 
     128             :     ! Read namelist
     129        1536 :     if (masterproc) then
     130           2 :        unitn = getunit()
     131           2 :        open( unitn, file=trim(nlfile), status='old' )
     132           2 :        call find_group_name(unitn, 'aerosol_nl', status=ierr)
     133           2 :        if (ierr == 0) then
     134           2 :           read(unitn, aerosol_nl, iostat=ierr)
     135           2 :           if (ierr /= 0) then
     136           0 :              call endrun(subname // ':: ERROR reading namelist')
     137             :           end if
     138             :        end if
     139           2 :        close(unitn)
     140           2 :        call freeunit(unitn)
     141             :     end if
     142             : 
     143             : #ifdef SPMD
     144             :     ! Broadcast namelist variables
     145        1536 :     call mpibcast(aer_drydep_list,   len(aer_drydep_list(1))*pcnst, mpichar, 0, mpicom)
     146        1536 :     call mpibcast(modal_strat_sulfate,     1,                       mpilog,  0, mpicom)
     147        1536 :     call mpibcast(seasalt_emis_scale, 1,                            mpir8,   0, mpicom)
     148        1536 :     call mpibcast(modal_accum_coarse_exch, 1,                       mpilog,  0, mpicom)
     149             : #endif
     150             : 
     151       64512 :     drydep_list = aer_drydep_list
     152             : 
     153        1536 :     call aero_wetdep_readnl(nlfile)
     154             : 
     155        1536 :   end subroutine aero_model_readnl
     156             : 
     157             :   !=============================================================================
     158             :   !=============================================================================
     159        1536 :   subroutine aero_model_register()
     160        1536 :     use modal_aero_data, only: modal_aero_data_reg
     161             : 
     162        1536 :     call modal_aero_data_reg()
     163             : 
     164        1536 :   end subroutine aero_model_register
     165             : 
     166             :   !=============================================================================
     167             :   !=============================================================================
     168        1536 :   subroutine aero_model_init( pbuf2d )
     169             : 
     170             :     use mo_chem_utls,    only: get_inv_ndx
     171             :     use cam_history,     only: addfld, add_default, horiz_only
     172        1536 :     use mo_chem_utls,    only: get_spc_ndx
     173             :     use modal_aero_data, only: cnst_name_cw
     174             :     use modal_aero_data, only: modal_aero_data_init
     175             :     use rad_constituents,only: rad_cnst_get_info
     176             :     use dust_model,      only: dust_init, dust_names, dust_active, dust_nbin, dust_nnum
     177             :     use seasalt_model,   only: seasalt_init, seasalt_names, seasalt_active,seasalt_nbin
     178             :     use aer_drydep_mod,  only: inidrydep
     179             :     use aero_wetdep_cam, only: aero_wetdep_init
     180             : 
     181             :     use modal_aero_calcsize,   only: modal_aero_calcsize_init
     182             :     use modal_aero_coag,       only: modal_aero_coag_init
     183             :     use aero_deposition_cam, only: aero_deposition_cam_init
     184             :     use modal_aero_gasaerexch, only: modal_aero_gasaerexch_init
     185             :     use modal_aero_newnuc,     only: modal_aero_newnuc_init
     186             :     use modal_aero_rename,     only: modal_aero_rename_init
     187             : 
     188             :     ! args
     189             :     type(physics_buffer_desc), pointer :: pbuf2d(:,:)
     190             : 
     191             :     ! local vars
     192             :     character(len=*), parameter :: subrname = 'aero_model_init'
     193             :     integer :: m, n, id
     194             :     character(len=20) :: dummy
     195             : 
     196             :     logical  :: history_aerosol ! Output MAM or SECT aerosol tendencies
     197             :     logical  :: history_chemistry, history_cesm_forcing, history_dust
     198             : 
     199             :     integer :: l
     200             :     character(len=6) :: test_name
     201             :     character(len=64) :: errmes
     202             : 
     203             :     character(len=2)  :: unit_basename  ! Units 'kg' or '1'
     204             :     integer :: errcode
     205             :     character(len=fieldname_len) :: field_name
     206             : 
     207             :     character(len=32) :: spec_name
     208             :     character(len=32) :: spec_type
     209             :     character(len=32) :: mode_type
     210             :     integer :: nspec
     211             : 
     212        1536 :     dgnum_idx       = pbuf_get_index('DGNUM')
     213        1536 :     dgnumwet_idx    = pbuf_get_index('DGNUMWET')
     214        1536 :     fracis_idx      = pbuf_get_index('FRACIS')
     215        1536 :     prain_idx       = pbuf_get_index('PRAIN')
     216        1536 :     rprddp_idx      = pbuf_get_index('RPRDDP')
     217        1536 :     rprdsh_idx      = pbuf_get_index('RPRDSH')
     218        1536 :     nevapr_shcu_idx = pbuf_get_index('NEVAPR_SHCU')
     219        1536 :     nevapr_dpcu_idx = pbuf_get_index('NEVAPR_DPCU')
     220        1536 :     sulfeq_idx      = pbuf_get_index('MAMH2SO4EQ',errcode)
     221             : 
     222             :     call phys_getopts(history_aerosol_out = history_aerosol, &
     223             :                       history_chemistry_out=history_chemistry, &
     224             :                       history_cesm_forcing_out=history_cesm_forcing, &
     225        1536 :                       history_dust_out=history_dust)
     226             : 
     227        1536 :     call rad_cnst_get_info(0, nmodes=nmodes)
     228             : 
     229        1536 :     call modal_aero_data_init(pbuf2d)
     230        1536 :     call modal_aero_bcscavcoef_init()
     231             : 
     232        1536 :     call modal_aero_rename_init( modal_accum_coarse_exch )
     233             :     !   calcsize call must follow rename call
     234        1536 :     call modal_aero_calcsize_init( pbuf2d )
     235        1536 :     call modal_aero_gasaerexch_init
     236             :     !   coag call must follow gasaerexch call
     237        1536 :     call modal_aero_coag_init
     238        1536 :     call modal_aero_newnuc_init
     239             : 
     240             :     ! call aero_deposition_cam_init only if the user has not specified
     241             :     ! prescribed aerosol deposition fluxes
     242        1536 :     if (.not.aerodep_flx_prescribed()) then
     243        1536 :        aero_props => modal_aerosol_properties()
     244        1536 :        call aero_deposition_cam_init(aero_props)
     245             :     endif
     246             : 
     247        1536 :     call dust_init()
     248        1536 :     call seasalt_init(seasalt_emis_scale)
     249             : 
     250        1536 :     ndrydep = 0
     251             : 
     252       64512 :     count_species: do m = 1,pcnst
     253       64512 :        if ( len_trim(drydep_list(m)) /= 0 ) then
     254       29184 :           ndrydep = ndrydep+1
     255             :        endif
     256             :     enddo count_species
     257             : 
     258        1536 :     if (ndrydep>0) &
     259        4608 :          allocate(drydep_indices(ndrydep))
     260             : 
     261       30720 :     do m = 1,ndrydep
     262       29184 :        call cnst_get_ind ( drydep_list(m), id, abort=.false. )
     263       29184 :        if (id>0) then
     264       29184 :           drydep_indices(m) = id
     265             :        else
     266           0 :           call endrun(subrname//': invalid drydep species: '//trim(drydep_list(m)) )
     267             :        endif
     268             : 
     269       30720 :        if (masterproc) then
     270          38 :           write(iulog,*) subrname//': '//drydep_list(m)//' will have drydep applied'
     271             :        endif
     272             :     enddo
     273             : 
     274        1536 :     if (ndrydep>0) then
     275             : 
     276        1536 :        call inidrydep(rair, gravit)
     277             : 
     278        1536 :        dummy = 'RAM1'
     279        1536 :        call addfld (dummy,horiz_only, 'A','frac','RAM1')
     280        1536 :        if ( history_aerosol ) then
     281           0 :           call add_default (dummy, 1, ' ')
     282             :        endif
     283        1536 :        dummy = 'airFV'
     284        1536 :        call addfld (dummy,horiz_only, 'A','frac','FV')
     285        1536 :        if ( history_aerosol ) then
     286           0 :           call add_default (dummy, 1, ' ')
     287             :        endif
     288             : 
     289             :     endif
     290             : 
     291        1536 :     if (dust_active) then
     292             :        ! emissions diagnostics ....
     293             : 
     294       10752 :        do m = 1, dust_nbin+dust_nnum
     295        9216 :           dummy = trim(dust_names(m)) // 'SF'
     296        9216 :           call addfld (dummy,horiz_only, 'A','kg/m2/s',trim(dust_names(m))//' dust surface emission')
     297       10752 :           if (history_aerosol.or.history_chemistry) then
     298        9216 :              call add_default (dummy, 1, ' ')
     299             :           endif
     300             :        enddo
     301             : 
     302        1536 :        dummy = 'DSTSFMBL'
     303        1536 :        call addfld (dummy,horiz_only, 'A','kg/m2/s','Mobilization flux at surface')
     304        1536 :        if (history_aerosol .or. history_dust) then
     305           0 :           call add_default (dummy, 1, ' ')
     306             :        endif
     307             : 
     308        1536 :        dummy = 'LND_MBL'
     309        1536 :        call addfld (dummy,horiz_only, 'A','frac','Soil erodibility factor')
     310        1536 :        if (history_aerosol) then
     311           0 :           call add_default (dummy, 1, ' ')
     312             :        endif
     313             : 
     314             :     endif
     315             : 
     316        1536 :     if (seasalt_active) then
     317             : 
     318        1536 :        dummy = 'SSTSFMBL'
     319        1536 :        call addfld (dummy,horiz_only, 'A','kg/m2/s','Mobilization flux at surface')
     320        1536 :        if (history_aerosol) then
     321           0 :           call add_default (dummy, 1, ' ')
     322             :        endif
     323             : 
     324        6144 :        do m = 1, seasalt_nbin
     325        4608 :           dummy = trim(seasalt_names(m)) // 'SF'
     326        4608 :           call addfld (dummy,horiz_only, 'A','kg/m2/s',trim(seasalt_names(m))//' seasalt surface emission')
     327        6144 :           if (history_aerosol.or.history_chemistry) then
     328        4608 :              call add_default (dummy, 1, ' ')
     329             :           endif
     330             :        enddo
     331             : 
     332             :     endif
     333             : 
     334             : 
     335             :     ! set flags for drydep tendencies
     336        1536 :     drydep_lq(:) = .false.
     337       30720 :     do m=1,ndrydep
     338       29184 :        id = drydep_indices(m)
     339       30720 :        drydep_lq(id) =  .true.
     340             :     enddo
     341             : 
     342        1536 :     wetdens_ap_idx = pbuf_get_index('WETDENS_AP')
     343        1536 :     qaerwat_idx    = pbuf_get_index('QAERWAT')
     344        1536 :     pblh_idx       = pbuf_get_index('pblh')
     345             : 
     346        1536 :     rate1_cw2pr_st_idx  = pbuf_get_index('RATE1_CW2PR_ST')
     347        1536 :     call pbuf_set_field(pbuf2d, rate1_cw2pr_st_idx, 0.0_r8)
     348             : 
     349       30720 :     do m = 1,ndrydep
     350             : 
     351             :        ! units
     352       29184 :        if (drydep_list(m)(1:3) == 'num') then
     353        6144 :           unit_basename = ' 1'
     354             :        else
     355       23040 :           unit_basename = 'kg'
     356             :        endif
     357             : 
     358             :        call addfld (trim(drydep_list(m))//'DDF', horiz_only,  'A',unit_basename//'/m2/s ', &
     359       29184 :             trim(drydep_list(m))//' dry deposition flux at bottom (grav + turb)')
     360             :        call addfld (trim(drydep_list(m))//'TBF', horiz_only,  'A',unit_basename//'/m2/s',  &
     361       29184 :             trim(drydep_list(m))//' turbulent dry deposition flux')
     362             :        call addfld (trim(drydep_list(m))//'GVF', horiz_only,  'A',unit_basename//'/m2/s ', &
     363       29184 :             trim(drydep_list(m))//' gravitational dry deposition flux')
     364             :        call addfld (trim(drydep_list(m))//'DTQ', (/ 'lev' /), 'A',unit_basename//'/kg/s ', &
     365       58368 :             trim(drydep_list(m))//' dry deposition')
     366             :        call addfld (trim(drydep_list(m))//'DDV', (/ 'lev' /), 'A','m/s',                   &
     367       58368 :             trim(drydep_list(m))//' deposition velocity')
     368             : 
     369       29184 :        if ( history_aerosol.or.history_chemistry ) then
     370       29184 :           call add_default (trim(drydep_list(m))//'DDF', 1, ' ')
     371             :        endif
     372       30720 :        if ( history_aerosol ) then
     373           0 :           call add_default (trim(drydep_list(m))//'TBF', 1, ' ')
     374           0 :           call add_default (trim(drydep_list(m))//'GVF', 1, ' ')
     375             :        endif
     376             : 
     377             :     enddo
     378             : 
     379       49152 :     do m = 1,gas_pcnst
     380             : 
     381       47616 :        if  ( solsym(m)(1:3) == 'num') then
     382        6144 :           unit_basename = ' 1'  ! Units 'kg' or '1'
     383             :        else
     384       41472 :           unit_basename = 'kg'  ! Units 'kg' or '1'
     385             :        end if
     386             : 
     387             :        call addfld( 'GS_'//trim(solsym(m)),horiz_only, 'A', unit_basename//'/m2/s ', &
     388       47616 :                     trim(solsym(m))//' gas chemistry/wet removal (for gas species)')
     389             :        call addfld( 'AQ_'//trim(solsym(m)),horiz_only, 'A', unit_basename//'/m2/s ', &
     390       47616 :                     trim(solsym(m))//' aqueous chemistry (for gas species)')
     391       49152 :        if ( history_aerosol ) then
     392           0 :           call add_default( 'AQ_'//trim(solsym(m)), 1, ' ')
     393             :        endif
     394             : 
     395             :     enddo
     396       64512 :     do n = 1,pcnst
     397       64512 :        if( .not. (cnst_name_cw(n) == ' ') ) then
     398             : 
     399       29184 :           if (cnst_name_cw(n)(1:3) == 'num') then
     400        6144 :              unit_basename = ' 1'
     401             :           else
     402       23040 :              unit_basename = 'kg'
     403             :           endif
     404             : 
     405             :           call addfld( cnst_name_cw(n),                (/ 'lev' /), 'A', unit_basename//'/kg ',   &
     406       58368 :                trim(cnst_name_cw(n))//' in cloud water')
     407       29184 :           call addfld (trim(cnst_name_cw(n))//'DDF',   horiz_only,  'A', unit_basename//'/m2/s ', &
     408       58368 :                trim(cnst_name_cw(n))//' dry deposition flux at bottom (grav + turb)')
     409       29184 :           call addfld (trim(cnst_name_cw(n))//'TBF',   horiz_only,  'A', unit_basename//'/m2/s ', &
     410       58368 :                trim(cnst_name_cw(n))//' turbulent dry deposition flux')
     411       29184 :           call addfld (trim(cnst_name_cw(n))//'GVF',   horiz_only,  'A', unit_basename//'/m2/s ', &
     412       58368 :                trim(cnst_name_cw(n))//' gravitational dry deposition flux')
     413             : 
     414       29184 :           if ( history_aerosol.or. history_chemistry ) then
     415       29184 :              call add_default( cnst_name_cw(n), 1, ' ' )
     416             :           endif
     417       29184 :           if ( history_aerosol ) then
     418           0 :              call add_default (trim(cnst_name_cw(n))//'GVF', 1, ' ')
     419           0 :              call add_default (trim(cnst_name_cw(n))//'TBF', 1, ' ')
     420           0 :              call add_default (trim(cnst_name_cw(n))//'DDF', 1, ' ')
     421             :           endif
     422             :        endif
     423             :     enddo
     424             : 
     425        6144 :     allocate(dgnum_name(ntot_amode), dgnumwet_name(ntot_amode))
     426        7680 :     do n=1,ntot_amode
     427        6144 :        dgnum_name(n) = ' '
     428        6144 :        dgnumwet_name(n) = ' '
     429        6144 :        write(dgnum_name(n),fmt='(a,i1)') 'dgnum',n
     430        6144 :        write(dgnumwet_name(n),fmt='(a,i1)') 'dgnumwet',n
     431       12288 :        call addfld( dgnum_name(n),    (/ 'lev' /), 'I', 'm', 'Aerosol mode dry diameter' )
     432       12288 :        call addfld( dgnumwet_name(n), (/ 'lev' /), 'I', 'm', 'Aerosol mode wet diameter' )
     433        6144 :        if ( history_aerosol ) then
     434           0 :           call add_default( dgnum_name(n), 1, ' ' )
     435           0 :           call add_default( dgnumwet_name(n), 1, ' ' )
     436             :        endif
     437        6144 :        if ( history_cesm_forcing .and. n<4 ) then
     438           0 :           call add_default( dgnumwet_name(n), 8, ' ' )
     439             :        endif
     440             : 
     441        7680 :        if (modal_strat_sulfate) then
     442           0 :           field_name = ' '
     443           0 :           write(field_name,fmt='(a,i1)') 'wtpct_a',n
     444           0 :           call addfld( field_name, (/ 'lev' /), 'I', '%', 'Aerosol mode weight percent H2SO4' )
     445           0 :           if ( history_aerosol ) then
     446           0 :              call add_default (field_name, 0, 'I')
     447             :           endif
     448             : 
     449           0 :           field_name = ' '
     450           0 :           write(field_name,fmt='(a,i1)') 'sulfeq_a',n
     451           0 :           call addfld( field_name, (/ 'lev' /), 'I', 'kg/kg', 'H2SO4 equilibrium mixing ratio' )
     452           0 :           if ( history_aerosol ) then
     453           0 :              call add_default (field_name, 0, 'I')
     454             :           endif
     455             : 
     456           0 :           field_name = ' '
     457           0 :           write(field_name,fmt='(a,i1)') 'sulden_a',n
     458           0 :           call addfld( field_name, (/ 'lev' /), 'I', 'g/cm3', 'Sulfate aerosol particle mass density' )
     459           0 :           if ( history_aerosol ) then
     460           0 :              call add_default (field_name, 0, 'I')
     461             :           endif
     462             : 
     463             :        end if
     464             :     end do
     465             : 
     466        1536 :     ndx_h2so4 = get_spc_ndx('H2SO4')
     467        1536 :     nh3_ndx = get_spc_ndx('NH3')
     468        1536 :     nh4_ndx = get_spc_ndx('NH4')
     469             : 
     470        4608 :     allocate(num_idx(ntot_amode))
     471        7680 :     num_idx = -1
     472             : 
     473             :     ! for aero_model_surfarea called from mo_usrrxt
     474        7680 :     do l=1,ntot_amode
     475        6144 :        test_name = ' '
     476        6144 :        write(test_name,fmt='(a5,i1)') 'num_a',l
     477        6144 :        num_idx(l) = get_spc_ndx( trim(test_name) )
     478        7680 :        if (num_idx(l) < 0) then
     479           0 :           write(errmes,fmt='(a,i1)') 'usrrxt_inti: cannot find MAM num_idx ',l
     480           0 :           write(iulog,*) errmes
     481           0 :           call endrun(errmes)
     482             :        endif
     483             :     end do
     484             : 
     485        6144 :     allocate(index_tot_mass(nmodes,nspec_max))
     486        4608 :     allocate(index_chm_mass(nmodes,nspec_max))
     487       47616 :     index_tot_mass = -1
     488       47616 :     index_chm_mass = -1
     489             : 
     490             :     ! for surf_area_dens
     491             :     ! define indices associated with the various aerosol types
     492        7680 :     do n = 1,nmodes
     493        6144 :        call rad_cnst_get_info(0, n, mode_type=mode_type, nspec=nspec)
     494        7680 :        if ( trim(mode_type) /= 'primary_carbon') then ! ignore the primary_carbon mode
     495       24576 :           do l = 1, nspec
     496       19968 :              call rad_cnst_get_info(0, n, l, spec_type=spec_type, spec_name=spec_name)
     497       19968 :              index_tot_mass(n,l) = get_spc_ndx(spec_name)
     498             :              if ( trim(spec_type) == 'sulfate'   .or. &
     499             :                   trim(spec_type) == 's-organic' .or. &
     500             :                   trim(spec_type) == 'p-organic' .or. &
     501       19968 :                   trim(spec_type) == 'black-c'   .or. &
     502        4608 :                   trim(spec_type) == 'ammonium') then
     503       10752 :                 index_chm_mass(n,l) = get_spc_ndx(spec_name)
     504             :              endif
     505             :           enddo
     506             :        endif
     507             :     enddo
     508             : 
     509        1536 :     if (has_sox) then
     510        7680 :        do m = 1, ntot_amode
     511             : 
     512        6144 :           l = lptr_so4_cw_amode(m)
     513        7680 :           if (l > 0) then
     514             :              call addfld (&
     515        4608 :                   trim(cnst_name_cw(l))//'AQSO4',horiz_only,  'A','kg/m2/s', &
     516        9216 :                   trim(cnst_name_cw(l))//' aqueous phase chemistry')
     517             :              call addfld (&
     518        4608 :                   trim(cnst_name_cw(l))//'AQH2SO4',horiz_only,  'A','kg/m2/s', &
     519        9216 :                   trim(cnst_name_cw(l))//' aqueous phase chemistry')
     520        4608 :              if ( history_aerosol ) then
     521           0 :                 call add_default (trim(cnst_name_cw(l))//'AQSO4', 1, ' ')
     522           0 :                 call add_default (trim(cnst_name_cw(l))//'AQH2SO4', 1, ' ')
     523             :              endif
     524             :           end if
     525             : 
     526             :        end do
     527             : 
     528        3072 :        call addfld( 'XPH_LWC',    (/ 'lev' /), 'A','kg/kg',   'pH value multiplied by lwc')
     529        1536 :        call addfld ('AQSO4_H2O2', horiz_only,  'A','kg/m2/s', 'SO4 aqueous phase chemistry due to H2O2')
     530        1536 :        call addfld ('AQSO4_O3',   horiz_only,  'A','kg/m2/s', 'SO4 aqueous phase chemistry due to O3')
     531             : 
     532        1536 :        if ( history_aerosol ) then
     533           0 :           call add_default ('XPH_LWC', 1, ' ')
     534           0 :           call add_default ('AQSO4_H2O2', 1, ' ')
     535           0 :           call add_default ('AQSO4_O3', 1, ' ')
     536             :        endif
     537             :     endif
     538             : 
     539        1536 :     call aero_wetdep_init()
     540             : 
     541        3072 :   end subroutine aero_model_init
     542             : 
     543             :   !=============================================================================
     544             :   !=============================================================================
     545    64034568 :   subroutine aero_model_drydep  ( state, pbuf, obklen, ustar, cam_in, dt, cam_out, ptend )
     546             : 
     547        1536 :     use dust_sediment_mod, only: dust_sediment_tend
     548             :     use aer_drydep_mod,    only: d3ddflux, calcram
     549             :     use modal_aero_data,   only: qqcw_get_field
     550             :     use modal_aero_data,   only: cnst_name_cw
     551             :     use modal_aero_data,   only: alnsg_amode
     552             :     use modal_aero_data,   only: sigmag_amode
     553             :     use modal_aero_data,   only: nspec_amode
     554             :     use modal_aero_data,   only: numptr_amode
     555             :     use modal_aero_data,   only: numptrcw_amode
     556             :     use modal_aero_data,   only: lmassptr_amode
     557             :     use modal_aero_data,   only: lmassptrcw_amode
     558             :     use aero_deposition_cam,only: aero_deposition_cam_setdry
     559             : 
     560             :   ! args
     561             :     type(physics_state),    intent(in)    :: state     ! Physics state variables
     562             :     real(r8),               intent(in)    :: obklen(:)
     563             :     real(r8),               intent(in)    :: ustar(:)  ! sfc fric vel
     564             :     type(cam_in_t), target, intent(in)    :: cam_in    ! import state
     565             :     real(r8),               intent(in)    :: dt             ! time step
     566             :     type(cam_out_t),        intent(inout) :: cam_out   ! export state
     567             :     type(physics_ptend),    intent(out)   :: ptend     ! indivdual parameterization tendencies
     568             :     type(physics_buffer_desc),    pointer :: pbuf(:)
     569             : 
     570             :   ! local vars
     571     1489176 :     real(r8), pointer :: landfrac(:) ! land fraction
     572     1489176 :     real(r8), pointer :: icefrac(:)  ! ice fraction
     573     1489176 :     real(r8), pointer :: ocnfrac(:)  ! ocean fraction
     574     1489176 :     real(r8), pointer :: fvin(:)     !
     575     1489176 :     real(r8), pointer :: ram1in(:)   ! for dry dep velocities from land model for progseasalts
     576             : 
     577             :     real(r8) :: fv(pcols)            ! for dry dep velocities, from land modified over ocean & ice
     578             :     real(r8) :: ram1(pcols)          ! for dry dep velocities, from land modified over ocean & ice
     579             : 
     580             :     integer :: lchnk                   ! chunk identifier
     581             :     integer :: ncol                    ! number of atmospheric columns
     582             :     integer :: jvlc                    ! index for last dimension of vlc_xxx arrays
     583             :     integer :: lphase                  ! index for interstitial / cloudborne aerosol
     584             :     integer :: lspec                   ! index for aerosol number / chem-mass / water-mass
     585             :     integer :: m                       ! aerosol mode index
     586             :     integer :: mm                      ! tracer index
     587             :     integer :: i
     588             : 
     589             :     real(r8) :: tvs(pcols,pver)
     590             :     real(r8) :: rho(pcols,pver)      ! air density in kg/m3
     591             :     real(r8) :: sflx(pcols)          ! deposition flux
     592             :     real(r8) :: dep_trb(pcols)       !kg/m2/s
     593             :     real(r8) :: dep_grv(pcols)       !kg/m2/s (total of grav and trb)
     594             :     real(r8) :: pvmzaer(pcols,pverp) ! sedimentation velocity in Pa
     595             :     real(r8) :: dqdt_tmp(pcols,pver) ! temporary array to hold tendency for 1 species
     596             : 
     597             :     real(r8) :: rad_drop(pcols,pver)
     598             :     real(r8) :: dens_drop(pcols,pver)
     599             :     real(r8) :: sg_drop(pcols,pver)
     600             :     real(r8) :: rad_aer(pcols,pver)
     601             :     real(r8) :: dens_aer(pcols,pver)
     602             :     real(r8) :: sg_aer(pcols,pver)
     603             : 
     604             :     real(r8) :: vlc_dry(pcols,pver,4)     ! dep velocity
     605             :     real(r8) :: vlc_grv(pcols,pver,4)     ! dep velocity
     606             :     real(r8)::  vlc_trb(pcols,4)          ! dep velocity
     607             :     real(r8) :: aerdepdryis(pcols,pcnst)  ! aerosol dry deposition (interstitial)
     608             :     real(r8) :: aerdepdrycw(pcols,pcnst)  ! aerosol dry deposition (cloud water)
     609     1489176 :     real(r8), pointer :: fldcw(:,:)
     610     1489176 :     real(r8), pointer :: dgncur_awet(:,:,:)
     611     1489176 :     real(r8), pointer :: wetdens(:,:,:)
     612     1489176 :     real(r8), pointer :: qaerwat(:,:,:)
     613             : 
     614     1489176 :     landfrac => cam_in%landfrac(:)
     615     1489176 :     icefrac  => cam_in%icefrac(:)
     616     1489176 :     ocnfrac  => cam_in%ocnfrac(:)
     617     1489176 :     fvin     => cam_in%fv(:)
     618     1489176 :     ram1in   => cam_in%ram1(:)
     619             : 
     620     1489176 :     lchnk = state%lchnk
     621     1489176 :     ncol  = state%ncol
     622             : 
     623             :     ! calc ram and fv over ocean and sea ice ...
     624             :     call calcram( ncol,landfrac,icefrac,ocnfrac,obklen,&
     625             :                   ustar,ram1in,ram1,state%t(:,pver),state%pmid(:,pver),&
     626     1489176 :                   state%pdel(:,pver),fvin,fv)
     627             : 
     628     1489176 :     call outfld( 'airFV', fv(:), pcols, lchnk )
     629     1489176 :     call outfld( 'RAM1', ram1(:), pcols, lchnk )
     630             : 
     631             :     ! note that tendencies are not only in sfc layer (because of sedimentation)
     632             :     ! and that ptend is updated within each subroutine for different species
     633             : 
     634     1489176 :     call physics_ptend_init(ptend, state%psetcols, 'aero_model_drydep', lq=drydep_lq)
     635             : 
     636     5956704 :     call pbuf_get_field(pbuf, dgnumwet_idx,   dgncur_awet, start=(/1,1,1/), kount=(/pcols,pver,nmodes/) )
     637     5956704 :     call pbuf_get_field(pbuf, wetdens_ap_idx, wetdens,     start=(/1,1,1/), kount=(/pcols,pver,nmodes/) )
     638     5956704 :     call pbuf_get_field(pbuf, qaerwat_idx,    qaerwat,     start=(/1,1,1/), kount=(/pcols,pver,nmodes/) )
     639             : 
     640  2314006344 :     tvs(:ncol,:) = state%t(:ncol,:)!*(1+state%q(:ncol,k)
     641  2314006344 :     rho(:ncol,:)=  state%pmid(:ncol,:)/(rair*state%t(:ncol,:))
     642             : 
     643             : !
     644             : ! calc settling/deposition velocities for cloud droplets (and cloud-borne aerosols)
     645             : !
     646             : ! *** mean drop radius should eventually be computed from ndrop and qcldwtr
     647  2355876432 :     rad_drop(:,:) = 5.0e-6_r8
     648  2355876432 :     dens_drop(:,:) = rhoh2o
     649  2355876432 :     sg_drop(:,:) = 1.46_r8
     650     1489176 :     jvlc = 3
     651             :     call modal_aero_depvel_part( ncol,state%t(:,:), state%pmid(:,:), ram1, fv,  &
     652             :                      vlc_dry(:,:,jvlc), vlc_trb(:,jvlc), vlc_grv(:,:,jvlc),  &
     653     1489176 :                      rad_drop(:,:), dens_drop(:,:), sg_drop(:,:), 0, lchnk)
     654     1489176 :     jvlc = 4
     655             :     call modal_aero_depvel_part( ncol,state%t(:,:), state%pmid(:,:), ram1, fv,  &
     656             :                      vlc_dry(:,:,jvlc), vlc_trb(:,jvlc), vlc_grv(:,:,jvlc),  &
     657     1489176 :                      rad_drop(:,:), dens_drop(:,:), sg_drop(:,:), 3, lchnk)
     658             : 
     659             : 
     660             : 
     661     7445880 :     do m = 1, ntot_amode   ! main loop over aerosol modes
     662             : 
     663    19359288 :        do lphase = 1, 2   ! loop over interstitial / cloud-borne forms
     664             : 
     665    11913408 :           if (lphase == 1) then   ! interstial aerosol - calc settling/dep velocities of mode
     666             : 
     667             : ! rad_aer = volume mean wet radius (m)
     668             : ! dgncur_awet = geometric mean wet diameter for number distribution (m)
     669    11913408 :              rad_aer(1:ncol,:) = 0.5_r8*dgncur_awet(1:ncol,:,m)   &
     670  9267938784 :                                  *exp(1.5_r8*(alnsg_amode(m)**2))
     671             : ! dens_aer(1:ncol,:) = wet density (kg/m3)
     672  9256025376 :              dens_aer(1:ncol,:) = wetdens(1:ncol,:,m)
     673  9256025376 :              sg_aer(1:ncol,:) = sigmag_amode(m)
     674             : 
     675     5956704 :              jvlc = 1
     676             :              call modal_aero_depvel_part( ncol, state%t(:,:), state%pmid(:,:), ram1, fv,  &
     677             :                         vlc_dry(:,:,jvlc), vlc_trb(:,jvlc), vlc_grv(:,:,jvlc),  &
     678     5956704 :                         rad_aer(:,:), dens_aer(:,:), sg_aer(:,:), 0, lchnk)
     679     5956704 :              jvlc = 2
     680             :              call modal_aero_depvel_part( ncol, state%t(:,:), state%pmid(:,:), ram1, fv,  &
     681             :                         vlc_dry(:,:,jvlc), vlc_trb(:,jvlc), vlc_grv(:,:,jvlc),  &
     682     5956704 :                         rad_aer(:,:), dens_aer(:,:), sg_aer(:,:), 3, lchnk)
     683             :           end if
     684             : 
     685    86372208 :           do lspec = 0, nspec_amode(m)+1   ! loop over number + constituents + water
     686             : 
     687    68502096 :              if (lspec == 0) then   ! number
     688    11913408 :                 if (lphase == 1) then
     689     5956704 :                    mm = numptr_amode(m)
     690     5956704 :                    jvlc = 1
     691             :                 else
     692     5956704 :                    mm = numptrcw_amode(m)
     693     5956704 :                    jvlc = 3
     694             :                 endif
     695    56588688 :              else if (lspec <= nspec_amode(m)) then   ! non-water mass
     696    44675280 :                 if (lphase == 1) then
     697    22337640 :                    mm = lmassptr_amode(lspec,m)
     698    22337640 :                    jvlc = 2
     699             :                 else
     700    22337640 :                    mm = lmassptrcw_amode(lspec,m)
     701    22337640 :                    jvlc = 4
     702             :                 endif
     703             :              else   ! water mass
     704             : !   bypass dry deposition of aerosol water
     705             :                 cycle
     706             :                 if (lphase == 1) then
     707             :                    mm = 0
     708             : !                  mm = lwaterptr_amode(m)
     709             :                    jvlc = 2
     710             :                 else
     711             :                    mm = 0
     712             :                    jvlc = 4
     713             :                 endif
     714             :              endif
     715             : 
     716             : 
     717    56588688 :           if (mm <= 0) cycle
     718             : 
     719             : !         if (lphase == 1) then
     720    68502096 :           if ((lphase == 1) .and. (lspec <= nspec_amode(m))) then
     721    28294344 :              ptend%lq(mm) = .TRUE.
     722             : 
     723             :              ! use pvprogseasalts instead (means making the top level 0)
     724   472449744 :              pvmzaer(:ncol,1)=0._r8
     725 43966120536 :              pvmzaer(:ncol,2:pverp) = vlc_dry(:ncol,:,jvlc)
     726             : 
     727    28294344 :              call outfld( trim(cnst_name(mm))//'DDV', pvmzaer(:,2:pverp), pcols, lchnk )
     728             : 
     729             :              if(.true.) then ! use phil's method
     730             :              !      convert from meters/sec to pascals/sec
     731             :              !      pvprogseasalts(:,1) is assumed zero, use density from layer above in conversion
     732 43966120536 :                 pvmzaer(:ncol,2:pverp) = pvmzaer(:ncol,2:pverp) * rho(:ncol,:)*gravit
     733             : 
     734             :              !      calculate the tendencies and sfc fluxes from the above velocities
     735             :                 call dust_sediment_tend( &
     736             :                      ncol,             dt,       state%pint(:,:), state%pmid, state%pdel, state%t , &
     737    28294344 :                      state%q(:,:,mm),  pvmzaer,  ptend%q(:,:,mm), sflx  )
     738             :              else   !use charlie's method
     739             :                 call d3ddflux( ncol, vlc_dry(:,:,jvlc), state%q(:,:,mm), state%pmid, &
     740             :                                state%pdel, tvs, sflx, ptend%q(:,:,mm), dt )
     741             :              endif
     742             : 
     743             :              ! apportion dry deposition into turb and gravitational settling for tapes
     744    28294344 :              dep_trb = 0._r8
     745    28294344 :              dep_grv = 0._r8
     746   472449744 :              do i=1,ncol
     747   472449744 :                 if (vlc_dry(i,pver,jvlc) /= 0._r8) then
     748   444155400 :                    dep_trb(i)=sflx(i)*vlc_trb(i,jvlc)/vlc_dry(i,pver,jvlc)
     749   444155400 :                    dep_grv(i)=sflx(i)*vlc_grv(i,pver,jvlc)/vlc_dry(i,pver,jvlc)
     750             :                 end if
     751             :              enddo
     752             : 
     753    28294344 :              call outfld( trim(cnst_name(mm))//'DDF', sflx, pcols, lchnk)
     754    28294344 :              call outfld( trim(cnst_name(mm))//'TBF', dep_trb, pcols, lchnk )
     755    28294344 :              call outfld( trim(cnst_name(mm))//'GVF', dep_grv, pcols, lchnk )
     756    28294344 :              call outfld( trim(cnst_name(mm))//'DTQ', ptend%q(:,:,mm), pcols, lchnk)
     757   472449744 :              aerdepdryis(:ncol,mm) = sflx(:ncol)
     758             : 
     759    28294344 :           else if ((lphase == 1) .and. (lspec == nspec_amode(m)+1)) then  ! aerosol water
     760             :              ! use pvprogseasalts instead (means making the top level 0)
     761           0 :              pvmzaer(:ncol,1)=0._r8
     762           0 :              pvmzaer(:ncol,2:pverp) = vlc_dry(:ncol,:,jvlc)
     763             : 
     764             :              if(.true.) then ! use phil's method
     765             :              !      convert from meters/sec to pascals/sec
     766             :              !      pvprogseasalts(:,1) is assumed zero, use density from layer above in conversion
     767           0 :                 pvmzaer(:ncol,2:pverp) = pvmzaer(:ncol,2:pverp) * rho(:ncol,:)*gravit
     768             : 
     769             :              !      calculate the tendencies and sfc fluxes from the above velocities
     770             :                 call dust_sediment_tend( &
     771             :                      ncol,             dt,       state%pint(:,:), state%pmid, state%pdel, state%t , &
     772           0 :                      qaerwat(:,:,mm),  pvmzaer,  dqdt_tmp(:,:), sflx  )
     773             :              else   !use charlie's method
     774             :                 call d3ddflux( ncol, vlc_dry(:,:,jvlc), qaerwat(:,:,mm), state%pmid, &
     775             :                                state%pdel, tvs, sflx, dqdt_tmp(:,:), dt )
     776             :              endif
     777             : 
     778             :              ! apportion dry deposition into turb and gravitational settling for tapes
     779           0 :              dep_trb = 0._r8
     780           0 :              dep_grv = 0._r8
     781           0 :              do i=1,ncol
     782           0 :                 if (vlc_dry(i,pver,jvlc) /= 0._r8) then
     783           0 :                    dep_trb(i)=sflx(i)*vlc_trb(i,jvlc)/vlc_dry(i,pver,jvlc)
     784           0 :                    dep_grv(i)=sflx(i)*vlc_grv(i,pver,jvlc)/vlc_dry(i,pver,jvlc)
     785             :                 end if
     786             :              enddo
     787             : 
     788           0 :              qaerwat(1:ncol,:,mm) = qaerwat(1:ncol,:,mm) + dqdt_tmp(1:ncol,:) * dt
     789             : 
     790             :           else  ! lphase == 2
     791             :              ! use pvprogseasalts instead (means making the top level 0)
     792   472449744 :              pvmzaer(:ncol,1)=0._r8
     793 43966120536 :              pvmzaer(:ncol,2:pverp) = vlc_dry(:ncol,:,jvlc)
     794    28294344 :              fldcw => qqcw_get_field(pbuf, mm,lchnk)
     795             : 
     796             :              if(.true.) then ! use phil's method
     797             :              !      convert from meters/sec to pascals/sec
     798             :              !      pvprogseasalts(:,1) is assumed zero, use density from layer above in conversion
     799 43966120536 :                 pvmzaer(:ncol,2:pverp) = pvmzaer(:ncol,2:pverp) * rho(:ncol,:)*gravit
     800             : 
     801             :              !      calculate the tendencies and sfc fluxes from the above velocities
     802             :                 call dust_sediment_tend( &
     803             :                      ncol,             dt,       state%pint(:,:), state%pmid, state%pdel, state%t , &
     804    28294344 :                      fldcw(:,:),  pvmzaer,  dqdt_tmp(:,:), sflx  )
     805             :              else   !use charlie's method
     806             :                 call d3ddflux( ncol, vlc_dry(:,:,jvlc), fldcw(:,:), state%pmid, &
     807             :                                state%pdel, tvs, sflx, dqdt_tmp(:,:), dt )
     808             :              endif
     809             : 
     810             :              ! apportion dry deposition into turb and gravitational settling for tapes
     811    28294344 :              dep_trb = 0._r8
     812    28294344 :              dep_grv = 0._r8
     813   472449744 :              do i=1,ncol
     814   472449744 :                 if (vlc_dry(i,pver,jvlc) /= 0._r8) then
     815   444155400 :                    dep_trb(i)=sflx(i)*vlc_trb(i,jvlc)/vlc_dry(i,pver,jvlc)
     816   444155400 :                    dep_grv(i)=sflx(i)*vlc_grv(i,pver,jvlc)/vlc_dry(i,pver,jvlc)
     817             :                 end if
     818             :              enddo
     819             : 
     820 43966120536 :              fldcw(1:ncol,:) = fldcw(1:ncol,:) + dqdt_tmp(1:ncol,:) * dt
     821             : 
     822    28294344 :              call outfld( trim(cnst_name_cw(mm))//'DDF', sflx, pcols, lchnk)
     823    28294344 :              call outfld( trim(cnst_name_cw(mm))//'TBF', dep_trb, pcols, lchnk )
     824    28294344 :              call outfld( trim(cnst_name_cw(mm))//'GVF', dep_grv, pcols, lchnk )
     825   472449744 :              aerdepdrycw(:ncol,mm) = sflx(:ncol)
     826             : 
     827             :           endif
     828             : 
     829             :           enddo   ! lspec = 0, nspec_amode(m)+1
     830             :        enddo   ! lphase = 1, 2
     831             :     enddo   ! m = 1, ntot_amode
     832             : 
     833             :     ! if the user has specified prescribed aerosol dep fluxes then
     834             :     ! do not set cam_out dep fluxes according to the prognostic aerosols
     835     1489176 :     if (.not.aerodep_flx_prescribed()) then
     836     1489176 :        call aero_deposition_cam_setdry(aerdepdryis, aerdepdrycw, cam_out)
     837             :     endif
     838             : 
     839     2978352 :   endsubroutine aero_model_drydep
     840             : 
     841             :   !=============================================================================
     842             :   !=============================================================================
     843    62545392 :   subroutine aero_model_wetdep( state, dt, dlf, cam_out, ptend, pbuf)
     844             : 
     845     1489176 :     use aero_wetdep_cam, only: aero_wetdep_tend
     846             : 
     847             :     ! args
     848             : 
     849             :     type(physics_state), intent(in)    :: state       ! Physics state variables
     850             :     real(r8),            intent(in)    :: dt          ! time step
     851             :     real(r8),            intent(in)    :: dlf(:,:)    ! shallow+deep convective detrainment [kg/kg/s]
     852             :     type(cam_out_t),     intent(inout) :: cam_out     ! export state
     853             :     type(physics_ptend), intent(out)   :: ptend       ! indivdual parameterization tendencies
     854             :     type(physics_buffer_desc), pointer :: pbuf(:)
     855             : 
     856     1489176 :     call aero_wetdep_tend(state, dt, dlf, cam_out, ptend, pbuf)
     857             : 
     858     1489176 :   end subroutine aero_model_wetdep
     859             : 
     860             :   !-------------------------------------------------------------------------
     861             :   ! provides wet tropospheric aerosol surface area info for modal aerosols
     862             :   ! called from mo_usrrxt
     863             :   !-------------------------------------------------------------------------
     864           0 :   subroutine aero_model_surfarea( &
     865           0 :                   mmr, radmean, relhum, pmid, temp, strato_sad, sulfate, rho, ltrop, &
     866           0 :                   dlat, het1_ndx, pbuf, ncol, sfc, dm_aer, sad_trop, reff_trop )
     867             : 
     868             :     ! dummy args
     869             :     real(r8), intent(in)    :: pmid(:,:)
     870             :     real(r8), intent(in)    :: temp(:,:)
     871             :     real(r8), intent(in)    :: mmr(:,:,:)
     872             :     real(r8), intent(in)    :: radmean      ! mean radii in cm
     873             :     real(r8), intent(in)    :: strato_sad(:,:)
     874             :     integer,  intent(in)    :: ncol
     875             :     integer,  intent(in)    :: ltrop(:)
     876             :     real(r8), intent(in)    :: dlat(:)                    ! degrees latitude
     877             :     integer,  intent(in)    :: het1_ndx
     878             :     real(r8), intent(in)    :: relhum(:,:)
     879             :     real(r8), intent(in)    :: rho(:,:) ! total atm density (/cm^3)
     880             :     real(r8), intent(in)    :: sulfate(:,:)
     881             :     type(physics_buffer_desc), pointer :: pbuf(:)
     882             : 
     883             :     real(r8), intent(inout) :: sfc(:,:,:)
     884             :     real(r8), intent(inout) :: dm_aer(:,:,:)
     885             :     real(r8), intent(inout) :: sad_trop(:,:)
     886             :     real(r8), intent(out)   :: reff_trop(:,:)
     887             : 
     888             :     ! local vars
     889           0 :     real(r8), pointer, dimension(:,:,:) :: dgnumwet
     890           0 :     integer :: beglev(ncol)
     891           0 :     integer :: endlev(ncol)
     892             :     integer :: i,k
     893             : 
     894           0 :     call pbuf_get_field(pbuf, dgnumwet_idx, dgnumwet )
     895             : 
     896           0 :     beglev(:ncol)=ltrop(:ncol)+1
     897           0 :     endlev(:ncol)=pver
     898           0 :     call surf_area_dens( ncol, mmr, pmid, temp, dgnumwet, beglev, endlev, sad_trop, reff_trop, sfc=sfc )
     899             : 
     900           0 :     do i = 1,ncol
     901           0 :        do k = ltrop(i)+1,pver
     902           0 :           dm_aer(i,k,:) = dgnumwet(i,k,:) * 1.e2_r8 ! convert m to cm
     903             :        enddo
     904             :     enddo
     905             : 
     906     1489176 :   end subroutine aero_model_surfarea
     907             : 
     908             :   !-------------------------------------------------------------------------
     909             :   ! provides WET stratospheric aerosol surface area info for modal aerosols
     910             :   ! if modal_strat_sulfate = TRUE -- called from mo_gas_phase_chemdr
     911             :   !-------------------------------------------------------------------------
     912           0 :   subroutine aero_model_strat_surfarea( ncol, mmr, pmid, temp, ltrop, pbuf, strato_sad, reff_strat )
     913             : 
     914             :     ! dummy args
     915             :     integer,  intent(in)    :: ncol
     916             :     real(r8), intent(in)    :: mmr(:,:,:)
     917             :     real(r8), intent(in)    :: pmid(:,:)
     918             :     real(r8), intent(in)    :: temp(:,:)
     919             :     integer,  intent(in)    :: ltrop(:) ! tropopause level indices
     920             :     type(physics_buffer_desc), pointer :: pbuf(:)
     921             :     real(r8), intent(out)   :: strato_sad(:,:)
     922             :     real(r8), intent(out)   :: reff_strat(:,:)
     923             : 
     924             :     ! local vars
     925           0 :     real(r8), pointer, dimension(:,:,:) :: dgnumwet
     926           0 :     integer :: beglev(ncol)
     927           0 :     integer :: endlev(ncol)
     928             : 
     929           0 :     reff_strat = 0._r8
     930           0 :     strato_sad = 0._r8
     931             : 
     932           0 :     if (.not.modal_strat_sulfate) return
     933             : 
     934           0 :     call pbuf_get_field(pbuf, dgnumwet_idx, dgnumwet )
     935             : 
     936           0 :     beglev(:ncol)=top_lev
     937           0 :     endlev(:ncol)=ltrop(:ncol)
     938           0 :     call surf_area_dens( ncol, mmr, pmid, temp, dgnumwet, beglev, endlev, strato_sad, reff_strat )
     939             : 
     940           0 :   end subroutine aero_model_strat_surfarea
     941             : 
     942             :   !=============================================================================
     943             :   !=============================================================================
     944     1489176 :   subroutine aero_model_gasaerexch( loffset, ncol, lchnk, troplev, delt, reaction_rates, &
     945     1489176 :                                     tfld, pmid, pdel, mbar, relhum, &
     946     2978352 :                                     zm,  qh2o, cwat, cldfr, cldnum, &
     947     2978352 :                                     airdens, invariants, del_h2so4_gasprod,  &
     948     1489176 :                                     vmr0, vmr, pbuf )
     949             : 
     950             :     use time_manager,          only : get_nstep
     951             :     use modal_aero_coag,       only : modal_aero_coag_sub
     952             :     use modal_aero_gasaerexch, only : modal_aero_gasaerexch_sub
     953             :     use modal_aero_newnuc,     only : modal_aero_newnuc_sub
     954             :     use modal_aero_data,       only : cnst_name_cw, qqcw_get_field
     955             : 
     956             :     !-----------------------------------------------------------------------
     957             :     !      ... dummy arguments
     958             :     !-----------------------------------------------------------------------
     959             :     integer,  intent(in) :: loffset                ! offset applied to modal aero "pointers"
     960             :     integer,  intent(in) :: ncol                   ! number columns in chunk
     961             :     integer,  intent(in) :: lchnk                  ! chunk index
     962             :     integer,  intent(in) :: troplev(pcols)
     963             :     real(r8), intent(in) :: delt                   ! time step size (sec)
     964             :     real(r8), intent(in) :: reaction_rates(:,:,:)  ! reaction rates
     965             :     real(r8), intent(in) :: tfld(:,:)              ! temperature (K)
     966             :     real(r8), intent(in) :: pmid(:,:)              ! pressure at model levels (Pa)
     967             :     real(r8), intent(in) :: pdel(:,:)              ! pressure thickness of levels (Pa)
     968             :     real(r8), intent(in) :: mbar(:,:)              ! mean wet atmospheric mass ( amu )
     969             :     real(r8), intent(in) :: relhum(:,:)            ! relative humidity
     970             :     real(r8), intent(in) :: airdens(:,:)           ! total atms density (molec/cm**3)
     971             :     real(r8), intent(in) :: invariants(:,:,:)
     972             :     real(r8), intent(in) :: del_h2so4_gasprod(:,:)
     973             :     real(r8), intent(in) :: zm(:,:)
     974             :     real(r8), intent(in) :: qh2o(:,:)
     975             :     real(r8), intent(in) :: cwat(:,:)          ! cloud liquid water content (kg/kg)
     976             :     real(r8), intent(in) :: cldfr(:,:)
     977             :     real(r8), intent(in) :: cldnum(:,:)       ! droplet number concentration (#/kg)
     978             :     real(r8), intent(in) :: vmr0(:,:,:)       ! initial mixing ratios (before gas-phase chem changes)
     979             :     real(r8), intent(inout) :: vmr(:,:,:)         ! mixing ratios ( vmr )
     980             : 
     981             :     type(physics_buffer_desc), pointer :: pbuf(:)
     982             : 
     983             :     ! local vars
     984             : 
     985             :     integer :: n, m
     986             :     integer :: i,k,l
     987             :     integer :: nstep
     988             : 
     989     2978352 :     real(r8) :: del_h2so4_aeruptk(ncol,pver)
     990             : 
     991     1489176 :     real(r8), pointer :: dgnum(:,:,:), dgnumwet(:,:,:), wetdens(:,:,:)
     992     1489176 :     real(r8), pointer :: pblh(:)                    ! pbl height (m)
     993             : 
     994     2978352 :     real(r8), dimension(ncol) :: wrk
     995             :     character(len=32)         :: name
     996     2978352 :     real(r8) :: dvmrcwdt(ncol,pver,gas_pcnst)
     997     2978352 :     real(r8) :: dvmrdt(ncol,pver,gas_pcnst)
     998     2978352 :     real(r8) :: vmrcw(ncol,pver,gas_pcnst)            ! cloud-borne aerosol (vmr)
     999             : 
    1000     2978352 :     real(r8) ::  aqso4(ncol,ntot_amode)               ! aqueous phase chemistry
    1001     2978352 :     real(r8) ::  aqh2so4(ncol,ntot_amode)             ! aqueous phase chemistry
    1002     2978352 :     real(r8) ::  aqso4_h2o2(ncol)                     ! SO4 aqueous phase chemistry due to H2O2
    1003     2978352 :     real(r8) ::  aqso4_o3(ncol)                       ! SO4 aqueous phase chemistry due to O3
    1004     2978352 :     real(r8) ::  xphlwc(ncol,pver)                    ! pH value multiplied by lwc
    1005     2978352 :     real(r8) ::  nh3_beg(ncol,pver)
    1006     1489176 :     real(r8), pointer :: fldcw(:,:)
    1007     1489176 :     real(r8), pointer :: sulfeq(:,:,:)
    1008             : 
    1009             :     logical :: is_spcam_m2005
    1010             : !
    1011             : ! ... initialize nh3
    1012             : !
    1013     1489176 :     if ( nh3_ndx > 0 ) then
    1014           0 :       nh3_beg = vmr(1:ncol,:,nh3_ndx)
    1015             :     end if
    1016             : !
    1017     1489176 :     is_spcam_m2005   = cam_physpkg_is('spcam_m2005')
    1018             : 
    1019     1489176 :     call pbuf_get_field(pbuf, dgnum_idx,      dgnum)
    1020     1489176 :     call pbuf_get_field(pbuf, dgnumwet_idx,   dgnumwet )
    1021     1489176 :     call pbuf_get_field(pbuf, wetdens_ap_idx, wetdens )
    1022     1489176 :     call pbuf_get_field(pbuf, pblh_idx,       pblh)
    1023             : 
    1024     7445880 :     do n=1,ntot_amode
    1025     5956704 :        call outfld(dgnum_name(n), dgnum(1:ncol,1:pver,n), ncol, lchnk )
    1026     7445880 :        call outfld(dgnumwet_name(n), dgnumwet(1:ncol,1:pver,n), ncol, lchnk )
    1027             :     end do
    1028             : 
    1029             : ! do gas-aerosol exchange (h2so4, msa, nh3 condensation)
    1030             : 
    1031     1489176 :     nstep = get_nstep()
    1032             : 
    1033             :     ! calculate tendency due to gas phase chemistry and processes
    1034 71735685840 :     dvmrdt(:ncol,:,:) = (vmr(:ncol,:,:) - vmr0(:ncol,:,:)) / delt
    1035    47653632 :     do m = 1, gas_pcnst
    1036   770839056 :       wrk(:) = 0._r8
    1037  4339458864 :       do k = 1,pver
    1038 71734196664 :         wrk(:ncol) = wrk(:ncol) + dvmrdt(:ncol,k,m)*adv_mass(m)/mbar(:ncol,k)*pdel(:ncol,k)/gravit
    1039             :       end do
    1040    46164456 :       name = 'GS_'//trim(solsym(m))
    1041    47653632 :       call outfld( name, wrk(:ncol), ncol, lchnk )
    1042             :     enddo
    1043             : 
    1044             : !
    1045             : ! Aerosol processes ...
    1046             : !
    1047     1489176 :     call qqcw2vmr( lchnk, vmrcw, mbar, ncol, loffset, pbuf )
    1048             : 
    1049     1489176 :     if (.not. is_spcam_m2005) then  ! regular CAM
    1050 71735685840 :       dvmrdt(:ncol,:,:) = vmr(:ncol,:,:)
    1051 71735685840 :       dvmrcwdt(:ncol,:,:) = vmrcw(:ncol,:,:)
    1052             : 
    1053             :     ! aqueous chemistry ...
    1054             : 
    1055     1489176 :       if( has_sox ) then
    1056             :          call setsox(   &
    1057             :               ncol,     &
    1058             :               lchnk,    &
    1059             :               loffset,  &
    1060             :               delt,     &
    1061             :               pmid,     &
    1062             :               pdel,     &
    1063             :               tfld,     &
    1064             :               mbar,     &
    1065             :               cwat,     &
    1066             :               cldfr,    &
    1067             :               cldnum,   &
    1068             :               airdens,  &
    1069             :               invariants, &
    1070             :               vmrcw,    &
    1071             :               vmr,      &
    1072             :               xphlwc,   &
    1073             :               aqso4,    &
    1074             :               aqh2so4,  &
    1075             :               aqso4_h2o2, &
    1076             :               aqso4_o3  &
    1077     1489176 :               )
    1078             : 
    1079     7445880 :          do n = 1, ntot_amode
    1080     5956704 :             l = lptr_so4_cw_amode(n)
    1081     7445880 :             if (l > 0) then
    1082     4467528 :                call outfld( trim(cnst_name_cw(l))//'AQSO4',   aqso4(:ncol,n),   ncol, lchnk)
    1083     4467528 :                call outfld( trim(cnst_name_cw(l))//'AQH2SO4', aqh2so4(:ncol,n), ncol, lchnk)
    1084             :             end if
    1085             :          end do
    1086             : 
    1087     1489176 :          call outfld( 'AQSO4_H2O2', aqso4_h2o2(:ncol), ncol, lchnk)
    1088     1489176 :          call outfld( 'AQSO4_O3',   aqso4_o3(:ncol),   ncol, lchnk)
    1089     1489176 :          call outfld( 'XPH_LWC',    xphlwc(:ncol,:),   ncol, lchnk )
    1090             : 
    1091             :       endif
    1092             : 
    1093             : !   Tendency due to aqueous chemistry
    1094 71737175016 :     dvmrdt = (vmr - dvmrdt) / delt
    1095 71735685840 :     dvmrcwdt = (vmrcw - dvmrcwdt) / delt
    1096    47653632 :     do m = 1, gas_pcnst
    1097   770839056 :       wrk(:) = 0._r8
    1098  4339458864 :       do k = 1,pver
    1099 71734196664 :         wrk(:ncol) = wrk(:ncol) + dvmrdt(:ncol,k,m) * adv_mass(m)/mbar(:ncol,k)*pdel(:ncol,k)/gravit
    1100             :       end do
    1101    46164456 :       name = 'AQ_'//trim(solsym(m))
    1102    47653632 :       call outfld( name, wrk(:ncol), ncol, lchnk )
    1103             :     enddo
    1104             : 
    1105             :    else if (is_spcam_m2005) then  ! SPCAM ECPP
    1106             : ! when ECPP is used, aqueous chemistry is done in ECPP,
    1107             : ! and not updated here.
    1108             : ! Minghuai Wang, 2010-02 (Minghuai.Wang@pnl.gov)
    1109             : !
    1110           0 :       dvmrdt = 0.0_r8
    1111           0 :       dvmrcwdt = 0.0_r8
    1112             :    endif
    1113             : 
    1114             : ! do gas-aerosol exchange (h2so4, msa, nh3 condensation)
    1115             : 
    1116     1489176 :     if (ndx_h2so4 > 0) then
    1117  2314006344 :        del_h2so4_aeruptk(1:ncol,:) = vmr(1:ncol,:,ndx_h2so4)
    1118             :     else
    1119           0 :        del_h2so4_aeruptk(:,:) = 0.0_r8
    1120             :     endif
    1121             : 
    1122     1489176 :     call t_startf('modal_gas-aer_exchng')
    1123             : 
    1124     1489176 :     if ( sulfeq_idx>0 ) then
    1125           0 :        call pbuf_get_field( pbuf, sulfeq_idx, sulfeq )
    1126             :     else
    1127     1489176 :        nullify( sulfeq )
    1128             :     endif
    1129             : 
    1130             :     call modal_aero_gasaerexch_sub(            &
    1131             :          lchnk,    ncol,     nstep,            &
    1132             :          loffset,            delt,             &
    1133             :          tfld,     pmid,     pdel,             &
    1134             :          qh2o,               troplev,          &
    1135             :          vmr,                vmrcw,            &
    1136             :          dvmrdt,             dvmrcwdt,         &
    1137             :          dgnum,              dgnumwet,         &
    1138     1489176 :          sulfeq     )
    1139             : 
    1140     1489176 :     if (ndx_h2so4 > 0) then
    1141  2314006344 :        del_h2so4_aeruptk(1:ncol,:) = vmr(1:ncol,:,ndx_h2so4) - del_h2so4_aeruptk(1:ncol,:)
    1142             :     endif
    1143             : 
    1144     1489176 :     call t_stopf('modal_gas-aer_exchng')
    1145             : 
    1146     1489176 :     call t_startf('modal_nucl')
    1147             : 
    1148             :     ! do aerosol nucleation (new particle formation)
    1149             :     call modal_aero_newnuc_sub(                             &
    1150             :          lchnk,    ncol,     nstep,            &
    1151             :          loffset,            delt,             &
    1152             :          tfld,     pmid,     pdel,             &
    1153             :          zm,       pblh,                       &
    1154             :          qh2o,     cldfr,                      &
    1155             :          vmr,                                  &
    1156   543653136 :          del_h2so4_gasprod,  del_h2so4_aeruptk )
    1157             : 
    1158     1489176 :     call t_stopf('modal_nucl')
    1159             : 
    1160     1489176 :     call t_startf('modal_coag')
    1161             : 
    1162             :     ! do aerosol coagulation
    1163             :     call modal_aero_coag_sub(                               &
    1164             :          lchnk,    ncol,     nstep,            &
    1165             :          loffset,            delt,             &
    1166             :          tfld,     pmid,     pdel,             &
    1167             :          vmr,                                  &
    1168             :          dgnum,              dgnumwet,         &
    1169     1489176 :          wetdens                          )
    1170             : 
    1171     1489176 :     call t_stopf('modal_coag')
    1172             : 
    1173     1489176 :     call vmr2qqcw( lchnk, vmrcw, mbar, ncol, loffset, pbuf )
    1174             : 
    1175             :     ! diagnostics for cloud-borne aerosols...
    1176    62545392 :     do n = 1,pcnst
    1177    61056216 :        fldcw => qqcw_get_field(pbuf,n,lchnk,errorhandle=.true.)
    1178    62545392 :        if(associated(fldcw)) then
    1179    28294344 :           call outfld( cnst_name_cw(n), fldcw(:,:), pcols, lchnk )
    1180             :        endif
    1181             :     end do
    1182             : !
    1183             : ! ... put missing NH3 into NH4
    1184             : !
    1185     1489176 :     if ( nh3_ndx > 0 .and. nh4_ndx > 0 ) then
    1186           0 :       vmr(1:ncol,:,nh4_ndx) = vmr(1:ncol,:,nh4_ndx) + (nh3_beg-vmr(1:ncol,:,nh3_ndx))
    1187           0 :       vmr(1:ncol,:,nh4_ndx) = max(0._r8,vmr(1:ncol,:,nh4_ndx))
    1188             :     end if
    1189             : 
    1190     2978352 :   end subroutine aero_model_gasaerexch
    1191             : 
    1192             :   !=============================================================================
    1193             :   !=============================================================================
    1194     1489176 :   subroutine aero_model_emissions( state, cam_in )
    1195     1489176 :     use seasalt_model, only: seasalt_emis, seasalt_names, seasalt_indices, seasalt_active,seasalt_nbin
    1196             :     use dust_model,    only: dust_emis, dust_names, dust_indices, dust_active,dust_nbin, dust_nnum
    1197             :     use physics_types, only: physics_state
    1198             : 
    1199             :     ! Arguments:
    1200             : 
    1201             :     type(physics_state),    intent(in)    :: state   ! Physics state variables
    1202             :     type(cam_in_t),         intent(inout) :: cam_in  ! import state
    1203             : 
    1204             :     ! local vars
    1205             : 
    1206             :     integer :: lchnk, ncol
    1207             :     integer :: m, mm
    1208             :     real(r8) :: soil_erod_tmp(pcols)
    1209             :     real(r8) :: sflx(pcols)   ! accumulate over all bins for output
    1210             :     real(r8) :: u10cubed(pcols)
    1211             :     real (r8), parameter :: z0=0.0001_r8  ! m roughness length over oceans--from ocean model
    1212             : 
    1213     1489176 :     lchnk = state%lchnk
    1214     1489176 :     ncol = state%ncol
    1215             : 
    1216     1489176 :     if (dust_active) then
    1217             : 
    1218     1489176 :        call dust_emis( ncol, lchnk, cam_in%dstflx, cam_in%cflx, soil_erod_tmp )
    1219             : 
    1220             :        ! some dust emis diagnostics ...
    1221     1489176 :        sflx(:)=0._r8
    1222    10424232 :        do m=1,dust_nbin+dust_nnum
    1223     8935056 :           mm = dust_indices(m)
    1224    79064856 :           if (m<=dust_nbin) sflx(:ncol)=sflx(:ncol)+cam_in%cflx(:ncol,mm)
    1225    10424232 :           call outfld(trim(dust_names(m))//'SF',cam_in%cflx(:,mm),pcols, lchnk)
    1226             :        enddo
    1227     1489176 :        call outfld('DSTSFMBL',sflx(:),pcols,lchnk)
    1228     1489176 :        call outfld('LND_MBL',soil_erod_tmp(:),pcols, lchnk )
    1229             :     endif
    1230             : 
    1231     1489176 :     if (seasalt_active) then
    1232    24865776 :        u10cubed(:ncol)=sqrt(state%u(:ncol,pver)**2+state%v(:ncol,pver)**2)
    1233             :        ! move the winds to 10m high from the midpoint of the gridbox:
    1234             :        ! follows Tie and Seinfeld and Pandis, p.859 with math.
    1235             : 
    1236    24865776 :        u10cubed(:ncol)=u10cubed(:ncol)*log(10._r8/z0)/log(state%zm(:ncol,pver)/z0)
    1237             : 
    1238             :        ! we need them to the 3.41 power, according to Gong et al., 1997:
    1239    24865776 :        u10cubed(:ncol)=u10cubed(:ncol)**3.41_r8
    1240             : 
    1241     1489176 :        sflx(:)=0._r8
    1242             : 
    1243     1489176 :        call seasalt_emis( u10cubed, cam_in%sst, cam_in%ocnfrac, ncol, cam_in%cflx )
    1244             : 
    1245     5956704 :        do m=1,seasalt_nbin
    1246     4467528 :           mm = seasalt_indices(m)
    1247    74597328 :           sflx(:ncol)=sflx(:ncol)+cam_in%cflx(:ncol,mm)
    1248     5956704 :           call outfld(trim(seasalt_names(m))//'SF',cam_in%cflx(:,mm),pcols,lchnk)
    1249             :        enddo
    1250     1489176 :        call outfld('SSTSFMBL',sflx(:),pcols,lchnk)
    1251             :     endif
    1252             : 
    1253     1489176 :   end subroutine aero_model_emissions
    1254             : 
    1255             :   !===============================================================================
    1256             :   ! private methods
    1257             : 
    1258             : 
    1259             :   !=============================================================================
    1260             :   !=============================================================================
    1261           0 :   subroutine surf_area_dens( ncol, mmr, pmid, temp, diam, beglev, endlev, sad, reff, sfc )
    1262     1489176 :     use mo_constants,    only : pi
    1263             :     use modal_aero_data, only : nspec_amode, alnsg_amode
    1264             : 
    1265             :     ! dummy args
    1266             :     integer,  intent(in)  :: ncol
    1267             :     real(r8), intent(in)  :: mmr(:,:,:)
    1268             :     real(r8), intent(in)  :: pmid(:,:)
    1269             :     real(r8), intent(in)  :: temp(:,:)
    1270             :     real(r8), intent(in)  :: diam(:,:,:)
    1271             :     integer,  intent(in)  :: beglev(:)
    1272             :     integer,  intent(in)  :: endlev(:)
    1273             :     real(r8), intent(out) :: sad(:,:)
    1274             :     real(r8), intent(out) :: reff(:,:)
    1275             :     real(r8),optional, intent(out) :: sfc(:,:,:)
    1276             : 
    1277             :     ! local vars
    1278           0 :     real(r8) :: sad_mode(pcols,pver,ntot_amode),radeff(pcols,pver)
    1279           0 :     real(r8) :: vol(pcols,pver),vol_mode(pcols,pver,ntot_amode)
    1280             :     real(r8) :: rho_air
    1281             :     integer  :: i,k,l,m
    1282             :     real(r8) :: chm_mass, tot_mass
    1283             : 
    1284             :     !
    1285             :     ! Compute surface aero for each mode.
    1286             :     ! Total over all modes as the surface area for chemical reactions.
    1287             :     !
    1288             : 
    1289           0 :     sad = 0._r8
    1290           0 :     sad_mode = 0._r8
    1291           0 :     vol = 0._r8
    1292           0 :     vol_mode = 0._r8
    1293           0 :     reff = 0._r8
    1294             : 
    1295           0 :     do i = 1,ncol
    1296           0 :        do k = beglev(i),endlev(i)
    1297           0 :           rho_air = pmid(i,k)/(temp(i,k)*287.04_r8)
    1298           0 :           do l=1,ntot_amode
    1299             :              !
    1300             :              ! compute a mass weighting of the number
    1301             :              !
    1302           0 :              tot_mass = 0._r8
    1303           0 :              chm_mass = 0._r8
    1304           0 :              do m=1,nspec_amode(l)
    1305           0 :                if ( index_tot_mass(l,m) > 0 ) &
    1306           0 :                     tot_mass = tot_mass + mmr(i,k,index_tot_mass(l,m))
    1307           0 :                if ( index_chm_mass(l,m) > 0 ) &
    1308           0 :                     chm_mass = chm_mass + mmr(i,k,index_chm_mass(l,m))
    1309             :              end do
    1310           0 :              if ( tot_mass > 0._r8 ) then
    1311             :               ! surface area density
    1312           0 :                sad_mode(i,k,l) = chm_mass/tot_mass &
    1313           0 :                                * mmr(i,k,num_idx(l))*rho_air*pi*diam(i,k,l)**2._r8 &
    1314           0 :                                * exp(2._r8*alnsg_amode(l)**2._r8)  ! m^2/m^3
    1315           0 :                sad_mode(i,k,l) = 1.e-2_r8 * sad_mode(i,k,l) ! cm^2/cm^3
    1316             : 
    1317             :               ! volume calculation, for use in effective radius calculation
    1318             :                vol_mode(i,k,l) = chm_mass/tot_mass &
    1319           0 :                                * mmr(i,k,num_idx(l))*rho_air*pi/6._r8*diam(i,k,l)**3._r8  &
    1320           0 :                                * exp(4.5_r8*alnsg_amode(l)**2._r8)  ! m^3/m^3 = cm^3/cm^3
    1321             :              else
    1322           0 :                sad_mode(i,k,l) = 0._r8
    1323           0 :                vol_mode(i,k,l) = 0._r8
    1324             :              end if
    1325             :           end do
    1326           0 :           sad(i,k) = sum(sad_mode(i,k,:))
    1327           0 :           vol(i,k) = sum(vol_mode(i,k,:))
    1328           0 :           reff(i,k) = 3._r8*vol(i,k)/sad(i,k)
    1329             : 
    1330             :        enddo
    1331             :     enddo
    1332             : 
    1333           0 :     if (present(sfc)) then
    1334           0 :        sfc(:,:,:) = sad_mode(:,:,:)
    1335             :     endif
    1336             : 
    1337           0 :   end subroutine surf_area_dens
    1338             : 
    1339             :   !===============================================================================
    1340             :   !===============================================================================
    1341        1536 :   subroutine modal_aero_bcscavcoef_init
    1342             :     !-----------------------------------------------------------------------
    1343             :     !
    1344             :     ! Purpose:
    1345             :     ! Computes lookup table for aerosol impaction/interception scavenging rates
    1346             :     !
    1347             :     ! Authors: R. Easter
    1348             :     !
    1349             :     !-----------------------------------------------------------------------
    1350             : 
    1351           0 :     use shr_kind_mod,    only: r8 => shr_kind_r8
    1352             :     use modal_aero_data
    1353             :     use cam_abortutils,  only: endrun
    1354             : 
    1355             :     implicit none
    1356             : 
    1357             : 
    1358             :     !   local variables
    1359             :     integer nnfit_maxd
    1360             :     parameter (nnfit_maxd=27)
    1361             : 
    1362             :     integer i, jgrow, jdens, jpress, jtemp, mode, nnfit
    1363             :     integer lunerr
    1364             : 
    1365             :     real(r8) dg0, dg0_cgs, press, &
    1366             :          rhodryaero, rhowetaero, rhowetaero_cgs, rmserr, &
    1367             :          scavratenum, scavratevol, sigmag,                &
    1368             :          temp, wetdiaratio, wetvolratio
    1369             :     real(r8) aafitnum(1), xxfitnum(1,nnfit_maxd), yyfitnum(nnfit_maxd)
    1370             :     real(r8) aafitvol(1), xxfitvol(1,nnfit_maxd), yyfitvol(nnfit_maxd)
    1371             : 
    1372        4608 :     allocate(scavimptblnum(nimptblgrow_mind:nimptblgrow_maxd, ntot_amode))
    1373        3072 :     allocate(scavimptblvol(nimptblgrow_mind:nimptblgrow_maxd, ntot_amode))
    1374             : 
    1375        1536 :     lunerr = 6
    1376        1536 :     dlndg_nimptblgrow = log( 1.25_r8 )
    1377             : 
    1378        7680 :     modeloop: do mode = 1, ntot_amode
    1379             : 
    1380        6144 :        sigmag = sigmag_amode(mode)
    1381             : 
    1382        6144 :        rhodryaero = specdens_amode(1,mode)
    1383             : 
    1384      130560 :        growloop: do jgrow = nimptblgrow_mind, nimptblgrow_maxd
    1385             : 
    1386      122880 :           wetdiaratio = exp( jgrow*dlndg_nimptblgrow )
    1387      122880 :           dg0 = dgnum_amode(mode)*wetdiaratio
    1388             : 
    1389             :           wetvolratio = exp( jgrow*dlndg_nimptblgrow*3._r8 )
    1390      122880 :           rhowetaero = 1.0_r8 + (rhodryaero-1.0_r8)/wetvolratio
    1391      122880 :           rhowetaero = min( rhowetaero, rhodryaero )
    1392             : 
    1393             :           !
    1394             :           !   compute impaction scavenging rates at 1 temp-press pair and save
    1395             :           !
    1396      122880 :           nnfit = 0
    1397             : 
    1398      122880 :           temp = 273.16_r8
    1399      122880 :           press = 0.75e6_r8   ! dynes/cm2
    1400      122880 :           rhowetaero = rhodryaero
    1401             : 
    1402      122880 :           dg0_cgs = dg0*1.0e2_r8   ! m to cm
    1403      122880 :           rhowetaero_cgs = rhowetaero*1.0e-3_r8   ! kg/m3 to g/cm3
    1404             :           call calc_1_impact_rate( &
    1405             :                dg0_cgs, sigmag, rhowetaero_cgs, temp, press, &
    1406      122880 :                scavratenum, scavratevol, lunerr )
    1407             : 
    1408      122880 :           nnfit = nnfit + 1
    1409             :           if (nnfit > nnfit_maxd) then
    1410             :              write(lunerr,9110)
    1411             :              call endrun()
    1412             :           end if
    1413             : 9110      format( '*** subr. modal_aero_bcscavcoef_init -- nnfit too big' )
    1414             : 
    1415      122880 :           xxfitnum(1,nnfit) = 1._r8
    1416      122880 :           yyfitnum(nnfit) = log( scavratenum )
    1417             : 
    1418      122880 :           xxfitvol(1,nnfit) = 1._r8
    1419      122880 :           yyfitvol(nnfit) = log( scavratevol )
    1420             : 
    1421             : 5900      continue
    1422             : 
    1423             :           !
    1424             :           ! skip mlinfit stuff because scav table no longer has dependencies on
    1425             :           !    air temp, air press, and particle wet density
    1426             :           ! just load the log( scavrate--- ) values
    1427             :           !
    1428             :           !!
    1429             :           !!   do linear regression
    1430             :           !!    log(scavrate) = a1 + a2*log(wetdens)
    1431             :           !!
    1432             :           !     call mlinft( xxfitnum, yyfitnum, aafitnum, nnfit, 1, 1, rmserr )
    1433             :           !     call mlinft( xxfitvol, yyfitvol, aafitvol, nnfit, 1, 1, rmserr )
    1434             :           !
    1435             :           !     scavimptblnum(jgrow,mode) = aafitnum(1)
    1436             :           !     scavimptblvol(jgrow,mode) = aafitvol(1)
    1437             : 
    1438      122880 :           scavimptblnum(jgrow,mode) = yyfitnum(1)
    1439      129024 :           scavimptblvol(jgrow,mode) = yyfitvol(1)
    1440             : 
    1441             :        enddo growloop
    1442             :     enddo modeloop
    1443        1536 :     return
    1444        1536 :   end subroutine modal_aero_bcscavcoef_init
    1445             : 
    1446             :   !===============================================================================
    1447             :   !===============================================================================
    1448    14891760 :   subroutine modal_aero_depvel_part( ncol, t, pmid, ram1, fv, vlc_dry, vlc_trb, vlc_grv,  &
    1449             :                                      radius_part, density_part, sig_part, moment, lchnk )
    1450             : 
    1451             : !    calculates surface deposition velocity of particles
    1452             : !    L. Zhang, S. Gong, J. Padro, and L. Barrie
    1453             : !    A size-seggregated particle dry deposition scheme for an atmospheric aerosol module
    1454             : !    Atmospheric Environment, 35, 549-560, 2001.
    1455             : !
    1456             : !    Authors: X. Liu
    1457             : 
    1458             :     !
    1459             :     ! !USES
    1460             :     !
    1461        1536 :     use physconst,     only: pi,boltz, gravit, rair
    1462             :     use mo_drydep,     only: n_land_type, fraction_landuse
    1463             : 
    1464             :     ! !ARGUMENTS:
    1465             :     !
    1466             :     implicit none
    1467             :     !
    1468             :     real(r8), intent(in) :: t(pcols,pver)       !atm temperature (K)
    1469             :     real(r8), intent(in) :: pmid(pcols,pver)    !atm pressure (Pa)
    1470             :     real(r8), intent(in) :: fv(pcols)           !friction velocity (m/s)
    1471             :     real(r8), intent(in) :: ram1(pcols)         !aerodynamical resistance (s/m)
    1472             :     real(r8), intent(in) :: radius_part(pcols,pver)    ! mean (volume/number) particle radius (m)
    1473             :     real(r8), intent(in) :: density_part(pcols,pver)   ! density of particle material (kg/m3)
    1474             :     real(r8), intent(in) :: sig_part(pcols,pver)       ! geometric standard deviation of particles
    1475             :     integer,  intent(in) :: moment ! moment of size distribution (0 for number, 2 for surface area, 3 for volume)
    1476             :     integer,  intent(in) :: ncol
    1477             :     integer,  intent(in) :: lchnk
    1478             : 
    1479             :     real(r8), intent(out) :: vlc_trb(pcols)       !Turbulent deposn velocity (m/s)
    1480             :     real(r8), intent(out) :: vlc_grv(pcols,pver)       !grav deposn velocity (m/s)
    1481             :     real(r8), intent(out) :: vlc_dry(pcols,pver)       !dry deposn velocity (m/s)
    1482             :     !------------------------------------------------------------------------
    1483             : 
    1484             :     !------------------------------------------------------------------------
    1485             :     ! Local Variables
    1486             :     integer  :: m,i,k,ix                !indices
    1487             :     real(r8) :: rho     !atm density (kg/m**3)
    1488             :     real(r8) :: vsc_dyn_atm(pcols,pver)   ![kg m-1 s-1] Dynamic viscosity of air
    1489             :     real(r8) :: vsc_knm_atm(pcols,pver)   ![m2 s-1] Kinematic viscosity of atmosphere
    1490             :     real(r8) :: shm_nbr       ![frc] Schmidt number
    1491             :     real(r8) :: stk_nbr       ![frc] Stokes number
    1492             :     real(r8) :: mfp_atm(pcols,pver)       ![m] Mean free path of air
    1493             :     real(r8) :: dff_aer       ![m2 s-1] Brownian diffusivity of particle
    1494             :     real(r8) :: slp_crc(pcols,pver) ![frc] Slip correction factor
    1495             :     real(r8) :: rss_trb       ![s m-1] Resistance to turbulent deposition
    1496             :     real(r8) :: rss_lmn       ![s m-1] Quasi-laminar layer resistance
    1497             :     real(r8) :: brownian      ! collection efficiency for Browning diffusion
    1498             :     real(r8) :: impaction     ! collection efficiency for impaction
    1499             :     real(r8) :: interception  ! collection efficiency for interception
    1500             :     real(r8) :: stickfrac     ! fraction of particles sticking to surface
    1501             :     real(r8) :: radius_moment(pcols,pver) ! median radius (m) for moment
    1502             :     real(r8) :: lnsig         ! ln(sig_part)
    1503             :     real(r8) :: dispersion    ! accounts for influence of size dist dispersion on bulk settling velocity
    1504             :                               ! assuming radius_part is number mode radius * exp(1.5 ln(sigma))
    1505             : 
    1506             :     integer  :: lt
    1507             :     real(r8) :: lnd_frc
    1508             :     real(r8) :: wrk1, wrk2, wrk3
    1509             : 
    1510             :     ! constants
    1511             :     real(r8) gamma(11)      ! exponent of schmidt number
    1512             : !   data gamma/0.54d+00,  0.56d+00,  0.57d+00,  0.54d+00,  0.54d+00, &
    1513             : !              0.56d+00,  0.54d+00,  0.54d+00,  0.54d+00,  0.56d+00, &
    1514             : !              0.50d+00/
    1515             :     data gamma/0.56e+00_r8,  0.54e+00_r8,  0.54e+00_r8,  0.56e+00_r8,  0.56e+00_r8, &
    1516             :                0.56e+00_r8,  0.50e+00_r8,  0.54e+00_r8,  0.54e+00_r8,  0.54e+00_r8, &
    1517             :                0.54e+00_r8/
    1518             :     save gamma
    1519             : 
    1520             :     real(r8) alpha(11)      ! parameter for impaction
    1521             : !   data alpha/50.00d+00,  0.95d+00,  0.80d+00,  1.20d+00,  1.30d+00, &
    1522             : !               0.80d+00, 50.00d+00, 50.00d+00,  2.00d+00,  1.50d+00, &
    1523             : !             100.00d+00/
    1524             :     data alpha/1.50e+00_r8,   1.20e+00_r8,  1.20e+00_r8,  0.80e+00_r8,  1.00e+00_r8, &
    1525             :                0.80e+00_r8, 100.00e+00_r8, 50.00e+00_r8,  2.00e+00_r8,  1.20e+00_r8, &
    1526             :               50.00e+00_r8/
    1527             :     save alpha
    1528             : 
    1529             :     real(r8) radius_collector(11) ! radius (m) of surface collectors
    1530             : !   data radius_collector/-1.00d+00,  5.10d-03,  3.50d-03,  3.20d-03, 10.00d-03, &
    1531             : !                          5.00d-03, -1.00d+00, -1.00d+00, 10.00d-03, 10.00d-03, &
    1532             : !                         -1.00d+00/
    1533             :     data radius_collector/10.00e-03_r8,  3.50e-03_r8,  3.50e-03_r8,  5.10e-03_r8,  2.00e-03_r8, &
    1534             :                            5.00e-03_r8, -1.00e+00_r8, -1.00e+00_r8, 10.00e-03_r8,  3.50e-03_r8, &
    1535             :                           -1.00e+00_r8/
    1536             :     save radius_collector
    1537             : 
    1538             :     integer            :: iwet(11) ! flag for wet surface = 1, otherwise = -1
    1539             : !   data iwet/1,   -1,   -1,   -1,   -1,  &
    1540             : !            -1,   -1,   -1,    1,   -1,  &
    1541             : !             1/
    1542             :     data iwet/-1,  -1,   -1,   -1,   -1,  &
    1543             :               -1,   1,   -1,    1,   -1,  &
    1544             :               -1/
    1545             :     save iwet
    1546             : 
    1547             : 
    1548    14891760 :     vlc_trb = 0._r8
    1549    14891760 :     vlc_grv = 0._r8
    1550    14891760 :     vlc_dry = 0._r8
    1551             : 
    1552             :     !------------------------------------------------------------------------
    1553  1399825440 :     do k=top_lev,pver ! radius_part is not defined above top_lev
    1554 23140063440 :        do i=1,ncol
    1555             : 
    1556 21740238000 :           lnsig = log(sig_part(i,k))
    1557             : ! use a maximum radius of 50 microns when calculating deposition velocity
    1558             :           radius_moment(i,k) = min(50.0e-6_r8,radius_part(i,k))*   &
    1559 21740238000 :                           exp((float(moment)-1.5_r8)*lnsig*lnsig)
    1560 21740238000 :           dispersion = exp(2._r8*lnsig*lnsig)
    1561             : 
    1562 21740238000 :           rho=pmid(i,k)/rair/t(i,k)
    1563             : 
    1564             :           ! Quasi-laminar layer resistance: call rss_lmn_get
    1565             :           ! Size-independent thermokinetic properties
    1566             :           vsc_dyn_atm(i,k) = 1.72e-5_r8 * ((t(i,k)/273.0_r8)**1.5_r8) * 393.0_r8 / &
    1567 21740238000 :                (t(i,k)+120.0_r8)      ![kg m-1 s-1] RoY94 p. 102
    1568             :           mfp_atm(i,k) = 2.0_r8 * vsc_dyn_atm(i,k) / &   ![m] SeP97 p. 455
    1569 21740238000 :                (pmid(i,k)*sqrt(8.0_r8/(pi*rair*t(i,k))))
    1570 21740238000 :           vsc_knm_atm(i,k) = vsc_dyn_atm(i,k) / rho ![m2 s-1] Kinematic viscosity of air
    1571             : 
    1572             :           slp_crc(i,k) = 1.0_r8 + mfp_atm(i,k) * &
    1573             :                   (1.257_r8+0.4_r8*exp(-1.1_r8*radius_moment(i,k)/(mfp_atm(i,k)))) / &
    1574 21740238000 :                   radius_moment(i,k)   ![frc] Slip correction factor SeP97 p. 464
    1575             :           vlc_grv(i,k) = (4.0_r8/18.0_r8) * radius_moment(i,k)*radius_moment(i,k)*density_part(i,k)* &
    1576 21740238000 :                   gravit*slp_crc(i,k) / vsc_dyn_atm(i,k) ![m s-1] Stokes' settling velocity SeP97 p. 466
    1577 21740238000 :           vlc_grv(i,k) = vlc_grv(i,k) * dispersion
    1578             : 
    1579 23125171680 :           vlc_dry(i,k)=vlc_grv(i,k)
    1580             :        enddo
    1581             :     enddo
    1582    14891760 :     k=pver  ! only look at bottom level for next part
    1583   248657760 :     do i=1,ncol
    1584   233766000 :        dff_aer = boltz * t(i,k) * slp_crc(i,k) / &    ![m2 s-1]
    1585   233766000 :                  (6.0_r8*pi*vsc_dyn_atm(i,k)*radius_moment(i,k)) !SeP97 p.474
    1586   233766000 :        shm_nbr = vsc_knm_atm(i,k) / dff_aer                        ![frc] SeP97 p.972
    1587             : 
    1588   233766000 :        wrk2 = 0._r8
    1589   233766000 :        wrk3 = 0._r8
    1590  2805192000 :        do lt = 1,n_land_type
    1591  2571426000 :           lnd_frc = fraction_landuse(i,lt,lchnk)
    1592  2805192000 :           if ( lnd_frc /= 0._r8 ) then
    1593   570692070 :              brownian = shm_nbr**(-gamma(lt))
    1594   570692070 :              if (radius_collector(lt) > 0.0_r8) then
    1595             : !       vegetated surface
    1596   259898730 :                 stk_nbr = vlc_grv(i,k) * fv(i) / (gravit*radius_collector(lt))
    1597   259898730 :                 interception = 2.0_r8*(radius_moment(i,k)/radius_collector(lt))**2.0_r8
    1598             :              else
    1599             : !       non-vegetated surface
    1600   310793340 :                 stk_nbr = vlc_grv(i,k) * fv(i) * fv(i) / (gravit*vsc_knm_atm(i,k))  ![frc] SeP97 p.965
    1601   310793340 :                 interception = 0.0_r8
    1602             :              endif
    1603   570692070 :              impaction = (stk_nbr/(alpha(lt)+stk_nbr))**2.0_r8
    1604             : 
    1605   570692070 :              if (iwet(lt) > 0) then
    1606             :                 stickfrac = 1.0_r8
    1607             :              else
    1608   353636010 :                 stickfrac = exp(-sqrt(stk_nbr))
    1609   353636010 :                 if (stickfrac < 1.0e-10_r8) stickfrac = 1.0e-10_r8
    1610             :              endif
    1611   570692070 :              rss_lmn = 1.0_r8 / (3.0_r8 * fv(i) * stickfrac * (brownian+interception+impaction))
    1612   570692070 :              rss_trb = ram1(i) + rss_lmn + ram1(i)*rss_lmn*vlc_grv(i,k)
    1613             : 
    1614   570692070 :              wrk1 = 1.0_r8 / rss_trb
    1615   570692070 :              wrk2 = wrk2 + lnd_frc*( wrk1 )
    1616   570692070 :              wrk3 = wrk3 + lnd_frc*( wrk1 + vlc_grv(i,k) )
    1617             :           endif
    1618             :        enddo  ! n_land_type
    1619   233766000 :        vlc_trb(i) = wrk2
    1620   248657760 :        vlc_dry(i,k) = wrk3
    1621             :     enddo !ncol
    1622             : 
    1623    14891760 :     return
    1624    14891760 :   end subroutine modal_aero_depvel_part
    1625             : 
    1626             :   !===============================================================================
    1627             :   subroutine modal_aero_bcscavcoef_get( m, ncol, isprx, dgn_awet, scavcoefnum, scavcoefvol )
    1628             : 
    1629    14891760 :     use modal_aero_data
    1630             :     !-----------------------------------------------------------------------
    1631             :     implicit none
    1632             : 
    1633             :     integer,intent(in) :: m, ncol
    1634             :     logical,intent(in):: isprx(pcols,pver)
    1635             :     real(r8), intent(in) :: dgn_awet(pcols,pver,ntot_amode)
    1636             :     real(r8), intent(out) :: scavcoefnum(pcols,pver), scavcoefvol(pcols,pver)
    1637             : 
    1638             :     integer i, k, jgrow
    1639             :     real(r8) dumdgratio, xgrow, dumfhi, dumflo, scavimpvol, scavimpnum
    1640             : 
    1641             : 
    1642             :     do k = 1, pver
    1643             :        do i = 1, ncol
    1644             : 
    1645             :           ! do only if no precip
    1646             :           if ( isprx(i,k) ) then
    1647             :              !
    1648             :              ! interpolate table values using log of (actual-wet-size)/(base-dry-size)
    1649             : 
    1650             :              dumdgratio = dgn_awet(i,k,m)/dgnum_amode(m)
    1651             : 
    1652             :              if ((dumdgratio >= 0.99_r8) .and. (dumdgratio <= 1.01_r8)) then
    1653             :                 scavimpvol = scavimptblvol(0,m)
    1654             :                 scavimpnum = scavimptblnum(0,m)
    1655             :              else
    1656             :                 xgrow = log( dumdgratio ) / dlndg_nimptblgrow
    1657             :                 jgrow = int( xgrow )
    1658             :                 if (xgrow < 0._r8) jgrow = jgrow - 1
    1659             :                 if (jgrow < nimptblgrow_mind) then
    1660             :                    jgrow = nimptblgrow_mind
    1661             :                    xgrow = jgrow
    1662             :                 else
    1663             :                    jgrow = min( jgrow, nimptblgrow_maxd-1 )
    1664             :                 end if
    1665             : 
    1666             :                 dumfhi = xgrow - jgrow
    1667             :                 dumflo = 1._r8 - dumfhi
    1668             : 
    1669             :                 scavimpvol = dumflo*scavimptblvol(jgrow,m) + &
    1670             :                      dumfhi*scavimptblvol(jgrow+1,m)
    1671             :                 scavimpnum = dumflo*scavimptblnum(jgrow,m) + &
    1672             :                      dumfhi*scavimptblnum(jgrow+1,m)
    1673             : 
    1674             :              end if
    1675             : 
    1676             :              ! impaction scavenging removal amount for volume
    1677             :              scavcoefvol(i,k) = exp( scavimpvol )
    1678             :              ! impaction scavenging removal amount to number
    1679             :              scavcoefnum(i,k) = exp( scavimpnum )
    1680             : 
    1681             :              ! scavcoef = impaction scav rate (1/h) for precip = 1 mm/h
    1682             :              ! scavcoef = impaction scav rate (1/s) for precip = pfx_inrain
    1683             :              ! (scavcoef/3600) = impaction scav rate (1/s) for precip = 1 mm/h
    1684             :              ! (pfx_inrain*3600) = in-rain-area precip rate (mm/h)
    1685             :              ! impactrate = (scavcoef/3600) * (pfx_inrain*3600)
    1686             :           else
    1687             :              scavcoefvol(i,k) = 0._r8
    1688             :              scavcoefnum(i,k) = 0._r8
    1689             :           end if
    1690             : 
    1691             :        end do
    1692             :     end do
    1693             : 
    1694             :     return
    1695             :   end subroutine modal_aero_bcscavcoef_get
    1696             : 
    1697             :   !===============================================================================
    1698      122880 :         subroutine calc_1_impact_rate(             &
    1699             :                 dg0, sigmag, rhoaero, temp, press, &
    1700             :                 scavratenum, scavratevol, lunerr )
    1701             :    !
    1702             :    !   routine computes a single impaction scavenging rate
    1703             :    !    for precipitation rate of 1 mm/h
    1704             :    !
    1705             :    !   dg0 = geometric mean diameter of aerosol number size distrib. (cm)
    1706             :    !   sigmag = geometric standard deviation of size distrib.
    1707             :    !   rhoaero = density of aerosol particles (g/cm^3)
    1708             :    !   temp = temperature (K)
    1709             :    !   press = pressure (dyne/cm^2)
    1710             :    !   scavratenum = number scavenging rate (1/h)
    1711             :    !   scavratevol = volume or mass scavenging rate (1/h)
    1712             :    !   lunerr = logical unit for error message
    1713             :    !
    1714             :    use shr_kind_mod, only: r8 => shr_kind_r8
    1715             :    use mo_constants, only: boltz_cgs, pi, rhowater => rhoh2o_cgs, &
    1716             :                            gravity => gravity_cgs, rgas => rgas_cgs
    1717             : 
    1718             :    implicit none
    1719             : 
    1720             :    !   subr. parameters
    1721             :    integer lunerr
    1722             :    real(r8) dg0, sigmag, rhoaero, temp, press, scavratenum, scavratevol
    1723             : 
    1724             :    !   local variables
    1725             :    integer nrainsvmax
    1726             :    parameter (nrainsvmax=50)
    1727             :    real(r8) rrainsv(nrainsvmax), xnumrainsv(nrainsvmax),&
    1728             :         vfallrainsv(nrainsvmax)
    1729             : 
    1730             :    integer naerosvmax
    1731             :    parameter (naerosvmax=51)
    1732             :    real(r8) aaerosv(naerosvmax), &
    1733             :         ynumaerosv(naerosvmax), yvolaerosv(naerosvmax)
    1734             : 
    1735             :    integer i, ja, jr, na, nr
    1736             :    real(r8) a, aerodiffus, aeromass, ag0, airdynvisc, airkinvisc
    1737             :    real(r8) anumsum, avolsum, cair, chi
    1738             :    real(r8) d, dr, dum, dumfuchs, dx
    1739             :    real(r8) ebrown, eimpact, eintercept, etotal, freepath
    1740             :    real(r8) precip, precipmmhr, precipsum
    1741             :    real(r8) r, rainsweepout, reynolds, rhi, rhoair, rlo, rnumsum
    1742             :    real(r8) scavsumnum, scavsumnumbb
    1743             :    real(r8) scavsumvol, scavsumvolbb
    1744             :    real(r8) schmidt, sqrtreynolds, sstar, stokes, sx
    1745             :    real(r8) taurelax, vfall, vfallstp
    1746             :    real(r8) x, xg0, xg3, xhi, xlo, xmuwaterair
    1747             : 
    1748             : 
    1749      122880 :    rlo = .005_r8
    1750      122880 :    rhi = .250_r8
    1751      122880 :    dr = 0.005_r8
    1752      122880 :    nr = 1 + nint( (rhi-rlo)/dr )
    1753             :    if (nr > nrainsvmax) then
    1754             :       write(lunerr,9110)
    1755             :       call endrun()
    1756             :    end if
    1757             : 
    1758             : 9110 format( '*** subr. calc_1_impact_rate -- nr > nrainsvmax' )
    1759             : 
    1760      122880 :    precipmmhr = 1.0_r8
    1761      122880 :    precip = precipmmhr/36000._r8
    1762             : 
    1763      122880 :    ag0 = dg0/2._r8
    1764      122880 :    sx = log( sigmag )
    1765      122880 :    xg0 = log( ag0 )
    1766      122880 :    xg3 = xg0 + 3._r8*sx*sx
    1767             : 
    1768      122880 :    xlo = xg3 - 4._r8*sx
    1769      122880 :    xhi = xg3 + 4._r8*sx
    1770      122880 :    dx = 0.2_r8*sx
    1771             : 
    1772      122880 :    dx = max( 0.2_r8*sx, 0.01_r8 )
    1773      122880 :    xlo = xg3 - max( 4._r8*sx, 2._r8*dx )
    1774      122880 :    xhi = xg3 + max( 4._r8*sx, 2._r8*dx )
    1775             : 
    1776      122880 :    na = 1 + nint( (xhi-xlo)/dx )
    1777      122880 :    if (na > naerosvmax) then
    1778           0 :       write(lunerr,9120)
    1779           0 :       call endrun()
    1780             :    end if
    1781             : 
    1782             : 9120 format( '*** subr. calc_1_impact_rate -- na > naerosvmax' )
    1783             : 
    1784             :    !   air molar density
    1785      122880 :    cair = press/(rgas*temp)
    1786             :    !   air mass density
    1787      122880 :    rhoair = 28.966_r8*cair
    1788             :    !   molecular freepath
    1789      122880 :    freepath = 2.8052e-10_r8/cair
    1790             :    !   air dynamic viscosity
    1791             :    airdynvisc = 1.8325e-4_r8 * (416.16_r8/(temp+120._r8)) *    &
    1792      122880 :         ((temp/296.16_r8)**1.5_r8)
    1793             :    !   air kinemaic viscosity
    1794      122880 :    airkinvisc = airdynvisc/rhoair
    1795             :    !   ratio of water viscosity to air viscosity (from Slinn)
    1796      122880 :    xmuwaterair = 60.0_r8
    1797             : 
    1798             :    !
    1799             :    !   compute rain drop number concentrations
    1800             :    !    rrainsv = raindrop radius (cm)
    1801             :    !    xnumrainsv = raindrop number concentration (#/cm^3)
    1802             :    !            (number in the bin, not number density)
    1803             :    !    vfallrainsv = fall velocity (cm/s)
    1804             :    !
    1805      122880 :    precipsum = 0._r8
    1806     6266880 :    do i = 1, nr
    1807     6144000 :       r = rlo + (i-1)*dr
    1808     6144000 :       rrainsv(i) = r
    1809     6144000 :       xnumrainsv(i) = exp( -r/2.7e-2_r8 )
    1810             : 
    1811     6144000 :       d = 2._r8*r
    1812     6144000 :       if (d <= 0.007_r8) then
    1813           0 :          vfallstp = 2.88e5_r8 * d**2._r8
    1814     6144000 :       else if (d <= 0.025_r8) then
    1815      245760 :          vfallstp = 2.8008e4_r8 * d**1.528_r8
    1816     5898240 :       else if (d <= 0.1_r8) then
    1817      983040 :          vfallstp = 4104.9_r8 * d**1.008_r8
    1818     4915200 :       else if (d <= 0.25_r8) then
    1819     1843200 :          vfallstp = 1812.1_r8 * d**0.638_r8
    1820             :       else
    1821     3072000 :          vfallstp = 1069.8_r8 * d**0.235_r8
    1822             :       end if
    1823             : 
    1824     6144000 :       vfall = vfallstp * sqrt(1.204e-3_r8/rhoair)
    1825     6144000 :       vfallrainsv(i) = vfall
    1826     6266880 :       precipsum = precipsum + vfall*(r**3)*xnumrainsv(i)
    1827             :    end do
    1828      122880 :    precipsum = precipsum*pi*1.333333_r8
    1829             : 
    1830      122880 :    rnumsum = 0._r8
    1831     6266880 :    do i = 1, nr
    1832     6144000 :       xnumrainsv(i) = xnumrainsv(i)*(precip/precipsum)
    1833     6266880 :       rnumsum = rnumsum + xnumrainsv(i)
    1834             :    end do
    1835             : 
    1836             :    !
    1837             :    !   compute aerosol concentrations
    1838             :    !    aaerosv = particle radius (cm)
    1839             :    !    fnumaerosv = fraction of total number in the bin (--)
    1840             :    !    fvolaerosv = fraction of total volume in the bin (--)
    1841             :    !
    1842             :    anumsum = 0._r8
    1843             :    avolsum = 0._r8
    1844     5160960 :    do i = 1, na
    1845     5038080 :       x = xlo + (i-1)*dx
    1846     5038080 :       a = exp( x )
    1847     5038080 :       aaerosv(i) = a
    1848     5038080 :       dum = (x - xg0)/sx
    1849     5038080 :       ynumaerosv(i) = exp( -0.5_r8*dum*dum )
    1850     5038080 :       yvolaerosv(i) = ynumaerosv(i)*1.3333_r8*pi*a*a*a
    1851     5038080 :       anumsum = anumsum + ynumaerosv(i)
    1852     5160960 :       avolsum = avolsum + yvolaerosv(i)
    1853             :    end do
    1854             : 
    1855     5160960 :    do i = 1, na
    1856     5038080 :       ynumaerosv(i) = ynumaerosv(i)/anumsum
    1857     5160960 :       yvolaerosv(i) = yvolaerosv(i)/avolsum
    1858             :    end do
    1859             : 
    1860             : 
    1861             :    !
    1862             :    !   compute scavenging
    1863             :    !
    1864             :    scavsumnum = 0._r8
    1865             :    scavsumvol = 0._r8
    1866             :    !
    1867             :    !   outer loop for rain drop radius
    1868             :    !
    1869     6266880 :    jr_loop: do jr = 1, nr
    1870             : 
    1871     6144000 :       r = rrainsv(jr)
    1872     6144000 :       vfall = vfallrainsv(jr)
    1873             : 
    1874     6144000 :       reynolds = r * vfall / airkinvisc
    1875     6144000 :       sqrtreynolds = sqrt( reynolds )
    1876             : 
    1877             :       !
    1878             :       !   inner loop for aerosol particle radius
    1879             :       !
    1880     6144000 :       scavsumnumbb = 0._r8
    1881     6144000 :       scavsumvolbb = 0._r8
    1882             : 
    1883   258048000 :       ja_loop: do ja = 1, na
    1884             : 
    1885   251904000 :          a = aaerosv(ja)
    1886             : 
    1887   251904000 :          chi = a/r
    1888             : 
    1889   251904000 :          dum = freepath/a
    1890   251904000 :          dumfuchs = 1._r8 + 1.246_r8*dum + 0.42_r8*dum*exp(-0.87_r8/dum)
    1891   251904000 :          taurelax = 2._r8*rhoaero*a*a*dumfuchs/(9._r8*rhoair*airkinvisc)
    1892             : 
    1893   251904000 :          aeromass = 4._r8*pi*a*a*a*rhoaero/3._r8
    1894   251904000 :          aerodiffus = boltz_cgs*temp*taurelax/aeromass
    1895             : 
    1896   251904000 :          schmidt = airkinvisc/aerodiffus
    1897   251904000 :          stokes = vfall*taurelax/r
    1898             : 
    1899             :          ebrown = 4._r8*(1._r8 + 0.4_r8*sqrtreynolds*(schmidt**0.3333333_r8)) /  &
    1900   251904000 :               (reynolds*schmidt)
    1901             : 
    1902             :          dum = (1._r8 + 2._r8*xmuwaterair*chi) /         &
    1903   251904000 :               (1._r8 + xmuwaterair/sqrtreynolds)
    1904   251904000 :          eintercept = 4._r8*chi*(chi + dum)
    1905             : 
    1906   251904000 :          dum = log( 1._r8 + reynolds )
    1907   251904000 :          sstar = (1.2_r8 + dum/12._r8) / (1._r8 + dum)
    1908   251904000 :          eimpact = 0._r8
    1909   251904000 :          if (stokes > sstar) then
    1910    61905408 :             dum = stokes - sstar
    1911    61905408 :             eimpact = (dum/(dum+0.6666667_r8)) ** 1.5_r8
    1912             :          end if
    1913             : 
    1914   251904000 :          etotal = ebrown + eintercept + eimpact
    1915   251904000 :          etotal = min( etotal, 1.0_r8 )
    1916             : 
    1917   251904000 :          rainsweepout = xnumrainsv(jr)*4._r8*pi*r*r*vfall
    1918             : 
    1919   251904000 :          scavsumnumbb = scavsumnumbb + rainsweepout*etotal*ynumaerosv(ja)
    1920   258048000 :          scavsumvolbb = scavsumvolbb + rainsweepout*etotal*yvolaerosv(ja)
    1921             : 
    1922             :       enddo ja_loop
    1923             : 
    1924     6144000 :       scavsumnum = scavsumnum + scavsumnumbb
    1925     6266880 :       scavsumvol = scavsumvol + scavsumvolbb
    1926             : 
    1927             :    enddo jr_loop
    1928             : 
    1929      122880 :    scavratenum = scavsumnum*3600._r8
    1930      122880 :    scavratevol = scavsumvol*3600._r8
    1931             : 
    1932      122880 :    return
    1933             :  end subroutine calc_1_impact_rate
    1934             : 
    1935             :   !=============================================================================
    1936             :   !=============================================================================
    1937     2978352 :   subroutine qqcw2vmr(lchnk, vmr, mbar, ncol, im, pbuf)
    1938             :     use modal_aero_data, only : qqcw_get_field
    1939             :     use physics_buffer, only : physics_buffer_desc
    1940             :     !-----------------------------------------------------------------
    1941             :     !   ... Xfrom from mass to volume mixing ratio
    1942             :     !-----------------------------------------------------------------
    1943             : 
    1944             :     use chem_mods, only : adv_mass, gas_pcnst
    1945             : 
    1946             :     implicit none
    1947             : 
    1948             :     !-----------------------------------------------------------------
    1949             :     !   ... Dummy args
    1950             :     !-----------------------------------------------------------------
    1951             :     integer, intent(in)     :: lchnk, ncol, im
    1952             :     real(r8), intent(in)    :: mbar(ncol,pver)
    1953             :     real(r8), intent(inout) :: vmr(ncol,pver,gas_pcnst)
    1954             :     type(physics_buffer_desc), pointer :: pbuf(:)
    1955             : 
    1956             :     !-----------------------------------------------------------------
    1957             :     !   ... Local variables
    1958             :     !-----------------------------------------------------------------
    1959             :     integer :: k, m
    1960     1489176 :     real(r8), pointer :: fldcw(:,:)
    1961             : 
    1962    47653632 :     do m=1,gas_pcnst
    1963    47653632 :        if( adv_mass(m) /= 0._r8 ) then
    1964    46164456 :           fldcw => qqcw_get_field(pbuf, m+im,lchnk,errorhandle=.true.)
    1965    46164456 :           if(associated(fldcw)) then
    1966  2659668336 :              do k=1,pver
    1967 43966120536 :                 vmr(:ncol,k,m) = mbar(:ncol,k) * fldcw(:ncol,k) / adv_mass(m)
    1968             :              end do
    1969             :           else
    1970 27768076128 :              vmr(:,:,m) = 0.0_r8
    1971             :           end if
    1972             :        end if
    1973             :     end do
    1974     2978352 :   end subroutine qqcw2vmr
    1975             : 
    1976             : 
    1977             :   !=============================================================================
    1978             :   !=============================================================================
    1979     2978352 :   subroutine vmr2qqcw( lchnk, vmr, mbar, ncol, im, pbuf )
    1980             :     !-----------------------------------------------------------------
    1981             :     !   ... Xfrom from volume to mass mixing ratio
    1982             :     !-----------------------------------------------------------------
    1983             : 
    1984     1489176 :     use m_spc_id
    1985             :     use chem_mods,       only : adv_mass, gas_pcnst
    1986             :     use modal_aero_data, only : qqcw_get_field
    1987             :     use physics_buffer,  only : physics_buffer_desc
    1988             : 
    1989             :     implicit none
    1990             : 
    1991             :     !-----------------------------------------------------------------
    1992             :     !   ... Dummy args
    1993             :     !-----------------------------------------------------------------
    1994             :     integer, intent(in)     :: lchnk, ncol, im
    1995             :     real(r8), intent(in)    :: mbar(ncol,pver)
    1996             :     real(r8), intent(in)    :: vmr(ncol,pver,gas_pcnst)
    1997             :     type(physics_buffer_desc), pointer :: pbuf(:)
    1998             : 
    1999             :     !-----------------------------------------------------------------
    2000             :     !   ... Local variables
    2001             :     !-----------------------------------------------------------------
    2002             :     integer :: k, m
    2003     1489176 :     real(r8), pointer :: fldcw(:,:)
    2004             :     !-----------------------------------------------------------------
    2005             :     !   ... The non-group species
    2006             :     !-----------------------------------------------------------------
    2007    47653632 :     do m = 1,gas_pcnst
    2008    46164456 :        fldcw => qqcw_get_field(pbuf, m+im,lchnk,errorhandle=.true.)
    2009    47653632 :        if( adv_mass(m) /= 0._r8 .and. associated(fldcw)) then
    2010  2659668336 :           do k = 1,pver
    2011 43966120536 :              fldcw(:ncol,k) = adv_mass(m) * vmr(:ncol,k,m) / mbar(:ncol,k)
    2012             :           end do
    2013             :        end if
    2014             :     end do
    2015             : 
    2016     2978352 :   end subroutine vmr2qqcw
    2017             : 
    2018           0 :   function get_dlndg_nimptblgrow() result (dlndg_nimptblgrow_ret)
    2019             :     real(r8) ::  dlndg_nimptblgrow_ret
    2020           0 :     dlndg_nimptblgrow_ret =  dlndg_nimptblgrow
    2021     1489176 :   end function get_dlndg_nimptblgrow
    2022             : 
    2023           0 :   function get_scavimptblvol() result (scavimptblvol_ret)
    2024             :     real(r8) :: scavimptblvol_ret(nimptblgrow_mind:nimptblgrow_maxd, ntot_amode)
    2025           0 :     scavimptblvol_ret = scavimptblvol
    2026           0 :   end function get_scavimptblvol
    2027             : 
    2028           0 :   function get_scavimptblnum() result (scavimptblnum_ret)
    2029             :     real(r8) :: scavimptblnum_ret(nimptblgrow_mind:nimptblgrow_maxd, ntot_amode)
    2030           0 :     scavimptblnum_ret = scavimptblnum
    2031           0 :   end function get_scavimptblnum
    2032             : 
    2033             : end module aero_model

Generated by: LCOV version 1.14