LCOV - code coverage report
Current view: top level - chemistry/aerosol - aero_wetdep_cam.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 439 482 91.1 %
Date: 2025-03-14 01:26:08 Functions: 7 7 100.0 %

          Line data    Source code
       1             : module aero_wetdep_cam
       2             :   use shr_kind_mod,  only: r8 => shr_kind_r8
       3             :   use physics_types, only: physics_state, physics_ptend, physics_ptend_init
       4             :   use camsrfexch,    only: cam_out_t
       5             :   use physics_buffer,only: physics_buffer_desc, pbuf_get_index, pbuf_set_field, pbuf_get_field
       6             :   use constituents,  only: pcnst, cnst_name, cnst_get_ind
       7             :   use phys_control,  only: phys_getopts
       8             :   use ppgrid,        only: pcols, pver
       9             :   use physconst,     only: gravit
      10             : 
      11             :   use cam_abortutils,only: endrun
      12             :   use cam_logfile,   only: iulog
      13             :   use spmd_utils,    only: masterproc
      14             :   use infnan,        only: nan, assignment(=)
      15             : 
      16             :   use cam_history,   only: addfld, add_default, horiz_only, outfld
      17             :   use wetdep,        only: wetdep_init
      18             : 
      19             :   use rad_constituents, only: rad_cnst_get_info
      20             : 
      21             :   use aerosol_properties_mod, only: aero_name_len
      22             :   use aerosol_properties_mod, only: aerosol_properties
      23             :   use modal_aerosol_properties_mod, only: modal_aerosol_properties
      24             :   use carma_aerosol_properties_mod, only: carma_aerosol_properties
      25             : 
      26             :   use aerosol_state_mod, only: aerosol_state, ptr2d_t
      27             :   use modal_aerosol_state_mod, only: modal_aerosol_state
      28             :   use carma_aerosol_state_mod, only: carma_aerosol_state
      29             : 
      30             :   use aero_convproc, only: aero_convproc_readnl, aero_convproc_init, aero_convproc_intr
      31             :   use aero_convproc, only: convproc_do_evaprain_atonce
      32             :   use aero_convproc, only: deepconv_wetdep_history
      33             : 
      34             :   use infnan,         only: nan, assignment(=)
      35             :   use perf_mod,       only: t_startf, t_stopf
      36             : 
      37             :   implicit none
      38             :   private
      39             : 
      40             :   public :: aero_wetdep_readnl
      41             :   public :: aero_wetdep_init
      42             :   public :: aero_wetdep_tend
      43             : 
      44             :   real(r8), parameter :: NOTSET = -huge(1._r8)
      45             :   real(r8) :: sol_facti_cloud_borne   = NOTSET
      46             :   real(r8) :: sol_factb_interstitial  = NOTSET
      47             :   real(r8) :: sol_factic_interstitial = NOTSET
      48             : 
      49             :   integer :: fracis_idx = -1
      50             :   integer :: rprddp_idx          = -1
      51             :   integer :: rprdsh_idx          = -1
      52             :   integer :: nevapr_shcu_idx     = -1
      53             :   integer :: nevapr_dpcu_idx     = -1
      54             : 
      55             :   logical :: wetdep_active = .false.
      56             :   integer :: nwetdep = 0
      57             :   logical :: convproc_do_aer = .false.
      58             :   logical,allocatable :: aero_cnst_lq(:,:)
      59             :   integer,allocatable :: aero_cnst_id(:,:)
      60             :   logical, public, protected :: wetdep_lq(pcnst) ! set flags true for constituents with non-zero tendencies
      61             : 
      62             :   ! variables for table lookup of aerosol impaction/interception scavenging rates
      63             :   integer, parameter :: nimptblgrow_mind=-7, nimptblgrow_maxd=12
      64             :   real(r8) :: dlndg_nimptblgrow
      65             :   real(r8),allocatable :: scavimptblnum(:,:)
      66             :   real(r8),allocatable :: scavimptblvol(:,:)
      67             : 
      68             :   integer :: nmodes=0
      69             :   integer :: nbins=0
      70             :   integer :: nspec_max=0
      71             :   integer :: nele_tot            ! total number of aerosol elements
      72             :   class(aerosol_properties), pointer :: aero_props=>null()
      73             : 
      74             : contains
      75             : 
      76             :   !------------------------------------------------------------------------------
      77             :   !------------------------------------------------------------------------------
      78         768 :   subroutine aero_wetdep_readnl(nlfile)
      79             :     use namelist_utils,  only: find_group_name
      80             :     use spmd_utils,      only: mpicom, masterprocid, mpi_character, mpi_real8, mpi_integer, mpi_success
      81             :     use spmd_utils,      only: mpi_logical
      82             : 
      83             :     character(len=*), intent(in)  :: nlfile  ! filepath for file containing namelist input
      84             : 
      85             :     integer                       :: unitn, ierr
      86             :     character(len=*), parameter   :: subname = 'aero_wetdep_readnl'
      87             : 
      88             :     ! ===================
      89             :     ! Namelist definition
      90             :     ! ===================
      91             :     namelist /aero_wetdep_nl/ sol_facti_cloud_borne, sol_factb_interstitial, sol_factic_interstitial
      92             : 
      93             :     ! =============
      94             :     ! Read namelist
      95             :     ! =============
      96         768 :     if (masterproc) then
      97           2 :        open( newunit=unitn, file=trim(nlfile), status='old' )
      98           2 :        call find_group_name(unitn, 'aero_wetdep_nl', status=ierr)
      99           2 :        if (ierr == 0) then
     100           2 :           read(unitn, aero_wetdep_nl, iostat=ierr)
     101           2 :           if (ierr /= 0) then
     102           0 :              call endrun(subname // ':: ERROR reading namelist')
     103             :           end if
     104             :        end if
     105           2 :        close(unitn)
     106             : 
     107             :        ! ============================
     108             :        ! Log namelist options
     109             :        ! ============================
     110           2 :        write(iulog,*) subname,' namelist settings: '
     111           2 :        write(iulog,*) '   sol_facti_cloud_borne  : ',sol_facti_cloud_borne
     112           2 :        write(iulog,*) '   sol_factb_interstitial : ',sol_factb_interstitial
     113           2 :        write(iulog,*) '   sol_factic_interstitial: ',sol_factic_interstitial
     114             :     end if
     115             : 
     116             :     ! ============================
     117             :     ! Broadcast namelist variables
     118             :     ! ============================
     119         768 :     call mpi_bcast(sol_facti_cloud_borne, 1, mpi_real8, masterprocid, mpicom, ierr)
     120         768 :     if (ierr/=mpi_success) then
     121           0 :        call endrun(subname//': MPI_BCAST ERROR: sol_facti_cloud_borne')
     122             :     end if
     123         768 :     call mpi_bcast(sol_factb_interstitial, 1, mpi_real8, masterprocid, mpicom, ierr)
     124         768 :     if (ierr/=mpi_success) then
     125           0 :        call endrun(subname//': MPI_BCAST ERROR: sol_factb_interstitial')
     126             :     end if
     127         768 :     call mpi_bcast(sol_factic_interstitial, 1, mpi_real8, masterprocid, mpicom, ierr)
     128         768 :     if (ierr/=mpi_success) then
     129           0 :        call endrun(subname//': MPI_BCAST ERROR: sol_factic_interstitial')
     130             :     end if
     131             : 
     132         768 :     call mpi_bcast(nwetdep, 1, mpi_integer, masterprocid, mpicom, ierr)
     133         768 :     if (ierr/=mpi_success) then
     134           0 :        call endrun(subname//': MPI_BCAST ERROR: nwetdep')
     135             :     end if
     136             : 
     137         768 :     wetdep_active = .true. !nwetdep>0
     138             : 
     139         768 :     if (masterproc) then
     140           2 :        write(iulog,*) subname,' wetdep_active = ',wetdep_active,' nwetdep = ',nwetdep
     141             :     endif
     142             : 
     143         768 :     call aero_convproc_readnl(nlfile)
     144             : 
     145         768 :   end subroutine aero_wetdep_readnl
     146             : 
     147             :   !------------------------------------------------------------------------------
     148             :   !------------------------------------------------------------------------------
     149         768 :   subroutine aero_wetdep_init( )
     150             : 
     151             :     character(len=*), parameter :: subrname = 'aero_wetdep_init'
     152             : 
     153             :     character(len=2)  :: unit_basename  ! Units 'kg' or '1'
     154             :     character(len=aero_name_len) :: tmpname
     155             :     character(len=aero_name_len) :: tmpname_cw
     156             : 
     157             :     logical  :: history_aerosol ! Output MAM or SECT aerosol tendencies
     158             :     logical  :: history_chemistry
     159             : 
     160             :     integer :: l,m, id, astat
     161             :     character(len=2) :: binstr
     162             : 
     163         768 :     fracis_idx = pbuf_get_index('FRACIS')
     164         768 :     rprddp_idx      = pbuf_get_index('RPRDDP')
     165         768 :     rprdsh_idx      = pbuf_get_index('RPRDSH')
     166         768 :     nevapr_shcu_idx = pbuf_get_index('NEVAPR_SHCU')
     167         768 :     nevapr_dpcu_idx = pbuf_get_index('NEVAPR_DPCU')
     168             : 
     169         768 :     if (.not.wetdep_active) return
     170             : 
     171             :     call phys_getopts(history_aerosol_out = history_aerosol, &
     172             :                       history_chemistry_out=history_chemistry, &
     173             :                       convproc_do_aer_out = convproc_do_aer)
     174             : 
     175         768 :     call rad_cnst_get_info(0, nmodes=nmodes, nbins=nbins)
     176             : 
     177         768 :     if (nmodes>0) then
     178         768 :        aero_props => modal_aerosol_properties()
     179         768 :        if (.not.associated(aero_props)) then
     180           0 :           call endrun(subrname//' : construction of aero_props modal_aerosol_properties object failed')
     181             :        end if
     182           0 :     else if (nbins>0) then
     183           0 :        aero_props => carma_aerosol_properties()
     184           0 :        if (.not.associated(aero_props)) then
     185           0 :           call endrun(subrname//' : construction of aero_props carma_aerosol_properties object failed')
     186             :        end if
     187             :     else
     188           0 :        call endrun(subrname//' : cannot determine aerosol model')
     189             :     endif
     190             : 
     191         768 :     nele_tot = aero_props%ncnst_tot()
     192             : 
     193        7680 :     allocate(aero_cnst_lq(aero_props%nbins(),0:maxval(aero_props%nspecies())), stat=astat)
     194         768 :     if (astat/=0) then
     195           0 :        call endrun(subrname//' : not able to allocate aero_cnst_lq array')
     196             :     end if
     197       33024 :     aero_cnst_lq(:,:) = .false.
     198             : 
     199        7680 :     allocate(aero_cnst_id(aero_props%nbins(),0:maxval(aero_props%nspecies())), stat=astat)
     200         768 :     if (astat/=0) then
     201           0 :        call endrun(subrname//' : not able to allocate aero_cnst_id array')
     202             :     end if
     203       33024 :     aero_cnst_id(:,:) = -1
     204             : 
     205         768 :     wetdep_lq = .false.
     206             : 
     207        4608 :     do m = 1, aero_props%nbins()
     208        3840 :        write(binstr,'(i2.2)') m
     209        7680 :        call addfld('SOLFACTB'//binstr,  (/ 'lev' /), 'A', '1', 'below cld sol fact')
     210             : 
     211       20736 :        do l = 0, aero_props%nspecies(m)
     212             : 
     213       16128 :           if (l == 0) then   ! number
     214        3840 :              call aero_props%num_names( m, tmpname, tmpname_cw)
     215             :           else
     216       12288 :              call aero_props%mmr_names( m,l, tmpname, tmpname_cw)
     217             :           end if
     218             : 
     219       16128 :           call cnst_get_ind(tmpname, id, abort=.false.)
     220       16128 :           aero_cnst_id(m,l) = id
     221       16128 :           aero_cnst_lq(m,l) = id > 0
     222       16128 :           if (id > 0) then
     223       16128 :              wetdep_lq(id) = .true.
     224             :           end if
     225             : 
     226             :           ! units --
     227       16128 :           if (l==0) then
     228        3840 :              unit_basename = ' 1' ! for num
     229             :           else
     230       12288 :              unit_basename = 'kg'
     231             :           endif
     232             : 
     233       16128 :           call add_hist_fields(tmpname, unit_basename)
     234       16128 :           call add_hist_fields(tmpname_cw, unit_basename)
     235             : 
     236             :           call addfld( trim(tmpname_cw)//'RSPTD', (/ 'lev' /), 'A', unit_basename//'/kg/s',   &
     237       36096 :                        trim(tmpname_cw)//' resuspension tendency')
     238             : 
     239             :        end do
     240             :     end do
     241             : 
     242        2304 :     allocate(scavimptblnum(nimptblgrow_mind:nimptblgrow_maxd, aero_props%nbins()), stat=astat)
     243         768 :     if (astat/=0) then
     244           0 :        call endrun(subrname//' : not able to allocate scavimptblnum array')
     245             :     end if
     246        2304 :     allocate(scavimptblvol(nimptblgrow_mind:nimptblgrow_maxd, aero_props%nbins()), stat=astat)
     247         768 :     if (astat/=0) then
     248           0 :        call endrun(subrname//' : not able to allocate scavimptblvol array')
     249             :     end if
     250         768 :     scavimptblnum = nan
     251         768 :     scavimptblvol = nan
     252             : 
     253         768 :     call wetdep_init()
     254             : 
     255        4608 :     nspec_max = maxval(aero_props%nspecies()) + 2
     256             : 
     257         768 :     call init_bcscavcoef()
     258             : 
     259        3072 :     if (convproc_do_aer) then
     260         768 :        call aero_convproc_init(aero_props)
     261             :     end if
     262             : 
     263             :   contains
     264             : 
     265       32256 :     subroutine add_hist_fields(name,baseunits)
     266             :       character(len=*), intent(in) :: name
     267             :       character(len=*), intent(in) :: baseunits
     268             : 
     269             :       call addfld (trim(name)//'SFWET', &
     270       32256 :            horiz_only,  'A',baseunits//'/m2/s ','Wet deposition flux at surface')
     271             :       call addfld (trim(name)//'SFSIC', &
     272       32256 :            horiz_only,  'A',baseunits//'/m2/s ','Wet deposition flux (incloud, convective) at surface')
     273             :       call addfld (trim(name)//'SFSIS', &
     274       32256 :            horiz_only,  'A',baseunits//'/m2/s ','Wet deposition flux (incloud, stratiform) at surface')
     275             :       call addfld (trim(name)//'SFSBC', &
     276       32256 :            horiz_only,  'A',baseunits//'/m2/s ','Wet deposition flux (belowcloud, convective) at surface')
     277             :       call addfld (trim(name)//'SFSBS', &
     278       32256 :            horiz_only,  'A',baseunits//'/m2/s ','Wet deposition flux (belowcloud, stratiform) at surface')
     279             : 
     280       32256 :       if (convproc_do_aer) then
     281             :          call addfld (trim(name)//'SFSEC', &
     282       32256 :               horiz_only,  'A',unit_basename//'/m2/s','Wet deposition flux (precip evap, convective) at surface')
     283             :          call addfld (trim(name)//'SFSES', &
     284       32256 :               horiz_only,  'A',unit_basename//'/m2/s','Wet deposition flux (precip evap, stratiform) at surface')
     285             :          call addfld (trim(name)//'SFSBD', &
     286       32256 :               horiz_only,  'A',unit_basename//'/m2/s','Wet deposition flux (belowcloud, deep convective) at surface')
     287             :          call addfld (trim(name)//'WETC',  &
     288       64512 :               (/ 'lev' /), 'A',unit_basename//'/kg/s ','wet deposition tendency')
     289             :          call addfld (trim(name)//'CONU',  &
     290       64512 :               (/ 'lev' /), 'A',unit_basename//'/kg ','updraft mixing ratio')
     291             :       end if
     292             : 
     293       64512 :       call addfld (trim(name)//'WET',(/ 'lev' /), 'A',baseunits//'/kg/s ','wet deposition tendency')
     294       64512 :       call addfld (trim(name)//'INS',(/ 'lev' /), 'A',baseunits//'/kg/s ','insol frac')
     295             : 
     296             :       call addfld (trim(name)//'SIC',(/ 'lev' /), 'A',baseunits//'/kg/s ', &
     297       64512 :            trim(name)//' ic wet deposition')
     298             :       call addfld (trim(name)//'SIS',(/ 'lev' /), 'A',baseunits//'/kg/s ', &
     299       64512 :            trim(name)//' is wet deposition')
     300             :       call addfld (trim(name)//'SBC',(/ 'lev' /), 'A',baseunits//'/kg/s ', &
     301       64512 :            trim(name)//' bc wet deposition')
     302             :       call addfld (trim(name)//'SBS',(/ 'lev' /), 'A',baseunits//'/kg/s ', &
     303       64512 :            trim(name)//' bs wet deposition')
     304             : 
     305       32256 :       if ( history_aerosol .or. history_chemistry ) then
     306       32256 :          call add_default (trim(name)//'SFWET', 1, ' ')
     307             :       endif
     308       32256 :       if ( history_aerosol ) then
     309           0 :          call add_default (trim(name)//'SFSEC', 1, ' ')
     310           0 :          call add_default (trim(name)//'SFSIC', 1, ' ')
     311           0 :          call add_default (trim(name)//'SFSIS', 1, ' ')
     312           0 :          call add_default (trim(name)//'SFSBC', 1, ' ')
     313           0 :          call add_default (trim(name)//'SFSBS', 1, ' ')
     314           0 :          if (convproc_do_aer) then
     315           0 :             call add_default (trim(name)//'SFSES', 1, ' ')
     316           0 :             call add_default (trim(name)//'SFSBD', 1, ' ')
     317             :          end if
     318             :       endif
     319             : 
     320       32256 :     end subroutine add_hist_fields
     321             : 
     322             :   end subroutine aero_wetdep_init
     323             : 
     324             :   !------------------------------------------------------------------------------
     325             :   !------------------------------------------------------------------------------
     326     2491776 :   subroutine aero_wetdep_tend( state, dt, dlf, cam_out, ptend, pbuf)
     327             :     use wetdep, only: wetdepa_v2, wetdep_inputs_set, wetdep_inputs_t
     328             :     use aerodep_flx, only: aerodep_flx_prescribed
     329             :     use aero_deposition_cam, only: aero_deposition_cam_setwet
     330             : 
     331             :     type(physics_state), target, intent(in) :: state  ! Physics state variables
     332             :     real(r8),            intent(in)    :: dt          ! time step
     333             :     real(r8),            intent(in)    :: dlf(:,:)    ! shallow+deep convective detrainment [kg/kg/s]
     334             :     type(cam_out_t),     intent(inout) :: cam_out     ! export state
     335             :     type(physics_ptend), intent(out)   :: ptend       ! indivdual parameterization tendencies
     336             :     type(physics_buffer_desc), pointer :: pbuf(:)
     337             : 
     338             :     character(len=*), parameter :: subrname = 'aero_wetdep_tend'
     339             :     type(wetdep_inputs_t) :: dep_inputs
     340       24192 :     real(r8), pointer :: fracis(:,:,:)   ! fraction of transported species that are insoluble (pcols, pver, pcnst)
     341             :     real(r8), target :: fracis_nadv(pcols,pver)  ! fraction of not-transported aerosols
     342             : 
     343             :     real(r8) :: scavcoefnv(pcols,pver,0:2) ! Dana and Hales coefficient (/mm) for
     344             :                                            ! cloud-borne num & vol (0),
     345             :                                            ! interstitial num (1), interstitial vol (2)
     346             :     integer :: jnv ! index for scavcoefnv 3rd dimension
     347             :     integer :: lphase ! index for interstitial / cloudborne aerosol
     348             :     integer :: strt_loop, end_loop, stride_loop !loop indices for the lphase loop
     349             : 
     350             :     real(r8) :: sol_factb(pcols, pver)
     351             :     real(r8) :: sol_facti(pcols, pver)
     352             :     real(r8) :: sol_factic(pcols,pver)
     353             : 
     354             :     real(r8) :: dqdt_tmp(pcols,pver) ! temporary array to hold tendency for 1 species
     355             :     real(r8) :: rcscavt(pcols, pver)
     356             :     real(r8) :: rsscavt(pcols, pver)
     357             :     real(r8) :: iscavt(pcols, pver)
     358             :     real(r8) :: icscavt(pcols, pver)
     359             :     real(r8) :: isscavt(pcols, pver)
     360             :     real(r8) :: bcscavt(pcols, pver)
     361             :     real(r8) :: bsscavt(pcols, pver)
     362             : 
     363       48384 :     real(r8) :: diam_wet(state%ncol, pver)
     364             :     logical  :: isprx(pcols,pver) ! true if precipation
     365             :     real(r8) :: prec(pcols) ! precipitation rate
     366             : 
     367       48384 :     real(r8) :: rtscavt(pcols, pver, 0:nspec_max)
     368             : 
     369             :     integer :: ncol, lchnk, m, ndx,mm, l
     370             :     integer :: i,k
     371             : 
     372       24192 :     real(r8), pointer :: insolfr_ptr(:,:)
     373             :     real(r8) :: q_tmp(pcols,pver) ! temporary array to hold "most current" mixing ratio for 1 species
     374             :     logical :: cldbrn
     375             : 
     376       48384 :     type(ptr2d_t) :: raer(nele_tot)
     377       48384 :     type(ptr2d_t) :: qqcw(nele_tot)
     378             : 
     379             :     real(r8) :: sflx(pcols)
     380             :     character(len=aero_name_len) :: aname, cname, name
     381             : 
     382       48384 :     real(r8) :: qqcw_in(pcols,pver), qqcw_sav(pcols,pver,0:nspec_max)
     383             :     real(r8) :: f_act_conv(pcols,pver) ! prescribed aerosol activation fraction for convective cloud ! rce 2010/05/01
     384             : 
     385             :     character(len=2) :: binstr
     386             :     real(r8) :: aerdepwetcw(pcols,pcnst) ! aerosol wet deposition (cloud water)
     387             :     real(r8) :: aerdepwetis(pcols,pcnst)  ! aerosol wet deposition (interstitial)
     388       48384 :     real(r8) :: dcondt_resusp3d(nele_tot,pcols,pver)
     389             : 
     390             :     integer, parameter :: nsrflx_mzaer2cnvpr = 2
     391       48384 :     real(r8) :: qsrflx_mzaer2cnvpr(pcols,nele_tot,nsrflx_mzaer2cnvpr)
     392             : 
     393       24192 :     real(r8), pointer :: rprddp(:,:)     ! rain production, deep convection
     394       24192 :     real(r8), pointer :: rprdsh(:,:)     ! rain production, shallow convection
     395       24192 :     real(r8), pointer :: evapcdp(:,:)    ! Evaporation rate of deep    convective precipitation >=0.
     396       24192 :     real(r8), pointer :: evapcsh(:,:)    ! Evaporation rate of shallow convective precipitation >=0.
     397             : 
     398             :     real(r8) :: rprddpsum(pcols)
     399             :     real(r8) :: rprdshsum(pcols)
     400             :     real(r8) :: evapcdpsum(pcols)
     401             :     real(r8) :: evapcshsum(pcols)
     402             : 
     403             :     real(r8) :: tmp_resudp, tmp_resush
     404             :     real(r8) :: tmpa, tmpb
     405             :     real(r8) :: sflxec(pcols), sflxecdp(pcols)  ! deposition flux
     406             :     real(r8) :: sflxic(pcols), sflxicdp(pcols)  ! deposition flux
     407             :     real(r8) :: sflxbc(pcols), sflxbcdp(pcols)  ! deposition flux
     408             : 
     409             :     class(aerosol_state), pointer :: aero_state
     410             : 
     411       24192 :     nullify(aero_state)
     412             : 
     413       24192 :     if (.not.wetdep_active) return
     414             : 
     415  1110195072 :     dcondt_resusp3d(:,:,:) = 0._r8
     416             : 
     417       24192 :     if (nmodes>0) then
     418       24192 :        aero_state => modal_aerosol_state(state,pbuf)
     419       24192 :        if (.not.associated(aero_state)) then
     420           0 :           call endrun(subrname//' : construction of aero_state modal_aerosol_state object failed')
     421             :        end if
     422           0 :     else if (nbins>0) then
     423           0 :        aero_state => carma_aerosol_state(state,pbuf)
     424           0 :        if (.not.associated(aero_state)) then
     425           0 :           call endrun(subrname//' : construction of aero_state carma_aerosol_state object failed')
     426             :        end if
     427             :     else
     428           0 :        call endrun(subrname//' : cannot determine aerosol model')
     429             :     endif
     430             : 
     431       24192 :     lchnk = state%lchnk
     432       24192 :     ncol = state%ncol
     433             : 
     434       24192 :     call physics_ptend_init(ptend, state%psetcols, subrname, lq=wetdep_lq)
     435             : 
     436       24192 :     call wetdep_inputs_set( state, pbuf, dep_inputs )
     437             : 
     438       24192 :     call pbuf_get_field(pbuf, fracis_idx, fracis)
     439             : 
     440       24192 :     call aero_state%get_states( aero_props, raer, qqcw )
     441             : 
     442    17345664 :     qsrflx_mzaer2cnvpr(:,:,:) = 0.0_r8
     443       24192 :     aerdepwetis(:,:) = 0.0_r8
     444       24192 :     aerdepwetcw(:,:) = 0.0_r8
     445             : 
     446       24192 :     if (convproc_do_aer) then
     447             :        !Do cloudborne first for unified convection scheme so that the resuspension of cloudborne
     448             :        !can be saved then applied to interstitial
     449             :        strt_loop   =  2
     450             :        end_loop    =  1
     451             :        stride_loop = -1
     452             :     else
     453             :        ! Counters for "without" unified convective treatment (i.e. default case)
     454           0 :        strt_loop   = 1
     455           0 :        end_loop    = 2
     456           0 :        stride_loop = 1
     457             :     endif
     458             : 
     459      314496 :     prec(:ncol)=0._r8
     460     3169152 :     do k=1,pver
     461    40884480 :        where (prec(:ncol) >= 1.e-7_r8)
     462             :           isprx(:ncol,k) = .true.
     463             :        elsewhere
     464     3144960 :           isprx(:ncol,k) = .false.
     465             :        endwhere
     466           0 :        prec(:ncol) = prec(:ncol) + (dep_inputs%prain(:ncol,k) + dep_inputs%cmfdqr(:ncol,k) - dep_inputs%evapr(:ncol,k)) &
     467    40908672 :                     *state%pdel(:ncol,k)/gravit
     468             :     end do
     469             : 
     470       24192 :     f_act_conv = 0._r8
     471       24192 :     scavcoefnv = nan
     472       24192 :     qqcw_sav = nan
     473             : 
     474       24192 :     if (convproc_do_aer) then
     475             : 
     476       24192 :        call t_startf('aero_convproc')
     477             :        call aero_convproc_intr( aero_props, aero_state, state, ptend, pbuf, dt, &
     478       24192 :             nsrflx_mzaer2cnvpr, qsrflx_mzaer2cnvpr, aerdepwetis, dcondt_resusp3d )
     479             : 
     480       24192 :        if (convproc_do_evaprain_atonce) then
     481             : 
     482      145152 :           do m = 1,aero_props%nbins()
     483      653184 :              do l = 0,aero_props%nspecies(m)
     484      508032 :                 mm = aero_props%indexer(m,l)
     485             : 
     486      508032 :                 if (l == 0) then   ! number
     487      120960 :                    call aero_props%num_names(m, aname, cname)
     488             :                 else
     489      387072 :                    call aero_props%mmr_names(m,l, aname, cname)
     490             :                 end if
     491             : 
     492   859082112 :                 call outfld( trim(cname)//'RSPTD', dcondt_resusp3d(mm,:ncol,:), ncol, lchnk )
     493             : 
     494    66673152 :                 do k = 1,pver
     495   859082112 :                    do i = 1,ncol
     496   858574080 :                       qqcw(mm)%fld(i,k) = max(0._r8, qqcw(mm)%fld(i,k) + dcondt_resusp3d(mm,i,k)*dt)
     497             :                    end do
     498             :                 end do
     499             : 
     500             :              end do
     501             :           end do
     502             :        end if
     503       24192 :        call t_stopf('aero_convproc')
     504             : 
     505             :     end if
     506             : 
     507      145152 :     bins_loop: do m = 1,aero_props%nbins()
     508             : 
     509      387072 :        phase_loop: do lphase = strt_loop,end_loop, stride_loop ! loop over interstitial (1) and cloud-borne (2) forms
     510             : 
     511      241920 :           cldbrn = lphase==2
     512             : 
     513      241920 :           sol_factb = nan
     514      241920 :           sol_facti = nan
     515      241920 :           sol_factic = nan
     516             : 
     517      241920 :           if (lphase == 1) then ! interstial aerosol
     518             : 
     519      120960 :              sol_facti = 0.0_r8 ! strat in-cloud scav totally OFF for institial
     520             : 
     521   267442560 :              sol_factic = sol_factic_interstitial
     522             : 
     523             :           else ! cloud-borne aerosol (borne by stratiform cloud drops)
     524             : 
     525      120960 :              sol_factb  = 0.0_r8   ! all below-cloud scav OFF (anything cloud-borne is located "in-cloud")
     526   267442560 :              sol_facti  = sol_facti_cloud_borne   ! strat  in-cloud scav cloud-borne tuning factor
     527      120960 :              sol_factic = 0.0_r8   ! conv   in-cloud scav OFF (having this on would mean
     528             :              !        that conv precip collects strat droplets)
     529      120960 :              f_act_conv = 0.0_r8   ! conv   in-cloud scav OFF (having this on would mean
     530             : 
     531             :           end if
     532      241920 :           if (convproc_do_aer .and. lphase == 1) then
     533             :              ! if modal aero convproc is turned on for aerosols, then
     534             :              !    turn off the convective in-cloud removal for interstitial aerosols
     535             :              !    (but leave the below-cloud on, as convproc only does in-cloud)
     536             :              !    and turn off the outfld SFWET, SFSIC, SFSID, SFSEC, and SFSED calls
     537             :              ! for (stratiform)-cloudborne aerosols, convective wet removal
     538             :              !    (all forms) is zero, so no action is needed
     539      120960 :              sol_factic = 0.0_r8
     540             :           endif
     541             : 
     542   409086720 :           diam_wet = aero_state%wet_diameter(m,ncol,pver)
     543             : 
     544      241920 :           scavcoefnv = 0.0_r8
     545             : 
     546      241920 :           if (lphase == 1) then ! interstial aerosol
     547      120960 :              call get_bcscavcoefs( m, ncol, isprx, diam_wet, scavcoefnv(:,:,1), scavcoefnv(:,:,2) )
     548             : 
     549      120960 :              if ( sol_factb_interstitial /= NOTSET ) then
     550   204543360 :                 sol_factb(:ncol,:) = sol_factb_interstitial ! all below-cloud scav
     551             :              else
     552           0 :                 sol_factb(:ncol,:) = aero_state%sol_factb_interstitial( m, ncol, pver, aero_props )
     553             :              end if
     554             : 
     555      120960 :              write(binstr,'(i2.2)') m
     556      120960 :              call outfld('SOLFACTB'//binstr,sol_factb, pcols, lchnk)
     557             : 
     558             :           end if
     559             : 
     560     1378944 :           elem_loop: do l = 0,aero_props%nspecies(m)
     561             : 
     562     1016064 :              ndx = aero_cnst_id(m,l)
     563     1016064 :              if (ndx<1) cycle elem_loop
     564             : 
     565     1016064 :              if (.not. cldbrn .and. ndx>0) then
     566      508032 :                 insolfr_ptr => fracis(:,:,ndx)
     567             :              else
     568      508032 :                 insolfr_ptr => fracis_nadv
     569             :              endif
     570             : 
     571     1016064 :              mm = aero_props%indexer(m,l)
     572             : 
     573     1016064 :              if (l == 0) then   ! number
     574      241920 :                 call aero_props%num_names( m, aname, cname)
     575             :              else
     576      774144 :                 call aero_props%mmr_names( m,l, aname, cname)
     577             :              end if
     578             : 
     579     1016064 :              if (cldbrn) then
     580   859082112 :                 q_tmp(1:ncol,:) = qqcw(mm)%fld(1:ncol,:)
     581      508032 :                 jnv = 0
     582      508032 :                 if (convproc_do_aer) then
     583   859082112 :                    qqcw_sav(:ncol,:,l) = q_tmp(1:ncol,:)
     584             :                 endif
     585      508032 :                 name = cname
     586      508032 :                 qqcw_in = nan
     587      508032 :                 f_act_conv = nan
     588             :              else ! interstial aerosol
     589   859082112 :                 q_tmp(1:ncol,:) = raer(mm)%fld(1:ncol,:) + ptend%q(1:ncol,:,ndx)*dt
     590      508032 :                 if (l==0) then
     591             :                    jnv = 1
     592             :                 else
     593      387072 :                    jnv = 2
     594             :                 end if
     595      508032 :                 if(convproc_do_aer) then
     596             :                    !Feed in the saved cloudborne mixing ratios from phase 2
     597   859082112 :                    qqcw_in(:ncol,:) = qqcw_sav(:ncol,:,l)
     598             :                 else
     599           0 :                    qqcw_in(:ncol,:) = qqcw(mm)%fld(:ncol,:)
     600             :                 end if
     601             : 
     602   859082112 :                 f_act_conv(:ncol,:) = aero_state%convcld_actfrac( m, l, ncol, pver)
     603      508032 :                 name = aname
     604             :              end if
     605             : 
     606  1718164224 :              dqdt_tmp(1:ncol,:) = 0.0_r8
     607             : 
     608             :              call wetdepa_v2(state%pmid, state%q(:,:,1), state%pdel, &
     609             :                   dep_inputs%cldt, dep_inputs%cldcu, dep_inputs%cmfdqr, &
     610             :                   dep_inputs%evapc, dep_inputs%conicw, dep_inputs%prain, dep_inputs%qme, &
     611             :                   dep_inputs%evapr, dep_inputs%totcond, q_tmp, dt, &
     612             :                   dqdt_tmp, iscavt, dep_inputs%cldvcu, dep_inputs%cldvst, &
     613             :                   dlf, insolfr_ptr, sol_factb, ncol, &
     614             :                   scavcoefnv(:,:,jnv), &
     615             :                   is_strat_cloudborne=cldbrn, &
     616             :                   qqcw=qqcw_in(:,:), f_act_conv=f_act_conv, &
     617             :                   icscavt=icscavt, isscavt=isscavt, bcscavt=bcscavt, bsscavt=bsscavt, &
     618             :                   convproc_do_aer=convproc_do_aer, rcscavt=rcscavt, rsscavt=rsscavt,  &
     619             :                   sol_facti_in=sol_facti, sol_factic_in=sol_factic, &
     620             :                   convproc_do_evaprain_atonce_in=convproc_do_evaprain_atonce, &
     621     1016064 :                   bergso_in=dep_inputs%bergso )
     622             : 
     623     1016064 :              if(convproc_do_aer) then
     624     1016064 :                 if(cldbrn) then
     625             :                    ! save resuspension of cloudborne species
     626   859082112 :                    rtscavt(1:ncol,:,l) = rcscavt(1:ncol,:) + rsscavt(1:ncol,:)
     627             :                    ! wetdepa_v2 adds the resuspension of cloudborne to the dqdt of cloudborne (as a source)
     628             :                    ! undo this, so the resuspension of cloudborne can be added to the dqdt of interstitial (above)
     629   859082112 :                    dqdt_tmp(1:ncol,:) = dqdt_tmp(1:ncol,:) - rtscavt(1:ncol,:,l)
     630             :                 else
     631             :                    ! add resuspension of cloudborne species to dqdt of interstitial species
     632   859082112 :                    dqdt_tmp(1:ncol,:) = dqdt_tmp(1:ncol,:) + rtscavt(1:ncol,:,l)
     633             :                 end if
     634             :              endif
     635             : 
     636     1016064 :              if (cldbrn) then
     637    66552192 :                 do k = 1,pver
     638   859082112 :                    do i = 1,ncol
     639   858574080 :                       if ( (qqcw(mm)%fld(i,k) + dqdt_tmp(i,k) * dt) .lt. 0.0_r8 )   then
     640           0 :                          dqdt_tmp(i,k) = - qqcw(mm)%fld(i,k) / dt
     641             :                       end if
     642             :                    end do
     643             :                 end do
     644             : 
     645   859082112 :                 qqcw(mm)%fld(1:ncol,:) = qqcw(mm)%fld(1:ncol,:) + dqdt_tmp(1:ncol,:) * dt
     646             : 
     647             :              else
     648   859082112 :                 ptend%q(1:ncol,:,ndx) = ptend%q(1:ncol,:,ndx) + dqdt_tmp(1:ncol,:)
     649             :              end if
     650             : 
     651     1016064 :              call outfld( trim(name)//'WET', dqdt_tmp(:,:), pcols, lchnk)
     652     1016064 :              call outfld( trim(name)//'SIC', icscavt, pcols, lchnk)
     653     1016064 :              call outfld( trim(name)//'SIS', isscavt, pcols, lchnk)
     654     1016064 :              call outfld( trim(name)//'SBC', bcscavt, pcols, lchnk)
     655     1016064 :              call outfld( trim(name)//'SBS', bsscavt, pcols, lchnk)
     656             : 
     657     1016064 :              call outfld( trim(name)//'INS', insolfr_ptr, pcols, lchnk)
     658             : 
     659     1016064 :              sflx(:)=0._r8
     660   133104384 :              do k=1,pver
     661  1718164224 :                 do i=1,ncol
     662  1717148160 :                    sflx(i)=sflx(i)+dqdt_tmp(i,k)*state%pdel(i,k)/gravit
     663             :                 enddo
     664             :              enddo
     665     1016064 :              if (cldbrn) then
     666      508032 :                 call outfld( trim(name)//'SFWET', sflx, pcols, lchnk)
     667     6604416 :                 if (ndx>0) aerdepwetcw(:ncol,ndx) = sflx(:ncol)
     668             :              else
     669      508032 :                 if (.not.convproc_do_aer) call outfld( trim(name)//'SFWET', sflx, pcols, lchnk)
     670     6604416 :                 if (ndx>0) aerdepwetis(:ncol,ndx) = aerdepwetis(:ncol,ndx) + sflx(:ncol)
     671             :              end if
     672             : 
     673     1016064 :              sflx(:)=0._r8
     674   133104384 :              do k=1,pver
     675  1718164224 :                 do i=1,ncol
     676  1717148160 :                    sflx(i)=sflx(i)+icscavt(i,k)*state%pdel(i,k)/gravit
     677             :                 enddo
     678             :              enddo
     679     1016064 :              if (cldbrn) then
     680      508032 :                 call outfld( trim(name)//'SFSIC', sflx, pcols, lchnk)
     681             :              else
     682      508032 :                 if (.not.convproc_do_aer) call outfld( trim(name)//'SFSIC', sflx, pcols, lchnk)
     683      508032 :                 if (convproc_do_aer) sflxic = sflx
     684             :              end if
     685             : 
     686     1016064 :              sflx(:)=0._r8
     687   133104384 :              do k=1,pver
     688  1718164224 :                 do i=1,ncol
     689  1717148160 :                    sflx(i)=sflx(i)+isscavt(i,k)*state%pdel(i,k)/gravit
     690             :                 enddo
     691             :              enddo
     692     1016064 :              call outfld( trim(name)//'SFSIS', sflx, pcols, lchnk)
     693             : 
     694     1016064 :              sflx(:)=0._r8
     695   133104384 :              do k=1,pver
     696  1718164224 :                 do i=1,ncol
     697  1717148160 :                    sflx(i)=sflx(i)+bcscavt(i,k)*state%pdel(i,k)/gravit
     698             :                 enddo
     699             :              enddo
     700     1016064 :              call outfld( trim(name)//'SFSBC', sflx, pcols, lchnk)
     701     1016064 :              if (convproc_do_aer) sflxbc = sflx
     702             : 
     703     1016064 :              sflx(:)=0._r8
     704   133104384 :              do k=1,pver
     705  1718164224 :                 do i=1,ncol
     706  1717148160 :                    sflx(i)=sflx(i)+bsscavt(i,k)*state%pdel(i,k)/gravit
     707             :                 enddo
     708             :              enddo
     709     1016064 :              call outfld( trim(name)//'SFSBS', sflx, pcols, lchnk)
     710             : 
     711     1257984 :              if(convproc_do_aer) then
     712             : 
     713     1016064 :                 sflx(:)=0.0_r8
     714   133104384 :                 do k=1,pver
     715  1718164224 :                    do i=1,ncol
     716  1717148160 :                       sflx(i)=sflx(i)+rsscavt(i,k)*state%pdel(i,k)/gravit
     717             :                    enddo
     718             :                 enddo
     719     1016064 :                 call outfld( trim(name)//'SFSES', sflx, pcols, lchnk)
     720             : 
     721     1016064 :                 sflx(:)=0._r8
     722   133104384 :                 do k=1,pver
     723  1718164224 :                    do i=1,ncol
     724  1717148160 :                       sflx(i)=sflx(i)+rcscavt(i,k)*state%pdel(i,k)/gravit
     725             :                    enddo
     726             :                 enddo
     727     1016064 :                 if (.not.convproc_do_aer) call outfld( trim(name)//'SFSEC', sflx, pcols, lchnk)
     728     1016064 :                 sflxec = sflx
     729             : 
     730     1016064 :                 if(.not.cldbrn) then
     731             : 
     732             :                    ! apportion convective surface fluxes to deep and shallow conv
     733             :                    ! this could be done more accurately in subr wetdepa
     734             :                    ! since deep and shallow rarely occur simultaneously, and these
     735             :                    !    fields are just diagnostics, this approximate method is adequate
     736             :                    ! only do this for interstitial aerosol, because conv clouds to not
     737             :                    !    affect the stratiform-cloudborne aerosol
     738      508032 :                    if ( deepconv_wetdep_history) then
     739             : 
     740      508032 :                       call pbuf_get_field(pbuf, rprddp_idx,      rprddp  )
     741      508032 :                       call pbuf_get_field(pbuf, rprdsh_idx,      rprdsh  )
     742      508032 :                       call pbuf_get_field(pbuf, nevapr_dpcu_idx, evapcdp )
     743      508032 :                       call pbuf_get_field(pbuf, nevapr_shcu_idx, evapcsh )
     744             : 
     745      508032 :                       rprddpsum(:)  = 0.0_r8
     746      508032 :                       rprdshsum(:)  = 0.0_r8
     747      508032 :                       evapcdpsum(:) = 0.0_r8
     748      508032 :                       evapcshsum(:) = 0.0_r8
     749             : 
     750    66552192 :                       do k = 1, pver
     751   858574080 :                          rprddpsum(:ncol)  = rprddpsum(:ncol)  +  rprddp(:ncol,k)*state%pdel(:ncol,k)/gravit
     752   858574080 :                          rprdshsum(:ncol)  = rprdshsum(:ncol)  +  rprdsh(:ncol,k)*state%pdel(:ncol,k)/gravit
     753   858574080 :                          evapcdpsum(:ncol) = evapcdpsum(:ncol) + evapcdp(:ncol,k)*state%pdel(:ncol,k)/gravit
     754   859082112 :                          evapcshsum(:ncol) = evapcshsum(:ncol) + evapcsh(:ncol,k)*state%pdel(:ncol,k)/gravit
     755             :                       end do
     756             : 
     757     6604416 :                       do i = 1, ncol
     758     6096384 :                          rprddpsum(i)  = max( rprddpsum(i),  1.0e-35_r8 )
     759     6096384 :                          rprdshsum(i)  = max( rprdshsum(i),  1.0e-35_r8 )
     760     6096384 :                          evapcdpsum(i) = max( evapcdpsum(i), 0.1e-35_r8 )
     761     6096384 :                          evapcshsum(i) = max( evapcshsum(i), 0.1e-35_r8 )
     762             : 
     763             :                          ! assume that in- and below-cloud removal are proportional to column precip production
     764     6096384 :                          tmpa = rprddpsum(i) / (rprddpsum(i) + rprdshsum(i))
     765     6096384 :                          tmpa = max( 0.0_r8, min( 1.0_r8, tmpa ) )
     766     6096384 :                          sflxicdp(i) = sflxic(i)*tmpa
     767     6096384 :                          sflxbcdp(i) = sflxbc(i)*tmpa
     768             : 
     769             :                          ! assume that resuspension is proportional to (wet removal)*[(precip evap)/(precip production)]
     770     6096384 :                          tmp_resudp =           tmpa  * min( (evapcdpsum(i)/rprddpsum(i)), 1.0_r8 )
     771     6096384 :                          tmp_resush = (1.0_r8 - tmpa) * min( (evapcshsum(i)/rprdshsum(i)), 1.0_r8 )
     772     6096384 :                          tmpb = max( tmp_resudp, 1.0e-35_r8 ) / max( (tmp_resudp+tmp_resush), 1.0e-35_r8 )
     773     6096384 :                          tmpb = max( 0.0_r8, min( 1.0_r8, tmpb ) )
     774     6604416 :                          sflxecdp(i) = sflxec(i)*tmpb
     775             :                       end do
     776      508032 :                       call outfld( trim(name)//'SFSBD', sflxbcdp, pcols, lchnk)
     777             :                    else
     778           0 :                       sflxec(1:ncol)   = 0.0_r8
     779           0 :                       sflxecdp(1:ncol) = 0.0_r8
     780             :                    end if
     781             : 
     782             :                    ! when ma_convproc_intr is used, convective in-cloud wet removal is done there
     783             :                    ! the convective (total and deep) precip-evap-resuspension includes in- and below-cloud
     784             :                    ! contributions
     785             :                    ! so pass the below-cloud contribution to ma_convproc_intr
     786     6604416 :                    qsrflx_mzaer2cnvpr(1:ncol,mm,1) = sflxec(  1:ncol)
     787     6604416 :                    qsrflx_mzaer2cnvpr(1:ncol,mm,2) = sflxecdp(1:ncol)
     788             : 
     789             :                 end if
     790             :              end if
     791             : 
     792             :           end do elem_loop
     793             :        end do phase_loop
     794             : 
     795             :     end do bins_loop
     796             : 
     797       24192 :     if (associated(aero_state)) then
     798       48384 :        deallocate(aero_state)
     799             :        nullify(aero_state)
     800             :     end if
     801             : 
     802             :     ! if the user has specified prescribed aerosol dep fluxes then
     803             :     ! do not set cam_out dep fluxes according to the prognostic aerosols
     804       72576 :     if (.not. aerodep_flx_prescribed()) then
     805       24192 :        call aero_deposition_cam_setwet(aerdepwetis, aerdepwetcw, cam_out)
     806             :     endif
     807             : 
     808             :   contains
     809             : 
     810             :     ! below cloud impaction scavenging coefs
     811      120960 :     subroutine get_bcscavcoefs( m, ncol, isprx, diam_wet, scavcoefnum, scavcoefvol )
     812             : 
     813             :       integer,intent(in) :: m, ncol
     814             :       logical,intent(in):: isprx(:,:)
     815             :       real(r8), intent(in) :: diam_wet(:,:)
     816             :       real(r8), intent(out) :: scavcoefnum(:,:), scavcoefvol(:,:)
     817             : 
     818             :       integer i, k, jgrow
     819             :       real(r8) dumdgratio, xgrow, dumfhi, dumflo, scavimpvol, scavimpnum
     820             : 
     821    15845760 :       do k = 1, pver
     822   204543360 :          do i = 1, ncol
     823             : 
     824             :             ! do only if no precip
     825   204422400 :             if ( isprx(i,k) .and. diam_wet(i,k)>0.0_r8) then
     826             :                !
     827             :                ! interpolate table values using log of (actual-wet-size)/(base-dry-size)
     828             : 
     829    11252425 :                dumdgratio = diam_wet(i,k)/aero_props%scav_diam(m)
     830    11252425 :                if ((dumdgratio >= 0.99_r8) .and. (dumdgratio <= 1.01_r8)) then
     831      108858 :                   scavimpvol = scavimptblvol(0,m)
     832      108858 :                   scavimpnum = scavimptblnum(0,m)
     833             :                else
     834    11143567 :                   xgrow = log( dumdgratio ) / dlndg_nimptblgrow
     835    11143567 :                   jgrow = int( xgrow )
     836    11143567 :                   if (xgrow < 0._r8) jgrow = jgrow - 1
     837    11143567 :                   if (jgrow < nimptblgrow_mind) then
     838             :                      jgrow = nimptblgrow_mind
     839             :                      xgrow = jgrow
     840             :                   else
     841    11143567 :                      jgrow = min( jgrow, nimptblgrow_maxd-1 )
     842             :                   end if
     843             : 
     844    11143567 :                   dumfhi = xgrow - jgrow
     845    11143567 :                   dumflo = 1._r8 - dumfhi
     846             : 
     847           0 :                   scavimpvol = dumflo*scavimptblvol(jgrow,m) + &
     848    11143567 :                                dumfhi*scavimptblvol(jgrow+1,m)
     849           0 :                   scavimpnum = dumflo*scavimptblnum(jgrow,m) + &
     850    11143567 :                                dumfhi*scavimptblnum(jgrow+1,m)
     851             : 
     852             :                end if
     853             : 
     854             :                ! impaction scavenging removal amount for volume
     855    11252425 :                scavcoefvol(i,k) = exp( scavimpvol )
     856             :                ! impaction scavenging removal amount to number
     857    11252425 :                scavcoefnum(i,k) = exp( scavimpnum )
     858             : 
     859             :             else
     860   177445175 :                scavcoefvol(i,k) = 0._r8
     861   177445175 :                scavcoefnum(i,k) = 0._r8
     862             :             end if
     863             : 
     864             :          end do
     865             :       end do
     866             : 
     867       24192 :     end subroutine get_bcscavcoefs
     868             : 
     869             :   end subroutine aero_wetdep_tend
     870             : 
     871             :   !------------------------------------------------------------------------------
     872             :   !------------------------------------------------------------------------------
     873         768 :   subroutine init_bcscavcoef( )
     874             :     !-----------------------------------------------------------------------
     875             :     !
     876             :     ! Purpose:
     877             :     ! Computes lookup table for aerosol impaction/interception scavenging rates
     878             :     !
     879             :     ! Authors: R. Easter
     880             :     ! Simone Tilmes Nov 2021
     881             :     ! added modifications for bin model, assuming sigma = 1.
     882             :     !
     883             :     !-----------------------------------------------------------------------
     884             : 
     885             :     use mo_constants,   only: pi
     886             : 
     887             :     !   local variables
     888             :     integer nnfit_maxd
     889             :     parameter (nnfit_maxd=27)
     890             : 
     891             :     integer m, jgrow, nnfit
     892             :     integer lunerr
     893             : 
     894             :     real(r8) dg0, dg0_cgs, press, dg0_base, &
     895             :          rhodryaero, rhowetaero, rhowetaero_cgs, &
     896             :          scavratenum, scavratevol, logsig,                &
     897             :          temp, wetdiaratio, wetvolratio
     898             : 
     899             :     real(r8) :: xxfitnum(1,nnfit_maxd), yyfitnum(nnfit_maxd)
     900             :     real(r8) :: xxfitvol(1,nnfit_maxd), yyfitvol(nnfit_maxd)
     901             : 
     902             :     character(len=*), parameter :: subname = 'aero_wetdep_cam::init_bcscavcoef'
     903             : 
     904         768 :     lunerr = iulog
     905         768 :     dlndg_nimptblgrow = log( 1.25_r8 )
     906             : 
     907             :     ! bin model: main loop over aerosol bins
     908             : 
     909        4608 :     modeloop: do m = 1, aero_props%nbins()
     910             : 
     911             :        ! for setting up the lookup table, use the dry density of the first species
     912             :        ! -- assume the first species of the mode/bin is the dominate species
     913        3840 :        call aero_props%get(m,1,density=rhodryaero)
     914             : 
     915        3840 :        dg0_base = aero_props%scav_diam(m)
     916             : 
     917        3840 :        logsig = aero_props%alogsig(m)
     918             : 
     919       81408 :        growloop: do jgrow = nimptblgrow_mind, nimptblgrow_maxd
     920             : 
     921       76800 :           wetdiaratio = exp( jgrow*dlndg_nimptblgrow )
     922       76800 :           dg0 = dg0_base*wetdiaratio
     923             : 
     924             :           wetvolratio = exp( jgrow*dlndg_nimptblgrow*3._r8 )
     925       76800 :           rhowetaero = 1.0_r8 + (rhodryaero-1.0_r8)/wetvolratio
     926       76800 :           rhowetaero = min( rhowetaero, rhodryaero )
     927             : 
     928             :           !
     929             :           !   compute impaction scavenging rates at 1 temp-press pair and save
     930             :           !
     931       76800 :           nnfit = 0
     932             : 
     933       76800 :           temp = 273.16_r8
     934       76800 :           press = 0.75e6_r8   ! dynes/cm2
     935       76800 :           rhowetaero = rhodryaero
     936             : 
     937       76800 :           dg0_cgs = dg0*1.0e2_r8   ! m to cm
     938             : 
     939       76800 :           rhowetaero_cgs = rhowetaero*1.0e-3_r8   ! kg/m3 to g/cm3
     940             : 
     941             :           call calc_1_impact_rate( &
     942             :                dg0_cgs, logsig, rhowetaero_cgs, temp, press, &
     943       76800 :                scavratenum, scavratevol, lunerr )
     944             : 
     945       76800 :           nnfit = nnfit + 1
     946             :           if (nnfit > nnfit_maxd) then
     947             :              write(lunerr,9110)
     948             :              call endrun(subname//' : nnfit > nnfit_maxd')
     949             :           end if
     950             : 9110      format( '*** subr. init_bcscavcoef -- nnfit too big' )
     951             : 
     952       76800 :           xxfitnum(1,nnfit) = 1._r8
     953       76800 :           yyfitnum(nnfit) = log( scavratenum )
     954             : 
     955       76800 :           xxfitvol(1,nnfit) = 1._r8
     956       76800 :           yyfitvol(nnfit) = log( scavratevol )
     957             : 
     958             :          !depends on both bins and different species
     959       76800 :           scavimptblnum(jgrow,m) = yyfitnum(1)
     960      157440 :           scavimptblvol(jgrow,m) = yyfitvol(1)
     961             : 
     962             :        enddo growloop
     963             :     enddo modeloop
     964             : 
     965             :   contains
     966             : 
     967             :     !===============================================================================
     968       76800 :     subroutine calc_1_impact_rate(          &
     969             :          dg0, logsig, rhoaero, temp, press, &
     970             :          scavratenum, scavratevol, lunerr )
     971             :       !
     972             :       !   routine computes a single impaction scavenging rate
     973             :       ! for precipitation rate of 1 mm/h
     974             :       !
     975             :       !   dg0 = geometric mean diameter of aerosol number size distrib. (cm)
     976             :       !   sigmag = geometric standard deviation of size distrib.
     977             :       !   rhoaero = density of aerosol particles (g/cm^3)
     978             :       !   temp = temperature (K)
     979             :       !   press = pressure (dyne/cm^2)
     980             :       !   scavratenum = number scavenging rate (1/h)
     981             :       !   scavratevol = volume or mass scavenging rate (1/h)
     982             :       !   lunerr = logical unit for error message
     983             :       !
     984             :       use mo_constants, only: boltz_cgs, pi, rhowater => rhoh2o_cgs, rgas => rgas_cgs
     985             : 
     986             :       implicit none
     987             : 
     988             :       !   subr. parameters
     989             :       integer, intent(in) :: lunerr
     990             :       real(r8), intent(in) :: dg0, logsig, rhoaero, temp, press
     991             :       real(r8), intent(out) :: scavratenum, scavratevol
     992             : 
     993             :       !   local variables
     994             :       integer nrainsvmax
     995             :       parameter (nrainsvmax=50)
     996             :       real(r8) rrainsv(nrainsvmax), xnumrainsv(nrainsvmax),&
     997             :            vfallrainsv(nrainsvmax)
     998             : 
     999             :       integer naerosvmax
    1000             :       parameter (naerosvmax=51)
    1001             :       real(r8) aaerosv(naerosvmax), &
    1002             :            ynumaerosv(naerosvmax), yvolaerosv(naerosvmax)
    1003             : 
    1004             :       integer i, ja, jr, na, nr
    1005             :       real(r8) a, aerodiffus, aeromass, ag0, airdynvisc, airkinvisc
    1006             :       real(r8) anumsum, avolsum, cair, chi
    1007             :       real(r8) d, dr, dum, dumfuchs, dx
    1008             :       real(r8) ebrown, eimpact, eintercept, etotal, freepath
    1009             :       real(r8) precip, precipmmhr, precipsum
    1010             :       real(r8) r, rainsweepout, reynolds, rhi, rhoair, rlo, rnumsum
    1011             :       real(r8) scavsumnum, scavsumnumbb
    1012             :       real(r8) scavsumvol, scavsumvolbb
    1013             :       real(r8) schmidt, sqrtreynolds, sstar, stokes, sx
    1014             :       real(r8) taurelax, vfall, vfallstp
    1015             :       real(r8) x, xg0, xg3, xhi, xlo, xmuwaterair
    1016             : 
    1017       76800 :       rlo = .005_r8
    1018       76800 :       rhi = .250_r8
    1019       76800 :       dr = 0.005_r8
    1020       76800 :       nr = 1 + nint( (rhi-rlo)/dr )
    1021             :       if (nr > nrainsvmax) then
    1022             :          write(lunerr,9110)
    1023             :          call endrun(subname//' : nr > nrainsvmax')
    1024             :       end if
    1025             : 
    1026             : 9110  format( '*** subr. calc_1_impact_rate -- nr > nrainsvmax' )
    1027             : 
    1028       76800 :       precipmmhr = 1.0_r8
    1029       76800 :       precip = precipmmhr/36000._r8
    1030             : 
    1031       76800 :       ag0 = dg0/2._r8
    1032       76800 :       sx = logsig
    1033       76800 :       xg0 = log( ag0 )
    1034       76800 :       xg3 = xg0 + 3._r8*sx*sx
    1035             : 
    1036       76800 :       xlo = xg3 - 4._r8*sx
    1037       76800 :       xhi = xg3 + 4._r8*sx
    1038       76800 :       dx = 0.2_r8*sx
    1039             : 
    1040       76800 :       dx = max( 0.2_r8*sx, 0.01_r8 )
    1041       76800 :       xlo = xg3 - max( 4._r8*sx, 2._r8*dx )
    1042       76800 :       xhi = xg3 + max( 4._r8*sx, 2._r8*dx )
    1043             : 
    1044       76800 :       na = 1 + nint( (xhi-xlo)/dx )
    1045       76800 :       if (na > naerosvmax) then
    1046           0 :          write(lunerr,9120)
    1047           0 :          call endrun(subname//' : na > naerosvmax')
    1048             :       end if
    1049             : 
    1050             : 9120  format( '*** subr. calc_1_impact_rate -- na > naerosvmax' )
    1051             : 
    1052             :       !   air molar density
    1053       76800 :       cair = press/(rgas*temp)
    1054             :       !   air mass density
    1055       76800 :       rhoair = 28.966_r8*cair
    1056             :       !   molecular freepath
    1057       76800 :       freepath = 2.8052e-10_r8/cair
    1058             :       !   air dynamic viscosity
    1059             :       airdynvisc = 1.8325e-4_r8 * (416.16_r8/(temp+120._r8)) *    &
    1060       76800 :            ((temp/296.16_r8)**1.5_r8)
    1061             :       !   air kinemaic viscosity
    1062       76800 :       airkinvisc = airdynvisc/rhoair
    1063             :       !   ratio of water viscosity to air viscosity (from Slinn)
    1064       76800 :       xmuwaterair = 60.0_r8
    1065             : 
    1066             :       !
    1067             :       !   compute rain drop number concentrations
    1068             :       ! rrainsv = raindrop radius (cm)
    1069             :       ! xnumrainsv = raindrop number concentration (#/cm^3)
    1070             :       !         (number in the bin, not number density)
    1071             :       ! vfallrainsv = fall velocity (cm/s)
    1072             :       !
    1073       76800 :       precipsum = 0._r8
    1074     3916800 :       do i = 1, nr
    1075     3840000 :          r = rlo + (i-1)*dr
    1076     3840000 :          rrainsv(i) = r
    1077     3840000 :          xnumrainsv(i) = exp( -r/2.7e-2_r8 )
    1078             : 
    1079     3840000 :          d = 2._r8*r
    1080     3840000 :          if (d <= 0.007_r8) then
    1081           0 :             vfallstp = 2.88e5_r8 * d**2._r8
    1082     3840000 :          else if (d <= 0.025_r8) then
    1083      153600 :             vfallstp = 2.8008e4_r8 * d**1.528_r8
    1084     3686400 :          else if (d <= 0.1_r8) then
    1085      614400 :             vfallstp = 4104.9_r8 * d**1.008_r8
    1086     3072000 :          else if (d <= 0.25_r8) then
    1087     1152000 :             vfallstp = 1812.1_r8 * d**0.638_r8
    1088             :          else
    1089     1920000 :             vfallstp = 1069.8_r8 * d**0.235_r8
    1090             :          end if
    1091             : 
    1092     3840000 :          vfall = vfallstp * sqrt(1.204e-3_r8/rhoair)
    1093     3840000 :          vfallrainsv(i) = vfall
    1094     3916800 :          precipsum = precipsum + vfall*(r**3)*xnumrainsv(i)
    1095             :       end do
    1096       76800 :       precipsum = precipsum*pi*1.333333_r8
    1097             : 
    1098       76800 :       rnumsum = 0._r8
    1099     3916800 :       do i = 1, nr
    1100     3840000 :          xnumrainsv(i) = xnumrainsv(i)*(precip/precipsum)
    1101     3916800 :          rnumsum = rnumsum + xnumrainsv(i)
    1102             :       end do
    1103             : 
    1104             :       !
    1105             :       !   compute aerosol concentrations
    1106             :       ! aaerosv = particle radius (cm)
    1107             :       ! fnumaerosv = fraction of total number in the bin (--)
    1108             :       ! fvolaerosv = fraction of total volume in the bin (--)
    1109             :       !
    1110             :       anumsum = 0._r8
    1111             :       avolsum = 0._r8
    1112     3225600 :       do i = 1, na
    1113     3148800 :          x = xlo + (i-1)*dx
    1114     3148800 :          a = exp( x )
    1115     3148800 :          aaerosv(i) = a
    1116     3148800 :          dum = (x - xg0)/sx
    1117     3148800 :          ynumaerosv(i) = exp( -0.5_r8*dum*dum )
    1118     3148800 :          yvolaerosv(i) = ynumaerosv(i)*1.3333_r8*pi*a*a*a
    1119     3148800 :          anumsum = anumsum + ynumaerosv(i)
    1120     3225600 :          avolsum = avolsum + yvolaerosv(i)
    1121             :       end do
    1122             : 
    1123     3225600 :       do i = 1, na
    1124     3148800 :          ynumaerosv(i) = ynumaerosv(i)/anumsum
    1125     3225600 :          yvolaerosv(i) = yvolaerosv(i)/avolsum
    1126             :       end do
    1127             : 
    1128             :       !
    1129             :       !   compute scavenging
    1130             :       !
    1131             :       scavsumnum = 0._r8
    1132             :       scavsumvol = 0._r8
    1133             :       !
    1134             :       !   outer loop for rain drop radius
    1135             :       !
    1136     3916800 :       jr_loop: do jr = 1, nr
    1137             : 
    1138     3840000 :          r = rrainsv(jr)
    1139     3840000 :          vfall = vfallrainsv(jr)
    1140             : 
    1141     3840000 :          reynolds = r * vfall / airkinvisc
    1142     3840000 :          sqrtreynolds = sqrt( reynolds )
    1143             : 
    1144             :          !
    1145             :          !   inner loop for aerosol particle radius
    1146             :          !
    1147     3840000 :          scavsumnumbb = 0._r8
    1148     3840000 :          scavsumvolbb = 0._r8
    1149             : 
    1150   161280000 :          ja_loop: do ja = 1, na
    1151             : 
    1152   157440000 :             a = aaerosv(ja)
    1153             : 
    1154   157440000 :             chi = a/r
    1155             : 
    1156   157440000 :             dum = freepath/a
    1157   157440000 :             dumfuchs = 1._r8 + 1.246_r8*dum + 0.42_r8*dum*exp(-0.87_r8/dum)
    1158   157440000 :             taurelax = 2._r8*rhoaero*a*a*dumfuchs/(9._r8*rhoair*airkinvisc)
    1159             : 
    1160   157440000 :             aeromass = 4._r8*pi*a*a*a*rhoaero/3._r8
    1161   157440000 :             aerodiffus = boltz_cgs*temp*taurelax/aeromass
    1162             : 
    1163   157440000 :             schmidt = airkinvisc/aerodiffus
    1164   157440000 :             stokes = vfall*taurelax/r
    1165             : 
    1166             :             ebrown = 4._r8*(1._r8 + 0.4_r8*sqrtreynolds*(schmidt**0.3333333_r8)) /  &
    1167   157440000 :                  (reynolds*schmidt)
    1168             : 
    1169             :             dum = (1._r8 + 2._r8*xmuwaterair*chi) /         &
    1170   157440000 :                  (1._r8 + xmuwaterair/sqrtreynolds)
    1171   157440000 :             eintercept = 4._r8*chi*(chi + dum)
    1172             : 
    1173   157440000 :             dum = log( 1._r8 + reynolds )
    1174   157440000 :             sstar = (1.2_r8 + dum/12._r8) / (1._r8 + dum)
    1175   157440000 :             eimpact = 0._r8
    1176   157440000 :             if (stokes > sstar) then
    1177    44023296 :                dum = stokes - sstar
    1178    44023296 :                eimpact = (dum/(dum+0.6666667_r8)) ** 1.5_r8
    1179             :             end if
    1180             : 
    1181   157440000 :             etotal = ebrown + eintercept + eimpact
    1182   157440000 :             etotal = min( etotal, 1.0_r8 )
    1183             : 
    1184   157440000 :             rainsweepout = xnumrainsv(jr)*4._r8*pi*r*r*vfall
    1185             : 
    1186   157440000 :             scavsumnumbb = scavsumnumbb + rainsweepout*etotal*ynumaerosv(ja)
    1187   161280000 :             scavsumvolbb = scavsumvolbb + rainsweepout*etotal*yvolaerosv(ja)
    1188             : 
    1189             :          enddo ja_loop
    1190             : 
    1191     3840000 :          scavsumnum = scavsumnum + scavsumnumbb
    1192     3916800 :          scavsumvol = scavsumvol + scavsumvolbb
    1193             : 
    1194             :       enddo jr_loop
    1195             : 
    1196       76800 :       scavratenum = scavsumnum*3600._r8
    1197       76800 :       scavratevol = scavsumvol*3600._r8
    1198             : 
    1199       76800 :     end subroutine calc_1_impact_rate
    1200             : 
    1201             :   end subroutine init_bcscavcoef
    1202             : 
    1203             : end module aero_wetdep_cam

Generated by: LCOV version 1.14