LCOV - code coverage report
Current view: top level - physics/cam - pkg_cldoptics.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 62 63 98.4 %
Date: 2025-01-13 21:54:50 Functions: 6 6 100.0 %

          Line data    Source code
       1             : module pkg_cldoptics
       2             : 
       3             : !---------------------------------------------------------------------------------
       4             : ! Purpose:
       5             : !
       6             : ! Compute cloud optical properties: liquid and ice partical size; emissivity
       7             : !
       8             : ! Author: Byron Boville  Sept 06, 2002, assembled from existing subroutines
       9             : !
      10             : !---------------------------------------------------------------------------------
      11             : 
      12             :   use shr_kind_mod,  only: r8=>shr_kind_r8
      13             :   use ppgrid,        only: pcols, pver, pverp
      14             : 
      15             :   implicit none
      16             :   private
      17             :   save
      18             : 
      19             :   public :: cldefr, cldems, cldovrlap, cldclw, reitab, reltab
      20             : 
      21             : contains
      22             : 
      23             : !===============================================================================
      24     1495368 :   subroutine cldefr(lchnk   ,ncol    , &
      25             :        landfrac,t       ,rel     ,rei     ,ps      ,pmid    , landm, icefrac, snowh)
      26             : !----------------------------------------------------------------------- 
      27             : ! 
      28             : ! Purpose: 
      29             : ! Compute cloud water and ice particle size 
      30             : ! 
      31             : ! Method: 
      32             : ! use empirical formulas to construct effective radii
      33             : ! 
      34             : ! Author: J.T. Kiehl, B. A. Boville, P. Rasch
      35             : ! 
      36             : !-----------------------------------------------------------------------
      37             : 
      38             : !------------------------------Arguments--------------------------------
      39             : !
      40             : ! Input arguments
      41             : !
      42             :     integer, intent(in) :: lchnk                 ! chunk identifier
      43             :     integer, intent(in) :: ncol                  ! number of atmospheric columns
      44             : 
      45             :     real(r8), intent(in) :: landfrac(pcols)      ! Land fraction
      46             :     real(r8), intent(in) :: icefrac(pcols)       ! Ice fraction
      47             :     real(r8), intent(in) :: t(pcols,pver)        ! Temperature
      48             :     real(r8), intent(in) :: ps(pcols)            ! Surface pressure
      49             :     real(r8), intent(in) :: pmid(pcols,pver)     ! Midpoint pressures
      50             :     real(r8), intent(in) :: landm(pcols)
      51             :     real(r8), intent(in) :: snowh(pcols)         ! Snow depth over land, water equivalent (m)
      52             : !
      53             : ! Output arguments
      54             : !
      55             :     real(r8), intent(out) :: rel(pcols,pver)      ! Liquid effective drop size (microns)
      56             :     real(r8), intent(out) :: rei(pcols,pver)      ! Ice effective drop size (microns)
      57             : !
      58             : ! following Kiehl
      59     1495368 :          call reltab(ncol, t, landfrac, landm, icefrac, rel, snowh)
      60             : 
      61             : ! following Kristjansson and Mitchell
      62     1495368 :          call reitab(ncol, t, rei)
      63             : 
      64     1495368 :     return
      65             :   end subroutine cldefr
      66             : 
      67             : !===============================================================================
      68      749232 :   subroutine cldems(lchnk   ,ncol    ,clwp    ,fice    ,rei     ,emis    ,cldtau)
      69             : !----------------------------------------------------------------------- 
      70             : ! 
      71             : ! Purpose: 
      72             : ! Compute cloud emissivity using cloud liquid water path (g/m**2)
      73             : ! 
      74             : ! Method: 
      75             : ! <Describe the algorithm(s) used in the routine.> 
      76             : ! <Also include any applicable external references.> 
      77             : ! 
      78             : ! Author: J.T. Kiehl
      79             : ! 
      80             : !-----------------------------------------------------------------------
      81             : 
      82             :     use phys_control,    only: phys_getopts
      83             : 
      84             : !------------------------------Parameters-------------------------------
      85             : !
      86             :     real(r8) kabsl                  ! longwave liquid absorption coeff (m**2/g)
      87             :     parameter (kabsl = 0.090361_r8)
      88             : !
      89             : !------------------------------Arguments--------------------------------
      90             : !
      91             : ! Input arguments
      92             : !
      93             :     integer, intent(in) :: lchnk                   ! chunk identifier
      94             :     integer, intent(in) :: ncol                    ! number of atmospheric columns
      95             : 
      96             :     real(r8), intent(in) :: clwp(pcols,pver)       ! cloud liquid water path (g/m**2)
      97             :     real(r8), intent(in) :: rei(pcols,pver)        ! ice effective drop size (microns)
      98             :     real(r8), intent(in) :: fice(pcols,pver)       ! fractional ice content within cloud
      99             : !
     100             : ! Output arguments
     101             : !
     102             :     real(r8), intent(out) :: emis(pcols,pver)       ! cloud emissivity (fraction)
     103             :     real(r8), intent(out) :: cldtau(pcols,pver)     ! cloud optical depth
     104             : !
     105             : !---------------------------Local workspace-----------------------------
     106             : !
     107             :     integer i,k                 ! longitude, level indices
     108             :     real(r8) kabs                   ! longwave absorption coeff (m**2/g)
     109             :     real(r8) kabsi                  ! ice absorption coefficient
     110             : 
     111             :     character(len=16) :: microp_scheme  ! microphysics scheme
     112             : !-----------------------------------------------------------------------
     113             : !
     114      749232 :     call phys_getopts(microp_scheme_out=microp_scheme)
     115             : 
     116    20229264 :     do k=1,pver
     117   326020464 :        do i=1,ncol
     118             : 
     119             :           !note that optical properties for ice valid only
     120             :           !in range of 13 > rei > 130 micron (Ebert and Curry 92)
     121   305791200 :           if ( microp_scheme == 'RK' .or. microp_scheme == 'SPCAM_sam1mom') then
     122   305791200 :              kabsi = 0.005_r8 + 1._r8/rei(i,k)
     123             :           else
     124           0 :              kabsi = 0.005_r8 + 1._r8/min(max(13._r8,rei(i,k)),130._r8)
     125             :           end if
     126   305791200 :           kabs = kabsl*(1._r8-fice(i,k)) + kabsi*fice(i,k)
     127   305791200 :           emis(i,k) = 1._r8 - exp(-1.66_r8*kabs*clwp(i,k))
     128   325271232 :           cldtau(i,k) = kabs*clwp(i,k)
     129             :        end do
     130             :     end do
     131             : !
     132      749232 :     return
     133             :   end subroutine cldems
     134             : 
     135             : !===============================================================================
     136      749232 :   subroutine cldovrlap(lchnk   ,ncol    ,pint    ,cld     ,nmxrgn  ,pmxrgn  )
     137             : !----------------------------------------------------------------------- 
     138             : ! 
     139             : ! Purpose: 
     140             : ! Partitions each column into regions with clouds in neighboring layers.
     141             : ! This information is used to implement maximum overlap in these regions
     142             : ! with random overlap between them.
     143             : ! On output,
     144             : !    nmxrgn contains the number of regions in each column
     145             : !    pmxrgn contains the interface pressures for the lower boundaries of
     146             : !           each region! 
     147             : ! Method: 
     148             : 
     149             : ! 
     150             : ! Author: W. Collins
     151             : ! 
     152             : !-----------------------------------------------------------------------
     153             : 
     154             : !
     155             : ! Input arguments
     156             : !
     157             :     integer, intent(in) :: lchnk                ! chunk identifier
     158             :     integer, intent(in) :: ncol                 ! number of atmospheric columns
     159             : 
     160             :     real(r8), intent(in) :: pint(pcols,pverp)   ! Interface pressure
     161             :     real(r8), intent(in) :: cld(pcols,pver)     ! Fractional cloud cover
     162             : !
     163             : ! Output arguments
     164             : !
     165             :     integer,  intent(out) :: nmxrgn(pcols)      ! Number of maximally overlapped regions
     166             :     real(r8), intent(out) :: pmxrgn(pcols,pverp)! Maximum values of pressure for each
     167             : !    maximally overlapped region.
     168             : !    0->pmxrgn(i,1) is range of pressure for
     169             : !    1st region,pmxrgn(i,1)->pmxrgn(i,2) for
     170             : !    2nd region, etc
     171             : !
     172             : !---------------------------Local variables-----------------------------
     173             : !
     174             :     integer i                    ! Longitude index
     175             :     integer k                    ! Level index
     176             :     integer n                    ! Max-overlap region counter
     177             : 
     178             :     real(r8) pnm(pcols,pverp)    ! Interface pressure
     179             : 
     180             :     logical cld_found            ! Flag for detection of cloud
     181             :     logical cld_layer(pver)      ! Flag for cloud in layer
     182             : !
     183             : !------------------------------------------------------------------------
     184             : !
     185             : 
     186    12510432 :     do i = 1, ncol
     187    11761200 :        cld_found = .false.
     188   317552400 :        cld_layer(:) = cld(i,:) > 0.0_r8
     189   329313600 :        pmxrgn(i,:) = 0.0_r8
     190   329313600 :        pnm(i,:)=pint(i,:)*10._r8
     191             :        n = 1
     192   298541484 :        do k = 1, pver
     193   308032761 :           if (cld_layer(k) .and.  .not. cld_found) then
     194             :              cld_found = .true.
     195   278407392 :           else if ( .not. cld_layer(k) .and. cld_found) then
     196   106797867 :              cld_found = .false.
     197   106797867 :              if (count(cld_layer(k:pver)) == 0) then
     198             :                 exit
     199             :              endif
     200     6419595 :              pmxrgn(i,n) = pnm(i,k)
     201     6419595 :              n = n + 1
     202             :           endif
     203             :        end do
     204    11761200 :        pmxrgn(i,n) = pnm(i,pverp)
     205    12510432 :        nmxrgn(i) = n
     206             :     end do
     207             : 
     208      749232 :     return
     209             :   end subroutine cldovrlap
     210             : 
     211             : !===============================================================================
     212      749232 :   subroutine cldclw(lchnk   ,ncol    ,zi      ,clwp    ,tpw     ,hl      )
     213             : !----------------------------------------------------------------------- 
     214             : ! 
     215             : ! Purpose: 
     216             : ! Evaluate cloud liquid water path clwp (g/m**2)
     217             : ! 
     218             : ! Method: 
     219             : ! <Describe the algorithm(s) used in the routine.> 
     220             : ! <Also include any applicable external references.> 
     221             : ! 
     222             : ! Author: J.T. Kiehl
     223             : ! 
     224             : !-----------------------------------------------------------------------
     225             : 
     226             : 
     227             : !
     228             : ! Input arguments
     229             : !
     230             :     integer, intent(in) :: lchnk                 ! chunk identifier
     231             :     integer, intent(in) :: ncol                  ! number of atmospheric columns
     232             : 
     233             :     real(r8), intent(in) :: zi(pcols,pverp)      ! height at layer interfaces(m)
     234             :     real(r8), intent(in) :: tpw(pcols)           ! total precipitable water (mm)
     235             : !
     236             : ! Output arguments
     237             : !
     238             :     real(r8), intent(out) :: clwp(pcols,pver)     ! cloud liquid water path (g/m**2)
     239             :     real(r8), intent(out) :: hl(pcols)            ! liquid water scale height
     240             : 
     241             : !
     242             : !---------------------------Local workspace-----------------------------
     243             : !
     244             :     integer  :: i,k                  ! longitude, level indices
     245             :     real(r8) :: clwc0                ! reference liquid water concentration (g/m**3)
     246             :     real(r8) :: emziohl(pcols,pverp) ! exp(-zi/hl)
     247             :     real(r8) :: rhl(pcols)           ! 1/hl
     248             : !
     249             : !-----------------------------------------------------------------------
     250             : !
     251             : ! Set reference liquid water concentration
     252             : !
     253      749232 :     clwc0 = 0.21_r8
     254             : !
     255             : ! Diagnose liquid water scale height from precipitable water
     256             : !
     257    12510432 :     do i=1,ncol
     258    11761200 :        hl(i)  = 700.0_r8*log(max(tpw(i)+1.0_r8,1.0_r8))
     259    12510432 :        rhl(i) = 1.0_r8/hl(i)
     260             :     end do
     261             : !
     262             : ! Evaluate cloud liquid water path (vertical integral of exponential fn)
     263             : !
     264    20978496 :     do k=1,pverp
     265   338530896 :        do i=1,ncol
     266   337781664 :           emziohl(i,k) = exp(-zi(i,k)*rhl(i))
     267             :        end do
     268             :     end do
     269    20229264 :     do k=1,pver
     270   326020464 :        do i=1,ncol
     271   325271232 :           clwp(i,k) = clwc0*hl(i)*(emziohl(i,k+1) - emziohl(i,k))
     272             :        end do
     273             :     end do
     274             : !
     275      749232 :     return
     276             :   end subroutine cldclw
     277             : 
     278             : 
     279             : !===============================================================================
     280     2990736 :   subroutine reltab(ncol, t, landfrac, landm, icefrac, rel, snowh)
     281             : !----------------------------------------------------------------------- 
     282             : ! 
     283             : ! Purpose: 
     284             : ! Compute cloud water size
     285             : ! 
     286             : ! Method: 
     287             : ! analytic formula following the formulation originally developed by J. T. Kiehl
     288             : ! 
     289             : ! Author: Phil Rasch
     290             : ! 
     291             : !-----------------------------------------------------------------------
     292             :     use physconst,          only: tmelt
     293             : !------------------------------Arguments--------------------------------
     294             : !
     295             : ! Input arguments
     296             : !
     297             :     integer, intent(in) :: ncol
     298             :     real(r8), intent(in) :: landfrac(pcols)      ! Land fraction
     299             :     real(r8), intent(in) :: icefrac(pcols)       ! Ice fraction
     300             :     real(r8), intent(in) :: snowh(pcols)         ! Snow depth over land, water equivalent (m)
     301             :     real(r8), intent(in) :: landm(pcols)         ! Land fraction ramping to zero over ocean
     302             :     real(r8), intent(in) :: t(pcols,pver)        ! Temperature
     303             : 
     304             : !
     305             : ! Output arguments
     306             : !
     307             :     real(r8), intent(out) :: rel(pcols,pver)      ! Liquid effective drop size (microns)
     308             : !
     309             : !---------------------------Local workspace-----------------------------
     310             : !
     311             :     integer i,k               ! Lon, lev indices
     312             :     real(r8) rliqland         ! liquid drop size if over land
     313             :     real(r8) rliqocean        ! liquid drop size if over ocean
     314             :     real(r8) rliqice          ! liquid drop size if over sea ice
     315             : !
     316             : !-----------------------------------------------------------------------
     317             : !
     318     2990736 :     rliqocean = 14.0_r8
     319     2990736 :     rliqice   = 14.0_r8
     320     2990736 :     rliqland  = 8.0_r8
     321    80749872 :     do k=1,pver
     322  1301387472 :        do i=1,ncol
     323             : ! jrm Reworked effective radius algorithm
     324             :           ! Start with temperature-dependent value appropriate for continental air
     325             :           ! Note: findmcnew has a pressure dependence here
     326  1220637600 :           rel(i,k) = rliqland + (rliqocean-rliqland) * min(1.0_r8,max(0.0_r8,(tmelt-t(i,k))*0.05_r8))
     327             :           ! Modify for snow depth over land
     328  1220637600 :           rel(i,k) = rel(i,k) + (rliqocean-rel(i,k)) * min(1.0_r8,max(0.0_r8,snowh(i)*10._r8))
     329             :           ! Ramp between polluted value over land to clean value over ocean.
     330  1220637600 :           rel(i,k) = rel(i,k) + (rliqocean-rel(i,k)) * min(1.0_r8,max(0.0_r8,1.0_r8-landm(i)))
     331             :           ! Ramp between the resultant value and a sea ice value in the presence of ice.
     332  1298396736 :           rel(i,k) = rel(i,k) + (rliqice-rel(i,k)) * min(1.0_r8,max(0.0_r8,icefrac(i)))
     333             : ! end jrm
     334             :        end do
     335             :     end do
     336     2990736 :   end subroutine reltab
     337             : 
     338             : !===============================================================================
     339     2990736 :   subroutine reitab(ncol, t, re)
     340             : 
     341             :     integer, intent(in) :: ncol
     342             :     real(r8), intent(out) :: re(pcols,pver)
     343             :     real(r8), intent(in) :: t(pcols,pver)
     344             :     integer , parameter :: len_retab = 138
     345             :     real(r8), parameter :: min_retab = 136._r8
     346             :     real(r8) retab(len_retab)
     347             :     real(r8) corr
     348             :     integer i
     349             :     integer k
     350             :     integer index
     351             :     !
     352             :     !       Tabulated values of re(T) in the temperature interval
     353             :     !       180 K -- 274 K; hexagonal columns assumed:
     354             :     !
     355             :     !       Modified for pmc formation: 136K -- 274K    
     356             :     !
     357             :     data retab /                                                &
     358             :          0.05_r8,    0.05_r8,    0.05_r8,    0.05_r8,    0.05_r8,   0.05_r8,      &
     359             :          0.055_r8,   0.06_r8,    0.07_r8,    0.08_r8,    0.09_r8,    0.1_r8,      &
     360             :          0.2_r8,     0.3_r8,     0.40_r8,    0.50_r8,    0.60_r8,    0.70_r8,     &
     361             :          0.8_r8 ,    0.9_r8,     1.0_r8,     1.1_r8,     1.2_r8,     1.3_r8,      &
     362             :          1.4_r8,     1.5_r8,     1.6_r8,     1.8_r8,     2.0_r8,     2.2_r8,      &
     363             :          2.4_r8,     2.6_r8,     2.8_r8,     3.0_r8,     3.2_r8,     3.5_r8,      &
     364             :          3.8_r8,     4.1_r8,     4.4_r8,     4.7_r8,     5.0_r8,     5.3_r8,      &
     365             :          5.6_r8, &
     366             :          5.92779_r8, 6.26422_r8, 6.61973_r8, 6.99539_r8, 7.39234_r8,           &
     367             :          7.81177_r8, 8.25496_r8, 8.72323_r8, 9.21800_r8, 9.74075_r8, 10.2930_r8,        &
     368             :          10.8765_r8, 11.4929_r8, 12.1440_r8, 12.8317_r8, 13.5581_r8, 14.2319_r8,        &
     369             :          15.0351_r8, 15.8799_r8, 16.7674_r8, 17.6986_r8, 18.6744_r8, 19.6955_r8,        &
     370             :          20.7623_r8, 21.8757_r8, 23.0364_r8, 24.2452_r8, 25.5034_r8, 26.8125_r8,        &
     371             :          27.7895_r8, 28.6450_r8, 29.4167_r8, 30.1088_r8, 30.7306_r8, 31.2943_r8,        &
     372             :          31.8151_r8, 32.3077_r8, 32.7870_r8, 33.2657_r8, 33.7540_r8, 34.2601_r8,        &
     373             :          34.7892_r8, 35.3442_r8, 35.9255_r8, 36.5316_r8, 37.1602_r8, 37.8078_r8,        &
     374             :          38.4720_r8, 39.1508_r8, 39.8442_r8, 40.5552_r8, 41.2912_r8, 42.0635_r8,        &
     375             :          42.8876_r8, 43.7863_r8, 44.7853_r8, 45.9170_r8, 47.2165_r8, 48.7221_r8,        &
     376             :          50.4710_r8, 52.4980_r8, 54.8315_r8, 57.4898_r8, 60.4785_r8, 63.7898_r8,        &
     377             :          65.5604_r8, 71.2885_r8, 75.4113_r8, 79.7368_r8, 84.2351_r8, 88.8833_r8,        &
     378             :          93.6658_r8, 98.5739_r8, 103.603_r8, 108.752_r8, 114.025_r8, 119.424_r8,        &
     379             :          124.954_r8, 130.630_r8, 136.457_r8, 142.446_r8, 148.608_r8, 154.956_r8,        &
     380             :          161.503_r8, 168.262_r8, 175.248_r8, 182.473_r8, 189.952_r8, 197.699_r8,        &
     381             :          205.728_r8, 214.055_r8, 222.694_r8, 231.661_r8, 240.971_r8, 250.639_r8/        
     382             :     !
     383             :     save retab
     384             :     !
     385             : 
     386    80749872 :     do k=1,pver
     387  1301387472 :        do i=1,ncol
     388  1220637600 :           index = int(t(i,k)-min_retab)
     389  1220637600 :           index = min(max(index,1),len_retab-1)
     390  1220637600 :           corr = t(i,k) - int(t(i,k))
     391  1220637600 :           re(i,k) = retab(index)*(1._r8-corr)           &
     392  2519034336 :                +retab(index+1)*corr
     393             :           !           re(i,k) = amax1(amin1(re(i,k),30.),10.)
     394             :        end do
     395             :     end do
     396             :     !
     397     2990736 :     return
     398             :   end subroutine reitab
     399             : 
     400             : end module pkg_cldoptics

Generated by: LCOV version 1.14