#define WRF_PORT
#define MODAL_AERO
! Updated to CESM1.0.3 (CAM5.1.01) by Balwinder.Singh@pnnl.gov

      module ndrop 3,4
#ifdef MODAL_AERO
      use shr_kind_mod,  only: r8 => shr_kind_r8
#ifndef WRF_PORT
      use abortutils,    only: endrun
      use modal_aero_data, only: ntot_amode, qqcw_get_field
      use cam_logfile,     only: iulog
#else
      use module_cam_support, only: endrun, iulog
      use modal_aero_data, only: ntot_amode

#endif

      implicit none

      private
      save

      public activate_init, dropmixnuc

      real(r8) :: npv(ntot_amode) ! number per volume concentration
      real(r8) :: alogsig(ntot_amode) ! natl log of geometric standard dev of aerosol
      real(r8) :: exp45logsig(ntot_amode)
      real(r8) :: argfactor(ntot_amode)
      real(r8) :: f1(ntot_amode),f2(ntot_amode)  ! abdul-razzak functions of width
      real(r8) :: t0 ! reference temperature
      real(r8) :: aten
      real(r8) :: surften       ! surface tension of water w/respect to air (N/m)
      real(r8) :: alogten,alog2,alog3,alogaten
      real(r8) :: third, twothird, sixth, zero
      real(r8) :: sq2, sqpi, pi

      type qqcw_type
         real(r8), pointer :: fldcw(:,:)
      end type qqcw_type

contains


      subroutine dropmixnuc(lchnk, ncol, ncldwtr,tendnd, temp,omega,  & 1,32
                    pmid,pint,pdel,rpdel,zm,kvh,wsub,cldn,cldo,     &
                    raer, cflx, raertend, dtmicro                   &
#ifdef WRF_PORT
                    , qqcw_inout                                    &
#endif
                                                                    ) 

!     vertical diffusion and nucleation of cloud droplets
!     assume cloud presence controlled by cloud fraction
!     doesn't distinguish between warm, cold clouds
#ifndef WRF_PORT
      use ppgrid,        only: pcols, pver, pverp
#else
      use module_cam_support, only: pcols, pver, pverp
#endif
      use physconst,     only: gravit, rhoh2o, latvap, cpair, epsilo, rair, mwh2o, r_universal
#ifndef WRF_PORT
      use time_manager,  only: get_nstep
      use constituents,  only: pcnst, qmin, cnst_get_ind, cnst_name
#else
      use module_cam_support, only: pcnst => pcnst_mp
      use constituents,  only: cnst_get_ind, cnst_name 
#endif
      use error_function, only: erf

!      use aerosol_radiation_interface, only: collect_sw_aer_masses, aer_mass

#ifndef WRF_PORT
      use modal_aero_data
      use cam_history, only: fieldname_len
      use phys_grid,   only: get_lat_all_p, get_lon_all_p
      use physics_types, only: physics_state
      use cam_history,   only: outfld
#else
      use modal_aero_data,    only: numptrcw_amode => numptrcw_amode_mp, &
           nspec_amode  => nspec_amode_mp, lmassptrcw_amode => lmassptrcw_amode_mp, &
           numptr_amode => numptr_amode_mp  , lmassptr_amode   => lmassptr_amode_mp, &
           cnst_name_cw => cnst_name_cw_mp
      use module_cam_support, only: fieldname_len, outfld
#endif

      implicit none

!     input

      integer, intent(in) :: lchnk                ! chunk identifier
      integer, intent(in) :: ncol                 ! number of columns
