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

Generated by: LCOV version 1.14