LCOV - code coverage report
Current view: | top level - physics/cam - oldcloud_optics.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 9 | 111 | 8.1 %
Date: | 2024-12-17 17:57:11 |  | Functions: | 1 | 4 | 25.0 %

              Line data    Source code
           1             : module oldcloud_optics
           2             :
           3             : !------------------------------------------------------------------------------------------------
           4             : !------------------------------------------------------------------------------------------------
           5             :
           6             : use shr_kind_mod,     only: r8 => shr_kind_r8
           7             : use ppgrid,           only: pcols, pver, pverp
           8             : use physics_types,    only: physics_state
           9             : use physics_buffer,   only: physics_buffer_desc, pbuf_get_index, pbuf_old_tim_idx, pbuf_get_field
          10             : use constituents,     only: cnst_get_ind
          11             : use physconst,        only: gravit
          12             : use radconstants,     only: nlwbands
          13             : use ebert_curry_ice_optics, only: scalefactor
          14             :
          15             : use cam_abortutils,   only: endrun
          16             :
          17             : implicit none
          18             : private
          19             : save
          20             :
          21             : public :: &
          22             :    oldcloud_init,            &
          23             :    oldcloud_lw,              &
          24             :    old_liq_get_rad_props_lw, &
          25             :    old_ice_get_rad_props_lw
          26             :
          27             : integer :: nmu, nlambda
          28             : real(r8), allocatable :: g_mu(:)           ! mu samples on grid
          29             : real(r8), allocatable :: g_lambda(:,:)     ! lambda scale samples on grid
          30             : real(r8), allocatable :: ext_sw_liq(:,:,:)
          31             : real(r8), allocatable :: ssa_sw_liq(:,:,:)
          32             : real(r8), allocatable :: asm_sw_liq(:,:,:)
          33             : real(r8), allocatable :: abs_lw_liq(:,:,:)
          34             :
          35             : integer :: n_g_d
          36             : real(r8), allocatable :: g_d_eff(:)        ! radiative effective diameter samples on grid
          37             : real(r8), allocatable :: ext_sw_ice(:,:)
          38             : real(r8), allocatable :: ssa_sw_ice(:,:)
          39             : real(r8), allocatable :: asm_sw_ice(:,:)
          40             : real(r8), allocatable :: abs_lw_ice(:,:)
          41             :
          42             : ! Minimum cloud amount (as a fraction of the grid-box area) to
          43             : ! distinguish from clear sky
          44             : real(r8), parameter :: cldmin = 1.0e-80_r8
          45             :
          46             : ! Decimal precision of cloud amount (0 -> preserve full resolution;
          47             : ! 10^-n -> preserve n digits of cloud amount)
          48             : real(r8), parameter :: cldeps = 0.0_r8
          49             :
          50             : ! indexes into pbuf
          51             : integer :: iciwp_idx   = 0
          52             : integer :: iclwp_idx   = 0
          53             : integer :: cld_idx     = 0
          54             : integer :: rel_idx     = 0
          55             : integer :: rei_idx     = 0
          56             :
          57             : ! indexes into constituents for old optics
          58             : integer :: &
          59             :    ixcldice, & ! cloud ice water index
          60             :    ixcldliq    ! cloud liquid water index
          61             :
          62             :
          63             : !==============================================================================
          64             : contains
          65             : !==============================================================================
          66             :
          67        1536 : subroutine oldcloud_init()
          68             :
          69             :
          70             :    integer :: err
          71             :
          72        1536 :    iciwp_idx  = pbuf_get_index('ICIWP',errcode=err)
          73        1536 :    iclwp_idx  = pbuf_get_index('ICLWP',errcode=err)
          74        1536 :    cld_idx    = pbuf_get_index('CLD')
          75        1536 :    rel_idx    = pbuf_get_index('REL')
          76        1536 :    rei_idx    = pbuf_get_index('REI')
          77             :
          78             :    ! old optics
          79        1536 :    call cnst_get_ind('CLDICE', ixcldice)
          80        1536 :    call cnst_get_ind('CLDLIQ', ixcldliq)
          81             :
          82        1536 : end subroutine oldcloud_init
          83             :
          84             : !==============================================================================
          85             :
          86           0 : subroutine oldcloud_lw(state,pbuf,cld_abs_od,oldwp)
          87             :
          88             :    type(physics_state), intent(in) :: state
          89             :    type(physics_buffer_desc),pointer :: pbuf(:)
          90             :    real(r8),            intent(out) :: cld_abs_od(nlwbands,pcols,pver) ! [fraction] absorption optical depth, per layer
          91             :    logical,intent(in)              :: oldwp ! use old definition of waterpath
          92             :
          93             :
          94             :    real(r8) :: gicewp(pcols,pver)
          95             :    real(r8) :: gliqwp(pcols,pver)
          96             :    real(r8) :: cicewp(pcols,pver)
          97             :    real(r8) :: cliqwp(pcols,pver)
          98             :    real(r8) :: ficemr(pcols,pver)
          99             :    real(r8) :: cwp(pcols,pver)
         100             :    real(r8) :: cldtau(pcols,pver)
         101             :
         102           0 :    real(r8), pointer, dimension(:,:) :: cldn
         103           0 :    real(r8), pointer, dimension(:,:) :: rei
         104             :    integer :: ncol, itim_old, lwband, i, k, lchnk
         105           0 :    real(r8), pointer, dimension(:,:) :: iclwpth, iciwpth
         106             :
         107             :    real(r8) :: kabs, kabsi
         108             :    real(r8), parameter :: kabsl = 0.090361_r8 ! longwave liquid absorption coeff (m**2/g)
         109             :
         110             :
         111           0 :    ncol = state%ncol
         112           0 :    lchnk = state%lchnk
         113             :
         114           0 :    itim_old  =  pbuf_old_tim_idx()
         115           0 :    call pbuf_get_field(pbuf, rei_idx,   rei)
         116           0 :    call pbuf_get_field(pbuf, cld_idx,   cldn,   start=(/1,1,itim_old/), kount=(/pcols,pver,1/))
         117             :
         118           0 :    if (oldwp) then
         119           0 :      do k=1,pver
         120           0 :          do i = 1,ncol
         121           0 :             gicewp(i,k) = state%q(i,k,ixcldice)*state%pdel(i,k)/gravit*1000.0_r8  ! Grid box ice water path.
         122           0 :             gliqwp(i,k) = state%q(i,k,ixcldliq)*state%pdel(i,k)/gravit*1000.0_r8  ! Grid box liquid water path.
         123           0 :             cicewp(i,k) = gicewp(i,k) / max(0.01_r8,cldn(i,k))                 ! In-cloud ice water path.
         124           0 :             cliqwp(i,k) = gliqwp(i,k) / max(0.01_r8,cldn(i,k))                 ! In-cloud liquid water path.
         125             :             ficemr(i,k) = state%q(i,k,ixcldice) /                 &
         126           0 :                  max(1.e-10_r8,(state%q(i,k,ixcldice)+state%q(i,k,ixcldliq)))
         127             :          end do
         128             :      end do
         129           0 :      cwp(:ncol,:pver) = cicewp(:ncol,:pver) + cliqwp(:ncol,:pver)
         130             :    else
         131           0 :       if (iclwp_idx<=0 .or. iciwp_idx<=0) then
         132           0 :          call endrun('oldcloud_lw: oldwp must be set to true since ICIWP and/or ICLWP were not found in pbuf')
         133             :       endif
         134           0 :       call pbuf_get_field(pbuf, iclwp_idx, iclwpth)
         135           0 :       call pbuf_get_field(pbuf, iciwp_idx, iciwpth)
         136           0 :       do k=1,pver
         137           0 :          do i = 1,ncol
         138           0 :             cwp(i,k) = 1000.0_r8 *iclwpth(i,k) + 1000.0_r8 *iciwpth(i, k)
         139           0 :             ficemr(i,k) = 1000.0_r8 * iciwpth(i,k)/(max(1.e-18_r8,cwp(i,k)))
         140             :          end do
         141             :       end do
         142             :    endif
         143             :
         144           0 :    do k=1,pver
         145           0 :        do i=1,ncol
         146             :
         147             :           !note that optical properties for ice valid only
         148             :           !in range of 13 > rei > 130 micron (Ebert and Curry 92)
         149           0 :           kabsi = 0.005_r8 + 1._r8/min(max(13._r8,scalefactor*rei(i,k)),130._r8)
         150           0 :           kabs = kabsl*(1._r8-ficemr(i,k)) + kabsi*ficemr(i,k)
         151           0 :           cldtau(i,k) = kabs*cwp(i,k)
         152             :        end do
         153             :    end do
         154             : !
         155           0 :    do lwband = 1,nlwbands
         156           0 :       cld_abs_od(lwband,1:ncol,1:pver)=cldtau(1:ncol,1:pver)
         157             :    enddo
         158             :
         159           0 : end subroutine oldcloud_lw
         160             :
         161             : !==============================================================================
         162             :
         163           0 : subroutine old_liq_get_rad_props_lw(state, pbuf, abs_od, oldliqwp)
         164             :
         165             :    type(physics_state), intent(in)  :: state
         166             :    type(physics_buffer_desc),pointer  :: pbuf(:)
         167             :    real(r8), intent(out) :: abs_od(nlwbands,pcols,pver)
         168             :    logical, intent(in) :: oldliqwp
         169             :
         170             :    real(r8) :: gicewp(pcols,pver)
         171             :    real(r8) :: gliqwp(pcols,pver)
         172             :    real(r8) :: cicewp(pcols,pver)
         173             :    real(r8) :: cliqwp(pcols,pver)
         174             :    real(r8) :: ficemr(pcols,pver)
         175             :    real(r8) :: cwp(pcols,pver)
         176             :    real(r8) :: cldtau(pcols,pver)
         177             :
         178           0 :    real(r8), pointer, dimension(:,:) :: cldn
         179           0 :    real(r8), pointer, dimension(:,:) :: rei
         180             :    integer :: ncol, itim_old, lwband, i, k, lchnk
         181             :
         182             :    real(r8) :: kabs, kabsi
         183             :    real(r8), parameter :: kabsl = 0.090361_r8 ! longwave liquid absorption coeff (m**2/g)
         184             :
         185           0 :    real(r8), pointer, dimension(:,:) :: iclwpth, iciwpth
         186             :
         187           0 :    ncol=state%ncol
         188           0 :    lchnk = state%lchnk
         189             :
         190           0 :    itim_old  =  pbuf_old_tim_idx()
         191           0 :    call pbuf_get_field(pbuf, rei_idx,   rei)
         192           0 :    call pbuf_get_field(pbuf, cld_idx,   cldn,   start=(/1,1,itim_old/), kount=(/pcols,pver,1/))
         193             :
         194           0 :    if (oldliqwp) then
         195           0 :      do k=1,pver
         196           0 :          do i = 1,ncol
         197           0 :             gicewp(i,k) = state%q(i,k,ixcldice)*state%pdel(i,k)/gravit*1000.0_r8  ! Grid box ice water path.
         198           0 :             gliqwp(i,k) = state%q(i,k,ixcldliq)*state%pdel(i,k)/gravit*1000.0_r8  ! Grid box liquid water path.
         199           0 :             cicewp(i,k) = gicewp(i,k) / max(0.01_r8,cldn(i,k))                 ! In-cloud ice water path.
         200           0 :             cliqwp(i,k) = gliqwp(i,k) / max(0.01_r8,cldn(i,k))                 ! In-cloud liquid water path.
         201             :             ficemr(i,k) = state%q(i,k,ixcldice) /                 &
         202           0 :                  max(1.e-10_r8,(state%q(i,k,ixcldice)+state%q(i,k,ixcldliq)))
         203             :          end do
         204             :      end do
         205           0 :      cwp(:ncol,:pver) = cicewp(:ncol,:pver) + cliqwp(:ncol,:pver)
         206             :    else
         207           0 :       if (iclwp_idx<=0 .or. iciwp_idx<=0) then
         208           0 :          call endrun('old_liq_get_rad_props_lw: oldliqwp must be set to true since ICIWP and/or ICLWP were not found in pbuf')
         209             :       endif
         210           0 :       call pbuf_get_field(pbuf, iclwp_idx, iclwpth)
         211           0 :       call pbuf_get_field(pbuf, iciwp_idx, iciwpth)
         212           0 :       do k=1,pver
         213           0 :          do i = 1,ncol
         214           0 :             cwp(i,k) = 1000.0_r8 *iclwpth(i,k) + 1000.0_r8 *iciwpth(i, k)
         215           0 :             ficemr(i,k) = 1000.0_r8 * iciwpth(i,k)/(max(1.e-18_r8,cwp(i,k)))
         216             :          end do
         217             :       end do
         218             :    endif
         219             :
         220             :
         221           0 :    do k=1,pver
         222           0 :        do i=1,ncol
         223             :
         224             :           ! Note from Andrew Conley:
         225             :           !  Optics for RK no longer supported, This is constructed to get
         226             :           !  close to bit for bit.  Otherwise we could simply use liquid water path
         227             :           !note that optical properties for ice valid only
         228             :           !in range of 13 > rei > 130 micron (Ebert and Curry 92)
         229           0 :           kabsi = 0.005_r8 + 1._r8/min(max(13._r8,scalefactor*rei(i,k)),130._r8)
         230           0 :           kabs = kabsl*(1._r8-ficemr(i,k)) ! + kabsi*ficemr(i,k)
         231           0 :           cldtau(i,k) = kabs*cwp(i,k)
         232             :        end do
         233             :    end do
         234             :
         235           0 :    do lwband = 1,nlwbands
         236           0 :       abs_od(lwband,1:ncol,1:pver)=cldtau(1:ncol,1:pver)
         237             :    enddo
         238             :
         239             :
         240           0 : end subroutine old_liq_get_rad_props_lw
         241             :
         242             : !==============================================================================
         243             :
         244           0 : subroutine old_ice_get_rad_props_lw(state, pbuf, abs_od, oldicewp)
         245             :
         246             :    type(physics_state), intent(in)  :: state
         247             :    type(physics_buffer_desc),pointer  :: pbuf(:)
         248             :     real(r8), intent(out) :: abs_od(nlwbands,pcols,pver)
         249             :    logical, intent(in) :: oldicewp
         250             :
         251             :    real(r8) :: gicewp(pcols,pver)
         252             :    real(r8) :: gliqwp(pcols,pver)
         253             :    real(r8) :: cicewp(pcols,pver)
         254             :    real(r8) :: cliqwp(pcols,pver)
         255             :    real(r8) :: ficemr(pcols,pver)
         256             :    real(r8) :: cwp(pcols,pver)
         257             :    real(r8) :: cldtau(pcols,pver)
         258             :
         259           0 :    real(r8), pointer, dimension(:,:) :: cldn
         260           0 :    real(r8), pointer, dimension(:,:) :: rei
         261             :    integer :: ncol, itim_old, lwband, i, k, lchnk
         262             :
         263             :    real(r8) :: kabs, kabsi
         264             :    real(r8), parameter :: kabsl = 0.090361_r8 ! longwave liquid absorption coeff (m**2/g)
         265             :
         266           0 :    real(r8), pointer, dimension(:,:) :: iclwpth, iciwpth
         267             :
         268             :
         269           0 :    ncol = state%ncol
         270           0 :    lchnk = state%lchnk
         271             :
         272           0 :    itim_old  =  pbuf_old_tim_idx()
         273           0 :    call pbuf_get_field(pbuf, rei_idx,   rei)
         274           0 :    call pbuf_get_field(pbuf, cld_idx,   cldn,   start=(/1,1,itim_old/), kount=(/pcols,pver,1/))
         275             :
         276           0 :    if(oldicewp) then
         277           0 :      do k=1,pver
         278           0 :          do i = 1,ncol
         279           0 :             gicewp(i,k) = state%q(i,k,ixcldice)*state%pdel(i,k)/gravit*1000.0_r8  ! Grid box ice water path.
         280           0 :             gliqwp(i,k) = state%q(i,k,ixcldliq)*state%pdel(i,k)/gravit*1000.0_r8  ! Grid box liquid water path.
         281           0 :             cicewp(i,k) = gicewp(i,k) / max(0.01_r8,cldn(i,k))                 ! In-cloud ice water path.
         282           0 :             cliqwp(i,k) = gliqwp(i,k) / max(0.01_r8,cldn(i,k))                 ! In-cloud liquid water path.
         283             :             ficemr(i,k) = state%q(i,k,ixcldice) /                 &
         284           0 :                  max(1.e-10_r8,(state%q(i,k,ixcldice)+state%q(i,k,ixcldliq)))
         285             :          end do
         286             :      end do
         287           0 :      cwp(:ncol,:pver) = cicewp(:ncol,:pver) + cliqwp(:ncol,:pver)
         288             :    else
         289           0 :       if (iclwp_idx<=0 .or. iciwp_idx<=0) then
         290           0 :          call endrun('old_ice_get_rad_props_lw: oldicewp must be set to true since ICIWP and/or ICLWP were not found in pbuf')
         291             :       endif
         292           0 :       call pbuf_get_field(pbuf, iclwp_idx, iclwpth)
         293           0 :       call pbuf_get_field(pbuf, iciwp_idx, iciwpth)
         294           0 :       do k=1,pver
         295           0 :          do i = 1,ncol
         296           0 :             cwp(i,k) = 1000.0_r8 *iciwpth(i,k) + 1000.0_r8 *iclwpth(i,k)
         297           0 :             ficemr(i,k) = 1000.0_r8*iciwpth(i,k)/(max(1.e-18_r8,cwp(i,k)))
         298             :          end do
         299             :       end do
         300             :    endif
         301             :
         302           0 :    do k=1,pver
         303           0 :        do i=1,ncol
         304             :
         305             :           ! Note from Andrew Conley:
         306             :           !  Optics for RK no longer supported, This is constructed to get
         307             :           !  close to bit for bit.  Otherwise we could simply use ice water path
         308             :           !note that optical properties for ice valid only
         309             :           !in range of 13 > rei > 130 micron (Ebert and Curry 92)
         310           0 :           kabsi = 0.005_r8 + 1._r8/min(max(13._r8,scalefactor*rei(i,k)),130._r8)
         311           0 :           kabs =  kabsi*ficemr(i,k) ! kabsl*(1._r8-ficemr(i,k)) + kabsi*ficemr(i,k)
         312           0 :           cldtau(i,k) = kabs*cwp(i,k)
         313             :        end do
         314             :    end do
         315             :
         316           0 :    do lwband = 1,nlwbands
         317           0 :       abs_od(lwband,1:ncol,1:pver)=cldtau(1:ncol,1:pver)
         318             :    enddo
         319             :
         320           0 : end subroutine old_ice_get_rad_props_lw
         321             :
         322             : !==============================================================================
         323             :
         324             : end module oldcloud_optics

Generated by: LCOV version 1.14