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