LCOV - code coverage report
Current view: top level - chemistry/aerosol - aero_deposition_cam.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 120 122 98.4 %
Date: 2024-12-17 22:39:59 Functions: 4 4 100.0 %

          Line data    Source code
       1             : module aero_deposition_cam
       2             : !------------------------------------------------------------------------------
       3             : ! Purpose:
       4             : !
       5             : ! Partition the contributions from aerosols of wet and dry
       6             : ! deposition at the surface into the fields passed to the coupler.
       7             : !------------------------------------------------------------------------------
       8             : 
       9             :   use shr_kind_mod, only: r8 => shr_kind_r8
      10             :   use shr_kind_mod, only: cl => shr_kind_cl
      11             :   use constituents, only: cnst_get_ind, pcnst
      12             :   use camsrfexch,   only: cam_out_t
      13             :   use cam_abortutils,only: endrun
      14             :   use aerosol_properties_mod, only: aero_name_len
      15             :   use aerosol_properties_mod, only: aerosol_properties
      16             : 
      17             :   implicit none
      18             : 
      19             :   private
      20             : 
      21             : ! Public interfaces
      22             : 
      23             :   public :: aero_deposition_cam_init
      24             :   public :: aero_deposition_cam_setwet
      25             :   public :: aero_deposition_cam_setdry
      26             : 
      27             : ! Private module data
      28             : 
      29             :   integer :: bcphi_ndx( pcnst ) = -1
      30             :   integer :: bcphi_cnt = 0
      31             :   integer :: bcpho_ndx( pcnst ) = -1
      32             :   integer :: bcpho_cnt = 0
      33             :   integer :: ocphi_ndx( pcnst ) = -1
      34             :   integer :: ocphi_cnt = 0
      35             :   integer :: ocpho_ndx( pcnst ) = -1
      36             :   integer :: ocpho_cnt = 0
      37             : 
      38             :   class(aerosol_properties), pointer :: aero_props=>null()
      39             :   integer :: nele_tot=0            ! total number of aerosol elements
      40             : 
      41             :   ! bulk dust bins (meters)
      42             : 
      43             :   integer, parameter :: n_bulk_dst_bins = 4
      44             : 
      45             :   ! CAM4 bulk dust bin sizes (https://doi.org/10.1002/2013MS000279)
      46             :   real(r8), parameter :: bulk_dst_edges(n_bulk_dst_bins+1) = &
      47             :        (/0.1e-6_r8, 1.0e-6_r8, 2.5e-6_r8, 5.0e-6_r8, 10.e-6_r8/)
      48             : 
      49             : contains
      50             : 
      51             :   !============================================================================
      52        1536 :   subroutine aero_deposition_cam_init(aero_props_in)
      53             : 
      54             :     class(aerosol_properties),target, intent(in) :: aero_props_in
      55             : 
      56             :     integer :: pcnt, scnt
      57             :     character(len=*), parameter :: subrname = 'aero_deposition_cam_init'
      58             : 
      59             :     ! construct the aerosol properties object
      60        1536 :     aero_props => aero_props_in
      61             : 
      62             :     ! set the cam constituent indices and determine the counts
      63             :     ! for the specified aerosol types
      64             : 
      65             :     ! black carbons
      66        1536 :     call get_indices( type='black-c',  hydrophilic=.true.,  indices=bcphi_ndx, count=bcphi_cnt )
      67        1536 :     call get_indices( type='black-c',  hydrophilic=.false., indices=bcpho_ndx, count=bcpho_cnt )
      68             : 
      69             :     ! primary and secondary organics
      70        1536 :     call get_indices( type='p-organic',hydrophilic=.true.,  indices=ocphi_ndx, count=pcnt )
      71        1536 :     call get_indices( type='s-organic',hydrophilic=.true.,  indices=ocphi_ndx(pcnt+1:), count=scnt )
      72        1536 :     ocphi_cnt = pcnt+scnt
      73             : 
      74        1536 :     call get_indices( type='p-organic',hydrophilic=.false., indices=ocpho_ndx, count=pcnt )
      75        1536 :     call get_indices( type='s-organic',hydrophilic=.false., indices=ocpho_ndx(pcnt+1:), count=scnt )
      76        1536 :     ocpho_cnt = pcnt+scnt
      77             : 
      78             :     ! total number of aerosol elements
      79        1536 :     nele_tot = aero_props%ncnst_tot()
      80             : 
      81             :   contains
      82             : 
      83             :     !==========================================================================
      84             :     ! returns CAM constituent indices of the aerosol tracers (and count)
      85             :     !==========================================================================
      86        9216 :     subroutine get_indices( type, hydrophilic, indices, count)
      87             : 
      88             :       character(len=*), intent(in) :: type
      89             :       logical, intent(in ) :: hydrophilic
      90             :       integer, intent(out) :: indices(:)
      91             :       integer, intent(out) :: count
      92             : 
      93             :       integer :: ibin,ispc, ndx, nspec
      94             :       character(len=aero_name_len) :: spec_type, spec_name
      95             : 
      96        9216 :       count = 0
      97      384000 :       indices(:) = -1
      98             : 
      99             :       ! loop through aerosol bins / modes
     100       46080 :       do ibin = 1, aero_props%nbins()
     101             : 
     102             :          ! check if the bin/mode is hydrophilic
     103       46080 :          if ( aero_props%hydrophilic(ibin) .eqv. hydrophilic ) then
     104       87552 :             do ispc = 1, aero_props%nspecies(ibin)
     105             : 
     106       69120 :                call aero_props%get(ibin,ispc, spectype=spec_type, specname=spec_name)
     107             : 
     108       87552 :                if (spec_type==type) then
     109             : 
     110             :                   ! get CAM constituent index
     111        9216 :                   call cnst_get_ind(spec_name, ndx, abort=.false.)
     112        9216 :                   if (ndx>0) then
     113        9216 :                      count = count+1
     114        9216 :                      indices(count) = ndx
     115             :                   endif
     116             : 
     117             :                endif
     118             : 
     119             :             enddo
     120             :          endif
     121             : 
     122             :       enddo
     123             : 
     124        9216 :     end subroutine get_indices
     125             : 
     126             :   end subroutine aero_deposition_cam_init
     127             : 
     128             :   !============================================================================
     129             :   ! Set surface wet deposition fluxes passed to coupler.
     130             :   !============================================================================
     131     1489176 :   subroutine aero_deposition_cam_setwet(aerdepwetis, aerdepwetcw, cam_out)
     132             : 
     133             :    ! Arguments:
     134             :    real(r8), intent(in) :: aerdepwetis(:,:)  ! aerosol wet deposition (interstitial)
     135             :    real(r8), intent(in) :: aerdepwetcw(:,:)  ! aerosol wet deposition (cloud water)
     136             :    type(cam_out_t), intent(inout) :: cam_out     ! cam export state
     137             : 
     138             :    ! Local variables:
     139             :    integer :: i, ispec, ibin, mm, ndx
     140             :    integer :: ncol                      ! number of columns
     141             : 
     142     2978352 :    real(r8) :: dep_fluxes(nele_tot)
     143             :    real(r8) :: dst_fluxes(n_bulk_dst_bins)
     144             :    character(len=aero_name_len) :: specname, name_c
     145             :    integer :: errstat
     146             :    character(len=cl) :: errstr
     147             : 
     148     1489176 :    ncol = cam_out%ncol
     149             : 
     150    25315992 :    cam_out%bcphiwet(:) = 0._r8
     151    25315992 :    cam_out%ocphiwet(:) = 0._r8
     152    25315992 :    cam_out%dstwet1(:) = 0._r8
     153    25315992 :    cam_out%dstwet2(:) = 0._r8
     154    25315992 :    cam_out%dstwet3(:) = 0._r8
     155    25315992 :    cam_out%dstwet4(:) = 0._r8
     156             : 
     157             :    ! derive cam_out variables from deposition fluxes
     158             :    !  note: wet deposition fluxes are negative into surface,
     159             :    !        dry deposition fluxes are positive into surface.
     160             :    !        srf models want positive definite fluxes.
     161    24865776 :    do i = 1, ncol
     162             : 
     163             :       ! hydrophilic black carbon fluxes
     164    46753200 :       do ispec=1,bcphi_cnt
     165    23376600 :          cam_out%bcphiwet(i) = cam_out%bcphiwet(i) &
     166    70129800 :                              - (aerdepwetis(i,bcphi_ndx(ispec))+aerdepwetcw(i,bcphi_ndx(ispec)))
     167             :       enddo
     168             : 
     169             :       ! hydrophobic black carbon fluxes
     170    46753200 :       do ispec=1,bcpho_cnt
     171    23376600 :          cam_out%bcphiwet(i) = cam_out%bcphiwet(i) &
     172    70129800 :                              - (aerdepwetis(i,bcpho_ndx(ispec))+aerdepwetcw(i,bcpho_ndx(ispec)))
     173             :       enddo
     174             : 
     175             :       ! hydrophilic organic carbon fluxes
     176    70129800 :       do ispec=1,ocphi_cnt
     177    46753200 :          cam_out%ocphiwet(i) = cam_out%ocphiwet(i) &
     178   116883000 :                              - (aerdepwetis(i,ocphi_ndx(ispec))+aerdepwetcw(i,ocphi_ndx(ispec)))
     179             :       enddo
     180             : 
     181             :       ! hydrophobic organic carbon fluxes
     182    70129800 :       do ispec=1,ocpho_cnt
     183    46753200 :          cam_out%ocphiwet(i) = cam_out%ocphiwet(i) &
     184   116883000 :                              - (aerdepwetis(i,ocpho_ndx(ispec))+aerdepwetcw(i,ocpho_ndx(ispec)))
     185             :       enddo
     186             : 
     187             :       ! dust fluxes
     188             : 
     189   467532000 :       dep_fluxes = 0._r8
     190    23376600 :       dst_fluxes = 0._r8
     191             : 
     192   116883000 :       do ibin = 1,aero_props%nbins()
     193   561038400 :          do ispec = 0,aero_props%nmasses(ibin)
     194   444155400 :             if (ispec==0) then
     195    93506400 :                call aero_props%num_names(ibin, specname, name_c)
     196             :             else
     197   350649000 :                call aero_props%get(ibin,ispec, specname=specname)
     198             :             end if
     199   444155400 :             call cnst_get_ind(specname, ndx, abort=.false.)
     200   537661800 :             if (ndx>0) then
     201   444155400 :                mm = aero_props%indexer(ibin,ispec)
     202   444155400 :                dep_fluxes(mm) = - (aerdepwetis(i,ndx)+aerdepwetcw(i,ndx))
     203             :             end if
     204             :          end do
     205             :       end do
     206             : 
     207             :       ! rebin dust fluxes to bulk dust bins
     208    23376600 :       call aero_props%rebin_bulk_fluxes('dust', dep_fluxes, bulk_dst_edges, dst_fluxes, errstat, errstr)
     209    23376600 :       if (errstat/=0) then
     210           0 :          call endrun('aero_deposition_cam_setwet: '//trim(errstr))
     211             :       end if
     212             : 
     213    23376600 :       cam_out%dstwet1(i) = cam_out%dstwet1(i) + dst_fluxes(1)
     214    23376600 :       cam_out%dstwet2(i) = cam_out%dstwet2(i) + dst_fluxes(2)
     215    23376600 :       cam_out%dstwet3(i) = cam_out%dstwet3(i) + dst_fluxes(3)
     216    23376600 :       cam_out%dstwet4(i) = cam_out%dstwet4(i) + dst_fluxes(4)
     217             : 
     218             :       ! in rare cases, integrated deposition tendency is upward
     219    23376600 :       if (cam_out%bcphiwet(i) < 0._r8) cam_out%bcphiwet(i) = 0._r8
     220    23376600 :       if (cam_out%ocphiwet(i) < 0._r8) cam_out%ocphiwet(i) = 0._r8
     221    23376600 :       if (cam_out%dstwet1(i)  < 0._r8) cam_out%dstwet1(i)  = 0._r8
     222    23376600 :       if (cam_out%dstwet2(i)  < 0._r8) cam_out%dstwet2(i)  = 0._r8
     223    23376600 :       if (cam_out%dstwet3(i)  < 0._r8) cam_out%dstwet3(i)  = 0._r8
     224    24865776 :       if (cam_out%dstwet4(i)  < 0._r8) cam_out%dstwet4(i)  = 0._r8
     225             : 
     226             :    enddo
     227             : 
     228     1489176 :   end subroutine aero_deposition_cam_setwet
     229             : 
     230             :   !============================================================================
     231             :   ! Set surface dry deposition fluxes passed to coupler.
     232             :   !============================================================================
     233     1489176 :   subroutine aero_deposition_cam_setdry(aerdepdryis, aerdepdrycw, cam_out)
     234             : 
     235             :    ! Arguments:
     236             :    real(r8), intent(in) :: aerdepdryis(:,:)  ! aerosol dry deposition (interstitial)
     237             :    real(r8), intent(in) :: aerdepdrycw(:,:)  ! aerosol dry deposition (cloud water)
     238             :    type(cam_out_t), intent(inout) :: cam_out     ! cam export state
     239             : 
     240             :    ! Local variables:
     241             :    integer :: i, ispec, ibin, mm, ndx
     242             :    integer :: ncol                      ! number of columns
     243             : 
     244     2978352 :    real(r8) :: dep_fluxes(nele_tot)
     245             :    real(r8) :: dst_fluxes(n_bulk_dst_bins)
     246             :    character(len=aero_name_len) :: specname, name_c
     247             :    integer :: errstat
     248             :    character(len=cl) :: errstr
     249             : 
     250     1489176 :    ncol = cam_out%ncol
     251             : 
     252    25315992 :    cam_out%bcphidry(:) = 0._r8
     253    25315992 :    cam_out%ocphidry(:) = 0._r8
     254    25315992 :    cam_out%bcphodry(:) = 0._r8
     255    25315992 :    cam_out%ocphodry(:) = 0._r8
     256    25315992 :    cam_out%dstdry1(:) = 0._r8
     257    25315992 :    cam_out%dstdry2(:) = 0._r8
     258    25315992 :    cam_out%dstdry3(:) = 0._r8
     259    25315992 :    cam_out%dstdry4(:) = 0._r8
     260             : 
     261             :    ! derive cam_out variables from deposition fluxes
     262             :    !  note: wet deposition fluxes are negative into surface,
     263             :    !        dry deposition fluxes are positive into surface.
     264             :    !        srf models want positive definite fluxes.
     265    24865776 :    do i = 1, ncol
     266             : 
     267             :       ! hydrophilic black carbon fluxes
     268    46753200 :       do ispec=1,bcphi_cnt
     269    23376600 :          cam_out%bcphidry(i) = cam_out%bcphidry(i) &
     270    70129800 :                              + (aerdepdryis(i,bcphi_ndx(ispec))+aerdepdrycw(i,bcphi_ndx(ispec)))
     271             :       enddo
     272             : 
     273             :       ! hydrophobic black carbon fluxes
     274    46753200 :       do ispec=1,bcpho_cnt
     275    23376600 :          cam_out%bcphodry(i) = cam_out%bcphodry(i) &
     276    70129800 :                              + (aerdepdryis(i,bcpho_ndx(ispec))+aerdepdrycw(i,bcpho_ndx(ispec)))
     277             :       enddo
     278             : 
     279             :       ! hydrophilic organic carbon fluxes
     280    70129800 :       do ispec=1,ocphi_cnt
     281    46753200 :          cam_out%ocphidry(i) = cam_out%ocphidry(i) &
     282   116883000 :                              + (aerdepdryis(i,ocphi_ndx(ispec))+aerdepdrycw(i,ocphi_ndx(ispec)))
     283             :       enddo
     284             : 
     285             :       ! hydrophobic organic carbon fluxes
     286    70129800 :       do ispec=1,ocpho_cnt
     287    46753200 :          cam_out%ocphodry(i) = cam_out%ocphodry(i) &
     288   116883000 :                              + (aerdepdryis(i,ocpho_ndx(ispec))+aerdepdrycw(i,ocpho_ndx(ispec)))
     289             :       enddo
     290             : 
     291             :       ! dust fluxes
     292             : 
     293   467532000 :       dep_fluxes = 0._r8
     294    23376600 :       dst_fluxes = 0._r8
     295             : 
     296   116883000 :       do ibin = 1,aero_props%nbins()
     297   561038400 :          do ispec = 0,aero_props%nspecies(ibin)
     298   444155400 :             if (ispec==0) then
     299    93506400 :                call aero_props%num_names(ibin, specname, name_c)
     300             :             else
     301   350649000 :                call aero_props%get(ibin,ispec, specname=specname)
     302             :             end if
     303   444155400 :             call cnst_get_ind(specname, ndx, abort=.false.)
     304   537661800 :             if (ndx>0) then
     305   444155400 :                mm = aero_props%indexer(ibin,ispec)
     306   444155400 :                dep_fluxes(mm) = aerdepdryis(i,ndx)+aerdepdrycw(i,ndx)
     307             :             end if
     308             :          end do
     309             :       end do
     310             : 
     311             :       ! rebin dust fluxes to bulk dust bins
     312    23376600 :       call aero_props%rebin_bulk_fluxes('dust', dep_fluxes, bulk_dst_edges, dst_fluxes, errstat, errstr)
     313    23376600 :       if (errstat/=0) then
     314           0 :          call endrun('aero_deposition_cam_setdry: '//trim(errstr))
     315             :       end if
     316             : 
     317    23376600 :       cam_out%dstdry1(i) = cam_out%dstdry1(i) + dst_fluxes(1)
     318    23376600 :       cam_out%dstdry2(i) = cam_out%dstdry2(i) + dst_fluxes(2)
     319    23376600 :       cam_out%dstdry3(i) = cam_out%dstdry3(i) + dst_fluxes(3)
     320    23376600 :       cam_out%dstdry4(i) = cam_out%dstdry4(i) + dst_fluxes(4)
     321             : 
     322             :       ! in rare cases, integrated deposition tendency is upward
     323    23376600 :       if (cam_out%bcphidry(i) < 0._r8) cam_out%bcphidry(i) = 0._r8
     324    23376600 :       if (cam_out%ocphidry(i) < 0._r8) cam_out%ocphidry(i) = 0._r8
     325    23376600 :       if (cam_out%bcphodry(i) < 0._r8) cam_out%bcphodry(i) = 0._r8
     326    23376600 :       if (cam_out%ocphodry(i) < 0._r8) cam_out%ocphodry(i) = 0._r8
     327    23376600 :       if (cam_out%dstdry1(i)  < 0._r8) cam_out%dstdry1(i)  = 0._r8
     328    23376600 :       if (cam_out%dstdry2(i)  < 0._r8) cam_out%dstdry2(i)  = 0._r8
     329    23376600 :       if (cam_out%dstdry3(i)  < 0._r8) cam_out%dstdry3(i)  = 0._r8
     330    24865776 :       if (cam_out%dstdry4(i)  < 0._r8) cam_out%dstdry4(i)  = 0._r8
     331             : 
     332             :    enddo
     333             : 
     334     1489176 :   end subroutine aero_deposition_cam_setdry
     335             : 
     336             : end module aero_deposition_cam

Generated by: LCOV version 1.14