LCOV - code coverage report
Current view: top level - physics/cam - vertical_diffusion.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 273 599 45.6 %
Date: 2025-03-14 01:18:36 Functions: 5 6 83.3 %

          Line data    Source code
       1             : module vertical_diffusion
       2             : 
       3             : !----------------------------------------------------------------------------------------------------- !
       4             : ! Module to compute vertical diffusion of momentum,  moisture, trace constituents                      !
       5             : ! and static energy. Separate modules compute                                                          !
       6             : !   1. stresses associated with turbulent flow over orography                                          !
       7             : !      ( turbulent mountain stress )                                                                   !
       8             : !   2. eddy diffusivities, including nonlocal tranport terms                                           !
       9             : !   3. molecular diffusivities                                                                         !
      10             : ! Lastly, a implicit diffusion solver is called, and tendencies retrieved by                           !
      11             : ! differencing the diffused and initial states.                                                        !
      12             : !                                                                                                      !
      13             : ! Calling sequence:                                                                                    !
      14             : !                                                                                                      !
      15             : !  vertical_diffusion_init      Initializes vertical diffustion constants and modules                  !
      16             : !        init_molec_diff        Initializes molecular diffusivity module                               !
      17             : !        init_eddy_diff         Initializes eddy diffusivity module (includes PBL)                     !
      18             : !        init_tms               Initializes turbulent mountain stress module                           !
      19             : !        init_vdiff             Initializes diffusion solver module                                    !
      20             : !  vertical_diffusion_ts_init   Time step initialization (only used for upper boundary condition)      !
      21             : !  vertical_diffusion_tend      Computes vertical diffusion tendencies                                 !
      22             : !        compute_tms            Computes turbulent mountain stresses                                   !
      23             : !        compute_eddy_diff      Computes eddy diffusivities and countergradient terms                  !
      24             : !        compute_vdiff          Solves vertical diffusion equations, including molecular diffusivities !
      25             : !                                                                                                      !
      26             : !----------------------------------------------------------------------------------------------------- !
      27             : ! Some notes on refactoring changes made in 2015, which were not quite finished.                       !
      28             : !                                                                                                      !
      29             : !      - eddy_diff_tend should really only have state, pbuf, and cam_in as inputs. The process of      !
      30             : !        removing these arguments, and referring to pbuf fields instead, is not complete.              !
      31             : !                                                                                                      !
      32             : !      - compute_vdiff was intended to be split up into three components:                              !
      33             : !                                                                                                      !
      34             : !         1. Diffusion of winds and heat ("U", "V", and "S" in the fieldlist object).                  !
      35             : !                                                                                                      !
      36             : !         2. Turbulent diffusion of a single constituent                                               !
      37             : !                                                                                                      !
      38             : !         3. Molecular diffusion of a single constituent                                               !
      39             : !                                                                                                      !
      40             : !        This reorganization would allow the three resulting functions to each use a simpler interface !
      41             : !        than the current combined version, and possibly also remove the need to use the fieldlist     !
      42             : !        object at all.                                                                                !
      43             : !                                                                                                      !
      44             : !      - The conditionals controlled by "do_pbl_diags" are somewhat scattered. It might be better to   !
      45             : !        pull out these diagnostic calculations and outfld calls into separate functions.              !
      46             : !                                                                                                      !
      47             : !---------------------------Code history-------------------------------------------------------------- !
      48             : ! J. Rosinski : Jun. 1992                                                                              !
      49             : ! J. McCaa    : Sep. 2004                                                                              !
      50             : ! S. Park     : Aug. 2006, Dec. 2008. Jan. 2010                                                        !
      51             : !----------------------------------------------------------------------------------------------------- !
      52             : 
      53             : use shr_kind_mod,     only : r8 => shr_kind_r8, i4=> shr_kind_i4
      54             : use ppgrid,           only : pcols, pver, pverp
      55             : use constituents,     only : pcnst
      56             : use diffusion_solver, only : vdiff_selector
      57             : use cam_abortutils,   only : endrun
      58             : use error_messages,   only : handle_errmsg
      59             : use physconst,        only :          &
      60             :      cpair  , &     ! Specific heat of dry air
      61             :      gravit , &     ! Acceleration due to gravity
      62             :      rair   , &     ! Gas constant for dry air
      63             :      zvir   , &     ! rh2o/rair - 1
      64             :      latvap , &     ! Latent heat of vaporization
      65             :      latice , &     ! Latent heat of fusion
      66             :      karman , &     ! von Karman constant
      67             :      mwdry  , &     ! Molecular weight of dry air
      68             :      avogad         ! Avogadro's number
      69             : use cam_history,      only : fieldname_len
      70             : use perf_mod
      71             : use cam_logfile,      only : iulog
      72             : use ref_pres,         only : do_molec_diff, nbot_molec
      73             : use phys_control,     only : phys_getopts
      74             : use time_manager,     only : is_first_step
      75             : implicit none
      76             : private
      77             : save
      78             : 
      79             : ! ----------------- !
      80             : ! Public interfaces !
      81             : ! ----------------- !
      82             : 
      83             : public vd_readnl
      84             : public vd_register                                   ! Register multi-time-level variables with physics buffer
      85             : public vertical_diffusion_init                       ! Initialization
      86             : public vertical_diffusion_ts_init                    ! Time step initialization (only used for upper boundary condition)
      87             : public vertical_diffusion_tend                       ! Full vertical diffusion routine
      88             : 
      89             : ! ------------ !
      90             : ! Private data !
      91             : ! ------------ !
      92             : 
      93             : character(len=16)    :: eddy_scheme                  ! Default set in phys_control.F90, use namelist to change
      94             : !     'HB'       = Holtslag and Boville (default)
      95             : !     'HBR'      = Holtslag and Boville and Rash
      96             : !     'diag_TKE' = Bretherton and Park ( UW Moist Turbulence Scheme )
      97             : logical, parameter   :: wstarent = .true.            ! Use wstar (.true.) or TKE (.false.) entrainment closure
      98             : ! ( when 'diag_TKE' scheme is selected )
      99             : logical              :: do_pseudocon_diff = .false.  ! If .true., do pseudo-conservative variables diffusion
     100             : 
     101             : character(len=16)    :: shallow_scheme               ! Shallow convection scheme
     102             : 
     103             : type(vdiff_selector) :: fieldlist_wet                ! Logical switches for moist mixing ratio diffusion
     104             : type(vdiff_selector) :: fieldlist_dry                ! Logical switches for dry mixing ratio diffusion
     105             : type(vdiff_selector) :: fieldlist_molec              ! Logical switches for molecular diffusion
     106             : integer              :: tke_idx, kvh_idx, kvm_idx    ! TKE and eddy diffusivity indices for fields in the physics buffer
     107             : integer              :: kvt_idx                      ! Index for kinematic molecular conductivity
     108             : integer              :: tauresx_idx, tauresy_idx     ! Redisual stress for implicit surface stress
     109             : 
     110             : character(len=fieldname_len) :: vdiffnam(pcnst)      ! Names of vertical diffusion tendencies
     111             : integer              :: ixcldice, ixcldliq           ! Constituent indices for cloud liquid and ice water
     112             : integer              :: ixnumice, ixnumliq
     113             : 
     114             : integer              :: pblh_idx, tpert_idx, qpert_idx
     115             : 
     116             : ! pbuf fields for unicon
     117             : integer              :: qtl_flx_idx  = -1            ! for use in cloud macrophysics when UNICON is on
     118             : integer              :: qti_flx_idx  = -1            ! for use in cloud macrophysics when UNICON is on
     119             : 
     120             : ! pbuf fields for tms
     121             : integer              :: ksrftms_idx  = -1
     122             : integer              :: tautmsx_idx  = -1
     123             : integer              :: tautmsy_idx  = -1
     124             : 
     125             : ! pbuf fields for blj (Beljaars)
     126             : integer              :: dragblj_idx  = -1
     127             : integer              :: taubljx_idx  = -1
     128             : integer              :: taubljy_idx  = -1
     129             : 
     130             : ! pbuf field for clubb top above which HB (Holtslag Boville) scheme may be enabled
     131             : integer              :: clubbtop_idx = -1
     132             : 
     133             : logical              :: diff_cnsrv_mass_check        ! do mass conservation check
     134             : logical              :: do_iss                       ! switch for implicit turbulent surface stress
     135             : logical              :: do_pbl_diags = .false.
     136             : logical              :: waccmx_mode = .false.
     137             : logical              :: do_hb_above_clubb = .false.
     138             : 
     139             : real(r8),allocatable :: kvm_sponge(:)
     140             : 
     141             : contains
     142             : 
     143             :   ! =============================================================================== !
     144             :   !                                                                                 !
     145             :   ! =============================================================================== !
     146        1536 : subroutine vd_readnl(nlfile)
     147             : 
     148             :   use namelist_utils,  only: find_group_name
     149             :   use units,           only: getunit, freeunit
     150             :   use spmd_utils,      only: masterproc, masterprocid, mpi_logical, mpicom
     151             :   use shr_log_mod,     only: errMsg => shr_log_errMsg
     152             :   use trb_mtn_stress_cam, only: trb_mtn_stress_readnl
     153             :   use beljaars_drag_cam, only: beljaars_drag_readnl
     154             :   use eddy_diff_cam,   only: eddy_diff_readnl
     155             : 
     156             :   character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
     157             : 
     158             :   ! Local variables
     159             :   integer :: unitn, ierr
     160             :   character(len=*), parameter :: subname = 'vd_readnl'
     161             : 
     162             :   namelist /vert_diff_nl/ diff_cnsrv_mass_check, do_iss
     163             :   !-----------------------------------------------------------------------------
     164             : 
     165        1536 :   if (masterproc) then
     166           2 :      unitn = getunit()
     167           2 :      open( unitn, file=trim(nlfile), status='old' )
     168           2 :      call find_group_name(unitn, 'vert_diff_nl', status=ierr)
     169           2 :      if (ierr == 0) then
     170           2 :         read(unitn, vert_diff_nl, iostat=ierr)
     171           2 :         if (ierr /= 0) then
     172           0 :            call endrun(subname // ':: ERROR reading namelist')
     173             :         end if
     174             :      end if
     175           2 :      close(unitn)
     176           2 :      call freeunit(unitn)
     177             :   end if
     178             : 
     179        1536 :   call mpi_bcast(diff_cnsrv_mass_check, 1, mpi_logical, masterprocid, mpicom, ierr)
     180        1536 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     181        1536 :   call mpi_bcast(do_iss,                1, mpi_logical, masterprocid, mpicom, ierr)
     182        1536 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     183             : 
     184             :   ! Get eddy_scheme setting from phys_control.
     185             :   call phys_getopts( eddy_scheme_out          =          eddy_scheme, &
     186        1536 :        shallow_scheme_out       =       shallow_scheme )
     187             : 
     188             :   ! TMS reads its own namelist.
     189        1536 :   call trb_mtn_stress_readnl(nlfile)
     190             : 
     191             :   ! Beljaars reads its own namelist.
     192        1536 :   call beljaars_drag_readnl(nlfile)
     193             : 
     194        1536 :   if (eddy_scheme == 'diag_TKE') call eddy_diff_readnl(nlfile)
     195             : 
     196        1536 : end subroutine vd_readnl
     197             : 
     198             : ! =============================================================================== !
     199             : !                                                                                 !
     200             : ! =============================================================================== !
     201             : 
     202        1536 : subroutine vd_register()
     203             : 
     204             :   !------------------------------------------------ !
     205             :   ! Register physics buffer fields and constituents !
     206             :   !------------------------------------------------ !
     207             : 
     208        1536 :   use physics_buffer,      only : pbuf_add_field, dtype_r8, dtype_i4
     209             :   use trb_mtn_stress_cam,  only : trb_mtn_stress_register
     210             :   use beljaars_drag_cam,   only : beljaars_drag_register
     211             :   use eddy_diff_cam,       only : eddy_diff_register
     212             : 
     213             :   ! Add fields to physics buffer
     214             : 
     215             :   ! kvt is used by gw_drag.  only needs physpkg scope.
     216        1536 :   call pbuf_add_field('kvt', 'physpkg', dtype_r8, (/pcols,pverp/), kvt_idx)
     217             : 
     218             : 
     219        1536 :   if (eddy_scheme /= 'CLUBB_SGS') then
     220           0 :      call pbuf_add_field('kvh',      'global', dtype_r8, (/pcols, pverp/), kvh_idx)
     221             :   end if
     222             : 
     223        1536 :   call pbuf_add_field('kvm',      'global', dtype_r8, (/pcols, pverp/), kvm_idx )
     224        1536 :   call pbuf_add_field('pblh',     'global', dtype_r8, (/pcols/),        pblh_idx)
     225        1536 :   call pbuf_add_field('tke',      'global', dtype_r8, (/pcols, pverp/), tke_idx)
     226             : 
     227        1536 :   call pbuf_add_field('tauresx',  'global', dtype_r8, (/pcols/),        tauresx_idx)
     228        1536 :   call pbuf_add_field('tauresy',  'global', dtype_r8, (/pcols/),        tauresy_idx)
     229             : 
     230        1536 :   call pbuf_add_field('tpert', 'global', dtype_r8, (/pcols/),                       tpert_idx)
     231        1536 :   call pbuf_add_field('qpert', 'global', dtype_r8, (/pcols/),                       qpert_idx)
     232             : 
     233        1536 :   if (trim(shallow_scheme) == 'UNICON') then
     234           0 :      call pbuf_add_field('qtl_flx',  'global', dtype_r8, (/pcols, pverp/), qtl_flx_idx)
     235           0 :      call pbuf_add_field('qti_flx',  'global', dtype_r8, (/pcols, pverp/), qti_flx_idx)
     236             :   end if
     237             : 
     238             :   ! diag_TKE fields
     239        1536 :   if (eddy_scheme == 'diag_TKE') then
     240           0 :      call eddy_diff_register()
     241             :   end if
     242             : 
     243             :   ! TMS fields
     244        1536 :   call trb_mtn_stress_register()
     245             : 
     246             :   ! Beljaars fields
     247        1536 :   call beljaars_drag_register()
     248             : 
     249        1536 : end subroutine vd_register
     250             : 
     251             : ! =============================================================================== !
     252             : !                                                                                 !
     253             : ! =============================================================================== !
     254             : 
     255        1536 : subroutine vertical_diffusion_init(pbuf2d)
     256             : 
     257             :   !------------------------------------------------------------------!
     258             :   ! Initialization of time independent fields for vertical diffusion !
     259             :   ! Calls initialization routines for subsidiary modules             !
     260             :   !----------------------------------------------------------------- !
     261             : 
     262        1536 :   use cam_history,       only : addfld, add_default, horiz_only
     263             :   use cam_history,       only : register_vector_field
     264             :   use eddy_diff_cam,     only : eddy_diff_init
     265             :   use hb_diff,           only : init_hb_diff
     266             :   use molec_diff,        only : init_molec_diff
     267             :   use diffusion_solver,  only : init_vdiff, new_fieldlist_vdiff, vdiff_select
     268             :   use constituents,      only : cnst_get_ind, cnst_get_type_byind, cnst_name, cnst_get_molec_byind, cnst_ndropmixed
     269             :   use spmd_utils,        only : masterproc
     270             :   use ref_pres,          only : press_lim_idx, pref_mid
     271             :   use physics_buffer,    only : pbuf_set_field, pbuf_get_index, physics_buffer_desc
     272             :   use trb_mtn_stress_cam,only : trb_mtn_stress_init
     273             :   use beljaars_drag_cam, only : beljaars_drag_init
     274             :   use upper_bc,          only : ubc_init
     275             :   use phys_control,      only : waccmx_is, fv_am_correction
     276             :   use ref_pres,          only : ptop_ref
     277             : 
     278             :   type(physics_buffer_desc), pointer :: pbuf2d(:,:)
     279             :   character(128) :: errstring   ! Error status for init_vdiff
     280             :   integer        :: ntop_eddy   ! Top    interface level to which eddy vertical diffusion is applied ( = 1 )
     281             :   integer        :: nbot_eddy   ! Bottom interface level to which eddy vertical diffusion is applied ( = pver )
     282             :   integer        :: k           ! Vertical loop index
     283             : 
     284             :   real(r8), parameter :: ntop_eddy_pres = 1.e-7_r8 ! Pressure below which eddy diffusion is not done in WACCM-X. (Pa)
     285             : 
     286             :   integer :: im, l, m, nmodes, nspec, ierr
     287             : 
     288             :   logical :: history_amwg                 ! output the variables used by the AMWG diag package
     289             :   logical :: history_eddy                 ! output the eddy variables
     290             :   logical :: history_budget               ! Output tendencies and state variables for CAM4 T, qv, ql, qi
     291             :   integer :: history_budget_histfile_num  ! output history file number for budget fields
     292             :   logical :: history_waccm                ! output variables of interest for WACCM runs
     293             : 
     294             :   !
     295             :   ! add sponge layer vertical diffusion
     296             :   !
     297        1536 :   if (ptop_ref>1e-1_r8.and.ptop_ref<100.0_r8) then
     298             :      !
     299             :      ! CAM7 FMT (but not CAM6 top (~225 Pa) or CAM7 low top or lower)
     300             :      !
     301           0 :      allocate(kvm_sponge(4), stat=ierr)
     302           0 :      if( ierr /= 0 ) then
     303           0 :         write(iulog,*) 'vertical_diffusion_init:  kvm_sponge allocation error = ',ierr
     304           0 :         call endrun('vertical_diffusion_init: failed to allocate kvm_sponge array')
     305             :      end if
     306           0 :      kvm_sponge(1) = 2E6_r8
     307           0 :      kvm_sponge(2) = 2E6_r8
     308           0 :      kvm_sponge(3) = 0.5E6_r8
     309           0 :      kvm_sponge(4) = 0.1E6_r8
     310        1536 :   else if (ptop_ref>1e-4_r8) then
     311             :      !
     312             :      ! WACCM and WACCM-x
     313             :      !
     314        1536 :      allocate(kvm_sponge(6), stat=ierr)
     315        1536 :      if( ierr /= 0 ) then
     316           0 :         write(iulog,*) 'vertical_diffusion_init:  kvm_sponge allocation error = ',ierr
     317           0 :         call endrun('vertical_diffusion_init: failed to allocate kvm_sponge array')
     318             :      end if
     319        1536 :      kvm_sponge(1) = 2E6_r8
     320        1536 :      kvm_sponge(2) = 2E6_r8
     321        1536 :      kvm_sponge(3) = 1.5E6_r8
     322        1536 :      kvm_sponge(4) = 1.0E6_r8
     323        1536 :      kvm_sponge(5) = 0.5E6_r8
     324        1536 :      kvm_sponge(6) = 0.1E6_r8
     325             :   end if
     326             : 
     327        1536 :   if (masterproc) then
     328           2 :      write(iulog,*)'Initializing vertical diffusion (vertical_diffusion_init)'
     329           2 :      if (allocated(kvm_sponge)) then
     330           2 :         write(iulog,*)'Artificial sponge layer vertical diffusion added:'
     331          14 :         do k=1,size(kvm_sponge(:),1)
     332          12 :            write(iulog,'(a44,i2,a17,e7.2,a8)') 'vertical diffusion coefficient at interface',k,' is increased by ', &
     333          26 :                                                 kvm_sponge(k),' m2 s-2'
     334             :         end do
     335             :      end if !allocated
     336             :   end if
     337             : 
     338             :   ! Check to see if WACCM-X is on (currently we don't care whether the
     339             :   ! ionosphere is on or not, since this neutral diffusion code is the
     340             :   ! same either way).
     341        1536 :   waccmx_mode = waccmx_is('ionosphere') .or. waccmx_is('neutral')
     342             : 
     343             :   ! ----------------------------------------------------------------- !
     344             :   ! Get indices of cloud liquid and ice within the constituents array !
     345             :   ! ----------------------------------------------------------------- !
     346             : 
     347        1536 :   call cnst_get_ind( 'CLDLIQ', ixcldliq )
     348        1536 :   call cnst_get_ind( 'CLDICE', ixcldice )
     349             :   ! These are optional; with the CAM4 microphysics, there are no number
     350             :   ! constituents.
     351        1536 :   call cnst_get_ind( 'NUMLIQ', ixnumliq, abort=.false. )
     352        1536 :   call cnst_get_ind( 'NUMICE', ixnumice, abort=.false. )
     353             : 
     354             :   ! Initialize upper boundary condition module
     355             : 
     356        1536 :   call ubc_init()
     357             : 
     358             :   ! ---------------------------------------------------------------------------------------- !
     359             :   ! Initialize molecular diffusivity module                                                  !
     360             :   ! Note that computing molecular diffusivities is a trivial expense, but constituent        !
     361             :   ! diffusivities depend on their molecular weights. Decomposing the diffusion matrix        !
     362             :   ! for each constituent is a needless expense unless the diffusivity is significant.        !
     363             :   ! ---------------------------------------------------------------------------------------- !
     364             : 
     365             :   !----------------------------------------------------------------------------------------
     366             :   ! Initialize molecular diffusion and get top and bottom molecular diffusion limits
     367             :   !----------------------------------------------------------------------------------------
     368             : 
     369        1536 :   if( do_molec_diff ) then
     370             :      call init_molec_diff( r8, pcnst, mwdry, avogad, &
     371           0 :           errstring)
     372             : 
     373           0 :      call handle_errmsg(errstring, subname="init_molec_diff")
     374             : 
     375           0 :      call addfld( 'TTPXMLC', horiz_only, 'A', 'K/S', 'Top interf. temp. flux: molec. viscosity' )
     376           0 :      if( masterproc ) write(iulog,fmt='(a,i3,5x,a,i3)') 'NBOT_MOLEC =', nbot_molec
     377             :   end if
     378             : 
     379             :   ! ---------------------------------- !
     380             :   ! Initialize eddy diffusivity module !
     381             :   ! ---------------------------------- !
     382             : 
     383             :   ! ntop_eddy must be 1 or <= nbot_molec
     384             :   ! Currently, it is always 1 except for WACCM-X.
     385        1536 :   if ( waccmx_mode ) then
     386           0 :      ntop_eddy  = press_lim_idx(ntop_eddy_pres, top=.true.)
     387             :   else
     388        1536 :      ntop_eddy = 1
     389             :   end if
     390        1536 :   nbot_eddy  = pver
     391             : 
     392        1536 :   if (masterproc) write(iulog, fmt='(a,i3,5x,a,i3)') 'NTOP_EDDY  =', ntop_eddy, 'NBOT_EDDY  =', nbot_eddy
     393             : 
     394        1536 :   call phys_getopts(do_hb_above_clubb_out=do_hb_above_clubb)
     395             : 
     396           0 :   select case ( eddy_scheme )
     397             :   case ( 'diag_TKE' )
     398           0 :      if( masterproc ) write(iulog,*) &
     399           0 :           'vertical_diffusion_init: eddy_diffusivity scheme: UW Moist Turbulence Scheme by Bretherton and Park'
     400           0 :      call eddy_diff_init(pbuf2d, ntop_eddy, nbot_eddy)
     401             :   case ( 'HB', 'HBR')
     402           0 :      if( masterproc ) write(iulog,*) 'vertical_diffusion_init: eddy_diffusivity scheme:  Holtslag and Boville'
     403             :      call init_hb_diff(gravit, cpair, ntop_eddy, nbot_eddy, pref_mid, &
     404           0 :           karman, eddy_scheme)
     405           0 :      call addfld('HB_ri',      (/ 'lev' /),  'A', 'no',  'Richardson Number (HB Scheme), I' )
     406             :   case ( 'CLUBB_SGS' )
     407        1536 :      do_pbl_diags = .true.
     408        1536 :      call init_hb_diff(gravit, cpair, ntop_eddy, nbot_eddy, pref_mid, karman, eddy_scheme)
     409             :      !
     410             :      ! run HB scheme where CLUBB is not active when running cam7 or cam6 physics
     411             :      ! else init_hb_diff is called just for diagnostic purposes
     412             :      !
     413        3072 :      if (do_hb_above_clubb) then
     414        1536 :        if( masterproc ) then
     415           2 :          write(iulog,*) 'vertical_diffusion_init: '
     416           2 :          write(iulog,*) 'eddy_diffusivity scheme where CLUBB is not active:  Holtslag and Boville'
     417             :        end if
     418        3072 :        call addfld('HB_ri',      (/ 'lev' /),  'A', 'no',  'Richardson Number (HB Scheme), I' )
     419             :      end if
     420             :   end select
     421             : 
     422             :   ! ------------------------------------------- !
     423             :   ! Initialize turbulent mountain stress module !
     424             :   ! ------------------------------------------- !
     425             : 
     426        1536 :   call trb_mtn_stress_init()
     427             : 
     428             :   ! ----------------------------------- !
     429             :   ! Initialize Beljaars SGO drag module !
     430             :   ! ----------------------------------- !
     431             : 
     432        1536 :   call beljaars_drag_init()
     433             : 
     434             :   ! ---------------------------------- !
     435             :   ! Initialize diffusion solver module !
     436             :   ! ---------------------------------- !
     437             : 
     438        1536 :   call init_vdiff(r8, iulog, rair, cpair, gravit, do_iss, fv_am_correction, errstring)
     439        1536 :   call handle_errmsg(errstring, subname="init_vdiff")
     440             : 
     441             :   ! Use fieldlist_wet to select the fields which will be diffused using moist mixing ratios ( all by default )
     442             :   ! Use fieldlist_dry to select the fields which will be diffused using dry   mixing ratios.
     443             : 
     444        1536 :   fieldlist_wet = new_fieldlist_vdiff( pcnst)
     445        1536 :   fieldlist_dry = new_fieldlist_vdiff( pcnst)
     446        1536 :   fieldlist_molec = new_fieldlist_vdiff( pcnst)
     447             : 
     448        1536 :   if( vdiff_select( fieldlist_wet, 'u' ) .ne. '' ) call endrun( vdiff_select( fieldlist_wet, 'u' ) )
     449        1536 :   if( vdiff_select( fieldlist_wet, 'v' ) .ne. '' ) call endrun( vdiff_select( fieldlist_wet, 'v' ) )
     450        1536 :   if( vdiff_select( fieldlist_wet, 's' ) .ne. '' ) call endrun( vdiff_select( fieldlist_wet, 's' ) )
     451             : 
     452      379392 :   constit_loop: do k = 1, pcnst
     453             : 
     454             :      ! Do not diffuse tracer -- treated in dropmixnuc
     455      377856 :      if (cnst_ndropmixed(k))  cycle constit_loop
     456             : 
     457             :      ! Convert all constituents to wet before doing diffusion.
     458      331776 :      if( vdiff_select( fieldlist_wet, 'q', k ) .ne. '' ) call endrun( vdiff_select( fieldlist_wet, 'q', k ) )
     459             : 
     460             :      ! ----------------------------------------------- !
     461             :      ! Select constituents for molecular diffusion     !
     462             :      ! ----------------------------------------------- !
     463      333312 :      if ( cnst_get_molec_byind(k) .eq. 'minor' ) then
     464      709632 :         if( vdiff_select(fieldlist_molec,'q',k) .ne. '' ) call endrun( vdiff_select( fieldlist_molec,'q',k ) )
     465             :      endif
     466             : 
     467             :   end do constit_loop
     468             : 
     469             :   ! ------------------------ !
     470             :   ! Diagnostic output fields !
     471             :   ! ------------------------ !
     472             : 
     473      379392 :   do k = 1, pcnst
     474      377856 :      vdiffnam(k) = 'VD'//cnst_name(k)
     475      377856 :      if( k == 1 ) vdiffnam(k) = 'VD01'    !**** compatibility with old code ****
     476      757248 :      call addfld( vdiffnam(k), (/ 'lev' /), 'A', 'kg/kg/s', 'Vertical diffusion of '//cnst_name(k) )
     477             :   end do
     478             : 
     479        1536 :   if (.not. do_pbl_diags) then
     480           0 :      call addfld( 'PBLH'        , horiz_only    , 'A', 'm'      , 'PBL height'                                         )
     481           0 :      call addfld( 'QT'          , (/ 'lev' /)   , 'A', 'kg/kg'  , 'Total water mixing ratio'                           )
     482           0 :      call addfld( 'SL'          , (/ 'lev' /)   , 'A', 'J/kg'   , 'Liquid water static energy'                         )
     483           0 :      call addfld( 'SLV'         , (/ 'lev' /)   , 'A', 'J/kg'   , 'Liq wat virtual static energy'                      )
     484           0 :      call addfld( 'SLFLX'       , (/ 'ilev' /)  , 'A', 'W/m2'   , 'Liquid static energy flux'                          )
     485           0 :      call addfld( 'QTFLX'       , (/ 'ilev' /)  , 'A', 'W/m2'   , 'Total water flux'                                   )
     486           0 :      call addfld( 'TKE'         , (/ 'ilev' /)  , 'A', 'm2/s2'  , 'Turbulent Kinetic Energy'                           )
     487           0 :      call addfld( 'TPERT'       , horiz_only    , 'A', 'K'      , 'Perturbation temperature (eddies in PBL)'           )
     488           0 :      call addfld( 'QPERT'       , horiz_only    , 'A', 'kg/kg'  , 'Perturbation specific humidity (eddies in PBL)'     )
     489             : 
     490           0 :      call addfld( 'UFLX'        , (/ 'ilev' /)  , 'A', 'W/m2'   , 'Zonal momentum flux'                                )
     491           0 :      call addfld( 'VFLX'        , (/ 'ilev' /)  , 'A', 'W/m2'   , 'Meridional momentm flux'                            )
     492           0 :      call register_vector_field('UFLX', 'VFLX')
     493             :   end if
     494             : 
     495        1536 :   call addfld( 'USTAR'       , horiz_only    , 'A', 'm/s'    , 'Surface friction velocity'                          )
     496        3072 :   call addfld( 'KVH'         , (/ 'ilev' /)  , 'A', 'm2/s'   , 'Vertical diffusion diffusivities (heat/moisture)'   )
     497        3072 :   call addfld( 'KVM'         , (/ 'ilev' /)  , 'A', 'm2/s'   , 'Vertical diffusion diffusivities (momentum)'        )
     498        3072 :   call addfld( 'KVT'         , (/ 'ilev' /)  , 'A', 'm2/s'   , 'Vertical diffusion kinematic molecular conductivity')
     499        3072 :   call addfld( 'CGS'         , (/ 'ilev' /)  , 'A', 's/m2'   , 'Counter-gradient coeff on surface kinematic fluxes' )
     500        3072 :   call addfld( 'DTVKE'       , (/ 'lev' /)   , 'A', 'K/s'    , 'dT/dt vertical diffusion KE dissipation'            )
     501        3072 :   call addfld( 'DTV'         , (/ 'lev' /)   , 'A', 'K/s'    , 'T vertical diffusion'                               )
     502        3072 :   call addfld( 'DUV'         , (/ 'lev' /)   , 'A', 'm/s2'   , 'U vertical diffusion'                               )
     503        3072 :   call addfld( 'DVV'         , (/ 'lev' /)   , 'A', 'm/s2'   , 'V vertical diffusion'                               )
     504             : 
     505             :   ! ---------------------------------------------------------------------------- !
     506             :   ! Below ( with '_PBL') are for detailed analysis of UW Moist Turbulence Scheme !
     507             :   ! ---------------------------------------------------------------------------- !
     508             : 
     509        1536 :   if (.not. do_pbl_diags) then
     510             : 
     511           0 :      call addfld( 'qt_pre_PBL',   (/ 'lev' /)   , 'A', 'kg/kg'  , 'qt_prePBL'          )
     512           0 :      call addfld( 'sl_pre_PBL',   (/ 'lev' /)   , 'A', 'J/kg'   , 'sl_prePBL'          )
     513           0 :      call addfld( 'slv_pre_PBL',  (/ 'lev' /)   , 'A', 'J/kg'   , 'slv_prePBL'         )
     514           0 :      call addfld( 'u_pre_PBL',    (/ 'lev' /)   , 'A', 'm/s'    , 'u_prePBL'           )
     515           0 :      call addfld( 'v_pre_PBL',    (/ 'lev' /)   , 'A', 'm/s'    , 'v_prePBL'           )
     516           0 :      call addfld( 'qv_pre_PBL',   (/ 'lev' /)   , 'A', 'kg/kg'  , 'qv_prePBL'          )
     517           0 :      call addfld( 'ql_pre_PBL',   (/ 'lev' /)   , 'A', 'kg/kg'  , 'ql_prePBL'          )
     518           0 :      call addfld( 'qi_pre_PBL',   (/ 'lev' /)   , 'A', 'kg/kg'  , 'qi_prePBL'          )
     519           0 :      call addfld( 't_pre_PBL',    (/ 'lev' /)   , 'A', 'K'      , 't_prePBL'           )
     520           0 :      call addfld( 'rh_pre_PBL',   (/ 'lev' /)   , 'A', '%'      , 'rh_prePBL'          )
     521             : 
     522           0 :      call addfld( 'qt_aft_PBL',   (/ 'lev' /)   , 'A', 'kg/kg'  , 'qt_afterPBL'        )
     523           0 :      call addfld( 'sl_aft_PBL',   (/ 'lev' /)   , 'A', 'J/kg'   , 'sl_afterPBL'        )
     524           0 :      call addfld( 'slv_aft_PBL',  (/ 'lev' /)   , 'A', 'J/kg'   , 'slv_afterPBL'       )
     525           0 :      call addfld( 'u_aft_PBL',    (/ 'lev' /)   , 'A', 'm/s'    , 'u_afterPBL'         )
     526           0 :      call addfld( 'v_aft_PBL',    (/ 'lev' /)   , 'A', 'm/s'    , 'v_afterPBL'         )
     527           0 :      call addfld( 'qv_aft_PBL',   (/ 'lev' /)   , 'A', 'kg/kg'  , 'qv_afterPBL'        )
     528           0 :      call addfld( 'ql_aft_PBL',   (/ 'lev' /)   , 'A', 'kg/kg'  , 'ql_afterPBL'        )
     529           0 :      call addfld( 'qi_aft_PBL',   (/ 'lev' /)   , 'A', 'kg/kg'  , 'qi_afterPBL'        )
     530           0 :      call addfld( 't_aft_PBL',    (/ 'lev' /)   , 'A', 'K'      , 't_afterPBL'         )
     531           0 :      call addfld( 'rh_aft_PBL',   (/ 'lev' /)   , 'A', '%'      , 'rh_afterPBL'        )
     532             : 
     533           0 :      call addfld( 'slflx_PBL',    (/ 'ilev' /)  , 'A', 'J/m2/s' , 'sl flux by PBL'     )
     534           0 :      call addfld( 'qtflx_PBL',    (/ 'ilev' /)  , 'A', 'kg/m2/s', 'qt flux by PBL'     )
     535           0 :      call addfld( 'uflx_PBL',     (/ 'ilev' /)  , 'A', 'kg/m/s2', 'u flux by PBL'      )
     536           0 :      call addfld( 'vflx_PBL',     (/ 'ilev' /)  , 'A', 'kg/m/s2', 'v flux by PBL'      )
     537             : 
     538           0 :      call addfld( 'slflx_cg_PBL', (/ 'ilev' /)  , 'A', 'J/m2/s' , 'sl_cg flux by PBL'  )
     539           0 :      call addfld( 'qtflx_cg_PBL', (/ 'ilev' /)  , 'A', 'kg/m2/s', 'qt_cg flux by PBL'  )
     540           0 :      call addfld( 'uflx_cg_PBL',  (/ 'ilev' /)  , 'A', 'kg/m/s2', 'u_cg flux by PBL'   )
     541           0 :      call addfld( 'vflx_cg_PBL',  (/ 'ilev' /)  , 'A', 'kg/m/s2', 'v_cg flux by PBL'   )
     542             : 
     543           0 :      call addfld( 'qtten_PBL',    (/ 'lev' /)   , 'A', 'kg/kg/s', 'qt tendency by PBL' )
     544           0 :      call addfld( 'slten_PBL',    (/ 'lev' /)   , 'A', 'J/kg/s' , 'sl tendency by PBL' )
     545           0 :      call addfld( 'uten_PBL',     (/ 'lev' /)   , 'A', 'm/s2'   , 'u tendency by PBL'  )
     546           0 :      call addfld( 'vten_PBL',     (/ 'lev' /)   , 'A', 'm/s2'   , 'v tendency by PBL'  )
     547           0 :      call addfld( 'qvten_PBL',    (/ 'lev' /)   , 'A', 'kg/kg/s', 'qv tendency by PBL' )
     548           0 :      call addfld( 'qlten_PBL',    (/ 'lev' /)   , 'A', 'kg/kg/s', 'ql tendency by PBL' )
     549           0 :      call addfld( 'qiten_PBL',    (/ 'lev' /)   , 'A', 'kg/kg/s', 'qi tendency by PBL' )
     550           0 :      call addfld( 'tten_PBL',     (/ 'lev' /)   , 'A', 'K/s'    , 'T tendency by PBL'  )
     551           0 :      call addfld( 'rhten_PBL',    (/ 'lev' /)   , 'A', '%/s'    , 'RH tendency by PBL' )
     552             : 
     553             :   end if
     554             : 
     555        1536 :   call addfld ('ustar',horiz_only, 'A',     ' ',' ')
     556        1536 :   call addfld ('obklen',horiz_only, 'A',    ' ',' ')
     557             : 
     558             :   ! ----------------------------
     559             :   ! determine default variables
     560             :   ! ----------------------------
     561             : 
     562             :   call phys_getopts( history_amwg_out = history_amwg, &
     563             :        history_eddy_out = history_eddy, &
     564             :        history_budget_out = history_budget, &
     565             :        history_budget_histfile_num_out = history_budget_histfile_num, &
     566        1536 :        history_waccm_out = history_waccm)
     567             : 
     568        1536 :   if (history_amwg) then
     569        1536 :      call add_default(  vdiffnam(1), 1, ' ' )
     570        1536 :      call add_default( 'DTV'       , 1, ' ' )
     571        1536 :      if (.not. do_pbl_diags) then
     572           0 :         call add_default( 'PBLH'      , 1, ' ' )
     573             :      end if
     574             :   endif
     575             : 
     576        1536 :   if (history_eddy) then
     577           0 :      if (.not. do_pbl_diags) then
     578           0 :         call add_default( 'UFLX    ', 1, ' ' )
     579           0 :         call add_default( 'VFLX    ', 1, ' ' )
     580             :      end if
     581             :   endif
     582             : 
     583        1536 :   if( history_budget ) then
     584           0 :      call add_default( vdiffnam(ixcldliq), history_budget_histfile_num, ' ' )
     585           0 :      call add_default( vdiffnam(ixcldice), history_budget_histfile_num, ' ' )
     586           0 :      if( history_budget_histfile_num > 1 ) then
     587           0 :         call add_default(  vdiffnam(1), history_budget_histfile_num, ' ' )
     588           0 :         call add_default( 'DTV'       , history_budget_histfile_num, ' ' )
     589             :      end if
     590             :   end if
     591             : 
     592        1536 :   if ( history_waccm ) then
     593           0 :      if (do_molec_diff) then
     594           0 :         call add_default ( 'TTPXMLC', 1, ' ' )
     595             :      end if
     596           0 :      call add_default( 'DUV'     , 1, ' ' )
     597           0 :      call add_default( 'DVV'     , 1, ' ' )
     598             :   end if
     599             :   ! ----------------------------
     600             : 
     601             : 
     602        1536 :   ksrftms_idx = pbuf_get_index('ksrftms')
     603        1536 :   tautmsx_idx = pbuf_get_index('tautmsx')
     604        1536 :   tautmsy_idx = pbuf_get_index('tautmsy')
     605             : 
     606        1536 :   dragblj_idx = pbuf_get_index('dragblj')
     607        1536 :   taubljx_idx = pbuf_get_index('taubljx')
     608        1536 :   taubljy_idx = pbuf_get_index('taubljy')
     609             : 
     610        1536 :   if (eddy_scheme == 'CLUBB_SGS') then
     611        1536 :      kvh_idx = pbuf_get_index('kvh')
     612             :   end if
     613             : 
     614        1536 :   if (do_hb_above_clubb) then
     615             :      ! pbuf field denoting top of clubb
     616        1536 :      clubbtop_idx = pbuf_get_index('clubbtop')
     617             :   end if
     618             : 
     619             :   ! Initialization of some pbuf fields
     620        1536 :   if (is_first_step()) then
     621             :      ! Initialization of pbuf fields tke, kvh, kvm are done in phys_inidat
     622         768 :      call pbuf_set_field(pbuf2d, tauresx_idx,  0.0_r8)
     623         768 :      call pbuf_set_field(pbuf2d, tauresy_idx,  0.0_r8)
     624         768 :      if (trim(shallow_scheme) == 'UNICON') then
     625           0 :         call pbuf_set_field(pbuf2d, qtl_flx_idx,  0.0_r8)
     626           0 :         call pbuf_set_field(pbuf2d, qti_flx_idx,  0.0_r8)
     627             :      end if
     628             :   end if
     629        1536 : end subroutine vertical_diffusion_init
     630             : 
     631             : ! =============================================================================== !
     632             : !                                                                                 !
     633             : ! =============================================================================== !
     634             : 
     635       32256 : subroutine vertical_diffusion_ts_init( pbuf2d, state )
     636             : 
     637             :   !-------------------------------------------------------------- !
     638             :   ! Timestep dependent setting,                                   !
     639             :   ! At present only invokes upper bc code                         !
     640             :   !-------------------------------------------------------------- !
     641        1536 :   use upper_bc,       only : ubc_timestep_init
     642             :   use physics_types , only : physics_state
     643             :   use ppgrid        , only : begchunk, endchunk
     644             : 
     645             :   use physics_buffer, only : physics_buffer_desc
     646             : 
     647             :   type(physics_state), intent(in) :: state(begchunk:endchunk)
     648             :   type(physics_buffer_desc), pointer :: pbuf2d(:,:)
     649             : 
     650       16128 :   call ubc_timestep_init( pbuf2d, state)
     651             : 
     652       16128 : end subroutine vertical_diffusion_ts_init
     653             : 
     654             : ! =============================================================================== !
     655             : !                                                                                 !
     656             : ! =============================================================================== !
     657             : 
     658    18021120 : subroutine vertical_diffusion_tend( &
     659             :      ztodt    , state    , cam_in,          &
     660             :      ustar    , obklen   , ptend    , &
     661             :      cldn     , pbuf)
     662             :   !---------------------------------------------------- !
     663             :   ! This is an interface routine for vertical diffusion !
     664             :   !---------------------------------------------------- !
     665       16128 :   use physics_buffer,     only : physics_buffer_desc, pbuf_get_field, pbuf_set_field
     666             :   use physics_types,      only : physics_state, physics_ptend, physics_ptend_init
     667             : 
     668             :   use camsrfexch,           only : cam_in_t
     669             :   use cam_history,          only : outfld
     670             : 
     671             :   use trb_mtn_stress_cam,   only : trb_mtn_stress_tend
     672             :   use beljaars_drag_cam,    only : beljaars_drag_tend
     673             :   use eddy_diff_cam,        only : eddy_diff_tend
     674             :   use hb_diff,              only : compute_hb_diff, compute_hb_free_atm_diff
     675             :   use wv_saturation,        only : qsat
     676             :   use molec_diff,           only : compute_molec_diff, vd_lu_qdecomp
     677             :   use constituents,         only : qmincg, qmin, cnst_type
     678             :   use diffusion_solver,     only : compute_vdiff, any, operator(.not.)
     679             :   use air_composition,      only : cpairv, rairv !Needed for calculation of upward H flux
     680             :   use time_manager,         only : get_nstep
     681             :   use constituents,         only : cnst_get_type_byind, cnst_name, &
     682             :                                    cnst_mw, cnst_fixed_ubc, cnst_fixed_ubflx, cnst_ndropmixed
     683             :   use physconst,            only : pi
     684             :   use atmos_phys_pbl_utils, only: calc_virtual_temperature, calc_ideal_gas_rrho, calc_friction_velocity,                             &
     685             :                                   calc_kinematic_heat_flux, calc_kinematic_water_vapor_flux, calc_kinematic_buoyancy_flux, &
     686             :                                   calc_obukhov_length
     687             :   use upper_bc,             only : ubc_get_vals, ubc_fixed_temp
     688             :   use upper_bc,             only : ubc_get_flxs
     689             :   use coords_1d,            only : Coords1D
     690             :   use phys_control,         only : cam_physpkg_is
     691             :   use ref_pres,             only : ptop_ref
     692             : 
     693             :   ! --------------- !
     694             :   ! Input Arguments !
     695             :   ! --------------- !
     696             : 
     697             :   type(physics_state), intent(inout) :: state                     ! Physics state variables
     698             :   type(cam_in_t),      intent(in)    :: cam_in                    ! Surface inputs
     699             : 
     700             :   real(r8),            intent(in)    :: ztodt                     ! 2 delta-t [ s ]
     701             :   real(r8),            intent(in)    :: cldn(pcols,pver)          ! New stratus fraction [ fraction ]
     702             : 
     703             :   ! ---------------------- !
     704             :   ! Input-Output Arguments !
     705             :   ! ---------------------- !
     706             : 
     707             :   type(physics_ptend), intent(out) :: ptend                       ! Individual parameterization tendencies
     708             :   type(physics_buffer_desc), pointer :: pbuf(:)
     709             : 
     710             :   ! ---------------- !
     711             :   ! Output Arguments !
     712             :   ! ---------------- !
     713             : 
     714             :   real(r8),            intent(out)   :: ustar(pcols)              ! Surface friction velocity [ m/s ]
     715             :   real(r8),            intent(out)   :: obklen(pcols)             ! Obukhov length [ m ]
     716             : 
     717             :   ! --------------- !
     718             :   ! Local Variables !
     719             :   ! --------------- !
     720             : 
     721             :   character(128) :: errstring                                     ! Error status for compute_vdiff
     722             : 
     723             :   integer  :: lchnk                                               ! Chunk identifier
     724             :   integer  :: ncol                                                ! Number of atmospheric columns
     725             :   integer  :: i, k, l, m                                          ! column, level, constituent indices
     726             : 
     727             :   real(r8) :: dtk(pcols,pver)                                     ! T tendency from KE dissipation
     728       72960 :   real(r8), pointer   :: tke(:,:)                                 ! Turbulent kinetic energy [ m2/s2 ]
     729             : 
     730       72960 :   real(r8), pointer   :: qtl_flx(:,:)                             ! overbar(w'qtl') where qtl = qv + ql
     731       72960 :   real(r8), pointer   :: qti_flx(:,:)                             ! overbar(w'qti') where qti = qv + qi
     732             : 
     733             :   real(r8) :: cgs(pcols,pverp)                                    ! Counter-gradient star  [ cg/flux ]
     734             :   real(r8) :: cgh(pcols,pverp)                                    ! Counter-gradient term for heat
     735             :   real(r8) :: rztodt                                              ! 1./ztodt [ 1/s ]
     736       72960 :   real(r8), pointer :: ksrftms(:)                                 ! Turbulent mountain stress surface drag coefficient [ kg/s/m2 ]
     737       72960 :   real(r8), pointer :: tautmsx(:)                                 ! U component of turbulent mountain stress [ N/m2 ]
     738       72960 :   real(r8), pointer :: tautmsy(:)                                 ! V component of turbulent mountain stress [ N/m2 ]
     739             :   real(r8) :: tautotx(pcols)                                      ! U component of total surface stress [ N/m2 ]
     740             :   real(r8) :: tautoty(pcols)                                      ! V component of total surface stress [ N/m2 ]
     741             : 
     742       72960 :   real(r8), pointer :: dragblj(:,:)                               ! Beljaars SGO form drag profile [ 1/s ]
     743       72960 :   real(r8), pointer :: taubljx(:)                                 ! U component of turbulent mountain stress [ N/m2 ]
     744       72960 :   real(r8), pointer :: taubljy(:)                                 ! V component of turbulent mountain stress [ N/m2 ]
     745             : 
     746       72960 :   real(r8), pointer :: kvh_in(:,:)                                ! kvh from previous timestep [ m2/s ]
     747       72960 :   real(r8), pointer :: kvm_in(:,:)                                ! kvm from previous timestep [ m2/s ]
     748       72960 :   real(r8), pointer :: kvt(:,:)                                   ! Molecular kinematic conductivity for temperature [  ]
     749             :   real(r8) :: kvq(pcols,pverp)                                    ! Eddy diffusivity for constituents [ m2/s ]
     750             :   real(r8) :: kvh(pcols,pverp)                                    ! Eddy diffusivity for heat [ m2/s ]
     751             :   real(r8) :: kvm(pcols,pverp)                                    ! Eddy diffusivity for momentum [ m2/s ]
     752             :   real(r8) :: kvm_temp(pcols,pverp)                               ! Dummy eddy diffusivity for momentum (unused) [ m2/s ]
     753             :   real(r8) :: dtk_temp(pcols,pverp)                               ! Unused output from second compute_vdiff call
     754             :   real(r8) :: tautmsx_temp(pcols)                                 ! Unused output from second compute_vdiff call
     755             :   real(r8) :: tautmsy_temp(pcols)                                 ! Unused output from second compute_vdiff call
     756             :   real(r8) :: topflx_temp(pcols)                                  ! Unused output from second compute_vdiff call
     757             :   real(r8) :: sprod(pcols,pverp)                                  ! Shear production of tke [ m2/s3 ]
     758             :   real(r8) :: sfi(pcols,pverp)                                    ! Saturation fraction at interfaces [ fraction ]
     759             :   real(r8) :: sl(pcols,pver)
     760             :   real(r8) :: qt(pcols,pver)
     761             :   real(r8) :: slv(pcols,pver)
     762             :   real(r8) :: sl_prePBL(pcols,pver)
     763             :   real(r8) :: qt_prePBL(pcols,pver)
     764             :   real(r8) :: slv_prePBL(pcols,pver)
     765             :   real(r8) :: slten(pcols,pver)
     766             :   real(r8) :: qtten(pcols,pver)
     767             :   real(r8) :: slflx(pcols,pverp)
     768             :   real(r8) :: qtflx(pcols,pverp)
     769             :   real(r8) :: uflx(pcols,pverp)
     770             :   real(r8) :: vflx(pcols,pverp)
     771             :   real(r8) :: slflx_cg(pcols,pverp)
     772             :   real(r8) :: qtflx_cg(pcols,pverp)
     773             :   real(r8) :: uflx_cg(pcols,pverp)
     774             :   real(r8) :: vflx_cg(pcols,pverp)
     775             :   real(r8) :: th(pcols,pver)                                      ! Potential temperature
     776             :   real(r8) :: topflx(pcols)                                       ! Molecular heat flux at top interface
     777             :   real(r8) :: rhoair
     778             : 
     779             :   real(r8) :: ri(pcols,pver)                                      ! richardson number (HB output)
     780             : 
     781             :   ! for obklen calculation outside HB
     782             :   real(r8) :: thvs(pcols)                                         ! Virtual potential temperature at surface
     783             :   real(r8) :: rrho(pcols)                                         ! Reciprocal of density at surface
     784             :   real(r8) :: khfs(pcols)                                         ! sfc kinematic heat flux [mK/s]
     785             :   real(r8) :: kqfs(pcols)                                         ! sfc kinematic water vapor flux [m/s]
     786             :   real(r8) :: kbfs(pcols)                                         ! sfc kinematic buoyancy flux [m^2/s^3]
     787             : 
     788             :   real(r8) :: ftem(pcols,pver)                                    ! Saturation vapor pressure before PBL
     789             :   real(r8) :: ftem_prePBL(pcols,pver)                             ! Saturation vapor pressure before PBL
     790             :   real(r8) :: ftem_aftPBL(pcols,pver)                             ! Saturation vapor pressure after PBL
     791             :   real(r8) :: tem2(pcols,pver)                                    ! Saturation specific humidity and RH
     792             :   real(r8) :: t_aftPBL(pcols,pver)                                ! Temperature after PBL diffusion
     793             :   real(r8) :: tten(pcols,pver)                                    ! Temperature tendency by PBL diffusion
     794             :   real(r8) :: rhten(pcols,pver)                                   ! RH tendency by PBL diffusion
     795             :   real(r8) :: qv_aft_PBL(pcols,pver)                              ! qv after PBL diffusion
     796             :   real(r8) :: ql_aft_PBL(pcols,pver)                              ! ql after PBL diffusion
     797             :   real(r8) :: qi_aft_PBL(pcols,pver)                              ! qi after PBL diffusion
     798             :   real(r8) :: s_aft_PBL(pcols,pver)                               ! s after PBL diffusion
     799             :   real(r8) :: u_aft_PBL(pcols,pver)                               ! u after PBL diffusion
     800             :   real(r8) :: v_aft_PBL(pcols,pver)                               ! v after PBL diffusion
     801             :   real(r8) :: qv_pro(pcols,pver)
     802             :   real(r8) :: ql_pro(pcols,pver)
     803             :   real(r8) :: qi_pro(pcols,pver)
     804             :   real(r8) :: s_pro(pcols,pver)
     805             :   real(r8) :: t_pro(pcols,pver)
     806       72960 :   real(r8), pointer :: tauresx(:)                                      ! Residual stress to be added in vdiff to correct
     807       72960 :   real(r8), pointer :: tauresy(:)                                      ! for turb stress mismatch between sfc and atm accumulated.
     808             : 
     809             :   ! Interpolated interface values.
     810             :   real(r8) :: tint(pcols,pver+1)      ! Temperature [ K ]
     811             :   real(r8) :: rairi(pcols,pver+1)     ! Gas constant [ J/K/kg ]
     812             :   real(r8) :: rhoi(pcols,pver+1)      ! Density of air [ kg/m^3 ]
     813             :   real(r8) :: rhoi_dry(pcols,pver+1)  ! Density of air based on dry air pressure [ kg/m^3 ]
     814             : 
     815             :   ! Upper boundary conditions
     816             :   real(r8) :: ubc_t(pcols)            ! Temperature [ K ]
     817             :   real(r8) :: ubc_mmr(pcols,pcnst)    ! Mixing ratios [ kg/kg ]
     818             :   real(r8) :: ubc_flux(pcols,pcnst)   ! Constituent upper boundary flux (kg/s/m^2)
     819             : 
     820             :   ! Pressure coordinates used by the solver.
     821       72960 :   type(Coords1D) :: p
     822       72960 :   type(Coords1D) :: p_dry
     823             : 
     824       72960 :   real(r8), pointer :: tpert(:)
     825       72960 :   real(r8), pointer :: qpert(:)
     826       72960 :   real(r8), pointer :: pblh(:)
     827             : 
     828             :   real(r8) :: tmp1(pcols)                                         ! Temporary storage
     829             : 
     830             :   integer  :: nstep
     831             :   real(r8) :: sum1, sum2, sum3, pdelx
     832             :   real(r8) :: sflx
     833             : 
     834             :   ! Copy state so we can pass to intent(inout) routines that return
     835             :   ! new state instead of a tendency.
     836             :   real(r8) :: s_tmp(pcols,pver)
     837             :   real(r8) :: u_tmp(pcols,pver)
     838             :   real(r8) :: v_tmp(pcols,pver)
     839             :   real(r8) :: q_tmp(pcols,pver,pcnst)
     840             : 
     841             :   ! kq_fac*sqrt(T)*m_d/rho for molecular diffusivity
     842             :   real(r8) :: kq_scal(pcols,pver+1)
     843             :   ! composition dependent mw_fac on interface level
     844             :   real(r8) :: mw_fac(pcols,pver+1,pcnst)
     845             : 
     846             :   ! Dry static energy top boundary condition.
     847             :   real(r8) :: dse_top(pcols)
     848             : 
     849             :   ! Copies of flux arrays used to zero out any parts that are applied
     850             :   ! elsewhere (e.g. by CLUBB).
     851             :   real(r8) :: taux(pcols)
     852             :   real(r8) :: tauy(pcols)
     853             :   real(r8) :: shflux(pcols)
     854             :   real(r8) :: cflux(pcols,pcnst)
     855       72960 :   integer,  pointer :: clubbtop(:)   ! (pcols)
     856             : 
     857             :   logical  :: lq(pcnst)
     858             : 
     859             :   ! ----------------------- !
     860             :   ! Main Computation Begins !
     861             :   ! ----------------------- !
     862             : 
     863       72960 :   rztodt = 1._r8 / ztodt
     864       72960 :   lchnk  = state%lchnk
     865       72960 :   ncol   = state%ncol
     866             : 
     867       72960 :   call pbuf_get_field(pbuf, tauresx_idx,  tauresx)
     868       72960 :   call pbuf_get_field(pbuf, tauresy_idx,  tauresy)
     869       72960 :   call pbuf_get_field(pbuf, tpert_idx,    tpert)
     870       72960 :   call pbuf_get_field(pbuf, qpert_idx,    qpert)
     871       72960 :   call pbuf_get_field(pbuf, pblh_idx,     pblh)
     872             : 
     873             :   ! Interpolate temperature to interfaces.
     874     4085760 :   do k = 2, pver
     875    61870080 :      do i = 1, ncol
     876    61797120 :         tint(i,k)  = 0.5_r8 * ( state%t(i,k) + state%t(i,k-1) )
     877             :      end do
     878             :   end do
     879     1123584 :   tint(:ncol,pver+1) = state%t(:ncol,pver)
     880             : 
     881             :   ! Get upper boundary values
     882       72960 :   call ubc_get_vals( state%lchnk, ncol, state%pint, state%zi, ubc_t, ubc_mmr )
     883             : 
     884       72960 :   if (waccmx_mode) then
     885           0 :      call ubc_get_flxs( state%lchnk, ncol, state%pint, state%zi, state%t, state%q, state%phis, ubc_flux )
     886             :      ! For WACCM-X, set ubc temperature to extrapolate from next two lower interface level temperatures
     887           0 :      tint(:ncol,1) = 1.5_r8*tint(:ncol,2)-.5_r8*tint(:ncol,3)
     888       72960 :   else if(ubc_fixed_temp) then
     889           0 :      tint(:ncol,1) = ubc_t(:ncol)
     890             :   else
     891     1123584 :      tint(:ncol,1) = state%t(:ncol,1)
     892             :   end if
     893             : 
     894             :   ! Set up pressure coordinates for solver calls.
     895       72960 :   p = Coords1D(state%pint(:ncol,:))
     896       72960 :   p_dry = Coords1D(state%pintdry(:ncol,:))
     897             : 
     898             :   !------------------------------------------------------------------------
     899             :   !  Check to see if constituent dependent gas constant needed (WACCM-X)
     900             :   !------------------------------------------------------------------------
     901       72960 :   if (waccmx_mode) then
     902           0 :      rairi(:ncol,1) = rairv(:ncol,1,lchnk)
     903           0 :      do k = 2, pver
     904           0 :         do i = 1, ncol
     905           0 :            rairi(i,k) = 0.5_r8 * (rairv(i,k,lchnk)+rairv(i,k-1,lchnk))
     906             :         end do
     907             :      end do
     908           0 :      rairi(:ncol,pver+1) = rairv(:ncol,pver,lchnk)
     909             :   else
     910    64117248 :      rairi(:ncol,:pver+1) = rair
     911             :   endif
     912             : 
     913             :   ! Compute rho at interfaces.
     914     4231680 :   do k = 1, pver+1
     915    64117248 :      do i = 1, ncol
     916    64044288 :         rhoi(i,k)  = p%ifc(i,k) / (rairi(i,k)*tint(i,k))
     917             :      end do
     918             :   end do
     919             : 
     920             :   ! Compute rho_dry at interfaces.
     921     4231680 :   do k = 1, pver+1
     922    64117248 :      do i = 1, ncol
     923    64044288 :         rhoi_dry(i,k)  = p_dry%ifc(i,k) / (rairi(i,k)*tint(i,k))
     924             :      end do
     925             :   end do
     926             : 
     927             :   ! ---------------------------------------- !
     928             :   ! Computation of turbulent mountain stress !
     929             :   ! ---------------------------------------- !
     930             : 
     931             :   ! Consistent with the computation of 'normal' drag coefficient, we are using
     932             :   ! the raw input (u,v) to compute 'ksrftms', not the provisionally-marched 'u,v'
     933             :   ! within the iteration loop of the PBL scheme.
     934             : 
     935       72960 :   call trb_mtn_stress_tend(state, pbuf, cam_in)
     936             : 
     937       72960 :   call pbuf_get_field(pbuf, ksrftms_idx, ksrftms)
     938       72960 :   call pbuf_get_field(pbuf, tautmsx_idx, tautmsx)
     939       72960 :   call pbuf_get_field(pbuf, tautmsy_idx, tautmsy)
     940             : 
     941     1123584 :   tautotx(:ncol) = cam_in%wsx(:ncol) + tautmsx(:ncol)
     942     1123584 :   tautoty(:ncol) = cam_in%wsy(:ncol) + tautmsy(:ncol)
     943             : 
     944             :   ! ------------------------------------- !
     945             :   ! Computation of Beljaars SGO form drag !
     946             :   ! ------------------------------------- !
     947             : 
     948       72960 :   call beljaars_drag_tend(state, pbuf, cam_in)
     949             : 
     950       72960 :   call pbuf_get_field(pbuf, dragblj_idx, dragblj)
     951       72960 :   call pbuf_get_field(pbuf, taubljx_idx, taubljx)
     952       72960 :   call pbuf_get_field(pbuf, taubljy_idx, taubljy)
     953             : 
     954             :   ! Add Beljaars integrated drag
     955             : 
     956     1123584 :   tautotx(:ncol) = tautotx(:ncol) + taubljx(:ncol)
     957     1123584 :   tautoty(:ncol) = tautoty(:ncol) + taubljy(:ncol)
     958             : 
     959             :   !----------------------------------------------------------------------- !
     960             :   !   Computation of eddy diffusivities - Select appropriate PBL scheme    !
     961             :   !----------------------------------------------------------------------- !
     962       72960 :   call pbuf_get_field(pbuf, kvm_idx,  kvm_in)
     963       72960 :   call pbuf_get_field(pbuf, kvh_idx,  kvh_in)
     964       72960 :   call pbuf_get_field(pbuf, tke_idx,  tke)
     965             : 
     966             :   ! Get potential temperature.
     967    62993664 :   th(:ncol,:pver) = state%t(:ncol,:pver) * state%exner(:ncol,:pver)
     968             : 
     969           0 :   select case (eddy_scheme)
     970             :   case ( 'diag_TKE' )
     971             : 
     972             :      call eddy_diff_tend(state, pbuf, cam_in, &
     973             :           ztodt, p, tint, rhoi, cldn, wstarent, &
     974             :           kvm_in, kvh_in, ksrftms, dragblj, tauresx, tauresy, &
     975             :           rrho, ustar, pblh, kvm, kvh, kvq, cgh, cgs, tpert, qpert, &
     976           0 :           tke, sprod, sfi)
     977             : 
     978             :      ! The diag_TKE scheme does not calculate the Monin-Obukhov length, which is used in dry deposition calculations.
     979             :      ! Use the routines from pbl_utils to accomplish this. Assumes ustar and rrho have been set.
     980           0 :       thvs  (:ncol) = calc_virtual_temperature(th(:ncol,pver), state%q(:ncol,pver,1), zvir)
     981             : 
     982           0 :       khfs  (:ncol) = calc_kinematic_heat_flux(cam_in%shf(:ncol), rrho(:ncol), cpair)
     983           0 :       kqfs  (:ncol) = calc_kinematic_water_vapor_flux(cam_in%cflx(:ncol,1), rrho(:ncol))
     984           0 :       kbfs  (:ncol) = calc_kinematic_buoyancy_flux(khfs(:ncol), zvir, th(:ncol,pver), kqfs(:ncol))
     985           0 :       obklen(:ncol) = calc_obukhov_length(thvs(:ncol), ustar(:ncol), gravit, karman, kbfs(:ncol))
     986             : 
     987             :   case ( 'HB', 'HBR' )
     988             : 
     989             :      ! Modification : We may need to use 'taux' instead of 'tautotx' here, for
     990             :      !                consistency with the previous HB scheme.
     991             : 
     992             : 
     993             :      call compute_hb_diff(ncol                                    , &
     994             :           th        , state%t  , state%q , state%zm , state%zi    , &
     995             :           state%pmid, state%u  , state%v , tautotx  , tautoty     , &
     996             :           cam_in%shf, cam_in%cflx(:,1), obklen  , ustar    , pblh , &
     997             :           kvm       , kvh      , kvq     , cgh      , cgs         , &
     998             :           tpert     , qpert    , cldn    , cam_in%ocnfrac  , tke  , &
     999             :           ri        , &
    1000           0 :           eddy_scheme)
    1001             : 
    1002           0 :      call outfld( 'HB_ri',          ri,         pcols,   lchnk )
    1003             : 
    1004             :   case ( 'CLUBB_SGS' )
    1005             :     !
    1006             :     ! run HB scheme where CLUBB is not active when running cam7
    1007             :     !
    1008       72960 :     if (do_hb_above_clubb) then
    1009             :       call compute_hb_free_atm_diff( ncol          , &
    1010             :            th        , state%t  , state%q , state%zm           , &
    1011             :            state%pmid, state%u  , state%v , tautotx  , tautoty , &
    1012             :            cam_in%shf, cam_in%cflx(:,1), obklen  , ustar       , &
    1013             :            kvm       , kvh      , kvq     , cgh      , cgs     , &
    1014       72960 :            ri        )
    1015             : 
    1016       72960 :       call pbuf_get_field(pbuf, clubbtop_idx, clubbtop)
    1017             :       !
    1018             :       ! zero out HB where CLUBB is active
    1019             :       !
    1020     1123584 :       do i=1,ncol
    1021    31160705 :         do k=clubbtop(i),pverp
    1022    30037121 :           kvm(i,k) = 0.0_r8
    1023    30037121 :           kvh(i,k) = 0.0_r8
    1024    30037121 :           kvq(i,k) = 0.0_r8
    1025    30037121 :           cgs(i,k) = 0.0_r8
    1026    31087745 :           cgh(i,k) = 0.0_r8
    1027             :         end do
    1028             :       end do
    1029             : 
    1030       72960 :       call outfld( 'HB_ri',          ri,         pcols,   lchnk )
    1031             :     else
    1032             :       ! CLUBB has only a bare-bones placeholder here. If using CLUBB, the
    1033             :       ! PBL diffusion will happen before coupling, so vertical_diffusion
    1034             :       ! is only handling other things, e.g. some boundary conditions, tms,
    1035             :       ! and molecular diffusion.
    1036             : 
    1037           0 :       thvs  (:ncol) = calc_virtual_temperature(th(:ncol,pver), state%q(:ncol,pver,1), zvir)
    1038           0 :       rrho  (:ncol) = calc_ideal_gas_rrho(rair, state%t(:ncol,pver), state%pmid(:ncol,pver))
    1039           0 :       ustar (:ncol) = calc_friction_velocity(cam_in%wsx(:ncol), cam_in%wsy(:ncol), rrho(:ncol))
    1040           0 :       khfs  (:ncol) = calc_kinematic_heat_flux(cam_in%shf(:ncol), rrho(:ncol), cpair)
    1041           0 :       kqfs  (:ncol) = calc_kinematic_water_vapor_flux(cam_in%cflx(:ncol,1), rrho(:ncol))
    1042           0 :       kbfs  (:ncol) = calc_kinematic_buoyancy_flux(khfs(:ncol), zvir, th(:ncol,pver), kqfs(:ncol))
    1043           0 :       obklen(:ncol) = calc_obukhov_length(thvs(:ncol), ustar(:ncol), gravit, karman, kbfs(:ncol))
    1044             : 
    1045             :       ! These tendencies all applied elsewhere.
    1046           0 :       kvm = 0._r8
    1047           0 :       kvh = 0._r8
    1048           0 :       kvq = 0._r8
    1049             :       ! Not defined since PBL is not actually running here.
    1050           0 :       cgh = 0._r8
    1051           0 :       cgs = 0._r8
    1052             :     end if
    1053             :   end select
    1054             : 
    1055       72960 :   call outfld( 'ustar',   ustar(:), pcols, lchnk )
    1056       72960 :   call outfld( 'obklen', obklen(:), pcols, lchnk )
    1057             :   !
    1058             :   ! add sponge layer vertical diffusion
    1059             :   !
    1060       72960 :   if (allocated(kvm_sponge)) then
    1061      510720 :      do k=1,size(kvm_sponge(:),1)
    1062     6814464 :         kvm(:ncol,1) = kvm(:ncol,1)+kvm_sponge(k)
    1063             :      end do
    1064             :   end if
    1065             : 
    1066             :   ! kvh (in pbuf) is used by other physics parameterizations, and as an initial guess in compute_eddy_diff
    1067             :   ! on the next timestep.  It is not updated by the compute_vdiff call below.
    1068       72960 :   call pbuf_set_field(pbuf, kvh_idx, kvh)
    1069             : 
    1070             :   ! kvm (in pbuf) is only used as an initial guess in compute_eddy_diff on the next timestep.
    1071             :   ! The contributions for molecular diffusion made to kvm by the call to compute_vdiff below
    1072             :   ! are not included in the pbuf as these are not needed in the initial guess by compute_eddy_diff.
    1073       72960 :   call pbuf_set_field(pbuf, kvm_idx, kvm)
    1074             : 
    1075             :   !------------------------------------ !
    1076             :   !    Application of diffusivities     !
    1077             :   !------------------------------------ !
    1078             : 
    1079             :   ! Set arrays from input state.
    1080 15496514304 :   q_tmp(:ncol,:,:) = state%q(:ncol,:,:)
    1081    62993664 :   s_tmp(:ncol,:) = state%s(:ncol,:)
    1082    62993664 :   u_tmp(:ncol,:) = state%u(:ncol,:)
    1083    62993664 :   v_tmp(:ncol,:) = state%v(:ncol,:)
    1084             : 
    1085             :   !------------------------------------------------------ !
    1086             :   ! Write profile output before applying diffusion scheme !
    1087             :   !------------------------------------------------------ !
    1088             : 
    1089       72960 :   if (.not. do_pbl_diags) then
    1090           0 :      sl_prePBL(:ncol,:pver)  = s_tmp(:ncol,:) -   latvap * q_tmp(:ncol,:,ixcldliq) &
    1091           0 :           - ( latvap + latice) * q_tmp(:ncol,:,ixcldice)
    1092             :      qt_prePBL(:ncol,:pver)  = q_tmp(:ncol,:,1) + q_tmp(:ncol,:,ixcldliq) &
    1093           0 :           + q_tmp(:ncol,:,ixcldice)
    1094           0 :      slv_prePBL(:ncol,:pver) = sl_prePBL(:ncol,:pver) * ( 1._r8 + zvir*qt_prePBL(:ncol,:pver) )
    1095             : 
    1096           0 :      do k = 1, pver
    1097           0 :         call qsat(state%t(1:ncol,k), state%pmid(1:ncol,k), tem2(1:ncol,k), ftem(1:ncol,k), ncol)
    1098             :      end do
    1099           0 :      ftem_prePBL(:ncol,:) = state%q(:ncol,:,1)/ftem(:ncol,:)*100._r8
    1100             : 
    1101           0 :      call outfld( 'qt_pre_PBL   ', qt_prePBL,                 pcols, lchnk )
    1102           0 :      call outfld( 'sl_pre_PBL   ', sl_prePBL,                 pcols, lchnk )
    1103           0 :      call outfld( 'slv_pre_PBL  ', slv_prePBL,                pcols, lchnk )
    1104           0 :      call outfld( 'u_pre_PBL    ', state%u,                   pcols, lchnk )
    1105           0 :      call outfld( 'v_pre_PBL    ', state%v,                   pcols, lchnk )
    1106           0 :      call outfld( 'qv_pre_PBL   ', state%q(:,:,1),            pcols, lchnk )
    1107           0 :      call outfld( 'ql_pre_PBL   ', state%q(:,:,ixcldliq),     pcols, lchnk )
    1108           0 :      call outfld( 'qi_pre_PBL   ', state%q(:,:,ixcldice),     pcols, lchnk )
    1109           0 :      call outfld( 't_pre_PBL    ', state%t,                   pcols, lchnk )
    1110           0 :      call outfld( 'rh_pre_PBL   ', ftem_prePBL,               pcols, lchnk )
    1111             : 
    1112             :   end if
    1113             : 
    1114             :   ! --------------------------------------------------------------------------------- !
    1115             :   ! Call the diffusivity solver and solve diffusion equation                          !
    1116             :   ! The final two arguments are optional function references to                       !
    1117             :   ! constituent-independent and constituent-dependent moleculuar diffusivity routines !
    1118             :   ! --------------------------------------------------------------------------------- !
    1119             : 
    1120             :   ! Modification : We may need to output 'tautotx_im,tautoty_im' from below 'compute_vdiff' and
    1121             :   !                separately print out as diagnostic output, because these are different from
    1122             :   !                the explicit 'tautotx, tautoty' computed above.
    1123             :   ! Note that the output 'tauresx,tauresy' from below subroutines are fully implicit ones.
    1124             : 
    1125       72960 :   call pbuf_get_field(pbuf, kvt_idx, kvt)
    1126             : 
    1127       72960 :   if (do_molec_diff .and. .not. waccmx_mode) then
    1128             :      ! Top boundary condition for dry static energy
    1129           0 :      dse_top(:ncol) = cpairv(:ncol,1,lchnk) * tint(:ncol,1) + &
    1130           0 :           gravit * state%zi(:ncol,1)
    1131             :   else
    1132     1123584 :      dse_top(:ncol) = 0._r8
    1133             :   end if
    1134             : 
    1135       72960 :   select case (eddy_scheme)
    1136             :   case ('CLUBB_SGS')
    1137             :      ! CLUBB applies some fluxes itself, but we still want constituent
    1138             :      ! fluxes applied here (except water vapor).
    1139       72960 :      taux = 0._r8
    1140       72960 :      tauy = 0._r8
    1141       72960 :      shflux = 0._r8
    1142     1240320 :      cflux(:,1) = 0._r8
    1143       72960 :      if (cam_physpkg_is("cam7")) then
    1144             :        ! surface fluxes applied in clubb emissions module
    1145           0 :        cflux(:,2:) = 0._r8
    1146             :      else
    1147   303951360 :        cflux(:,2:) = cam_in%cflx(:,2:)
    1148             :      end if
    1149             :   case default
    1150           0 :      taux = cam_in%wsx
    1151           0 :      tauy = cam_in%wsy
    1152           0 :      shflux = cam_in%shf
    1153       72960 :      cflux = cam_in%cflx
    1154             :   end select
    1155             : 
    1156       72960 :   if( any(fieldlist_wet) ) then
    1157             : 
    1158       72960 :      if (do_molec_diff) then
    1159             :         call compute_molec_diff(state%lchnk, pcols, pver, pcnst, ncol, &
    1160             :              kvm, kvt, tint, rhoi, kq_scal, cnst_mw, &
    1161           0 :              mw_fac, nbot_molec)
    1162             :      end if
    1163             : 
    1164             :      call compute_vdiff( state%lchnk   ,                                                                     &
    1165             :           pcols         , pver               , pcnst        , ncol          , tint          , &
    1166             :           p    , state%t      , rhoi, ztodt         , taux          , &
    1167             :           tauy          , shflux             , cflux        , &
    1168             :           kvh           , kvm                , kvq          , cgs           , cgh           , &
    1169             :           state%zi      , ksrftms            , dragblj      , &
    1170             :           qmincg       , fieldlist_wet , fieldlist_molec,&
    1171             :           u_tmp         , v_tmp              , q_tmp        , s_tmp         ,                 &
    1172             :           tautmsx       , tautmsy            , dtk          , topflx        , errstring     , &
    1173             :           tauresx       , tauresy            , 1            , cpairv(:,:,state%lchnk), dse_top, &
    1174             :           do_molec_diff, waccmx_mode, &
    1175             :           vd_lu_qdecomp, &
    1176             :           ubc_mmr, ubc_flux, kvt, state%pmid, &
    1177             :           cnst_mw, cnst_fixed_ubc, cnst_fixed_ubflx, nbot_molec, &
    1178       72960 :           kq_scal, mw_fac)
    1179             : 
    1180             :      call handle_errmsg(errstring, subname="compute_vdiff", &
    1181       72960 :           extra_msg="Error in fieldlist_wet call from vertical_diffusion.")
    1182             : 
    1183             :   end if
    1184             : 
    1185       72960 :   if( any( fieldlist_dry ) ) then
    1186             : 
    1187           0 :      if( do_molec_diff ) then
    1188             :         ! kvm is unused in the output here (since it was assigned
    1189             :         ! above), so we use a temp kvm for the inout argument, and
    1190             :         ! ignore the value output by compute_molec_diff.
    1191           0 :         kvm_temp = kvm
    1192             :         call compute_molec_diff(state%lchnk, pcols, pver, pcnst, ncol, &
    1193             :              kvm_temp, kvt, tint, rhoi_dry, kq_scal, cnst_mw, &
    1194           0 :              mw_fac, nbot_molec)
    1195             :      end if
    1196             : 
    1197             :      call compute_vdiff( state%lchnk   ,                                                                     &
    1198             :           pcols         , pver               , pcnst        , ncol          , tint          , &
    1199             :           p_dry , state%t      , rhoi_dry,  ztodt         , taux          , &
    1200             :           tauy          , shflux             , cflux        , &
    1201             :           kvh           , kvm                , kvq          , cgs           , cgh           , &
    1202             :           state%zi      , ksrftms            , dragblj      , &
    1203             :           qmincg       , fieldlist_dry , fieldlist_molec,&
    1204             :           u_tmp         , v_tmp              , q_tmp        , s_tmp         ,                 &
    1205             :           tautmsx_temp  , tautmsy_temp       , dtk_temp     , topflx_temp   , errstring     , &
    1206             :           tauresx       , tauresy            , 1            , cpairv(:,:,state%lchnk), dse_top, &
    1207             :           do_molec_diff , waccmx_mode, &
    1208             :           vd_lu_qdecomp, &
    1209             :           ubc_mmr, ubc_flux, kvt, state%pmiddry, &
    1210             :           cnst_mw, cnst_fixed_ubc, cnst_fixed_ubflx, nbot_molec, &
    1211           0 :           kq_scal, mw_fac)
    1212             : 
    1213             :      call handle_errmsg(errstring, subname="compute_vdiff", &
    1214           0 :           extra_msg="Error in fieldlist_dry call from vertical_diffusion.")
    1215             : 
    1216             :   end if
    1217             : 
    1218             :   ! For species not diffused, so just add the explicit surface fluxes to the
    1219             :   ! lowest layer.  **NOTE** This code assumes wet mmr.
    1220     1123584 :   tmp1(:ncol) = ztodt * gravit * state%rpdel(:ncol,pver)
    1221    18021120 :   do l = 1, pcnst
    1222    18021120 :      if (cnst_ndropmixed(l)) then
    1223    33707520 :         q_tmp(:ncol,pver,l) = q_tmp(:ncol,pver,l) + tmp1(:ncol) * cflux(:ncol,l)
    1224             :      end if
    1225             :   end do
    1226             : 
    1227             :   ! -------------------------------------------------------- !
    1228             :   ! Diagnostics and output writing after applying PBL scheme !
    1229             :   ! -------------------------------------------------------- !
    1230             : 
    1231       72960 :   if (.not. do_pbl_diags) then
    1232             : 
    1233           0 :      sl(:ncol,:pver)  = s_tmp(:ncol,:) -   latvap           * q_tmp(:ncol,:,ixcldliq) &
    1234           0 :           - ( latvap + latice) * q_tmp(:ncol,:,ixcldice)
    1235             :      qt(:ncol,:pver)  = q_tmp(:ncol,:,1) + q_tmp(:ncol,:,ixcldliq) &
    1236           0 :           + q_tmp(:ncol,:,ixcldice)
    1237           0 :      slv(:ncol,:pver) = sl(:ncol,:pver) * ( 1._r8 + zvir*qt(:ncol,:pver) )
    1238             : 
    1239           0 :      slflx(:ncol,1) = 0._r8
    1240           0 :      qtflx(:ncol,1) = 0._r8
    1241           0 :      uflx(:ncol,1)  = 0._r8
    1242           0 :      vflx(:ncol,1)  = 0._r8
    1243             : 
    1244           0 :      slflx_cg(:ncol,1) = 0._r8
    1245           0 :      qtflx_cg(:ncol,1) = 0._r8
    1246           0 :      uflx_cg(:ncol,1)  = 0._r8
    1247           0 :      vflx_cg(:ncol,1)  = 0._r8
    1248             : 
    1249           0 :      do k = 2, pver
    1250           0 :         do i = 1, ncol
    1251           0 :            rhoair     = state%pint(i,k) / ( rair * ( ( 0.5_r8*(slv(i,k)+slv(i,k-1)) - gravit*state%zi(i,k))/cpair ) )
    1252           0 :            slflx(i,k) = kvh(i,k) * &
    1253           0 :                 ( - rhoair*(sl(i,k-1)-sl(i,k))/(state%zm(i,k-1)-state%zm(i,k)) &
    1254           0 :                 + cgh(i,k) )
    1255             :            qtflx(i,k) = kvh(i,k) * &
    1256           0 :                 ( - rhoair*(qt(i,k-1)-qt(i,k))/(state%zm(i,k-1)-state%zm(i,k)) &
    1257           0 :                 + rhoair*(cam_in%cflx(i,1)+cam_in%cflx(i,ixcldliq)+cam_in%cflx(i,ixcldice))*cgs(i,k) )
    1258             :            uflx(i,k)  = kvm(i,k) * &
    1259           0 :                 ( - rhoair*(u_tmp(i,k-1)-u_tmp(i,k))/(state%zm(i,k-1)-state%zm(i,k)))
    1260             :            vflx(i,k)  = kvm(i,k) * &
    1261           0 :                 ( - rhoair*(v_tmp(i,k-1)-v_tmp(i,k))/(state%zm(i,k-1)-state%zm(i,k)))
    1262           0 :            slflx_cg(i,k) = kvh(i,k) * cgh(i,k)
    1263             :            qtflx_cg(i,k) = kvh(i,k) * rhoair * ( cam_in%cflx(i,1) + &
    1264           0 :                 cam_in%cflx(i,ixcldliq) + cam_in%cflx(i,ixcldice) ) * cgs(i,k)
    1265           0 :            uflx_cg(i,k)  = 0._r8
    1266           0 :            vflx_cg(i,k)  = 0._r8
    1267             :         end do
    1268             :      end do
    1269             : 
    1270             :      ! Modification : I should check whether slflx(:ncol,pverp) is correctly computed.
    1271             :      !                Note also that 'tautotx' is explicit total stress, different from
    1272             :      !                the ones that have been actually added into the atmosphere.
    1273             : 
    1274           0 :      slflx(:ncol,pverp) = cam_in%shf(:ncol)
    1275           0 :      qtflx(:ncol,pverp) = cam_in%cflx(:ncol,1)
    1276           0 :      uflx(:ncol,pverp)  = tautotx(:ncol)
    1277           0 :      vflx(:ncol,pverp)  = tautoty(:ncol)
    1278             : 
    1279           0 :      slflx_cg(:ncol,pverp) = 0._r8
    1280           0 :      qtflx_cg(:ncol,pverp) = 0._r8
    1281           0 :      uflx_cg(:ncol,pverp)  = 0._r8
    1282           0 :      vflx_cg(:ncol,pverp)  = 0._r8
    1283             : 
    1284           0 :      if (trim(shallow_scheme) == 'UNICON') then
    1285           0 :         call pbuf_get_field(pbuf, qtl_flx_idx,  qtl_flx)
    1286           0 :         call pbuf_get_field(pbuf, qti_flx_idx,  qti_flx)
    1287           0 :         qtl_flx(:ncol,1) = 0._r8
    1288           0 :         qti_flx(:ncol,1) = 0._r8
    1289           0 :         do k = 2, pver
    1290           0 :            do i = 1, ncol
    1291             :               ! For use in the cloud macrophysics
    1292             :               ! Note that density is not added here. Also, only consider local transport term.
    1293           0 :               qtl_flx(i,k) = - kvh(i,k)*(q_tmp(i,k-1,1)-q_tmp(i,k,1)+q_tmp(i,k-1,ixcldliq)-q_tmp(i,k,ixcldliq))/&
    1294           0 :                    (state%zm(i,k-1)-state%zm(i,k))
    1295           0 :               qti_flx(i,k) = - kvh(i,k)*(q_tmp(i,k-1,1)-q_tmp(i,k,1)+q_tmp(i,k-1,ixcldice)-q_tmp(i,k,ixcldice))/&
    1296           0 :                    (state%zm(i,k-1)-state%zm(i,k))
    1297             :            end do
    1298             :         end do
    1299           0 :         do i = 1, ncol
    1300           0 :            rhoair = state%pint(i,pverp)/(rair*((slv(i,pver)-gravit*state%zi(i,pverp))/cpair))
    1301           0 :            qtl_flx(i,pverp) = cam_in%cflx(i,1)/rhoair
    1302           0 :            qti_flx(i,pverp) = cam_in%cflx(i,1)/rhoair
    1303             :         end do
    1304             :      end if
    1305             : 
    1306             :   end if
    1307             : 
    1308             :   ! --------------------------------------------------------------- !
    1309             :   ! Convert the new profiles into vertical diffusion tendencies.    !
    1310             :   ! Convert KE dissipative heat change into "temperature" tendency. !
    1311             :   ! --------------------------------------------------------------- !
    1312             :   ! All variables are modified by vertical diffusion
    1313             : 
    1314    18021120 :   lq(:) = .TRUE.
    1315             :   call physics_ptend_init(ptend,state%psetcols, "vertical diffusion", &
    1316       72960 :        ls=.true., lu=.true., lv=.true., lq=lq)
    1317             : 
    1318    62993664 :   ptend%s(:ncol,:)       = ( s_tmp(:ncol,:) - state%s(:ncol,:) ) * rztodt
    1319    62993664 :   ptend%u(:ncol,:)       = ( u_tmp(:ncol,:) - state%u(:ncol,:) ) * rztodt
    1320    62993664 :   ptend%v(:ncol,:)       = ( v_tmp(:ncol,:) - state%v(:ncol,:) ) * rztodt
    1321 15496514304 :   ptend%q(:ncol,:pver,:) = ( q_tmp(:ncol,:pver,:) - state%q(:ncol,:pver,:) ) * rztodt
    1322             : 
    1323             :   ! Convert tendencies of dry constituents to dry basis.
    1324    18021120 :   do m = 1,pcnst
    1325    18021120 :      if (cnst_type(m).eq.'dry') then
    1326 14740517376 :         ptend%q(:ncol,:pver,m) = ptend%q(:ncol,:pver,m)*state%pdel(:ncol,:pver)/state%pdeldry(:ncol,:pver)
    1327             :      endif
    1328             :   end do
    1329             : 
    1330       72960 :   if (.not. do_pbl_diags) then
    1331           0 :      slten(:ncol,:)         = ( sl(:ncol,:) - sl_prePBL(:ncol,:) ) * rztodt
    1332           0 :      qtten(:ncol,:)         = ( qt(:ncol,:) - qt_prePBL(:ncol,:) ) * rztodt
    1333             :   end if
    1334             : 
    1335             :   ! ------------------------------------------------------------ !
    1336             :   ! In order to perform 'pseudo-conservative variable diffusion' !
    1337             :   ! perform the following two stages:                            !
    1338             :   !                                                              !
    1339             :   ! I.  Re-set (1) 'qvten' by 'qtten', and 'qlten = qiten = 0'   !
    1340             :   !            (2) 'sten'  by 'slten', and                       !
    1341             :   !            (3) 'qlten = qiten = 0'                           !
    1342             :   !                                                              !
    1343             :   ! II. Apply 'positive_moisture'                                !
    1344             :   !                                                              !
    1345             :   ! ------------------------------------------------------------ !
    1346             : 
    1347       72960 :     if( eddy_scheme .eq. 'diag_TKE' .and. do_pseudocon_diff ) then
    1348             : 
    1349           0 :      ptend%q(:ncol,:pver,1) = qtten(:ncol,:pver)
    1350           0 :      ptend%s(:ncol,:pver)   = slten(:ncol,:pver)
    1351           0 :      ptend%q(:ncol,:pver,ixcldliq) = 0._r8
    1352           0 :      ptend%q(:ncol,:pver,ixcldice) = 0._r8
    1353           0 :      if (ixnumliq > 0) ptend%q(:ncol,:pver,ixnumliq) = 0._r8
    1354           0 :      if (ixnumice > 0) ptend%q(:ncol,:pver,ixnumice) = 0._r8
    1355             : 
    1356           0 :      do i = 1, ncol
    1357           0 :         do k = 1, pver
    1358           0 :            qv_pro(i,k) = state%q(i,k,1)        + ptend%q(i,k,1)             * ztodt
    1359           0 :            ql_pro(i,k) = state%q(i,k,ixcldliq) + ptend%q(i,k,ixcldliq)      * ztodt
    1360           0 :            qi_pro(i,k) = state%q(i,k,ixcldice) + ptend%q(i,k,ixcldice)      * ztodt
    1361           0 :            s_pro(i,k)  = state%s(i,k)          + ptend%s(i,k)               * ztodt
    1362           0 :            t_pro(i,k)  = state%t(i,k)          + (1._r8/cpair)*ptend%s(i,k) * ztodt
    1363             :         end do
    1364             :      end do
    1365             : 
    1366           0 :      call positive_moisture( cpair, latvap, latvap+latice, ncol, pver, ztodt, qmin(1), qmin(ixcldliq), qmin(ixcldice),    &
    1367           0 :           state%pdel(:ncol,pver:1:-1), qv_pro(:ncol,pver:1:-1), ql_pro(:ncol,pver:1:-1), &
    1368           0 :           qi_pro(:ncol,pver:1:-1), t_pro(:ncol,pver:1:-1), s_pro(:ncol,pver:1:-1),       &
    1369           0 :           ptend%q(:ncol,pver:1:-1,1), ptend%q(:ncol,pver:1:-1,ixcldliq),                 &
    1370           0 :           ptend%q(:ncol,pver:1:-1,ixcldice), ptend%s(:ncol,pver:1:-1) )
    1371             : 
    1372             :   end if
    1373             : 
    1374             :   ! ----------------------------------------------------------------- !
    1375             :   ! Re-calculate diagnostic output variables after vertical diffusion !
    1376             :   ! ----------------------------------------------------------------- !
    1377             : 
    1378       72960 :   if (.not. do_pbl_diags) then
    1379             : 
    1380           0 :      qv_aft_PBL(:ncol,:pver)  =   state%q(:ncol,:pver,1)         + ptend%q(:ncol,:pver,1)        * ztodt
    1381           0 :      ql_aft_PBL(:ncol,:pver)  =   state%q(:ncol,:pver,ixcldliq)  + ptend%q(:ncol,:pver,ixcldliq) * ztodt
    1382           0 :      qi_aft_PBL(:ncol,:pver)  =   state%q(:ncol,:pver,ixcldice)  + ptend%q(:ncol,:pver,ixcldice) * ztodt
    1383           0 :      s_aft_PBL(:ncol,:pver)   =   state%s(:ncol,:pver)           + ptend%s(:ncol,:pver)          * ztodt
    1384           0 :      t_aftPBL(:ncol,:pver)    = ( s_aft_PBL(:ncol,:pver) - gravit*state%zm(:ncol,:pver) ) / cpair
    1385             : 
    1386           0 :      u_aft_PBL(:ncol,:pver)   =  state%u(:ncol,:pver)          + ptend%u(:ncol,:pver)            * ztodt
    1387           0 :      v_aft_PBL(:ncol,:pver)   =  state%v(:ncol,:pver)          + ptend%v(:ncol,:pver)            * ztodt
    1388             : 
    1389           0 :      do k = 1, pver
    1390           0 :         call qsat(t_aftPBL(1:ncol,k), state%pmid(1:ncol,k), tem2(1:ncol,k), ftem(1:ncol,k), ncol)
    1391             :      end do
    1392           0 :      ftem_aftPBL(:ncol,:pver) = qv_aft_PBL(:ncol,:pver) / ftem(:ncol,:pver) * 100._r8
    1393             : 
    1394           0 :      tten(:ncol,:pver)        = ( t_aftPBL(:ncol,:pver)    - state%t(:ncol,:pver) )              * rztodt
    1395           0 :      rhten(:ncol,:pver)       = ( ftem_aftPBL(:ncol,:pver) - ftem_prePBL(:ncol,:pver) )          * rztodt
    1396             : 
    1397             :   end if
    1398             : 
    1399             : 
    1400             :   ! -------------------------------------------------------------- !
    1401             :   ! mass conservation check.........
    1402             :   ! -------------------------------------------------------------- !
    1403       72960 :   if (diff_cnsrv_mass_check) then
    1404             : 
    1405             :      ! Conservation check
    1406           0 :      do m = 1, pcnst
    1407           0 :         fixed_ubc: if ((.not.cnst_fixed_ubc(m)).and.(.not.cnst_fixed_ubflx(m))) then
    1408           0 :            col_loop: do i = 1, ncol
    1409           0 :               sum1 = 0._r8
    1410           0 :               sum2 = 0._r8
    1411           0 :               sum3 = 0._r8
    1412           0 :               do k = 1, pver
    1413           0 :                  if(cnst_get_type_byind(m).eq.'wet') then
    1414           0 :                     pdelx = state%pdel(i,k)
    1415             :                  else
    1416           0 :                     pdelx = state%pdeldry(i,k)
    1417             :                  endif
    1418           0 :                  sum1 = sum1 + state%q(i,k,m)*pdelx/gravit                          ! total column
    1419           0 :                  sum2 = sum2 +(state%q(i,k,m)+ptend%q(i,k,m)*ztodt)*pdelx/ gravit   ! total column after tendancy is applied
    1420           0 :                  sum3 = sum3 +(               ptend%q(i,k,m)*ztodt)*pdelx/ gravit   ! rate of change in column
    1421             :               enddo
    1422           0 :               sum1 = sum1 + (cam_in%cflx(i,m) * ztodt) ! add in surface flux (kg/m2)
    1423           0 :               sflx = (cam_in%cflx(i,m) * ztodt)
    1424           0 :               if (sum1>1.e-36_r8) then
    1425           0 :                  if( abs((sum2-sum1)/sum1) .gt. 1.e-12_r8  ) then
    1426           0 :                     nstep = get_nstep()
    1427             :                     write(iulog,'(a,a8,a,I4,2f8.3,5e25.16)') &
    1428           0 :                          'MASSCHECK vert diff : nstep,lon,lat,mass1,mass2,sum3,sflx,rel-diff : ', &
    1429           0 :                          trim(cnst_name(m)), ' : ', nstep, state%lon(i)*180._r8/pi, state%lat(i)*180._r8/pi, &
    1430           0 :                          sum1, sum2, sum3, sflx, abs(sum2-sum1)/sum1
    1431             : !xxx                    call endrun('vertical_diffusion_tend : mass not conserved' )
    1432             :                  endif
    1433             :               endif
    1434             :            enddo col_loop
    1435             :         endif fixed_ubc
    1436             :      enddo
    1437             :   endif
    1438             : 
    1439             :   ! -------------------------------------------------------------- !
    1440             :   ! Writing state variables after PBL scheme for detailed analysis !
    1441             :   ! -------------------------------------------------------------- !
    1442             : 
    1443       72960 :   if (.not. do_pbl_diags) then
    1444             : 
    1445           0 :      call outfld( 'sl_aft_PBL'   , sl,                        pcols, lchnk )
    1446           0 :      call outfld( 'qt_aft_PBL'   , qt,                        pcols, lchnk )
    1447           0 :      call outfld( 'slv_aft_PBL'  , slv,                       pcols, lchnk )
    1448           0 :      call outfld( 'u_aft_PBL'    , u_aft_PBL,                 pcols, lchnk )
    1449           0 :      call outfld( 'v_aft_PBL'    , v_aft_PBL,                 pcols, lchnk )
    1450           0 :      call outfld( 'qv_aft_PBL'   , qv_aft_PBL,                pcols, lchnk )
    1451           0 :      call outfld( 'ql_aft_PBL'   , ql_aft_PBL,                pcols, lchnk )
    1452           0 :      call outfld( 'qi_aft_PBL'   , qi_aft_PBL,                pcols, lchnk )
    1453           0 :      call outfld( 't_aft_PBL '   , t_aftPBL,                  pcols, lchnk )
    1454           0 :      call outfld( 'rh_aft_PBL'   , ftem_aftPBL,               pcols, lchnk )
    1455           0 :      call outfld( 'slflx_PBL'    , slflx,                     pcols, lchnk )
    1456           0 :      call outfld( 'qtflx_PBL'    , qtflx,                     pcols, lchnk )
    1457           0 :      call outfld( 'uflx_PBL'     , uflx,                      pcols, lchnk )
    1458           0 :      call outfld( 'vflx_PBL'     , vflx,                      pcols, lchnk )
    1459           0 :      call outfld( 'slflx_cg_PBL' , slflx_cg,                  pcols, lchnk )
    1460           0 :      call outfld( 'qtflx_cg_PBL' , qtflx_cg,                  pcols, lchnk )
    1461           0 :      call outfld( 'uflx_cg_PBL'  , uflx_cg,                   pcols, lchnk )
    1462           0 :      call outfld( 'vflx_cg_PBL'  , vflx_cg,                   pcols, lchnk )
    1463           0 :      call outfld( 'slten_PBL'    , slten,                     pcols, lchnk )
    1464           0 :      call outfld( 'qtten_PBL'    , qtten,                     pcols, lchnk )
    1465           0 :      call outfld( 'uten_PBL'     , ptend%u,                   pcols, lchnk )
    1466           0 :      call outfld( 'vten_PBL'     , ptend%v,                   pcols, lchnk )
    1467           0 :      call outfld( 'qvten_PBL'    , ptend%q(:,:,1),            pcols, lchnk )
    1468           0 :      call outfld( 'qlten_PBL'    , ptend%q(:,:,ixcldliq),     pcols, lchnk )
    1469           0 :      call outfld( 'qiten_PBL'    , ptend%q(:,:,ixcldice),     pcols, lchnk )
    1470           0 :      call outfld( 'tten_PBL'     , tten,                      pcols, lchnk )
    1471           0 :      call outfld( 'rhten_PBL'    , rhten,                     pcols, lchnk )
    1472             : 
    1473             :   end if
    1474             : 
    1475             :   ! ------------------------------------------- !
    1476             :   ! Writing the other standard output variables !
    1477             :   ! ------------------------------------------- !
    1478             : 
    1479       72960 :   if (.not. do_pbl_diags) then
    1480           0 :      call outfld( 'QT'           , qt,                        pcols, lchnk )
    1481           0 :      call outfld( 'SL'           , sl,                        pcols, lchnk )
    1482           0 :      call outfld( 'SLV'          , slv,                       pcols, lchnk )
    1483           0 :      call outfld( 'SLFLX'        , slflx,                     pcols, lchnk )
    1484           0 :      call outfld( 'QTFLX'        , qtflx,                     pcols, lchnk )
    1485           0 :      call outfld( 'UFLX'         , uflx,                      pcols, lchnk )
    1486           0 :      call outfld( 'VFLX'         , vflx,                      pcols, lchnk )
    1487           0 :      call outfld( 'TKE'          , tke,                       pcols, lchnk )
    1488             : 
    1489           0 :      call outfld( 'PBLH'         , pblh,                      pcols, lchnk )
    1490           0 :      call outfld( 'TPERT'        , tpert,                     pcols, lchnk )
    1491           0 :      call outfld( 'QPERT'        , qpert,                     pcols, lchnk )
    1492             :   end if
    1493       72960 :   call outfld( 'USTAR'        , ustar,                     pcols, lchnk )
    1494       72960 :   call outfld( 'KVH'          , kvh,                       pcols, lchnk )
    1495       72960 :   call outfld( 'KVT'          , kvt,                       pcols, lchnk )
    1496       72960 :   call outfld( 'KVM'          , kvm,                       pcols, lchnk )
    1497       72960 :   call outfld( 'CGS'          , cgs,                       pcols, lchnk )
    1498    62993664 :   dtk(:ncol,:) = dtk(:ncol,:) / cpair / ztodt      ! Normalize heating for history
    1499       72960 :   call outfld( 'DTVKE'        , dtk,                       pcols, lchnk )
    1500    62993664 :   dtk(:ncol,:) = ptend%s(:ncol,:) / cpair          ! Normalize heating for history using dtk
    1501       72960 :   call outfld( 'DTV'          , dtk,                       pcols, lchnk )
    1502       72960 :   call outfld( 'DUV'          , ptend%u,                   pcols, lchnk )
    1503       72960 :   call outfld( 'DVV'          , ptend%v,                   pcols, lchnk )
    1504    18021120 :   do m = 1, pcnst
    1505    18021120 :      call outfld( vdiffnam(m) , ptend%q(1,1,m),            pcols, lchnk )
    1506             :   end do
    1507       72960 :   if( do_molec_diff ) then
    1508           0 :      call outfld( 'TTPXMLC'  , topflx,                    pcols, lchnk )
    1509             :   end if
    1510             : 
    1511       72960 :   call p%finalize()
    1512       72960 :   call p_dry%finalize()
    1513             : 
    1514      145920 : end subroutine vertical_diffusion_tend
    1515             : 
    1516             : ! =============================================================================== !
    1517             : !                                                                                 !
    1518             : ! =============================================================================== !
    1519             : 
    1520           0 : subroutine positive_moisture( cp, xlv, xls, ncol, mkx, dt, qvmin, qlmin, qimin, &
    1521           0 :      dp, qv, ql, qi, t, s, qvten, qlten, qiten, sten )
    1522             :   ! ------------------------------------------------------------------------------- !
    1523             :   ! If any 'ql < qlmin, qi < qimin, qv < qvmin' are developed in any layer,         !
    1524             :   ! force them to be larger than minimum value by (1) condensating water vapor      !
    1525             :   ! into liquid or ice, and (2) by transporting water vapor from the very lower     !
    1526             :   ! layer. '2._r8' is multiplied to the minimum values for safety.                  !
    1527             :   ! Update final state variables and tendencies associated with this correction.    !
    1528             :   ! If any condensation happens, update (s,t) too.                                  !
    1529             :   ! Note that (qv,ql,qi,t,s) are final state variables after applying corresponding !
    1530             :   ! input tendencies.                                                               !
    1531             :   ! Be careful the order of k : '1': near-surface layer, 'mkx' : top layer          !
    1532             :   ! ------------------------------------------------------------------------------- !
    1533             :   implicit none
    1534             :   integer,  intent(in)     :: ncol, mkx
    1535             :   real(r8), intent(in)     :: cp, xlv, xls
    1536             :   real(r8), intent(in)     :: dt, qvmin, qlmin, qimin
    1537             :   real(r8), intent(in)     :: dp(ncol,mkx)
    1538             :   real(r8), intent(inout)  :: qv(ncol,mkx), ql(ncol,mkx), qi(ncol,mkx), t(ncol,mkx), s(ncol,mkx)
    1539             :   real(r8), intent(inout)  :: qvten(ncol,mkx), qlten(ncol,mkx), qiten(ncol,mkx), sten(ncol,mkx)
    1540             :   integer   i, k
    1541             :   real(r8)  dql, dqi, dqv, sum, aa, dum
    1542             : 
    1543             :   ! Modification : I should check whether this is exactly same as the one used in
    1544             :   !                shallow convection and cloud macrophysics.
    1545             : 
    1546           0 :   do i = 1, ncol
    1547           0 :      do k = mkx, 1, -1    ! From the top to the 1st (lowest) layer from the surface
    1548           0 :         dql        = max(0._r8,1._r8*qlmin-ql(i,k))
    1549           0 :         dqi        = max(0._r8,1._r8*qimin-qi(i,k))
    1550           0 :         qlten(i,k) = qlten(i,k) +  dql/dt
    1551           0 :         qiten(i,k) = qiten(i,k) +  dqi/dt
    1552           0 :         qvten(i,k) = qvten(i,k) - (dql+dqi)/dt
    1553           0 :         sten(i,k)  = sten(i,k)  + xlv * (dql/dt) + xls * (dqi/dt)
    1554           0 :         ql(i,k)    = ql(i,k) +  dql
    1555           0 :         qi(i,k)    = qi(i,k) +  dqi
    1556           0 :         qv(i,k)    = qv(i,k) -  dql - dqi
    1557           0 :         s(i,k)     = s(i,k)  +  xlv * dql + xls * dqi
    1558           0 :         t(i,k)     = t(i,k)  + (xlv * dql + xls * dqi)/cp
    1559           0 :         dqv        = max(0._r8,1._r8*qvmin-qv(i,k))
    1560           0 :         qvten(i,k) = qvten(i,k) + dqv/dt
    1561           0 :         qv(i,k)    = qv(i,k)    + dqv
    1562           0 :         if( k .ne. 1 ) then
    1563           0 :            qv(i,k-1)    = qv(i,k-1)    - dqv*dp(i,k)/dp(i,k-1)
    1564           0 :            qvten(i,k-1) = qvten(i,k-1) - dqv*dp(i,k)/dp(i,k-1)/dt
    1565             :         endif
    1566           0 :         qv(i,k) = max(qv(i,k),qvmin)
    1567           0 :         ql(i,k) = max(ql(i,k),qlmin)
    1568           0 :         qi(i,k) = max(qi(i,k),qimin)
    1569             :      end do
    1570             :      ! Extra moisture used to satisfy 'qv(i,1)=qvmin' is proportionally
    1571             :      ! extracted from all the layers that has 'qv > 2*qvmin'. This fully
    1572             :      ! preserves column moisture.
    1573           0 :      if( dqv .gt. 1.e-20_r8 ) then
    1574             :         sum = 0._r8
    1575           0 :         do k = 1, mkx
    1576           0 :            if( qv(i,k) .gt. 2._r8*qvmin ) sum = sum + qv(i,k)*dp(i,k)
    1577             :         enddo
    1578           0 :         aa = dqv*dp(i,1)/max(1.e-20_r8,sum)
    1579           0 :         if( aa .lt. 0.5_r8 ) then
    1580           0 :            do k = 1, mkx
    1581           0 :               if( qv(i,k) .gt. 2._r8*qvmin ) then
    1582           0 :                  dum        = aa*qv(i,k)
    1583           0 :                  qv(i,k)    = qv(i,k) - dum
    1584           0 :                  qvten(i,k) = qvten(i,k) - dum/dt
    1585             :               endif
    1586             :            enddo
    1587             :         else
    1588           0 :            write(iulog,*) 'Full positive_moisture is impossible in vertical_diffusion'
    1589             :         endif
    1590             :      endif
    1591             :   end do
    1592           0 :   return
    1593             : 
    1594       72960 : end subroutine positive_moisture
    1595             : 
    1596             : end module vertical_diffusion

Generated by: LCOV version 1.14