LCOV - code coverage report
Current view: | top level - physics/cam - pbl_utils.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 32 | 92 | 34.8 %
Date: | 2025-01-13 21:54:50 |  | Functions: | 5 | 10 | 50.0 %

              Line data    Source code
           1             : module pbl_utils
           2             : !-----------------------------------------------------------------------!
           3             : ! Module to hold PBL-related subprograms that may be used with multiple !
           4             : ! different vertical diffusion schemes.                                 !
           5             : !                                                                       !
           6             : ! Public subroutines:                                                   !
           7             : !
           8             : !     calc_obklen                                                       !
           9             : !                                                                       !
          10             : !------------------ History --------------------------------------------!
          11             : ! Created: Apr. 2012, by S. Santos                                      !
          12             : !-----------------------------------------------------------------------!
          13             :
          14             : use shr_kind_mod, only: r8 => shr_kind_r8
          15             :
          16             : implicit none
          17             : private
          18             :
          19             : ! Public Procedures
          20             : !----------------------------------------------------------------------!
          21             : ! Excepting the initialization procedure, these are elemental
          22             : ! procedures, so they can accept scalars or any dimension of array as
          23             : ! arguments, as long as all arguments have the same number of
          24             : ! elements.
          25             : public pbl_utils_init
          26             : public calc_ustar
          27             : public calc_obklen
          28             : public virtem
          29             : public compute_radf
          30             : public austausch_atm, austausch_atm_free
          31             :
          32             : real(r8), parameter :: ustar_min = 0.01_r8
          33             :
          34             : real(r8) :: g         ! acceleration of gravity
          35             : real(r8) :: vk        ! Von Karman's constant
          36             : real(r8) :: cpair     ! specific heat of dry air
          37             : real(r8) :: rair      ! gas constant for dry air
          38             : real(r8) :: zvir      ! rh2o/rair - 1
          39             :
          40             :
          41             : !------------------------------------------------------------------------!
          42             : ! Purpose: Compilers aren't creating optimized vector versions of        !
          43             : !          elemental routines, so we'll explicitly create them and bind  !
          44             : !          them via an interface for transparent use                     !
          45             : !------------------------------------------------------------------------!
          46             : interface calc_ustar
          47             :   module procedure calc_ustar_scalar
          48             :   module procedure calc_ustar_vector
          49             : end interface
          50             :
          51             : interface calc_obklen
          52             :   module procedure calc_obklen_scalar
          53             :   module procedure calc_obklen_vector
          54             : end interface
          55             :
          56             : interface virtem
          57             :   module procedure virtem_vector1D
          58             :   module procedure virtem_vector2D  ! Used in hb_diff.F90
          59             : end interface
          60             :
          61             :
          62             :
          63             : contains
          64             :
          65        1536 : subroutine pbl_utils_init(g_in,vk_in,cpair_in,rair_in,zvir_in)
          66             :
          67             :   !-----------------------------------------------------------------------!
          68             :   ! Purpose: Set constants to be used in calls to later functions         !
          69             :   !-----------------------------------------------------------------------!
          70             :
          71             :   real(r8), intent(in) :: g_in       ! acceleration of gravity
          72             :   real(r8), intent(in) :: vk_in      ! Von Karman's constant
          73             :   real(r8), intent(in) :: cpair_in   ! specific heat of dry air
          74             :   real(r8), intent(in) :: rair_in    ! gas constant for dry air
          75             :   real(r8), intent(in) :: zvir_in    ! rh2o/rair - 1
          76             :
          77        1536 :   g = g_in
          78        1536 :   vk = vk_in
          79        1536 :   cpair = cpair_in
          80        1536 :   rair = rair_in
          81        1536 :   zvir = zvir_in
          82             :
          83        1536 : end subroutine pbl_utils_init
          84             :
          85           0 : subroutine calc_ustar_scalar( t,    pmid, taux, tauy, &
          86             :                                  rrho, ustar)
          87             :
          88             :   !-----------------------------------------------------------------------!
          89             :   ! Purpose: Calculate ustar and bottom level density (necessary for      !
          90             :   !  Obukhov length calculation).                                         !
          91             :   !-----------------------------------------------------------------------!
          92             :
          93             :   real(r8), intent(in) :: t         ! surface temperature
          94             :   real(r8), intent(in) :: pmid      ! midpoint pressure (bottom level)
          95             :   real(r8), intent(in) :: taux      ! surface u stress [N/m2]
          96             :   real(r8), intent(in) :: tauy      ! surface v stress [N/m2]
          97             :
          98             :   real(r8), intent(out) :: rrho     ! 1./bottom level density
          99             :   real(r8), intent(out) :: ustar    ! surface friction velocity [m/s]
         100             :
         101           0 :   rrho = rair * t / pmid
         102           0 :   ustar = max( sqrt( sqrt(taux**2 + tauy**2)*rrho ), ustar_min )
         103             :
         104           0 : end subroutine calc_ustar_scalar
         105             :
         106     1489176 : subroutine calc_ustar_vector(n, t, pmid, taux, tauy, &
         107     1489176 :                                  rrho, ustar)
         108             :
         109             :   !-----------------------------------------------------------------------!
         110             :   ! Purpose: Calculate ustar and bottom level density (necessary for      !
         111             :   !  Obukhov length calculation).                                         !
         112             :   !-----------------------------------------------------------------------!
         113             :   integer, intent(in) :: n             ! Length of vectors
         114             :
         115             :   real(r8), intent(in) :: t(n)         ! surface temperature
         116             :   real(r8), intent(in) :: pmid(n)      ! midpoint pressure (bottom level)
         117             :   real(r8), intent(in) :: taux(n)      ! surface u stress [N/m2]
         118             :   real(r8), intent(in) :: tauy(n)      ! surface v stress [N/m2]
         119             :
         120             :
         121             :   real(r8), intent(out) :: rrho(n)     ! 1./bottom level density
         122             :   real(r8), intent(out) :: ustar(n)    ! surface friction velocity [m/s]
         123             :
         124             :
         125    24865776 :   rrho = rair * t / pmid
         126    24865776 :   ustar = max( sqrt( sqrt(taux**2 + tauy**2)*rrho ), ustar_min )
         127             :
         128     1489176 : end subroutine calc_ustar_vector
         129             :
         130           0 : subroutine calc_obklen_scalar( ths,  thvs, qflx, shflx, rrho, ustar, &
         131             :                                   khfs, kqfs, kbfs, obklen)
         132             :
         133             :   !-----------------------------------------------------------------------!
         134             :   ! Purpose: Calculate Obukhov length and kinematic fluxes.               !
         135             :   !-----------------------------------------------------------------------!
         136             :
         137             :   real(r8), intent(in)  :: ths           ! potential temperature at surface [K]
         138             :   real(r8), intent(in)  :: thvs          ! virtual potential temperature at surface
         139             :   real(r8), intent(in)  :: qflx          ! water vapor flux (kg/m2/s)
         140             :   real(r8), intent(in)  :: shflx         ! surface heat flux (W/m2)
         141             :
         142             :   real(r8), intent(in)  :: rrho          ! 1./bottom level density [ m3/kg ]
         143             :   real(r8), intent(in)  :: ustar         ! Surface friction velocity [ m/s ]
         144             :
         145             :   real(r8), intent(out) :: khfs          ! sfc kinematic heat flux [mK/s]
         146             :   real(r8), intent(out) :: kqfs          ! sfc kinematic water vapor flux [m/s]
         147             :   real(r8), intent(out) :: kbfs          ! sfc kinematic buoyancy flux [m^2/s^3]
         148             :   real(r8), intent(out) :: obklen        ! Obukhov length
         149             :
         150             :   ! Need kinematic fluxes for Obukhov:
         151           0 :   khfs = shflx*rrho/cpair
         152           0 :   kqfs = qflx*rrho
         153           0 :   kbfs = khfs + zvir*ths*kqfs
         154             :
         155             :   ! Compute Obukhov length:
         156           0 :   obklen = -thvs * ustar**3 / (g*vk*(kbfs + sign(1.e-10_r8,kbfs)))
         157             :
         158           0 : end subroutine calc_obklen_scalar
         159             :
         160     1489176 : subroutine calc_obklen_vector(n, ths,  thvs, qflx, shflx, rrho, ustar, &
         161     1489176 :                                   khfs, kqfs, kbfs, obklen)
         162             :
         163             :   !-----------------------------------------------------------------------!
         164             :   ! Purpose: Calculate Obukhov length and kinematic fluxes.               !
         165             :   !-----------------------------------------------------------------------!
         166             :   integer, intent(in) :: n                  ! Length of vectors
         167             :
         168             :   real(r8), intent(in)  :: ths(n)           ! potential temperature at surface [K]
         169             :   real(r8), intent(in)  :: thvs(n)          ! virtual potential temperature at surface
         170             :   real(r8), intent(in)  :: qflx(n)          ! water vapor flux (kg/m2/s)
         171             :   real(r8), intent(in)  :: shflx(n)         ! surface heat flux (W/m2)
         172             :
         173             :   real(r8), intent(in)  :: rrho(n)          ! 1./bottom level density [ m3/kg ]
         174             :   real(r8), intent(in)  :: ustar(n)         ! Surface friction velocity [ m/s ]
         175             :
         176             :   real(r8), intent(out) :: khfs(n)          ! sfc kinematic heat flux [mK/s]
         177             :   real(r8), intent(out) :: kqfs(n)          ! sfc kinematic water vapor flux [m/s]
         178             :   real(r8), intent(out) :: kbfs(n)          ! sfc kinematic buoyancy flux [m^2/s^3]
         179             :   real(r8), intent(out) :: obklen(n)        ! Obukhov length
         180             :
         181             :
         182             :   ! Need kinematic fluxes for Obukhov:
         183    24865776 :   khfs = shflx*rrho/cpair
         184    24865776 :   kqfs = qflx*rrho
         185    24865776 :   kbfs = khfs + zvir*ths*kqfs
         186             :
         187             :   ! Compute Obukhov length:
         188    24865776 :   obklen = -thvs * ustar**3 / (g*vk*(kbfs + sign(1.e-10_r8,kbfs)))
         189             :
         190     1489176 : end subroutine calc_obklen_vector
         191             :
         192           0 : subroutine virtem_vector1D(n, t,q, virtem)
         193             :
         194             :   !-----------------------------------------------------------------------!
         195             :   ! Purpose: Calculate virtual temperature from temperature and specific  !
         196             :   !  humidity.                                                            !
         197             :   !-----------------------------------------------------------------------!
         198             :
         199             :   integer,  intent(in) :: n              ! vector length
         200             :
         201             :   real(r8), intent(in) :: t(n), q(n)
         202             :   real(r8), intent(out):: virtem(n)
         203             :
         204           0 :   virtem = t * (1.0_r8 + zvir*q)
         205             :
         206           0 : end subroutine virtem_vector1D
         207             :
         208     1489176 : subroutine virtem_vector2D(n, m, t, q, virtem)
         209             :
         210             :   !-----------------------------------------------------------------------!
         211             :   ! Purpose: Calculate virtual temperature from temperature and specific  !
         212             :   !  humidity.                                                            !
         213             :   !-----------------------------------------------------------------------!
         214             :
         215             :   integer,  intent(in) :: n, m            ! vector lengths
         216             :
         217             :   real(r8), intent(in) :: t(n,m), q(n,m)
         218             :   real(r8), intent(out):: virtem(n,m)
         219             :
         220   647999352 :   virtem = t * (1.0_r8 + zvir*q)
         221             :
         222     1489176 : end subroutine virtem_vector2D
         223             :
         224             :
         225           0 : subroutine compute_radf( choice_radf, i, pcols, pver, ncvmax, ncvfin, ktop, qmin, &
         226           0 :                          ql, pi, qrlw, g, cldeff, zi, chs, lwp_CL, opt_depth_CL,  &
         227           0 :                          radinvfrac_CL, radf_CL )
         228             :   ! -------------------------------------------------------------------------- !
         229             :   ! Purpose:                                                                   !
         230             :   ! Calculate cloud-top radiative cooling contribution to buoyancy production. !
         231             :   ! Here,  'radf' [m2/s3] is additional buoyancy flux at the CL top interface  !
         232             :   ! associated with cloud-top LW cooling being mainly concentrated near the CL !
         233             :   ! top interface ( just below CL top interface ).  Contribution of SW heating !
         234             :   ! within the cloud is not included in this radiative buoyancy production     !
         235             :   ! since SW heating is more broadly distributed throughout the CL top layer.  !
         236             :   ! -------------------------------------------------------------------------- !
         237             :
         238             :   !-----------------!
         239             :   ! Input variables !
         240             :   !-----------------!
         241             :   character(len=6), intent(in) :: choice_radf  ! Method for calculating radf
         242             :   integer,  intent(in)  :: i                   ! Index of current column
         243             :   integer,  intent(in)  :: pcols               ! Number of atmospheric columns
         244             :   integer,  intent(in)  :: pver                ! Number of atmospheric layers
         245             :   integer,  intent(in)  :: ncvmax              ! Max numbers of CLs (perhaps equal to pver)
         246             :   integer,  intent(in)  :: ncvfin(pcols)       ! Total number of CL in column
         247             :   integer,  intent(in)  :: ktop(pcols, ncvmax) ! ktop for current column
         248             :   real(r8), intent(in)  :: qmin                ! Minimum grid-mean LWC counted as clouds [kg/kg]
         249             :   real(r8), intent(in)  :: ql(pcols, pver)     ! Liquid water specific humidity [ kg/kg ]
         250             :   real(r8), intent(in)  :: pi(pcols, pver+1)   ! Interface pressures [ Pa ]
         251             :   real(r8), intent(in)  :: qrlw(pcols, pver)   ! Input grid-mean LW heating rate : [ K/s ] * cpair * dp = [ W/kg*Pa ]
         252             :   real(r8), intent(in)  :: g                   ! Gravitational acceleration
         253             :   real(r8), intent(in)  :: cldeff(pcols,pver)  ! Effective Cloud Fraction [fraction]
         254             :   real(r8), intent(in)  :: zi(pcols, pver+1)   ! Interface heights [ m ]
         255             :   real(r8), intent(in)  :: chs(pcols, pver+1)  ! Buoyancy coeffi. saturated sl (heat) coef. at all interfaces.
         256             :
         257             :   !------------------!
         258             :   ! Output variables !
         259             :   !------------------!
         260             :   real(r8), intent(out) :: lwp_CL(ncvmax)         ! LWP in the CL top layer [ kg/m2 ]
         261             :   real(r8), intent(out) :: opt_depth_CL(ncvmax)   ! Optical depth of the CL top layer
         262             :   real(r8), intent(out) :: radinvfrac_CL(ncvmax)  ! Fraction of LW radiative cooling confined in the top portion of CL
         263             :   real(r8), intent(out) :: radf_CL(ncvmax)        ! Buoyancy production at the CL top due to radiative cooling [ m2/s3 ]
         264             :
         265             :   !-----------------!
         266             :   ! Local variables !
         267             :   !-----------------!
         268             :   integer :: kt, ncv
         269             :   real(r8) :: lwp, opt_depth, radinvfrac, radf
         270             :
         271             :
         272             :   !-----------------!
         273             :   ! Begin main code !
         274             :   !-----------------!
         275           0 :   lwp_CL        = 0._r8
         276           0 :   opt_depth_CL  = 0._r8
         277           0 :   radinvfrac_CL = 0._r8
         278           0 :   radf_CL       = 0._r8
         279             :
         280             :   ! ---------------------------------------- !
         281             :   ! Perform do loop for individual CL regime !
         282             :   ! ---------------------------------------- !
         283           0 :   do ncv = 1, ncvfin(i)
         284           0 :     kt = ktop(i,ncv)
         285             :     !-----------------------------------------------------!
         286             :     ! Compute radf for each CL regime and for each column !
         287             :     !-----------------------------------------------------!
         288           0 :     if( choice_radf .eq. 'orig' ) then
         289           0 :       if( ql(i,kt) .gt. qmin .and. ql(i,kt-1) .lt. qmin ) then
         290           0 :         lwp       = ql(i,kt) * ( pi(i,kt+1) - pi(i,kt) ) / g
         291           0 :         opt_depth = 156._r8 * lwp  ! Estimated LW optical depth in the CL top layer
         292             :         ! Approximate LW cooling fraction concentrated at the inversion by using
         293             :         ! polynomial approx to exact formula 1-2/opt_depth+2/(exp(opt_depth)-1))
         294             :
         295           0 :         radinvfrac  = opt_depth * ( 4._r8 + opt_depth ) / ( 6._r8 * ( 4._r8 + opt_depth ) + opt_depth**2 )
         296           0 :         radf        = qrlw(i,kt) / ( pi(i,kt) - pi(i,kt+1) ) ! Cp*radiative cooling = [ W/kg ]
         297           0 :         radf        = max( radinvfrac * radf * ( zi(i,kt) - zi(i,kt+1) ), 0._r8 ) * chs(i,kt)
         298             :         ! We can disable cloud LW cooling contribution to turbulence by uncommenting:
         299             :         ! radf = 0._r8
         300             :       end if
         301             :
         302           0 :     elseif( choice_radf .eq. 'ramp' ) then
         303             :
         304           0 :       lwp         = ql(i,kt) * ( pi(i,kt+1) - pi(i,kt) ) / g
         305           0 :       opt_depth   = 156._r8 * lwp  ! Estimated LW optical depth in the CL top layer
         306           0 :       radinvfrac  = opt_depth * ( 4._r8 + opt_depth ) / ( 6._r8 * ( 4._r8 + opt_depth ) + opt_depth**2 )
         307           0 :       radinvfrac  = max(cldeff(i,kt)-cldeff(i,kt-1),0._r8) * radinvfrac
         308           0 :       radf        = qrlw(i,kt) / ( pi(i,kt) - pi(i,kt+1) ) ! Cp*radiative cooling [W/kg]
         309           0 :       radf        = max( radinvfrac * radf * ( zi(i,kt) - zi(i,kt+1) ), 0._r8 ) * chs(i,kt)
         310             :
         311           0 :     elseif( choice_radf .eq. 'maxi' ) then
         312             :
         313             :       ! Radiative flux divergence both in 'kt' and 'kt-1' layers are included
         314             :       ! 1. From 'kt' layer
         315           0 :         lwp         = ql(i,kt) * ( pi(i,kt+1) - pi(i,kt) ) / g
         316           0 :         opt_depth   = 156._r8 * lwp  ! Estimated LW optical depth in the CL top layer
         317           0 :         radinvfrac  = opt_depth * ( 4._r8 + opt_depth ) / ( 6._r8 * ( 4._r8 + opt_depth ) + opt_depth**2 )
         318           0 :         radf        = max( radinvfrac * qrlw(i,kt) / ( pi(i,kt) - pi(i,kt+1) ) * ( zi(i,kt) - zi(i,kt+1) ), 0._r8 )
         319             :       ! 2. From 'kt-1' layer and add the contribution from 'kt' layer
         320           0 :         lwp         = ql(i,kt-1) * ( pi(i,kt) - pi(i,kt-1) ) / g
         321           0 :         opt_depth   = 156._r8 * lwp  ! Estimated LW optical depth in the CL top layer
         322           0 :         radinvfrac  = opt_depth * ( 4._r8 + opt_depth ) / ( 6._r8 * ( 4._r8 + opt_depth) + opt_depth**2 )
         323           0 :         radf        = radf + max( radinvfrac * qrlw(i,kt-1) / ( pi(i,kt-1) - pi(i,kt) ) * ( zi(i,kt-1) - zi(i,kt) ), 0._r8 )
         324           0 :         radf        = max( radf, 0._r8 ) * chs(i,kt)
         325             :
         326             :     endif
         327             :
         328           0 :     lwp_CL(ncv)        = lwp
         329           0 :     opt_depth_CL(ncv)  = opt_depth
         330           0 :     radinvfrac_CL(ncv) = radinvfrac
         331           0 :     radf_CL(ncv)       = radf
         332             :   end do ! ncv = 1, ncvfin(i)
         333           0 : end subroutine compute_radf
         334             :
         335     1489176 : subroutine austausch_atm(pcols, ncol, pver, ntop, nbot, ml2, ri, s2, kvf)
         336             :
         337             :   !---------------------------------------------------------------------- !
         338             :   !                                                                       !
         339             :   ! Purpose: Computes exchange coefficients for free turbulent flows.     !
         340             :   !                                                                       !
         341             :   ! Method:                                                               !
         342             :   !                                                                       !
         343             :   ! The free atmosphere diffusivities are based on standard mixing length !
         344             :   ! forms for the neutral diffusivity multiplied by functns of Richardson !
         345             :   ! number. K = l^2 * |dV/dz| * f(Ri). The same functions are used for    !
         346             :   ! momentum, potential temperature, and constitutents.                   !
         347             :   !                                                                       !
         348             :   ! The stable Richardson num function (Ri>0) is taken from Holtslag and  !
         349             :   ! Beljaars (1989), ECMWF proceedings. f = 1 / (1 + 10*Ri*(1 + 8*Ri))    !
         350             :   ! The unstable Richardson number function (Ri<0) is taken from  CCM1.   !
         351             :   ! f = sqrt(1 - 18*Ri)                                                   !
         352             :   !                                                                       !
         353             :   ! Author: B. Stevens (rewrite, August 2000)                             !
         354             :   !                                                                       !
         355             :   !---------------------------------------------------------------------- !
         356             :
         357             :   ! --------------- !
         358             :   ! Input arguments !
         359             :   ! --------------- !
         360             :
         361             :   integer,  intent(in)  :: pcols                ! Atmospheric columns dimension size
         362             :   integer,  intent(in)  :: ncol                 ! Number of atmospheric columns
         363             :   integer,  intent(in)  :: pver                 ! Number of atmospheric layers
         364             :   integer,  intent(in)  :: ntop                 ! Top layer for calculation
         365             :   integer,  intent(in)  :: nbot                 ! Bottom layer for calculation
         366             :
         367             :   real(r8), intent(in)  :: ml2(pver+1)          ! Mixing lengths squared
         368             :   real(r8), intent(in)  :: s2(pcols,pver)       ! Shear squared
         369             :   real(r8), intent(in)  :: ri(pcols,pver)       ! Richardson no
         370             :
         371             :   ! ---------------- !
         372             :   ! Output arguments !
         373             :   ! ---------------- !
         374             :
         375             :   real(r8), intent(out) :: kvf(pcols,pver+1)    ! Eddy diffusivity for heat and tracers
         376             :
         377             :   ! --------------- !
         378             :   ! Local Variables !
         379             :   ! --------------- !
         380             :
         381             :   real(r8)              :: fofri                ! f(ri)
         382             :   real(r8)              :: kvn                  ! Neutral Kv
         383             :
         384             :   integer               :: i                    ! Longitude index
         385             :   integer               :: k                    ! Vertical index
         386             :
         387             :   real(r8), parameter :: zkmin =  0.01_r8       ! Minimum kneutral*f(ri).
         388             :
         389             :   ! ----------------------- !
         390             :   ! Main Computation Begins !
         391             :   ! ----------------------- !
         392             :
         393   672865128 :   kvf(:ncol,:)           = 0.0_r8
         394             :
         395             :   ! Compute the free atmosphere vertical diffusion coefficients: kvh = kvq = kvm.
         396             :
         397    38718576 :   do k = ntop, nbot - 1
         398   623133576 :      do i = 1, ncol
         399   584415000 :         if( ri(i,k) < 0.0_r8 ) then
         400    12022687 :            fofri = sqrt( max( 1._r8 - 18._r8 * ri(i,k), 0._r8 ) )
         401             :         else
         402   572392313 :            fofri = 1.0_r8 / ( 1.0_r8 + 10.0_r8 * ri(i,k) * ( 1.0_r8 + 8.0_r8 * ri(i,k) ) )
         403             :         end if
         404   584415000 :         kvn = ml2(k) * sqrt(s2(i,k))
         405   621644400 :         kvf(i,k+1) = max( zkmin, kvn * fofri )
         406             :      end do
         407             :   end do
         408             :
         409     1489176 : end subroutine austausch_atm
         410             :
         411           0 : subroutine austausch_atm_free(pcols, ncol, pver, ntop, nbot, ml2, ri, s2, kvf)
         412             :
         413             :   !---------------------------------------------------------------------- !
         414             :   !                                                                       !
         415             :   ! same as austausch_atm but only mixing for Ri<0                        !
         416             :   ! i.e. no background mixing and mixing for Ri>0                         !
         417             :   !                                                                       !
         418             :   !---------------------------------------------------------------------- !
         419             :
         420             :   ! --------------- !
         421             :   ! Input arguments !
         422             :   ! --------------- !
         423             :
         424             :   integer,  intent(in)  :: pcols                ! Atmospheric columns dimension size
         425             :   integer,  intent(in)  :: ncol                 ! Number of atmospheric columns
         426             :   integer,  intent(in)  :: pver                 ! Number of atmospheric layers
         427             :   integer,  intent(in)  :: ntop                 ! Top layer for calculation
         428             :   integer,  intent(in)  :: nbot                 ! Bottom layer for calculation
         429             :
         430             :   real(r8), intent(in)  :: ml2(pver+1)          ! Mixing lengths squared
         431             :   real(r8), intent(in)  :: s2(pcols,pver)       ! Shear squared
         432             :   real(r8), intent(in)  :: ri(pcols,pver)       ! Richardson no
         433             :
         434             :   ! ---------------- !
         435             :   ! Output arguments !
         436             :   ! ---------------- !
         437             :
         438             :   real(r8), intent(out) :: kvf(pcols,pver+1)    ! Eddy diffusivity for heat and tracers
         439             :
         440             :   ! --------------- !
         441             :   ! Local Variables !
         442             :   ! --------------- !
         443             :
         444             :   real(r8)              :: fofri                ! f(ri)
         445             :   real(r8)              :: kvn                  ! Neutral Kv
         446             :
         447             :   integer               :: i                    ! Longitude index
         448             :   integer               :: k                    ! Vertical index
         449             :
         450             :   ! ----------------------- !
         451             :   ! Main Computation Begins !
         452             :   ! ----------------------- !
         453             :
         454           0 :   kvf(:ncol,:)           = 0.0_r8
         455             :   ! Compute the free atmosphere vertical diffusion coefficients: kvh = kvq = kvm.
         456           0 :   do k = ntop, nbot - 1
         457           0 :      do i = 1, ncol
         458           0 :         if( ri(i,k) < 0.0_r8 ) then
         459           0 :            fofri = sqrt( max( 1._r8 - 18._r8 * ri(i,k), 0._r8 ) )
         460             :         else
         461             :            fofri = 0.0_r8
         462             :         end if
         463           0 :         kvn = ml2(k) * sqrt(s2(i,k))
         464           0 :         kvf(i,k+1) = kvn * fofri
         465             :      end do
         466             :   end do
         467           0 : end subroutine austausch_atm_free
         468             :
         469             : end module pbl_utils

Generated by: LCOV version 1.14