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

Generated by: LCOV version 1.14