!      type(physics_state), intent(in) :: state      ! Physics state variables
      real(r8), intent(in) :: dtmicro             ! time step for microphysics (s)
      real(r8), intent(in) :: temp(pcols,pver)    ! temperature (K)
      real(r8), intent(inout) :: ncldwtr(pcols,pver) ! droplet number concentration (#/kg)
      real(r8), intent(inout) :: tendnd(pcols,pver) ! change in droplet number concentration (#/kg/s)
      real(r8), intent(in) :: omega(pcols,pver)   ! vertical velocity (Pa/s)
      real(r8), intent(in) :: pmid(pcols,pver)    ! mid-level pressure (Pa)
      real(r8), intent(in) :: pint(pcols,pverp)   ! pressure at layer interfaces (Pa)
      real(r8), intent(in) :: pdel(pcols,pver)    ! pressure thickess of layer (Pa)
      real(r8), intent(in) :: rpdel(pcols,pver)   ! inverse of pressure thickess of layer (/Pa)
      real(r8), intent(in) :: zm(pcols,pver)      ! geopotential height of level (m)
      real(r8), intent(in) :: kvh(pcols,pverp)    ! vertical diffusivity (m2/s)
      real(r8), intent(in) :: wsub(pcols,pver)    ! subgrid vertical velocity
      real(r8), intent(in) :: cldo(pcols,pver)    ! cloud fraction on previous time step
      real(r8), intent(in) :: cldn(pcols,pver)    ! cloud fraction


!     output

      real(r8), intent(in) :: raer(pcols,pver,pcnst) ! aerosol mass, number mixing ratios
      real(r8), intent(in) :: cflx(pcols,pcnst) ! constituent flux from surface
      real(r8), intent(out) :: raertend(pcols,pver,pcnst) ! tendency of aerosol mass, number mixing ratios
#ifdef WRF_PORT
      real(r8), target, intent(inout) :: qqcw_inout(pcols,pver,pcnst) ! cloud-borne aerosol
#endif

!--------------------Local storage-------------------------------------
!
      type(qqcw_type) :: QQCW(pcnst)

      real(r8) depvel(pcols,pcnst)! deposition velocity for droplets (m/s)
      real(r8) qcld(pver) ! cloud droplet number mixing ratio (#/kg)
      real(r8) wtke(pcols,pver)     ! turbulent vertical velocity at base of layer k (m/s)
      real(r8) wtke_cen(pcols,pver) ! turbulent vertical velocity at center of layer k (m/s)
      real(r8) zn(pver) ! g/pdel (m2/g) for layer
      real(r8) zs(pver) ! inverse of distance between levels (m)
      real(r8), parameter :: zkmin=0.01_r8,zkmax=100._r8
      real(r8) w(pcols,pver)       ! vertical velocity (m/s)
      real(r8) cs(pcols,pver)      ! air density (kg/m3)
      real(r8) dz(pcols,pver)      ! geometric thickness of layers (m)
      real(r8) zero,flxconv ! convergence of flux into lowest layer

      real(r8) wdiab           ! diabatic vertical velocity
      real(r8), parameter :: wmixmin = 0.1 ! minimum turbulence vertical velocity (m/s)
!       real(r8), parameter :: wmixmin = 0.2 ! minimum turbulence vertical velocity (m/s)
!      real(r8), parameter :: wmixmin = 1.0 ! minimum turbulence vertical velocity (m/s)
      real(r8) qncld(pver)     ! droplet number nucleated on cloud boundaries
      real(r8) ekd(pver)       ! diffusivity for droplets (m2/s)
      real(r8) ekk(0:pver)       ! density*diffusivity for droplets (kg/m3 m2/s)
      real(r8) srcn(pver) ! droplet source rate (/s)
      real(r8), parameter :: sq2pi=2.5066283_r8
      real(r8) dtinv

      logical top        ! true if cloud top, false if cloud base or new cloud
      integer km1,kp1
      real(r8) wbar,wmix,wmin,wmax
      real(r8) dum,dumc
      real(r8) dact
      real(r8) fluxntot         ! (#/cm2/s)
      real(r8) fac_srflx
      real(r8) surfrate(pcnst) ! surface exchange rate (/s)
      real(r8) surfratemax      ! max surfrate for all species treated here
      real(r8) dtmin,tinv,dtt
      integer nsubmix,nsubmix_bnd
      integer i,k,m,n
      real(r8) tempr4 ! temperature
      real(r8) dtmix
      real(r8) alogarg
      integer nstep
      real(r8) pi
      integer nnew,nsav,ntemp
      real(r8) overlapp(pver),overlapm(pver) ! cloud overlap
      real(r8) ekkp(pver),ekkm(pver) ! zn*zs*density*diffusivity
      integer count_submix(100)
      save count_submix
      real(r8) kvhmax
      save kvhmax
      real(r8) nsource(pcols,pver)            ! droplet number source (#/kg/s)
      real(r8) ndropmix(pcols,pver)           ! droplet number mixing (#/kg/s)
      real(r8) ndropcol(pcols)               ! column droplet number (#/m2)

      integer lnum, lnumcw, lmass, lmasscw, lphase, &
              lsfc, lsfccw, lsig, lspec, ltype, lwater
      integer ntype(ntot_amode)

      real(r8) na(pcols),va(pcols),hy(pcols)
      real(r8) naermod(ntot_amode) ! (/m3)
      real(r8) sigmag(ntot_amode)  ! geometric standard deviation of aerosol size dist
      real(r8) hygro(ntot_amode)  ! hygroscopicity of aerosol mode
      real(r8) vaerosol(ntot_amode) ! interstit+activated aerosol volume conc (cm3/cm3)
      real(r8) raercol(pver,pcnst,2) ! aerosol mass, number mixing ratios
      real(r8) raercol_cw(pver,pcnst,2) ! cloud-borne aerosol mass, number mixing ratios
      real(r8) surfrate_cw(pcnst) ! surface exchange rate for cloud-borne aerosol (/s)
      real(r8) source(pver) !

      real(r8) fn(ntot_amode)         ! activation fraction for aerosol number
      real(r8) fm(ntot_amode)         ! activation fraction for aerosol mass

      real(r8) fluxn(ntot_amode)      ! number  activation fraction flux (cm/s)
      real(r8) fluxm(ntot_amode)      ! mass    activation fraction flux (cm/s)
      real(r8) sum,sumcw,flux,fluxcw
!     note:  activation fraction fluxes are defined as 
!     fluxn = [flux of activated aero. number into cloud (#/cm2/s)]
!           / [aero. number conc. in updraft, just below cloudbase (#/cm3)]

      real(r8) nact(pver,ntot_amode)  ! fractional aero. number  activation rate (/s)
      real(r8) mact(pver,ntot_amode)  ! fractional aero. mass    activation rate (/s)
      real(r8) sigmag_amode_cur(ntot_amode) ! sigmag for current grid cell
      save sigmag_amode_cur
      real(r8) :: qqcwtend(pcols,pver,pcnst) ! tendency of cloudborne aerosol mass, number mixing ratios
      real(r8) :: coltend(pcols)    ! column tendency
      real(r8) :: tmpa
      integer :: lc
      character(len=fieldname_len)   :: tmpname
      character(len=fieldname_len+3) :: fieldname
      real(r8) :: csbot(pver)       ! air density at bottom (interface) of layer (kg/m3)
      real(r8) :: csbot_cscen(pver) ! csbot(i)/cs(i,k)
      real(r8) :: flux_fullact(pver)     ! 100%    activation fraction flux (cm/s)
      real(r8) :: taumix_internal_pver_inv ! 1/(internal mixing time scale for k=pver) (1/s)
      real(r8) dactn,taunuc,damp
      real(r8) :: cldo_tmp, cldn_tmp
      real(r8) :: tau_cld_regenerate

      logical cldinterior

      integer ixndrop, l
      real(r8) naer_tot,naer(pcols)
      integer, parameter :: psat=6 ! number of supersaturations to calc ccn concentration
      real(r8)  :: supersat(psat)= & ! supersaturation (%) to determine ccn concentration
               (/0.02,0.05,0.1,0.2,0.5,1.0/)
      real(r8) ccn(pcols,pver,psat)        ! number conc of aerosols activated at supersat
      character(len=8), dimension(psat) :: ccn_name(psat)= &
               (/'CCN1','CCN2','CCN3','CCN4','CCN5','CCN6'/)
      real(r8) arg
      integer phase ! phase of aerosol



    arg = 1.0_r8
    if (abs(0.8427_r8-erf(arg))/0.8427_r8>0.001_r8) then
       write (iulog,*) 'erf(1.0) = ',ERF(arg)
#ifdef WRF_PORT
       call wrf_message(iulog)
#endif 
       call endrun('dropmixnuc: Error function error')
    endif
    arg = 0.0
    if (erf(arg) /= 0.0) then
       write (iulog,*) 'erf(0.0) = ',erf(arg)
#ifdef WRF_PORT
       call wrf_message(iulog)
#endif 
       write (iulog,*) 'dropmixnuc: Error function error'
#ifdef WRF_PORT
       call wrf_message(iulog)
#endif 
       call endrun('dropmixnuc: Error function error')
    endif
     zero=0._r8


       pi = 4._r8*atan(1.0_r8)
       dtinv=1./dtmicro
#ifndef WRF_PORT
       nstep = get_nstep()
#endif

!       call t_startf('load_aerosol')


       call cnst_get_ind('NUMLIQ', ixndrop)
       depvel(:,:) = 0.0_r8        ! droplet number is done in pkg_cld_sediment, aerosols in mz_aerosols_intr
!      depvel(:,ixndrop) =  0.1_r8 ! prescribed here rather than getting it from MIRAGE depvel_part

!    call t_stopf('load_aerosol')

       do m=1,ntot_amode
#ifndef WRF_PORT
          QQCW(numptrcw_amode(m))%fldcw => qqcw_get_field(numptrcw_amode(m),lchnk)
#else
          QQCW(numptrcw_amode(m))%fldcw => qqcw_inout(:,:,numptrcw_amode(m))
#endif
          do l=1,nspec_amode(m)
#ifndef WRF_PORT             
             QQCW(lmassptrcw_amode(l,m))%fldcw => qqcw_get_field(lmassptrcw_amode(l,m),lchnk)
#else
             QQCW(lmassptrcw_amode(l,m))%fldcw => qqcw_inout(:,:,lmassptrcw_amode(l,m))
#endif
          end do
       end do


!     start loop over columns
overall_main_i_loop: &
      do i=1,ncol

!        load number nucleated into qcld on cloud boundaries

! initialization for current i .........................................

!    call t_startf('calc_wtke')
         do k=1,pver-1
	    zs(k)=1._r8/(zm(i,k)-zm(i,k+1))
	 enddo
	 zs(pver)=zs(pver-1)

	 do k=1,pver
            qcld(k)=ncldwtr(i,k)
            qncld(k)=0._r8
            srcn(k)=0._r8
	    cs(i,k)=pmid(i,k)/(rair*temp(i,k)) ! air density (kg/m3)
	    dz(i,k)=1._r8/(cs(i,k)*gravit*rpdel(i,k)) ! layer thickness in m
	    w(i,k)=-1._r8*omega(i,k)/(cs(i,k)*gravit) ! large-scale vertical velocity m/s
            do m=1,ntot_amode
	       nact(k,m)=0._r8
	       mact(k,m)=0._r8
            enddo
            zn(k)=gravit*rpdel(i,k)
	    kvhmax=max(kvh(i,k),kvhmax)
	    if(k<pver)then
               ekd(k)=kvh(i,k+1)
               ekd(k)=max(ekd(k),zkmin)
               ekd(k)=min(ekd(k),zkmax)
               csbot(k)=2.0_r8*pint(i,k+1)/(rair*(temp(i,k)+temp(i,k+1)))
               csbot_cscen(k) = csbot(k)/cs(i,k)
	    else
               ekd(k)=0._r8
               csbot(k)=cs(i,k)
               csbot_cscen(k) = 1.0_r8
	    endif
!           diagnose subgrid vertical velocity from diffusivity
            if(k.eq.pver)then
               wtke(i,k)=sq2pi*depvel(i,ixndrop)
!               wtke(i,k)=sq2pi*kvh(i,k+1)
               wtke(i,k)=max(wtke(i,k),wmixmin)
            else
               wtke(i,k)=sq2pi*ekd(k)/dz(i,k)
            endif
! get sub-grid vertical velocity from diff coef.
! following morrison et al. 2005, JAS
! assume mixing length of 30 m
! rce-comment - define wtke at layer centers for new-cloud activation
!    and at layer boundaries for old-cloud activation

!++ag
!            wtke_cen(i,k)=0.5_r8*(kvh(i,k)+kvh(i,k+1))/30._r8
!            wtke(i,k)=kvh(i,k+1)/30._r8
            wtke_cen(i,k)=wsub(i,k)
            wtke(i,k)=wsub(i,k)
!--ag
            wtke_cen(i,k)=max(wtke_cen(i,k),wmixmin)
            wtke(i,k)=max(wtke(i,k),wmixmin)
            nsource(i,k)=0._r8
         enddo

            surfratemax = 0.0_r8
	    nsav=1
	    nnew=2
            surfrate(ixndrop)=depvel(i,ixndrop)/dz(i,pver)
            surfratemax = max( surfratemax, surfrate(ixndrop) )
            do m=1,ntot_amode
               lnum=numptr_amode(m)
               lnumcw=numptrcw_amode(m)
	       if(lnum>0)then
                  surfrate(lnum)=depvel(i,lnum)/dz(i,pver)
!                 surfrate(lnumcw)=surfrate(ixndrop)
                  surfrate_cw(lnumcw)=surfrate(ixndrop)
                  surfratemax = max( surfratemax, surfrate(lnum) )
!                 raercol(:,lnumcw,nsav)=raer(i,:,lnumcw)
                  raercol_cw(:,lnumcw,nsav)=qqcw(lnumcw)%fldcw(i,:)   ! use cloud-borne aerosol array
		  raercol(:,lnum,nsav)=raer(i,:,lnum)
	       endif
               do l=1,nspec_amode(m)
                  lmass=lmassptr_amode(l,m)
                  lmasscw=lmassptrcw_amode(l,m)
                  surfrate(lmass)=depvel(i,lmass)/dz(i,pver)
!                 surfrate(lmasscw)=surfrate(ixndrop)
                  surfrate_cw(lmasscw)=surfrate(ixndrop)
                  surfratemax = max( surfratemax, surfrate(lmass) )
!                 raercol(:,lmasscw,nsav)=raer(i,:,lmasscw)
                  raercol_cw(:,lmasscw,nsav)=qqcw(lmasscw)%fldcw(i,:)  ! use cloud-borne aerosol array
		  raercol(:,lmass,nsav)=raer(i,:,lmass)
               enddo
!              lwater=lwaterptr_amode(m)
!              surfrate(lwater)=depvel(i,lwater)/dz(i,pver)
!              surfratemax = max( surfratemax, surfrate(lwater) )
!              raercol(:,lwater,nsav)=raer(i,:,lwater)
            enddo
!    call t_stopf('calc_wtke')

!        droplet nucleation/aerosol activation

! tau_cld_regenerate = time scale for regeneration of cloudy air 
!    by (horizontal) exchange with clear air
            tau_cld_regenerate = 3600.0_r8 * 3.0_r8 

! k-loop for growing/shrinking cloud calcs .............................
grow_shrink_main_k_loop: &
         do k=1,pver
            km1=max0(k-1,1)
            kp1=min0(k+1,pver)

! shrinking cloud ......................................................
!    treat the reduction of cloud fraction from when cldn(i,k) < cldo(i,k)
!    and also dissipate the portion of the cloud that will be regenerated
              cldo_tmp = cldo(i,k)
              cldn_tmp = cldn(i,k) * exp( -dtmicro/tau_cld_regenerate )
!    alternate formulation
!             cldn_tmp = cldn(i,k) * max( 0.0_r8, (1.0_r8-dtmicro/tau_cld_regenerate) )

              if(cldn_tmp.lt.cldo_tmp)then
!                droplet loss in decaying cloud
!++ sungsup
		 nsource(i,k)=nsource(i,k)+qcld(k)*(cldn_tmp-cldo_tmp)/cldo_tmp*dtinv
                 qcld(k)=qcld(k)*(1.+(cldn_tmp-cldo_tmp)/cldo_tmp)
!-- sungsup

!                 convert activated aerosol to interstitial in decaying cloud

                  dumc=(cldn_tmp-cldo_tmp)/cldo_tmp
                  do m=1,ntot_amode
		     lnum=numptr_amode(m)
		     lnumcw=numptrcw_amode(m)
		     if(lnum.gt.0)then
		        dact=raercol_cw(k,lnumcw,nsav)*dumc
!                       raercol(k,lnumcw,nsav)=raercol(k,lnumcw,nsav)+dact
                        raercol_cw(k,lnumcw,nsav)=raercol_cw(k,lnumcw,nsav)+dact   ! cloud-borne aerosol
		        raercol(k,lnum,nsav)=raercol(k,lnum,nsav)-dact
		     endif
		     do l=1,nspec_amode(m)
		        lmass=lmassptr_amode(l,m)
			lmasscw=lmassptrcw_amode(l,m)
			dact=raercol_cw(k,lmasscw,nsav)*dumc
!                       raercol(k,lmasscw,nsav)=raercol(k,lmasscw,nsav)+dact
                        raercol_cw(k,lmasscw,nsav)=raercol_cw(k,lmasscw,nsav)+dact  ! cloud-borne aerosol
			raercol(k,lmass,nsav)=raercol(k,lmass,nsav)-dact
                     enddo
                  enddo
               endif

! growing cloud ......................................................
!    treat the increase of cloud fraction from when cldn(i,k) > cldo(i,k)
!    and also regenerate part of the cloud 
              cldo_tmp = cldn_tmp
              cldn_tmp = cldn(i,k)

              if(cldn_tmp-cldo_tmp.gt.0.01)then
!                wmix=wtke(i,k)
!                wbar=wtke(i,k)
! rce-comment - use wtke at layer centers for new-cloud activation
                 wbar=wtke_cen(i,k)
                 wmix=0._r8
                 wmin=0._r8
                 wmax=10._r8
                 wdiab=0
!                load aerosol properties, assuming external mixtures

                phase=1 ! interstitial
                 do m=1,ntot_amode
                    call loadaer(raer,qqcw,i,i,k,m,cs,npv(m),phase, &
                         na, va,  hy )
			 naermod(m)=na(i)
			 vaerosol(m)=va(i)
			 hygro(m)=hy(i)
                 end do
!		 m=1
!		 naermod(m)=1000.e6
!		 vaerosol(m)=naermod(m)/(density*num_to_mass_aer(m))

!                call t_startf ('activate')

                 call activate_modal(wbar,wmix,wdiab,wmin,wmax,temp(i,k),cs(i,k), &
                      naermod, ntot_amode,ntot_amode, vaerosol, sigmag,hygro,       &
                      fn,fm,fluxn,fluxm,flux_fullact(k))

!                call t_stopf ('activate')
!		 write(iulog,'(a,15f8.2)')'wtke,naer,fn=',wtke(i,k),naer_tot*1.e-6,(fn(m),m=1,ntot_amode)


                 dumc=(cldn_tmp-cldo_tmp)
                 do m=1,ntot_amode
                    lnum=numptr_amode(m)
                    lnumcw=numptrcw_amode(m)
		    dact=dumc*fn(m)*raer(i,k,lnum) ! interstitial only
                    qcld(k)=qcld(k)+dact
		    nsource(i,k)=nsource(i,k)+dact*dtinv
		    if(lnum.gt.0)then
                       raercol_cw(k,lnumcw,nsav)=raercol_cw(k,lnumcw,nsav)+dact  ! cloud-borne aerosol
		       raercol(k,lnum,nsav)=raercol(k,lnum,nsav)-dact
		    endif
                    dum=dumc*fm(m)
                    do l=1,nspec_amode(m)
		        lmass=lmassptr_amode(l,m)
			lmasscw=lmassptrcw_amode(l,m)
			dact=dum*(raer(i,k,lmass)) ! interstitial only
                        raercol_cw(k,lmasscw,nsav)=raercol_cw(k,lmasscw,nsav)+dact  ! cloud-borne aerosol
			raercol(k,lmass,nsav)=raercol(k,lmass,nsav)-dact
                    enddo
                 enddo
               endif

         enddo grow_shrink_main_k_loop
! end of k-loop for growing/shrinking cloud calcs ......................


! ......................................................................
! start of k-loop for calc of old cloud activation tendencies ..........
!
! rce-comment
!    changed this part of code to use current cloud fraction (cldn) exclusively
!    consider case of cldo(:)=0, cldn(k)=1, cldn(k+1)=0
!    previous code (which used cldo below here) would have no cloud-base activation
!       into layer k.  however, activated particles in k mix out to k+1,
!       so they are incorrectly depleted with no replacement
!
old_cloud_main_k_loop: &
         do k=1,pver
            km1=max0(k-1,1)
            kp1=min0(k+1,pver)
            taumix_internal_pver_inv = 0.0

            if(cldn(i,k).gt.0.01)then
! rce-comment
!             if(cldo(i,k).gt.0.01)then   ! with cldo changed to cldn this is redundant
               wdiab=0
!               wmix=wtke(i,k) ! spectrum of updrafts
!	       wbar=w(i,k) ! spectrum of updrafts
               wmix=0._r8 ! single updraft
	       wbar=wtke(i,k) ! single updraft
! rce-comment - different treatment for k=pver
	       if (k == pver) wbar=wtke_cen(i,k) ! single updraft
               wmax=10._r8
	       wmin=0._r8
!              old cloud
                  if(cldn(i,k)-cldn(i,kp1).gt.0.01.or.k.eq.pver)then

!                   cloud base
                    
                    ekd(k)=wtke(i,k)*dz(i,k)/sq2pi
! rce-comments
!   first, should probably have 1/zs(k) here rather than dz(i,k) because
!      the turbulent flux is proportional to ekd(k)*zs(k),
!      while the dz(i,k) is used to get flux divergences
!      and mixing ratio tendency/change
!   second and more importantly, using a single updraft velocity here
!      means having monodisperse turbulent updraft and downdrafts.
!      The sq2pi factor assumes a normal draft spectrum.
!      The fluxn/fluxm from activate must be consistent with the
!      fluxes calculated in explmix.
                    ekd(k)=wbar/zs(k)

                    alogarg=max(1.e-20_r8,1/cldn(i,k)-1._r8)
                    wmin=wbar+wmix*0.25*sq2pi*log(alogarg)
                    phase=1 ! interstitial
                    do m=1,ntot_amode
! rce-comment - use kp1 here as old-cloud activation involves 
!   aerosol from layer below
!                      call loadaer(raer,qqcw,i,i,k,m,cs, npv(m),phase, &
                       call loadaer(raer,qqcw,i,i,kp1,m,cs, npv(m),phase, &
                         na, va,  hy )
			 naermod(m)=na(i)
			 vaerosol(m)=va(i)
			 hygro(m)=hy(i)
                    end do
!		    m=1
!		    naermod(m)=1000.e6
!		    vaerosol(1,m)=naermod(m)/(density*num_to_mass_aer(m))
!                   call t_startf ('activate')

                    call activate_modal(wbar,wmix,wdiab,wmin,wmax,temp(i,k),cs(i,k), &
                      naermod, ntot_amode,ntot_amode, vaerosol, sigmag, hygro,    &
                      fn,fm,fluxn,fluxm,flux_fullact(k))

!                   call t_stopf ('activate')
!		    write(iulog,'(a,15f8.2)')'wtke,naer,fn=',wtke(i,k),naer_tot*1.e-6,(fn(m),m=1,ntot_amode)

                      if(k.lt.pver)then
                          dumc = cldn(i,k)-cldn(i,kp1)
                      else
                          dumc=cldn(i,k)
                      endif
                    fluxntot=0
! rce-comment 1
!    flux of activated mass into layer k (in kg/m2/s)
!       = "actmassflux" = dumc*fluxm*raercol(kp1,lmass)*csbot(k)
!    source of activated mass (in kg/kg/s) = flux divergence
!       = actmassflux/(cs(i,k)*dz(i,k))
!    so need factor of csbot_cscen = csbot(k)/cs(i,k)
!                   dum=1./(dz(i,k))
                    dum=csbot_cscen(k)/(dz(i,k))
! rce-comment 2
!    code for k=pver was changed to use the following conceptual model
!    in k=pver, there can be no cloud-base activation unless one considers
!       a scenario such as the layer being partially cloudy, 
!       with clear air at bottom and cloudy air at top
!    assume this scenario, and that the clear/cloudy portions mix with 
!       a timescale taumix_internal = dz(i,pver)/wtke_cen(i,pver)
!    in the absence of other sources/sinks, qact (the activated particle 
!       mixratio) attains a steady state value given by
!          qact_ss = fcloud*fact*qtot
!       where fcloud is cloud fraction, fact is activation fraction, 
!       qtot=qact+qint, qint is interstitial particle mixratio
!    the activation rate (from mixing within the layer) can now be
!       written as
!          d(qact)/dt = (qact_ss - qact)/taumix_internal
!                     = qtot*(fcloud*fact*wtke/dz) - qact*(wtke/dz)
!    note that (fcloud*fact*wtke/dz) is equal to the nact/mact
!    also, d(qact)/dt can be negative.  in the code below
!       it is forced to be >= 0
!
! steve -- 
!    you will likely want to change this.  i did not really understand 
!       what was previously being done in k=pver
!    in the cam3_5_3 code, wtke(i,pver) appears to be equal to the
!       droplet deposition velocity which is quite small
!    in the cam3_5_37 version, wtke is done differently and is much
!       larger in k=pver, so the activation is stronger there
!
                    if (k == pver) then
                       taumix_internal_pver_inv = flux_fullact(k)/dz(i,k)
                    end if
                    do m=1,ntot_amode
                       fluxn(m)=fluxn(m)*dumc
                       fluxm(m)=fluxm(m)*dumc
                       lnum=numptr_amode(m)
                       nact(k,m)=nact(k,m)+fluxn(m)*dum
                       mact(k,m)=mact(k,m)+fluxm(m)*dum
                       if (k > pver) then
! note that kp1 is used here
                          fluxntot = fluxntot &
                                   +fluxn(m)*raercol(kp1,lnum,nsav)*cs(i,k)
                       else
                          lnumcw=numptrcw_amode(m)
                          tmpa = raercol(kp1,lnum,nsav)*fluxn(m) &
                               + raercol(kp1,lnumcw,nsav)*(fluxn(m) &
                                    -taumix_internal_pver_inv)
                          fluxntot = fluxntot + max(0.0_r8,tmpa)*cs(i,k)
                       end if
                    enddo
                      srcn(k)=srcn(k)+fluxntot/(cs(i,k)*dz(i,k))
		      nsource(i,k)=nsource(i,k)+fluxntot/(cs(i,k)*dz(i,k))

                 endif  ! (cldn(i,k)-cldn(i,kp1).gt.0.01 .or. k.eq.pver)

! rce-comment
!             endif ! (cldo(i,k).gt.0.01)   ! with cldo changed to cldn this is redundant

            else
!              no cloud
               nsource(i,k)=nsource(i,k)-qcld(k)*dtinv
               qcld(k)=0
!              convert activated aerosol to interstitial in decaying cloud
               do m=1,ntot_amode
	          lnum=numptr_amode(m)
		  lnumcw=numptrcw_amode(m)
		  if(lnum.gt.0)then
                     raercol(k,lnum,nsav)=raercol(k,lnum,nsav)+raercol_cw(k,lnumcw,nsav)  ! cloud-borne aerosol
                     raercol_cw(k,lnumcw,nsav)=0.
		  endif
		  do l=1,nspec_amode(m)
		     lmass=lmassptr_amode(l,m)
		     lmasscw=lmassptrcw_amode(l,m)
                     raercol(k,lmass,nsav)=raercol(k,lmass,nsav)+raercol_cw(k,lmasscw,nsav) ! cloud-borne aerosol
                     raercol_cw(k,lmasscw,nsav)=0.
                  enddo
                enddo
            endif
         enddo old_cloud_main_k_loop
!           switch nsav, nnew so that nnew is the updated aerosol
 	    ntemp=nsav
 	    nsav=nnew
 	    nnew=ntemp
!          call t_startf ('nsubmix')

!        load new droplets in layers above, below clouds

         dtmin=dtmicro
         ekk(0)=0.0
         ekk(pver)=0.0
         do k=1,pver-1
! rce-comment -- ekd(k) is eddy-diffusivity at k/k+1 interface
!   want ekk(k) = ekd(k) * (density at k/k+1 interface)
!   so use pint(i,k+1) as pint is 1:pverp 
!           ekk(k)=ekd(k)*2.*pint(i,k)/(rair*(temp(i,k)+temp(i,k+1)))
!           ekk(k)=ekd(k)*2.*pint(i,k+1)/(rair*(temp(i,k)+temp(i,k+1)))
            ekk(k)=ekd(k)*csbot(k)
         enddo
         do k=1,pver
            km1=max0(k-1,1)
            ekkp(k)=zn(k)*ekk(k)*zs(k)
            ekkm(k)=zn(k)*ekk(k-1)*zs(km1)
            tinv=ekkp(k)+ekkm(k)

            if(k.eq.pver)tinv=tinv+surfratemax
! rce-comment -- tinv is the sum of all first-order-loss-rates
!    for the layer.  for most layers, the activation loss rate
!    (for interstitial particles) is accounted for by the loss by
!    turb-transfer to the layer above.
!    k=pver is special, and the loss rate for activation within 
!    the layer must be added to tinv.  if not, the time step
!    can be too big, and explmix can produce negative values.
!    the negative values are reset to zero, resulting in an 
!    artificial source.
            if(k.eq.pver)tinv=tinv+taumix_internal_pver_inv

            if(tinv.gt.1.e-6)then
               dtt=1./tinv
               dtmin=min(dtmin,dtt)
            endif
         enddo
         dtmix=0.9*dtmin
         nsubmix=dtmicro/dtmix+1
	 if(nsubmix>100)then
	    nsubmix_bnd=100
	 else
	    nsubmix_bnd=nsubmix
	 endif
	 count_submix(nsubmix_bnd)=count_submix(nsubmix_bnd)+1
         dtmix=dtmicro/nsubmix
         fac_srflx = -1.0/(zn(pver)*nsubmix)

	 do k=1,pver
            kp1=min(k+1,pver)
            km1=max(k-1,1)
	    ! maximum overlap assumption
            if(cldn(i,kp1).gt.1.e-10_r8)then
               overlapp(k)=min(cldn(i,k)/cldn(i,kp1),1._r8)
            else
               overlapp(k)=1.
            endif
            if(cldn(i,km1).gt.1.e-10_r8)then
               overlapm(k)=min(cldn(i,k)/cldn(i,km1),1._r8)
            else
               overlapm(k)=1.
            endif
	 enddo


! rce-comment
!    the activation source(k) = mact(k,m)*raercol(kp1,lmass)
!       should not exceed the rate of transfer of unactivated particles
!       from kp1 to k which = ekkp(k)*raercol(kp1,lmass)
!    however it might if things are not "just right" in subr activate
!    the following is a safety measure to avoid negatives in explmix
         do k = 1, pver-1
         do m = 1, ntot_amode
            nact(k,m) = min( nact(k,m), ekkp(k) )
            mact(k,m) = min( mact(k,m), ekkp(k) )
         end do
         end do


old_cloud_nsubmix_loop: &
         do n=1,nsubmix
            qncld(:)=qcld(:)
!           switch nsav, nnew so that nsav is the updated aerosol
	    ntemp=nsav
	    nsav=nnew
	    nnew=ntemp
            srcn(:)=0.0
            do m=1,ntot_amode
               lnum=numptr_amode(m)
               lnumcw=numptrcw_amode(m)
!              update droplet source
! rce-comment- activation source in layer k involves particles from k+1
!	       srcn(:)=srcn(:)+nact(:,m)*(raercol(:,lnum,nsav))
               srcn(1:pver-1)=srcn(1:pver-1)+nact(1:pver-1,m)*(raercol(2:pver,lnum,nsav))
! rce-comment- new formulation for k=pver
!              srcn(  pver  )=srcn(  pver  )+nact(  pver  ,m)*(raercol(  pver,lnum,nsav))
               tmpa = raercol(pver,lnum,nsav)*nact(pver,m) &
                    + raercol(pver,lnumcw,nsav)*(nact(pver,m) - taumix_internal_pver_inv)
               srcn(pver)=srcn(pver) + max(0.0_r8,tmpa)
            enddo
            call explmix(qcld,srcn,ekkp,ekkm,overlapp,overlapm,   &
                         qncld,surfrate(ixndrop),zero,pver,dtmix,.false.)

! rce-comment
!    the interstitial particle mixratio is different in clear/cloudy portions
!    of a layer, and generally higher in the clear portion.  (we have/had
!    a method for diagnosing the the clear/cloudy mixratios.)  the activation
!    source terms involve clear air (from below) moving into cloudy air (above).
!    in theory, the clear-portion mixratio should be used when calculating 
!    source terms
            do m=1,ntot_amode
               lnum=numptr_amode(m)
               lnumcw=numptrcw_amode(m)
               if(lnum>0)then
! rce-comment -   activation source in layer k involves particles from k+1
!	          source(:)= nact(:,m)*(raercol(:,lnum,nsav))
                  source(1:pver-1)= nact(1:pver-1,m)*(raercol(2:pver,lnum,nsav))
! rce-comment- new formulation for k=pver
!                 source(  pver  )= nact(  pver,  m)*(raercol(  pver,lnum,nsav))
                  tmpa = raercol(pver,lnum,nsav)*nact(pver,m) &
                       + raercol(pver,lnumcw,nsav)*(nact(pver,m) - taumix_internal_pver_inv)
                  source(pver) = max(0.0_r8,tmpa)
!                  flxconv=cflx(i,lnum)*zn(pver)
                  flxconv=0.
                  call explmix(raercol_cw(1,lnumcw,nnew),source,ekkp,ekkm,overlapp,overlapm, &
                               raercol_cw(1,lnumcw,nsav),surfrate_cw(lnumcw),zero,pver,dtmix,&
                               .false.)
                  call explmix(raercol(1,lnum,nnew),source,ekkp,ekkm,overlapp,overlapm,  &
                               raercol(1,lnum,nsav),surfrate(lnum),flxconv,pver,dtmix, &
                               .true.,raercol_cw(1,lnumcw,nsav))
               endif

               do l=1,nspec_amode(m)
                  lmass=lmassptr_amode(l,m)
                  lmasscw=lmassptrcw_amode(l,m)
! rce-comment -   activation source in layer k involves particles from k+1
!	          source(:)= mact(:,m)*(raercol(:,lmass,nsav))
                  source(1:pver-1)= mact(1:pver-1,m)*(raercol(2:pver,lmass,nsav))
! rce-comment- new formulation for k=pver
!                 source(  pver  )= mact(  pver  ,m)*(raercol(  pver,lmass,nsav))
                  tmpa = raercol(pver,lmass,nsav)*mact(pver,m) &
                       + raercol(pver,lmasscw,nsav)*(mact(pver,m) - taumix_internal_pver_inv)
                  source(pver) = max(0.0_r8,tmpa)
!                  flxconv=cflx(i,lmass)*zn(pver)
		  flxconv=0.

                  call explmix(raercol_cw(1,lmasscw,nnew),source,ekkp,ekkm,overlapp,overlapm, &
                               raercol_cw(1,lmasscw,nsav),surfrate_cw(lmasscw),zero,pver,dtmix,&
                               .false.)
                  call explmix(raercol(1,lmass,nnew),source,ekkp,ekkm,overlapp,overlapm,  &
                               raercol(1,lmass,nsav),surfrate(lmass),flxconv, pver,dtmix,&
                               .true.,raercol_cw(1,lmasscw,nsav))
	       enddo   ! l
!              lwater=lwaterptr_amode(m)  ! aerosol water
!              source(:)=0.
!              call explmix(   raercol(1,lwater,nnew),source,ekkp,ekkm,overlapp,overlapm,   &
!                              raercol(1,lwater,nsav),surfrate(lwater),zero,pver,dtmix,&
!                              .true.,source)
            enddo   ! m

         enddo old_cloud_nsubmix_loop
!          call t_stopf ('nsubmix')

!        evaporate particles again if no cloud

         do k=1,pver
	    if(cldn(i,k).eq.0.)then
!              no cloud
               qcld(k)=0.
!              convert activated aerosol to interstitial in decaying cloud
               do m=1,ntot_amode
	          lnum=numptr_amode(m)
		  lnumcw=numptrcw_amode(m)
		  if(lnum.gt.0)then
                        raercol(k,lnum,nnew)=raercol(k,lnum,nnew)+raercol_cw(k,lnumcw,nnew)
                        raercol_cw(k,lnumcw,nnew)=0.
		  endif
!
		  do l=1,nspec_amode(m)
		        lmass=lmassptr_amode(l,m)
			lmasscw=lmassptrcw_amode(l,m)
!                       raercol(k,lmass,nnew)=raercol(k,lmass,nnew)+raercol(k,lmasscw,nnew)
!                       raercol(k,lmasscw,nnew)=0.
                        raercol(k,lmass,nnew)=raercol(k,lmass,nnew)+raercol_cw(k,lmasscw,nnew)
                        raercol_cw(k,lmasscw,nnew)=0.
                  enddo
                enddo
            endif
         enddo

!        droplet number

         ndropcol(i)=0.
         do k=1,pver
	    ndropmix(i,k)=(qcld(k)-ncldwtr(i,k))*dtinv - nsource(i,k)
	    tendnd(i,k) = (max(qcld(k),1.e-6_r8)-ncldwtr(i,k))*dtinv
	    ndropcol(i) = ndropcol(i) + ncldwtr(i,k)*pdel(i,k)
	 enddo
	 ndropcol(i) = ndropcol(i)/gravit


!        aerosol tendency
         do m=1,ntot_amode
            lnum=numptr_amode(m)
            lnumcw=numptrcw_amode(m)
	    if(lnum.gt.0)then
               qqcwtend(i,:,lnumcw)=(raercol_cw(:,lnumcw,nnew)-qqcw(lnumcw)%fldcw(i,:))*dtinv
               qqcw(lnumcw)%fldcw(i,:)=raercol_cw(:,lnumcw,nnew)    ! update cloud-borne aerosol
	       raertend(i,:,lnum)= (raercol(:,lnum,nnew)-raer(i,:,lnum))*dtinv
	    endif
	    do l=1,nspec_amode(m)
	       lmass=lmassptr_amode(l,m)
	       lmasscw=lmassptrcw_amode(l,m)
               qqcwtend(i,:,lmasscw)=(raercol_cw(:,lmasscw,nnew)-qqcw(lmasscw)%fldcw(i,:))*dtinv
               qqcw(lmasscw)%fldcw(i,:)=raercol_cw(:,lmasscw,nnew)   ! update cloud-borne aerosol
	       raertend(i,:,lmass)=(raercol(:,lmass,nnew)-raer(i,:,lmass))*dtinv
            enddo
!           lwater=lwaterptr_amode(m)
!           raertend(i,:,lwater)=(raercol(:,lwater,nnew)-raer(i,:,lwater))*dtinv
         enddo

      enddo overall_main_i_loop
! end of main loop over i/longitude ....................................

      call outfld('NDROPCOL', ndropcol  , pcols, lchnk   )
      call outfld('NDROPSRC', nsource    , pcols, lchnk   )
      call outfld('NDROPMIX', ndropmix    , pcols, lchnk   )
      call outfld('LCLOUD  ', cldn    , pcols, lchnk   )
      call outfld('WTKE    ', wtke    , pcols, lchnk   )

      call ccncalc(lchnk,ncol,temp,cs,raer,qqcw,ccn,psat,supersat,alogsig,npv)
      do l=1,psat
         call outfld(ccn_name(l), ccn(1,1,l)    , pcols, lchnk   )
      enddo

! do column tendencies
      do m = 1, ntot_amode
      do lphase = 1, 2
      do lspec = 0, nspec_amode(m)+1   ! loop over number + chem constituents + water
         if (lspec == 0) then   ! number
            if (lphase == 1) then
               l = numptr_amode(m)
            else
               l = numptrcw_amode(m)
            endif
         else if (lspec <= nspec_amode(m)) then   ! non-water mass
            if (lphase == 1) then
               l = lmassptr_amode(lspec,m)
            else
               l = lmassptrcw_amode(lspec,m)
            endif
         else   ! water mass
!           if (lphase == 1) then
!              l = lwaterptr_amode(m)
!           else
               cycle
!           end if
         end if
         if (l <= 0) cycle

! mixnuc1 tendency for interstitial = (total tendency) - cflx
! mixnuc1 tendency for activated    = (total tendency)
         coltend(:) = 0.0
         if (lphase == 1) then
            tmpname = cnst_name(l)
            do i = 1, ncol
               coltend(i) = sum( pdel(i,:)*raertend(i,:,l) )/gravit
!               coltend(i) = coltend(i) - cflx(i,l)
            end do
         else
            tmpname = cnst_name_cw(l)
            do i = 1, ncol
               coltend(i) = sum( pdel(i,:)*qqcwtend(i,:,l) )/gravit
            end do
         end if
         fieldname = trim(tmpname) // '_mixnuc1'
         call outfld( fieldname, coltend, pcols, lchnk)

      end do   ! lspec
      end do   ! lphase
      end do   ! m

      return
      end subroutine dropmixnuc


   subroutine explmix( q, src, ekkp, ekkm, overlapp, overlapm, & 11
                       qold, surfrate, flxconv, pver, dt, is_unact, qactold )

!  explicit integration of droplet/aerosol mixing
!     with source due to activation/nucleation
      

   implicit none
   integer, intent(in) :: pver ! number of levels
   real(r8), intent(out) :: q(pver) ! mixing ratio to be updated
   real(r8), intent(in) :: qold(pver) ! mixing ratio from previous time step
   real(r8), intent(in) :: src(pver) ! source due to activation/nucleation (/s)
   real(r8), intent(in) :: ekkp(pver) ! zn*zs*density*diffusivity (kg/m3 m2/s) at interface
                      ! below layer k  (k,k+1 interface)
   real(r8), intent(in) :: ekkm(pver) ! zn*zs*density*diffusivity (kg/m3 m2/s) at interface
                      ! above layer k  (k,k+1 interface)
   real(r8), intent(in) :: overlapp(pver) ! cloud overlap below
   real(r8), intent(in) :: overlapm(pver) ! cloud overlap above
   real(r8), intent(in) :: surfrate ! surface exchange rate (/s)
   real(r8), intent(in) :: flxconv ! convergence of flux from surface
   real(r8), intent(in) :: dt ! time step (s)
   logical, intent(in) :: is_unact ! true if this is an unactivated species
   real(r8), intent(in),optional :: qactold(pver)
          ! mixing ratio of ACTIVATED species from previous step
          ! *** this should only be present
          !     if the current species is unactivated number/sfc/mass

   integer k,kp1,km1

   if ( is_unact ) then
!     the qactold*(1-overlap) terms are resuspension of activated material
      do k=1,pver
         kp1=min(k+1,pver)
         km1=max(k-1,1)
         q(k) = qold(k) + dt*( - src(k) + ekkp(k)*(qold(kp1) - qold(k) +       &
                           qactold(kp1)*(1.0-overlapp(k)))               &
                                  + ekkm(k)*(qold(km1) - qold(k) +     &
                           qactold(km1)*(1.0-overlapm(k))) )
!        force to non-negative
!        if(q(k)<-1.e-30)then
!           write(iulog,*)'q=',q(k),' in explmix'
            q(k)=max(q(k),0._r8)
!        endif
      end do
!     diffusion loss at base of lowest layer
      q(pver)=q(pver)-surfrate*qold(pver)*dt+flxconv*dt
!        force to non-negative
!        if(q(pver)<-1.e-30)then
!           write(iulog,*)'q=',q(pver),' in explmix'
            q(pver)=max(q(pver),0._r8)
!        endif
   else
      do k=1,pver
         kp1=min(k+1,pver)
         km1=max(k-1,1)
         q(k) = qold(k) + dt*(src(k) + ekkp(k)*(overlapp(k)*qold(kp1)-qold(k)) +      &
                                    ekkm(k)*(overlapm(k)*qold(km1)-qold(k)) )
!        force to non-negative
!        if(q(k)<-1.e-30)then
!           write(iulog,*)'q=',q(k),' in explmix'
            q(k)=max(q(k),0._r8)
!        endif
      end do
!     diffusion loss at base of lowest layer
      q(pver)=q(pver)-surfrate*qold(pver)*dt+flxconv*dt
!        force to non-negative
!        if(q(pver)<-1.e-30)then
!           write(iulog,*)'q=',q(pver),' in explmix'
            q(pver)=max(q(pver),0._r8)
!        endif
   end if

   return
   end subroutine explmix


   subroutine activate_init 3,16
#ifndef WRF_PORT
      use ppgrid,  only: pver
#else
      use module_cam_support, only: pver
#endif
#ifndef WRF_PORT
      use modal_aero_data
      use cam_history,   only: addfld, add_default, phys_decomp
#else
      use modal_aero_data, only:sigmag_amode => sigmag_amode_mp, &
           numptr_amode   => numptr_amode_mp, nspec_amode => nspec_amode_mp, &
           lmassptr_amode => lmassptr_amode_mp, dgnum_amode => dgnum_amode_mp
      use module_cam_support, only: addfld, add_default, phys_decomp
#endif
      use physconst, only: rhoh2o, mwh2o, r_universal
      use error_function, only: erf

      implicit none

      integer l,m
      real(r8) arg
      integer lnum, lmass

      character*16 ccn_longname

!      mathematical constants

      zero=0._r8
      third=1./3._r8
      twothird=2.*third
      sixth=1./6._r8
      sq2=sqrt(2._r8)
      pi=4._r8*atan(1.0_r8)
      sqpi=sqrt(pi)

      t0=273.
      surften=0.076_r8
      aten=2.*mwh2o*surften/(r_universal*t0*rhoh2o)
      alogaten=log(aten)
      alog2=log(2._r8)
      alog3=log(3._r8)

      do m=1,ntot_amode
!         use only if width of size distribution is prescribed
          alogsig(m)=log(sigmag_amode(m))
          exp45logsig(m)=exp(4.5*alogsig(m)*alogsig(m))
	  argfactor(m)=2./(3.*sqrt(2.)*alogsig(m))
          f1(m)=0.5*exp(2.5*alogsig(m)*alogsig(m))
	  f2(m)=1.+0.25*alogsig(m)
          lnum=numptr_amode(m)
          do l=1,nspec_amode(m)
               lmass=lmassptr_amode(l,m)
               if(lmass.le.0)then
                  write(iulog,*)'lmassptr_amode(',l,m,')=',lmass
#ifdef WRF_PORT
                  call wrf_message(iulog)
#endif 
                  call endrun
               endif
          enddo
          npv(m)=6./(pi*dgnum_amode(m)**3*exp45logsig(m))
      enddo
      
      call addfld ('WTKE     ', 'm/s     ', pver, 'A', 'Standard deviation of updraft velocity'                  ,phys_decomp)
      call addfld ('LCLOUD   ', '        ', pver, 'A', 'Liquid cloud fraction'                                   ,phys_decomp)
      call addfld ('NDROPMIX ', '#/kg/s  ', pver, 'A', 'Droplet number mixing'                     ,phys_decomp)
      call addfld ('NDROPSRC ', '#/kg/s  ', pver, 'A', 'Droplet number source'                     ,phys_decomp)
      call addfld ('NDROPSNK ', '#/kg/s  ', pver, 'A', 'Droplet number loss by microphysics'       ,phys_decomp)
      call addfld ('NDROPCOL ', '#/m2    ', 1,    'A', 'Column droplet number'                     ,phys_decomp)
      call add_default ('WTKE    ', 1, ' ')
      call add_default ('LCLOUD  ', 1, ' ')

      return
      end subroutine activate_init


      subroutine activate_modal(wbar, sigw, wdiab, wminf, wmaxf, tair, rhoair,  & 2,27
                          na, pmode, nmode, volume, sigman, hygro, &
                          fn, fm, fluxn, fluxm, flux_fullact )

!      calculates number, surface, and mass fraction of aerosols activated as CCN
!      calculates flux of cloud droplets, surface area, and aerosol mass into cloud
!      assumes an internal mixture within each of up to pmode multiple aerosol modes
!      a gaussiam spectrum of updrafts can be treated.

!      mks units

!      Abdul-Razzak and Ghan, A parameterization of aerosol activation.
!      2. Multiple aerosol types. J. Geophys. Res., 105, 6837-6844.

      use physconst, only: rair, epsilo, cpair, rh2o, latvap, gravit,   &
                                 rhoh2o, mwh2o, r_universal
      use wv_saturation, only: estblf, epsqs
      use error_function, only: erf

      implicit none


!      input

      integer pmode ! dimension of modes
      real(r8) wbar          ! grid cell mean vertical velocity (m/s)
      real(r8) sigw          ! subgrid standard deviation of vertical vel (m/s)
      real(r8) wdiab         ! diabatic vertical velocity (0 if adiabatic)
      real(r8) wminf         ! minimum updraft velocity for integration (m/s)
      real(r8) wmaxf         ! maximum updraft velocity for integration (m/s)
      real(r8) tair          ! air temperature (K)
      real(r8) rhoair        ! air density (kg/m3)
      real(r8) na(pmode)           ! aerosol number concentration (/m3)
      integer nmode      ! number of aerosol modes
      real(r8) volume(pmode)     ! aerosol volume concentration (m3/m3)
      real(r8) sigman(pmode)  ! geometric standard deviation of aerosol size distribution
      real(r8) hygro(pmode)  ! hygroscopicity of aerosol mode

!      output

      real(r8) fn(pmode)      ! number fraction of aerosols activated
      real(r8) fm(pmode)      ! mass fraction of aerosols activated
      real(r8) fluxn(pmode)   ! flux of activated aerosol number fraction into cloud (cm/s)
      real(r8) fluxm(pmode)   ! flux of activated aerosol mass fraction into cloud (cm/s)
      real(r8) flux_fullact   ! flux of activated aerosol fraction assuming 100% activation (cm/s)
                              !    rce-comment
                              !    used for consistency check -- this should match (ekd(k)*zs(k))
                              !    also, fluxm/flux_fullact gives fraction of aerosol mass flux
                              !       that is activated

!      local

      integer, parameter:: nx=200
      integer iquasisect_option, isectional
      real(r8) integ,integf
      real(r8), parameter :: p0 = 1013.25e2_r8    ! reference pressure (Pa)
      real(r8) xmin(ntot_amode),xmax(ntot_amode) ! ln(r) at section interfaces
      real(r8) volmin(ntot_amode),volmax(ntot_amode) ! volume at interfaces
      real(r8) tmass ! total aerosol mass concentration (g/cm3)
      real(r8) sign(ntot_amode)    ! geometric standard deviation of size distribution
      real(r8) rm ! number mode radius of aerosol at max supersat (cm)
      real(r8) pres ! pressure (Pa)
      real(r8) path ! mean free path (m)
      real(r8) diff ! diffusivity (m2/s)
      real(r8) conduct ! thermal conductivity (Joule/m/sec/deg)
      real(r8) diff0,conduct0
      real(r8) es ! saturation vapor pressure
      real(r8) qs ! water vapor saturation mixing ratio
      real(r8) dqsdt ! change in qs with temperature
      real(r8) dqsdp ! change in qs with pressure
      real(r8) g ! thermodynamic function (m2/s)
      real(r8) zeta(ntot_amode), eta(ntot_amode)
      real(r8) lnsmax ! ln(smax)
      real(r8) alpha
      real(r8) gamma
      real(r8) beta
      real(r8) sqrtg(ntot_amode)
      real(r8) :: amcube(ntot_amode) ! cube of dry mode radius (m)
      real(r8) :: smcrit(ntot_amode) ! critical supersatuation for activation
      real(r8) :: lnsm(ntot_amode) ! ln(smcrit)
      real(r8) smc(ntot_amode) ! critical supersaturation for number mode radius
      real(r8) sumflx_fullact
      real(r8) sumflxn(ntot_amode)
      real(r8) sumflxm(ntot_amode)
      real(r8) sumfn(ntot_amode)
      real(r8) sumfm(ntot_amode)
      real(r8) fnold(ntot_amode)   ! number fraction activated
      real(r8) fmold(ntot_amode)   ! mass fraction activated
      real(r8) wold,gold
      real(r8) alogam
      real(r8) rlo,rhi,xint1,xint2,xint3,xint4
      real(r8) wmin,wmax,w,dw,dwmax,dwmin,wnuc,dwnew,wb
      real(r8) dfmin,dfmax,fnew,fold,fnmin,fnbar,fsbar,fmbar
      real(r8) alw,sqrtalw
      real(r8) smax
      real(r8) x,arg
      real(r8) xmincoeff,xcut,volcut,surfcut
      real(r8) z,z1,z2,wf1,wf2,zf1,zf2,gf1,gf2,gf
      real(r8) etafactor1,etafactor2(ntot_amode),etafactor2max
      integer m,n
!      numerical integration parameters
      real(r8), parameter :: eps=0.3_r8,fmax=0.99_r8,sds=3._r8
 
      real(r8), parameter :: namin=1.e6_r8   ! minimum aerosol number concentration (/m3)

      integer ndist(nx)  ! accumulates frequency distribution of integration bins required
      data ndist/nx*0/
      save ndist

      if(ntot_amode<pmode)then
         write(iulog,*)'ntot_amode,pmode in activate =',ntot_amode,pmode
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif 
	 call endrun('activate')
      endif

      fn(:)=0._r8
      fm(:)=0._r8
      fluxn(:)=0._r8
      fluxm(:)=0._r8
      flux_fullact=0._r8

      if(nmode.eq.1.and.na(1).lt.1.e-20_r8)return

      if(sigw.le.1.e-5_r8.and.wbar.le.0.)return

      pres=rair*rhoair*tair
      diff0=0.211e-4_r8*(p0/pres)*(tair/t0)**1.94
      conduct0=(5.69_r8+0.017_r8*(tair-t0))*4.186e2_r8*1.e-5_r8 ! convert to J/m/s/deg
      es = estblf(tair)
      qs = epsilo*es/(pres-(1.0_r8 - epsqs)*es)
      dqsdt=latvap/(rh2o*tair*tair)*qs
      alpha=gravit*(latvap/(cpair*rh2o*tair*tair)-1./(rair*tair))
      gamma=(1+latvap/cpair*dqsdt)/(rhoair*qs)
      etafactor2max=1.e10/(alpha*wmaxf)**1.5 ! this should make eta big if na is very small.

      do m=1,nmode
         if(volume(m).gt.1.e-39_r8.and.na(m).gt.1.e-39_r8)then
!            number mode radius (m)
!           write(iulog,*)'alogsig,volc,na=',alogsig(m),volc(m),na(m)
            amcube(m)=(3.*volume(m)/(4.*pi*exp45logsig(m)*na(m)))  ! only if variable size dist
!           growth coefficent Abdul-Razzak & Ghan 1998 eqn 16
!           should depend on mean radius of mode to account for gas kinetic effects
!           see Fountoukis and Nenes, JGR2005 and Meskhidze et al., JGR2006
!           for approriate size to use for effective diffusivity.
            g=1._r8/(rhoh2o/(diff0*rhoair*qs)                                    &
              +latvap*rhoh2o/(conduct0*tair)*(latvap/(rh2o*tair)-1._r8))
            sqrtg(m)=sqrt(g)
            beta=2._r8*pi*rhoh2o*g*gamma
            etafactor2(m)=1._r8/(na(m)*beta*sqrtg(m))
            if(hygro(m).gt.1.e-10)then
               smc(m)=2.*aten*sqrt(aten/(27.*hygro(m)*amcube(m))) ! only if variable size dist
            else
               smc(m)=100.
            endif
!	    write(iulog,*)'sm,hygro,amcube=',smcrit(m),hygro(m),amcube(m)
         else
            g=1._r8/(rhoh2o/(diff0*rhoair*qs)                                    &
              +latvap*rhoh2o/(conduct0*tair)*(latvap/(rh2o*tair)-1._r8))
            sqrtg(m)=sqrt(g)
            smc(m)=1._r8
	    etafactor2(m)=etafactor2max ! this should make eta big if na is very small.
         endif
         lnsm(m)=log(smc(m)) ! only if variable size dist
!	 write(iulog,'(a,i4,4g12.2)')'m,na,amcube,hygro,sm,lnsm=', &
!                   m,na(m),amcube(m),hygro(m),sm(m),lnsm(m)
      enddo

      if(sigw.gt.1.e-5_r8)then ! spectrum of updrafts

         wmax=min(wmaxf,wbar+sds*sigw)
         wmin=max(wminf,-wdiab)
         wmin=max(wmin,wbar-sds*sigw)
         w=wmin
         dwmax=eps*sigw
         dw=dwmax
         dfmax=0.2_r8
         dfmin=0.1_r8
         if(wmax.le.w)then
            do m=1,nmode
               fluxn(m)=0.
               fn(m)=0.
               fluxm(m)=0.
               fm(m)=0.
            enddo
            flux_fullact=0._r8
            return
         endif
         do m=1,nmode
            sumflxn(m)=0._r8
            sumfn(m)=0._r8
	    fnold(m)=0._r8
            sumflxm(m)=0._r8
            sumfm(m)=0._r8
	    fmold(m)=0._r8
         enddo
         sumflx_fullact=0._r8

         fold=0._r8
         wold=0._r8
         gold=0._r8

         dwmin = min( dwmax, 0.01_r8 )

         do n=1,200
 100        wnuc=w+wdiab
!           write(iulog,*)'wnuc=',wnuc
            alw=alpha*wnuc
            sqrtalw=sqrt(alw)
	    etafactor1=alw*sqrtalw

              do m=1,nmode
	         eta(m)=etafactor1*etafactor2(m)
                 zeta(m)=twothird*sqrtalw*aten/sqrtg(m)
              enddo

              call maxsat(zeta,eta,nmode,smc,smax)
!	      write(iulog,*)'w,smax=',w,smax

              lnsmax=log(smax)

              x=twothird*(lnsm(nmode)-lnsmax)/(sq2*alogsig(nmode))
              fnew=0.5_r8*(1._r8-erf(x))


            dwnew = dw
            if(fnew-fold.gt.dfmax.and.n.gt.1)then
!              reduce updraft increment for greater accuracy in integration
	       if (dw .gt. 1.01*dwmin) then
                  dw=0.7_r8*dw
                  dw=max(dw,dwmin)
                  w=wold+dw
                  go to 100
               else
                  dwnew = dwmin
               endif
            endif

            if(fnew-fold.lt.dfmin)then
!              increase updraft increment to accelerate integration
	       dwnew=min(1.5_r8*dw,dwmax)
            endif
            fold=fnew

            z=(w-wbar)/(sigw*sq2)
            g=exp(-z*z)
            fnmin=1._r8
            xmincoeff=alogaten-twothird*(lnsmax-alog2)-alog3

            do m=1,nmode
!              modal
               x=twothird*(lnsm(m)-lnsmax)/(sq2*alogsig(m))
               fn(m)=0.5_r8*(1.-erf(x))
               fnmin=min(fn(m),fnmin)
!               integration is second order accurate
!               assumes linear variation of f*g with w
               fnbar=(fn(m)*g+fnold(m)*gold)
	       arg=x-1.5_r8*sq2*alogsig(m)
               fm(m)=0.5_r8*(1._r8-erf(arg))
               fmbar=(fm(m)*g+fmold(m)*gold)
               wb=(w+wold)
               if(w.gt.0.)then
                  sumflxn(m)=sumflxn(m)+sixth*(wb*fnbar           &
                      +(fn(m)*g*w+fnold(m)*gold*wold))*dw
                  sumflxm(m)=sumflxm(m)+sixth*(wb*fmbar           &
                      +(fm(m)*g*w+fmold(m)*gold*wold))*dw
               endif
               sumfn(m)=sumfn(m)+0.5_r8*fnbar*dw
!	       write(iulog,'(a,9g10.2)')'lnsmax,lnsm(m),x,fn(m),fnold(m),g,gold,fnbar,dw=',lnsmax,lnsm(m),x,fn(m),fnold(m),g,gold,fnbar,dw
               fnold(m)=fn(m)
               sumfm(m)=sumfm(m)+0.5_r8*fmbar*dw
               fmold(m)=fm(m)
            enddo
!           same form as sumflxm but replace the fm with 1.0
            sumflx_fullact = sumflx_fullact &
                           + sixth*(wb*(g+gold) + (g*w+gold*wold))*dw
!            sumg=sumg+0.5_r8*(g+gold)*dw
            gold=g
            wold=w
            dw=dwnew
            if(n.gt.1.and.(w.gt.wmax.or.fnmin.gt.fmax))go to 20
            w=w+dw
         enddo
         write(iulog,*)'do loop is too short in activate'
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif 
         write(iulog,*)'wmin=',wmin,' w=',w,' wmax=',wmax,' dw=',dw
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif 
         write(iulog,*)'wbar=',wbar,' sigw=',sigw,' wdiab=',wdiab
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif          
         write(iulog,*)'wnuc=',wnuc
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif 
         write(iulog,*)'na=',(na(m),m=1,nmode)
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif 
         write(iulog,*)'fn=',(fn(m),m=1,nmode)
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif 
!   dump all subr parameters to allow testing with standalone code
!   (build a driver that will read input and call activate)
         write(iulog,*)'wbar,sigw,wdiab,tair,rhoair,nmode='
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif 
         write(iulog,*) wbar,sigw,wdiab,tair,rhoair,nmode
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif
         write(iulog,*)'na=',na
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif
         write(iulog,*)'volume=', (volume(m),m=1,nmode)
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif
         write(iulog,*)'sigman=',sigman
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif
         write(iulog,*)'hydro='
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif
         write(iulog,*) hygro
#ifdef WRF_PORT
         call wrf_message(iulog)
#endif

         call endrun
   20    continue
         ndist(n)=ndist(n)+1
         if(w.lt.wmaxf)then

!            contribution from all updrafts stronger than wmax
!            assuming constant f (close to fmax)
            wnuc=w+wdiab

            z1=(w-wbar)/(sigw*sq2)
            z2=(wmaxf-wbar)/(sigw*sq2)
            g=exp(-z1*z1)
            integ=sigw*0.5*sq2*sqpi*(erf(z2)-erf(z1))
!            consider only upward flow into cloud base when estimating flux
            wf1=max(w,zero)
            zf1=(wf1-wbar)/(sigw*sq2)
            gf1=exp(-zf1*zf1)
            wf2=max(wmaxf,zero)
            zf2=(wf2-wbar)/(sigw*sq2)
            gf2=exp(-zf2*zf2)
            gf=(gf1-gf2)
            integf=wbar*sigw*0.5*sq2*sqpi*(erf(zf2)-erf(zf1))+sigw*sigw*gf

            do m=1,nmode
               sumflxn(m)=sumflxn(m)+integf*fn(m)
               sumfn(m)=sumfn(m)+fn(m)*integ
              sumflxm(m)=sumflxm(m)+integf*fm(m)
               sumfm(m)=sumfm(m)+fm(m)*integ
            enddo
!           same form as sumflxm but replace the fm with 1.0
            sumflx_fullact = sumflx_fullact + integf
!            sumg=sumg+integ
         endif


         do m=1,nmode
            fn(m)=sumfn(m)/(sq2*sqpi*sigw)
!            fn(m)=sumfn(m)/(sumg)
            if(fn(m).gt.1.01)then
               write(iulog,*)'fn=',fn(m),' > 1 in activate'
#ifdef WRF_PORT
               call wrf_message(iulog)
#endif
	       write(iulog,*)'w,m,na,amcube=',w,m,na(m),amcube(m)
#ifdef WRF_PORT
               call wrf_message(iulog)
#endif
	       write(iulog,*)'integ,sumfn,sigw=',integ,sumfn(m),sigw
#ifdef WRF_PORT
               call wrf_message(iulog)
#endif
	       call endrun('activate')
            endif
            fluxn(m)=sumflxn(m)/(sq2*sqpi*sigw)
           fm(m)=sumfm(m)/(sq2*sqpi*sigw)
!            fm(m)=sumfm(m)/(sumg)
            if(fm(m).gt.1.01)then
               write(iulog,*)'fm=',fm(m),' > 1 in activate'
#ifdef WRF_PORT
               call wrf_message(iulog)
#endif
            endif
            fluxm(m)=sumflxm(m)/(sq2*sqpi*sigw)
         enddo
!        same form as fluxm
         flux_fullact = sumflx_fullact/(sq2*sqpi*sigw)

      else

!        single updraft
         wnuc=wbar+wdiab

         if(wnuc.gt.0._r8)then

            w=wbar
            alw=alpha*wnuc
            sqrtalw=sqrt(alw)
	    etafactor1=alw*sqrtalw

            do m=1,nmode
	       eta(m)=etafactor1*etafactor2(m)
               zeta(m)=twothird*sqrtalw*aten/sqrtg(m)
            enddo

            call maxsat(zeta,eta,nmode,smc,smax)

            lnsmax=log(smax)
            xmincoeff=alogaten-twothird*(lnsmax-alog2)-alog3


            do m=1,nmode
!                 modal
		  x=twothird*(lnsm(m)-lnsmax)/(sq2*alogsig(m))
                  fn(m)=0.5_r8*(1._r8-erf(x))
		  arg=x-1.5_r8*sq2*alogsig(m)
                  fm(m)=0.5_r8*(1._r8-erf(arg))
                if(wbar.gt.0._r8)then
                   fluxn(m)=fn(m)*w
                   fluxm(m)=fm(m)*w
               endif
            enddo
            flux_fullact = w
         endif

      endif

      return
      end subroutine activate_modal


      subroutine maxsat(zeta,eta,nmode,smc,smax) 7

!      calculates maximum supersaturation for multiple
!      competing aerosol modes.

!      Abdul-Razzak and Ghan, A parameterization of aerosol activation.
!      2. Multiple aerosol types. J. Geophys. Res., 105, 6837-6844.

      implicit none

      integer nmode ! number of modes
      real(r8) smc(ntot_amode) ! critical supersaturation for number mode radius
      real(r8) zeta(ntot_amode), eta(ntot_amode)
      real(r8) smax ! maximum supersaturation
      integer m  ! mode index
      real(r8) sum, g1, g2, g1sqrt, g2sqrt

      do m=1,nmode
         if(zeta(m).gt.1.e5_r8*eta(m).or.smc(m)*smc(m).gt.1.e5_r8*eta(m))then
!            weak forcing. essentially none activated
            smax=1.e-20_r8
         else
!            significant activation of this mode. calc activation all modes.
            go to 1
         endif
      enddo

      return

  1   continue

      sum=0
      do m=1,nmode
         if(eta(m).gt.1.e-20_r8)then
            g1=zeta(m)/eta(m)
            g1sqrt=sqrt(g1)
            g1=g1sqrt*g1
            g1=g1sqrt*g1
            g2=smc(m)/sqrt(eta(m)+3._r8*zeta(m))
            g2sqrt=sqrt(g2)
            g2=g2sqrt*g2
            sum=sum+(f1(m)*g1+f2(m)*g2)/(smc(m)*smc(m))
         else
            sum=1.e20_r8
         endif
      enddo

      smax=1._r8/sqrt(sum)

      return

      end subroutine maxsat


      subroutine ccncalc(lchnk,ncol,tair,cs,raer,qqcw,ccn,psat,supersat,alogsig,npv) 1,8

!     calculates number concentration of aerosols activated as CCN at
!     supersaturation supersat.
!     assumes an internal mixture of a multiple externally-mixed aerosol modes
!     cgs units

!     Ghan et al., Atmos. Res., 1993, 198-221.

      use shr_kind_mod,  only: r8 => shr_kind_r8
#ifndef WRF_PORT
      use ppgrid,        only: pcols, pver, pverp
      use constituents,  only: pcnst
      use modal_aero_data
#else
      use module_cam_support, only: pcols, pver, pverp, pcnst =>pcnst_mp
#endif
      use physconst,     only: rhoh2o, mwh2o, r_universal
      use modal_aero_data, only:
      use error_function, only: erf

      implicit none

!     input

      integer lchnk ! chunk index
      integer, intent(in) :: ncol ! number of columns
      integer, intent(in) :: psat ! number of supesaturations
      real(r8), intent(in) :: raer(pcols,pver,pcnst) ! aerosol mass, number mixing ratios
      type(qqcw_type), intent(in) :: QQCW(:)


      real(r8), intent(in) :: tair(pcols,pver)          ! air temperature (K)
      real(r8), intent(in) :: cs(pcols,pver)    ! air density (kg/m3)
      real(r8), intent(in) :: supersat(psat)
      real(r8), intent(in) :: npv(ntot_amode) ! number per volume concentration
      real(r8), intent(in) :: alogsig(ntot_amode) ! natl log of geometric standard dev of aerosol
      real(r8), intent(out) :: ccn(pcols,pver,psat) ! number conc of aerosols activated at supersat (#/m3)

!     local

      real(r8) naerosol(pcols) ! interstit+activated aerosol number conc (/m3)
      real(r8) vaerosol(pcols) ! interstit+activated aerosol volume conc (m3/m3)
      real(r8) exp45logsig(ntot_amode)     ! exp(4.5*alogsig**2)
      real(r8) amcube(pcols)
      real(r8) super(psat) ! supersaturation
      real(r8) amcubecoef(ntot_amode)
      real(r8) :: surften       ! surface tension of water w/respect to air (N/m)
      real(r8) surften_coef
      real(r8) a(pcols) ! surface tension parameter
      real(r8) hygro(pcols)  ! aerosol hygroscopicity
      real(r8) sm(pcols)  ! critical supersaturation at mode radius
      real(r8) argfactor(ntot_amode),arg(pcols)
!     mathematical constants
      real(r8) pi
      real(r8) twothird,sq2
      integer l,m,n,i,k
      real(r8) log,cc
      real(r8) smcoefcoef,smcoef(pcols)
      integer phase ! phase of aerosol

      super(:)=supersat(:)*0.01
      pi = 4.*atan(1.0)
      sq2=sqrt(2._r8)
      twothird=2._r8/3._r8
      surften=0.076_r8
      surften_coef=2._r8*mwh2o*surften/(r_universal*rhoh2o)
      smcoefcoef=2._r8/sqrt(27._r8)

      do m=1,ntot_amode
          exp45logsig(m)=exp(4.5*alogsig(m)*alogsig(m))
	  amcubecoef(m)=3./(4.*pi*exp45logsig(m))
	  argfactor(m)=twothird/(sq2*alogsig(m))
      end do

      do k=1,pver

         do i=1,ncol
            ccn(i,k,:)=0.
            a(i)=surften_coef/tair(i,k)
	    smcoef(i)=smcoefcoef*a(i)*sqrt(a(i))
	 end do

         do m=1,ntot_amode
            phase=3 ! interstitial+cloudborne
            call loadaer(raer,qqcw,1,ncol,k,m,cs,npv(m), phase, &
                         naerosol, vaerosol,  hygro )
            where(naerosol(:ncol)>1.e-3)
               amcube(:ncol)=amcubecoef(m)*vaerosol(:ncol)/naerosol(:ncol)
	       sm(:ncol)=smcoef(:ncol)/sqrt(hygro(:ncol)*amcube(:ncol)) ! critical supersaturation
	    elsewhere
	       sm(:ncol)=1. ! value shouldn't matter much since naerosol is small
	    endwhere
            do l=1,psat
               do i=1,ncol
	          arg(i)=argfactor(m)*log(sm(i)/super(l))
                  ccn(i,k,l)=ccn(i,k,l)+naerosol(i)*0.5*(1._r8-erf(arg(i)))
               enddo
             enddo
         enddo
      enddo
      ccn(:ncol,:,:)=ccn(:ncol,:,:)*1.e-6 ! convert from #/m3 to #/cm3

      return
      end subroutine ccncalc


      subroutine loadaer(raer,qqcw,istart,istop,k,m,cs,npv1, phase, & 5,6
                         naerosol, vaerosol,  hygro )

      use shr_kind_mod,  only: r8 => shr_kind_r8
#ifndef WRF_PORT
      use abortutils,    only: endrun
      use ppgrid,        only: pcols, pver
      use modal_aero_data
#else
      use module_cam_support, only: pcols, pver, endrun, pcnst =>pcnst_mp
      use modal_aero_data,   only: nspec_amode => nspec_amode_mp, &
           lmassptr_amode    => lmassptr_amode_mp , lmassptrcw_amode  => lmassptrcw_amode_mp, &
           lspectype_amode   => lspectype_amode_mp, specdens_amode    => specdens_amode_mp,   &
           spechygro         => spechygro_mp      , numptr_amode      => numptr_amode_mp,     &
           numptrcw_amode    => numptrcw_amode_mp , voltonumbhi_amode => voltonumbhi_amode_mp,&
           voltonumblo_amode => voltonumblo_amode_mp 
#endif
     

      implicit none

      !      load aerosol number, volume concentrations, and bulk hygroscopicity

      type(qqcw_type), intent(in) :: QQCW(:)

      real(r8), intent(in) :: raer(pcols,pver,pcnst) ! aerosol mass, number mixing ratios
       integer, intent(in) :: istart, istop ! start, stop column index
       integer, intent(in) ::  m          ! m=mode index
       integer, intent(in) ::  k          ! level index
       real(r8), intent(in) :: cs(pcols,pver)  ! air density (kg/m3)
       integer, intent(in) :: phase ! phase of aerosol: 1 for interstitial, 2 for cloud-borne, 3 for sum
       real(r8), intent(in) :: npv1 ! number per volume
       real(r8), intent(out) :: naerosol(pcols)                ! interstitial number conc (/m3)
       real(r8), intent(out) :: vaerosol(pcols)       ! interstitial+activated volume conc (m3/m3)
       real(r8), intent(out) :: hygro(pcols) ! bulk hygroscopicity of mode

!      internal

       real(r8) vol(pcols) ! aerosol volume mixing ratio
       integer i,lnum,lnumcw,l,ltype,lmass,lmasscw

          do i=istart,istop
             vaerosol(i)=0._r8
	     hygro(i)=0._r8
	  end do

          do l=1,nspec_amode(m)
             lmass=lmassptr_amode(l,m) ! interstitial
             lmasscw=lmassptrcw_amode(l,m) ! cloud-borne
             ltype=lspectype_amode(l,m)
	     if(phase.eq.3)then
	        do i=istart,istop
!                  vol(i)=max(raer(i,k,lmass)+raer(i,k,lmasscw),0._r8)/specdens_amode(ltype)
                   vol(i)=max(raer(i,k,lmass)+qqcw(lmasscw)%fldcw(i,k),0._r8)/specdens_amode(ltype)
		end do
             elseif(phase.eq.2)then
                do i=istart,istop
                   vol(i)=max(qqcw(lmasscw)%fldcw(i,k),0._r8)/specdens_amode(ltype)
                end do
             elseif(phase.eq.1)then
                do i=istart,istop
                   vol(i)=max(raer(i,k,lmass),0._r8)/specdens_amode(ltype)
		end do
             else
	        write(iulog,*)'phase=',phase,' in loadaer'
#ifdef WRF_PORT
               call wrf_message(iulog)
#endif
	        call endrun('phase error in loadaer')
	     endif
	     do i=istart,istop
                vaerosol(i)=vaerosol(i)+vol(i)
                hygro(i)=hygro(i)+vol(i)*spechygro(ltype)
	     end do
          enddo
	  do i=istart,istop
             if (vaerosol(i) > 1.0e-30_r8) then   ! +++xl add 8/2/2007
               hygro(i)=hygro(i)/(vaerosol(i))
               vaerosol(i)=vaerosol(i)*cs(i,k)
             else
               hygro(i)=0.0_r8
               vaerosol(i)=0.0_r8
             endif
	  end do

          lnum=numptr_amode(m)
          lnumcw=numptrcw_amode(m)
          if(lnum.gt.0)then
!            aerosol number predicted
             if(phase.eq.3)then
	        do i=istart,istop
!                  naerosol(i)=(raer(i,k,lnum)+raer(i,k,lnumcw))*cs(i,k)
                   naerosol(i)=(raer(i,k,lnum)+qqcw(lnumcw)%fldcw(i,k))*cs(i,k)
		end do
             elseif(phase.eq.2)then
                do i=istart,istop
                   naerosol(i)=qqcw(lnumcw)%fldcw(i,k)*cs(i,k)
                end do
	     else
	        do i=istart,istop
                   naerosol(i)=raer(i,k,lnum)*cs(i,k)
		end do
	     endif
!            adjust number so that dgnumlo < dgnum < dgnumhi
	     do i=istart,istop
                naerosol(i) = max( naerosol(i), vaerosol(i)*voltonumbhi_amode(m) )
                naerosol(i) = min( naerosol(i), vaerosol(i)*voltonumblo_amode(m) )
	     end do
          else
!            aerosol number diagnosed from mass and prescribed size
	     do i=istart,istop
                naerosol(i)=vaerosol(i)*npv1
                naerosol(i)=max(naerosol(i),0._r8)
	     end do
          endif

       return
       end subroutine loadaer
#endif
      end module ndrop