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