LCOV - code coverage report
Current view: top level - chemistry/carma_aero - aero_model.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 304 333 91.3 %
Date: 2025-03-14 01:33:33 Functions: 12 13 92.3 %

          Line data    Source code
       1             : !===============================================================================
       2             : ! CAMRA Aerosol Model
       3             : !===============================================================================
       4             : module aero_model
       5             :   use physics_buffer,    only: physics_buffer_desc, pbuf_get_index, pbuf_add_field, dtype_r8
       6             :   use shr_kind_mod,      only: r8 => shr_kind_r8
       7             :   use constituents,      only: pcnst, cnst_name, cnst_get_ind
       8             :   use perf_mod,          only: t_startf, t_stopf
       9             :   use ppgrid,            only: pcols, pver, pverp
      10             :   use phys_control,      only: phys_getopts, cam_physpkg_is
      11             :   use cam_abortutils,    only: endrun
      12             :   use cam_logfile,       only: iulog
      13             :   use physics_types,     only: physics_state, physics_ptend, physics_ptend_init
      14             :   use camsrfexch,        only: cam_in_t, cam_out_t
      15             :   use physics_buffer,    only: pbuf_get_field, pbuf_set_field, dtype_r8
      16             :   use physconst,         only: gravit, rair, rhoh2o
      17             :   use spmd_utils,        only: masterproc
      18             :   use cam_history,       only: outfld
      19             :   use chem_mods,         only: gas_pcnst, adv_mass
      20             :   use mo_tracname,       only: solsym
      21             :   use infnan,            only: nan, assignment(=)
      22             :   use rad_constituents,  only: rad_cnst_get_info, rad_cnst_get_info_by_bin, &
      23             :                                rad_cnst_get_info_by_bin_spec, rad_cnst_get_bin_props_by_idx, &
      24             :                                rad_cnst_get_bin_mmr_by_idx
      25             :   use mo_setsox,         only: setsox, has_sox
      26             :   use carma_aerosol_properties_mod, only: carma_aerosol_properties
      27             : 
      28             :   use carma_intr, only: carma_get_group_by_name, carma_get_dry_radius, carma_get_wet_radius, carma_get_bin_rmass
      29             :   use carma_intr, only: carma_get_sad
      30             : 
      31             :   use aerosol_properties_mod, only: aero_name_len
      32             : 
      33             :   implicit none
      34             :   private
      35             : 
      36             :   public :: aero_model_readnl
      37             :   public :: aero_model_register
      38             :   public :: aero_model_init
      39             :   public :: aero_model_gasaerexch ! create, grow, change, and shrink aerosols.
      40             :   public :: aero_model_drydep     ! aerosol dry deposition and sediment
      41             :   public :: aero_model_wetdep     ! aerosol wet removal
      42             :   public :: aero_model_emissions  ! aerosol emissions
      43             :   public :: aero_model_surfarea    ! tropospheric aerosol wet surface area for chemistry
      44             :   public :: aero_model_strat_surfarea   ! stub
      45             : 
      46             :    ! Misc private data
      47             :   character(len=32), allocatable :: fieldname(:)    ! names for interstitial output fields
      48             :   character(len=32), allocatable :: fieldname_cw(:)    ! names for cloud_borne output fields
      49             : 
      50             :   integer :: fracis_idx          = 0
      51             :   integer :: prain_idx           = 0
      52             :   integer :: rprddp_idx          = 0
      53             :   integer :: rprdsh_idx          = 0
      54             :   integer :: nevapr_shcu_idx     = 0
      55             :   integer :: nevapr_dpcu_idx     = 0
      56             :   integer :: nh3_ndx    = 0
      57             :   integer :: nh4_ndx    = 0
      58             :   integer :: h2so4_ndx  = 0
      59             : 
      60             :   ! variables for table lookup of aerosol impaction/interception scavenging rates
      61             :   integer, parameter :: nimptblgrow_mind=-7, nimptblgrow_maxd=12
      62             : 
      63             : 
      64             :   ! description of bin aerosols
      65             :   integer, public, protected :: nspec_max = 0
      66             :   integer, public, protected :: nbins = 0
      67             :   integer, public, protected, allocatable :: nspec(:)
      68             : 
      69             :   ! local indexing for bins
      70             :   integer, allocatable :: bin_idx(:,:) ! table for local indexing of modal aero number and mmr
      71             :   integer :: ncnst_tot                  ! total number of mode number conc + mode species
      72             :   integer :: ncnst_extd                  ! twiece total number of mode number conc + mode species
      73             : 
      74             :   ! Indices for CARMA species in the ptend%q array.  Needed for prognostic aerosol case.
      75             :   logical, allocatable :: bin_cnst_lq(:,:)
      76             :   integer, allocatable :: bin_cnst_idx(:,:)
      77             : 
      78             : 
      79             :   ! ptr2d_t is used to create arrays of pointers to 2D fields
      80             :   type ptr2d_t
      81             :     real(r8), pointer :: fld(:,:) => null()
      82             :   end type ptr2d_t
      83             : 
      84             :   logical :: lq(pcnst) = .false. ! set flags true for constituents with non-zero tendencies
      85             :                                  ! in the ptend object
      86             : 
      87             :   ! Namelist variables
      88             :   real(r8)          :: sol_facti_cloud_borne   = 1._r8
      89             :   real(r8)          :: sol_factb_interstitial  = 0.1_r8
      90             :   real(r8)          :: sol_factic_interstitial = 0.4_r8
      91             : 
      92             :   logical :: convproc_do_aer
      93             : 
      94             :   type(carma_aerosol_properties), pointer :: aero_props =>null()
      95             : 
      96             : contains
      97             : 
      98             :   !=============================================================================
      99             :   ! reads aerosol namelist options
     100             :   !=============================================================================
     101        1536 :   subroutine aero_model_readnl(nlfile)
     102             : 
     103             :     use namelist_utils,  only: find_group_name
     104             :     use units,           only: getunit, freeunit
     105             :     use aero_wetdep_cam, only: aero_wetdep_readnl
     106             :     use mpishorthand
     107             : 
     108             :     character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
     109             : 
     110             :     ! Local variables
     111             :     integer :: unitn, ierr
     112             :     character(len=*), parameter :: subname = 'aero_model_readnl'
     113             : 
     114             :     ! Namelist variables
     115             :     namelist /aerosol_nl/ sol_facti_cloud_borne, sol_factb_interstitial, sol_factic_interstitial
     116             : 
     117             :     !-----------------------------------------------------------------------------
     118             : 
     119             :     ! Read namelist
     120        1536 :     if (masterproc) then
     121           2 :        unitn = getunit()
     122           2 :        open( unitn, file=trim(nlfile), status='old' )
     123           2 :        call find_group_name(unitn, 'aerosol_nl', status=ierr)
     124           2 :        if (ierr == 0) then
     125           0 :           read(unitn, aerosol_nl, iostat=ierr)
     126           0 :           if (ierr /= 0) then
     127           0 :              call endrun(subname // ':: ERROR reading namelist')
     128             :           end if
     129             :        end if
     130           2 :        close(unitn)
     131           2 :        call freeunit(unitn)
     132             :     end if
     133             : 
     134             : #ifdef SPMD
     135             :     ! Broadcast namelist variables
     136        1536 :     call mpibcast(sol_facti_cloud_borne, 1,                         mpir8,   0, mpicom)
     137        1536 :     call mpibcast(sol_factb_interstitial, 1,                        mpir8,   0, mpicom)
     138        1536 :     call mpibcast(sol_factic_interstitial, 1,                       mpir8,   0, mpicom)
     139             : #endif
     140             : 
     141        1536 :     call aero_wetdep_readnl(nlfile)
     142             : 
     143        1536 :   end subroutine aero_model_readnl
     144             : 
     145             :   !=============================================================================
     146             :   !=============================================================================
     147        1536 :   subroutine aero_model_register()
     148             : 
     149        1536 :     use carma_flags_mod,   only: carma_model
     150             : 
     151             :     integer :: m, l, i
     152             :     integer :: nsoa_vbs
     153             :     character(len=32) :: num_name
     154             :     character(len=32) :: num_name_cw
     155             :     character(len=32) :: spec_name_cw
     156             : 
     157             :     integer :: idx, ierr
     158             : 
     159        1536 :     call rad_cnst_get_info( 0, nbins=nbins)
     160        4608 :     allocate( nspec(nbins), stat=ierr )
     161        1536 :     if (ierr/=0) call endrun('aero_model_register: allocate error')
     162             : 
     163             :     ! add pbuf fields for interstitial (cloud borne) aerosols in CARMA
     164       62976 :     do m = 1, nbins
     165       61440 :        call rad_cnst_get_info_by_bin(0, m, num_name=num_name, num_name_cw=num_name_cw, nspec=nspec(m))
     166       61440 :        call pbuf_add_field(num_name,'global',dtype_r8,(/pcols,pver/), idx)
     167       61440 :        call pbuf_add_field(num_name_cw,'global',dtype_r8,(/pcols,pver/), idx)
     168      278016 :        do l = 1, nspec(m)
     169      215040 :           call rad_cnst_get_info_by_bin_spec(0, m, l, spec_name_cw=spec_name_cw)
     170      276480 :           call pbuf_add_field(spec_name_cw,'global',dtype_r8,(/pcols,pver/),idx)
     171             :        enddo
     172             :     enddo
     173             : 
     174             :   ! SOA information
     175             :   ! Define number of VBS bins (nsoa) based on number of SOAG chemistry species
     176        1536 :     nsoa_vbs = 0
     177      336384 :     do i = 1, pcnst
     178      336384 :        if (cnst_name(i)(:4) == 'SOAG') then
     179        1536 :           nsoa_vbs = nsoa_vbs + 1
     180             :        end if
     181             :     end do
     182        1536 :     if (masterproc) then
     183           2 :        write(iulog,*) 'nsoa_vbs  = ', nsoa_vbs
     184             :     endif
     185             : 
     186             :    ! Define pbuf field for soa_fraction
     187        7680 :     call pbuf_add_field('FRACVBS','global',dtype_r8,(/pcols,pver,nbins,nsoa_vbs/), idx)
     188             : 
     189        1536 :   end subroutine aero_model_register
     190             : 
     191             :   !=============================================================================
     192             :   !=============================================================================
     193        1536 :   subroutine aero_model_init( pbuf2d )
     194             : 
     195             :     use mo_chem_utls,    only: get_inv_ndx
     196             :     use cam_history,     only: addfld, add_default, horiz_only
     197             :     use mo_chem_utls,    only: get_rxt_ndx, get_spc_ndx
     198             :     use aero_wetdep_cam, only: aero_wetdep_init
     199             :     use mo_setsox,       only: sox_inti
     200             :     use carma_aero_gasaerexch, only: carma_aero_gasaerexch_init
     201             : 
     202             :     use time_manager,    only: is_first_step
     203             :     use constituents,    only: cnst_set_convtran2
     204             :     use aero_deposition_cam, only: aero_deposition_cam_init
     205             : 
     206             :     ! args
     207             :     type(physics_buffer_desc), pointer :: pbuf2d(:,:)
     208             : 
     209             : 
     210             :     ! local vars
     211             :     character(len=*), parameter :: subrname = 'aero_model_init'
     212             :     integer :: m, n, ii, mm
     213             :     integer :: idxtmp    = -1
     214             : 
     215             :     logical  :: history_aerosol ! Output MAM or SECT aerosol tendencies
     216             :     logical  :: history_chemistry, history_cesm_forcing
     217             : 
     218             :     integer :: l
     219             : 
     220             :     character(len=2)  :: unit_basename  ! Units 'kg' or '1'
     221             :     character(len=32) :: num_name
     222             :     character(len=32) :: num_name_cw
     223             :     character(len=32) :: spec_name_cw
     224             : 
     225             :     integer :: idx, ierr
     226             :     real(r8) :: nanval
     227             : 
     228        1536 :     aero_props => carma_aerosol_properties()
     229        1536 :     call aero_deposition_cam_init(aero_props)
     230             : 
     231        1536 :     if (is_first_step()) then
     232       31488 :        do m = 1, nbins
     233       30720 :           call rad_cnst_get_info_by_bin(0, m, num_name=num_name, num_name_cw=num_name_cw)
     234       30720 :           idx = pbuf_get_index(num_name)
     235       30720 :           call pbuf_set_field(pbuf2d, idx, 0.0_r8)
     236       30720 :           idx = pbuf_get_index(num_name_cw)
     237       30720 :           call pbuf_set_field(pbuf2d, idx, 0.0_r8)
     238      139008 :           do l = 1, nspec(m)
     239      107520 :              call rad_cnst_get_info_by_bin_spec(0, m, l, spec_name_cw=spec_name_cw)
     240      107520 :              idx = pbuf_get_index(spec_name_cw)
     241      138240 :              call pbuf_set_field(pbuf2d, idx, 0.0_r8)
     242             :           enddo
     243             :        enddo
     244             :     endif
     245             : 
     246             :     ! define pbuf field for soa_fraction
     247        1536 :     if (is_first_step()) then
     248         768 :        nanval = nan
     249         768 :        idx = pbuf_get_index('FRACVBS')
     250         768 :        call pbuf_set_field(pbuf2d, idx, nanval)
     251             :     end if
     252             : 
     253             :     ! aqueous chem initialization
     254        1536 :     call sox_inti()
     255             : 
     256        1536 :     h2so4_ndx = get_spc_ndx('H2SO4')
     257        1536 :     nh3_ndx = get_spc_ndx('NH3')
     258        1536 :     nh4_ndx = get_spc_ndx('NH4')
     259             : 
     260        1536 :     fracis_idx      = pbuf_get_index('FRACIS')
     261        1536 :     prain_idx       = pbuf_get_index('PRAIN')
     262        1536 :     rprddp_idx      = pbuf_get_index('RPRDDP')
     263        1536 :     rprdsh_idx      = pbuf_get_index('RPRDSH')
     264        1536 :     nevapr_shcu_idx = pbuf_get_index('NEVAPR_SHCU')
     265        1536 :     nevapr_dpcu_idx = pbuf_get_index('NEVAPR_DPCU')
     266             : 
     267             :     call phys_getopts(history_aerosol_out = history_aerosol, &
     268             :                       history_chemistry_out=history_chemistry, &
     269             :                       history_cesm_forcing_out=history_cesm_forcing, &
     270        1536 :                       convproc_do_aer_out = convproc_do_aer)
     271             : 
     272        1536 :     call carma_aero_gasaerexch_init
     273             : 
     274       62976 :     nspec_max = maxval(nspec)
     275             : 
     276        1536 :     ncnst_tot = nspec(1)
     277       61440 :     do m = 2, nbins
     278       61440 :       ncnst_tot = ncnst_tot + nspec(m)
     279             :     end do
     280        1536 :     ncnst_extd = 2*ncnst_tot
     281             : 
     282             :     allocate( &
     283             :       bin_idx(nbins,nspec_max),      &
     284             :       bin_cnst_lq(nbins,nspec_max), &
     285             :       bin_cnst_idx(nbins,nspec_max), &
     286             :       fieldname_cw(ncnst_tot), &
     287       16896 :       fieldname(ncnst_tot), stat=ierr  )
     288        1536 :     if (ierr/=0) call endrun(subrname//' : allocate error')
     289             : 
     290        1536 :     ii = 0
     291       62976 :     do m = 1, nbins
     292      278016 :       do l = 1, nspec(m) ! loop through species
     293      215040 :          ii = ii + 1
     294      215040 :          bin_idx(m,l) = ii
     295             : 
     296      215040 :          if (l <= nspec(m) ) then   ! species
     297      215040 :             call rad_cnst_get_info_by_bin_spec(0, m, l, spec_name=fieldname(ii), spec_name_cw=fieldname_cw(ii))
     298             :          else  !number
     299           0 :             call rad_cnst_get_info_by_bin(0, m, num_name=fieldname(ii), num_name_cw=fieldname_cw(ii))
     300             :          end if
     301             : 
     302      215040 :          call cnst_get_ind(fieldname(ii), idxtmp, abort=.false.)
     303      215040 :           if (idxtmp.gt.0) then
     304      215040 :              bin_cnst_lq(m,l) = .true.
     305      215040 :              bin_cnst_idx(m,l) = idxtmp
     306      215040 :              lq(idxtmp) = .true.
     307      215040 :              call cnst_set_convtran2(idxtmp, .not.convproc_do_aer)
     308             :           else
     309           0 :              bin_cnst_lq(m,l) = .false.
     310           0 :              bin_cnst_idx(m,l) = 0
     311             :           end if
     312             : 
     313      215040 :          mm = ii
     314             : 
     315      215040 :          unit_basename = 'kg'
     316      215040 :          if (l == nspec(m) + 2) then   ! number
     317           0 :           unit_basename = ' 1'
     318             :          end if
     319             : 
     320             : 
     321           0 :           call addfld( fieldname_cw(mm),                (/ 'lev' /), 'A', unit_basename//'/kg ',   &
     322      430080 :                trim(fieldname_cw(mm))//' in cloud water')
     323           0 :           call addfld (trim(fieldname_cw(mm))//'DDF',   horiz_only,  'A', unit_basename//'/m2/s ', &
     324      215040 :                trim(fieldname_cw(mm))//' dry deposition flux at bottom (grav + turb)')
     325           0 :           call addfld (trim(fieldname_cw(mm))//'TBF',   horiz_only,  'A', unit_basename//'/m2/s ', &
     326      215040 :                trim(fieldname_cw(mm))//' turbulent dry deposition flux')
     327           0 :           call addfld (trim(fieldname_cw(mm))//'GVF',   horiz_only,  'A', unit_basename//'/m2/s ', &
     328      215040 :                trim(fieldname_cw(mm))//' gravitational dry deposition flux')
     329             : 
     330      215040 :           if ( history_aerosol.or. history_chemistry ) then
     331           0 :              call add_default( fieldname_cw(mm), 1, ' ' )
     332             :           endif
     333      276480 :           if ( history_aerosol ) then
     334           0 :              call add_default (trim(fieldname_cw(mm))//'GVF', 1, ' ')
     335           0 :              call add_default (trim(fieldname_cw(mm))//'TBF', 1, ' ')
     336           0 :              call add_default (trim(fieldname_cw(mm))//'DDF', 1, ' ')
     337             :           endif
     338             :        enddo
     339             :     enddo
     340             : 
     341      125952 :     do m = 1,gas_pcnst
     342             : 
     343      124416 :        unit_basename = 'kg'  ! Units 'kg' or '1'
     344             : 
     345      124416 :        call addfld( 'GS_'//trim(solsym(m)),horiz_only, 'A', unit_basename//'/m2/s ', &
     346      248832 :                     trim(solsym(m))//' gas chemistry/wet removal (for gas species)')
     347      124416 :        call addfld( 'AQ_'//trim(solsym(m)),horiz_only, 'A', unit_basename//'/m2/s ', &
     348      248832 :                     trim(solsym(m))//' aqueous chemistry (for gas species)')
     349      125952 :        if ( history_aerosol ) then
     350           0 :           call add_default( 'AQ_'//trim(solsym(m)), 1, ' ')
     351             :        endif
     352             : 
     353             :     enddo
     354             : 
     355        1536 :     if (has_sox) then
     356       62976 :        do n = 1, nbins
     357      278016 :           do l = 1, nspec(n)   ! not for total mass or number
     358      215040 :              mm = bin_idx(n, l)
     359             :              call addfld (&
     360           0 :                   trim(fieldname_cw(mm))//'AQSO4',horiz_only,  'A','kg/m2/s', &
     361      215040 :                   trim(fieldname_cw(mm))//' aqueous phase chemistry')
     362             :              call addfld (&
     363           0 :                   trim(fieldname_cw(mm))//'AQH2SO4',horiz_only,  'A','kg/m2/s', &
     364      215040 :                   trim(fieldname_cw(mm))//' aqueous phase chemistry')
     365      276480 :              if ( history_aerosol ) then
     366           0 :                 call add_default (trim(fieldname_cw(mm))//'AQSO4', 1, ' ')
     367           0 :                 call add_default (trim(fieldname_cw(mm))//'AQH2SO4', 1, ' ')
     368             :              endif
     369             :           end do
     370             :        end do
     371             : 
     372        3072 :        call addfld( 'XPH_LWC',    (/ 'lev' /), 'A','kg/kg',   'pH value multiplied by lwc')
     373        1536 :        call addfld ('AQSO4_H2O2', horiz_only,  'A','kg/m2/s', 'SO4 aqueous phase chemistry due to H2O2')
     374        1536 :        call addfld ('AQSO4_O3',   horiz_only,  'A','kg/m2/s', 'SO4 aqueous phase chemistry due to O3')
     375             : 
     376        1536 :        if ( history_aerosol ) then
     377           0 :           call add_default ('XPH_LWC', 1, ' ')
     378           0 :           call add_default ('AQSO4_H2O2', 1, ' ')
     379           0 :           call add_default ('AQSO4_O3', 1, ' ')
     380             :        endif
     381             :     endif
     382             : 
     383        1536 :     call aero_wetdep_init()
     384             : 
     385        3072 :   end subroutine aero_model_init
     386             : 
     387             :   !=============================================================================
     388             :   !=============================================================================
     389    15978240 :   subroutine aero_model_drydep  ( state, pbuf, obklen, ustar, cam_in, dt, cam_out, ptend )
     390             : 
     391             :     ! args
     392             :     type(physics_state),    intent(in)    :: state     ! Physics state variables
     393             :     real(r8),               intent(in)    :: obklen(:)
     394             :     real(r8),               intent(in)    :: ustar(:)  ! sfc fric vel
     395             :     type(cam_in_t), target, intent(in)    :: cam_in    ! import state
     396             :     real(r8),               intent(in)    :: dt        ! time step
     397             :     type(cam_out_t),        intent(inout) :: cam_out   ! export state
     398             :     type(physics_ptend),    intent(out)   :: ptend     ! indivdual parameterization tendencies
     399             :     type(physics_buffer_desc),    pointer :: pbuf(:)
     400             : 
     401        1536 :   endsubroutine aero_model_drydep
     402             : 
     403             :   !=============================================================================
     404             :   !=============================================================================
     405    17660160 :   subroutine aero_model_wetdep( state, dt, dlf, cam_out, ptend, pbuf)
     406             : 
     407             :     use aero_wetdep_cam, only: aero_wetdep_tend
     408             : 
     409             :     ! args
     410             : 
     411             :     type(physics_state), intent(in)    :: state       ! Physics state variables
     412             :     real(r8),            intent(in)    :: dt          ! time step
     413             :     real(r8),            intent(in)    :: dlf(:,:)    ! shallow+deep convective detrainment [kg/kg/s]
     414             :     type(cam_out_t),     intent(inout) :: cam_out     ! export state
     415             :     type(physics_ptend), intent(out)   :: ptend       ! indivdual parameterization tendencies
     416             :     type(physics_buffer_desc), pointer :: pbuf(:)
     417             : 
     418       80640 :     call aero_wetdep_tend(state, dt, dlf, cam_out, ptend, pbuf)
     419             : 
     420       80640 :   end subroutine aero_model_wetdep
     421             : 
     422             :   !-------------------------------------------------------------------------
     423             :   ! provides wet tropospheric aerosol surface area info for sectional aerosols
     424             :   ! called from mo_usrrxt
     425             :   !-------------------------------------------------------------------------
     426       72960 :   subroutine aero_model_surfarea( &
     427       72960 :                   state, mmr, radmean, relhum, pmid, temp, strato_sad, sulfate,  m, ltrop, &
     428       72960 :                   dlat, het1_ndx, pbuf, ncol, sfc, dm_aer, sad_trop, reff_trop )
     429             : 
     430             :     ! dummy args
     431             :     type(physics_state), intent(in) :: state           ! Physics state variables
     432             :     real(r8), intent(in)    :: pmid(:,:)
     433             :     real(r8), intent(in)    :: temp(:,:)
     434             :     real(r8), intent(in)    :: mmr(:,:,:)
     435             :     real(r8), intent(in)    :: radmean      ! mean radii in cm
     436             :     real(r8), intent(in)    :: strato_sad(:,:)
     437             :     integer,  intent(in)    :: ncol
     438             :     integer,  intent(in)    :: ltrop(:)
     439             :     real(r8), intent(in)    :: dlat(:)                    ! degrees latitude
     440             :     integer,  intent(in)    :: het1_ndx
     441             :     real(r8), intent(in)    :: relhum(:,:)
     442             :     real(r8), intent(in)    :: m(:,:) ! total atm density (/cm^3)
     443             :     real(r8), intent(in)    :: sulfate(:,:)
     444             :     type(physics_buffer_desc), pointer :: pbuf(:)
     445             : 
     446             :     real(r8), intent(inout) :: sfc(:,:,:)
     447             :     real(r8), intent(inout) :: dm_aer(:,:,:)
     448             :     real(r8), intent(inout) :: sad_trop(:,:)  ! aerosol surface area density (cm2/cm3), zeroed above the tropopause
     449             :     real(r8), intent(out)   :: reff_trop(:,:) ! aerosol effective radius (cm), zeroed above the tropopause
     450             : 
     451             :     ! local vars
     452      145920 :     integer :: beglev(ncol)
     453      145920 :     integer :: endlev(ncol)
     454             : 
     455     1196544 :     beglev(:ncol)=ltrop(:ncol)+1
     456     1123584 :     endlev(:ncol)=pver
     457       72960 :     call surf_area_dens( state, pbuf, ncol, mmr, beglev, endlev, sad_trop, reff_trop, sfc=sfc, dm_aer=dm_aer )
     458             : 
     459       80640 :   end subroutine aero_model_surfarea
     460             : 
     461             :   !-------------------------------------------------------------------------
     462             :   ! provides wet stratospheric aerosol surface area info for sectional aerosols
     463             :   ! called from mo_gas_phase_chemdr.F90
     464             :   !-------------------------------------------------------------------------
     465       72960 :   subroutine aero_model_strat_surfarea( state, ncol, mmr, pmid, temp, ltrop, pbuf, strato_sad, reff_strat )
     466             : 
     467             :     use ref_pres, only: clim_modal_aero_top_lev
     468             : 
     469             :     ! dummy args
     470             :     type(physics_state), intent(in) :: state           ! Physics state variables
     471             :     integer,  intent(in)    :: ncol
     472             :     real(r8), intent(in)    :: mmr(:,:,:)
     473             :     real(r8), intent(in)    :: pmid(:,:)
     474             :     real(r8), intent(in)    :: temp(:,:)
     475             :     integer,  intent(in)    :: ltrop(:) ! tropopause level indices
     476             :     type(physics_buffer_desc), pointer :: pbuf(:)
     477             :     real(r8), intent(out)   :: strato_sad(:,:) ! aerosol surface area density (cm2/cm3), zeroed below the tropopause
     478             :     real(r8), intent(out)   :: reff_strat(:,:) ! aerosol effective radius (cm), zeroed below the tropopause
     479             : 
     480             :     ! local vars
     481      145920 :     integer :: beglev(ncol)
     482      145920 :     integer :: endlev(ncol)
     483             : 
     484     1123584 :     beglev(:ncol) = clim_modal_aero_top_lev
     485     1196544 :     endlev(:ncol) = ltrop(:ncol)
     486             : 
     487       72960 :     call surf_area_dens( state, pbuf, ncol, mmr, beglev, endlev, strato_sad, reff_strat )
     488             : 
     489       72960 :   end subroutine aero_model_strat_surfarea
     490             : 
     491             :   !=============================================================================
     492             :   !=============================================================================
     493      218880 :   subroutine aero_model_gasaerexch( state, loffset, ncol, lchnk, troplev, delt, reaction_rates, &
     494       72960 :                                     tfld, pmid, pdel, mbar, relhum, &
     495      145920 :                                     zm,  qh2o, cwat, cldfr, cldnum, &
     496       72960 :                                     airdens, invariants, del_h2so4_gasprod,  &
     497       72960 :                                     vmr0, vmr, pbuf )
     498             : 
     499       72960 :     use carma_aero_gasaerexch, only : carma_aero_gasaerexch_sub
     500             :     use time_manager,          only : get_nstep
     501             :     !-----------------------------------------------------------------------
     502             :     !      ... dummy arguments
     503             :     !-----------------------------------------------------------------------
     504             :     type(physics_state), intent(in)    :: state    ! Physics state variables
     505             :     integer,  intent(in) :: loffset                ! offset applied to modal aero "pointers"
     506             :     integer,  intent(in) :: ncol                   ! number columns in chunk
     507             :     integer,  intent(in) :: lchnk                  ! chunk index
     508             :     integer,  intent(in) :: troplev(:)
     509             :     real(r8), intent(in) :: delt                   ! time step size (sec)
     510             :     real(r8), intent(in) :: reaction_rates(:,:,:)  ! reaction rates
     511             :     real(r8), intent(in) :: tfld(:,:)              ! temperature (K)
     512             :     real(r8), intent(in) :: pmid(:,:)              ! pressure at model levels (Pa)
     513             :     real(r8), intent(in) :: pdel(:,:)              ! pressure thickness of levels (Pa)
     514             :     real(r8), intent(in) :: mbar(:,:)              ! mean wet atmospheric mass ( amu )
     515             :     real(r8), intent(in) :: relhum(:,:)            ! relative humidity
     516             :     real(r8), intent(in) :: airdens(:,:)           ! total atms density (molec/cm**3)
     517             :     real(r8), intent(in) :: invariants(:,:,:)
     518             :     real(r8), intent(in) :: del_h2so4_gasprod(:,:)
     519             :     real(r8), intent(in) :: zm(:,:)
     520             :     real(r8), intent(in) :: qh2o(:,:)
     521             :     real(r8), intent(in) :: cwat(:,:)          ! cloud liquid water content (kg/kg)
     522             :     real(r8), intent(in) :: cldfr(:,:)
     523             :     real(r8), intent(in) :: cldnum(:,:)       ! droplet number concentration (#/kg)
     524             :     real(r8), intent(in) :: vmr0(:,:,:)       ! initial mixing ratios (before gas-phase chem changes)
     525             :     real(r8), intent(inout) :: vmr(:,:,:)         ! mixing ratios ( vmr )
     526             : 
     527             :     type(physics_buffer_desc), pointer :: pbuf(:)
     528             : 
     529             :     ! local vars
     530             : 
     531             :     integer :: n, m, mm
     532             :     integer :: i,k,l
     533             :     integer :: nstep
     534             : 
     535       72960 :     type(ptr2d_t), allocatable :: raer(:)     ! aerosol mass, number mixing ratios
     536       72960 :     type(ptr2d_t), allocatable :: qqcw(:)
     537             : 
     538      145920 :     real(r8) :: del_h2so4_aeruptk(ncol,pver)
     539             : 
     540             :     real(r8), pointer :: pblh(:)                    ! pbl height (m)
     541             : 
     542      145920 :     real(r8), dimension(ncol) :: wrk
     543             :     character(len=32)         :: name
     544      145920 :     real(r8) :: dvmrcwdt(ncol,pver,ncnst_tot)
     545      145920 :     real(r8) :: dvmrdt(ncol,pver,gas_pcnst)
     546      145920 :     real(r8) :: delta_so4mass(ncol,pver,ncnst_tot)
     547      145920 :     real(r8) :: wetr_n(pcols,pver,nbins)       ! wet radius from CARMA for different bin
     548      145920 :     real(r8) :: vmrcw(ncol,pver,ncnst_tot)            ! cloud-borne aerosol (vmr)
     549      145920 :     real(r8) :: mmrcw(ncol,pver,ncnst_tot)            ! cloud-borne aerosol (mmr)
     550      145920 :     real(r8) :: raervmr(ncol,pver,ncnst_tot)            ! cloud-borne aerosol (vmr)
     551             : 
     552      145920 :     real(r8) ::  aqso4(ncol,ncnst_tot)               ! aqueous phase chemistry
     553      145920 :     real(r8) ::  aqh2so4(ncol,ncnst_tot)             ! aqueous phase chemistry
     554      145920 :     real(r8) ::  aqso4_h2o2(ncol)                     ! SO4 aqueous phase chemistry due to H2O2
     555      145920 :     real(r8) ::  aqso4_o3(ncol)                       ! SO4 aqueous phase chemistry due to O3
     556      145920 :     real(r8) ::  xphlwc(ncol,pver)                    ! pH value multiplied by lwc
     557      145920 :     real(r8) ::  nh3_beg(ncol,pver)
     558      145920 :     real(r8) ::  mw_carma(ncnst_tot)
     559             :     real(r8), pointer :: fldcw(:,:)
     560             :     real(r8), pointer :: sulfeq(:,:,:)
     561             :     real(r8) :: wetr(pcols,pver)   ! CARMA wet radius in cm
     562             :     real(r8) :: wetrho(pcols,pver)   ! CARMA wet dens
     563       72960 :     real(r8), allocatable :: rmass(:)     ! CARMA rmass
     564             : 
     565             :     real(r8) :: old_total_mass
     566             :     real(r8) :: new_total_mass
     567             :     real(r8) :: old_total_number
     568             : 
     569             :     character(len=32) :: spectype
     570             : 
     571             :     character(len=aero_name_len) :: bin_name, shortname
     572             :     integer :: igroup, ibin, rc, nchr, ierr
     573             :     character(len=*), parameter :: subname = 'aero_model_gasaerexch'
     574             : 
     575             : !
     576             : ! ... initialize nh3
     577             : !
     578       72960 :     if ( nh3_ndx > 0 ) then
     579           0 :       nh3_beg = vmr(1:ncol,:,nh3_ndx)
     580             :     end if
     581             : !
     582             : ! do gas-aerosol exchange (h2so4, msa, nh3 condensation)
     583             : 
     584       72960 :     nstep = get_nstep()
     585             : 
     586             :     ! calculate tendency due to gas phase chemistry and processes
     587  6376704000 :     dvmrdt(:ncol,:,:) = (vmr(:ncol,:,:) - vmr0(:ncol,:,:)) / delt
     588     5982720 :     do m = 1, gas_pcnst
     589    91010304 :       wrk(:) = 0.0_r8
     590   419592960 :       do k = 1,pver
     591  6376631040 :         wrk(:ncol) = wrk(:ncol) + dvmrdt(:ncol,k,m)*adv_mass(m)/mbar(:ncol,k)*pdel(:ncol,k)/gravit
     592             :       end do
     593     5909760 :       name = 'GS_'//trim(solsym(m))
     594     5982720 :       call outfld( name, wrk(:ncol), ncol, lchnk )
     595             :     enddo
     596             : 
     597             : !
     598             : ! Aerosol processes ...
     599             : !
     600             :     allocate( &
     601             :       rmass(nbins), &
     602             :       raer(ncnst_tot), &
     603    20866560 :       qqcw(ncnst_tot), stat=ierr )
     604       72960 :     if (ierr /= 0) call endrun(subname//': allocate error')
     605             : 
     606    10287360 :     mw_carma(:) = 0.0_r8
     607     2991360 :     do m = 1, nbins      ! main loop over aerosol bins
     608             :        ! dryr is the dry bin radius
     609             :        ! wetr is the dry bin radius
     610             :        ! Note: taken here from CARMA pbuf field which may be not any more consistent with changed fields after carma was applied
     611             :        ! Need to add new code that recalcuates dryr and wetr
     612             :        ! get bin info
     613     2918400 :        call rad_cnst_get_info_by_bin(0, m, nspec=nspec(m), bin_name=bin_name)
     614             : 
     615     2918400 :        nchr = len_trim(bin_name)-2
     616     2918400 :        shortname = bin_name(:nchr)
     617             : 
     618     2918400 :        call carma_get_group_by_name(shortname, igroup, rc)
     619     2918400 :        if (rc/=0) then
     620           0 :           call endrun(subname//': ERROR in carma_get_group_by_name')
     621             :        end if
     622             : 
     623     2918400 :        read(bin_name(nchr+1:),*) ibin
     624             : 
     625     2918400 :        call carma_get_wet_radius(state, igroup, ibin, wetr, wetrho, rc) ! m
     626     2918400 :        if (rc/=0) then
     627           0 :           call endrun(subname//': ERROR in carma_get_wet_radius')
     628             :        end if
     629  3148953600 :        wetr(:ncol,:) = wetr(:ncol,:) * 1.e2_r8 ! cm
     630             : 
     631     2918400 :        call carma_get_bin_rmass(igroup, ibin, rmass(m), rc) ! grams
     632     2918400 :        if (rc/=0) then
     633           0 :           call endrun(subname//': ERROR in carma_get_bin_rmass')
     634             :        end if
     635             : 
     636  3475814400 :        wetr_n(:,:,m) = wetr(:,:)
     637             : 
     638             :        ! Init pointers to mode number and specie mass mixing ratios in
     639             :        ! intersitial and cloud borne phases.
     640    19042560 :        do l = 1, nspec(m)
     641    10214400 :           mm = bin_idx(m, l)
     642    10214400 :           if (l <= nspec(m)) then
     643    10214400 :              call rad_cnst_get_bin_props_by_idx(0, m, l,spectype=spectype)
     644    10214400 :              call rad_cnst_get_bin_mmr_by_idx(0, m, l, 'a', state, pbuf, raer(mm)%fld)
     645    10214400 :              call rad_cnst_get_bin_mmr_by_idx(0, m, l, 'c', state, pbuf, qqcw(mm)%fld)  ! cloud-borne aerosol
     646    10214400 :              if (trim(spectype) == 'sulfate') then
     647     2918400 :                 mw_carma(mm) = 96._r8
     648             :              end if
     649    10214400 :              if (trim(spectype) == 'black-c') then
     650     1459200 :                 mw_carma(mm) = 12._r8
     651             :              end if
     652    10214400 :              if (trim(spectype) == 'p-organic') then
     653     1459200 :                 mw_carma(mm) = 12._r8
     654             :              end if
     655    10214400 :              if (trim(spectype) == 's-organic') then
     656     1459200 :                 mw_carma(mm) = 250._r8
     657             :              end if
     658    10214400 :              if (trim(spectype) == 'dust') then
     659     1459200 :                 mw_carma(mm) = 12._r8
     660             :              end if
     661    10214400 :              if (trim(spectype) == 'seasalt') then
     662     1459200 :                 mw_carma(mm) = 57._r8
     663             :              end if
     664             :           end if
     665 11021337600 :           mmrcw(:ncol,:,mm) = qqcw(mm)%fld(:ncol,:)
     666 11021337600 :           vmrcw(:ncol,:,mm) = qqcw(mm)%fld(:ncol,:)
     667 11024256000 :           raervmr(:ncol,:,mm) = raer(mm)%fld(:ncol,:)
     668             :        end do
     669             :     end do
     670             : 
     671             :     ! qqcw2vrm is different from what is done in MAM, here we pass in the fields set by the qqcw and raer pointer
     672             :     ! for all the CARMA aerosols, species, mmr, and number, vmrcw (kg/kg) -> vmr
     673       72960 :     call mmr2vmr_carma ( lchnk, vmrcw, mbar, mw_carma, ncol, loffset, rmass )
     674             : 
     675  6376704000 :     dvmrdt(:ncol,:,:) = vmr(:ncol,:,:)   ! all adveced species no aerosols
     676 11021410560 :     dvmrcwdt(:ncol,:,:) = vmrcw(:ncol,:,:)  ! cloud borne carma aerosol species
     677             :     ! aqueous chemistry ...
     678             : 
     679       72960 :     if( has_sox ) then
     680             :          call setsox( state,  &
     681             :               ncol,     &
     682             :               lchnk,    &
     683             :               loffset,  &
     684             :               delt,     &
     685             :               pmid,     &
     686             :               pdel,     &
     687             :               tfld,     &
     688             :               mbar,     &
     689             :               cwat,     &
     690             :               cldfr,    &
     691             :               cldnum,   &
     692             :               airdens,  &
     693             :               invariants, &
     694             :               vmrcw,    &
     695             :               vmr,      &
     696             :               xphlwc,   &
     697             :               aqso4,    &
     698             :               aqh2so4,  &
     699             :               aqso4_h2o2, &
     700             :               aqso4_o3  &
     701       72960 :               )
     702             : 
     703     2991360 :           do n = 1, nbins
     704    13205760 :             do l = 1, nspec(n)   ! not for total mass or number
     705    10214400 :                 mm = bin_idx(n, l)
     706    10214400 :                 call outfld( trim(fieldname_cw(mm))//'AQSO4',   aqso4(:ncol,mm),   ncol, lchnk)
     707    13132800 :                 call outfld( trim(fieldname_cw(mm))//'AQH2SO4', aqh2so4(:ncol,mm), ncol, lchnk)
     708             :              end do
     709             :           end do
     710             : 
     711       72960 :           call outfld( 'AQSO4_H2O2', aqso4_h2o2(:ncol), ncol, lchnk)
     712       72960 :           call outfld( 'AQSO4_O3',   aqso4_o3(:ncol),   ncol, lchnk)
     713       72960 :           call outfld( 'XPH_LWC',    xphlwc(:ncol,:),   ncol, lchnk )
     714             : 
     715             :     endif
     716             : 
     717             : !   Tendency due to aqueous chemistry
     718  6376704000 :     dvmrdt = (vmr - dvmrdt) / delt
     719 11021410560 :     dvmrcwdt = (vmrcw - dvmrcwdt) / delt
     720             : 
     721     5982720 :     do m = 1, gas_pcnst
     722    91010304 :        wrk(:) = 0.0_r8
     723   419592960 :        do k = 1,pver
     724  6376631040 :           wrk(:ncol) = wrk(:ncol) + dvmrdt(:ncol,k,m) * adv_mass(m)/mbar(:ncol,k)*pdel(:ncol,k)/gravit
     725             :        end do
     726     5909760 :        name = 'AQ_'//trim(solsym(m))
     727     5982720 :        call outfld( name, wrk(:ncol), ncol, lchnk )
     728             :     enddo
     729             : 
     730             : ! do gas-aerosol exchange (h2so4, msa, nh3 condensation)
     731             : 
     732       72960 :     if (h2so4_ndx > 0) then
     733    78723840 :        del_h2so4_aeruptk(1:ncol,:) = vmr(1:ncol,:,h2so4_ndx)
     734             :     else
     735           0 :        del_h2so4_aeruptk(:,:) = 0.0_r8
     736             :     endif
     737             : 
     738             :     ! need to transform raer to raervmr from CARMA, routine requires vmr, note number wil not be changed here
     739       72960 :     call mmr2vmr_carma ( lchnk, raervmr, mbar, mw_carma, ncol, loffset, rmass)
     740             : 
     741             :     call carma_aero_gasaerexch_sub( state, &
     742             :           pbuf, lchnk,    ncol,     nstep,      &
     743             :           loffset,            delt, mbar ,      &
     744             :           tfld,     pmid,     pdel,             &
     745             :           qh2o,               troplev,          &
     746             :           vmr,                raervmr,          &
     747       72960 :           wetr_n     )
     748             : 
     749             :     ! note vmr2qqcw does not change qqcw pointer (different than in MAM)
     750       72960 :     call vmr2mmr_carma ( lchnk, vmrcw, mbar, mw_carma, ncol, loffset, rmass )
     751             : 
     752             :     !vmrcw in kg/kg
     753             :     ! change pointer value for total mmr and number. In order to do this correctly
     754             :     ! only mass has to be added to each bin (not number). This will require redistributing
     755             :     ! mass to different bins. Here, we change both mass and number until we have a better
     756             :     ! solution.
     757 11021410560 :     delta_so4mass(:,:,:) = 0.0_r8
     758     2991360 :     do m = 1, nbins
     759    13205760 :        do l = 1, nspec(m)  ! for sulfate only
     760    10214400 :           mm = bin_idx(m, l)
     761             :          ! sulfate mass that needs to be added to the total mass
     762    10214400 :           call rad_cnst_get_bin_props_by_idx(0, m, l,spectype=spectype)
     763    13132800 :           if (trim(spectype) == 'sulfate') then
     764             :               ! only do loop if vmrcw has changed
     765   207206400 :               do k=1,pver
     766  3148953600 :                  do i=1,ncol
     767  3146035200 :                   if (vmrcw(i,k,mm) .gt. mmrcw(i,k,mm) .and. mmrcw(i,k,mm) /= 0.0_r8)  then
     768    44420676 :                    delta_so4mass(i,k,mm) = ( vmrcw(i,k,mm) - mmrcw(i,k,mm) )
     769             :                   else
     770  2897326524 :                     delta_so4mass(i,k,mm) = 0.0_r8
     771             :                   end if
     772             :                  end do
     773             :               end do
     774             :          end if
     775             :        end do
     776             :     end do
     777             : 
     778     2991360 :     do m = 1, nbins
     779    13205760 :        do l = 1, nspec(m) ! for sulfate only
     780    10214400 :           mm = bin_idx(m, l)
     781 11021337600 :           qqcw(mm)%fld(:ncol,:) = vmrcw(:ncol,:,mm)
     782 11024256000 :           call outfld( trim(fieldname_cw(mm)), qqcw(mm)%fld(:ncol,:), ncol, lchnk)
     783             :        end do
     784             :     end do
     785             : 
     786             : 
     787       72960 :   end subroutine aero_model_gasaerexch
     788             : 
     789             :   !=============================================================================
     790             :   !=============================================================================
     791       72960 :   subroutine aero_model_emissions( state, cam_in )
     792             : 
     793             :     ! Arguments:
     794             : 
     795             :     type(physics_state),    intent(in)    :: state   ! Physics state variables
     796             :     type(cam_in_t),         intent(inout) :: cam_in  ! import state
     797             : 
     798       72960 :   end subroutine aero_model_emissions
     799             : 
     800             : 
     801             :   !===============================================================================
     802             :   !===============================================================================
     803             :   ! private methods
     804             : 
     805             : 
     806             :   !=============================================================================
     807             :   !=============================================================================
     808      145920 :   subroutine surf_area_dens( state, pbuf, ncol, mmr, beglev, endlev, sad, reff, sfc, dm_aer )
     809             :     use mo_constants, only: pi
     810             :     use carma_intr,   only: carma_effecitive_radius
     811             : 
     812             :     ! dummy args
     813             :     type(physics_state),    intent(in) :: state           ! Physics state variables
     814             :     type(physics_buffer_desc), pointer :: pbuf(:)
     815             :     integer,  intent(in)  :: ncol
     816             :     real(r8), intent(in)  :: mmr(:,:,:)
     817             :     integer,  intent(in)  :: beglev(:)
     818             :     integer,  intent(in)  :: endlev(:)
     819             :     real(r8), intent(out) :: sad(:,:)    ! bulk surface area density in cm2/cm3 from beglev to endlev, zero elsewhere
     820             :     real(r8), intent(out) :: reff(:,:)   ! bulk effective radius in cm from beglev to endlev, zero elsewhere
     821             :     real(r8), optional, intent(out) :: sfc(:,:,:) ! surface area density per bin
     822             :     real(r8), optional, intent(out) :: dm_aer(:,:,:) ! diameter per bin
     823             : 
     824             :     ! local vars
     825             :     real(r8) :: reffaer(pcols,pver) ! bulk effective radius in cm
     826             : 
     827      291840 :     real(r8) :: sad_bin(pcols,pver,nbins)
     828             :     integer  :: icol, ilev, ibin, ispec !!, reff_pbf_ndx
     829             :     real(r8) :: chm_mass, tot_mass
     830             :     character(len=32) :: spectype
     831             :     real(r8) :: wetr(pcols,pver)      ! CARMA bin wet radius in cm
     832             :     real(r8) :: wetrho(pcols,pver)    ! CARMA bin wet density
     833             :     real(r8) :: sad_carma(pcols,pver) ! CARMA bin wet surface area density in cm2/cm3
     834      145920 :     real(r8), pointer :: aer_bin_mmr(:,:)
     835             : 
     836             :     character(len=aero_name_len) :: bin_name, shortname
     837             :     integer :: igroup, indxbin, rc, nchr
     838             : 
     839   173790720 :     sad = 0._r8
     840   173790720 :     reff = 0._r8
     841             : 
     842             :     !
     843             :     ! Compute surface aero for each bin.
     844             :     ! Total over all bins as the surface area for chemical reactions.
     845             :     !
     846             : 
     847      145920 :     reffaer = carma_effecitive_radius(state)
     848             : 
     849   173790720 :     sad = 0._r8
     850  6951774720 :     sad_bin = 0._r8
     851   173790720 :     reff = 0._r8
     852             : 
     853     5982720 :     do ibin=1,nbins ! loop over aerosol bins
     854     5836800 :       call rad_cnst_get_info_by_bin(0, ibin, bin_name=bin_name)
     855             : 
     856     5836800 :       nchr = len_trim(bin_name)-2
     857     5836800 :       shortname = bin_name(:nchr)
     858             : 
     859     5836800 :       call carma_get_group_by_name(shortname, igroup, rc)
     860             : 
     861     5836800 :       read(bin_name(nchr+1:),*) indxbin
     862             : 
     863     5836800 :       call carma_get_wet_radius(state, igroup, indxbin, wetr, wetrho, rc) ! m
     864  6297907200 :       wetr(:ncol,:) = wetr(:ncol,:) * 1.e2_r8 ! cm
     865     5836800 :       call carma_get_sad(state, igroup, indxbin, sad_carma, rc)
     866             : 
     867     5836800 :       if (present(dm_aer)) then
     868  3148953600 :          dm_aer(:ncol,:,ibin) = 2._r8 * wetr(:ncol,:) ! convert wet radius (cm) to wet diameter (cm)
     869             :       endif
     870  6309726720 :       sad_bin(:ncol,:,ibin) = sad_carma(:ncol,:) ! cm^2/cm^3
     871             :     end do
     872             : 
     873     2247168 :     do icol = 1,ncol
     874    75790848 :       do ilev = beglev(icol),endlev(icol)
     875  3015290880 :         do ibin=1,nbins ! loop over aerosol bins
     876             :           !
     877             :           ! compute a mass weighting of the number
     878             :           !
     879  2941747200 :           tot_mass = 0._r8
     880  2941747200 :           chm_mass = 0._r8
     881 13237862400 :           do ispec=1,nspec(ibin)
     882             : 
     883 10296115200 :              call rad_cnst_get_bin_mmr_by_idx(0, ibin, ispec, 'a', state, pbuf, aer_bin_mmr)
     884             : 
     885 10296115200 :              tot_mass = tot_mass + aer_bin_mmr(icol,ilev)
     886             : 
     887 10296115200 :              call rad_cnst_get_bin_props_by_idx(0, ibin, ispec, spectype=spectype)
     888             : 
     889             :              if ( trim(spectype) == 'sulfate'   .or. &
     890             :                 trim(spectype) == 's-organic' .or. &
     891             :                 trim(spectype) == 'p-organic' .or. &
     892 10296115200 :                 trim(spectype) == 'black-c'   .or. &
     893  2941747200 :                 trim(spectype) == 'ammonium') then
     894  7354368000 :                 chm_mass = chm_mass + aer_bin_mmr(icol,ilev)
     895             :              end if
     896             : 
     897             :           end do
     898  3015290880 :           if ( tot_mass > 0._r8 ) then
     899             :          ! surface area density
     900  2861412147 :             sad_bin(icol,ilev,ibin) = chm_mass / tot_mass * sad_bin(icol,ilev,ibin) ! cm^2/cm^3
     901             :           else
     902    80335053 :             sad_bin(icol,ilev,ibin) = 0._r8
     903             :           end if
     904             :         end do
     905  3015290880 :         sad(icol,ilev) = sum(sad_bin(icol,ilev,:))
     906    75644928 :         reff(icol,ilev) = reffaer(icol,ilev)
     907             : 
     908             :        end do
     909             :     end do
     910             : 
     911      145920 :     if (present(sfc)) then
     912  3475887360 :        sfc(:,:,:) = sad_bin(:,:,:)
     913             :     endif
     914             : 
     915      291840 :   end subroutine surf_area_dens
     916             : 
     917             :   !=============================================================================
     918      145920 :   subroutine mmr2vmr_carma(lchnk, vmr, mbar, mw_carma, ncol, im, rmass)
     919             :     !-----------------------------------------------------------------
     920             :     !   ... Xfrom from mass to volume mixing ratio
     921             :     !-----------------------------------------------------------------
     922             : 
     923             :     implicit none
     924             : 
     925             :     !-----------------------------------------------------------------
     926             :     !   ... Dummy args
     927             :     !-----------------------------------------------------------------
     928             :     integer, intent(in)     :: lchnk, ncol, im
     929             :     real(r8), intent(in)    :: mbar(ncol,pver)
     930             :     real(r8), intent(in)    :: rmass(nbins)
     931             :     real(r8), intent(in)    :: mw_carma(ncnst_tot)
     932             :     real(r8), intent(inout) :: vmr(ncol,pver,ncnst_tot)
     933             : 
     934             :     !-----------------------------------------------------------------
     935             :     !   ... Local variables
     936             :     !-----------------------------------------------------------------
     937             :     integer :: k, m, mm, l
     938             : 
     939     5982720 :     do m = 1, nbins
     940    26411520 :        do l = 1, nspec(m)   ! for each species, not total mmr or number, information of mw are missing
     941    20428800 :           mm = bin_idx(m, l)
     942  1456281600 :           do k=1,pver
     943 22042675200 :              vmr(:ncol,k,mm) = mbar(:ncol,k) * vmr(:ncol,k,mm) / mw_carma(mm)
     944             :           end do
     945             :        end do
     946             :     end do
     947             : 
     948      145920 :   end subroutine mmr2vmr_carma
     949             :   !=============================================================================
     950             : 
     951             :   !=============================================================================
     952       72960 :   subroutine vmr2mmr_carma ( lchnk, vmr, mbar, mw_carma, ncol, im, rmass )
     953             :     !-----------------------------------------------------------------
     954             :     !   ... Xfrom from volume to mass mixing ratio
     955             :     !-----------------------------------------------------------------
     956             : 
     957             :     implicit none
     958             : 
     959             :     !-----------------------------------------------------------------
     960             :     !   ... Dummy args
     961             :     !-----------------------------------------------------------------
     962             :     integer, intent(in)     :: lchnk, ncol, im
     963             :     real(r8), intent(in)    :: mbar(ncol,pver)
     964             :     real(r8), intent(in)    :: rmass(nbins)
     965             :     real(r8), intent(inout)    :: vmr(ncol,pver,ncnst_tot)
     966             :     real(r8), intent(in)    :: mw_carma(ncnst_tot)
     967             : 
     968             :     !-----------------------------------------------------------------
     969             :     !   ... Local variables
     970             :     !-----------------------------------------------------------------
     971             :     integer :: k, m, mm, l
     972             :     !-----------------------------------------------------------------
     973             :     !   ... The non-group species
     974             :     !-----------------------------------------------------------------
     975     2991360 :     do m = 1, nbins
     976    13205760 :        do l = 1, nspec(m)   ! for each species, not total mmr or number, information of mw are missing
     977    10214400 :           mm = bin_idx(m, l)
     978   728140800 :           do k=1,pver
     979 11021337600 :              vmr(:ncol,k,mm) = mw_carma(mm) * vmr(:ncol,k,mm) / mbar(:ncol,k)
     980             :           end do
     981             :        end do
     982             :     end do
     983             : 
     984       72960 :   end subroutine vmr2mmr_carma
     985             : 
     986           0 : end module aero_model

Generated by: LCOV version 1.14