LCOV - code coverage report
Current view: top level - chemistry/modal_aero - dust_model.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 55 61 90.2 %
Date: 2025-03-13 18:42:46 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             : 
      10             :   implicit none
      11             :   private
      12             : 
      13             :   public :: dust_names
      14             :   public :: dust_nbin
      15             :   public :: dust_nnum
      16             :   public :: dust_indices
      17             :   public :: dust_emis
      18             :   public :: dust_readnl
      19             :   public :: dust_init
      20             :   public :: dust_active
      21             : 
      22             :   integer, protected :: dust_nbin != 2
      23             :   integer, protected :: dust_nnum != 2
      24             :   character(len=6), protected, allocatable :: dust_names(:)
      25             : 
      26             :   real(r8), allocatable :: dust_dmt_grd(:)
      27             :   real(r8), allocatable :: dust_emis_sclfctr(:)
      28             : 
      29             :   integer , protected, allocatable :: dust_indices(:)
      30             :   real(r8), allocatable :: dust_dmt_vwr(:)
      31             :   real(r8), allocatable :: dust_stk_crc(:)
      32             : 
      33             :   real(r8)          :: dust_emis_fact = -1.e36_r8        ! tuning parameter for dust emissions
      34             :   character(len=cl) :: soil_erod_file = 'soil_erod_file' ! full pathname for soil erodibility dataset
      35             : 
      36             :   logical :: dust_active = .false.
      37             : 
      38             :  contains
      39             : 
      40             :   !=============================================================================
      41             :   ! reads dust namelist options
      42             :   !=============================================================================
      43        1536 :   subroutine dust_readnl(nlfile)
      44             : 
      45             :     use namelist_utils,  only: find_group_name
      46             :     use units,           only: getunit, freeunit
      47             :     use mpishorthand
      48             : 
      49             :     character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
      50             : 
      51             :     ! Local variables
      52             :     integer :: unitn, ierr
      53             :     character(len=*), parameter :: subname = 'dust_readnl'
      54             : 
      55             :     namelist /dust_nl/ dust_emis_fact, soil_erod_file
      56             : 
      57             :     !-----------------------------------------------------------------------------
      58             : 
      59             :     ! Read namelist
      60        1536 :     if (masterproc) then
      61           2 :        unitn = getunit()
      62           2 :        open( unitn, file=trim(nlfile), status='old' )
      63           2 :        call find_group_name(unitn, 'dust_nl', status=ierr)
      64           2 :        if (ierr == 0) then
      65           2 :           read(unitn, dust_nl, iostat=ierr)
      66           2 :           if (ierr /= 0) then
      67           0 :              call endrun(subname // ':: ERROR reading namelist')
      68             :           end if
      69             :        end if
      70           2 :        close(unitn)
      71           2 :        call freeunit(unitn)
      72             :     end if
      73             : 
      74             : #ifdef SPMD
      75             :     ! Broadcast namelist variables
      76        1536 :     call mpibcast(dust_emis_fact, 1,                   mpir8,   0, mpicom)
      77        1536 :     call mpibcast(soil_erod_file, len(soil_erod_file), mpichar, 0, mpicom)
      78             : #endif
      79             : 
      80        1536 :   end subroutine dust_readnl
      81             : 
      82             :   !=============================================================================
      83             :   !=============================================================================
      84        1536 :   subroutine dust_init()
      85             :     use soil_erod_mod, only: soil_erod_init
      86             :     use constituents,  only: cnst_get_ind
      87             :     use rad_constituents, only: rad_cnst_get_info
      88             :     use dust_common,   only: dust_set_params
      89             : 
      90             :     integer :: l, m, mm, ndx, nspec
      91             :     character(len=32) :: spec_name
      92             :     integer, parameter :: mymodes(7) = (/ 2, 1, 3, 4, 5, 6, 7 /) ! tricky order ...
      93             : 
      94        1536 :     dust_nbin = ndst
      95        1536 :     dust_nnum = ndst
      96             : 
      97        4608 :     allocate( dust_names(2*ndst) )
      98        4608 :     allocate( dust_indices(2*ndst) )
      99        4608 :     allocate( dust_dmt_grd(ndst+1) )
     100        4608 :     allocate( dust_emis_sclfctr(ndst) )
     101        3072 :     allocate( dust_dmt_vwr(ndst) )
     102        3072 :     allocate( dust_stk_crc(ndst) )
     103             : 
     104        1536 :     if ( ntot_amode == 3 ) then
     105           0 :        dust_dmt_grd(:) = (/ 0.1e-6_r8, 1.0e-6_r8, 10.0e-6_r8/)
     106           0 :        dust_emis_sclfctr(:) = (/ 0.011_r8,0.989_r8 /)
     107        1536 :     elseif ( ntot_amode == 4 .or. ntot_amode == 5 ) then
     108        7680 :        dust_dmt_grd(:) = (/ 0.01e-6_r8, 0.1e-6_r8, 1.0e-6_r8, 10.0e-6_r8 /) ! Aitken dust
     109        6144 :        dust_emis_sclfctr(:) = (/ 1.65E-05_r8, 0.011_r8, 0.989_r8 /) ! Aitken dust
     110           0 :     else if( ntot_amode == 7 ) then
     111           0 :        dust_dmt_grd(:) = (/ 0.1e-6_r8, 2.0e-6_r8, 10.0e-6_r8/)
     112           0 :        dust_emis_sclfctr(:) = (/ 0.13_r8, 0.87_r8 /)
     113             :     endif
     114             : 
     115             :     ndx = 0
     116        7680 :     do mm = 1, ntot_amode
     117        6144 :        m = mymodes(mm)
     118        6144 :        call rad_cnst_get_info(0, m, nspec=nspec)
     119       30720 :        do l = 1, nspec
     120       23040 :           call rad_cnst_get_info(0, m, l, spec_name=spec_name )
     121       29184 :           if (spec_name(:3) == 'dst') then
     122        4608 :              ndx=ndx+1
     123        4608 :              dust_names(ndx) = spec_name
     124        4608 :              dust_names(ndst+ndx) = 'num_'//spec_name(5:)
     125        4608 :              call cnst_get_ind(dust_names(     ndx), dust_indices(     ndx))
     126        4608 :              call cnst_get_ind(dust_names(ndst+ndx), dust_indices(ndst+ndx))
     127             :           endif
     128             :        enddo
     129             :     enddo
     130             : 
     131        1536 :     dust_active = any(dust_indices(:) > 0)
     132        1536 :     if (.not.dust_active) return
     133             : 
     134        1536 :     call  soil_erod_init( dust_emis_fact, soil_erod_file )
     135             : 
     136        1536 :     call dust_set_params( dust_nbin, dust_dmt_grd, dust_dmt_vwr, dust_stk_crc )
     137             : 
     138        1536 :   end subroutine dust_init
     139             : 
     140             :   !===============================================================================
     141             :   !===============================================================================
     142       58824 :   subroutine dust_emis( ncol, lchnk, dust_flux_in, cflx, soil_erod )
     143        1536 :     use soil_erod_mod, only : soil_erod_fact
     144             :     use soil_erod_mod, only : soil_erodibility
     145             :     use mo_constants,  only : dust_density
     146             :     use physconst,     only : pi
     147             : 
     148             :   ! args
     149             :     integer,  intent(in)    :: ncol, lchnk
     150             :     real(r8), intent(in)    :: dust_flux_in(:,:)
     151             :     real(r8), intent(inout) :: cflx(:,:)
     152             :     real(r8), intent(out)   :: soil_erod(:)
     153             : 
     154             :   ! local vars
     155             :     integer :: i, m, idst, inum
     156             :     real(r8) :: x_mton
     157             :     real(r8),parameter :: soil_erod_threshold = 0.1_r8
     158             : 
     159             :     ! set dust emissions
     160             : 
     161      982224 :     col_loop: do i =1,ncol
     162             : 
     163      923400 :        soil_erod(i) = soil_erodibility( i, lchnk )
     164             : 
     165      923400 :        if( soil_erod(i) .lt. soil_erod_threshold ) soil_erod(i) = 0._r8
     166             : 
     167             :        ! rebin and adjust dust emissons..
     168     3752424 :        do m = 1,dust_nbin
     169             : 
     170     2770200 :           idst = dust_indices(m)
     171             : 
     172     2770200 :           cflx(i,idst) = sum( -dust_flux_in(i,:) ) &
     173    16621200 :                * dust_emis_sclfctr(m)*soil_erod(i)/soil_erod_fact*1.15_r8
     174             : 
     175     2770200 :           x_mton = 6._r8 / (pi * dust_density * (dust_dmt_vwr(m)**3._r8))
     176             : 
     177     2770200 :           inum = dust_indices(m+dust_nbin)
     178             : 
     179     3693600 :           cflx(i,inum) = cflx(i,idst)*x_mton
     180             : 
     181             :        enddo
     182             : 
     183             :     end do col_loop
     184             : 
     185       58824 :   end subroutine dust_emis
     186             : 
     187             : end module dust_model

Generated by: LCOV version 1.14