LCOV - code coverage report
Current view: | top level - chemistry/aerosol - aerosol_state_mod.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 221 | 258 | 85.7 %
Date: | 2024-12-17 22:39:59 |  | Functions: | 10 | 13 | 76.9 %

              Line data    Source code
           1             : module aerosol_state_mod
           2             :   use shr_kind_mod, only: r8 => shr_kind_r8
           3             :   use aerosol_properties_mod, only: aerosol_properties, aero_name_len
           4             :   use physconst, only: pi
           5             :
           6             :   implicit none
           7             :
           8             :   private
           9             :
          10             :   public :: aerosol_state
          11             :   public :: ptr2d_t
          12             :
          13             :   !> aerosol_state defines the interface to the time-varying aerosol state
          14             :   !! variables (e.g., mixing ratios, number concentrations). This includes the
          15             :   !! aerosol portion of the overall model state.
          16             :   !!
          17             :   !! Each aerosol package (e.g., MAM, CARMA, etc) must extend the aerosol_state
          18             :   !! class to allow access to the state information (transported and not transported)
          19             :   !! of the aerosol package. Any package must implement each of the deferred
          20             :   !! procedures of the abstract aerosol_state class, may include additional private
          21             :   !! data members and type-bound procedures, and may override functions of the
          22             :   !! abstract class.
          23             :   !!
          24             :   !! Please see the modal_aerosol_state module for an example of how the aerosol_state
          25             :   !! class can be extended for a specific aerosol package.
          26             :   type, abstract :: aerosol_state
          27             :    contains
          28             :      procedure(aero_get_transported), deferred :: get_transported
          29             :      procedure(aero_set_transported), deferred :: set_transported
          30             :      procedure(aero_get_amb_total_bin_mmr), deferred :: ambient_total_bin_mmr
          31             :      procedure(aero_get_state_mmr), deferred :: get_ambient_mmr_0list
          32             :      procedure(aero_get_list_mmr), deferred :: get_ambient_mmr_rlist
          33             :      generic :: get_ambient_mmr=>get_ambient_mmr_0list,get_ambient_mmr_rlist
          34             :      procedure(aero_get_state_mmr), deferred :: get_cldbrne_mmr
          35             :      procedure(aero_get_state_num), deferred :: get_ambient_num
          36             :      procedure(aero_get_state_num), deferred :: get_cldbrne_num
          37             :      procedure(aero_get_states), deferred :: get_states
          38             :      procedure(aero_update_bin), deferred :: update_bin
          39             :      procedure :: loadaer
          40             :      procedure(aero_icenuc_size_wght_arr), deferred :: icenuc_size_wght_arr
          41             :      procedure(aero_icenuc_size_wght_val), deferred :: icenuc_size_wght_val
          42             :      generic :: icenuc_size_wght => icenuc_size_wght_arr,icenuc_size_wght_val
          43             :      procedure :: icenuc_type_wght_base
          44             :      procedure :: icenuc_type_wght => icenuc_type_wght_base
          45             :      procedure :: nuclice_get_numdens
          46             :      procedure :: get_amb_species_numdens
          47             :      procedure :: get_cld_species_numdens
          48             :      procedure :: coated_frac
          49             :      procedure :: mass_mean_radius
          50             :      procedure :: watact_mfactor
          51             :      procedure(aero_hetfrz_size_wght), deferred :: hetfrz_size_wght
          52             :      procedure(aero_hygroscopicity), deferred :: hygroscopicity
          53             :      procedure(aero_water_uptake), deferred :: water_uptake
          54             :      procedure :: refractive_index_sw
          55             :      procedure :: refractive_index_lw
          56             :      procedure(aero_volume), deferred :: dry_volume
          57             :      procedure(aero_volume), deferred :: wet_volume
          58             :      procedure(aero_volume), deferred :: water_volume
          59             :      procedure(aero_wet_diam), deferred :: wet_diameter
          60             :      procedure :: convcld_actfrac
          61             :      procedure :: sol_factb_interstitial
          62             :  end type aerosol_state
          63             :
          64             :   ! for state fields
          65             :   type ptr2d_t
          66             :      real(r8), pointer :: fld(:,:)
          67             :   end type ptr2d_t
          68             :
          69             :   real(r8), parameter :: per_cm3 = 1.e-6_r8 ! factor for m-3 to cm-3 conversions
          70             :   real(r8), parameter :: per_m3 = 1.e6_r8   ! factor for cm-3 to m-3 conversions
          71             :   real(r8), parameter :: kg2mug = 1.e9_r8   ! factor for kg to micrograms (mug) conversions
          72             :
          73             :   abstract interface
          74             :
          75             :      !------------------------------------------------------------------------
          76             :      ! Total aerosol mass mixing ratio for a bin in a given grid box location (column and layer)
          77             :      !------------------------------------------------------------------------
          78             :      function aero_get_amb_total_bin_mmr(self, aero_props, bin_ndx, col_ndx, lyr_ndx) result(mmr_tot)
          79             :        import :: aerosol_state, aerosol_properties, r8
          80             :        class(aerosol_state), intent(in) :: self
          81             :        class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
          82             :        integer, intent(in) :: bin_ndx      ! bin index
          83             :        integer, intent(in) :: col_ndx      ! column index
          84             :        integer, intent(in) :: lyr_ndx      ! vertical layer index
          85             :
          86             :        real(r8) :: mmr_tot                 ! mass mixing ratios totaled for all species
          87             :
          88             :      end function aero_get_amb_total_bin_mmr
          89             :
          90             :      !------------------------------------------------------------------------
          91             :      ! returns aerosol mass mixing ratio for a given species index and bin index
          92             :      !------------------------------------------------------------------------
          93             :      subroutine aero_get_state_mmr(self, species_ndx, bin_ndx, mmr)
          94             :        import :: aerosol_state, r8
          95             :        class(aerosol_state), intent(in) :: self
          96             :        integer, intent(in) :: species_ndx  ! species index
          97             :        integer, intent(in) :: bin_ndx      ! bin index
          98             :        real(r8), pointer :: mmr(:,:)       ! mass mixing ratios (ncol,nlev)
          99             :      end subroutine aero_get_state_mmr
         100             :
         101             :      !------------------------------------------------------------------------
         102             :      ! returns aerosol mass mixing ratio for a given species index, bin index
         103             :      ! and raditaion climate or diagnsotic list number
         104             :      !------------------------------------------------------------------------
         105             :      subroutine aero_get_list_mmr(self, list_ndx, species_ndx, bin_ndx, mmr)
         106             :        import :: aerosol_state, r8
         107             :        class(aerosol_state), intent(in) :: self
         108             :        integer, intent(in) :: list_ndx     ! rad climate/diagnostic list index
         109             :        integer, intent(in) :: species_ndx  ! species index
         110             :        integer, intent(in) :: bin_ndx      ! bin index
         111             :        real(r8), pointer :: mmr(:,:)       ! mass mixing ratios (ncol,nlev)
         112             :      end subroutine aero_get_list_mmr
         113             :
         114             :      !------------------------------------------------------------------------
         115             :      ! returns aerosol number mixing ratio for a given species index and bin index
         116             :      !------------------------------------------------------------------------
         117             :      subroutine aero_get_state_num(self, bin_ndx, num)
         118             :        import :: aerosol_state, r8
         119             :        class(aerosol_state), intent(in) :: self
         120             :        integer, intent(in) :: bin_ndx     ! bin index
         121             :        real(r8), pointer   :: num(:,:)    ! number densities (ncol,nlev)
         122             :      end subroutine aero_get_state_num
         123             :
         124             :      !------------------------------------------------------------------------
         125             :      ! returns interstitial and cloud-borne aerosol states
         126             :      !------------------------------------------------------------------------
         127             :      subroutine aero_get_states( self, aero_props, raer, qqcw )
         128             :        import :: aerosol_state, aerosol_properties, ptr2d_t
         129             :
         130             :        class(aerosol_state), intent(in) :: self
         131             :        class(aerosol_properties), intent(in) :: aero_props ! properties of the aerosol model
         132             :        type(ptr2d_t), intent(out) :: raer(:) ! state of interstitial aerosols
         133             :        type(ptr2d_t), intent(out) :: qqcw(:) ! state of cloud-borne aerosols
         134             :
         135             :      end subroutine aero_get_states
         136             :
         137             :      !------------------------------------------------------------------------------
         138             :      ! sets transported components
         139             :      ! This updates the aerosol model state from the host transported aerosol constituents array.
         140             :      ! (mass mixing ratios or number mixing ratios)
         141             :      !------------------------------------------------------------------------------
         142             :      subroutine aero_set_transported( self, transported_array )
         143             :        import :: aerosol_state, r8
         144             :        class(aerosol_state), intent(inout) :: self
         145             :        real(r8), intent(in) :: transported_array(:,:,:)
         146             :      end subroutine aero_set_transported
         147             :
         148             :      !------------------------------------------------------------------------------
         149             :      ! returns transported components
         150             :      ! This updates the transported aerosol constituent array to match the aerosol model state.
         151             :      ! (mass mixing ratios or number mixing ratios)
         152             :      !------------------------------------------------------------------------------
         153             :      subroutine aero_get_transported( self, transported_array )
         154             :        import :: aerosol_state, r8
         155             :        class(aerosol_state), intent(in) :: self
         156             :        real(r8), intent(out) :: transported_array(:,:,:)
         157             :      end subroutine aero_get_transported
         158             :
         159             :      !------------------------------------------------------------------------------
         160             :      ! return aerosol bin size weights for a given bin
         161             :      !------------------------------------------------------------------------------
         162             :      subroutine aero_icenuc_size_wght_arr(self, bin_ndx, ncol, nlev, species_type, use_preexisting_ice, wght)
         163             :        import :: aerosol_state, r8
         164             :        class(aerosol_state), intent(in) :: self
         165             :        integer, intent(in) :: bin_ndx             ! bin number
         166             :        integer, intent(in) :: ncol                ! number of columns
         167             :        integer, intent(in) :: nlev                ! number of vertical levels
         168             :        character(len=*), intent(in) :: species_type  ! species type
         169             :        logical, intent(in) :: use_preexisting_ice ! pre-existing ice flag
         170             :        real(r8), intent(out) :: wght(:,:)
         171             :
         172             :      end subroutine aero_icenuc_size_wght_arr
         173             :
         174             :      !------------------------------------------------------------------------------
         175             :      ! return aerosol bin size weights for a given bin, column and vertical layer
         176             :      !------------------------------------------------------------------------------
         177             :      subroutine aero_icenuc_size_wght_val(self, bin_ndx, col_ndx, lyr_ndx, species_type, use_preexisting_ice, wght)
         178             :        import :: aerosol_state, r8
         179             :        class(aerosol_state), intent(in) :: self
         180             :        integer, intent(in) :: bin_ndx                ! bin number
         181             :        integer, intent(in) :: col_ndx                ! column index
         182             :        integer, intent(in) :: lyr_ndx                ! vertical layer index
         183             :        character(len=*), intent(in) :: species_type  ! species type
         184             :        logical, intent(in) :: use_preexisting_ice    ! pre-existing ice flag
         185             :        real(r8), intent(out) :: wght
         186             :
         187             :      end subroutine aero_icenuc_size_wght_val
         188             :
         189             :      !------------------------------------------------------------------------------
         190             :      ! updates state and tendency
         191             :      !------------------------------------------------------------------------------
         192             :      subroutine aero_update_bin( self, bin_ndx, col_ndx, lyr_ndx, delmmr_sum, delnum_sum, tnd_ndx, dtime, tend )
         193             :        import :: aerosol_state, r8
         194             :        class(aerosol_state), intent(in) :: self
         195             :        integer, intent(in) :: bin_ndx                ! bin number
         196             :        integer, intent(in) :: col_ndx                ! column index
         197             :        integer, intent(in) :: lyr_ndx                ! vertical layer index
         198             :        real(r8),intent(in) :: delmmr_sum             ! mass mixing ratio change summed over all species in bin
         199             :        real(r8),intent(in) :: delnum_sum             ! number mixing ratio change summed over all species in bin
         200             :        integer, intent(in) :: tnd_ndx                ! tendency index
         201             :        real(r8),intent(in) :: dtime                  ! time step size (sec)
         202             :        real(r8),intent(inout) :: tend(:,:,:)         ! tendency
         203             :
         204             :      end subroutine aero_update_bin
         205             :
         206             :      !------------------------------------------------------------------------------
         207             :      ! returns the volume-weighted fractions of aerosol subset `bin_ndx` that can act
         208             :      ! as heterogeneous freezing nuclei
         209             :      !------------------------------------------------------------------------------
         210             :      function aero_hetfrz_size_wght(self, bin_ndx, ncol, nlev) result(wght)
         211             :        import :: aerosol_state, r8
         212             :        class(aerosol_state), intent(in) :: self
         213             :        integer, intent(in) :: bin_ndx             ! bin number
         214             :        integer, intent(in) :: ncol                ! number of columns
         215             :        integer, intent(in) :: nlev                ! number of vertical levels
         216             :
         217             :        real(r8) :: wght(ncol,nlev)
         218             :
         219             :      end function aero_hetfrz_size_wght
         220             :
         221             :      !------------------------------------------------------------------------------
         222             :      ! returns hygroscopicity for a given radiation diagnostic list number and
         223             :      ! bin number
         224             :      !------------------------------------------------------------------------------
         225             :      function aero_hygroscopicity(self, list_ndx, bin_ndx) result(kappa)
         226             :        import :: aerosol_state, r8
         227             :        class(aerosol_state), intent(in) :: self
         228             :        integer, intent(in) :: list_ndx     ! rad climate/diagnostic list index
         229             :        integer, intent(in) :: bin_ndx      ! bin number
         230             :
         231             :        real(r8), pointer :: kappa(:,:)     ! hygroscopicity (ncol,nlev)
         232             :
         233             :      end function aero_hygroscopicity
         234             :
         235             :      !------------------------------------------------------------------------------
         236             :      ! returns aerosol wet diameter and aerosol water concentration for a given
         237             :      ! radiation diagnostic list number and bin number
         238             :      !------------------------------------------------------------------------------
         239             :      subroutine aero_water_uptake(self, aero_props, list_idx, bin_idx, ncol, nlev, dgnumwet, qaerwat)
         240             :        import :: aerosol_state, aerosol_properties, r8
         241             :
         242             :        class(aerosol_state), intent(in) :: self
         243             :        class(aerosol_properties), intent(in) :: aero_props
         244             :        integer, intent(in) :: list_idx             ! rad climate/diags list number
         245             :        integer, intent(in) :: bin_idx              ! bin number
         246             :        integer, intent(in) :: ncol                 ! number of columns
         247             :        integer, intent(in) :: nlev                 ! number of levels
         248             :        real(r8),intent(out) :: dgnumwet(ncol,nlev) ! aerosol wet diameter (m)
         249             :        real(r8),intent(out) :: qaerwat(ncol,nlev)  ! aerosol water concentration (g/g)
         250             :
         251             :      end subroutine aero_water_uptake
         252             :
         253             :      !------------------------------------------------------------------------------
         254             :      ! aerosol volume interface
         255             :      !------------------------------------------------------------------------------
         256             :      function aero_volume(self, aero_props, list_idx, bin_idx, ncol, nlev) result(vol)
         257             :        import :: aerosol_state, aerosol_properties, r8
         258             :
         259             :        class(aerosol_state), intent(in) :: self
         260             :        class(aerosol_properties), intent(in) :: aero_props
         261             :        integer, intent(in) :: list_idx  ! rad climate/diags list number
         262             :        integer, intent(in) :: bin_idx   ! bin number
         263             :        integer, intent(in) :: ncol      ! number of columns
         264             :        integer, intent(in) :: nlev      ! number of levels
         265             :
         266             :        real(r8) :: vol(ncol,nlev)       ! m3/kg
         267             :
         268             :      end function aero_volume
         269             :
         270             :      !------------------------------------------------------------------------------
         271             :      ! aerosol wet diameter
         272             :      !------------------------------------------------------------------------------
         273             :      function aero_wet_diam(self, bin_idx, ncol, nlev) result(diam)
         274             :        import :: aerosol_state,  r8
         275             :
         276             :        class(aerosol_state), intent(in) :: self
         277             :        integer, intent(in) :: bin_idx   ! bin number
         278             :        integer, intent(in) :: ncol      ! number of columns
         279             :        integer, intent(in) :: nlev      ! number of levels
         280             :
         281             :        real(r8) :: diam(ncol,nlev)
         282             :
         283             :      end function aero_wet_diam
         284             :
         285             :   end interface
         286             :
         287             : contains
         288             :
         289             :   !------------------------------------------------------------------------------
         290             :   ! returns aerosol number, volume concentrations, and bulk hygroscopicity
         291             :   !------------------------------------------------------------------------------
         292  8833072308 :   subroutine loadaer( self, aero_props, istart, istop, k,  m, cs, phase, &
         293  2944357436 :                        naerosol, vaerosol, hygro, errnum, errstr, pom_hygro)
         294             :
         295             :     use aerosol_properties_mod, only: aerosol_properties
         296             :
         297             :     ! input arguments
         298             :     class(aerosol_state), intent(in) :: self
         299             :     class(aerosol_properties), intent(in) :: aero_props
         300             :
         301             :     integer,  intent(in) :: istart      ! start column index (1 <= istart <= istop <= pcols)
         302             :     integer,  intent(in) :: istop       ! stop column index
         303             :     integer,  intent(in) :: k           ! level index
         304             :     integer,  intent(in) :: m           ! mode or bin index
         305             :     real(r8), intent(in) :: cs(:,:)     ! air density (kg/m3)
         306             :     integer,  intent(in) :: phase       ! phase of aerosol: 1 for interstitial, 2 for cloud-borne, 3 for sum
         307             :
         308             :     ! output arguments
         309             :     real(r8), intent(out) :: naerosol(:)  ! number conc (1/m3)
         310             :     real(r8), intent(out) :: vaerosol(:)  ! volume conc (m3/m3)
         311             :     real(r8), intent(out) :: hygro(:)     ! bulk hygroscopicity of mode
         312             :
         313             :     integer ,         intent(out) :: errnum
         314             :     character(len=*), intent(out) :: errstr
         315             :
         316             :     real(r8), optional, intent(in) :: pom_hygro     ! POM hygroscopicity override
         317             :
         318             :     ! internal
         319  2944357436 :     real(r8), pointer :: raer(:,:) ! interstitial aerosol mass, number mixing ratios
         320  2944357436 :     real(r8), pointer :: qqcw(:,:) ! cloud-borne aerosol mass, number mixing ratios
         321             :     real(r8) :: specdens, spechygro
         322             :     character(len=aero_name_len) :: spectype
         323             :
         324  2944357436 :     real(r8) :: vol(istart:istop) ! aerosol volume mixing ratio
         325             :     integer  :: i, l
         326             :     !-------------------------------------------------------------------------------
         327  2944357436 :     errnum = 0
         328             :
         329 27951238264 :     do i = istart, istop
         330 25006880828 :        vaerosol(i) = 0._r8
         331 27951238264 :        hygro(i)    = 0._r8
         332             :     end do
         333             :
         334 13985697821 :     do l = 1, aero_props%nspecies(m)
         335             :
         336 11041340385 :        call self%get_ambient_mmr(l,m, raer)
         337 11041340385 :        call self%get_cldbrne_mmr(l,m, qqcw)
         338 11041340385 :        call aero_props%get(m,l, density=specdens, hygro=spechygro, spectype=spectype)
         339 11041340385 :        if (present(pom_hygro)) then
         340           0 :           if (spectype=='p-organic'.and.pom_hygro>0._r8) then
         341           0 :              spechygro=pom_hygro
         342             :           endif
         343             :        endif
         344             :
         345 11041340385 :        if (phase == 3) then
         346 93992633280 :           do i = istart, istop
         347 93992633280 :              vol(i) = max(raer(i,k) + qqcw(i,k), 0._r8)/specdens
         348             :           end do
         349  5412255105 :        else if (phase == 2) then
         350           0 :           do i = istart, istop
         351           0 :              vol(i) = max(qqcw(i,k), 0._r8)/specdens
         352             :           end do
         353  5412255105 :        else if (phase == 1) then
         354 10824510210 :           do i = istart, istop
         355 10824510210 :              vol(i) = max(raer(i,k), 0._r8)/specdens
         356             :           end do
         357             :        else
         358           0 :           errnum = -1
         359           0 :           write(errstr,*)'phase = ',phase,' in aerosol_state::loadaer not recognized'
         360             :           return
         361             :        end if
         362             :
         363 >11880*10^7 :        do i = istart, istop
         364 93775803105 :           vaerosol(i) = vaerosol(i) + vol(i)
         365 >10481*10^7 :           hygro(i)    = hygro(i) + vol(i)*spechygro
         366             :        end do
         367             :
         368             :     end do
         369             :
         370 27951238264 :     do i = istart, istop
         371 27951238264 :        if (vaerosol(i) > 1.0e-30_r8) then
         372 25006878161 :           hygro(i)    = hygro(i)/(vaerosol(i))
         373 25006878161 :           vaerosol(i) = vaerosol(i)*cs(i,k)
         374             :        else
         375        2667 :           hygro(i)    = 0.0_r8
         376        2667 :           vaerosol(i) = 0.0_r8
         377             :        end if
         378             :     end do
         379             :
         380             :     ! aerosol number mixing ratios (#/kg)
         381  2944357436 :     call self%get_ambient_num(m, raer)
         382  2944357436 :     call self%get_cldbrne_num(m, qqcw)
         383  2944357436 :     if (phase == 3) then
         384 25064702208 :        do i = istart, istop
         385 25064702208 :           naerosol(i) = (raer(i,k) + qqcw(i,k))*cs(i,k) ! #/kg -> #/m3
         386             :        end do
         387  1443268028 :     else if (phase == 2) then
         388           0 :        do i = istart, istop
         389           0 :           naerosol(i) = qqcw(i,k)*cs(i,k)
         390             :        end do
         391             :     else
         392  2886536056 :        do i = istart, istop
         393  2886536056 :           naerosol(i) = raer(i,k)*cs(i,k)
         394             :        end do
         395             :     end if
         396             :
         397             :     ! adjust number
         398  2944357436 :     call aero_props%apply_number_limits( naerosol, vaerosol, istart, istop, m )
         399             :
         400  2944357436 :   end subroutine loadaer
         401             :
         402             :   !------------------------------------------------------------------------------
         403             :   ! returns ambient aerosol number density for a given bin number and species type
         404             :   !------------------------------------------------------------------------------
         405    53610336 :   subroutine get_amb_species_numdens(self, bin_ndx, ncol, nlev, species_type, aero_props, rho, numdens)
         406             :     use aerosol_properties_mod, only: aerosol_properties
         407             :     class(aerosol_state), intent(in) :: self
         408             :     integer, intent(in) :: bin_ndx                ! bin number
         409             :     integer, intent(in) :: ncol                   ! number of columns
         410             :     integer, intent(in) :: nlev                   ! number of vertical levels
         411             :     character(len=*), intent(in) :: species_type  ! species type
         412             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         413             :     real(r8), intent(in) :: rho(:,:)              ! air density (kg m-3)
         414             :     real(r8), intent(out) :: numdens(:,:)         ! species number densities (#/cm^3)
         415             :
         416    53610336 :     real(r8), pointer :: num(:,:)
         417   107220672 :     real(r8) :: type_wght(ncol,nlev)
         418   107220672 :     real(r8) :: size_wght(ncol,nlev)
         419             :
         420 83304228384 :     size_wght = self%hetfrz_size_wght(bin_ndx, ncol, nlev)
         421             :
         422    53610336 :     call self%icenuc_type_wght_base(bin_ndx, ncol, nlev, species_type, aero_props, rho, type_wght)
         423             :
         424    53610336 :     call self%get_ambient_num(bin_ndx, num)
         425             :
         426 83304228384 :     numdens(:ncol,:) = num(:ncol,:)*rho(:ncol,:)*type_wght(:ncol,:)*size_wght(:ncol,:)*per_cm3
         427             :
         428    53610336 :   end subroutine get_amb_species_numdens
         429             :
         430             :   !------------------------------------------------------------------------------
         431             :   ! returns cloud-borne aerosol number density for a given bin number and species type
         432             :   !------------------------------------------------------------------------------
         433    17870112 :   subroutine get_cld_species_numdens(self, bin_ndx, ncol, nlev, species_type, aero_props, rho, numdens)
         434             :     use aerosol_properties_mod, only: aerosol_properties
         435             :     class(aerosol_state), intent(in) :: self
         436             :     integer, intent(in) :: bin_ndx                ! bin number
         437             :     integer, intent(in) :: ncol                   ! number of columns
         438             :     integer, intent(in) :: nlev                   ! number of vertical levels
         439             :     character(len=*), intent(in) :: species_type  ! species type
         440             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         441             :     real(r8), intent(in) :: rho(:,:)              ! air density (kg m-3)
         442             :     real(r8), intent(out) :: numdens(:,:)         ! number densities (#/cm^3)
         443             :
         444    17870112 :     real(r8), pointer :: num(:,:)
         445    35740224 :     real(r8) :: type_wght(ncol,nlev)
         446    35740224 :     real(r8) :: size_wght(ncol,nlev)
         447             :
         448 27768076128 :     size_wght = self%hetfrz_size_wght(bin_ndx, ncol, nlev)
         449             :
         450    17870112 :     call self%icenuc_type_wght_base(bin_ndx, ncol, nlev, species_type, aero_props, rho, type_wght, cloud_borne=.true.)
         451             :
         452    17870112 :     call self%get_cldbrne_num(bin_ndx, num)
         453             :
         454 27768076128 :     numdens(:ncol,:) = num(:ncol,:)*rho(:ncol,:)*type_wght(:ncol,:)*size_wght(:ncol,:)*per_cm3
         455             :
         456    17870112 :   end subroutine get_cld_species_numdens
         457             :
         458             :   !------------------------------------------------------------------------------
         459             :   ! returns aerosol type weights for a given aerosol type and bin
         460             :   !------------------------------------------------------------------------------
         461    89350560 :   subroutine icenuc_type_wght_base(self, bin_ndx, ncol, nlev, species_type, aero_props, rho, wght, cloud_borne)
         462             :
         463             :     use aerosol_properties_mod, only: aerosol_properties
         464             :
         465             :     class(aerosol_state), intent(in) :: self
         466             :     integer, intent(in) :: bin_ndx                ! bin number
         467             :     integer, intent(in) :: ncol                   ! number of columns
         468             :     integer, intent(in) :: nlev                   ! number of vertical levels
         469             :     character(len=*), intent(in) :: species_type  ! species type
         470             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         471             :     real(r8), intent(in) :: rho(:,:)              ! air density (kg m-3)
         472             :     real(r8), intent(out) :: wght(:,:)            ! type weights
         473             :     logical, optional, intent(in) :: cloud_borne  ! if TRUE cloud-borne aerosols are used
         474             :                                                   ! otherwise ambient aerosols are used
         475             :
         476   178701120 :     real(r8) :: mass(ncol,nlev)
         477   178701120 :     real(r8) :: totalmass(ncol,nlev)
         478    89350560 :     real(r8), pointer :: aer_bin(:,:)
         479             :
         480             :     character(len=aero_name_len) :: spectype, sptype
         481             :     integer :: ispc
         482             :     logical :: cldbrne
         483             :
         484    89350560 :     if (present(cloud_borne)) then
         485    17870112 :        cldbrne = cloud_borne
         486             :     else
         487             :        cldbrne = .false.
         488             :     end if
         489             :
         490 >13884*10^7 :     wght(:,:) = 0._r8
         491 >13884*10^7 :     totalmass(:,:) = 0._r8
         492 >13884*10^7 :     mass(:,:)   = 0._r8
         493             :
         494    89350560 :     if (species_type=='sulfate_strat') then
         495     4467528 :        sptype = 'sulfate'
         496             :     else
         497    84883032 :        sptype = species_type
         498             :     end if
         499             :
         500   464622912 :     do ispc = 1, aero_props%nspecies(bin_ndx)
         501             :
         502   375272352 :        if (cldbrne) then
         503    75947976 :           call self%get_cldbrne_mmr(ispc, bin_ndx, aer_bin)
         504             :        else
         505   299324376 :           call self%get_ambient_mmr(ispc, bin_ndx, aer_bin)
         506             :        end if
         507   375272352 :        call aero_props%species_type(bin_ndx, ispc, spectype=spectype)
         508             :
         509 >58312*10^7 :        totalmass(:ncol,:) = totalmass(:ncol,:) + aer_bin(:ncol,:)*rho(:ncol,:)
         510             :
         511   464622912 :        if (trim(spectype) == trim(sptype)) then
         512 >13884*10^7 :           mass(:ncol,:) = mass(:ncol,:) + aer_bin(:ncol,:)*rho(:ncol,:)
         513             :        end if
         514             :
         515             :     end do
         516             :
         517 >13884*10^7 :     where (totalmass(:ncol,:) > 0._r8)
         518    89350560 :        wght(:ncol,:) = mass(:ncol,:)/totalmass(:ncol,:)
         519             :     end where
         520             :
         521   178701120 :   end subroutine icenuc_type_wght_base
         522             :
         523             :   !------------------------------------------------------------------------------
         524     4467528 :   subroutine nuclice_get_numdens(self, aero_props, use_preexisting_ice, ncol, nlev, rho, dust_num_col, sulf_num_col, soot_num_col, sulf_num_tot_col )
         525             :
         526             :     class(aerosol_state), intent(in) :: self
         527             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         528             :
         529             :     logical, intent(in) :: use_preexisting_ice
         530             :     integer, intent(in) :: ncol                   ! number of columns
         531             :     integer, intent(in) :: nlev                   ! number of vertical levels
         532             :     real(r8), intent(in) :: rho(:,:) ! air density (kg m-3)
         533             :     real(r8), intent(out) :: dust_num_col(:,:) ! dust number densities (#/cm^3)
         534             :     real(r8), intent(out) :: sulf_num_col(:,:) ! sulfate number densities (#/cm^3)
         535             :     real(r8), intent(out) :: soot_num_col(:,:) ! soot number densities (#/cm^3)
         536             :     real(r8), intent(out) :: sulf_num_tot_col(:,:) ! stratopsheric sulfate number densities (#/cm^3)
         537             :
         538             :     integer :: ibin,ispc
         539             :     character(len=aero_name_len) :: spectype
         540     8935056 :     real(r8) :: size_wghts(ncol,nlev)
         541     8935056 :     real(r8) :: type_wghts(ncol,nlev)
         542             :
         543     4467528 :     real(r8), pointer :: num_col(:,:)
         544             :
         545  7067629296 :     dust_num_col(:,:) = 0._r8
         546  7067629296 :     sulf_num_col(:,:) = 0._r8
         547  7067629296 :     soot_num_col(:,:) = 0._r8
         548  7067629296 :     sulf_num_tot_col(:,:) = 0._r8
         549             :
         550             :     ! collect number densities (#/cm^3) for dust, sulfate, and soot
         551    22337640 :     do ibin = 1,aero_props%nbins()
         552             :
         553    17870112 :        call self%get_ambient_num(ibin, num_col)
         554             :
         555    84883032 :        do ispc = 1,aero_props%nspecies(ibin)
         556             :
         557    67012920 :           call aero_props%species_type(ibin, ispc, spectype)
         558             :
         559    67012920 :           call self%icenuc_size_wght(ibin, ncol, nlev, spectype, use_preexisting_ice, size_wghts)
         560             :
         561    67012920 :           call self%icenuc_type_wght(ibin, ncol, nlev, spectype, aero_props, rho, type_wghts)
         562             :
         563   151895952 :           select case ( trim(spectype) )
         564             :           case('dust')
         565    13402584 :              dust_num_col(:ncol,:) = dust_num_col(:ncol,:) &
         566 20839459680 :                   + size_wghts(:ncol,:)*type_wghts(:ncol,:)*num_col(:ncol,:)*rho(:ncol,:)*per_cm3
         567             :           case('sulfate')
         568             :              ! This order of ops gives bit-for-bit results for cam5 phys ( use_preexisting_ice = .false. )
         569    13402584 :              sulf_num_col(:ncol,:) = sulf_num_col(:ncol,:) &
         570 20839459680 :                   + num_col(:ncol,:)*rho(:ncol,:)*per_cm3  * size_wghts(:ncol,:)*type_wghts(:ncol,:)
         571             :           case('black-c')
         572     8935056 :              soot_num_col(:ncol,:) = soot_num_col(:ncol,:) &
         573 14018063904 :                   + size_wghts(:ncol,:)*type_wghts(:ncol,:)*num_col(:ncol,:)*rho(:ncol,:)*per_cm3
         574             :           end select
         575             :
         576             :        enddo
         577             :
         578             :        ! stratospheric sulfates -- special case not included in the species loop above
         579    17870112 :        call self%icenuc_size_wght(ibin, ncol, nlev, 'sulfate_strat', use_preexisting_ice, size_wghts)
         580    17870112 :        call self%icenuc_type_wght(ibin, ncol, nlev, 'sulfate_strat', aero_props, rho, type_wghts)
         581    17870112 :        sulf_num_tot_col(:ncol,:) = sulf_num_tot_col(:ncol,:) &
         582 27790413768 :             + size_wghts(:ncol,:)*type_wghts(:ncol,:)*num_col(:ncol,:)*rho(:ncol,:)*per_cm3
         583             :
         584             :     enddo
         585             :
         586     4467528 :   end subroutine nuclice_get_numdens
         587             :
         588             :   !------------------------------------------------------------------------------
         589             :   ! returns the fraction of particle surface area of aerosol subset `bin_ndx` covered
         590             :   ! by at least a monolayer of species `species_type` [0-1]
         591             :   !------------------------------------------------------------------------------
         592    17870112 :   function coated_frac(self, bin_ndx,  species_type, ncol, nlev, aero_props, radius) result(frac)
         593             :
         594             :     class(aerosol_state), intent(in) :: self
         595             :     integer, intent(in) :: bin_ndx                ! bin number
         596             :     character(len=*), intent(in) :: species_type  ! species type
         597             :     integer, intent(in) :: ncol                   ! number of columns
         598             :     integer, intent(in) :: nlev                   ! number of vertical levels
         599             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         600             :     real(r8), intent(in) :: radius(:,:) ! m
         601             :
         602             :     real(r8) :: frac(ncol,nlev)                              ! coated fraction
         603             :
         604             :     !------------coated variables--------------------
         605             :     real(r8), parameter :: n_so4_monolayers_dust = 1.0_r8 ! number of so4(+nh4) monolayers needed to coat a dust particle
         606             :     real(r8), parameter :: dr_so4_monolayers_dust = n_so4_monolayers_dust * 4.76e-10_r8
         607    35740224 :     real(r8) :: vol_shell(ncol,nlev)
         608    35740224 :     real(r8) :: vol_core(ncol,nlev)
         609             :     real(r8) :: alnsg, fac_volsfc
         610    35740224 :     real(r8) :: tmp1(ncol,nlev), tmp2(ncol,nlev)
         611    17870112 :     real(r8),pointer :: sulf_mmr(:,:)
         612    17870112 :     real(r8),pointer :: soa_mmr(:,:)
         613    17870112 :     real(r8),pointer :: pom_mmr(:,:)
         614    17870112 :     real(r8),pointer :: aer_mmr(:,:)
         615             :
         616             :     integer :: sulf_ndx
         617             :     integer :: soa_ndx
         618             :     integer :: pom_ndx
         619             :     integer :: species_ndx
         620             :
         621             :     real(r8) :: specdens_so4
         622             :     real(r8) :: specdens_pom
         623             :     real(r8) :: specdens_soa
         624             :     real(r8) :: specdens
         625             :
         626             :     character(len=aero_name_len) :: spectype
         627             :     integer :: ispc
         628             :
         629 27768076128 :     frac = -huge(1._r8)
         630             :
         631    17870112 :     sulf_ndx = -1
         632    17870112 :     pom_ndx = -1
         633    17870112 :     soa_ndx = -1
         634    17870112 :     species_ndx = -1
         635             :
         636    93818088 :     do ispc = 1, aero_props%nspecies(bin_ndx)
         637    75947976 :        call aero_props%species_type(bin_ndx, ispc, spectype)
         638             :
         639   151895952 :        select case ( trim(spectype) )
         640             :        case('sulfate')
         641    13402584 :           sulf_ndx = ispc
         642             :        case('p-organic')
         643    13402584 :           pom_ndx = ispc
         644             :        case('s-organic')
         645   151895952 :           soa_ndx = ispc
         646             :        end select
         647    93818088 :        if (spectype==species_type) then
         648    17870112 :           species_ndx = ispc
         649             :        end if
         650             :     end do
         651             :
         652 27768076128 :     vol_shell(:ncol,:) = 0._r8
         653             :
         654    17870112 :     if (sulf_ndx>0) then
         655    13402584 :        call aero_props%get(bin_ndx, sulf_ndx, density=specdens_so4)
         656    13402584 :        call self%get_ambient_mmr(sulf_ndx, bin_ndx, sulf_mmr)
         657 20826057096 :        vol_shell(:ncol,:) = vol_shell(:ncol,:) + sulf_mmr(:ncol,:)/specdens_so4
         658             :     end if
         659    17870112 :     if (pom_ndx>0) then
         660    13402584 :        call aero_props%get(bin_ndx, pom_ndx, density=specdens_pom)
         661    13402584 :        call self%get_ambient_mmr(pom_ndx, bin_ndx, pom_mmr)
         662 20826057096 :        vol_shell(:ncol,:) = vol_shell(:ncol,:) + pom_mmr(:ncol,:)*aero_props%pom_equivso4_factor()/specdens_pom
         663             :     end if
         664    17870112 :     if (soa_ndx>0) then
         665     8935056 :        call aero_props%get(bin_ndx, soa_ndx, density=specdens_soa)
         666     8935056 :        call self%get_ambient_mmr(soa_ndx, bin_ndx, soa_mmr)
         667 13884038064 :        vol_shell(:ncol,:) = vol_shell(:ncol,:) + soa_mmr(:ncol,:)*aero_props%soa_equivso4_factor()/specdens_soa
         668             :     end if
         669             :
         670    17870112 :     call aero_props%get(bin_ndx, species_ndx, density=specdens)
         671    17870112 :     call self%get_ambient_mmr(species_ndx, bin_ndx, aer_mmr)
         672 27768076128 :     vol_core(:ncol,:) = aer_mmr(:ncol,:)/specdens
         673             :
         674    17870112 :     alnsg = aero_props%alogsig(bin_ndx)
         675    17870112 :     fac_volsfc = exp(2.5_r8*alnsg**2)
         676             :
         677 27768076128 :     tmp1(:ncol,:) = vol_shell(:ncol,:)*(radius(:ncol,:)*2._r8)*fac_volsfc
         678 27768076128 :     tmp2(:ncol,:) = max(6.0_r8*dr_so4_monolayers_dust*vol_core(:ncol,:), 0.0_r8)
         679             :
         680 27768076128 :     where(tmp1(:ncol,:)>0._r8 .and. tmp2(:ncol,:)>0._r8)
         681             :        frac(:ncol,:) = tmp1(:ncol,:)/tmp2(:ncol,:)
         682             :     elsewhere
         683             :        frac(:ncol,:) = 0.001_r8
         684             :     end where
         685             :
         686 27768076128 :     where(frac(:ncol,:)>1._r8)
         687             :        frac(:ncol,:) = 1._r8
         688             :     end where
         689 27768076128 :     where(frac(:ncol,:) < 0.001_r8)
         690             :        frac(:ncol,:) = 0.001_r8
         691             :     end where
         692             :
         693    17870112 :   end function coated_frac
         694             :
         695             :   !------------------------------------------------------------------------------
         696             :   ! returns the radius [m] of particles in aerosol subset `bin_ndx` assuming all particles are
         697             :   ! the same size and only species `species_ndx` contributes to the particle volume
         698             :   !------------------------------------------------------------------------------
         699    17870112 :   function mass_mean_radius(self, bin_ndx, species_ndx, ncol, nlev, aero_props, rho) result(radius)
         700             :
         701             :     class(aerosol_state), intent(in) :: self
         702             :     integer, intent(in) :: bin_ndx                ! bin number
         703             :     integer, intent(in) :: species_ndx            ! species number
         704             :     integer, intent(in) :: ncol                   ! number of columns
         705             :     integer, intent(in) :: nlev                   ! number of vertical levels
         706             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         707             :     real(r8), intent(in) :: rho(:,:)              ! air density (kg m-3)
         708             :
         709             :     real(r8) :: radius(ncol,nlev) ! m
         710             :
         711             :     character(len=aero_name_len) :: species_type
         712    35740224 :     real(r8) :: aer_numdens(ncol,nlev) ! kg/m3
         713    35740224 :     real(r8) :: aer_massdens(ncol,nlev) ! kg/m3
         714    17870112 :     real(r8),pointer :: aer_mmr(:,:) ! kg/kg
         715             :
         716             :     real(r8) :: specdens,minrad
         717    35740224 :     real(r8) :: wght(ncol,nlev)
         718             :     integer :: i,k
         719             :
         720 27768076128 :     wght = self%hetfrz_size_wght(bin_ndx, ncol, nlev)
         721             :
         722    17870112 :     call aero_props%species_type(bin_ndx, species_ndx, spectype=species_type)
         723             :
         724    17870112 :     call aero_props%get(bin_ndx, species_ndx, density=specdens) ! kg/m3
         725    17870112 :     call self%get_ambient_mmr(species_ndx, bin_ndx, aer_mmr) ! kg/kg
         726    17870112 :     call self%get_amb_species_numdens(bin_ndx, ncol, nlev, species_type, aero_props, rho, aer_numdens) ! #/cm3
         727             :
         728 27768076128 :     aer_massdens(:ncol,:) = aer_mmr(:ncol,:)*rho(:ncol,:)*wght(:ncol,:) ! kg/m3
         729             :
         730    17870112 :     minrad = aero_props%min_mass_mean_rad(bin_ndx, species_ndx)
         731             :
         732  1679790528 :     do k = 1,nlev
         733 27768076128 :        do i = 1,ncol
         734 27750206016 :           if (aer_massdens(i,k)*1.0e-3_r8 > 1.0e-30_r8 .and. aer_numdens(i,k) > 1.0e-3_r8) then
         735 15130985756 :              radius(i,k) = (3._r8/(4*pi*specdens)*aer_massdens(i,k)/(aer_numdens(i,k)*per_m3))**(1._r8/3._r8) ! m
         736             :           else
         737 10957299844 :              radius(i,k) = minrad
         738             :           end if
         739             :        end do
         740             :     end do
         741             :
         742    17870112 :   end function mass_mean_radius
         743             :
         744             :   !------------------------------------------------------------------------------
         745             :   ! calculates water activity mass factor -- density*(1.-(OC+BC)/(OC+BC+SO4)) [mug m-3]
         746             :   ! of species `species_type` in subset `bin_ndx`
         747             :   !------------------------------------------------------------------------------
         748    17870112 :   subroutine watact_mfactor(self, bin_ndx,  species_type, ncol, nlev, aero_props, rho, wact_factor)
         749             :
         750             :     class(aerosol_state), intent(in) :: self
         751             :     integer, intent(in) :: bin_ndx                ! bin number
         752             :     character(len=*), intent(in) :: species_type  ! species type
         753             :     integer, intent(in) :: ncol                   ! number of columns
         754             :     integer, intent(in) :: nlev                   ! number of vertical levels
         755             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         756             :     real(r8), intent(in) :: rho(:,:)              ! air density (kg m-3)
         757             :     real(r8), intent(out) :: wact_factor(:,:)     ! water activity factor -- density*(1.-(OC+BC)/(OC+BC+SO4)) [mug m-3]
         758             :
         759    17870112 :     real(r8), pointer :: aer_mmr(:,:)
         760    17870112 :     real(r8), pointer :: bin_num(:,:)
         761    35740224 :     real(r8) :: tot2_mmr(ncol,nlev)
         762    35740224 :     real(r8) :: tot1_mmr(ncol,nlev)
         763    35740224 :     real(r8) :: aer_numdens(ncol,nlev)
         764             :     integer :: ispc
         765             :     character(len=aero_name_len) :: spectype
         766             :
         767    35740224 :     real(r8) :: awcam(ncol,nlev)          ! mass density [mug m-3]
         768    35740224 :     real(r8) :: awfacm(ncol,nlev)         ! mass factor ! (OC+BC)/(OC+BC+SO4)
         769             :
         770 27768076128 :     tot2_mmr = 0.0_r8
         771 27768076128 :     tot1_mmr = 0.0_r8
         772             :
         773    17870112 :     if (aero_props%soluble(bin_ndx)) then
         774             :
         775    80415504 :        do ispc = 1, aero_props%nspecies(bin_ndx)
         776             :
         777    67012920 :           call aero_props%species_type(bin_ndx, ispc, spectype)
         778             :
         779    67012920 :           if (trim(spectype)=='black-c' .or. trim(spectype)=='p-organic' .or. trim(spectype)=='s-organic') then
         780    26805168 :              call self%get_ambient_mmr(ispc, bin_ndx, aer_mmr)
         781 41652114192 :              tot2_mmr(:ncol,:) = tot2_mmr(:ncol,:) + aer_mmr(:ncol,:)
         782             :           end if
         783    80415504 :           if (trim(spectype)=='sulfate') then
         784    13402584 :              call self%get_ambient_mmr(ispc, bin_ndx, aer_mmr)
         785 20826057096 :              tot1_mmr(:ncol,:) = tot1_mmr(:ncol,:) + aer_mmr(:ncol,:)
         786             :           end if
         787             :        end do
         788             :
         789             :     end if
         790             :
         791 27768076128 :     tot1_mmr(:ncol,:) = tot1_mmr(:ncol,:) + tot2_mmr(:ncol,:)
         792             :
         793    17870112 :     call self%get_amb_species_numdens(bin_ndx, ncol, nlev, species_type, aero_props, rho, aer_numdens) ! #/cm3
         794    17870112 :     call self%get_ambient_num(bin_ndx, bin_num) ! #/kg
         795             :
         796 27768076128 :     where(bin_num(:ncol,:)>0._r8)
         797    17870112 :        awcam(:ncol,:) = ((aer_numdens(:ncol,:)*per_m3/bin_num(:ncol,:)) * tot1_mmr(:ncol,:)) * kg2mug  ! [mug m-3]
         798             :     elsewhere
         799             :        awcam(:ncol,:) = 0._r8
         800             :     end where
         801             :
         802 27768076128 :     where(tot1_mmr(:ncol,:)>0)
         803             :        awfacm(:ncol,:) = tot2_mmr(:ncol,:) / tot1_mmr(:ncol,:)
         804             :     elsewhere
         805             :        awfacm(:ncol,:) = 0._r8
         806             :     end where
         807             :
         808 27768076128 :     wact_factor(:ncol,:) = awcam(:ncol,:)*(1._r8-awfacm(:ncol,:))
         809             :
         810    17870112 :   end subroutine watact_mfactor
         811             :
         812             :   !------------------------------------------------------------------------------
         813             :   ! aerosol short wave refactive index
         814             :   !------------------------------------------------------------------------------
         815  3885876288 :   function refractive_index_sw(self, ncol, ilev, ilist, ibin, iwav, aero_props) result(crefin)
         816             :
         817             :     class(aerosol_state), intent(in) :: self
         818             :     integer, intent(in) :: ncol   ! number of columes
         819             :     integer, intent(in) :: ilev   ! level index
         820             :     integer, intent(in) :: ilist  ! radiation diagnostics list index
         821             :     integer, intent(in) :: ibin   ! bin index
         822             :     integer, intent(in) :: iwav   ! wave length index
         823             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         824             :
         825             :     complex(r8) :: crefin(ncol) ! complex refractive index
         826             :
         827  3885876288 :     real(r8), pointer :: specmmr(:,:) ! species mass mixing ratio
         828  3885876288 :     complex(r8), pointer :: specrefindex(:)     ! species refractive index
         829             :     real(r8) :: specdens              ! species density (kg/m3)
         830             :     integer :: ispec, icol
         831  7771752576 :     real(r8) :: vol(ncol)
         832             :
         833 64885097088 :     crefin(:ncol) = (0._r8, 0._r8)
         834             :
         835 18457912368 :     do ispec = 1, aero_props%nspecies(ilist,ibin)
         836             :
         837 14572036080 :        call self%get_ambient_mmr(ilist,ispec,ibin,specmmr)
         838 14572036080 :        call aero_props%get(ibin, ispec, list_ndx=ilist, density=specdens,  refindex_sw=specrefindex)
         839             :
         840 >24720*10^7 :        do icol = 1, ncol
         841 >22874*10^7 :           vol(icol) = specmmr(icol,ilev)/specdens
         842 >24331*10^7 :           crefin(icol) = crefin(icol) + vol(icol)*specrefindex(iwav)
         843             :        end do
         844             :     end do
         845             :
         846  3885876288 :   end function refractive_index_sw
         847             :
         848             :   !------------------------------------------------------------------------------
         849             :   ! aerosol long wave refactive index
         850             :   !------------------------------------------------------------------------------
         851  4441001472 :   function refractive_index_lw(self, ncol, ilev, ilist, ibin, iwav, aero_props) result(crefin)
         852             :
         853             :     class(aerosol_state), intent(in) :: self
         854             :     integer, intent(in) :: ncol   ! number of columes
         855             :     integer, intent(in) :: ilev   ! level index
         856             :     integer, intent(in) :: ilist  ! radiation diagnostics list index
         857             :     integer, intent(in) :: ibin   ! bin index
         858             :     integer, intent(in) :: iwav   ! wave length index
         859             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         860             :
         861             :     complex(r8) :: crefin(ncol) ! complex refractive index
         862             :
         863  4441001472 :     real(r8), pointer :: specmmr(:,:) ! species mass mixing ratio
         864  4441001472 :     complex(r8), pointer :: specrefindex(:)     ! species refractive index
         865             :     real(r8) :: specdens              ! species density (kg/m3)
         866             :     integer :: ispec, icol
         867  8882002944 :     real(r8) :: vol(ncol)
         868             :
         869 74154396672 :     crefin(:ncol) = (0._r8, 0._r8)
         870             :
         871 21094756992 :     do ispec = 1, aero_props%nspecies(ilist,ibin)
         872             :
         873 16653755520 :        call self%get_ambient_mmr(ilist,ispec,ibin,specmmr)
         874 16653755520 :        call aero_props%get(ibin, ispec, list_ndx=ilist, density=specdens,  refindex_lw=specrefindex)
         875             :
         876 >28251*10^7 :        do icol = 1, ncol
         877 >26142*10^7 :           vol(icol) = specmmr(icol,ilev)/specdens
         878 >27807*10^7 :           crefin(icol) = crefin(icol) + vol(icol)*specrefindex(iwav)
         879             :        end do
         880             :     end do
         881             :
         882  4441001472 :   end function refractive_index_lw
         883             :
         884             :   !------------------------------------------------------------------------------
         885             :   ! prescribed aerosol activation fraction for convective cloud
         886             :   !------------------------------------------------------------------------------
         887           0 :   function convcld_actfrac(self, ibin, ispc, ncol, nlev) result(frac)
         888             :
         889             :     class(aerosol_state), intent(in) :: self
         890             :     integer, intent(in) :: ibin   ! bin index
         891             :     integer, intent(in) :: ispc   ! species index
         892             :     integer, intent(in) :: ncol   ! number of columns
         893             :     integer, intent(in) :: nlev   ! number of vertical levels
         894             :
         895             :     real(r8) :: frac(ncol,nlev)
         896             :
         897           0 :     frac = 0.8_r8 ! rce 2010/05/02
         898             :
         899           0 :   end function convcld_actfrac
         900             :
         901             :   !------------------------------------------------------------------------------
         902             :   ! below cloud solubility factor for interstitial aerosols
         903             :   !------------------------------------------------------------------------------
         904           0 :   function sol_factb_interstitial(self, bin_ndx, ncol, nlev, aero_props) result(sol_factb)
         905             :
         906             :     class(aerosol_state), intent(in) :: self
         907             :     integer, intent(in) :: bin_ndx                ! bin number
         908             :     integer, intent(in) :: ncol                   ! number of columns
         909             :     integer, intent(in) :: nlev                   ! number of vertical levels
         910             :     class(aerosol_properties), intent(in) :: aero_props ! aerosol properties object
         911             :
         912             :     real(r8) :: sol_factb(ncol,nlev)
         913             :
         914           0 :     real(r8), pointer :: aer_mmr(:,:)
         915           0 :     real(r8) :: totmmr(ncol,nlev)
         916           0 :     real(r8) :: solmmr(ncol,nlev)
         917             :     integer :: ispc
         918             :     character(len=aero_name_len) :: spectype
         919             :
         920           0 :     sol_factb(:,:) = 0.0_r8
         921             :
         922           0 :     totmmr(:,:) = 0._r8
         923           0 :     solmmr(:,:) = 0._r8
         924             :
         925           0 :     do ispc = 1, aero_props%nspecies(bin_ndx)
         926             :
         927           0 :        call aero_props%species_type(bin_ndx, ispc, spectype)
         928           0 :        call self%get_ambient_mmr(ispc, bin_ndx, aer_mmr)
         929             :
         930           0 :        totmmr(:ncol,:) = totmmr(:ncol,:) + aer_mmr(:ncol,:)
         931             :
         932           0 :        if (trim(spectype) == 'sulfate') then
         933           0 :           solmmr(:ncol,:) = solmmr(:ncol,:) + aer_mmr(:ncol,:)*0.5_r8
         934             :        end if
         935           0 :        if (trim(spectype) == 'p-organic') then
         936           0 :           solmmr(:ncol,:) = solmmr(:ncol,:) + aer_mmr(:ncol,:)*0.2_r8
         937             :        end if
         938           0 :        if (trim(spectype) == 's-organic') then
         939           0 :           solmmr(:ncol,:) = solmmr(:ncol,:) + aer_mmr(:ncol,:)*0.2_r8
         940             :        end if
         941           0 :        if (trim(spectype) == 'dust') then
         942           0 :           solmmr(:ncol,:) = solmmr(:ncol,:) + aer_mmr(:ncol,:)*0.1_r8
         943             :        end if
         944           0 :        if (trim(spectype) == 'seasalt') then
         945           0 :           solmmr(:ncol,:) = solmmr(:ncol,:) + aer_mmr(:ncol,:)*0.8_r8
         946             :        end if
         947             :
         948             :     end do   !nspec
         949             :
         950           0 :     where ( totmmr > 0._r8 )
         951             :        sol_factb = solmmr/totmmr
         952             :     end where
         953             :
         954           0 :     where ( sol_factb > 0.8_r8 )
         955             :        sol_factb = 0.8_r8
         956             :     end where
         957           0 :     where ( sol_factb < 0.1_r8 )
         958             :        sol_factb = 0.1_r8
         959             :     end where
         960             :
         961           0 :   end function sol_factb_interstitial
         962             :
         963             :
         964           0 : end module aerosol_state_mod

Generated by: LCOV version 1.14