LCOV - code coverage report
Current view: | top level - chemistry/aerosol - aerosol_properties_mod.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 91 | 93 | 97.8 %
Date: | 2024-12-17 22:39:59 |  | Functions: | 13 | 14 | 92.9 %

              Line data    Source code
           1             : module aerosol_properties_mod
           2             :   use shr_kind_mod, only: r8 => shr_kind_r8
           3             :
           4             :   implicit none
           5             :
           6             :   private
           7             :
           8             :   public :: aerosol_properties
           9             :
          10             :   !> aerosol_properties defines the configuration of any aerosol package (using
          11             :   !! any aerosol representation) based on user specification. These values are
          12             :   !! set during initialization and do not vary during the simulation.
          13             :   !!
          14             :   !! Each aerosol package (e.g., MAM, CARMA, etc) must extend the abstract
          15             :   !! aerosol_properties class to define the details of their configuration. Any
          16             :   !! package must implement each of the deferred procedures of the abstract
          17             :   !! aerosol_properties class, may include additional private data members and
          18             :   !! type-bound procedures, and may override functions of the abstract class.
          19             :   !!
          20             :   !! Please see the modal_aerosol_properties module for an example of how the
          21             :   !! aerosol_properties class can be extended for a specific aerosol package.
          22             :   type, abstract :: aerosol_properties
          23             :      private
          24             :      integer :: nbins_ = 0  ! number of aerosol bins
          25             :      integer :: ncnst_tot_ = 0 ! total number of constituents
          26             :      integer, allocatable :: nmasses_(:) ! number of species masses
          27             :      integer, allocatable :: nspecies_(:) ! number of species
          28             :      integer, allocatable :: indexer_(:,:) ! unique indices of the aerosol elements
          29             :      real(r8), allocatable :: alogsig_(:) ! natural log of geometric deviation of the number distribution for aerosol bin
          30             :      real(r8), allocatable :: f1_(:) ! eq 28 Abdul-Razzak et al 1998
          31             :      real(r8), allocatable :: f2_(:) ! eq 29 Abdul-Razzak et al 1998
          32             :      ! Abdul-Razzak, H., S.J. Ghan, and C. Rivera-Carpio, A parameterization of aerosol activation,
          33             :      ! 1, Singleaerosoltype. J. Geophys. Res., 103, 6123-6132, 1998.
          34             :      real(r8) :: soa_equivso4_factor_ = -huge(1._r8)
          35             :      real(r8) :: pom_equivso4_factor_ = -huge(1._r8)
          36             :    contains
          37             :      procedure :: initialize => aero_props_init
          38             :      procedure,private :: nbins_0list
          39             :      procedure(aero_nbins_rlist), deferred :: nbins_rlist
          40             :      generic :: nbins => nbins_0list,nbins_rlist
          41             :      procedure :: ncnst_tot
          42             :      procedure,private :: nspecies_per_bin
          43             :      procedure(aero_nspecies_rlist), deferred :: nspecies_per_bin_rlist
          44             :      procedure,private :: nspecies_all_bins
          45             :      generic :: nspecies => nspecies_all_bins,nspecies_per_bin,nspecies_per_bin_rlist
          46             :      procedure,private :: n_masses_all_bins
          47             :      procedure,private :: n_masses_per_bin
          48             :      generic :: nmasses => n_masses_all_bins,n_masses_per_bin
          49             :      procedure :: indexer
          50             :      procedure :: maxsat
          51             :      procedure(aero_amcube), deferred :: amcube
          52             :      procedure :: alogsig_0list
          53             :      procedure(aero_alogsig_rlist), deferred :: alogsig_rlist
          54             :      generic :: alogsig =>  alogsig_0list,alogsig_rlist
          55             :      procedure(aero_number_transported), deferred :: number_transported
          56             :      procedure(aero_props_get), deferred :: get
          57             :      procedure(aero_actfracs), deferred :: actfracs
          58             :      procedure(aero_num_names), deferred :: num_names
          59             :      procedure(aero_mmr_names), deferred :: mmr_names
          60             :      procedure(aero_amb_num_name), deferred :: amb_num_name
          61             :      procedure(aero_amb_mmr_name), deferred :: amb_mmr_name
          62             :      procedure(aero_species_type), deferred :: species_type
          63             :      procedure(aero_icenuc_updates_num), deferred :: icenuc_updates_num
          64             :      procedure(aero_icenuc_updates_mmr), deferred :: icenuc_updates_mmr
          65             :      procedure(aero_apply_num_limits), deferred :: apply_number_limits
          66             :      procedure(aero_hetfrz_species), deferred :: hetfrz_species
          67             :      procedure :: soa_equivso4_factor ! SOA Hygroscopicity / Sulfate Hygroscopicity
          68             :      procedure :: pom_equivso4_factor ! POM Hygroscopicity / Sulfate Hygroscopicity
          69             :      procedure(aero_soluble), deferred :: soluble
          70             :      procedure(aero_min_mass_mean_rad), deferred :: min_mass_mean_rad
          71             :      procedure(aero_optics_params), deferred :: optics_params
          72             :      procedure(aero_bin_name), deferred :: bin_name
          73             :      procedure(aero_scav_diam), deferred :: scav_diam
          74             :      procedure(aero_resuspension_resize), deferred :: resuspension_resize
          75             :      procedure(aero_rebin_bulk_fluxes), deferred :: rebin_bulk_fluxes
          76             :      procedure(aero_hydrophilic), deferred :: hydrophilic
          77             :
          78             :      procedure :: final=>aero_props_final
          79             :   end type aerosol_properties
          80             :
          81             :   integer,public, parameter :: aero_name_len = 32 ! common length of aersols names, species, etc
          82             :
          83             :   abstract interface
          84             :
          85             :      !------------------------------------------------------------------------------
          86             :      ! returns number of transported aerosol constituents
          87             :      !------------------------------------------------------------------------------
          88             :      integer function aero_number_transported(self)
          89             :        import :: aerosol_properties
          90             :        class(aerosol_properties), intent(in) :: self
          91             :      end function aero_number_transported
          92             :
          93             :      !------------------------------------------------------------------------
          94             :      ! returns aerosol properties:
          95             :      !  density
          96             :      !  hygroscopicity
          97             :      !  species type
          98             :      !  species name
          99             :      !  short wave species refractive indices
         100             :      !  long wave species refractive indices
         101             :      !  species morphology
         102             :      !------------------------------------------------------------------------
         103             :      subroutine aero_props_get(self, bin_ndx, species_ndx, list_ndx, density, hygro, &
         104             :                                spectype, specname, specmorph, refindex_sw, refindex_lw)
         105             :        import :: aerosol_properties, r8
         106             :        class(aerosol_properties), intent(in) :: self
         107             :        integer, intent(in) :: bin_ndx             ! bin index
         108             :        integer, intent(in) :: species_ndx         ! species index
         109             :        integer, optional, intent(in) :: list_ndx  ! climate or a diagnostic list number
         110             :        real(r8), optional, intent(out) :: density ! density (kg/m3)
         111             :        real(r8), optional, intent(out) :: hygro   ! hygroscopicity
         112             :        character(len=*), optional, intent(out) :: spectype  ! species type
         113             :        character(len=*), optional, intent(out) :: specname  ! species name
         114             :        character(len=*), optional, intent(out) :: specmorph ! species morphology
         115             :        complex(r8), pointer, optional, intent(out) :: refindex_sw(:) ! short wave species refractive indices
         116             :        complex(r8), pointer, optional, intent(out) :: refindex_lw(:) ! long wave species refractive indices
         117             :
         118             :      end subroutine aero_props_get
         119             :
         120             :      !------------------------------------------------------------------------
         121             :      ! returns optics type and table parameters
         122             :      !------------------------------------------------------------------------
         123             :      subroutine aero_optics_params(self, list_ndx, bin_ndx, opticstype, extpsw, abspsw, asmpsw, absplw, &
         124             :           refrtabsw, refitabsw, refrtablw, refitablw, ncoef, prefr, prefi, sw_hygro_ext_wtp, &
         125             :           sw_hygro_ssa_wtp, sw_hygro_asm_wtp, lw_hygro_ext_wtp, wgtpct, nwtp, &
         126             :           sw_hygro_coreshell_ext, sw_hygro_coreshell_ssa, sw_hygro_coreshell_asm, lw_hygro_coreshell_ext, &
         127             :           corefrac, bcdust, kap, relh, nfrac, nbcdust, nkap, nrelh )
         128             :
         129             :        import :: aerosol_properties, r8
         130             :
         131             :        class(aerosol_properties), intent(in) :: self
         132             :        integer, intent(in) :: bin_ndx             ! bin index
         133             :        integer, intent(in) :: list_ndx            ! rad climate/diags list
         134             :
         135             :        character(len=*), optional, intent(out) :: opticstype
         136             :
         137             :        ! refactive index table parameters
         138             :        real(r8),  optional, pointer     :: extpsw(:,:,:,:) ! short wave specific extinction
         139             :        real(r8),  optional, pointer     :: abspsw(:,:,:,:) ! short wave specific absorption
         140             :        real(r8),  optional, pointer     :: asmpsw(:,:,:,:) ! short wave asymmetry factor
         141             :        real(r8),  optional, pointer     :: absplw(:,:,:,:) ! long wave specific absorption
         142             :        real(r8),  optional, pointer     :: refrtabsw(:,:)  ! table of short wave real refractive indices for aerosols
         143             :        real(r8),  optional, pointer     :: refitabsw(:,:)  ! table of short wave imaginary refractive indices for aerosols
         144             :        real(r8),  optional, pointer     :: refrtablw(:,:)  ! table of long wave real refractive indices for aerosols
         145             :        real(r8),  optional, pointer     :: refitablw(:,:)  ! table of long wave imaginary refractive indices for aerosols
         146             :        integer,   optional, intent(out) :: ncoef  ! number of chebychev polynomials
         147             :        integer,   optional, intent(out) :: prefr  ! number of real refractive indices in table
         148             :        integer,   optional, intent(out) :: prefi  ! number of imaginary refractive indices in table
         149             :
         150             :        ! hygrowghtpct table parameters
         151             :        real(r8),  optional, pointer     :: sw_hygro_ext_wtp(:,:) ! short wave extinction table
         152             :        real(r8),  optional, pointer     :: sw_hygro_ssa_wtp(:,:) ! short wave single-scatter albedo table
         153             :        real(r8),  optional, pointer     :: sw_hygro_asm_wtp(:,:) ! short wave asymmetry table
         154             :        real(r8),  optional, pointer     :: lw_hygro_ext_wtp(:,:) ! long wave absorption table
         155             :        real(r8),  optional, pointer     :: wgtpct(:)   ! weight precent of H2SO4/H2O solution
         156             :        integer,   optional, intent(out) :: nwtp        ! number of weight precent values
         157             :
         158             :        ! hygrocoreshell table parameters
         159             :        real(r8),  optional, pointer     :: sw_hygro_coreshell_ext(:,:,:,:,:) ! short wave extinction table
         160             :        real(r8),  optional, pointer     :: sw_hygro_coreshell_ssa(:,:,:,:,:) ! short wave single-scatter albedo table
         161             :        real(r8),  optional, pointer     :: sw_hygro_coreshell_asm(:,:,:,:,:) ! short wave asymmetry table
         162             :        real(r8),  optional, pointer     :: lw_hygro_coreshell_ext(:,:,:,:,:) ! long wave absorption table
         163             :        real(r8),  optional, pointer     :: corefrac(:) ! core fraction dimension values
         164             :        real(r8),  optional, pointer     :: bcdust(:)   ! bc/(bc + dust) fraction dimension values
         165             :        real(r8),  optional, pointer     :: kap(:)      ! hygroscopicity dimension values
         166             :        real(r8),  optional, pointer     :: relh(:)     ! relative humidity dimension values
         167             :        integer,   optional, intent(out) :: nfrac       ! core fraction dimension size
         168             :        integer,   optional, intent(out) :: nbcdust     ! bc/(bc + dust) fraction dimension size
         169             :        integer,   optional, intent(out) :: nkap        ! hygroscopicity dimension size
         170             :        integer,   optional, intent(out) :: nrelh       ! relative humidity dimension size
         171             :
         172             :      end subroutine aero_optics_params
         173             :
         174             :      !------------------------------------------------------------------------
         175             :      ! returns species type
         176             :      !------------------------------------------------------------------------
         177             :      subroutine aero_species_type(self, bin_ndx, species_ndx, spectype)
         178             :        import :: aerosol_properties
         179             :        class(aerosol_properties), intent(in) :: self
         180             :        integer, intent(in) :: bin_ndx           ! bin number
         181             :        integer, intent(in) :: species_ndx       ! species number
         182             :        character(len=*), intent(out) :: spectype ! species type
         183             :
         184             :      end subroutine aero_species_type
         185             :
         186             :      !------------------------------------------------------------------------
         187             :      ! returns mass and number activation fractions
         188             :      !------------------------------------------------------------------------
         189             :      subroutine aero_actfracs(self, bin_ndx, smc, smax, fn, fm )
         190             :        import :: aerosol_properties, r8
         191             :        class(aerosol_properties), intent(in) :: self
         192             :        integer, intent(in) :: bin_ndx   ! bin index
         193             :        real(r8),intent(in) :: smc       ! critical supersaturation for particles of bin radius
         194             :        real(r8),intent(in) :: smax      ! maximum supersaturation for multiple competing aerosols
         195             :        real(r8),intent(out) :: fn       ! activation fraction for aerosol number
         196             :        real(r8),intent(out) :: fm       ! activation fraction for aerosol mass
         197             :
         198             :      end subroutine aero_actfracs
         199             :
         200             :      !------------------------------------------------------------------------
         201             :      ! returns constituents names of aerosol number mixing ratios
         202             :      !------------------------------------------------------------------------
         203             :      subroutine aero_num_names(self, bin_ndx, name_a, name_c)
         204             :        import :: aerosol_properties
         205             :        class(aerosol_properties), intent(in) :: self
         206             :        integer, intent(in) :: bin_ndx           ! bin number
         207             :        character(len=*), intent(out) :: name_a ! constituent name of ambient aerosol number dens
         208             :        character(len=*), intent(out) :: name_c ! constituent name of cloud-borne aerosol number dens
         209             :      end subroutine aero_num_names
         210             :
         211             :      !------------------------------------------------------------------------
         212             :      ! returns constituents names of aerosol mass mixing ratios
         213             :      !------------------------------------------------------------------------
         214             :      subroutine aero_mmr_names(self, bin_ndx, species_ndx, name_a, name_c)
         215             :        import :: aerosol_properties
         216             :        class(aerosol_properties), intent(in) :: self
         217             :        integer, intent(in) :: bin_ndx           ! bin number
         218             :        integer, intent(in) :: species_ndx       ! species number
         219             :        character(len=*), intent(out) :: name_a ! constituent name of ambient aerosol MMR
         220             :        character(len=*), intent(out) :: name_c ! constituent name of cloud-borne aerosol MMR
         221             :      end subroutine aero_mmr_names
         222             :
         223             :      !------------------------------------------------------------------------
         224             :      ! returns constituent name of ambient aerosol number mixing ratios
         225             :      !------------------------------------------------------------------------
         226             :      subroutine aero_amb_num_name(self, bin_ndx, name)
         227             :        import :: aerosol_properties
         228             :        class(aerosol_properties), intent(in) :: self
         229             :        integer, intent(in) :: bin_ndx          ! bin number
         230             :        character(len=*), intent(out) :: name  ! constituent name of ambient aerosol number dens
         231             :
         232             :      end subroutine aero_amb_num_name
         233             :
         234             :      !------------------------------------------------------------------------
         235             :      ! returns constituent name of ambient aerosol mass mixing ratios
         236             :      !------------------------------------------------------------------------
         237             :      subroutine aero_amb_mmr_name(self, bin_ndx, species_ndx, name)
         238             :        import :: aerosol_properties
         239             :        class(aerosol_properties), intent(in) :: self
         240             :        integer, intent(in) :: bin_ndx           ! bin number
         241             :        integer, intent(in) :: species_ndx       ! species number
         242             :        character(len=*), intent(out) :: name   ! constituent name of ambient aerosol MMR
         243             :
         244             :      end subroutine aero_amb_mmr_name
         245             :
         246             :      !------------------------------------------------------------------------------
         247             :      ! returns radius^3 (m3) of a given bin number
         248             :      !------------------------------------------------------------------------------
         249             :      pure elemental real(r8) function aero_amcube(self, bin_ndx, volconc, numconc)
         250             :        import :: aerosol_properties, r8
         251             :
         252             :        class(aerosol_properties), intent(in) :: self
         253             :        integer, intent(in) :: bin_ndx  ! bin number
         254             :        real(r8), intent(in) :: volconc ! volume conc (m3/m3)
         255             :        real(r8), intent(in) :: numconc ! number conc (1/m3)
         256             :
         257             :      end function aero_amcube
         258             :
         259             :      !------------------------------------------------------------------------------
         260             :      ! returns TRUE if Ice Nucleation tendencies are applied to given aerosol bin number
         261             :      !------------------------------------------------------------------------------
         262             :      function aero_icenuc_updates_num(self, bin_ndx) result(res)
         263             :        import :: aerosol_properties
         264             :        class(aerosol_properties), intent(in) :: self
         265             :        integer, intent(in) :: bin_ndx  ! bin number
         266             :
         267             :        logical :: res
         268             :
         269             :      end function aero_icenuc_updates_num
         270             :
         271             :      !------------------------------------------------------------------------------
         272             :      ! returns TRUE if Ice Nucleation tendencies are applied to a given species within a bin
         273             :      !------------------------------------------------------------------------------
         274             :      function aero_icenuc_updates_mmr(self, bin_ndx, species_ndx) result(res)
         275             :        import :: aerosol_properties
         276             :        class(aerosol_properties), intent(in) :: self
         277             :        integer, intent(in) :: bin_ndx     ! bin number
         278             :        integer, intent(in) :: species_ndx ! species number
         279             :
         280             :        logical :: res
         281             :
         282             :      end function aero_icenuc_updates_mmr
         283             :
         284             :      !------------------------------------------------------------------------------
         285             :      ! apply max / min to number concentration
         286             :      !------------------------------------------------------------------------------
         287             :      subroutine aero_apply_num_limits( self, naerosol, vaerosol, istart, istop, m )
         288             :        import :: aerosol_properties, r8
         289             :        class(aerosol_properties), intent(in) :: self
         290             :        real(r8), intent(inout) :: naerosol(:)  ! number conc (1/m3)
         291             :        real(r8), intent(in)    :: vaerosol(:)  ! volume conc (m3/m3)
         292             :        integer,  intent(in) :: istart          ! start column index (1 <= istart <= istop <= pcols)
         293             :        integer,  intent(in) :: istop           ! stop column index
         294             :        integer,  intent(in) :: m               ! mode or bin index
         295             :
         296             :      end subroutine aero_apply_num_limits
         297             :
         298             :      !------------------------------------------------------------------------------
         299             :      ! returns TRUE if species `spc_ndx` in aerosol subset `bin_ndx` contributes to
         300             :      ! the particles' ability to act as heterogeneous freezing nuclei
         301             :      !------------------------------------------------------------------------------
         302             :      function aero_hetfrz_species(self, bin_ndx, spc_ndx) result(res)
         303             :        import :: aerosol_properties
         304             :        class(aerosol_properties), intent(in) :: self
         305             :        integer, intent(in) :: bin_ndx  ! bin number
         306             :        integer, intent(in) :: spc_ndx  ! species number
         307             :
         308             :        logical :: res
         309             :
         310             :      end function aero_hetfrz_species
         311             :
         312             :      !------------------------------------------------------------------------------
         313             :      ! returns minimum mass mean radius (meters)
         314             :      !------------------------------------------------------------------------------
         315             :      function aero_min_mass_mean_rad(self,bin_ndx,species_ndx) result(minrad)
         316             :        import :: aerosol_properties, r8
         317             :        class(aerosol_properties), intent(in) :: self
         318             :        integer, intent(in) :: bin_ndx           ! bin number
         319             :        integer, intent(in) :: species_ndx       ! species number
         320             :
         321             :        real(r8) :: minrad  ! meters
         322             :
         323             :      end function aero_min_mass_mean_rad
         324             :
         325             :      !------------------------------------------------------------------------------
         326             :      ! returns TRUE if soluble
         327             :      !------------------------------------------------------------------------------
         328             :      logical function aero_soluble(self,bin_ndx)
         329             :        import :: aerosol_properties
         330             :        class(aerosol_properties), intent(in) :: self
         331             :        integer, intent(in) :: bin_ndx           ! bin number
         332             :
         333             :      end function aero_soluble
         334             :
         335             :      !------------------------------------------------------------------------------
         336             :      ! returns the total number of bins for a given radiation list index
         337             :      !------------------------------------------------------------------------------
         338             :      function aero_nbins_rlist(self, list_ndx)  result(res)
         339             :        import :: aerosol_properties
         340             :        class(aerosol_properties), intent(in) :: self
         341             :        integer, intent(in) :: list_ndx  ! radiation list number
         342             :
         343             :        integer :: res
         344             :
         345             :      end function aero_nbins_rlist
         346             :
         347             :      !------------------------------------------------------------------------------
         348             :      ! returns number of species in a bin for a given radiation list index
         349             :      !------------------------------------------------------------------------------
         350             :      function aero_nspecies_rlist(self, list_ndx,  bin_ndx)  result(res)
         351             :        import :: aerosol_properties
         352             :        class(aerosol_properties), intent(in) :: self
         353             :        integer, intent(in) :: list_ndx ! radiation list number
         354             :        integer, intent(in) :: bin_ndx  ! bin number
         355             :
         356             :        integer :: res
         357             :
         358             :      end function aero_nspecies_rlist
         359             :
         360             :      !------------------------------------------------------------------------------
         361             :      ! returns the natural log of geometric standard deviation of the number
         362             :      ! distribution for radiation list number and aerosol bin
         363             :      !------------------------------------------------------------------------------
         364             :      function aero_alogsig_rlist(self, list_ndx,  bin_ndx)  result(res)
         365             :        import :: aerosol_properties, r8
         366             :        class(aerosol_properties), intent(in) :: self
         367             :        integer, intent(in) :: list_ndx ! radiation list number
         368             :        integer, intent(in) :: bin_ndx  ! bin number
         369             :
         370             :        real(r8) :: res
         371             :
         372             :      end function aero_alogsig_rlist
         373             :
         374             :      !------------------------------------------------------------------------------
         375             :      ! returns name for a given radiation list number and aerosol bin
         376             :      !------------------------------------------------------------------------------
         377             :      function aero_bin_name(self, list_ndx,  bin_ndx) result(name)
         378             :        import :: aerosol_properties, r8
         379             :        class(aerosol_properties), intent(in) :: self
         380             :        integer, intent(in) :: list_ndx ! radiation list number
         381             :        integer, intent(in) :: bin_ndx  ! bin number
         382             :
         383             :        character(len=32) name
         384             :
         385             :      end function aero_bin_name
         386             :
         387             :      !------------------------------------------------------------------------------
         388             :      ! returns scavenging diameter for a given aerosol bin number
         389             :      !------------------------------------------------------------------------------
         390             :      function aero_scav_diam(self, bin_ndx) result(diam)
         391             :        import :: aerosol_properties, r8
         392             :        class(aerosol_properties), intent(in) :: self
         393             :        integer, intent(in) :: bin_ndx  ! bin number
         394             :
         395             :        real(r8) :: diam
         396             :
         397             :      end function aero_scav_diam
         398             :
         399             :      !------------------------------------------------------------------------------
         400             :      ! adjust aerosol concentration tendencies to create larger sizes of aerosols
         401             :      ! during resuspension
         402             :      !------------------------------------------------------------------------------
         403             :      subroutine aero_resuspension_resize(self, dcondt)
         404             :        import :: aerosol_properties, r8
         405             :
         406             :        class(aerosol_properties), intent(in) :: self
         407             :        real(r8), intent(inout) :: dcondt(:)
         408             :
         409             :      end subroutine aero_resuspension_resize
         410             :
         411             :      !------------------------------------------------------------------------------
         412             :      ! returns bulk deposition fluxes of the specified species type
         413             :      ! rebinned to specified diameter limits
         414             :      !------------------------------------------------------------------------------
         415             :      subroutine aero_rebin_bulk_fluxes(self, bulk_type, dep_fluxes, diam_edges, bulk_fluxes, &
         416             :                                        error_code, error_string)
         417             :        import :: aerosol_properties, r8
         418             :        class(aerosol_properties), intent(in) :: self
         419             :        character(len=*),intent(in) :: bulk_type       ! aerosol type to rebin
         420             :        real(r8), intent(in) :: dep_fluxes(:)          ! kg/m2
         421             :        real(r8), intent(in) :: diam_edges(:)          ! meters
         422             :        real(r8), intent(out) :: bulk_fluxes(:)        ! kg/m2
         423             :        integer,  intent(out) :: error_code            ! error code (0 if no error)
         424             :        character(len=*), intent(out) :: error_string  ! error string
         425             :
         426             :      end subroutine aero_rebin_bulk_fluxes
         427             :
         428             :      !------------------------------------------------------------------------------
         429             :      ! Returns TRUE if bin is hydrophilic, otherwise FALSE
         430             :      !------------------------------------------------------------------------------
         431             :      logical function aero_hydrophilic(self, bin_ndx)
         432             :        import :: aerosol_properties
         433             :        class(aerosol_properties), intent(in) :: self
         434             :        integer, intent(in) :: bin_ndx ! bin number
         435             :      end function aero_hydrophilic
         436             :
         437             :   end interface
         438             :
         439             : contains
         440             :
         441             :   !------------------------------------------------------------------------------
         442             :   ! object initializer
         443             :   !------------------------------------------------------------------------------
         444        6144 :   subroutine aero_props_init(self, nbin, ncnst, nspec, nmasses, alogsig, f1,f2, ierr )
         445             :     class(aerosol_properties), intent(inout) :: self
         446             :     integer, intent(in) :: nbin               ! number of bins
         447             :     integer, intent(in) :: ncnst              ! total number of constituents
         448             :     integer, intent(in) :: nspec(nbin)        ! number of species in each bin
         449             :     integer, intent(in) :: nmasses(nbin)      ! number of masses in each bin
         450             :     real(r8),intent(in) :: alogsig(nbin)      ! natural log of the standard deviation (sigma) of the aerosol bins
         451             :     real(r8),intent(in) :: f1(nbin)           ! eq 28 Abdul-Razzak et al 1998
         452             :     real(r8),intent(in) :: f2(nbin)           ! eq 29 Abdul-Razzak et al 1998
         453             :     integer,intent(out) :: ierr
         454             :
         455             :     integer :: imas,ibin,indx
         456             :     character(len=*),parameter :: prefix = 'aerosol_properties::aero_props_init: '
         457             :
         458             :     real(r8), parameter :: spechygro_so4 = 0.507_r8          ! Sulfate hygroscopicity
         459             :     real(r8), parameter :: spechygro_soa = 0.14_r8           ! SOA hygroscopicity
         460             :     real(r8), parameter :: spechygro_pom = 0.1_r8            ! POM hygroscopicity
         461             :
         462        6144 :     ierr = 0
         463             :
         464       18432 :     allocate(self%nspecies_(nbin),stat=ierr)
         465        6144 :     if( ierr /= 0 ) then
         466             :        return
         467             :     end if
         468       12288 :     allocate(self%nmasses_(nbin),stat=ierr)
         469        6144 :     if( ierr /= 0 ) then
         470             :        return
         471             :     end if
         472       18432 :     allocate(self%alogsig_(nbin),stat=ierr)
         473        6144 :     if( ierr /= 0 ) then
         474             :        return
         475             :     end if
         476       12288 :     allocate(self%f1_(nbin),stat=ierr)
         477        6144 :     if( ierr /= 0 ) then
         478             :        return
         479             :     end if
         480       12288 :     allocate(self%f2_(nbin),stat=ierr)
         481        6144 :     if( ierr /= 0 ) then
         482             :        return
         483             :     end if
         484             :
         485       49152 :     allocate( self%indexer_(nbin,0:maxval(nmasses)),stat=ierr )
         486        6144 :     if( ierr /= 0 ) then
         487             :        return
         488             :     end if
         489             :
         490             :     ! Local indexing compresses the mode and number/mass indices into one index.
         491             :     ! This indexing is used by the pointer arrays used to reference state and pbuf
         492             :     ! fields. We add number = 0, total mass = 1 (if available), and mass from each
         493             :     ! constituency into mm.
         494             :
         495      221184 :     self%indexer_ = -1
         496             :     indx = 0
         497             :
         498       30720 :     do ibin=1,nbin
         499      147456 :        do imas = 0,nmasses(ibin)
         500      116736 :           indx = indx+1
         501      141312 :           self%indexer_(ibin,imas) = indx
         502             :        end do
         503             :     end do
         504             :
         505        6144 :     self%nbins_ = nbin
         506        6144 :     self%ncnst_tot_ = ncnst
         507       30720 :     self%nmasses_(:) = nmasses(:)
         508       30720 :     self%nspecies_(:) = nspec(:)
         509       30720 :     self%alogsig_(:) = alogsig(:)
         510       30720 :     self%f1_(:) = f1(:)
         511       30720 :     self%f2_(:) = f2(:)
         512             :
         513        6144 :     self%soa_equivso4_factor_ = spechygro_soa/spechygro_so4
         514        6144 :     self%pom_equivso4_factor_ = spechygro_pom/spechygro_so4
         515             :
         516             :   end subroutine aero_props_init
         517             :
         518             :   !------------------------------------------------------------------------------
         519             :   ! Object clean
         520             :   !------------------------------------------------------------------------------
         521        1536 :   subroutine aero_props_final(self)
         522             :     class(aerosol_properties), intent(inout) :: self
         523             :
         524        1536 :     if (allocated(self%nspecies_)) then
         525        1536 :        deallocate(self%nspecies_)
         526             :     end if
         527        1536 :     if (allocated(self%nmasses_)) then
         528        1536 :        deallocate(self%nmasses_)
         529             :     end if
         530        1536 :     if (allocated(self%indexer_)) then
         531        1536 :        deallocate(self%indexer_)
         532             :     endif
         533        1536 :     if (allocated(self%alogsig_)) then
         534        1536 :        deallocate(self%alogsig_)
         535             :     endif
         536        1536 :     if (allocated(self%f1_)) then
         537        1536 :        deallocate(self%f1_)
         538             :     endif
         539        1536 :     if (allocated(self%f2_)) then
         540        1536 :        deallocate(self%f2_)
         541             :     endif
         542             :
         543        1536 :     self%nbins_ = 0
         544        1536 :     self%ncnst_tot_ = 0
         545             :
         546        1536 :   end subroutine aero_props_final
         547             :
         548             :   !------------------------------------------------------------------------------
         549             :   ! returns number of species in a bin
         550             :   !------------------------------------------------------------------------------
         551 12767931338 :   pure function nspecies_per_bin(self,bin_ndx) result(val)
         552             :     class(aerosol_properties), intent(in) :: self
         553             :     integer, intent(in) :: bin_ndx           ! bin number
         554             :     integer :: val
         555             :
         556 12767931338 :     val = self%nspecies_(bin_ndx)
         557 12767931338 :   end function nspecies_per_bin
         558             :
         559             :   !------------------------------------------------------------------------------
         560             :   ! returns number of species for all bins
         561             :   !------------------------------------------------------------------------------
         562        3072 :   pure function nspecies_all_bins(self) result(arr)
         563             :     class(aerosol_properties), intent(in) :: self
         564             :     integer :: arr(self%nbins_)
         565             :
         566       15360 :     arr(:) = self%nspecies_(:)
         567             :
         568        3072 :   end function nspecies_all_bins
         569             :
         570             :   !------------------------------------------------------------------------------
         571             :   ! returns number of species masses in a given bin number
         572             :   !------------------------------------------------------------------------------
         573  6192344848 :   pure function n_masses_per_bin(self,bin_ndx) result(val)
         574             :     class(aerosol_properties), intent(in) :: self
         575             :     integer, intent(in) :: bin_ndx           ! bin number
         576             :     integer :: val
         577             :
         578  6192344848 :     val = self%nmasses_(bin_ndx)
         579  6192344848 :   end function n_masses_per_bin
         580             :
         581             :   !------------------------------------------------------------------------------
         582             :   ! returns an array of number of species masses for all bins
         583             :   !------------------------------------------------------------------------------
         584        4608 :   pure function n_masses_all_bins(self) result(arr)
         585             :     class(aerosol_properties), intent(in) :: self
         586             :     integer :: arr(self%nbins_)
         587             :
         588       23040 :     arr(:) = self%nmasses_(:)
         589        4608 :   end function n_masses_all_bins
         590             :
         591             :   !------------------------------------------------------------------------------
         592             :   ! returns a single index for given bin and species
         593             :   !------------------------------------------------------------------------------
         594 35090384453 :   pure integer function indexer(self,bin_ndx,species_ndx)
         595             :     class(aerosol_properties), intent(in) :: self
         596             :     integer, intent(in) :: bin_ndx           ! bin number
         597             :     integer, intent(in) :: species_ndx       ! species number
         598             :
         599 35090384453 :     indexer = self%indexer_(bin_ndx,species_ndx)
         600 35090384453 :   end function indexer
         601             :
         602             :   !------------------------------------------------------------------------------
         603             :   ! returns the total number of bins
         604             :   !------------------------------------------------------------------------------
         605  6708844464 :   pure function nbins_0list(self) result(nbins)
         606             :     class(aerosol_properties), intent(in) :: self
         607             :     integer :: nbins
         608             :
         609  6708844464 :     nbins = self%nbins_
         610  6708844464 :   end function nbins_0list
         611             :
         612             :   !------------------------------------------------------------------------------
         613             :   ! returns number of constituents (or elements) totaled across all bins
         614             :   !------------------------------------------------------------------------------
         615     4475208 :   pure integer function ncnst_tot(self)
         616             :     class(aerosol_properties), intent(in) :: self
         617             :
         618     4475208 :     ncnst_tot = self%ncnst_tot_
         619     4475208 :   end function ncnst_tot
         620             :
         621             :   !------------------------------------------------------------------------------
         622             :   ! returns the natural log of geometric standard deviation of the number distribution for aerosol bin
         623             :   !------------------------------------------------------------------------------
         624  3371132784 :   pure real(r8) function alogsig_0list(self, bin_ndx)
         625             :     class(aerosol_properties), intent(in) :: self
         626             :     integer, intent(in) :: bin_ndx           ! bin number
         627             :
         628  3371132784 :     alogsig_0list = self%alogsig_(bin_ndx)
         629  3371132784 :   end function alogsig_0list
         630             :
         631             :   !------------------------------------------------------------------------------
         632             :   ! returns maximum supersaturation
         633             :   !------------------------------------------------------------------------------
         634   365272372 :   function maxsat(self, zeta,eta,smc) result(smax)
         635             :
         636             :     !-------------------------------------------------------------------------
         637             :     ! Calculates maximum supersaturation for multiple competing aerosols.
         638             :     !
         639             :     ! Abdul-Razzak and Ghan, A parameterization of aerosol activation.
         640             :     ! 2. Multiple aerosol types. J. Geophys. Res., 105, 6837-6844., 2000
         641             :     !-------------------------------------------------------------------------
         642             :
         643             :     class(aerosol_properties), intent(in) :: self
         644             :     real(r8), intent(in)  :: zeta(self%nbins_) ! Abdul-Razzak and Ghan eq 10
         645             :     real(r8), intent(in)  :: eta(self%nbins_)  ! Abdul-Razzak and Ghan eq 11
         646             :     real(r8), intent(in)  :: smc(self%nbins_)  ! critical supersaturation
         647             :
         648             :     real(r8) :: smax ! maximum supersaturation
         649             :
         650             :     integer  :: m
         651             :     integer  :: nbins
         652             :     real(r8) :: sum, g1, g2, g1sqrt, g2sqrt
         653             :
         654             :     real(r8), parameter :: small_maxsat = 1.e-20_r8 ! for weak forcing
         655             :     real(r8), parameter :: large_maxsat = 1.e20_r8  ! for small eta
         656             :
         657   365272372 :     smax=0.0_r8
         658   365272372 :     nbins = self%nbins_
         659             :
         660   365272372 :     check_loop: do m=1,nbins
         661   365272372 :        if((zeta(m) > 1.e5_r8*eta(m)) .or. (smc(m)*smc(m) > 1.e5_r8*eta(m))) then
         662             :           ! weak forcing -- essentially none activated
         663           0 :           smax=small_maxsat
         664             :        else
         665             :           ! significant activation of this mode -- calc activation all modes
         666             :           exit check_loop
         667             :        endif
         668             :        ! No significant activation in any mode.  Do nothing.
         669   365272372 :        if (m == nbins) return
         670             :     enddo check_loop
         671             :
         672             :     sum=0.0_r8
         673             :
         674  1826361860 :     do m=1,nbins
         675  1826361860 :        if(eta(m) > 1.e-20_r8)then
         676             :           ! from Abdul-Razzak and Ghan 2000
         677  1461089488 :           g1=zeta(m)/eta(m)
         678  1461089488 :           g1sqrt=sqrt(g1)
         679  1461089488 :           g1=g1sqrt*g1
         680  1461089488 :           g2=smc(m)/sqrt(eta(m)+3._r8*zeta(m))
         681  1461089488 :           g2sqrt=sqrt(g2)
         682  1461089488 :           g2=g2sqrt*g2
         683  1461089488 :           sum=sum+(self%f1_(m)*g1+self%f2_(m)*g2)/(smc(m)*smc(m))
         684             :        else
         685             :           sum=large_maxsat
         686             :        endif
         687             :     enddo
         688             :
         689   365272372 :     smax=1._r8/sqrt(sum)
         690             :
         691   365272372 :   end function maxsat
         692             :
         693             :   !------------------------------------------------------------------------------
         694             :   ! returns the ratio of SOA Hygroscopicity / Sulfate Hygroscopicity
         695             :   !------------------------------------------------------------------------------
         696     8935056 :   pure real(r8) function soa_equivso4_factor(self)
         697             :     class(aerosol_properties), intent(in) :: self
         698             :
         699     8935056 :     soa_equivso4_factor = self%soa_equivso4_factor_
         700             :
         701     8935056 :   end function soa_equivso4_factor
         702             :
         703             :   !------------------------------------------------------------------------------
         704             :   ! returns the ratio of POM Hygroscopicity / Sulfate Hygroscopicity
         705             :   !------------------------------------------------------------------------------
         706    13402584 :   pure real(r8) function pom_equivso4_factor(self)
         707             :     class(aerosol_properties), intent(in) :: self
         708             :
         709    13402584 :     pom_equivso4_factor = self%pom_equivso4_factor_
         710             :
         711    13402584 :   end function pom_equivso4_factor
         712             :
         713           0 : end module aerosol_properties_mod

Generated by: LCOV version 1.14