LCOV - code coverage report
Current view: | top level - chemistry/modal_aero - dust_model.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 59 | 83 | 71.1 %
Date: | 2024-12-17 22:39:59 |  | Functions: | 3 | 3 | 100.0 %

              Line data    Source code
           1             : !===============================================================================
           2             : ! Dust for Modal Aerosol Model
           3             : !===============================================================================
           4             : module dust_model
           5             :   use shr_kind_mod,     only: r8 => shr_kind_r8, cl => shr_kind_cl
           6             :   use spmd_utils,       only: masterproc
           7             :   use cam_abortutils,   only: endrun
           8             :   use modal_aero_data,  only: ntot_amode, ndst=>nDust
           9             :   use cam_logfile,      only: iulog
          10             :   use shr_dust_emis_mod,only: is_dust_emis_zender, is_zender_soil_erod_from_atm
          11             :
          12             :   implicit none
          13             :   private
          14             :
          15             :   public :: dust_names
          16             :   public :: dust_nbin
          17             :   public :: dust_nnum
          18             :   public :: dust_indices
          19             :   public :: dust_emis
          20             :   public :: dust_readnl
          21             :   public :: dust_init
          22             :   public :: dust_active
          23             :
          24             :   integer, protected :: dust_nbin != 2
          25             :   integer, protected :: dust_nnum != 2
          26             :   character(len=6), protected, allocatable :: dust_names(:)
          27             :
          28             :   real(r8), allocatable :: dust_dmt_grd(:)
          29             :   real(r8), allocatable :: dust_emis_sclfctr(:)
          30             :
          31             :   integer , protected, allocatable :: dust_indices(:)
          32             :   real(r8), allocatable :: dust_dmt_vwr(:)
          33             :   real(r8), allocatable :: dust_stk_crc(:)
          34             :
          35             :   real(r8)          :: dust_emis_fact = 0._r8     ! tuning parameter for dust emissions
          36             :   character(len=cl) :: soil_erod_file = 'none'    ! full pathname for soil erodibility dataset
          37             :
          38             :   logical :: dust_active = .false.
          39             :
          40             :  contains
          41             :
          42             :   !=============================================================================
          43             :   ! reads dust namelist options
          44             :   !=============================================================================
          45        1536 :   subroutine dust_readnl(nlfile)
          46             :
          47             :     use namelist_utils,  only: find_group_name
          48             :     use spmd_utils,      only: mpicom, masterprocid, mpi_character, mpi_real8, mpi_success
          49             :     use shr_dust_emis_mod, only: shr_dust_emis_readnl
          50             :
          51             :     character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
          52             :
          53             :     ! Local variables
          54             :     integer :: unitn, ierr
          55             :     character(len=*), parameter :: subname = 'dust_readnl'
          56             :
          57             :     namelist /dust_nl/ dust_emis_fact, soil_erod_file
          58             :
          59             :     !-----------------------------------------------------------------------------
          60             :
          61             :     ! Read namelist
          62        1536 :     if (masterproc) then
          63           2 :        open( newunit=unitn, file=trim(nlfile), status='old' )
          64           2 :        call find_group_name(unitn, 'dust_nl', status=ierr)
          65           2 :        if (ierr == 0) then
          66           2 :           read(unitn, dust_nl, iostat=ierr)
          67           2 :           if (ierr /= 0) then
          68           0 :              call endrun(subname // ':: ERROR reading namelist')
          69             :           end if
          70             :        end if
          71           2 :        close(unitn)
          72             :     end if
          73             :
          74             :     ! Broadcast namelist variables
          75        1536 :     call mpi_bcast(soil_erod_file, len(soil_erod_file), mpi_character, masterprocid, mpicom, ierr)
          76        1536 :     if (ierr/=mpi_success) then
          77           0 :        call endrun(subname//' MPI_BCAST ERROR: soil_erod_file')
          78             :     end if
          79        1536 :     call mpi_bcast(dust_emis_fact, 1, mpi_real8, masterprocid, mpicom, ierr)
          80        1536 :     if (ierr/=mpi_success) then
          81           0 :        call endrun(subname//' MPI_BCAST ERROR: dust_emis_fact')
          82             :     end if
          83             :
          84        1536 :     call shr_dust_emis_readnl(mpicom, 'drv_flds_in')
          85             :
          86        1536 :     if ((soil_erod_file /= 'none') .and. (.not.is_zender_soil_erod_from_atm())) then
          87           0 :        call endrun(subname//': should not specify soil_erod_file if Zender soil erosion is not in CAM')
          88             :     end if
          89             :
          90        1536 :     if (masterproc) then
          91           2 :        if (is_dust_emis_zender()) then
          92           0 :           write(iulog,*) subname,': Zender_2003 dust emission method is being used.'
          93             :        end if
          94           2 :        if (is_zender_soil_erod_from_atm()) then
          95           0 :           write(iulog,*) subname,': Zender soil erod file is handled in atm'
          96           0 :           write(iulog,*) subname,': soil_erod_file = ',trim(soil_erod_file)
          97           0 :           write(iulog,*) subname,': dust_emis_fact = ',dust_emis_fact
          98             :        end if
          99             :     end if
         100             :
         101        1536 :   end subroutine dust_readnl
         102             :
         103             :   !=============================================================================
         104             :   !=============================================================================
         105        1536 :   subroutine dust_init()
         106             :     use soil_erod_mod, only: soil_erod_init
         107             :     use constituents,  only: cnst_get_ind
         108             :     use rad_constituents, only: rad_cnst_get_info
         109             :     use dust_common,   only: dust_set_params
         110             :
         111             :     integer :: l, m, mm, ndx, nspec
         112             :     character(len=32) :: spec_name
         113             :     integer, parameter :: mymodes(7) = (/ 2, 1, 3, 4, 5, 6, 7 /) ! tricky order ...
         114             :
         115        1536 :     dust_nbin = ndst
         116        1536 :     dust_nnum = ndst
         117             :
         118        4608 :     allocate( dust_names(2*ndst) )
         119        4608 :     allocate( dust_indices(2*ndst) )
         120        4608 :     allocate( dust_dmt_grd(ndst+1) )
         121        4608 :     allocate( dust_emis_sclfctr(ndst) )
         122        3072 :     allocate( dust_dmt_vwr(ndst) )
         123        3072 :     allocate( dust_stk_crc(ndst) )
         124             :
         125        1536 :     if ( ntot_amode == 3 ) then
         126           0 :        dust_dmt_grd(:) = (/ 0.1e-6_r8, 1.0e-6_r8, 10.0e-6_r8/)
         127           0 :        dust_emis_sclfctr(:) = (/ 0.011_r8,0.989_r8 /)
         128        1536 :     elseif ( ntot_amode == 4 .or. ntot_amode == 5 ) then
         129        7680 :        dust_dmt_grd(:) = (/ 0.01e-6_r8, 0.1e-6_r8, 1.0e-6_r8, 10.0e-6_r8 /) ! Aitken dust
         130        6144 :        dust_emis_sclfctr(:) = (/ 1.65E-05_r8, 0.011_r8, 0.989_r8 /) ! Aitken dust
         131           0 :     else if( ntot_amode == 7 ) then
         132           0 :        dust_dmt_grd(:) = (/ 0.1e-6_r8, 2.0e-6_r8, 10.0e-6_r8/)
         133           0 :        dust_emis_sclfctr(:) = (/ 0.13_r8, 0.87_r8 /)
         134             :     endif
         135             :
         136             :     ndx = 0
         137        7680 :     do mm = 1, ntot_amode
         138        6144 :        m = mymodes(mm)
         139        6144 :        call rad_cnst_get_info(0, m, nspec=nspec)
         140       30720 :        do l = 1, nspec
         141       23040 :           call rad_cnst_get_info(0, m, l, spec_name=spec_name )
         142       29184 :           if (spec_name(:3) == 'dst') then
         143        4608 :              ndx=ndx+1
         144        4608 :              dust_names(ndx) = spec_name
         145        4608 :              dust_names(ndst+ndx) = 'num_'//spec_name(5:)
         146        4608 :              call cnst_get_ind(dust_names(     ndx), dust_indices(     ndx))
         147        4608 :              call cnst_get_ind(dust_names(ndst+ndx), dust_indices(ndst+ndx))
         148             :           endif
         149             :        enddo
         150             :     enddo
         151             :
         152        1536 :     dust_active = any(dust_indices(:) > 0)
         153        1536 :     if (.not.dust_active) return
         154             :
         155        1536 :     if (is_zender_soil_erod_from_atm()) then
         156           0 :        call  soil_erod_init( dust_emis_fact, soil_erod_file )
         157             :     end if
         158             :
         159        1536 :     call dust_set_params( dust_nbin, dust_dmt_grd, dust_dmt_vwr, dust_stk_crc )
         160             :
         161        1536 :   end subroutine dust_init
         162             :
         163             :   !===============================================================================
         164             :   !===============================================================================
         165     1489176 :   subroutine dust_emis( ncol, lchnk, dust_flux_in, cflx, soil_erod )
         166             :     use soil_erod_mod, only : soil_erod_fact
         167        1536 :     use soil_erod_mod, only : soil_erodibility
         168             :     use mo_constants,  only : dust_density
         169             :     use physconst,     only : pi
         170             :
         171             :   ! args
         172             :     integer,  intent(in)    :: ncol, lchnk
         173             :     real(r8), intent(in)    :: dust_flux_in(:,:)
         174             :     real(r8), intent(inout) :: cflx(:,:)
         175             :     real(r8), intent(out)   :: soil_erod(:)
         176             :
         177             :   ! local vars
         178             :     integer :: i, m, idst, inum
         179             :     real(r8) :: x_mton
         180             :     real(r8),parameter :: soil_erod_threshold = 0.1_r8
         181             :
         182             :     ! set dust emissions
         183             :
         184     1489176 :     if (is_zender_soil_erod_from_atm()) then
         185           0 :        col_loop1: do i = 1,ncol
         186           0 :           soil_erod(i) = soil_erodibility( i, lchnk )
         187           0 :           if( soil_erod(i) .lt. soil_erod_threshold ) soil_erod(i) = 0._r8
         188             :
         189             :           ! rebin and adjust dust emissons.
         190           0 :           do m = 1,dust_nbin
         191           0 :              idst = dust_indices(m)
         192           0 :              cflx(i,idst) = sum( -dust_flux_in(i,:) ) &
         193           0 :                   * dust_emis_sclfctr(m)*soil_erod(i)/dust_emis_fact*1.15_r8
         194           0 :              x_mton = 6._r8 / (pi * dust_density * (dust_dmt_vwr(m)**3._r8))
         195           0 :              inum = dust_indices(m+dust_nbin)
         196           0 :              cflx(i,inum) = cflx(i,idst)*x_mton
         197             :           enddo
         198             :        enddo col_loop1
         199             :     else ! Leung emissions
         200             :
         201    24865776 :        col_loop2: do i = 1,ncol
         202             :           ! rebin and adjust dust emissons.
         203    94995576 :           do m = 1,dust_nbin
         204    70129800 :              idst = dust_indices(m)
         205             :
         206   140259600 :              cflx(i,idst) = sum( -dust_flux_in(i,:) ) &
         207   490908600 :                   * dust_emis_sclfctr(m) / dust_emis_fact
         208    70129800 :              x_mton = 6._r8 / (pi * dust_density * (dust_dmt_vwr(m)**3._r8))
         209    70129800 :              inum = dust_indices(m+dust_nbin)
         210    93506400 :              cflx(i,inum) = cflx(i,idst)*x_mton
         211             :           enddo
         212             :        enddo col_loop2
         213             :     end if
         214             :
         215     1489176 :   end subroutine dust_emis
         216             :
         217             : end module dust_model

Generated by: LCOV version 1.14