LCOV - code coverage report
Current view: top level - physics/cam - hk_conv.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 303 323 93.8 %
Date: 2025-01-13 21:54:50 Functions: 3 3 100.0 %

          Line data    Source code
       1             : 
       2             : module hk_conv
       3             : !
       4             : ! Moist convection. Primarily data used by both Zhang-McFarlane convection
       5             : ! and Hack shallow convective schemes.
       6             : !
       7             : ! $Id$
       8             : !
       9             :    use shr_kind_mod,     only: r8 => shr_kind_r8
      10             :    use cam_logfile,      only: iulog
      11             :    use spmd_utils,       only: masterproc
      12             :    use cam_abortutils,   only: endrun
      13             :    implicit none
      14             : 
      15             :    private
      16             :    save
      17             : !
      18             : ! Public interfaces
      19             : !
      20             :    public mfinti   !  Initialization of data for moist convection
      21             :    public cmfmca   !  Hack shallow convection
      22             :    public hkconv_readnl ! read hkconv_nl namelist
      23             : 
      24             : !
      25             : ! Private data used for Hack shallow convection
      26             : !
      27             :    real(r8), parameter :: unset_r8 = huge(1.0_r8)
      28             : 
      29             :   ! Namelist variables
      30             :    real(r8) :: hkconv_c0 = unset_r8
      31             :    real(r8) :: hkconv_cmftau = unset_r8
      32             : 
      33             :    real(r8) :: hlat        ! latent heat of vaporization
      34             :    real(r8) :: c0          ! rain water autoconversion coefficient set from namelist input hkconv_c0
      35             :    real(r8) :: betamn      ! minimum overshoot parameter
      36             :    real(r8) :: rhlat       ! reciprocal of hlat
      37             :    real(r8) :: rcp         ! reciprocal of cp
      38             :    real(r8) :: cmftau      ! characteristic adjustment time scale set from namelist input hkconv_cmftau
      39             :    real(r8) :: rhoh2o      ! density of liquid water (STP)
      40             :    real(r8) :: dzmin       ! minimum convective depth for precipitation
      41             :    real(r8) :: tiny        ! arbitrary small num used in transport estimates
      42             :    real(r8) :: eps         ! convergence criteria (machine dependent)
      43             :    real(r8) :: tpmax       ! maximum acceptable t perturbation (degrees C)
      44             :    real(r8) :: shpmax      ! maximum acceptable q perturbation (g/g)
      45             : 
      46             :    integer :: iloc         ! longitude location for diagnostics
      47             :    integer :: jloc         ! latitude  location for diagnostics
      48             :    integer :: nsloc        ! nstep for which to produce diagnostics
      49             : !
      50             :    logical :: rlxclm       ! logical to relax column versus cloud triplet
      51             : 
      52             :    real(r8) cp          ! specific heat of dry air
      53             :    real(r8) grav        ! gravitational constant
      54             :    real(r8) rgrav       ! reciprocal of grav
      55             :    real(r8) rgas        ! gas constant for dry air
      56             :    integer limcnv          ! top interface level limit for convection
      57             : 
      58             : 
      59             : 
      60             : 
      61             : contains
      62        1536 : subroutine hkconv_readnl(nlfile)
      63             : 
      64             :    use namelist_utils,  only: find_group_name
      65             :    use units,           only: getunit, freeunit
      66             :    use mpishorthand
      67             : 
      68             :    character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
      69             : 
      70             :    ! Local variables
      71             :    integer :: unitn, ierr
      72             :    character(len=*), parameter :: subname = 'hkconv_readnl'
      73             : 
      74             :    namelist /hkconv_nl/ hkconv_cmftau, hkconv_c0
      75             :    !-----------------------------------------------------------------------------
      76             : 
      77        1536 :    if (masterproc) then
      78           2 :       unitn = getunit()
      79           2 :       open( unitn, file=trim(nlfile), status='old' )
      80           2 :       call find_group_name(unitn, 'hkconv_nl', status=ierr)
      81           2 :       if (ierr == 0) then
      82           2 :          read(unitn, hkconv_nl, iostat=ierr)
      83           2 :          if (ierr /= 0) then
      84           0 :             call endrun(subname // ':: ERROR reading namelist')
      85             :          end if
      86             :       end if
      87           2 :       close(unitn)
      88           2 :       call freeunit(unitn)
      89             : 
      90             :       ! set local variables
      91           2 :       cmftau = hkconv_cmftau
      92           2 :       c0     = hkconv_c0
      93             : 
      94             :    end if
      95             : 
      96             : #ifdef SPMD
      97             :    ! Broadcast namelist variables
      98        1536 :    call mpibcast(cmftau,            1, mpir8,  0, mpicom)
      99        1536 :    call mpibcast(c0,                1, mpir8,  0, mpicom)
     100             : #endif
     101             : 
     102        1536 : end subroutine hkconv_readnl
     103             : 
     104             : !================================================================================================
     105             : 
     106        1536 : subroutine mfinti (rair    ,cpair   ,gravit  ,latvap  ,rhowtr,limcnv_in )
     107             : !-----------------------------------------------------------------------
     108             : !
     109             : ! Purpose:
     110             : ! Initialize moist convective mass flux procedure common block, cmfmca
     111             : !
     112             : ! Method:
     113             : ! <Describe the algorithm(s) used in the routine.>
     114             : ! <Also include any applicable external references.>
     115             : !
     116             : ! Author: J. Hack
     117             : !
     118             : !-----------------------------------------------------------------------
     119             :    use spmd_utils, only: masterproc
     120             : !------------------------------Arguments--------------------------------
     121             : !
     122             : ! Input arguments
     123             : !
     124             :    real(r8), intent(in) :: rair              ! gas constant for dry air
     125             :    real(r8), intent(in) :: cpair             ! specific heat of dry air
     126             :    real(r8), intent(in) :: gravit            ! acceleration due to gravity
     127             :    real(r8), intent(in) :: latvap            ! latent heat of vaporization
     128             :    real(r8), intent(in) :: rhowtr            ! density of liquid water (STP)
     129             :    integer,  intent(in) :: limcnv_in         ! top interface level limit for convection
     130             : 
     131             :    ! local variables
     132             :    character(len=32)    :: hgrid             ! horizontal grid specifier
     133             : !
     134             : !-----------------------------------------------------------------------
     135             : !
     136             : ! Initialize physical constants for moist convective mass flux procedure
     137             : !
     138        1536 :    cp     = cpair         ! specific heat of dry air
     139        1536 :    hlat   = latvap        ! latent heat of vaporization
     140        1536 :    grav   = gravit        ! gravitational constant
     141        1536 :    rgas   = rair          ! gas constant for dry air
     142        1536 :    rhoh2o = rhowtr        ! density of liquid water (STP)
     143             : 
     144        1536 :    limcnv = limcnv_in
     145             : 
     146             :    ! Initialize free parameters for moist convective mass flux procedure
     147             :    ! cmftau - characteristic adjustment time scale
     148             :    ! c0     - rain water autoconversion coeff (1/m)
     149             : 
     150        1536 :    if (masterproc) then
     151           2 :       write(iulog,*) 'tuning parameters hk_conv: cmftau',cmftau
     152           2 :       write(iulog,*) 'tuning parameters hk_conv: c0',c0
     153             :    endif
     154        1536 :    dzmin  = 0.0_r8           ! minimum cloud depth to precipitate (m)
     155        1536 :    betamn = 0.10_r8          ! minimum overshoot parameter
     156             : 
     157             : 
     158        1536 :    tpmax  = 1.50_r8          ! maximum acceptable t perturbation (deg C)
     159        1536 :    shpmax = 1.50e-3_r8       ! maximum acceptable q perturbation (g/g)
     160        1536 :    rlxclm = .true.        ! logical variable to specify that relaxation
     161             : !                                time scale should applied to column as
     162             : !                                opposed to triplets individually
     163             : !
     164             : ! Initialize miscellaneous (frequently used) constants
     165             : !
     166        1536 :    rhlat  = 1.0_r8/hlat      ! reciprocal latent heat of vaporization
     167        1536 :    rcp    = 1.0_r8/cp        ! reciprocal specific heat of dry air
     168        1536 :    rgrav  = 1.0_r8/grav      ! reciprocal gravitational constant
     169             : !
     170             : ! Initialize diagnostic location information for moist convection scheme
     171             : !
     172        1536 :    iloc   = 1             ! longitude point for diagnostic info
     173        1536 :    jloc   = 1             ! latitude  point for diagnostic info
     174        1536 :    nsloc  = 1             ! nstep value at which to begin diagnostics
     175             : !
     176             : ! Initialize other miscellaneous parameters
     177             : !
     178        1536 :    tiny   = 1.0e-36_r8       ! arbitrary small number (scalar transport)
     179        1536 :    eps    = 1.0e-13_r8       ! convergence criteria (machine dependent)
     180             : !
     181        1536 :    return
     182             : end subroutine mfinti
     183             : 
     184     1495368 : subroutine cmfmca(lchnk   ,ncol    , &
     185             :                   nstep   ,ztodt     ,pmid    ,pdel    , &
     186             :                   rpdel   ,zm      ,tpert   ,qpert   ,phis    , &
     187             :                   pblh    ,t       ,q       ,cmfdt   ,dq      , &
     188             :                   cmfmc   ,cmfdqr  ,cmfsl   ,cmflq   ,precc   , &
     189             :                   qc      ,cnt     ,cnb     ,icwmr   ,rliq    , &
     190             :                   pmiddry ,pdeldry ,rpdeldry)
     191             : !-----------------------------------------------------------------------
     192             : !
     193             : ! Purpose:
     194             : ! Moist convective mass flux procedure:
     195             : !
     196             : ! Method:
     197             : ! If stratification is unstable to nonentraining parcel ascent,
     198             : ! complete an adjustment making successive use of a simple cloud model
     199             : ! consisting of three layers (sometimes referred to as a triplet)
     200             : !
     201             : ! Code generalized to allow specification of parcel ("updraft")
     202             : ! properties, as well as convective transport of an arbitrary
     203             : ! number of passive constituents (see q array).  The code
     204             : ! is written so the water vapor field is passed independently
     205             : ! in the calling list from the block of other transported
     206             : ! constituents, even though as currently designed, it is the
     207             : ! first component in the constituents field.
     208             : !
     209             : ! Author: J. Hack
     210             : !
     211             : ! BAB: changed code to report tendencies in cmfdt and dq, instead of
     212             : ! updating profiles. Cmfdq contains water only, made it a local variable
     213             : ! made dq (all constituents) the argument.
     214             : !
     215             : !-----------------------------------------------------------------------
     216             : 
     217             : !#######################################################################
     218             : !#                                                                     #
     219             : !# Debugging blocks are marked this way for easy identification        #
     220             : !#                                                                     #
     221             : !#######################################################################
     222             :    use constituents,  only: pcnst
     223             :    use constituents,    only: cnst_get_type_byind
     224             :    use ppgrid,    only: pcols, pver, pverp
     225             : #if ( defined DIAGNS )
     226             :    use phys_grid, only: get_lat_all_p, get_lon_all_p
     227             : #endif
     228             :    use wv_saturation, only: qsat
     229             : 
     230             :    real(r8) ssfac               ! supersaturation bound (detrained air)
     231             :    parameter (ssfac = 1.001_r8)
     232             : 
     233             : !------------------------------Arguments--------------------------------
     234             : !
     235             : ! Input arguments
     236             : !
     237             :    integer, intent(in) :: lchnk                ! chunk identifier
     238             :    integer, intent(in) :: ncol                 ! number of atmospheric columns
     239             :    integer, intent(in) :: nstep                ! current time step index
     240             : 
     241             :    real(r8), intent(in) :: ztodt               ! 2 delta-t (seconds)
     242             :    real(r8), intent(in) :: pmid(pcols,pver)    ! pressure
     243             :    real(r8), intent(in) :: pdel(pcols,pver)    ! delta-p
     244             :    real(r8), intent(in) :: pmiddry(pcols,pver)    ! pressure
     245             :    real(r8), intent(in) :: pdeldry(pcols,pver)    ! delta-p
     246             :    real(r8), intent(in) :: rpdel(pcols,pver)   ! 1./pdel
     247             :    real(r8), intent(in) :: rpdeldry(pcols,pver)   ! 1./pdel
     248             :    real(r8), intent(in) :: zm(pcols,pver)      ! height abv sfc at midpoints
     249             :    real(r8), intent(in) :: tpert(pcols)        ! PBL perturbation theta
     250             :    real(r8), intent(in) :: qpert(pcols,pcnst)  ! PBL perturbation specific humidity
     251             :    real(r8), intent(in) :: phis(pcols)         ! surface geopotential
     252             :    real(r8), intent(in) :: pblh(pcols)         ! PBL height (provided by PBL routine)
     253             :    real(r8), intent(in) :: t(pcols,pver)       ! temperature (t bar)
     254             :    real(r8), intent(in) :: q(pcols,pver,pcnst) ! specific humidity (sh bar)
     255             : !
     256             : ! Output arguments
     257             : !
     258             :    real(r8), intent(out) :: cmfdt(pcols,pver)   ! dt/dt due to moist convection
     259             :    real(r8), intent(out) :: cmfmc(pcols,pverp)  ! moist convection cloud mass flux
     260             :    real(r8), intent(out) :: cmfdqr(pcols,pver)  ! dq/dt due to convective rainout
     261             :    real(r8), intent(out) :: cmfsl(pcols,pver )  ! convective lw static energy flux
     262             :    real(r8), intent(out) :: cmflq(pcols,pver )  ! convective total water flux
     263             :    real(r8), intent(out) :: precc(pcols)        ! convective precipitation rate
     264             : ! JJH mod to explicitly export cloud water
     265             :    real(r8), intent(out) :: qc(pcols,pver)      ! dq/dt due to export of cloud water
     266             :    real(r8), intent(out) :: cnt(pcols)          ! top level of convective activity
     267             :    real(r8), intent(out) :: cnb(pcols)          ! bottom level of convective activity
     268             :    real(r8), intent(out) :: dq(pcols,pver,pcnst) ! constituent tendencies
     269             :    real(r8), intent(out) :: icwmr(pcols,pver)
     270             :    real(r8), intent(out) :: rliq(pcols)
     271             : !
     272             : !---------------------------Local workspace-----------------------------
     273             : !
     274             :    real(r8) pm(pcols,pver)    ! pressure
     275             :    real(r8) pd(pcols,pver)    ! delta-p
     276             :    real(r8) rpd(pcols,pver)   ! 1./pdel
     277             : 
     278             :    real(r8) cmfdq(pcols,pver)   ! dq/dt due to moist convection
     279             :    real(r8) gam(pcols,pver)     ! 1/cp (d(qsat)/dT)
     280             :    real(r8) sb(pcols,pver)      ! dry static energy (s bar)
     281             :    real(r8) hb(pcols,pver)      ! moist static energy (h bar)
     282             :    real(r8) shbs(pcols,pver)    ! sat. specific humidity (sh bar star)
     283             :    real(r8) hbs(pcols,pver)     ! sat. moist static energy (h bar star)
     284             :    real(r8) shbh(pcols,pverp)   ! specific humidity on interfaces
     285             :    real(r8) sbh(pcols,pverp)    ! s bar on interfaces
     286             :    real(r8) hbh(pcols,pverp)    ! h bar on interfaces
     287             :    real(r8) cmrh(pcols,pverp)   ! interface constituent mixing ratio
     288             :    real(r8) prec(pcols)         ! instantaneous total precipitation
     289             :    real(r8) dzcld(pcols)        ! depth of convective layer (m)
     290             :    real(r8) beta(pcols)         ! overshoot parameter (fraction)
     291             :    real(r8) betamx(pcols)       ! local maximum on overshoot
     292             :    real(r8) eta(pcols)          ! convective mass flux (kg/m^2 s)
     293             :    real(r8) etagdt(pcols)       ! eta*grav*dt
     294             :    real(r8) cldwtr(pcols)       ! cloud water (mass)
     295             :    real(r8) rnwtr(pcols)        ! rain water  (mass)
     296             : !  JJH extension to facilitate export of cloud liquid water
     297             :    real(r8) totcond(pcols)      ! total condensate; mix of precip and cloud water (mass)
     298             :    real(r8) sc  (pcols)         ! dry static energy   ("in-cloud")
     299             :    real(r8) shc (pcols)         ! specific humidity   ("in-cloud")
     300             :    real(r8) hc  (pcols)         ! moist static energy ("in-cloud")
     301             :    real(r8) cmrc(pcols)         ! constituent mix rat ("in-cloud")
     302             :    real(r8) dq1(pcols)          ! shb  convective change (lower lvl)
     303             :    real(r8) dq2(pcols)          ! shb  convective change (mid level)
     304             :    real(r8) dq3(pcols)          ! shb  convective change (upper lvl)
     305             :    real(r8) ds1(pcols)          ! sb   convective change (lower lvl)
     306             :    real(r8) ds2(pcols)          ! sb   convective change (mid level)
     307             :    real(r8) ds3(pcols)          ! sb   convective change (upper lvl)
     308             :    real(r8) dcmr1(pcols)        ! q convective change (lower lvl)
     309             :    real(r8) dcmr2(pcols)        ! q convective change (mid level)
     310             :    real(r8) dcmr3(pcols)        ! q convective change (upper lvl)
     311             :    real(r8) estemp(pcols,pver)  ! saturation vapor pressure (scratch)
     312             :    real(r8) vtemp1(2*pcols)     ! intermediate scratch vector
     313             :    real(r8) vtemp2(2*pcols)     ! intermediate scratch vector
     314             :    real(r8) vtemp3(2*pcols)     ! intermediate scratch vector
     315             :    real(r8) vtemp4(2*pcols)     ! intermediate scratch vector
     316             :    real(r8) vtemp5(2*pcols)     ! intermediate scratch vector
     317             :    integer indx1(pcols)     ! longitude indices for condition true
     318             :    logical etagt0           ! true if eta > 0.0
     319             :    real(r8) sh1                 ! dummy arg in qhalf statement func.
     320             :    real(r8) sh2                 ! dummy arg in qhalf statement func.
     321             :    real(r8) shbs1               ! dummy arg in qhalf statement func.
     322             :    real(r8) shbs2               ! dummy arg in qhalf statement func.
     323             :    real(r8) cats                ! modified characteristic adj. time
     324             :    real(r8) rtdt                ! 1./ztodt
     325             :    real(r8) qprime              ! modified specific humidity pert.
     326             :    real(r8) tprime              ! modified thermal perturbation
     327             :    real(r8) pblhgt              ! bounded pbl height (max[pblh,1m])
     328             :    real(r8) fac1                ! intermediate scratch variable
     329             :    real(r8) shprme              ! intermediate specific humidity pert.
     330             :    real(r8) qsattp              ! sat mix rat for thermally pert PBL parcels
     331             :    real(r8) dz                  ! local layer depth
     332             :    real(r8) temp1               ! intermediate scratch variable
     333             :    real(r8) b1                  ! bouyancy measure in detrainment lvl
     334             :    real(r8) b2                  ! bouyancy measure in condensation lvl
     335             :    real(r8) temp2               ! intermediate scratch variable
     336             :    real(r8) temp3               ! intermediate scratch variable
     337             :    real(r8) g                   ! bounded vertical gradient of hb
     338             :    real(r8) tmass               ! total mass available for convective exch
     339             :    real(r8) denom               ! intermediate scratch variable
     340             :    real(r8) qtest1              ! used in negative q test (middle lvl)
     341             :    real(r8) qtest2              ! used in negative q test (lower lvl)
     342             :    real(r8) fslkp               ! flux lw static energy (bot interface)
     343             :    real(r8) fslkm               ! flux lw static energy (top interface)
     344             :    real(r8) fqlkp               ! flux total water (bottom interface)
     345             :    real(r8) fqlkm               ! flux total water (top interface)
     346             :    real(r8) botflx              ! bottom constituent mixing ratio flux
     347             :    real(r8) topflx              ! top constituent mixing ratio flux
     348             :    real(r8) efac1               ! ratio q to convectively induced chg (btm lvl)
     349             :    real(r8) efac2               ! ratio q to convectively induced chg (mid lvl)
     350             :    real(r8) efac3               ! ratio q to convectively induced chg (top lvl)
     351             :    real(r8) tb(pcols,pver)      ! working storage for temp (t bar)
     352             :    real(r8) shb(pcols,pver)     ! working storage for spec hum (sh bar)
     353             :    real(r8) adjfac              ! adjustment factor (relaxation related)
     354             :    real(r8) rktp
     355             :    real(r8) rk
     356             : #if ( defined DIAGNS )
     357             : !
     358             : !  Following 7 real variables are used in diagnostics calculations
     359             : !
     360             :    real(r8) rh                  ! relative humidity
     361             :    real(r8) es                  ! sat vapor pressure
     362             :    real(r8) hsum1               ! moist static energy integral
     363             :    real(r8) qsum1               ! total water integral
     364             :    real(r8) hsum2               ! final moist static energy integral
     365             :    real(r8) qsum2               ! final total water integral
     366             :    real(r8) fac                 ! intermediate scratch variable
     367             : #endif
     368             :    integer i,k              ! longitude, level indices
     369             :    integer ii               ! index on "gathered" vectors
     370             :    integer len1             ! vector length of "gathered" vectors
     371             :    integer m                ! constituent index
     372             :    integer ktp              ! tmp indx used to track top of convective layer
     373             : #if ( defined DIAGNS )
     374             :    integer n                ! vertical index     (diagnostics)
     375             :    integer kp               ! vertical index     (diagnostics)
     376             :    integer kpp              ! index offset, kp+1 (diagnostics)
     377             :    integer kpm1             ! index offset, kp-1 (diagnostics)
     378             :    integer lat(pcols)       ! latitude indices
     379             :    integer lon(pcols)       ! longitude indices
     380             : #endif
     381             : !
     382             : !---------------------------Statement functions-------------------------
     383             : !
     384             :    real(r8) qhalf
     385             :    qhalf(sh1,sh2,shbs1,shbs2) = min(max(sh1,sh2),(shbs2*sh1 + shbs1*sh2)/(shbs1+shbs2))
     386             : !
     387             : !-----------------------------------------------------------------------
     388             : 
     389             : !** BAB initialize output tendencies here
     390             : !       copy q to dq; use dq below for passive tracer transport
     391   650693736 :    cmfdt(:ncol,:)  = 0._r8
     392   650693736 :    cmfdq(:ncol,:)  = 0._r8
     393  1302882840 :    dq(:ncol,:,2:)  = q(:ncol,:,2:)
     394   675662904 :    cmfmc(:ncol,:)  = 0._r8
     395   650693736 :    cmfdqr(:ncol,:) = 0._r8
     396   650693736 :    cmfsl(:ncol,:)  = 0._r8
     397   650693736 :    cmflq(:ncol,:)  = 0._r8
     398   650693736 :    qc(:ncol,:)     = 0._r8
     399    24969168 :    rliq(:ncol)     = 0._r8
     400             : !
     401             : #if ( defined DIAGNS )
     402             : ! Determine chunk latitudes and longitudes
     403             :    call get_lat_all_p(lchnk, ncol, lat)
     404             :    call get_lon_all_p(lchnk, ncol, lon)
     405             : #endif
     406             : !
     407             : ! Ensure that characteristic adjustment time scale (cmftau) assumed
     408             : ! in estimate of eta isn't smaller than model time scale (ztodt)
     409             : ! The time over which the convection is assumed to act (the adjustment
     410             : ! time scale) can be applied with each application of the three-level
     411             : ! cloud model, or applied to the column tendencies after a "hard"
     412             : ! adjustment (i.e., on a 2-delta t time scale) is evaluated
     413             : !
     414     1495368 :    if (rlxclm) then
     415     1495368 :       cats   = ztodt             ! relaxation applied to column
     416     1495368 :       adjfac = ztodt/(max(ztodt,cmftau))
     417             :    else
     418           0 :       cats   = max(ztodt,cmftau) ! relaxation applied to triplet
     419           0 :       adjfac = 1.0_r8
     420             :    endif
     421     1495368 :    rtdt = 1.0_r8/ztodt
     422             : !
     423             : ! Move temperature and moisture into working storage
     424             : !
     425    34393464 :    do k=limcnv,pver
     426   550817064 :       do i=1,ncol
     427   516423600 :          tb (i,k) = t(i,k)
     428   549321696 :          shb(i,k) = q(i,k,1)
     429             :       end do
     430             :    end do
     431    40374936 :    do k=1,pver
     432   650693736 :       do i=1,ncol
     433   649198368 :          icwmr(i,k) = 0._r8
     434             :       end do
     435             :    end do
     436             : !
     437             : ! Compute sb,hb,shbs,hbs
     438             : !
     439    34393464 :    do k = limcnv,pver
     440             :       call qsat(tb(1:ncol,k), pmid(1:ncol,k), &
     441             :            estemp(1:ncol,k), shbs(1:ncol,k), ncol, &
     442    34393464 :            gam=gam(1:ncol,k))
     443             :    end do
     444             : !
     445    34393464 :    do k=limcnv,pver
     446   550817064 :       do i=1,ncol
     447   516423600 :          sb (i,k) = cp*tb(i,k) + zm(i,k)*grav + phis(i)
     448   516423600 :          hb (i,k) = sb(i,k) + hlat*shb(i,k)
     449   549321696 :          hbs(i,k) = sb(i,k) + hlat*shbs(i,k)
     450             :       end do
     451             :    end do
     452             : !
     453             : ! Compute sbh, shbh
     454             : !
     455    32898096 :    do k=limcnv+1,pver
     456   525847896 :       do i=1,ncol
     457   492949800 :          sbh (i,k) = 0.5_r8*(sb(i,k-1) + sb(i,k))
     458   492949800 :          shbh(i,k) = qhalf(shb(i,k-1),shb(i,k),shbs(i,k-1),shbs(i,k))
     459   524352528 :          hbh (i,k) = sbh(i,k) + hlat*shbh(i,k)
     460             :       end do
     461             :    end do
     462             : !
     463             : ! Specify properties at top of model (not used, but filling anyway)
     464             : !
     465    24969168 :    do i=1,ncol
     466    23473800 :       sbh (i,limcnv) = sb(i,limcnv)
     467    23473800 :       shbh(i,limcnv) = shb(i,limcnv)
     468    24969168 :       hbh (i,limcnv) = hb(i,limcnv)
     469             :    end do
     470             : !
     471             : ! Zero vertically independent control, tendency & diagnostic arrays
     472             : !
     473    24969168 :    do i=1,ncol
     474    23473800 :       prec(i)  = 0.0_r8
     475    23473800 :       dzcld(i) = 0.0_r8
     476    23473800 :       cnb(i)   = 0.0_r8
     477    24969168 :       cnt(i)   = real(pver+1,r8)
     478             :    end do
     479             : #if ( defined DIAGNS )
     480             : !#######################################################################
     481             : !#                                                                     #
     482             : !#    output initial thermodynamic profile if debug diagnostics        #
     483             : !#                                                                     #
     484             :    do i=1,ncol
     485             :      if ((lat(i).eq.jloc) .and. (lon(i).eq.iloc) &
     486             :          .and. (nstep.ge.nsloc)) then
     487             : !#                                                                     #
     488             : !#       approximate vertical integral of moist static energy          #
     489             : !#       and total preciptable water                                   #
     490             : !#                                                                     #
     491             :       hsum1 = 0.0_r8
     492             :       qsum1 = 0.0_r8
     493             :       do k=limcnv,pver
     494             :          hsum1 = hsum1 + pdel(i,k)*rgrav*hb(i,k)
     495             :          qsum1 = qsum1 + pdel(i,k)*rgrav*shb(i,k)
     496             :       end do
     497             : !#                                                                     #
     498             :       write(iulog,8010)
     499             :       fac = grav*864._r8
     500             :       do k=limcnv,pver
     501             :          rh = shb(i,k)/shbs(i,k)
     502             :          write(iulog,8020) shbh(i,k),sbh(i,k),hbh(i,k),fac*cmfmc(i,k),cmfsl(i,k), cmflq(i,k)
     503             :          write(iulog,8040) tb(i,k),shb(i,k),rh,sb(i,k),hb(i,k),hbs(i,k),ztodt*cmfdt(i,k), &
     504             :                        ztodt*cmfdq(i,k),ztodt*cmfdqr(i,k)
     505             :       end do
     506             :       write(iulog, 8000) prec(i)
     507             :      end if
     508             :    enddo
     509             : #endif
     510             : !#                                                                     #
     511             : !#                                                                     #
     512             : !#######################################################################
     513             : !
     514             : ! Begin moist convective mass flux adjustment procedure.
     515             : ! Formalism ensures that negative cloud liquid water can never occur
     516             : !
     517    31402728 :    do 70 k=pver-1,limcnv+1,-1
     518   499383360 :       do 10 i=1,ncol
     519   469476000 :          etagdt(i) = 0.0_r8
     520   469476000 :          eta   (i) = 0.0_r8
     521   469476000 :          beta  (i) = 0.0_r8
     522   469476000 :          ds1   (i) = 0.0_r8
     523   469476000 :          ds2   (i) = 0.0_r8
     524   469476000 :          ds3   (i) = 0.0_r8
     525   469476000 :          dq1   (i) = 0.0_r8
     526   469476000 :          dq2   (i) = 0.0_r8
     527   469476000 :          dq3   (i) = 0.0_r8
     528             : !
     529             : ! Specification of "cloud base" conditions
     530             : !
     531   469476000 :          qprime    = 0.0_r8
     532   469476000 :          tprime    = 0.0_r8
     533             : !
     534             : ! Assign tprime within the PBL to be proportional to the quantity
     535             : ! tpert (which will be bounded by tpmax), passed to this routine by
     536             : ! the PBL routine.  Don't allow perturbation to produce a dry
     537             : ! adiabatically unstable parcel.  Assign qprime within the PBL to be
     538             : ! an appropriately modified value of the quantity qpert (which will be
     539             : ! bounded by shpmax) passed to this routine by the PBL routine.  The
     540             : ! quantity qprime should be less than the local saturation value
     541             : ! (qsattp=qsat[t+tprime,p]).  In both cases, tpert and qpert are
     542             : ! linearly reduced toward zero as the PBL top is approached.
     543             : !
     544   469476000 :          pblhgt = max(pblh(i),1.0_r8)
     545   469476000 :          if ( (zm(i,k+1) <= pblhgt) .and. dzcld(i) == 0.0_r8 ) then
     546    54440113 :             fac1   = max(0.0_r8,1.0_r8-zm(i,k+1)/pblhgt)
     547    54440113 :             tprime = min(tpert(i),tpmax)*fac1
     548    54440113 :             qsattp = shbs(i,k+1) + cp*rhlat*gam(i,k+1)*tprime
     549    54440113 :             shprme = min(min(qpert(i,1),shpmax)*fac1,max(qsattp-shb(i,k+1),0.0_r8))
     550    54440113 :             qprime = max(qprime,shprme)
     551             :          else
     552             :             tprime = 0.0_r8
     553             :             qprime = 0.0_r8
     554             :          end if
     555             : !
     556             : ! Specify "updraft" (in-cloud) thermodynamic properties
     557             : !
     558   469476000 :          sc (i)    = sb (i,k+1) + cp*tprime
     559   469476000 :          shc(i)    = shb(i,k+1) + qprime
     560   469476000 :          hc (i)    = sc (i    ) + hlat*shc(i)
     561   469476000 :          vtemp4(i) = hc(i) - hbs(i,k)
     562   469476000 :          dz        = pdel(i,k)*rgas*tb(i,k)*rgrav/pmid(i,k)
     563   469476000 :          if (vtemp4(i) > 0.0_r8) then
     564    32205264 :             dzcld(i) = dzcld(i) + dz
     565             :          else
     566   437270736 :             dzcld(i) = 0.0_r8
     567             :          end if
     568    29907360 : 10       continue
     569             : #if ( defined DIAGNS )
     570             : !#######################################################################
     571             : !#                                                                     #
     572             : !#    output thermodynamic perturbation information                    #
     573             : !#                                                                     #
     574             :          do i=1,ncol
     575             :            if ((lat(i)==jloc).and.(lon(i)==iloc).and.(nstep>=nsloc)) then
     576             :             write(iulog,8090) k+1,sc(iloc),shc(iloc),hc(iloc)
     577             :            end if
     578             :          enddo
     579             : !#                                                                     #
     580             : !#######################################################################
     581             : #endif
     582             : !
     583             : ! Check on moist convective instability
     584             : ! Build index vector of points where instability exists
     585             : !
     586             :          len1 = 0
     587   499383360 :          do i=1,ncol
     588   499383360 :             if (vtemp4(i) > 0.0_r8) then
     589    32205264 :                len1 = len1 + 1
     590    32205264 :                indx1(len1) = i
     591             :             end if
     592             :          end do
     593    29907360 :          if (len1 <= 0) go to 70
     594             : !
     595             : ! Current level just below top level => no overshoot
     596             : !
     597     5008903 :          if (k <= limcnv+1) then
     598           0 :             do ii=1,len1
     599           0 :                i = indx1(ii)
     600           0 :                temp1     = vtemp4(i)/(1.0_r8 + gam(i,k))
     601           0 :                cldwtr(i) = max(0.0_r8,(sb(i,k) - sc(i) + temp1))
     602           0 :                beta(i)   = 0.0_r8
     603           0 :                vtemp3(i) = (1.0_r8 + gam(i,k))*(sc(i) - sbh(i,k))
     604             :             end do
     605             :          else
     606             : !
     607             : ! First guess at overshoot parameter using crude buoyancy closure
     608             : ! 10% overshoot assumed as a minimum and 1-c0*dz maximum to start
     609             : ! If pre-existing supersaturation in detrainment layer, beta=0
     610             : ! cldwtr is temporarily equal to hlat*l (l=> liquid water)
     611             : !
     612    37214167 :             do ii=1,len1
     613    32205264 :                i = indx1(ii)
     614    32205264 :                temp1     = vtemp4(i)/(1.0_r8 + gam(i,k))
     615    32205264 :                cldwtr(i) = max(0.0_r8,(sb(i,k)-sc(i)+temp1))
     616    32205264 :                betamx(i) = 1.0_r8 - c0*max(0.0_r8,(dzcld(i)-dzmin))
     617    32205264 :                b1        = (hc(i) - hbs(i,k-1))*pdel(i,k-1)
     618    32205264 :                b2        = (hc(i) - hbs(i,k  ))*pdel(i,k  )
     619    32205264 :                beta(i)   = max(betamn,min(betamx(i), 1.0_r8 + b1/b2))
     620    32205264 :                if (hbs(i,k-1) <= hb(i,k-1)) beta(i) = 0.0_r8
     621             : !
     622             : ! Bound maximum beta to ensure physically realistic solutions
     623             : !
     624             : ! First check constrains beta so that eta remains positive
     625             : ! (assuming that eta is already positive for beta equal zero)
     626             : !
     627    32205264 :                vtemp1(i) = -(hbh(i,k+1) - hc(i))*pdel(i,k)*rpdel(i,k+1)+ &
     628    32205264 :                            (1.0_r8 + gam(i,k))*(sc(i) - sbh(i,k+1) + cldwtr(i))
     629    32205264 :                vtemp2(i) = (1.0_r8 + gam(i,k))*(sc(i) - sbh(i,k))
     630    32205264 :                vtemp3(i) = vtemp2(i)
     631    37214167 :                if ((beta(i)*vtemp2(i) - vtemp1(i)) > 0._r8) then
     632         189 :                   betamx(i) = 0.99_r8*(vtemp1(i)/vtemp2(i))
     633         189 :                   beta(i)   = max(0.0_r8,min(betamx(i),beta(i)))
     634             :                end if
     635             :             end do
     636             : !
     637             : ! Second check involves supersaturation of "detrainment layer"
     638             : ! small amount of supersaturation acceptable (by ssfac factor)
     639             : !
     640    37214167 :             do ii=1,len1
     641    32205264 :                i = indx1(ii)
     642    37214167 :                if (hb(i,k-1) < hbs(i,k-1)) then
     643    28918269 :                   vtemp1(i) = vtemp1(i)*rpdel(i,k)
     644    28918269 :                   temp2 = gam(i,k-1)*(sbh(i,k) - sc(i) + cldwtr(i)) -  &
     645    28918269 :                           hbh(i,k) + hc(i) - sc(i) + sbh(i,k)
     646    28918269 :                   temp3 = vtemp3(i)*rpdel(i,k)
     647             :                   vtemp2(i) = (ztodt/cats)*(hc(i) - hbs(i,k))*temp2/ &
     648    28918269 :                               (pdel(i,k-1)*(hbs(i,k-1) - hb(i,k-1))) + temp3
     649    28918269 :                   if ((beta(i)*vtemp2(i) - vtemp1(i)) > 0._r8) then
     650     3169407 :                      betamx(i) = ssfac*(vtemp1(i)/vtemp2(i))
     651     3169407 :                      beta(i)   = max(0.0_r8,min(betamx(i),beta(i)))
     652             :                   end if
     653             :                else
     654     3286995 :                   beta(i) = 0.0_r8
     655             :                end if
     656             :             end do
     657             : !
     658             : ! Third check to avoid introducing 2 delta x thermodynamic
     659             : ! noise in the vertical ... constrain adjusted h (or theta e)
     660             : ! so that the adjustment doesn't contribute to "kinks" in h
     661             : !
     662    37214167 :             do ii=1,len1
     663    32205264 :                i = indx1(ii)
     664    32205264 :                g = min(0.0_r8,hb(i,k) - hb(i,k-1))
     665    32205264 :                temp1 = (hb(i,k) - hb(i,k-1) - g)*(cats/ztodt)/(hc(i) - hbs(i,k))
     666    32205264 :                vtemp1(i) = temp1*vtemp1(i) + (hc(i) - hbh(i,k+1))*rpdel(i,k)
     667    32205264 :                vtemp2(i) = temp1*vtemp3(i)*rpdel(i,k) + (hc(i) - hbh(i,k) - cldwtr(i))* &
     668    32205264 :                            (rpdel(i,k) + rpdel(i,k+1))
     669    37214167 :                if ((beta(i)*vtemp2(i) - vtemp1(i)) > 0._r8) then
     670     2014555 :                   if (vtemp2(i) /= 0.0_r8) then
     671     2014555 :                      betamx(i) = vtemp1(i)/vtemp2(i)
     672             :                   else
     673           0 :                      betamx(i) = 0.0_r8
     674             :                   end if
     675     2014555 :                   beta(i) = max(0.0_r8,min(betamx(i),beta(i)))
     676             :                end if
     677             :             end do
     678             :          end if
     679             : !
     680             : ! Calculate mass flux required for stabilization.
     681             : !
     682             : ! Ensure that the convective mass flux, eta, is positive by
     683             : ! setting negative values of eta to zero..
     684             : ! Ensure that estimated mass flux cannot move more than the
     685             : ! minimum of total mass contained in either layer k or layer k+1.
     686             : ! Also test for other pathological cases that result in non-
     687             : ! physical states and adjust eta accordingly.
     688             : !
     689    37214167 :          do ii=1,len1
     690    32205264 :             i = indx1(ii)
     691    32205264 :             beta(i) = max(0.0_r8,beta(i))
     692    32205264 :             temp1 = hc(i) - hbs(i,k)
     693    32205264 :             temp2 = ((1.0_r8 + gam(i,k))*(sc(i) - sbh(i,k+1) + cldwtr(i)) - &
     694    64410528 :                       beta(i)*vtemp3(i))*rpdel(i,k) - (hbh(i,k+1) - hc(i))*rpdel(i,k+1)
     695    32205264 :             eta(i) = temp1/(temp2*grav*cats)
     696    32205264 :             tmass = min(pdel(i,k),pdel(i,k+1))*rgrav
     697    32205264 :             if (eta(i) > tmass*rtdt .or. eta(i) <= 0.0_r8) eta(i) = 0.0_r8
     698             : !
     699             : ! Check on negative q in top layer (bound beta)
     700             : !
     701    32205264 :             if (shc(i)-shbh(i,k) < 0.0_r8 .and. beta(i)*eta(i) /= 0.0_r8) then
     702       19843 :                denom = eta(i)*grav*ztodt*(shc(i) - shbh(i,k))*rpdel(i,k-1)
     703       19843 :                beta(i) = max(0.0_r8,min(-0.999_r8*shb(i,k-1)/denom,beta(i)))
     704             :             end if
     705             : !
     706             : ! Check on negative q in middle layer (zero eta)
     707             : !
     708             :             qtest1 = shb(i,k) + eta(i)*grav*ztodt*((shc(i) - shbh(i,k+1)) - &
     709             :                      (1.0_r8 - beta(i))*cldwtr(i)*rhlat - beta(i)*(shc(i) - shbh(i,k)))* &
     710    32205264 :                      rpdel(i,k)
     711    32205264 :             if (qtest1 <= 0.0_r8) eta(i) = 0.0_r8
     712             : !
     713             : ! Check on negative q in lower layer (bound eta)
     714             : !
     715    32205264 :             fac1 = -(shbh(i,k+1) - shc(i))*rpdel(i,k+1)
     716    32205264 :             qtest2 = shb(i,k+1) - eta(i)*grav*ztodt*fac1
     717    32205264 :             if (qtest2 < 0.0_r8) then
     718           0 :                eta(i) = 0.99_r8*shb(i,k+1)/(grav*ztodt*fac1)
     719             :             end if
     720    37214167 :             etagdt(i) = eta(i)*grav*ztodt
     721             :          end do
     722             : !
     723             : #if ( defined DIAGNS )
     724             : !#######################################################################
     725             : !#                                                                     #
     726             :          do i=1,ncol
     727             :            if ((lat(i)==jloc).and.(lon(i)==iloc).and.(nstep >= nsloc)) then
     728             :             write(iulog,8080) beta(iloc), eta(iloc)
     729             :            end if
     730             :          enddo
     731             : !#                                                                     #
     732             : !#######################################################################
     733             : #endif
     734             : !
     735             : ! Calculate cloud water, rain water, and thermodynamic changes
     736             : !
     737    37214167 :          do 30 ii=1,len1
     738    32205264 :             i = indx1(ii)
     739    32205264 :             icwmr(i,k) = cldwtr(i)*rhlat
     740    32205264 :             cldwtr(i) = etagdt(i)*cldwtr(i)*rhlat*rgrav
     741             : ! JJH changes to facilitate export of cloud liquid water --------------------------------
     742    32205264 :             totcond(i) = (1.0_r8 - beta(i))*cldwtr(i)
     743    32205264 :             rnwtr(i) = min(totcond(i),c0*(dzcld(i)-dzmin)*cldwtr(i))
     744    32205264 :             ds1(i) = etagdt(i)*(sbh(i,k+1) - sc(i))*rpdel(i,k+1)
     745    32205264 :             dq1(i) = etagdt(i)*(shbh(i,k+1) - shc(i))*rpdel(i,k+1)
     746             :             ds2(i) = (etagdt(i)*(sc(i) - sbh(i,k+1)) +  &
     747    32205264 :                      hlat*grav*cldwtr(i) - beta(i)*etagdt(i)*(sc(i) - sbh(i,k)))*rpdel(i,k)
     748             : ! JJH change for export of cloud liquid water; must use total condensate
     749             : ! since rainwater no longer represents total condensate
     750             :             dq2(i) = (etagdt(i)*(shc(i) - shbh(i,k+1)) - grav*totcond(i) - beta(i)* &
     751    32205264 :                      etagdt(i)*(shc(i) - shbh(i,k)))*rpdel(i,k)
     752             :             ds3(i) = beta(i)*(etagdt(i)*(sc(i) - sbh(i,k)) - hlat*grav*cldwtr(i))* &
     753    32205264 :                      rpdel(i,k-1)
     754    32205264 :             dq3(i) = beta(i)*etagdt(i)*(shc(i) - shbh(i,k))*rpdel(i,k-1)
     755             : !
     756             : ! Isolate convective fluxes for later diagnostics
     757             : !
     758    32205264 :             fslkp = eta(i)*(sc(i) - sbh(i,k+1))
     759    32205264 :             fslkm = beta(i)*(eta(i)*(sc(i) - sbh(i,k)) - hlat*cldwtr(i)*rtdt)
     760    32205264 :             fqlkp = eta(i)*(shc(i) - shbh(i,k+1))
     761    32205264 :             fqlkm = beta(i)*eta(i)*(shc(i) - shbh(i,k))
     762             : !
     763             : ! Update thermodynamic profile (update sb, hb, & hbs later)
     764             : !
     765    32205264 :             tb (i,k+1) = tb(i,k+1)  + ds1(i)*rcp
     766    32205264 :             tb (i,k  ) = tb(i,k  )  + ds2(i)*rcp
     767    32205264 :             tb (i,k-1) = tb(i,k-1)  + ds3(i)*rcp
     768    32205264 :             shb(i,k+1) = shb(i,k+1) + dq1(i)
     769    32205264 :             shb(i,k  ) = shb(i,k  ) + dq2(i)
     770    32205264 :             shb(i,k-1) = shb(i,k-1) + dq3(i)
     771             : !
     772             : ! ** Update diagnostic information for final budget **
     773             : ! Tracking precipitation, temperature & specific humidity tendencies,
     774             : ! rainout term, convective mass flux, convective liquid
     775             : ! water static energy flux, and convective total water flux
     776             : ! The variable afac makes the necessary adjustment to the
     777             : ! diagnostic fluxes to account for adjustment time scale based on
     778             : ! how relaxation time scale is to be applied (column vs. triplet)
     779             : !
     780    32205264 :             prec(i)    = prec(i) + (rnwtr(i)/rhoh2o)*adjfac
     781             : !
     782             : ! The following variables have units of "units"/second
     783             : !
     784    32205264 :             cmfdt (i,k+1) = cmfdt (i,k+1) + ds1(i)*rtdt*adjfac
     785    32205264 :             cmfdt (i,k  ) = cmfdt (i,k  ) + ds2(i)*rtdt*adjfac
     786    32205264 :             cmfdt (i,k-1) = cmfdt (i,k-1) + ds3(i)*rtdt*adjfac
     787    32205264 :             cmfdq (i,k+1) = cmfdq (i,k+1) + dq1(i)*rtdt*adjfac
     788    32205264 :             cmfdq (i,k  ) = cmfdq (i,k  ) + dq2(i)*rtdt*adjfac
     789    32205264 :             cmfdq (i,k-1) = cmfdq (i,k-1) + dq3(i)*rtdt*adjfac
     790             : ! JJH changes to export cloud liquid water --------------------------------
     791    32205264 :             qc    (i,k  ) = (grav*(totcond(i)-rnwtr(i))*rpdel(i,k))*rtdt*adjfac
     792    32205264 :             cmfdqr(i,k  ) = cmfdqr(i,k  ) + (grav*rnwtr(i)*rpdel(i,k))*rtdt*adjfac
     793    32205264 :             cmfmc (i,k+1) = cmfmc (i,k+1) + eta(i)*adjfac
     794    32205264 :             cmfmc (i,k  ) = cmfmc (i,k  ) + beta(i)*eta(i)*adjfac
     795             : !
     796             : ! The following variables have units of w/m**2
     797             : !
     798    32205264 :             cmfsl (i,k+1) = cmfsl (i,k+1) + fslkp*adjfac
     799    32205264 :             cmfsl (i,k  ) = cmfsl (i,k  ) + fslkm*adjfac
     800    32205264 :             cmflq (i,k+1) = cmflq (i,k+1) + hlat*fqlkp*adjfac
     801    32205264 :             cmflq (i,k  ) = cmflq (i,k  ) + hlat*fqlkm*adjfac
     802     5008903 : 30          continue
     803             : !
     804             : ! Next, convectively modify passive constituents
     805             : ! For now, when applying relaxation time scale to thermal fields after
     806             : ! entire column has undergone convective overturning, constituents will
     807             : ! be mixed using a "relaxed" value of the mass flux determined above
     808             : ! Although this will be inconsistant with the treatment of the thermal
     809             : ! fields, it's computationally much cheaper, no more-or-less justifiable,
     810             : ! and consistent with how the history tape mass fluxes would be used in
     811             : ! an off-line mode (i.e., using an off-line transport model)
     812             : !
     813    15026709 :             do 50 m=2,pcnst    ! note: indexing assumes water is first field
     814    10017806 :                if (cnst_get_type_byind(m).eq.'dry') then
     815           0 :                   pd(:ncol,:) = pdeldry(:ncol,:)
     816           0 :                   rpd(:ncol,:) = rpdeldry(:ncol,:)
     817           0 :                   pm(:ncol,:) = pmiddry(:ncol,:)
     818             :                else
     819  4364572634 :                   pd(:ncol,:) = pdel(:ncol,:)
     820  4364572634 :                   rpd(:ncol,:) = rpdel(:ncol,:)
     821  4374590440 :                   pm(:ncol,:) = pmid(:ncol,:)
     822             :                endif
     823    74428334 :                do 40 ii=1,len1
     824    64410528 :                   i = indx1(ii)
     825             : !
     826             : ! If any of the reported values of the constituent is negative in
     827             : ! the three adjacent levels, nothing will be done to the profile
     828             : !
     829    64410528 :                   if ((dq(i,k+1,m) < 0.0_r8) .or. (dq(i,k,m) < 0.0_r8) .or. (dq(i,k-1,m) < 0.0_r8)) go to 40
     830             : !
     831             : ! Specify constituent interface values (linear interpolation)
     832             : !
     833    64410528 :                   cmrh(i,k  ) = 0.5_r8*(dq(i,k-1,m) + dq(i,k  ,m))
     834    64410528 :                   cmrh(i,k+1) = 0.5_r8*(dq(i,k  ,m) + dq(i,k+1,m))
     835             : !
     836             : ! Specify perturbation properties of constituents in PBL
     837             : !
     838    64410528 :                   pblhgt = max(pblh(i),1.0_r8)
     839    64410528 :                   if ( (zm(i,k+1) <= pblhgt) .and. dzcld(i) == 0.0_r8 ) then
     840           0 :                      fac1 = max(0.0_r8,1.0_r8-zm(i,k+1)/pblhgt)
     841           0 :                      cmrc(i) = dq(i,k+1,m) + qpert(i,m)*fac1
     842             :                   else
     843    64410528 :                      cmrc(i) = dq(i,k+1,m)
     844             :                   end if
     845             : !
     846             : ! Determine fluxes, flux divergence => changes due to convection
     847             : ! Logic must be included to avoid producing negative values. A bit
     848             : ! messy since there are no a priori assumptions about profiles.
     849             : ! Tendency is modified (reduced) when pending disaster detected.
     850             : !
     851    64410528 :                   botflx   = etagdt(i)*(cmrc(i) - cmrh(i,k+1))*adjfac
     852    64410528 :                   topflx   = beta(i)*etagdt(i)*(cmrc(i)-cmrh(i,k))*adjfac
     853    64410528 :                   dcmr1(i) = -botflx*rpd(i,k+1)
     854    64410528 :                   efac1    = 1.0_r8
     855    64410528 :                   efac2    = 1.0_r8
     856    64410528 :                   efac3    = 1.0_r8
     857             : !
     858    64410528 :                   if (dq(i,k+1,m)+dcmr1(i) < 0.0_r8) then
     859           0 :                      if ( abs(dcmr1(i)) > 1.e-300_r8 ) then
     860           0 :                         efac1 = max(tiny,abs(dq(i,k+1,m)/dcmr1(i)) - eps)
     861             :                      else
     862           0 :                         efac1 = tiny
     863             :                      endif
     864             :                   end if
     865             : !
     866    64410528 :                   if (efac1 == tiny .or. efac1 > 1.0_r8) efac1 = 0.0_r8
     867    64410528 :                   dcmr1(i) = -efac1*botflx*rpd(i,k+1)
     868    64410528 :                   dcmr2(i) = (efac1*botflx - topflx)*rpd(i,k)
     869             : !
     870    64410528 :                   if (dq(i,k,m)+dcmr2(i) < 0.0_r8) then
     871     1276174 :                      if ( abs(dcmr2(i)) > 1.e-300_r8 ) then
     872     1276174 :                         efac2 = max(tiny,abs(dq(i,k  ,m)/dcmr2(i)) - eps)
     873             :                      else
     874             :                         efac2 = tiny
     875             :                      endif
     876             :                   end if
     877             : !
     878    64410528 :                   if (efac2 == tiny .or. efac2 > 1.0_r8) efac2 = 0.0_r8
     879    64410528 :                   dcmr2(i) = (efac1*botflx - efac2*topflx)*rpd(i,k)
     880    64410528 :                   dcmr3(i) = efac2*topflx*rpd(i,k-1)
     881             : !
     882    64410528 :                   if ( (dq(i,k-1,m)+dcmr3(i) < 0.0_r8 ) ) then
     883     7319589 :                      if  ( abs(dcmr3(i)) > 1.e-300_r8 ) then
     884     7319589 :                         efac3 = max(tiny,abs(dq(i,k-1,m)/dcmr3(i)) - eps)
     885             :                      else
     886             :                         efac3 = tiny
     887             :                      endif
     888             :                   end if
     889             : !
     890    64410528 :                   if (efac3 == tiny .or. efac3 > 1.0_r8) efac3 = 0.0_r8
     891    64410528 :                   efac3    = min(efac2,efac3)
     892    64410528 :                   dcmr2(i) = (efac1*botflx - efac3*topflx)*rpd(i,k)
     893    64410528 :                   dcmr3(i) = efac3*topflx*rpd(i,k-1)
     894             : !
     895    64410528 :                   dq(i,k+1,m) = dq(i,k+1,m) + dcmr1(i)
     896    64410528 :                   dq(i,k  ,m) = dq(i,k  ,m) + dcmr2(i)
     897    64410528 :                   dq(i,k-1,m) = dq(i,k-1,m) + dcmr3(i)
     898    10017806 : 40                continue
     899     5008903 : 50                continue                ! end of m=2,pcnst loop
     900             : !
     901             : ! Constituent modifications complete
     902             : !
     903     5008903 :                   if (k == limcnv+1) go to 60
     904             : !
     905             : ! Complete update of thermodynamic structure at integer levels
     906             : ! gather/scatter points that need new values of shbs and gamma
     907             : !
     908    37214167 :                   do ii=1,len1
     909    32205264 :                      i = indx1(ii)
     910    32205264 :                      vtemp1(ii     ) = tb(i,k)
     911    32205264 :                      vtemp1(ii+len1) = tb(i,k-1)
     912    32205264 :                      vtemp2(ii     ) = pmid(i,k)
     913    37214167 :                      vtemp2(ii+len1) = pmid(i,k-1)
     914             :                   end do
     915           0 :                   call qsat(vtemp1(1:2*len1), vtemp2(1:2*len1), &
     916     5008903 :                             vtemp5(1:2*len1), vtemp3(1:2*len1), 2*len1, gam=vtemp4(1:2*len1))
     917    37214167 :                   do ii=1,len1
     918    32205264 :                      i = indx1(ii)
     919    32205264 :                      shbs(i,k  ) = vtemp3(ii     )
     920    32205264 :                      shbs(i,k-1) = vtemp3(ii+len1)
     921    32205264 :                      gam(i,k  ) = vtemp4(ii     )
     922    32205264 :                      gam(i,k-1) = vtemp4(ii+len1)
     923    32205264 :                      sb (i,k  ) = sb(i,k  ) + ds2(i)
     924    32205264 :                      sb (i,k-1) = sb(i,k-1) + ds3(i)
     925    32205264 :                      hb (i,k  ) = sb(i,k  ) + hlat*shb(i,k  )
     926    32205264 :                      hb (i,k-1) = sb(i,k-1) + hlat*shb(i,k-1)
     927    32205264 :                      hbs(i,k  ) = sb(i,k  ) + hlat*shbs(i,k  )
     928    37214167 :                      hbs(i,k-1) = sb(i,k-1) + hlat*shbs(i,k-1)
     929             :                   end do
     930             : !
     931             : ! Update thermodynamic information at half (i.e., interface) levels
     932             : !
     933    37214167 :                   do ii=1,len1
     934    32205264 :                      i = indx1(ii)
     935    32205264 :                      sbh (i,k) = 0.5_r8*(sb(i,k) + sb(i,k-1))
     936    32205264 :                      shbh(i,k) = qhalf(shb(i,k-1),shb(i,k),shbs(i,k-1),shbs(i,k))
     937    32205264 :                      hbh (i,k) = sbh(i,k) + hlat*shbh(i,k)
     938    32205264 :                      sbh (i,k-1) = 0.5_r8*(sb(i,k-1) + sb(i,k-2))
     939    32205264 :                      shbh(i,k-1) = qhalf(shb(i,k-2),shb(i,k-1),shbs(i,k-2),shbs(i,k-1))
     940    37214167 :                      hbh (i,k-1) = sbh(i,k-1) + hlat*shbh(i,k-1)
     941             :                   end do
     942             : !
     943             : #if ( defined DIAGNS )
     944             : !#######################################################################
     945             : !#                                                                     #
     946             : !#    this update necessary, only if debugging diagnostics requested   #
     947             : !#                                                                     #
     948             :                   do i=1,ncol
     949             :                      if (lat(i) == jloc .and. nstep >= nsloc) then
     950             :                         call qsat(tb(i,k+1), pmid(i,k+1), &
     951             :                              es, shbs(i,k+1), gam=gam(i,k+1))
     952             :                         sb (i,k+1) = sb(i,k+1) + ds1(i)
     953             :                         hb (i,k+1) = sb(i,k+1) + hlat*shb(i,k+1)
     954             :                         hbs(i,k+1) = sb(i,k+1) + hlat*shbs(i,k+1)
     955             :                         kpp = k + 2
     956             :                         if (k+1 == pver) kpp = k + 1
     957             :                         do kp=k+1,kpp
     958             :                            kpm1 = kp-1
     959             :                            sbh(i,kp)  = 0.5_r8*(sb(i,kpm1) + sb(i,kp))
     960             :                            shbh(i,kp) = qhalf(shb(i,kpm1),shb(i,kp),shbs(i,kpm1),shbs(i,kp))
     961             :                            hbh(i,kp)  = sbh(i,kp) + hlat*shbh(i,kp)
     962             :                         end do
     963             :                      end if
     964             :                   end do
     965             : !#                                                                     #
     966             : !#          diagnostic output                                          #
     967             : !#                                                                     #
     968             :                   do i=1,ncol
     969             :                     if ((lat(i)== jloc).and.(lon(i)==iloc).and.(nstep>=nsloc)) then
     970             :                      write(iulog, 8060) k
     971             :                      fac = grav*864._r8
     972             :                      do n=limcnv,pver
     973             :                         rh  = shb(i,n)/shbs(i,n)
     974             :                         write(iulog,8020)shbh(i,n),sbh(i,n),hbh(i,n),fac*cmfmc(i,n), &
     975             :                                      cmfsl(i,n), cmflq(i,n)
     976             : !--------------write(iulog, 8050)
     977             : !--------------write(iulog, 8030) fac*cmfmc(i,n),cmfsl(i,n), cmflq(i,n)
     978             :                         write(iulog, 8040) tb(i,n),shb(i,n),rh,sb(i,n),hb(i,n), &
     979             :                                        hbs(i,n), ztodt*cmfdt(i,n),ztodt*cmfdq(i,n), &
     980             :                                        ztodt*cmfdqr(i,n)
     981             :                      end do
     982             :                      write(iulog, 8000) prec(i)
     983             :                     end if
     984             :                   end do
     985             : !#                                                                     #
     986             : !#                                                                     #
     987             : !#######################################################################
     988             : #endif
     989             : !
     990             : ! Ensure that dzcld is reset if convective mass flux zero
     991             : ! specify the current vertical extent of the convective activity
     992             : ! top of convective layer determined by size of overshoot param.
     993             : !
     994    83741439 : 60                do i=1,ncol
     995    78732536 :                      etagt0 = eta(i).gt.0.0_r8
     996    78732536 :                      if ( .not. etagt0) dzcld(i) = 0.0_r8
     997    78732536 :                      if (etagt0 .and. beta(i) > betamn) then
     998    15727755 :                         ktp = k-1
     999             :                      else
    1000             :                         ktp = k
    1001             :                      end if
    1002   108639896 :                      if (etagt0) then
    1003    32182355 :                         rk=k
    1004    32182355 :                         rktp=ktp
    1005    32182355 :                         cnt(i) = min(cnt(i),rktp)
    1006    32182355 :                         cnb(i) = max(cnb(i),rk)
    1007             :                      end if
    1008             :                   end do
    1009     1495368 : 70                continue                  ! end of k loop
    1010             : !
    1011             : ! ** apply final thermodynamic tendencies **
    1012             : !
    1013             : !**BAB don't update input profiles
    1014             : !!$                  do k=limcnv,pver
    1015             : !!$                     do i=1,ncol
    1016             : !!$                        t (i,k) = t (i,k) + cmfdt(i,k)*ztodt
    1017             : !!$                        q(i,k,1) = q(i,k,1) + cmfdq(i,k)*ztodt
    1018             : !!$                     end do
    1019             : !!$                  end do
    1020             : ! Set output q tendencies
    1021   650693736 :       dq(:ncol,:,1 ) = cmfdq(:ncol,:)
    1022  1302882840 :       dq(:ncol,:,2:) = (dq(:ncol,:,2:) - q(:ncol,:,2:))/ztodt
    1023             : !
    1024             : ! Kludge to prevent cnb-cnt from being zero (in the event
    1025             : ! someone decides that they want to divide by this quantity)
    1026             : !
    1027    24969168 :                   do i=1,ncol
    1028    24969168 :                      if (cnb(i) /= 0.0_r8 .and. cnb(i) == cnt(i)) then
    1029     5544475 :                         cnt(i) = cnt(i) - 1.0_r8
    1030             :                      end if
    1031             :                   end do
    1032             : !
    1033    24969168 :                   do i=1,ncol
    1034    24969168 :                      precc(i) = prec(i)*rtdt
    1035             :                   end do
    1036             : !
    1037             : ! Compute reserved liquid (not yet in cldliq) for energy integrals.
    1038             : ! Treat rliq as flux out bottom, to be added back later.
    1039    40374936 :    do k = 1, pver
    1040   650693736 :       do i = 1, ncol
    1041   649198368 :          rliq(i) = rliq(i) + qc(i,k)*pdel(i,k)/grav
    1042             :       end do
    1043             :    end do
    1044    24969168 :    rliq(:ncol) = rliq(:ncol) /1000._r8
    1045             : 
    1046             : #if ( defined DIAGNS )
    1047             : !#######################################################################
    1048             : !#                                                                     #
    1049             : !#    we're done ... show final result if debug diagnostics requested  #
    1050             : !#                                                                     #
    1051             :                   do i=1,ncol
    1052             :                     if ((lat(i)==jloc).and.(lon(i)==iloc).and.(nstep>=nsloc)) then
    1053             :                      fac = grav*864._r8
    1054             :                      write(iulog, 8010)
    1055             :                      do k=limcnv,pver
    1056             :                         rh = shb(i,k)/shbs(i,k)
    1057             :                         write(iulog, 8020) shbh(i,k),sbh(i,k),hbh(i,k),fac*cmfmc(i,k), &
    1058             :                                        cmfsl(i,k), cmflq(i,k)
    1059             :                         write(iulog, 8040) tb(i,k),shb(i,k),rh   ,sb(i,k),hb(i,k), &
    1060             :                                        hbs(i,k), ztodt*cmfdt(i,k),ztodt*cmfdq(i,k), &
    1061             :                                        ztodt*cmfdqr(i,k)
    1062             :                      end do
    1063             :                      write(iulog, 8000) prec(i)
    1064             : !#                                                                     #
    1065             : !#       approximate vertical integral of moist static energy and      #
    1066             : !#       total preciptable water after adjustment and output changes   #
    1067             : !#                                                                     #
    1068             :                      hsum2 = 0.0_r8
    1069             :                      qsum2 = 0.0_r8
    1070             :                      do k=limcnv,pver
    1071             :                         hsum2 = hsum2 + pdel(i,k)*rgrav*hb(i,k)
    1072             :                         qsum2 = qsum2 + pdel(i,k)*rgrav*shb(i,k)
    1073             :                      end do
    1074             : !#                                                                     #
    1075             :                      write(iulog,8070) hsum1, hsum2, abs(hsum2-hsum1)/hsum2, &
    1076             :                                     qsum1, qsum2, abs(qsum2-qsum1)/qsum2
    1077             :                     end if
    1078             :                   enddo
    1079             : !#                                                                     #
    1080             : !#                                                                     #
    1081             : !#######################################################################
    1082             : #endif
    1083     1495368 :                   return                 ! we're all done ... return to calling procedure
    1084             : #if ( defined DIAGNS )
    1085             : !
    1086             : ! Formats
    1087             : !
    1088             : 8000              format(///,10x,'PREC = ',3pf12.6,/)
    1089             : 8010              format('1**        TB      SHB      RH       SB', &
    1090             :                         '       HB      HBS      CAH      CAM       PRECC ', &
    1091             :                         '     ETA      FSL       FLQ     **', /)
    1092             : 8020              format(' ----- ',     9x,3p,f7.3,2x,2p,     9x,-3p,f7.3,2x, &
    1093             :                         f7.3, 37x, 0p,2x,f8.2,  0p,2x,f8.2,2x,f8.2, ' ----- ')
    1094             : 8030              format(' ----- ',  0p,82x,f8.2,  0p,2x,f8.2,2x,f8.2, &
    1095             :                          ' ----- ')
    1096             : 8040              format(' - - - ',f7.3,2x,3p,f7.3,2x,2p,f7.3,2x,-3p,f7.3,2x, &
    1097             :                         f7.3, 2x,f8.3,2x,0p,f7.3,3p,2x,f7.3,2x,f7.3,30x, &
    1098             :                          ' - - - ')
    1099             : 8050              format(' ----- ',110x,' ----- ')
    1100             : 8060              format('1 K =>',  i4,/, &
    1101             :                            '           TB      SHB      RH       SB', &
    1102             :                            '       HB      HBS      CAH      CAM       PREC ', &
    1103             :                            '     ETA      FSL       FLQ', /)
    1104             : 8070              format(' VERTICALLY INTEGRATED MOIST STATIC ENERGY BEFORE, AFTER', &
    1105             :                         ' AND PERCENTAGE DIFFERENCE => ',1p,2e15.7,2x,2p,f7.3,/, &
    1106             :                         ' VERTICALLY INTEGRATED MOISTURE            BEFORE, AFTER' &,
    1107             :                         ' AND PERCENTAGE DIFFERENCE => ',1p,2e15_r8.7_r8,2x,2p,f7.3,/)
    1108             : 8080              format(' BETA, ETA => ', 1p,2e12.3)
    1109             : 8090              format (' k+1, sc, shc, hc => ', 1x, i2, 1p, 3e12.4)
    1110             : #endif
    1111             : !
    1112             : end subroutine cmfmca
    1113             : end module hk_conv

Generated by: LCOV version 1.14