LCOV - code coverage report
Current view: top level - physics/cam - subcol_SILHS.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 485 0.0 %
Date: 2024-12-17 22:39:59 Functions: 0 11 0.0 %

          Line data    Source code
       1             : module subcol_SILHS
       2             :    !---------------------------------------------------------------------------
       3             :    ! Purpose:
       4             :    !
       5             :    ! Implement a subcolumn scheme based on the Subgrid Importance Latin Hypercube 
       6             :    ! Sampling (SILHS) functionality of the CLUBB moist turbulence parameterization.
       7             :    !
       8             :    !---------------------------------------------------------------------------
       9             : 
      10             :    use shr_kind_mod,     only: r8=>shr_kind_r8, r4=>shr_kind_r4, i4=>shr_kind_i4
      11             :    use physics_types,    only: physics_state, physics_tend, physics_ptend
      12             :    use ppgrid,           only: pcols, psubcols, pver, pverp, begchunk, endchunk
      13             :    use constituents,     only: pcnst, cnst_get_ind
      14             :    use cam_abortutils,   only: endrun
      15             :    use cam_logfile,      only: iulog
      16             :    use cam_history,      only: addfld, add_default, outfld, horiz_only
      17             :    use ref_pres,         only: top_lev => trop_cloud_top_lev
      18             : #ifdef CLUBB_SGS
      19             : #ifdef SILHS
      20             :   use clubb_intr, only: &
      21             :         clubb_config_flags, &
      22             :         clubb_params_single_col, &
      23             :         stats_metadata, &
      24             :         stats_zt, stats_zm, stats_sfc, &
      25             :         pdf_params_chnk, &
      26             :         hm_metadata, &
      27             :         hydromet_dim, &
      28             :         pdf_dim
      29             :         
      30             :    use clubb_api_module, only: &
      31             :         hmp2_ip_on_hmm2_ip_slope_type, &
      32             :         hmp2_ip_on_hmm2_ip_intrcpt_type, &
      33             :         precipitation_fractions, &
      34             :         stats, &
      35             :         core_rknd
      36             : 
      37             :    use silhs_api_module, only: &
      38             :         silhs_config_flags_type
      39             : #endif
      40             : #endif
      41             :    use physconst,     only: cpair, gravit, latvap, latice, rair, rga, cappa
      42             : 
      43             :    implicit none
      44             :    private
      45             :    save
      46             : 
      47             :    public :: subcol_register_SILHS  ! 
      48             :    public :: subcol_init_SILHS      ! Initialize 
      49             :    public :: subcol_gen_SILHS       ! Generate subcolumn fields by calling SILHS 
      50             :    public :: subcol_readnl_SILHS    ! SILHS namelist reader
      51             :    public :: subcol_ptend_avg_SILHS
      52             :    public :: subcol_SILHS_var_covar_driver
      53             :    public :: subcol_SILHS_fill_holes_conserv
      54             :    public :: subcol_SILHS_hydromet_conc_tend_lim
      55             :    public :: init_state_subcol
      56             :    private :: fill_holes_sedimentation
      57             :    private :: fill_holes_same_phase_vert
      58             : #ifdef SILHS
      59             :    ! Calc subcol mean ! Calc subcol variance
      60             :    private :: meansc
      61             :    private :: stdsc
      62             :    
      63             :    type (stats), target :: stats_lh_zt,   &
      64             :                            stats_lh_sfc
      65             :    !$omp threadprivate(stats_lh_zt, stats_lh_sfc)
      66             : 
      67             :   real( kind = core_rknd ), dimension(:,:), allocatable :: &
      68             :       corr_array_n_cloud, &
      69             :       corr_array_n_below
      70             : 
      71             : #endif
      72             : 
      73             :    !-----
      74             :    ! Private module vars
      75             :    !-----
      76             : 
      77             :    ! constituent indicies
      78             :    integer :: &
      79             :       ixq      = 0, &
      80             :       ixcldliq = 0, &
      81             :       ixnumliq = 0, &
      82             :       ixcldice = 0, &
      83             :       ixnumice = 0, &
      84             :       ixrain   = 0, &
      85             :       ixnumrain= 0, &
      86             :       ixsnow   = 0, &
      87             :       ixnumsnow= 0
      88             :    
      89             :    ! Pbuf indicies
      90             :    integer :: thlm_idx, rtm_idx, ice_supersat_idx, &
      91             :               alst_idx, cld_idx, qrain_idx, qsnow_idx, &
      92             :               nrain_idx, nsnow_idx, ztodt_idx, tke_idx, kvh_idx, &
      93             :               prec_pcw_idx, snow_pcw_idx, prec_str_idx, snow_str_idx, &
      94             :               qcsedten_idx, qrsedten_idx, qisedten_idx, qssedten_idx, &
      95             :               vtrmc_idx, umr_idx, vtrmi_idx, ums_idx, qcsevap_idx, qisevap_idx
      96             : 
      97             :    logical :: subcol_SILHS_weight  ! if set, sets up weights for averaging subcolumns for SILHS
      98             :    integer :: subcol_SILHS_numsubcol ! number of subcolumns for this run
      99             :    logical :: docldfracscaling = .false. ! Weight tendencies by cloud fraction
     100             : 
     101             :    character(len=256) :: subcol_SILHS_corr_file_path
     102             :    character(len=16)  :: subcol_SILHS_corr_file_name
     103             : 
     104             :    logical :: subcol_SILHS_q_to_micro, &
     105             :               subcol_SILHS_n_to_micro, &
     106             :               subcol_SILHS_use_clear_col, &
     107             :               subcol_SILHS_meanice, &
     108             :               subcol_SILHS_constrainmn
     109             : 
     110             :    logical :: subcol_SILHS_var_covar_src
     111             : 
     112             :    real(r8) :: subcol_SILHS_ncnp2_on_ncnm2
     113             : 
     114             :    ! There may or may not be a better place to put this.
     115             :    real(r8), parameter :: p0_clubb = 100000._r8
     116             : 
     117             : 
     118             : !   real(r8) :: subcol_SILHS_c6rt, subcol_SILHS_c7, subcol_SILHS_c8, subcol_SILHS_c11, &
     119             : !               subcol_SILHS_c11b, subcol_SILHS_gamma_coef, &
     120             : !               subcol_SILHS_mult_coef, subcol_SILHS_mu
     121             : 
     122             :    real(r8) :: ztodt  ! model timestep
     123             : #ifdef CLUBB_SGS
     124             : #ifdef SILHS
     125             :     type(hmp2_ip_on_hmm2_ip_slope_type) :: subcol_SILHS_hmp2_ip_on_hmm2_ip_slope    
     126             :     type(hmp2_ip_on_hmm2_ip_intrcpt_type) :: subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt
     127             : 
     128             :     type(silhs_config_flags_type) :: silhs_config_flags
     129             : #endif
     130             : #endif
     131             : 
     132             : contains
     133             : 
     134           0 :    subroutine subcol_register_SILHS()
     135             : 
     136             :       !--------------------------------
     137             :       ! Register fields needed by SILHS in the physics buffer
     138             :       ! Currently, most fields needed by SILHS but calculated by CLUBB are registered
     139             :       ! by clubb in clubb_intr.F90.
     140             :       ! 
     141             :       !--------------------------------
     142             : #ifdef CLUBB_SGS
     143             : #ifdef SILHS
     144             : #endif
     145             : #endif
     146           0 :    end subroutine subcol_register_SILHS
     147             : 
     148             : 
     149           0 :    subroutine subcol_readnl_SILHS(nlfile)
     150             : #ifdef CLUBB_SGS
     151             : #ifdef SILHS
     152             :       use namelist_utils,   only: find_group_name
     153             :       use spmd_utils,       only: masterproc, masterprocid, mpicom
     154             :       use spmd_utils,       only: mpi_integer, mpi_logical, mpi_character, mpir8, iam
     155             :       use clubb_api_module, only: core_rknd
     156             :       use silhs_api_module, only: set_default_silhs_config_flags_api, &
     157             :                                   initialize_silhs_config_flags_type_api, &
     158             :                                   print_silhs_config_flags_api
     159             : #endif
     160             : #endif
     161             :       character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
     162             : 
     163             :       ! Local variables
     164             :       integer :: unitn, ierr
     165             : #ifdef CLUBB_SGS
     166             : #ifdef SILHS
     167             : 
     168             :       integer :: &
     169             :           cluster_allocation_strategy
     170             : 
     171             :       logical :: &
     172             :           subcol_silhs_l_lh_importance_sampling, &
     173             :           subcol_silhs_l_Lscale_vert_avg, &
     174             :           subcol_silhs_l_lh_straight_mc, &
     175             :           subcol_silhs_l_lh_clustered_sampling, &
     176             :           subcol_silhs_l_rcm_in_cloud_k_lh_start, &
     177             :           subcol_silhs_l_random_k_lh_start, &
     178             :           subcol_silhs_l_max_overlap_in_cloud, &
     179             :           subcol_silhs_l_lh_instant_var_covar_src, &
     180             :           subcol_silhs_l_lh_limit_weights, &
     181             :           subcol_silhs_l_lh_var_frac, &
     182             :           subcol_silhs_l_lh_normalize_weights
     183             : 
     184             :       namelist /subcol_SILHS_nl/ subcol_SILHS_weight, &
     185             :                                  subcol_SILHS_numsubcol, &
     186             :                                  subcol_SILHS_corr_file_path, &
     187             :                                  subcol_SILHS_corr_file_name, &
     188             :                                  subcol_SILHS_q_to_micro, &
     189             :                                  subcol_SILHS_n_to_micro, &
     190             :                                  subcol_SILHS_ncnp2_on_ncnm2, &
     191             :                                  subcol_SILHS_hmp2_ip_on_hmm2_ip_slope, &
     192             :                                  subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt, &
     193             :                                  subcol_SILHS_meanice, &
     194             :                                  subcol_SILHS_use_clear_col, &
     195             :                                  subcol_SILHS_constrainmn, &
     196             :                                  subcol_SILHS_var_covar_src
     197             : !                                 subcol_SILHS_c6rt, subcol_SILHS_c7, &
     198             : !                                 subcol_SILHS_c8, subcol_SILHS_c11, subcol_SILHS_c11b, &
     199             : !                                 subcol_SILHS_gamma_coef, subcol_SILHS_mult_coef, subcol_SILHS_mu
     200             : 
     201             :      namelist /silhs_config_flags_nl/ subcol_silhs_l_lh_importance_sampling, &
     202             :                                       subcol_silhs_l_Lscale_vert_avg, &
     203             :                                       subcol_silhs_l_lh_straight_mc, &
     204             :                                       subcol_silhs_l_lh_clustered_sampling, &
     205             :                                       subcol_silhs_l_rcm_in_cloud_k_lh_start, &
     206             :                                       subcol_silhs_l_random_k_lh_start, &
     207             :                                       subcol_silhs_l_max_overlap_in_cloud, &
     208             :                                       subcol_silhs_l_lh_instant_var_covar_src, &
     209             :                                       subcol_silhs_l_lh_limit_weights, &
     210             :                                       subcol_silhs_l_lh_var_frac, &
     211             :                                       subcol_silhs_l_lh_normalize_weights
     212             : 
     213             :       !-----------------------------------------------------------------------------
     214             :       ! Set defaults
     215             : 
     216             :       ! Eric Raut changed a default.
     217             :       subcol_SILHS_hmp2_ip_on_hmm2_ip_slope%Ni = 0.0_core_rknd
     218             :       subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt%Ni = 0.5_core_rknd
     219             : 
     220             :       if (masterproc) then
     221             :          open( newunit=unitn, file=trim(nlfile), status='old' )
     222             :          call find_group_name(unitn, 'subcol_SILHS_nl', status=ierr)
     223             :          if (ierr == 0) then
     224             :             read(unitn, subcol_SILHS_nl, iostat=ierr)
     225             :             if (ierr /= 0) then
     226             :                call endrun('subcol_readnl_SILHS: ERROR reading namelist')
     227             :             end if
     228             :          end if
     229             :          close(unitn)
     230             :       end if
     231             : 
     232             :       ! Set default silhs_config_flags entires
     233             :       call set_default_silhs_config_flags_api( cluster_allocation_strategy, &
     234             :                                                subcol_silhs_l_lh_importance_sampling, &
     235             :                                                subcol_silhs_l_Lscale_vert_avg, &
     236             :                                                subcol_silhs_l_lh_straight_mc, &
     237             :                                                subcol_silhs_l_lh_clustered_sampling, &
     238             :                                                subcol_silhs_l_rcm_in_cloud_k_lh_start, &
     239             :                                                subcol_silhs_l_random_k_lh_start, &
     240             :                                                subcol_silhs_l_max_overlap_in_cloud, &
     241             :                                                subcol_silhs_l_lh_instant_var_covar_src, &
     242             :                                                subcol_silhs_l_lh_limit_weights, &
     243             :                                                subcol_silhs_l_lh_var_frac, &
     244             :                                                subcol_silhs_l_lh_normalize_weights )
     245             : 
     246             :       ! Get silhs_config_flags entries from namelist
     247             :       if (masterproc) then
     248             :         open( newunit=unitn, file=trim(nlfile), status='old' )
     249             :         call find_group_name(unitn, 'silhs_config_flags_nl', status=ierr)
     250             :         if (ierr == 0) then
     251             :           read(unitn, silhs_config_flags_nl, iostat=ierr)
     252             :           if (ierr /= 0) then
     253             :             call endrun('silhs_config_flags_nl: ERROR reading namelist')
     254             :           end if
     255             :         end if
     256             :         close(unitn)
     257             :       end if
     258             : 
     259             :       ! Save silhs_config_flags entries into module variable silhs_config_flags
     260             :       call initialize_silhs_config_flags_type_api( cluster_allocation_strategy, &
     261             :                                                    subcol_silhs_l_lh_importance_sampling, &
     262             :                                                    subcol_silhs_l_Lscale_vert_avg, &
     263             :                                                    subcol_silhs_l_lh_straight_mc, &
     264             :                                                    subcol_silhs_l_lh_clustered_sampling, &
     265             :                                                    subcol_silhs_l_rcm_in_cloud_k_lh_start, &
     266             :                                                    subcol_silhs_l_random_k_lh_start, &
     267             :                                                    subcol_silhs_l_max_overlap_in_cloud, &
     268             :                                                    subcol_silhs_l_lh_instant_var_covar_src, &
     269             :                                                    subcol_silhs_l_lh_limit_weights, &
     270             :                                                    subcol_silhs_l_lh_var_frac, &
     271             :                                                    subcol_silhs_l_lh_normalize_weights, &
     272             :                                                    silhs_config_flags )
     273             : 
     274             :       ! Print the SILHS configurable flags
     275             :       call print_silhs_config_flags_api( iulog, silhs_config_flags ) ! Intent(in)
     276             : 
     277             : #ifdef SPMD
     278             :       ! Broadcast namelist variables
     279             :       call mpi_bcast(subcol_SILHS_weight,    1, mpi_logical, masterprocid, mpicom, ierr)
     280             :       call mpi_bcast(subcol_SILHS_numsubcol, 1, mpi_integer, masterprocid, mpicom, ierr)
     281             :       call mpi_bcast(subcol_SILHS_corr_file_path, len(subcol_SILHS_corr_file_path), &
     282             :                      mpi_character, masterprocid, mpicom, ierr)
     283             :       call mpi_bcast(subcol_SILHS_corr_file_name, len(subcol_SILHS_corr_file_name), &
     284             :                      mpi_character, masterprocid, mpicom, ierr)
     285             :       call mpi_bcast(subcol_SILHS_use_clear_col, 1, mpi_logical, masterprocid, mpicom, ierr)
     286             :       call mpi_bcast(subcol_SILHS_constrainmn, 1, mpi_logical, masterprocid, mpicom, ierr)
     287             :       call mpi_bcast(subcol_SILHS_meanice, 1, mpi_logical, masterprocid, mpicom, ierr)
     288             :       call mpi_bcast(subcol_SILHS_q_to_micro, 1, mpi_logical, masterprocid, mpicom, ierr)
     289             :       call mpi_bcast(subcol_SILHS_n_to_micro, 1, mpi_logical, masterprocid, mpicom, ierr)
     290             :       call mpi_bcast(subcol_SILHS_var_covar_src,1,mpi_logical,masterprocid, mpicom, ierr)
     291             :       call mpi_bcast(subcol_SILHS_ncnp2_on_ncnm2, 1, mpir8, masterprocid, mpicom, ierr)
     292             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_slope%rr, 1, mpir8, masterprocid, mpicom, ierr)
     293             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_slope%Nr, 1, mpir8, masterprocid, mpicom, ierr)
     294             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_slope%ri, 1, mpir8, masterprocid, mpicom, ierr)
     295             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_slope%Ni, 1, mpir8, masterprocid, mpicom, ierr)
     296             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_slope%rs, 1, mpir8, masterprocid, mpicom, ierr)
     297             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_slope%Ns, 1, mpir8, masterprocid, mpicom, ierr)
     298             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt%rr, 1, mpir8, masterprocid, mpicom, ierr)
     299             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt%Nr, 1, mpir8, masterprocid, mpicom, ierr)
     300             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt%ri, 1, mpir8, masterprocid, mpicom, ierr)
     301             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt%Ni, 1, mpir8, masterprocid, mpicom, ierr)
     302             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt%rs, 1, mpir8, masterprocid, mpicom, ierr)
     303             :       call mpi_bcast(subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt%Ns, 1, mpir8, masterprocid, mpicom, ierr)
     304             : !      call mpi_bcast(subcol_SILHS_c6rt, 1, mpir8, masterprocid, mpicom, ierr)
     305             : !      call mpi_bcast(subcol_SILHS_c7, 1, mpir8, masterprocid, mpicom, ierr)
     306             : !      call mpi_bcast(subcol_SILHS_c8, 1, mpir8, masterprocid, mpicom, ierr)
     307             : !      call mpi_bcast(subcol_SILHS_c11, 1, mpir8, masterprocid, mpicom, ierr)
     308             : !      call mpi_bcast(subcol_SILHS_c11b, 1, mpir8, masterprocid, mpicom, ierr)
     309             : !      call mpi_bcast(subcol_SILHS_gamma_coef, 1, mpir8, masterprocid, mpicom, ierr)
     310             : !      call mpi_bcast(subcol_SILHS_mult_coef, 1, mpir8, masterprocid, mpicom, ierr)
     311             : !      call mpi_bcast(subcol_SILHS_mu, 1, mpir8, masterprocid, mpicom, ierr)
     312             :       call mpi_bcast(silhs_config_flags%l_lh_importance_sampling, 1, mpi_logical, masterprocid, mpicom, ierr)
     313             :       call mpi_bcast(silhs_config_flags%l_Lscale_vert_avg, 1, mpi_logical, masterprocid, mpicom, ierr)
     314             :       call mpi_bcast(silhs_config_flags%l_lh_straight_mc, 1, mpi_logical, masterprocid, mpicom, ierr)
     315             :       call mpi_bcast(silhs_config_flags%l_lh_clustered_sampling, 1, mpi_logical, masterprocid, mpicom, ierr)
     316             :       call mpi_bcast(silhs_config_flags%l_rcm_in_cloud_k_lh_start, 1, mpi_logical, masterprocid, mpicom, ierr)
     317             :       call mpi_bcast(silhs_config_flags%l_random_k_lh_start, 1, mpi_logical, masterprocid, mpicom, ierr)
     318             :       call mpi_bcast(silhs_config_flags%l_max_overlap_in_cloud, 1, mpi_logical, masterprocid, mpicom, ierr)
     319             :       call mpi_bcast(silhs_config_flags%l_lh_instant_var_covar_src, 1, mpi_logical, masterprocid, mpicom, ierr)
     320             :       call mpi_bcast(silhs_config_flags%l_lh_limit_weights, 1, mpi_logical, masterprocid, mpicom, ierr)
     321             :       call mpi_bcast(silhs_config_flags%l_lh_var_frac, 1, mpi_logical, masterprocid, mpicom, ierr)
     322             :       call mpi_bcast(silhs_config_flags%l_lh_normalize_weights, 1, mpi_logical, masterprocid, mpicom, ierr)
     323             : 
     324             : ! SPMD
     325             : #endif
     326             : ! SILHS
     327             : #endif
     328             : ! CLUBB_SGS
     329             : #endif
     330           0 :    end subroutine subcol_readnl_SILHS
     331             : 
     332             : 
     333           0 :    subroutine subcol_init_SILHS(pbuf2d)
     334             : 
     335             :       !--------------------------------
     336             :       ! Read in parameters and initialize SILHS PDF fields.
     337             :       ! Set up indexes into Pbuf fields.
     338             :       ! Register history outputs.
     339             :       !--------------------------------
     340             : 
     341             :       use physics_buffer,          only: physics_buffer_desc, pbuf_get_field, &
     342             :                                          dtype_r8, pbuf_get_index
     343             : #ifdef CLUBB_SGS
     344             : #ifdef SILHS
     345             :       use clubb_api_module,        only: core_rknd, &
     346             :                                          setup_corr_varnce_array_api, &
     347             :                                          init_pdf_hydromet_arrays_api, &
     348             :                                          set_clubb_debug_level_api
     349             : 
     350             : #endif
     351             : #endif
     352             : 
     353             :       type(physics_buffer_desc), pointer :: pbuf2d(:,:)
     354             : 
     355             : #ifdef CLUBB_SGS
     356             : #ifdef SILHS
     357             : 
     358             :       integer :: iunit = 501 ! Default value, will get iunit from CAM 
     359             :       !character(len=*), parameter :: default_corr_case = "arm_97"
     360             :       character(len=*), parameter :: &
     361             :             cloud_file_ext  = "_corr_array_cloud.in", & ! File extensions for corr files
     362             :             below_file_ext  = "_corr_array_below.in"
     363             :       character(len=256) :: corr_file_path_cloud, corr_file_path_below
     364             : 
     365             :       ! To set up CLUBB hydromet indices
     366             :       integer :: &
     367             :           iirr,         & ! Hydrometeor array index for rain water mixing ratio, rr
     368             :           iirs,         & ! Hydrometeor array index for snow mixing ratio, rs
     369             :           iiri,         & ! Hydrometeor array index for ice mixing ratio, ri
     370             :           iirg,         & ! Hydrometeor array index for graupel mixing ratio, rg
     371             :           iiNr,         & ! Hydrometeor array index for rain drop concentration, Nr
     372             :           iiNs,         & ! Hydrometeor array index for snow concentration, Ns
     373             :           iiNi,         & ! Hydrometeor array index for ice concentration, Ni
     374             :           iiNg            ! Hydrometeor array index for graupel concentration, Ng
     375             : 
     376             :       integer :: l, ierr=0  ! Loop variable, error check
     377             : 
     378             :       ! Set CLUBB's debug level
     379             :       ! This is called in module clubb_intr; no need to do it here.
     380             : !      call set_clubb_debug_level_api( 0 )
     381             : 
     382             :       !-------------------------------
     383             :       ! CLUBB-SILHS Parameters (global module variables)
     384             :       !-------------------------------
     385             :       clubb_config_flags%l_fix_w_chi_eta_correlations = .true.
     386             :       clubb_config_flags%l_diagnose_correlations = .false.
     387             :       clubb_config_flags%l_calc_w_corr = .false.
     388             : !      l_prescribed_avg_deltaz = .false.
     389             :       clubb_config_flags%l_use_cloud_cover = .false.
     390             :       clubb_config_flags%l_const_Nc_in_cloud = .true.
     391             : 
     392             :       ! Values from the namelist
     393             :       docldfracscaling = subcol_SILHS_use_clear_col
     394             : 
     395             :       ! Namelist "tuning" or set correlations
     396             :       ! KTC Todo: Move these to a tuning "in" file or into the namelist
     397             :       ! JHTODO: we might want these on CLUBB's API and ultimatively on a namelist for tuning
     398             : !      C6rt = subcol_SILHS_c6rt
     399             : !      C7 = subcol_SILHS_c7                                      ! to all ice clouds
     400             : !      C8 = subcol_SILHS_c8
     401             : !      C11 = subcol_SILHS_c11
     402             : !      C11b = subcol_SILHS_c11b
     403             : !      gamma_coef = subcol_SILHS_gamma_coef
     404             : !      mult_coef = subcol_SILHS_mult_coef
     405             : !      mu = subcol_SILHS_mu
     406             : 
     407             :       !call set_clubb_debug_level( 0 )  !#KTCtodo: Add a namelist variable to set debug level
     408             : 
     409             :       ! Get constituent indices
     410             :       call cnst_get_ind('Q', ixq)
     411             :       call cnst_get_ind('CLDLIQ', ixcldliq)
     412             :       call cnst_get_ind('NUMLIQ', ixnumliq)
     413             :       call cnst_get_ind('CLDICE', ixcldice)
     414             :       call cnst_get_ind('NUMICE', ixnumice)
     415             :       call cnst_get_ind('RAINQM', ixrain, abort=.false.)
     416             :       call cnst_get_ind('NUMRAI', ixnumrain, abort=.false.)
     417             :       call cnst_get_ind('SNOWQM', ixsnow, abort=.false.)
     418             :       call cnst_get_ind('NUMSNO', ixnumsnow, abort=.false.)
     419             : 
     420             :       ! Get physics buffer indexes
     421             :       thlm_idx = pbuf_get_index('THLM')
     422             :       rtm_idx = pbuf_get_index('RTM')
     423             :       cld_idx = pbuf_get_index('CLD')
     424             :       alst_idx = pbuf_get_index('ALST')  ! SILHS expects clubb's cloud_frac liq stratus fraction
     425             :       ztodt_idx = pbuf_get_index('ZTODT')
     426             :       ice_supersat_idx = pbuf_get_index('ISS_FRAC')
     427             :       tke_idx = pbuf_get_index('tke')
     428             :       kvh_idx = pbuf_get_index('kvh')
     429             :       prec_pcw_idx = pbuf_get_index('PREC_PCW')
     430             :       snow_pcw_idx = pbuf_get_index('SNOW_PCW')
     431             :       prec_str_idx = pbuf_get_index('PREC_STR')
     432             :       snow_str_idx = pbuf_get_index('SNOW_STR')
     433             :       qcsedten_idx = pbuf_get_index('QCSEDTEN')
     434             :       qrsedten_idx = pbuf_get_index('QRSEDTEN')
     435             :       qisedten_idx = pbuf_get_index('QISEDTEN')
     436             :       qssedten_idx = pbuf_get_index('QSSEDTEN')
     437             :       vtrmc_idx = pbuf_get_index('VTRMC')
     438             :       umr_idx = pbuf_get_index('UMR')
     439             :       vtrmi_idx = pbuf_get_index('VTRMI')
     440             :       ums_idx = pbuf_get_index('UMS')
     441             :       qcsevap_idx = pbuf_get_index('QCSEVAP')
     442             :       qisevap_idx = pbuf_get_index('QISEVAP')
     443             :       qrain_idx = pbuf_get_index('QRAIN')
     444             :       qsnow_idx = pbuf_get_index('QSNOW')
     445             :       nrain_idx = pbuf_get_index('NRAIN')
     446             :       nsnow_idx = pbuf_get_index('NSNOW')
     447             :      
     448             :       !-------------------------------
     449             :       ! Set up SILHS hydrometeors #KTCtodo: move microphys specification to config time,
     450             :       !        Steve wants to set up a microphysics query so I can ask the microphysics
     451             :       !        scheme which hydrometeors to use. For the future.
     452             :       !-------------------------------
     453             :       iirr = 1
     454             :       iirs = 3
     455             :       iiri = 5
     456             :       iirg = -1
     457             : 
     458             :       iiNr = 2
     459             :       iiNs = 4
     460             :       iiNi = 6
     461             :       iiNg = -1
     462             : 
     463             :       hydromet_dim = 6
     464             :  
     465             :       ! Set up pdf indices, hydromet indicies, hydromet arrays, and hydromet variance ratios
     466             :       call init_pdf_hydromet_arrays_api( 1.0_core_rknd, 1.0_core_rknd, hydromet_dim,  & ! intent(in)
     467             :                                          iirr, iiNr, iiri, iiNi,                      & ! intent(in)
     468             :                                          iirs, iiNs, iirg, iiNg,                      & ! intent(in)
     469             :                                          subcol_SILHS_ncnp2_on_ncnm2,                 & ! intent(in)
     470             :                                          hm_metadata, pdf_dim,                        & ! intent(out)
     471             :                                          subcol_SILHS_hmp2_ip_on_hmm2_ip_slope,       & ! optional(in)
     472             :                                          subcol_SILHS_hmp2_ip_on_hmm2_ip_intrcpt )      ! optional(in)
     473             : 
     474             :       !-------------------------------
     475             :       ! Set up hydrometeors and correlation arrays for SILHS
     476             :       !-------------------------------
     477             :       allocate( corr_array_n_cloud(pdf_dim,pdf_dim), corr_array_n_below(pdf_dim,pdf_dim), stat=ierr)
     478             :       if( ierr /= 0 ) call endrun(' subcol_init_SILHS: failed to allocate corr_array fields ')
     479             : 
     480             :       corr_file_path_cloud = trim( subcol_SILHS_corr_file_path )//trim( subcol_SILHS_corr_file_name )//cloud_file_ext
     481             :       corr_file_path_below = trim( subcol_SILHS_corr_file_path )//trim( subcol_SILHS_corr_file_name )//below_file_ext
     482             : 
     483             :       call setup_corr_varnce_array_api( corr_file_path_cloud, corr_file_path_below, &
     484             :                                         pdf_dim, hm_metadata, newunit(iunit), &
     485             :                                         clubb_config_flags%l_fix_w_chi_eta_correlations,               & ! In
     486             :                                         corr_array_n_cloud, corr_array_n_below )
     487             : 
     488             :       !-------------------------------
     489             :       ! Register output fields from SILHS
     490             :       !-------------------------------
     491             :       call addfld('SILHS_NCLD_SCOL', (/'psubcols', 'ilev    '/), 'I', 'm^-3', &
     492             :            'Subcolumn Cloud Number Concentration', flag_xyfill=.true., fill_value=1.e30_r8)
     493             :       call addfld('SILHS_NRAIN_SCOL', (/'psubcols', 'ilev    '/), 'I', 'm^-3', &
     494             :            'Subcolumn Number Concentration of Rain from SILHS', flag_xyfill=.true., fill_value=1.e30_r8)
     495             :       call addfld('SILHS_OMEGA_SCOL', (/'psubcols', 'ilev    '/), 'I', 'Pa/s', &
     496             :            'Subcolumn vertical pressure velocity', flag_xyfill=.true., fill_value=1.e30_r8)
     497             :       call addfld('SILHS_RCM_SCOL', (/'psubcols', 'ilev    '/), 'I', 'kg/kg', &
     498             :            'Subcolumn Cloud Liquid Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8)
     499             :       call addfld('SILHS_RICLD_SCOL', (/'psubcols', 'ilev    '/), 'I', 'kg/kg', &
     500             :            'Subcolumn Cloud Ice Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8)
     501             :       call addfld('SILHS_NICLD_SCOL', (/'psubcols', 'ilev    '/), 'I', 'kg/kg', &
     502             :            'Subcolumn Cloud Ice Number Conc from SILHS', flag_xyfill=.true., fill_value=1.e30_r8)
     503             :       call addfld('SILHS_RRAIN_SCOL', (/'psubcols', 'ilev    '/), 'I', 'kg/kg', &
     504             :            'Subcolumn Precipitating Liquid Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8)
     505             :       call addfld('SILHS_RT_SCOL', (/'psubcols', 'ilev    '/), 'I', 'kg/kg ', &
     506             :            'Subcolumn Total Water from SILHS', flag_xyfill=.true., fill_value=1.e30_r8)
     507             :       call addfld('SILHS_THLM_SCOL', (/'psubcols', 'ilev    '/), 'I', 'K', &
     508             :            'Subcolumn liquid water pot temperature', flag_xyfill=.true., fill_value=1.e30_r8)
     509             :       call addfld('SILHS_WEIGHT_SCOL', (/'psubcols'/), 'I', 'frac', &
     510             :            'Weights for each subcolumn', flag_xyfill=.true., fill_value=1.e30_r8)
     511             :       call addfld('SILHS_WM_SCOL', (/'psubcols', 'ilev    '/), 'I', 'm/s', &
     512             :            'Subcolumn vertical velocity from SILHS', flag_xyfill=.true., fill_value=1.e30_r8)
     513             : 
     514             :       call addfld('NR_IN_LH', (/ 'lev' /), 'I', 'm^-3', &
     515             :                   'Num Rain Conc as input to SILHS')
     516             :      call addfld('SILHS_RTM', (/ 'ilev' /), 'I', 'kg/kg', &
     517             :                   'Input total water mixing ratio')
     518             :      call addfld('SILHS_THLM', (/ 'ilev' /), 'I', 'K', &
     519             :                   'Input liquid water potential temperature')
     520             :      call addfld('SILHS_QC_IN', (/ 'lev' /), 'I', 'kg/kg', &
     521             :                   'Input cloud water mixing ratio')
     522             :      call addfld('SILHS_QI_IN', (/ 'lev' /), 'I', 'kg/kg', &
     523             :                   'Input cloud ice mixing ratio')
     524             :      call addfld('SILHS_NC_IN', (/ 'lev' /), 'I', '#/kg', &
     525             :                   'Input cloud water number concentration')
     526             :      call addfld('SILHS_NI_IN', (/ 'lev' /), 'I', '#/kg', &
     527             :                   'Input cloud ice number concentration')
     528             :      call addfld('AKM_CLUBB', (/ 'ilev' /), 'I', '(kg/kg)/s', &
     529             :                   'Exact Kessler autoconversion')
     530             :      call addfld('AKM_LH_CLUBB', (/ 'ilev' /), 'I', '(kg/kg)/s', &
     531             :                   'Monte Carlo estimate of Kessler autoconversion')
     532             :      call addfld('INVS_EXNER', (/ 'lev' /), 'I', 'none', &
     533             :                   'inverse EXNER function from state in subcol_SILHS')
     534             :      call addfld('SILHS_ZTODT', horiz_only, 'I', 's', & 
     535             :                   'Length of Physics timestep (for debugging)')
     536             :      if ( subcol_SILHS_constrainmn ) then
     537             :         call addfld('SILHS_MSC_CLDICE', (/ 'lev' /), 'A', 'kg/kg', &
     538             :                     'Mean Cloud Ice across subcolumns')
     539             :         call addfld('SILHS_STDSC_CLDICE', (/ 'lev' /), 'A', 'kg/kg', &
     540             :                     'Standard deviation of Ice across subcolumns')
     541             :         if ( ixsnow > 0 ) then
     542             :            call addfld('SILHS_MSC_CLDLIQ', (/ 'lev' /), 'A', 'kg/kg', &
     543             :                        'Mean Cloud Liquid across subcolumns')
     544             :            call addfld('SILHS_STDSC_CLDLIQ', (/ 'lev' /), 'A', 'kg/kg', &
     545             :                        'Standard deviation of Liquid across subcolumns')
     546             :            call addfld('SILHS_MSC_Q', (/ 'lev' /), 'A', 'kg/kg', &
     547             :                        'Mean water vapor across subcolumns')
     548             :            call addfld('SILHS_STDSC_Q', (/ 'lev' /), 'A', 'kg/kg', &
     549             :                        'Standard deviation of water vapor across subcolumns')
     550             :         endif ! ixsnow > 0
     551             :      endif ! subcol_SILHS_constrainmn
     552             :      call addfld('SILHS_EFF_CLDFRAC', (/ 'lev' /), 'A', 'frac', &
     553             :                   'Calculated cloud fraction from subcolumn liq or ice') 
     554             : 
     555             :      call addfld('SILHS_CLUBB_PRECIP_FRAC', (/ 'lev' /), 'A', 'frac', &
     556             :                   'Precipitation fraction from CLUBB (set_up_pdf_params_incl_hydromet)')
     557             :      call addfld('SILHS_CLUBB_ICE_SS_FRAC', (/ 'lev' /), 'A', 'frac', &
     558             :                   'Ice supersaturation fraction from CLUBB')
     559             : 
     560             :      call addfld ('QVHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Water vapor mixing ratio tendency from hole filling')
     561             :      call addfld ('QCHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud water mixing ratio tendency from hole filling')
     562             :      call addfld ('QRHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Rain water mixing ratio tendency from hole filling')
     563             :      call addfld ('QIHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Cloud ice mixing ratio tendency from hole filling')
     564             :      call addfld ('QSHFTEN', (/ 'lev' /), 'A', 'kg/kg/s', 'Snow mixing ratio tendency from hole filling')
     565             :      call addfld ('THFTEN', (/ 'lev' /), 'A', 'K/s', 'Temperature tendency from hole filling')
     566             : 
     567             : #endif
     568             : #endif
     569           0 :    end subroutine subcol_init_SILHS
     570             : !==============================================================!
     571           0 :    subroutine init_state_subcol(state, tend, state_sc, tend_sc)
     572             :      
     573           0 :      use ppgrid,                 only : pver, pverp, pcols
     574             :      
     575             :      use subcol_utils,           only : subcol_set_subcols
     576             :      
     577             :      implicit none
     578             :      
     579             :      type(physics_state), intent(inout) :: state
     580             :      type(physics_tend),  intent(inout) :: tend
     581             :      type(physics_state), intent(inout) :: state_sc        ! sub-column state
     582             :      type(physics_tend),  intent(inout) :: tend_sc         ! sub-column tend
     583             :      
     584             :      integer, dimension(pcols) :: numsubcol_arr ! To set up the state struct
     585             :      
     586           0 :      numsubcol_arr(:) = 0  ! Start over each chunk
     587           0 :      numsubcol_arr(:state%ngrdcol) = subcol_SILHS_numsubcol ! Only set for valid grid columns
     588           0 :      call subcol_set_subcols(state, tend, numsubcol_arr, state_sc, tend_sc)
     589             :      
     590           0 :    end subroutine init_state_subcol
     591             : !==================================================================!
     592           0 :    subroutine subcol_gen_SILHS(state, tend, state_sc, tend_sc, pbuf)
     593             :       !-------------------------------
     594             :       ! This is where the subcolumns are created, and the call to
     595             :       !      generate_silhs_sample_mod_api
     596             :       !    goes out. Variables needed to make this call are pulled from the 
     597             :       !    pbuf, from module data, and calculated based on the CAM state.
     598             :       !-------------------------------
     599             : 
     600           0 :       use physics_buffer,         only : physics_buffer_desc, pbuf_get_index, &
     601             :                                          pbuf_get_field
     602             :       use time_manager,           only : get_nstep
     603             :       use subcol_utils,           only : subcol_set_subcols, subcol_set_weight
     604             :       use subcol_pack_mod,        only : subcol_pack
     605             :       use phys_control,           only : phys_getopts
     606             :       use spmd_utils,             only : masterproc
     607             :       use shr_const_mod,          only : SHR_CONST_PI, SHR_CONST_RHOFW
     608             : 
     609             : #ifdef CLUBB_SGS
     610             : #ifdef SILHS
     611             :       use clubb_api_module,       only : setup_pdf_parameters_api, &
     612             : 
     613             :                                          zm2zt_api, setup_grid_heights_api, &
     614             : 
     615             :                                          core_rknd, &
     616             : 
     617             :                                          w_tol_sqd, zero_threshold, &
     618             :                                          em_min, cloud_frac_min, & ! rc_tol, &
     619             : 
     620             :                                          genrand_intg, genrand_init_api, &
     621             : 
     622             :                                          nparams, ic_K, &
     623             :                                          read_parameters_api, &
     624             :                                          Cp, Lv, &
     625             :                                          grid, setup_grid_api, &
     626             :                                          init_precip_fracs_api
     627             :    
     628             :       use silhs_api_module, only :       generate_silhs_sample_api, & ! Ncn_to_Nc, &
     629             :                                          clip_transform_silhs_output_api, &
     630             :                                          est_kessler_microphys_api, &
     631             :                                          vert_decorr_coef
     632             : 
     633             : #endif
     634             : #endif
     635             :       
     636             :       ! CAM data structures
     637             :       type(physics_state), intent(inout) :: state
     638             :       type(physics_tend),  intent(inout) :: tend
     639             :       type(physics_state), intent(inout) :: state_sc        ! sub-column state
     640             :       type(physics_tend),  intent(inout) :: tend_sc         ! sub-column tend
     641             :       type(physics_buffer_desc), pointer :: pbuf(:)
     642             : 
     643             : #ifdef CLUBB_SGS
     644             : #ifdef SILHS
     645             :       !----------------
     646             :       ! Local variables
     647             :       !----------------
     648             :       logical, parameter :: &
     649             :                  l_implemented = .true.   ! Implemented in a host model
     650             :       logical, parameter :: rx_Nc = .false. ! Use NC calculated based on grid mean effective radius
     651             :       integer, parameter :: &
     652             :                  grid_type = 3            ! The 3 grid centered on momentum levels
     653             :       real(r8), parameter :: cldmin = 0.001_r8 ! To use when cld frac = 0.0 to be consistant with micro_mg
     654             :       real(r8), parameter :: min_num_conc = 1.0e-12_r8
     655             :       real(r8), parameter :: qsmall = 1.0e-18_r8  ! Microphysics cut-off for cloud
     656             : 
     657             :       integer :: i, j, k, ngrdcol, ncol, lchnk, stncol
     658             :       real(r8) :: sfc_elevation(state%ngrdcol)  ! Surface elevation
     659             :       
     660             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: zt_g, zi_g ! Thermo & Momentum grids for clubb
     661             :       
     662             :       real(r8), dimension(pverp) :: scfrac     ! cloud fraction based on sc distributions
     663             :       real(r8) :: msc, std, maxcldfrac, maxsccldfrac
     664             :       real(r8) :: scale = 1.0_r8
     665             : 
     666             :       real(r8) :: c_K ! CLUBB parameter c_K (for eddy diffusivity)
     667             : 
     668             :       integer( kind = genrand_intg ) :: &
     669             :         lh_seed    ! Seed used in random number generator that will be different
     670             :                    ! for each column, yet reproducible for a restart run
     671             : 
     672             :       !----------------
     673             :       ! Required for set_up_pdf_params_incl_hydromet
     674             :       !----------------
     675             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: cld_frac_in  ! Cloud fraction
     676             :                                     
     677             :       real(r8), dimension(state%ngrdcol, pverp-top_lev+1, pdf_dim, pdf_dim) :: &       
     678             :                           corr_array_1, corr_array_2  ! Correlation matrix for pdf components
     679             :                                     
     680             :       real(r8), dimension(state%ngrdcol, pverp-top_lev+1, pdf_dim) :: &
     681             :                           mu_x_1, mu_x_2, &    ! Mean array for PDF components
     682             :                           sigma_x_1, sigma_x_2 ! Std dev arr for PDF components
     683             :                                     
     684             :       real(r8), dimension(state%ngrdcol, pverp-top_lev+1, pdf_dim, pdf_dim) :: &       
     685             :                           corr_cholesky_mtx_1, corr_cholesky_mtx_2  ! Transposed corr cholesky mtx
     686             :                                     
     687             :       real(r8), dimension(state%ngrdcol, pverp-top_lev+1) :: Nc_in_cloud
     688             :       real(r8), dimension(state%ngrdcol, pverp-top_lev+1) :: ice_supersat_frac_in
     689             :       real(r8), dimension(state%ngrdcol, pverp-top_lev+1, hydromet_dim) :: hydrometp2
     690             : 
     691             : 
     692             :       !----------------
     693             :       ! Input to generate_silhs_sample
     694             :       !----------------
     695             :       integer :: iter                            ! CLUBB iteration 
     696             :       integer :: num_subcols                     ! Number of subcolumns
     697             :       integer, parameter :: sequence_length = 1  ! Number of timesteps btn subcol calls
     698             :       
     699             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: rho_ds_zt    ! Dry static density (kg/m^3) on thermo levs
     700             :       real(r8), dimension(state%ngrdcol,pver)  :: dz_g         ! thickness of layer
     701             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: delta_zm     ! Difference in u wind altitudes
     702             :       
     703             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1,hydromet_dim) :: hydromet  ! Hydrometeor species
     704             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1,hydromet_dim) :: wphydrometp  ! Hydrometeor flux
     705             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1)              :: Ncm ! Mean cloud droplet concentration, <N_c>
     706             : 
     707             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: tke       ! TKE
     708             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: khzm      ! Eddy diffusivity coef
     709             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: Lscale_zm ! CLUBB's length scale on momentum (zm) levels
     710             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: Lscale    ! CLUBB's length scale
     711             : 
     712             :       logical, parameter :: &  
     713             :          l_calc_weights_all_levs = .false. ! .false. if all time steps use the same
     714             :                                           !   weights at all vertical grid levels 
     715             :       logical :: & 
     716             :         l_calc_weights_all_levs_itime, & ! .true. if we calculate sample weights separately at all 
     717             :                                          !    grid levels at the current time step   
     718             :         l_rad_itime                      ! .true. if we calculate radiation at the current time step  
     719             : 
     720             :       !---------------
     721             :       !Output from generate_silhs_sample
     722             :       !--------------
     723             :       real(r8), dimension(state%ngrdcol,subcol_SILHS_numsubcol,pverp-top_lev+1,pdf_dim) :: X_nl_all_levs ! Sample transformed to normal-lognormal
     724             :       real(r8), dimension(state%ngrdcol,subcol_SILHS_numsubcol,pverp-top_lev+1)   :: lh_sample_point_weights ! Subcolumn weights
     725             :       integer, dimension(state%ngrdcol,subcol_SILHS_numsubcol,pverp-top_lev+1)    :: X_mixt_comp_all_levs ! Which Mixture Component
     726             : 
     727             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1, subcol_SILHS_numsubcol) :: &
     728             :                   rc_all_points, & ! Calculate RCM from LH output
     729             :                   rain_all_pts,  & ! Calculate Rain from LH output
     730             :                   nrain_all_pts, & ! Calculate Rain Conc from LH
     731             :                   snow_all_pts,  & ! Calculate Snow from LH output
     732             :                   nsnow_all_pts, & ! Calculate Snow Conc from LH
     733             :                   w_all_points,  & ! Calculate W from LH output
     734             :                   ice_all_pts,   & ! Calculate Cld Ice from LH output
     735             :                   nice_all_pts,  & ! Calculate Num cld ice from LH
     736             :                   nclw_all_pts     ! Calculate Num cld wat from LH
     737             : 
     738             :       !----------------
     739             :       ! Output from clip_transform_silhs_output_api
     740             :       !----------------
     741             :       real( kind = core_rknd ), dimension(state%ngrdcol,subcol_SILHS_numsubcol,pverp-top_lev+1) :: &
     742             :         lh_rt_clipped,  & ! rt generated from silhs sample points
     743             :         lh_thl_clipped, & ! thl generated from silhs sample points
     744             :         lh_rc_clipped,  & ! rc generated from silhs sample points
     745             :         lh_rv_clipped,  & ! rv generated from silhs sample points
     746             :         lh_Nc_clipped     ! Nc generated from silhs sample points
     747             : 
     748             :       logical, parameter :: &
     749             :         l_use_Ncn_to_Nc = .true.  ! Whether to call Ncn_to_Nc (.true.) or not (.false.);
     750             :                                   ! Ncn_to_Nc might cause problems with the MG microphysics 
     751             :                                   ! since the changes made here (Nc-tendency) are not fed into 
     752             :                                   ! the microphysics
     753             :         
     754             : 
     755             :       !----------------
     756             :       ! Output to history
     757             :       !----------------
     758             :       ! V. Larson note: These variables are on the zt (full) levels: why do they
     759             :       ! have dimension pverp?  The pverp level corresponds to the CLUBB
     760             :       ! below-ground level.
     761             :       ! The variables in this paragraph are oriented like CAM variables (k=1 is
     762             :       ! the model top).
     763             :       ! They are flipped versions of CLUBB variables, for the entire chunk.
     764             :       real(r8), dimension(pcols*psubcols, pverp) :: RT_lh_out
     765             :       real(r8), dimension(pcols*psubcols, pverp) :: THL_lh_out
     766             :       real(r8), dimension(pcols*psubcols, pverp) :: OMEGA_lh_out
     767             :       real(r8), dimension(pcols*psubcols, pverp) :: WM_lh_out
     768             :       real(r8), dimension(pcols*psubcols, pverp) :: RVM_lh_out
     769             :       real(r8), dimension(pcols*psubcols, pverp) :: RCM_lh_out
     770             :       real(r8), dimension(pcols*psubcols, pverp) :: NCLW_lh_out
     771             :       real(r8), dimension(pcols*psubcols, pverp) :: ICE_lh_out
     772             :       real(r8), dimension(pcols*psubcols, pverp) :: NICE_lh_out
     773             :       real(r8), dimension(pcols*psubcols, pverp) :: RAIN_lh_out
     774             :       real(r8), dimension(pcols*psubcols, pverp) :: NRAIN_lh_out
     775             :       real(r8), dimension(pcols*psubcols, pverp) :: SNOW_lh_out
     776             :       real(r8), dimension(pcols*psubcols, pverp) :: NSNOW_lh_out
     777             : 
     778             :       real(r8), dimension(state_sc%psetcols) :: weights ! Subcol weights
     779             : 
     780             :       real(r8), dimension(pcols, pver) :: meansc_ice
     781             :       real(r8), dimension(pcols, pver) :: stdsc_ice
     782             : 
     783             :       real(r8), dimension(pcols, pver) :: meansc_liq
     784             :       real(r8), dimension(pcols, pver) :: stdsc_liq
     785             : 
     786             :       real(r8), dimension(pcols, pver) :: meansc_vap
     787             :       real(r8), dimension(pcols, pver) :: stdsc_vap
     788             :       real(r8), dimension(pcols, pver) :: grmn_eff_rad
     789             :       real(r8), dimension(pcols, pver) :: eff_cldfrac
     790             :       real(r8), dimension(pcols, pver) :: precip_frac_out
     791             : 
     792             :       real(r8) :: tmp_mean, diff_mean, rcubed
     793             : 
     794             :       !----------------
     795             :       ! Output from Est_Kessler_microphys
     796             :       !----------------
     797             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: lh_Akm     ! Monte Carlo estimate of Kessler Autoconversion
     798             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: AKm        ! Exact Kessler autoconversion
     799             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: AKstd      ! Exact Stdev of gba Kessler
     800             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: AKstd_cld  ! Exact w/in cloud stdev of gba Kessler
     801             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: AKm_rcm    ! Exact local gba Kessler auto based on rcm
     802             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: AKm_rcc    ! Exact local gba Kessler based on w/in cloud rc
     803             :       real(r8), dimension(state%ngrdcol,pverp-top_lev+1) :: lh_rcm_avg ! LH estimate of grid box avg liquid water
     804             :       real(r8), dimension(pcols,pverp) :: lh_AKm_out, AKm_out
     805             : 
     806             :       !----------------
     807             :       ! Needed to update State
     808             :       !----------------
     809             :       real(r8), dimension(pver)  :: Temp_prof  ! Subcolumn LWPT converted to Abs Temp
     810             :       real(r8), dimension(pver)  :: SE_prof    ! Static Energy calculated from Abs Temp
     811             :       real(r8), dimension(pver)  :: No_cloud = 0.0_r8     ! Clear air condensate profile
     812             :       real(r8), dimension(pcols, pver)  :: invs_exner  ! inverse exner sent to conversion codw
     813             :                                                        ! pcols for output to history
     814             :       real(r8) :: eff_rad_coef = 1.0_r8/(4.0_r8/3.0_r8*SHR_CONST_RHOFW*SHR_CONST_PI)
     815             :      
     816             :       !----------------
     817             :       ! Pointers
     818             :       !----------------
     819             :       real(r8), pointer, dimension(:) :: ztodt_ptr
     820             :       real(r8), pointer, dimension(:,:) :: thlm      ! Mean temperature
     821             :       real(r8), pointer, dimension(:,:) :: ice_supersat_frac ! ice cloud fraction
     822             :       real(r8), pointer, dimension(:,:) :: rtm       ! mean moisture mixing ratio
     823             :       real(r8), pointer, dimension(:,:) :: cld       ! CAM cloud fraction
     824             :       real(r8), pointer, dimension(:,:) :: alst      ! CLUBB liq cloud fraction
     825             :       real(r8), pointer, dimension(:,:) :: qrain     ! micro_mg rain from previous step
     826             :       real(r8), pointer, dimension(:,:) :: qsnow     
     827             :       real(r8), pointer, dimension(:,:) :: nrain     ! micro_mg rain num conc 
     828             :       real(r8), pointer, dimension(:,:) :: nsnow
     829             : 
     830             :       real(r8), pointer, dimension(:,:) :: tke_in    ! TKE
     831             :       real(r8), pointer, dimension(:,:) :: khzm_in   ! Eddy diffusivity coef
     832             :       
     833             :       logical, parameter :: l_est_kessler_microphys = .false.
     834             :       logical, parameter :: l_outfld_subcol         = .false.
     835             :       
     836             :       type(grid) :: gr
     837             :       
     838             :       type(precipitation_fractions) :: precip_fracs      
     839             : 
     840             :       ! Used as shortcuts to avoid typing hm_metadata%iiPDF_xx
     841             :       integer :: &
     842             :         iiPDF_chi, iiPDF_rr, iiPDF_w, iiPDF_Nr, &
     843             :         iiPDF_ri, iiPDF_Ni, iiPDF_Ncn, iiPDF_rs, iiPDF_Ns, &
     844             :         iirr, iiNr, iirs, iiri, &
     845             :         iirg, iiNs, iiNi, iiNg
     846             :       
     847             :       !------------------------------------------------
     848             :       !                     Begin Code
     849             :       !------------------------------------------------
     850             :       
     851             : #ifdef SILHS_OPENACC
     852             :       if ( l_est_kessler_microphys ) then
     853             :         call endrun('subcol_gen error: compilation with OpenACC requires l_est_kessler_microphys = .false.')
     854             :       end if
     855             :       
     856             :       if ( subcol_SILHS_constrainmn ) then
     857             :         call endrun('subcol_gen error: compilation with OpenACC requires subcol_SILHS_constrainmn = .false.')
     858             :       end if
     859             :       
     860             :       if ( subcol_SILHS_weight ) then
     861             :         call endrun('subcol_gen error: Importance sampling is not enabled for SILHS when using OpenACC. Set subcol_SILHS_weight to false.')
     862             :       end if
     863             : #endif
     864             : 
     865             :       if (.not. allocated(state_sc%lat)) then
     866             :          call endrun('subcol_gen error: state_sc must be allocated before calling subcol_gen')
     867             :       end if
     868             :       
     869             :       if( rx_Nc ) then
     870             :          call endrun('subcol_gen_SILHS: rx_Nc not enabled')
     871             :       endif
     872             :       
     873             :       if (subcol_SILHS_meanice) then
     874             :         call endrun('subcol_gen_SILHS: subcol_SILHS_meanice = T not currently available')
     875             :       end if
     876             : 
     877             :       ! Determine num of columns and which chunk we're working on and what timestep
     878             :       ngrdcol = state%ngrdcol
     879             :       ncol = state%ncol
     880             :       lchnk = state%lchnk
     881             :       iter = get_nstep() ! #KTCtodo: The model iteration is passed into SILHS without taking
     882             :                          !           substepping into account. I may need to change this in 
     883             :                          !           the future. Also, why does SILHS need an iter, but CLUBB
     884             :                          !           does not?
     885             :                          ! #ERDBG:   The model iteration number is not used in SILHS unless
     886             :                          !           sequence_length > 1, but nobody runs with that option.
     887             : 
     888             :       ! Copy hm_metadata indices to shortcuts
     889             :       iiPDF_chi = hm_metadata%iiPDF_chi
     890             :       iiPDF_Ncn = hm_metadata%iiPDF_Ncn
     891             :       iiPDF_rr  = hm_metadata%iiPDF_rr
     892             :       iiPDF_w   = hm_metadata%iiPDF_w
     893             :       iiPDF_Nr  = hm_metadata%iiPDF_Nr
     894             :       iiPDF_ri  = hm_metadata%iiPDF_ri
     895             :       iiPDF_Ni  = hm_metadata%iiPDF_Ni
     896             :       iiPDF_rs  = hm_metadata%iiPDF_rs
     897             :       iiPDF_Ns  = hm_metadata%iiPDF_Ns
     898             :       iirr      = hm_metadata%iirr
     899             :       iiNr      = hm_metadata%iiNr
     900             :       iirs      = hm_metadata%iirs
     901             :       iiri      = hm_metadata%iiri
     902             :       iirg      = hm_metadata%iirg
     903             :       iiNs      = hm_metadata%iiNs
     904             :       iiNi      = hm_metadata%iiNi
     905             :       iiNg      = hm_metadata%iiNg
     906             : 
     907             :       !----------------
     908             :       ! Establish associations between pointers and physics buffer fields
     909             :       !----------------
     910             :       call pbuf_get_field(pbuf, thlm_idx, thlm)
     911             :       call pbuf_get_field(pbuf, ztodt_idx, ztodt_ptr)
     912             :       call pbuf_get_field(pbuf, ice_supersat_idx, ice_supersat_frac)
     913             :       call pbuf_get_field(pbuf, rtm_idx, rtm)
     914             :       call pbuf_get_field(pbuf, alst_idx, alst)
     915             :       call pbuf_get_field(pbuf, cld_idx, cld)
     916             :       call pbuf_get_field(pbuf, qrain_idx, qrain)
     917             :       call pbuf_get_field(pbuf, qsnow_idx, qsnow)
     918             :       call pbuf_get_field(pbuf, nrain_idx, nrain)
     919             :       call pbuf_get_field(pbuf, nsnow_idx, nsnow)
     920             :       call pbuf_get_field(pbuf, tke_idx, tke_in)
     921             :       call pbuf_get_field(pbuf, kvh_idx, khzm_in)
     922             : 
     923             :       ! Pull c_K from clubb parameters.
     924             :       c_K = clubb_params_single_col(ic_K)
     925             : 
     926             :       !----------------
     927             :       ! Copy state and populate numbers and values of sub-columns
     928             :       !----------------
     929             :       ztodt = ztodt_ptr(1)
     930             :       num_subcols = subcol_SILHS_numsubcol
     931             : 
     932             :       ! The number of vertical grid levels used in CLUBB is pverp, which is originally
     933             :       ! set in the call to setup_clubb_core_api from subroutine clubb_ini_cam.  This
     934             :       ! is stored in CLUBB in the object gr%nz.  This isn't changed in CLUBB.
     935             :       ! However, when SILHS is used, SILHS only uses pverp - top_lev + 1 vertical grid
     936             :       ! levels and also uses the gr%nz object.  The value of gr%nz needs to be reset
     937             :       ! for SILHS here and then set again for CLUBB in subroutine clubb_tend_cam.
     938             :       gr%nz = pverp - top_lev + 1
     939             :       
     940             :       ! Calculate sample weights separately at all grid levels when
     941             :       ! radiation is not called  
     942             :       l_calc_weights_all_levs_itime = .false. ! subcol_utils cannot compute weighted avgs
     943             :                                               !   when the weights vary with height.   
     944             :                                               !   Don't set to true until this is fixed!!
     945             : 
     946             :          
     947             :       ! Setup the CLUBB vertical grid object. This must be done for each
     948             :       ! column as the z-distance between hybrid pressure levels can 
     949             :       ! change easily.
     950             :       ! Define the CLUBB momentum grid (in height, units of m)
     951             :       do k = 1, pverp-top_lev+1
     952             :         do i = 1, ngrdcol
     953             :           zi_g(i,k) = state%zi(i,pverp-k+1)-state%zi(i,pverp)
     954             :         end do
     955             :       end do
     956             :         
     957             :       
     958             :       ! Define the CLUBB thermodynamic grid (in units of m)
     959             :       do k = 1, pver-top_lev+1
     960             :         do i = 1, ngrdcol
     961             :           zt_g(i,k+1) = state%zm(i,pver-k+1)-state%zi(i,pverp)
     962             :           
     963             :           ! Thermodynamic ghost point is below surface
     964             :           zt_g(i,1) = -1._r8*zt_g(i,2)
     965             :         end do
     966             :       end do
     967             :       
     968             :       do i=1, ncol
     969             :         !  Set the elevation of the surface
     970             :         sfc_elevation(i) = state%zi(i,pver+1)
     971             :       end do
     972             :       
     973             :       !  Heights need to be set at each timestep.
     974             :       call setup_grid_api( pverp+1-top_lev, ncol, sfc_elevation(1:ncol), l_implemented,  & ! intent(in)
     975             :                            grid_type, zi_g(1:ncol,2), zi_g(1:ncol,1), zi_g(1:ncol,pverp+1-top_lev),   & ! intent(in)
     976             :                            zi_g(1:ncol,:), zt_g(1:ncol,:),                              & ! intent(in)
     977             :                            gr )        
     978             :          
     979             :       ! Calculate the distance between grid levels on the host model grid,
     980             :       ! using host model grid indices.
     981             :       do k = top_lev, pver
     982             :         do i = 1, ngrdcol
     983             :           dz_g(i,k) = state%zi(i,k)-state%zi(i,k+1)
     984             :         end do
     985             :       end do
     986             :         
     987             :       ! Inverse delta_zm is required for the 3-level L-scale averaging
     988             :       do k = 1, pver-top_lev+1
     989             :         do i = 1, ngrdcol
     990             :           delta_zm(i,k+1) = state%zi(i,pverp-k)-state%zi(i,pverp-k+1)
     991             :           
     992             :           ! Handle CLUBB sub-sfc ghost point as done in clubb grid_class.F90
     993             :           delta_zm(i,1) = delta_zm(i,2) 
     994             :         end do
     995             :       end do
     996             :        
     997             :       ! Compute dry static density on CLUBB vertical grid
     998             :       do k = 1, pver-top_lev+1
     999             :         do i = 1, ngrdcol
    1000             :           rho_ds_zt(i,k+1) = (rga)*state%pdel(i,pverp-k)/dz_g(i,pverp-k)
    1001             :           
    1002             :           ! CLUBB ghost point under the surface
    1003             :           rho_ds_zt(i,1) = rho_ds_zt(i,2)
    1004             :         end do
    1005             :       end do
    1006             :        
    1007             :       ! Set up hydromet array, flipped from CAM vert grid to CLUBB
    1008             :       if ( iirr > 0 ) then
    1009             :         ! If ixrain and family are greater than zero, then MG2 is
    1010             :         ! being used, and rain and snow are part of state. Otherwise,
    1011             :         ! diagnostic rain and snow from MG1 are used in hydromet.
    1012             :         if (ixrain > 0) then
    1013             :           do k = 1, pver-top_lev+1
    1014             :             do i = 1, ngrdcol
    1015             :               hydromet(i,k+1,iirr) = state%q(i,pver-k+1,ixrain)
    1016             :             end do
    1017             :           end do
    1018             :         else
    1019             :           do k = 1, pver-top_lev+1
    1020             :             do i = 1, ngrdcol
    1021             :               hydromet(i,k+1,iirr) = qrain(i,pver-k+1)
    1022             :             end do
    1023             :           end do
    1024             :         endif
    1025             :       endif
    1026             :       
    1027             :       if ( iiNr > 0 ) then
    1028             :         if (ixnumrain > 0) then
    1029             :           do k = 1, pver-top_lev+1
    1030             :             do i = 1, ngrdcol
    1031             :               hydromet(i,k+1,iiNr) = state%q(i,pver-k+1,ixnumrain)
    1032             :             end do
    1033             :           end do
    1034             :         else
    1035             :           do k = 1, pver-top_lev+1
    1036             :             do i = 1, ngrdcol
    1037             :               hydromet(i,k+1,iiNr) = nrain(i,pver-k+1)
    1038             :             end do
    1039             :           end do
    1040             :         endif
    1041             :       endif
    1042             :           
    1043             :       if ( iirs > 0 ) then
    1044             :         if (ixsnow > 0) then
    1045             :           do k = 1, pver-top_lev+1
    1046             :             do i = 1, ngrdcol
    1047             :               hydromet(i,k+1,iirs) = state%q(i,pver-k+1,ixsnow)
    1048             :             end do
    1049             :           end do
    1050             :         else
    1051             :           do k = 1, pver-top_lev+1
    1052             :             do i = 1, ngrdcol
    1053             :               hydromet(i,k+1,iirs) = qsnow(i,pver-k+1)
    1054             :             end do
    1055             :           end do
    1056             :         endif
    1057             :       endif
    1058             :           
    1059             :       if ( iiNs > 0 ) then
    1060             :         if (ixnumsnow > 0) then
    1061             :           do k = 1, pver-top_lev+1
    1062             :             do i = 1, ngrdcol
    1063             :               hydromet(i,k+1,iiNs) = state%q(i,pver-k+1,ixnumsnow)
    1064             :             end do
    1065             :           end do
    1066             :         else
    1067             :           do k = 1, pver-top_lev+1
    1068             :             do i = 1, ngrdcol
    1069             :               hydromet(i,k+1,iiNs) = nsnow(i,pver-k+1)
    1070             :             end do
    1071             :           end do
    1072             :         endif
    1073             :       endif
    1074             :           
    1075             :       if ( iiri > 0 ) then
    1076             :         do k = 1, pver-top_lev+1
    1077             :           do i = 1, ngrdcol
    1078             :             hydromet(i,k+1,iiri) = state%q(i,pver-k+1,ixcldice)
    1079             :           end do
    1080             :         end do
    1081             :       endif
    1082             :           
    1083             :       if ( iiNi > 0 ) then
    1084             :         do k = 1, pver-top_lev+1
    1085             :           do i = 1, ngrdcol
    1086             :             hydromet(i,k+1,iiNi) = state%q(i,pver-k+1,ixnumice)
    1087             :           end do
    1088             :         end do
    1089             :       endif
    1090             :       
    1091             :       do k = 1, hydromet_dim ! ghost point below the surface
    1092             :         do i = 1, ngrdcol
    1093             :           hydromet(i,1,k) = hydromet(i,2,k)                  
    1094             :         end do
    1095             :       end do
    1096             :    
    1097             :       do k = 1, pver-top_lev+1
    1098             :         do i = 1, ngrdcol
    1099             :           Ncm(i,k+1) = state%q(i,pver-k+1,ixnumliq)
    1100             :           Ncm(i,1) = Ncm(i,2)
    1101             :        end do
    1102             :       end do
    1103             :        
    1104             :       ! Convert from CAM vertical grid to CLUBB
    1105             :       do k = 1, pverp-top_lev+1 
    1106             :         do i = 1, ngrdcol
    1107             :           ice_supersat_frac_in(i,k) = ice_supersat_frac(i,pverp-k+1)
    1108             :         end do
    1109             :       end do
    1110             :         
    1111             :       
    1112             :       do k = 1, pver-top_lev+1
    1113             :         do i = 1, ngrdcol
    1114             :           cld_frac_in(i,k+1) = alst(i,pver-k+1)
    1115             :           cld_frac_in(i,1) = cld_frac_in(i,2) ! Ghost pt below surface
    1116             :         end do
    1117             :       end do
    1118             :         
    1119             :       ! Calculate a clubb-specific exner function
    1120             :       ! (This is grid mean, as pressure levels do not change in 
    1121             :       !  the subcolumn state)
    1122             :       do k = 1, pver-top_lev+1
    1123             :         do i = 1, ngrdcol
    1124             :           invs_exner(i,k) = ((state%pmid(i,k)/p0_clubb)**(cappa))
    1125             :         end do
    1126             :       end do
    1127             :      
    1128             :       ! Call setup_pdf_parameters to get the CLUBB PDF ready for SILHS
    1129             :       ! Compute Num concentration of cloud nuclei
    1130             :       do k = 1, pverp-top_lev+1 
    1131             :         do i = 1, ngrdcol
    1132             :           Nc_in_cloud(i,k) = Ncm(i,k) / max( cld_frac_in(i,k), cloud_frac_min )
    1133             :         end do
    1134             :       end do
    1135             : 
    1136             :       ! The variable wphydrometp is only used when l_calc_w_corr is enabled.
    1137             :       ! The l_calc_w_corr flag is turned off by default, so wphydrometp will
    1138             :       ! simply be set to 0 to simplify matters.
    1139             :       wphydrometp = 0.0_r8
    1140             : 
    1141             :       do k = 1, pverp-top_lev+1
    1142             :         do i = 1, ngrdcol
    1143             :           khzm(i,k) = khzm_in(i,pverp-k+1)
    1144             :         end do
    1145             :       end do
    1146             :       
    1147             :       ! Allocate 2D arrays in precip_fracs for all grid columns and vertical levels
    1148             :       call init_precip_fracs_api( pverp-top_lev+1, ngrdcol, &
    1149             :                                   precip_fracs )
    1150             :        
    1151             :       call setup_pdf_parameters_api( gr, pverp-top_lev+1, ngrdcol, pdf_dim, hydromet_dim, ztodt,  & ! In
    1152             :                                      Nc_in_cloud, cld_frac_in, khzm, &                              ! In
    1153             :                                      ice_supersat_frac_in, hydromet, wphydrometp, &                 ! In
    1154             :                                      corr_array_n_cloud, corr_array_n_below, &                      ! In
    1155             :                                      hm_metadata, &                                                 ! In
    1156             :                                      pdf_params_chnk(lchnk), &                                      ! In
    1157             :                                      clubb_params_single_col, &                                     ! In
    1158             :                                      clubb_config_flags%iiPDF_type, &                               ! In
    1159             :                                      clubb_config_flags%l_use_precip_frac, &                        ! In
    1160             :                                      clubb_config_flags%l_predict_upwp_vpwp, &                      ! In
    1161             :                                      clubb_config_flags%l_diagnose_correlations, &                  ! In
    1162             :                                      clubb_config_flags%l_calc_w_corr, &                            ! In
    1163             :                                      clubb_config_flags%l_const_Nc_in_cloud, &                      ! In
    1164             :                                      clubb_config_flags%l_fix_w_chi_eta_correlations, &             ! In
    1165             :                                      stats_metadata, &                                              ! In
    1166             :                                      stats_zt, stats_zm, stats_sfc, &                               ! In
    1167             :                                      hydrometp2, &                                                  ! Inout
    1168             :                                      mu_x_1, mu_x_2, &                                              ! Out
    1169             :                                      sigma_x_1, sigma_x_2, &                                        ! Out
    1170             :                                      corr_array_1, corr_array_2, &                                  ! Out
    1171             :                                      corr_cholesky_mtx_1, corr_cholesky_mtx_2, &                    ! Out
    1172             :                                      precip_fracs )                                                 ! Inout
    1173             :       
    1174             :       ! In order for Lscale to be used properly, it needs to be passed out of
    1175             :       ! advance_clubb_core, saved to the pbuf, and then pulled out of the
    1176             :       ! pbuf for use here.  The profile of Lscale is passed into subroutine
    1177             :       ! generate_silhs_sample_api for use in calculating the vertical
    1178             :       ! correlation coefficient.  Rather than output Lscale directly, its
    1179             :       ! value can be calculated from other fields that are already output to
    1180             :       ! pbuf.  The equation relating Lscale to eddy diffusivity is:
    1181             :       !
    1182             :       ! Kh = c_K * Lscale * sqrt( TKE ).
    1183             :       !
    1184             :       ! Both Kh and TKE are written to the pbuf, and c_K is easily extracted
    1185             :       ! from CLUBB's tunable parameters.  The equation for Lscale is:
    1186             :       !
    1187             :       ! Lscale = Kh / ( c_K * sqrt( TKE ) ).
    1188             :       !
    1189             :       ! Since Kh and TKE are output on momentum (interface) grid levels, the
    1190             :       ! resulting calculation of Lscale is also found on momentum levels.  It
    1191             :       ! needs to be interpolated back to thermodynamic (midpoint) grid levels
    1192             :       ! for further use.
    1193             :       do k = 1, pverp-top_lev+1
    1194             :         do i = 1, ngrdcol
    1195             :           tke(i,k) = tke_in(i,pverp-k+1)
    1196             :         end do
    1197             :       end do
    1198             :       
    1199             :       do k = 1, pverp-top_lev+1
    1200             :         do i = 1, ngrdcol
    1201             :           Lscale_zm(i,k) = khzm(i,k) / ( c_K * sqrt( max( tke(i,k), em_min ) ) )
    1202             :         end do
    1203             :       end do
    1204             : 
    1205             :       do i = 1, ngrdcol
    1206             :         Lscale(i,1) = Lscale_zm(i,1) + ( Lscale_zm(i,2) - Lscale_zm(i,1) ) &
    1207             :                                      * ( zt_g(i,1) - zi_g(i,1) ) / ( zi_g(i,2) - zi_g(i,1) )
    1208             :       end do
    1209             :      
    1210             :       do k = 2, pverp-top_lev+1
    1211             :         do i = 1, ngrdcol
    1212             :           Lscale(i,k) = Lscale_zm(i,k-1) + ( Lscale_zm(i,k) - Lscale_zm(i,k-1) ) &
    1213             :                                          * ( zt_g(i,k) - zi_g(i,k-1) ) / ( zi_g(i,k) - zi_g(i,k-1) )
    1214             :         end do
    1215             :       end do
    1216             :      
    1217             :       do k = 2, pverp-top_lev+1
    1218             :         do i = 1, ngrdcol
    1219             :           Lscale(i,:) = max( Lscale(i,:), 0.01_r8 )
    1220             :         end do
    1221             :       end do
    1222             :       
    1223             :       !$acc data create( X_mixt_comp_all_levs, X_nl_all_levs, lh_rc_clipped, lh_Nc_clipped, &
    1224             :       !$acc&             lh_sample_point_weights, lh_rt_clipped, lh_rt_clipped, &
    1225             :       !$acc&             lh_rv_clipped, lh_thl_clipped, THL_lh_out, &
    1226             :       !$acc&             RT_lh_out, RCM_lh_out, NCLW_lh_out, ICE_lh_out, &
    1227             :       !$acc&             NICE_lh_out, RVM_lh_out, THL_lh_out, RAIN_lh_out, &
    1228             :       !$acc&             NRAIN_lh_out, SNOW_lh_out, NSNOW_lh_out, WM_lh_out, &
    1229             :       !$acc&             OMEGA_lh_out ) &
    1230             :       !$acc&     copyin( state, state%zm, state%phis, rho_ds_zt, invs_exner ) &
    1231             :       !$acc&     copyout( state%t, state%s, state%omega, state_sc%q )
    1232             :       !$acc& async(1)
    1233             :       
    1234             :       ! Set the seed to the random number generator based on a quantity that
    1235             :       ! will be reproducible for restarts.
    1236             :       lh_seed = int( 1.0e4_r8 * rtm(1,pver), kind = genrand_intg )
    1237             :       
    1238             :       ! Let's generate some subcolumns!!!!!
    1239             :       call generate_silhs_sample_api( &
    1240             :                     iter, pdf_dim, num_subcols, sequence_length, pverp-top_lev+1, ngrdcol, & ! In
    1241             :                     l_calc_weights_all_levs_itime, &                      ! In 
    1242             :                     pdf_params_chnk(lchnk), delta_zm, Lscale, &           ! In
    1243             :                     lh_seed, hm_metadata, &                               ! In
    1244             :                     rho_ds_zt, &                                          ! In 
    1245             :                     mu_x_1, mu_x_2, sigma_x_1, sigma_x_2, &               ! In 
    1246             :                     corr_cholesky_mtx_1, corr_cholesky_mtx_2, &           ! In
    1247             :                     precip_fracs, silhs_config_flags, &                   ! In
    1248             :                     vert_decorr_coef, &                                   ! In
    1249             :                     stats_metadata, &                                     ! In
    1250             :                     stats_lh_zt, stats_lh_sfc, &                          ! InOut
    1251             :                     X_nl_all_levs, X_mixt_comp_all_levs, &                ! Out
    1252             :                     lh_sample_point_weights)                              ! Out
    1253             : 
    1254             :       ! Extract clipped variables from subcolumns
    1255             :       call clip_transform_silhs_output_api( gr, pverp-top_lev+1, ngrdcol, num_subcols, & ! In
    1256             :                                             pdf_dim, hydromet_dim, hm_metadata,        & ! In
    1257             :                                             X_mixt_comp_all_levs,                      & ! In
    1258             :                                             X_nl_all_levs,                             & ! In
    1259             :                                             pdf_params_chnk(lchnk),                    & ! In
    1260             :                                             l_use_Ncn_to_Nc,                           & ! In
    1261             :                                             lh_rt_clipped, lh_thl_clipped,             & ! Out
    1262             :                                             lh_rc_clipped, lh_rv_clipped,              & ! Out
    1263             :                                             lh_Nc_clipped )                              ! Out
    1264             :       !$acc wait
    1265             :        
    1266             :       if ( l_est_kessler_microphys ) then
    1267             :         call endrun('subcol_SILHS: l_est_kessler_microphys = T is not currently supported')
    1268             :       end if
    1269             : 
    1270             :       !-------------------------------------------------------------------------
    1271             :       !            Convert from CLUBB vertical grid to CAM grid
    1272             :       !------------------------------------------------------------------------
    1273             :       ! This kernel is executed in stream 1:
    1274             :       !$acc parallel loop collapse(3) default(present) async(1)
    1275             :       do k = top_lev, pverp
    1276             :         do j = 1, num_subcols
    1277             :           do i = 1, ngrdcol
    1278             :             RT_lh_out(   num_subcols*(i-1)+j,k ) = lh_rt_clipped(i,j,pverp-k+1)
    1279             :             RCM_lh_out(  num_subcols*(i-1)+j,k ) = lh_rc_clipped(i,j,pverp-k+1)
    1280             :             NCLW_lh_out( num_subcols*(i-1)+j,k ) = lh_Nc_clipped(i,j,pverp-k+1)
    1281             :             RVM_lh_out(  num_subcols*(i-1)+j,k ) = lh_rv_clipped(i,j,pverp-k+1)
    1282             :             THL_lh_out(  num_subcols*(i-1)+j,k ) = lh_thl_clipped(i,j,pverp-k+1)
    1283             :           end do          
    1284             :         end do
    1285             :       end do
    1286             :        
    1287             :       ! This kernel is executed in stream 2:
    1288             :       !$acc parallel loop collapse(3) default(present) async(2)
    1289             :       do k = top_lev, pverp
    1290             :         do j = 1, num_subcols
    1291             :           do i = 1, ngrdcol
    1292             :             ICE_lh_out(   num_subcols*(i-1)+j,k ) = X_nl_all_levs(i,j,pverp-k+1,iiPDF_ri)
    1293             :             NICE_lh_out(  num_subcols*(i-1)+j,k ) = X_nl_all_levs(i,j,pverp-k+1,iiPDF_Ni)
    1294             :             RAIN_lh_out(  num_subcols*(i-1)+j,k ) = X_nl_all_levs(i,j,pverp-k+1,iiPDF_rr)
    1295             :             NRAIN_lh_out( num_subcols*(i-1)+j,k ) = X_nl_all_levs(i,j,pverp-k+1,iiPDF_Nr)
    1296             :             SNOW_lh_out(  num_subcols*(i-1)+j,k ) = X_nl_all_levs(i,j,pverp-k+1,iiPDF_rs)
    1297             :             NSNOW_lh_out( num_subcols*(i-1)+j,k ) = X_nl_all_levs(i,j,pverp-k+1,iiPDF_Ns)
    1298             :             WM_lh_out(    num_subcols*(i-1)+j,k ) = X_nl_all_levs(i,j,pverp-k+1,iiPDF_w)
    1299             :           end do          
    1300             :         end do
    1301             :       end do
    1302             :      
    1303             :       ! This kernel is executed in stream 2 because WM_lh_out comes from stream 2:
    1304             :       !$acc parallel loop collapse(3) default(present) async(2)
    1305             :       do k = top_lev, pverp
    1306             :         do j = 1, num_subcols
    1307             :           do i = 1, ngrdcol
    1308             :             OMEGA_lh_out( num_subcols*(i-1)+j,k ) = -1._r8 * WM_lh_out(num_subcols*(i-1)+j,k) &
    1309             :                                                            * rho_ds_zt(i,pverp-k+1) * gravit
    1310             :           end do
    1311             :         end do
    1312             :       end do
    1313             :      
    1314             :       if ( l_est_kessler_microphys ) then
    1315             :         do k = top_lev, pverp
    1316             :           do j = 1, num_subcols
    1317             :             do i = 1, ngrdcol
    1318             :               AKm_out(i,k) = AKm(i,pverp-k+1)
    1319             :               lh_AKm_out(i,k) = lh_AKm(i,pverp-k+1)
    1320             :             end do
    1321             :           end do
    1322             :         end do
    1323             :       end if
    1324             : 
    1325             :       ! Pack up weights
    1326             :       ! Using grid level 2 always won't work if weights vary with height.
    1327             :       call subcol_pack(lchnk, lh_sample_point_weights(:,:,2), weights )
    1328             :       call subcol_set_weight(lchnk, weights)
    1329             :       
    1330             :       ! Constrain the sample distribution of cloud water and ice to the same mean
    1331             :       ! as the grid to prevent negative condensate errors
    1332             :       if(subcol_SILHS_constrainmn) then
    1333             :          
    1334             :         do i = 1, ngrdcol
    1335             :          
    1336             :           stncol = num_subcols*(i-1)
    1337             :            
    1338             :           call subcol_constrainmn( num_subcols, ICE_lh_out(stncol+1:stncol+num_subcols,:), &
    1339             :                                    weights(stncol+1:stncol+num_subcols), &
    1340             :                                    state%q(i,:,ixcldice), meansc_ice(i,:), stdsc_ice(i,:) )
    1341             :           if ( ixrain > 0 ) &
    1342             :           call subcol_constrainmn( num_subcols, RAIN_lh_out(stncol+1:stncol+num_subcols,:), &
    1343             :                                    weights(stncol+1:stncol+num_subcols), &
    1344             :                                    state%q(i,:,ixrain) )
    1345             :           if ( ixsnow > 0 ) &
    1346             :           call subcol_constrainmn( num_subcols, SNOW_lh_out(stncol+1:stncol+num_subcols,:), &
    1347             :                                    weights(stncol+1:stncol+num_subcols), &
    1348             :                                    state%q(i,:,ixsnow) )
    1349             :           call subcol_constrainmn( num_subcols, RCM_lh_out(stncol+1:stncol+num_subcols,:), &
    1350             :                                    weights(stncol+1:stncol+num_subcols), &
    1351             :                                    state%q(i,:,ixcldliq), meansc_liq(i,:), stdsc_liq(i,:) )
    1352             :           call subcol_constrainmn( num_subcols, RVM_lh_out(stncol+1:stncol+num_subcols,:), &
    1353             :                                    weights(stncol+1:stncol+num_subcols), &
    1354             :                                    state%q(i,:,ixq), meansc_vap(i,:), stdsc_vap(i,:) )
    1355             :           call subcol_constrainmn( num_subcols, NICE_lh_out(stncol+1:stncol+num_subcols,:), &
    1356             :                                    weights(stncol+1:stncol+num_subcols), &
    1357             :                                    state%q(i,:,ixnumice) )
    1358             :           if ( ixnumrain > 0 ) &
    1359             :           call subcol_constrainmn( num_subcols, NRAIN_lh_out(stncol+1:stncol+num_subcols,:), &
    1360             :                                    weights(stncol+1:stncol+num_subcols), &
    1361             :                                    state%q(i,:,ixnumrain) )
    1362             :           if ( ixnumsnow > 0 ) &
    1363             :           call subcol_constrainmn( num_subcols, NSNOW_lh_out(stncol+1:stncol+num_subcols,:), &
    1364             :                                    weights(stncol+1:stncol+num_subcols), &
    1365             :                                    state%q(i,:,ixnumsnow) )
    1366             :           call subcol_constrainmn( num_subcols, NCLW_lh_out(stncol+1:stncol+num_subcols,:), &
    1367             :                                    weights(stncol+1:stncol+num_subcols), &
    1368             :                                    state%q(i,:,ixnumliq) )
    1369             :           do k = top_lev, pver
    1370             :             ! Look for exceptionally large values of condensate
    1371             :             if(ANY(ICE_lh_out(stncol+1:stncol+num_subcols,k) .gt. 0.01_r8)) then
    1372             :               ! Clip the large values
    1373             :               where(ICE_lh_out(stncol+1:stncol+num_subcols,k) .gt. 0.01_r8)
    1374             :                  ICE_lh_out(stncol+1:stncol+num_subcols,k) = 0.01_r8
    1375             :                  NICE_lh_out(stncol+1:stncol+num_subcols,k) = 1.5e+7_r8
    1376             :               end where
    1377             :               ! Recalculate the weighted subcolumn mean
    1378             :               tmp_mean = meansc( ICE_lh_out( stncol+1:stncol+num_subcols, k ), & 
    1379             :                                      weights(stncol+1:stncol+num_subcols), &
    1380             :                                      real(num_subcols,r8) )
    1381             :               ! Calculate the difference between the weighted mean and grid mean
    1382             :               diff_mean = state%q(i,k,ixcldice)-tmp_mean
    1383             :               ! Add the difference to each subcolumn
    1384             :               ICE_lh_out(stncol+1:stncol+num_subcols,k) = &
    1385             :                  ICE_lh_out(stncol+1:stncol+num_subcols,k)+diff_mean
    1386             :               ! Recalculate the weight subcolumn mean for ice num conc
    1387             :               tmp_mean = meansc( NICE_lh_out( stncol+1:stncol+num_subcols, k ), & 
    1388             :                                      weights(stncol+1:stncol+num_subcols), &
    1389             :                                      real(num_subcols,r8) )
    1390             :               ! Calculate the difference between the weighted mean and grid mean
    1391             :               diff_mean = state%q(i,k,ixnumice)-tmp_mean
    1392             :               ! Add the difference to each subcolumn
    1393             :               if(diff_mean.gt.0.0_r8) then
    1394             :                  NICE_lh_out(stncol+1:stncol+num_subcols,k) = &
    1395             :                      NICE_lh_out(stncol+1:stncol+num_subcols,k)+diff_mean
    1396             :               else ! just use the grid mean in each subcolumn
    1397             :                  NICE_lh_out(stncol+1:stncol+num_subcols,k) = &
    1398             :                      state%q(i,k,ixnumice)
    1399             :               end if
    1400             :               ! Test adjusted means for debugging
    1401             :               tmp_mean = meansc( ICE_lh_out( stncol+1:stncol+num_subcols, k ), & 
    1402             :                                      weights(stncol+1:stncol+num_subcols), &
    1403             :                                      real(num_subcols,r8) )
    1404             :               diff_mean = state%q(i,k,ixcldice)-tmp_mean
    1405             :               tmp_mean = meansc( NICE_lh_out( stncol+1:stncol+num_subcols, k ), & 
    1406             :                                      weights(stncol+1:stncol+num_subcols), &
    1407             :                                      real(num_subcols,r8) )
    1408             :               diff_mean = state%q(i,k,ixnumice)-tmp_mean
    1409             :             endif
    1410             :           end do ! k = top_lev, pver
    1411             :         end do
    1412             :       endif ! subcol_silhs_constrainm
    1413             :       
    1414             :       
    1415             :       !---------------------------------------------------
    1416             :       !            Updating state variables
    1417             :       !---------------------------------------------------
    1418             :       ! Code to update the state variables for interactive runs
    1419             :       ! This kernel is executed in stream 3, but waits for stream 1
    1420             :       ! because THL_lh_out and RCM_lh_out come from stream 1:
    1421             :       !$acc parallel loop collapse(3) default(present) wait(1) async(3)
    1422             :       do k = 1, pver-top_lev+1
    1423             :         do j = 1, num_subcols
    1424             :           do i = 1, ngrdcol
    1425             :               
    1426             :             state_sc%t(num_subcols*(i-1)+j,k) = THL_lh_out(num_subcols*(i-1)+j,k) * invs_exner(i,k) &
    1427             :                                                 + Lv * RCM_lh_out(num_subcols*(i-1)+j,k) / Cp
    1428             :             
    1429             :             state_sc%s(num_subcols*(i-1)+j,k) = cpair * state_sc%t(num_subcols*(i-1)+j,k) &
    1430             :                                                 + gravit * state%zm(i,k) + state%phis(i)
    1431             :           end do
    1432             :         end do
    1433             :       end do
    1434             :       
    1435             :       ! This kernel is executed in stream 4, but waits for stream 1 and 2
    1436             :       ! because RVM_lh_out is from stream 1 and OMEGA_lh_out is from stream 2:
    1437             :       !$acc parallel loop collapse(3) default(present) wait(1,2) async(4)
    1438             :       do k = 1, pver-top_lev+1
    1439             :         do j = 1, num_subcols
    1440             :           do i = 1, ngrdcol
    1441             :             ! Vertical Velocity is not part of the energy conservation checks, but
    1442             :             ! we need to be careful here, because the SILHS output VV is noisy.
    1443             :             state_sc%omega(num_subcols*(i-1)+j,k) = OMEGA_lh_out(num_subcols*(i-1)+j,k)
    1444             :             state_sc%q(num_subcols*(i-1)+j,k,ixq) = RVM_lh_out(num_subcols*(i-1)+j,k) 
    1445             :           end do
    1446             :         end do
    1447             :       end do
    1448             : 
    1449             :         
    1450             :       if (subcol_SILHS_q_to_micro) then ! Send SILHS predicted constituents to microp
    1451             :          
    1452             :         ! This kernel is executed in stream 5, but waits for stream 1 and 2
    1453             :         ! because RCM_lh_out is from stream 1 and ICE_lh_out is from stream 2:
    1454             :         !$acc parallel loop collapse(3) default(present) wait(1,2) async(5)
    1455             :         do k = 1, pver-top_lev+1
    1456             :           do j = 1, num_subcols
    1457             :             do i = 1, ngrdcol
    1458             :               state_sc%q(num_subcols*(i-1)+j,k,ixcldliq) = RCM_lh_out(num_subcols*(i-1)+j,k)
    1459             :               state_sc%q(num_subcols*(i-1)+j,k,ixcldice) = ICE_lh_out(num_subcols*(i-1)+j,k)
    1460             :             end do
    1461             :           end do
    1462             :         end do
    1463             :         
    1464             :         if (ixrain > 0) then
    1465             :           ! This kernel is executed in stream 6, but waits for stream 2
    1466             :           ! because RAIN_lh_out is from stream 2:
    1467             :           !$acc parallel loop collapse(3) default(present) wait(2) async(6)
    1468             :           do k = 1, pver-top_lev+1
    1469             :             do j = 1, num_subcols
    1470             :               do i = 1, ngrdcol
    1471             :                 state_sc%q(num_subcols*(i-1)+j,k,ixrain) = RAIN_lh_out(num_subcols*(i-1)+j,k)
    1472             :               end do
    1473             :             end do
    1474             :           end do
    1475             :         end if
    1476             :         
    1477             :         if (ixsnow > 0) then
    1478             :           ! This kernel is executed in stream 7, but waits for stream 2
    1479             :           ! because SNOW_lh_out is from stream 2:
    1480             :           !$acc parallel loop collapse(3) default(present) wait(2) async(7)
    1481             :           do k = 1, pver-top_lev+1
    1482             :             do j = 1, num_subcols
    1483             :               do i = 1, ngrdcol
    1484             :                 state_sc%q(num_subcols*(i-1)+j,k,ixsnow) = SNOW_lh_out(num_subcols*(i-1)+j,k)
    1485             :               end do
    1486             :             end do
    1487             :           end do
    1488             :         end if
    1489             :           
    1490             :       else   
    1491             :          
    1492             :         do k = 1, pver-top_lev+1
    1493             :           do j = 1, num_subcols
    1494             :             do i = 1, ngrdcol
    1495             :               state_sc%q(num_subcols*(i-1)+j,k,ixcldliq) = state%q(i,k,ixcldliq)
    1496             :               state_sc%q(num_subcols*(i-1)+j,k,ixcldice) = state%q(i,k,ixcldice)
    1497             :               if (ixrain > 0) then
    1498             :                  state_sc%q(num_subcols*(i-1)+j,k,ixrain) = state%q(i,k,ixrain)
    1499             :               end if
    1500             :               if (ixsnow > 0) then
    1501             :                  state_sc%q(num_subcols*(i-1)+j,k,ixsnow) = state%q(i,k,ixsnow)
    1502             :               end if
    1503             :             end do
    1504             :           end do
    1505             :         end do
    1506             :        
    1507             :       endif
    1508             :        
    1509             :       if (subcol_SILHS_n_to_micro) then ! Send SILHS predicted number conc to microp
    1510             :         
    1511             :         ! This kernel is executed in stream 8, but waits for stream 1 and 2
    1512             :         ! because NCLW_lh_out is from stream 1 and NICE_lh_out is from stream 2:
    1513             :         !$acc parallel loop collapse(3) default(present) wait(1,2) async(8)
    1514             :         do k = 1, pver-top_lev+1
    1515             :           do j = 1, num_subcols
    1516             :             do i = 1, ngrdcol
    1517             :               state_sc%q(num_subcols*(i-1)+j,k,ixnumice) = NICE_lh_out(num_subcols*(i-1)+j,k)
    1518             :               state_sc%q(num_subcols*(i-1)+j,k,ixnumliq) = NCLW_lh_out(num_subcols*(i-1)+j,k)
    1519             :             end do
    1520             :           end do
    1521             :         end do
    1522             :         
    1523             :         if (ixnumrain > 0) then
    1524             :           ! This kernel is executed in stream 9, but waits for stream 2
    1525             :           ! because NRAIN_lh_out is from stream 2:
    1526             :           !$acc parallel loop collapse(3) default(present) wait(2) async(9)
    1527             :           do k = 1, pver-top_lev+1
    1528             :             do j = 1, num_subcols
    1529             :               do i = 1, ngrdcol
    1530             :                 state_sc%q(num_subcols*(i-1)+j,k,ixnumrain) = NRAIN_lh_out(num_subcols*(i-1)+j,k)
    1531             :               end do
    1532             :             end do
    1533             :           end do
    1534             :         end if
    1535             :         
    1536             :         if (ixnumsnow > 0) then
    1537             :           ! This kernel is executed in stream 10, but waits for stream 2
    1538             :           ! because NSNOW_lh_out is from stream 2:
    1539             :           !$acc parallel loop collapse(3) default(present) wait(2) async(10)
    1540             :           do k = 1, pver-top_lev+1
    1541             :             do j = 1, num_subcols
    1542             :               do i = 1, ngrdcol
    1543             :                 state_sc%q(num_subcols*(i-1)+j,k,ixnumsnow) = NSNOW_lh_out(num_subcols*(i-1)+j,k)
    1544             :               end do
    1545             :             end do
    1546             :           end do
    1547             :         end if
    1548             :        
    1549             :       else     
    1550             :        
    1551             :         do k = 1, pver-top_lev+1
    1552             :           do j = 1, num_subcols
    1553             :             do i = 1, ngrdcol
    1554             :               state_sc%q(num_subcols*(i-1)+j,k,ixnumliq) = state%q(i,k,ixnumliq)
    1555             :               state_sc%q(num_subcols*(i-1)+j,k,ixnumice) = state%q(i,k,ixnumice)
    1556             :               if (ixnumrain > 0) then
    1557             :                  state_sc%q(num_subcols*(i-1)+j,k,ixnumrain) = state%q(i,k,ixnumrain)
    1558             :               end if
    1559             :               if (ixnumsnow > 0) then
    1560             :                  state_sc%q(num_subcols*(i-1)+j,k,ixnumsnow) = state%q(i,k,ixnumsnow)
    1561             :               end if
    1562             :             end do
    1563             :           end do
    1564             :         end do
    1565             :          
    1566             :       endif
    1567             :       
    1568             :       ! This kernel is executed in stream 8, because state_sc%q(:,:,ixnumliq) and
    1569             :       !  state_sc%q(:,:,ixnumice) are from stream 8
    1570             :       !$acc parallel loop collapse(3) default(present) async(8)
    1571             :       do k = 1, pver-top_lev+1
    1572             :         do j = 1, num_subcols
    1573             :           do i = 1, ngrdcol
    1574             :             ! Change liq and ice (and rain and snow) num conc zeros to min values (1e-12)
    1575             :             if (state_sc%q(num_subcols*(i-1)+j,k,ixnumliq) .lt. min_num_conc) then
    1576             :                 state_sc%q(num_subcols*(i-1)+j,k,ixnumliq) = min_num_conc
    1577             :             end if
    1578             :             
    1579             :             if (state_sc%q(num_subcols*(i-1)+j,k,ixnumice) .lt. min_num_conc) then
    1580             :                 state_sc%q(num_subcols*(i-1)+j,k,ixnumice) = min_num_conc
    1581             :             end if
    1582             :           end do
    1583             :         end do
    1584             :       end do
    1585             :         
    1586             :       if (ixnumrain > 0) then
    1587             :         ! This kernel is executed in stream 9, because state_sc%q(:,:,ixnumrain) is
    1588             :         ! from stream 9
    1589             :         !$acc parallel loop collapse(3) default(present) async(9)
    1590             :         do k = 1, pver-top_lev+1
    1591             :           do j = 1, num_subcols   
    1592             :             do i = 1, ngrdcol   
    1593             :                if(state_sc%q(num_subcols*(i-1)+j,k,ixnumrain) .lt. min_num_conc) then
    1594             :                   state_sc%q(num_subcols*(i-1)+j,k,ixnumrain) = min_num_conc
    1595             :                end if
    1596             :             end do
    1597             :           end do
    1598             :         end do
    1599             :       endif
    1600             :         
    1601             :       if (ixnumsnow > 0) then
    1602             :         ! This kernel is executed in stream 10, because state_sc%q(:,:,ixnumsnow) is
    1603             :         ! from stream 10
    1604             :         !$acc parallel loop collapse(3) default(present) async(10)
    1605             :         do k = 1, pver-top_lev+1
    1606             :           do j = 1, num_subcols     
    1607             :             do i = 1, ngrdcol
    1608             :               if(state_sc%q(num_subcols*(i-1)+j,k,ixnumsnow) .lt. min_num_conc) then
    1609             :                  state_sc%q(num_subcols*(i-1)+j,k,ixnumsnow) = min_num_conc
    1610             :               end if
    1611             :             end do
    1612             :           end do
    1613             :         end do
    1614             :       endif
    1615             : 
    1616             :       if ( l_outfld_subcol ) then
    1617             :         
    1618             :         do k = 1, pver-top_lev+1
    1619             :           do i = 1, ngrdcol
    1620             :             do j = 1, num_subcols
    1621             :                
    1622             :               ! Calc effective cloud fraction for testing
    1623             :               if ( ( lh_rc_clipped(i,j,pverp-k+1) .gt. qsmall ) &
    1624             :                      .or. ( X_nl_all_levs(i,j,pverp-k+1,iiPDF_ri) .gt. qsmall ) ) then
    1625             :                  eff_cldfrac(i,k) = eff_cldfrac(i,k) + lh_sample_point_weights(i,j,pverp-k+1)
    1626             :               else 
    1627             :                 eff_cldfrac(i,k) = 0.0_r8
    1628             :               endif
    1629             :                 
    1630             :              end do 
    1631             :              
    1632             :              eff_cldfrac(i,k) = eff_cldfrac(i,k)/real(num_subcols, kind=r8)
    1633             :              
    1634             :           end do
    1635             :         end do
    1636             :         
    1637             :         ! Pack precip_frac for output
    1638             :         do k = 2, pverp-top_lev+1
    1639             :           do i = 1, ngrdcol
    1640             :             precip_frac_out(i,pver-k+2) = precip_fracs%precip_frac(i,k)
    1641             :           end do
    1642             :         end do
    1643             :         
    1644             :         call outfld( 'SILHS_THLM_SCOL', THL_lh_out, pcols*psubcols, lchnk )
    1645             :         call outfld( 'SILHS_RT_SCOL', RT_lh_out, pcols*psubcols, lchnk )
    1646             :         call outfld( 'SILHS_OMEGA_SCOL', OMEGA_lh_out, pcols*psubcols, lchnk )
    1647             :         call outfld( 'SILHS_WM_SCOL', WM_lh_out, pcols*psubcols, lchnk )
    1648             :         call outfld( 'SILHS_RCM_SCOL', RCM_lh_out, pcols*psubcols, lchnk )
    1649             :         call outfld( 'SILHS_RICLD_SCOL', ICE_lh_out, pcols*psubcols, lchnk )
    1650             :         call outfld( 'SILHS_NICLD_SCOL', NICE_lh_out, pcols*psubcols, lchnk )
    1651             :         call outfld( 'SILHS_NCLD_SCOL', NCLW_lh_out, pcols*psubcols, lchnk )
    1652             :         call outfld( 'SILHS_RRAIN_SCOL', RAIN_lh_out, pcols*psubcols, lchnk )
    1653             :         call outfld( 'SILHS_NRAIN_SCOL', NRAIN_lh_out, pcols*psubcols, lchnk )
    1654             :         call outfld( 'SILHS_WEIGHT_SCOL', weights, pcols*psubcols, lchnk )
    1655             :         call outfld( 'NR_IN_LH', nrain, pcols, lchnk )
    1656             :         call outfld( 'SILHS_RTM', rtm, pcols, lchnk )
    1657             :         call outfld( 'SILHS_THLM', thlm, pcols, lchnk )
    1658             :         call outfld( 'SILHS_QC_IN', state%q(:,:,ixcldliq), pcols, lchnk )
    1659             :         call outfld( 'SILHS_QI_IN', state%q(:,:,ixcldice), pcols, lchnk )
    1660             :         call outfld( 'SILHS_NC_IN', state%q(:,:,ixnumliq), pcols, lchnk )
    1661             :         call outfld( 'SILHS_NI_IN', state%q(:,:,ixnumice), pcols, lchnk )
    1662             :         if ( l_est_kessler_microphys ) then
    1663             :           call outfld( 'AKM_CLUBB', AKm_out, pcols, lchnk )
    1664             :           call outfld( 'AKM_LH_CLUBB', lh_AKm_out, pcols, lchnk )
    1665             :         end if
    1666             :         call outfld( 'INVS_EXNER', invs_exner, pcols, lchnk )
    1667             :         call outfld( 'SILHS_ZTODT', ztodt_ptr, pcols, lchnk )
    1668             :         if ( subcol_SILHS_constrainmn ) then
    1669             :           call outfld( 'SILHS_MSC_CLDICE', meansc_ice, pcols, lchnk )
    1670             :           call outfld( 'SILHS_STDSC_CLDICE', stdsc_ice, pcols, lchnk )
    1671             :           if ( ixsnow > 0 ) then
    1672             :             call outfld( 'SILHS_MSC_CLDLIQ', meansc_liq, pcols, lchnk )
    1673             :             call outfld( 'SILHS_STDSC_CLDLIQ', stdsc_liq, pcols, lchnk )
    1674             :             call outfld( 'SILHS_MSC_Q', meansc_vap, pcols, lchnk )
    1675             :             call outfld( 'SILHS_STDSC_Q', stdsc_vap, pcols, lchnk )
    1676             :           endif ! ixsnow > 0
    1677             :         endif ! subcol_SILHS_constrainmn
    1678             :         call outfld( 'SILHS_EFF_CLDFRAC', eff_cldfrac, pcols, lchnk )
    1679             :         call outfld( 'SILHS_CLUBB_PRECIP_FRAC', precip_frac_out, pcols, lchnk )
    1680             :         call outfld( 'SILHS_CLUBB_ICE_SS_FRAC', ice_supersat_frac, pcols, lchnk )
    1681             :       end if
    1682             :       
    1683             :       !$acc end data
    1684             :       !$acc wait
    1685             : 
    1686             : #endif
    1687             : #endif
    1688           0 :    end subroutine subcol_gen_SILHS
    1689             : 
    1690           0 :    subroutine subcol_ptend_avg_SILHS(ptend_sc, ngrdcol, lchnk, ptend)
    1691           0 :       use physics_buffer,   only: physics_buffer_desc
    1692             :       use subcol_utils,     only: subcol_ptend_get_firstsubcol, subcol_ptend_avg_shr, &
    1693             :                                   subcol_get_weight, subcol_get_filter, &
    1694             :                                   is_filter_set, is_weight_set
    1695             : 
    1696             :       !-----------------------------------
    1697             :       ! Average the subcolumns dimension (pcols*psubcols) to the grid dimension (pcols)
    1698             :       !-----------------------------------
    1699             : 
    1700             :       type(physics_ptend), intent(in)             :: ptend_sc        ! intent in
    1701             :       integer,  intent(in)                        :: ngrdcol       ! # grid cols
    1702             :       integer,  intent(in)                        :: lchnk         ! chunk index
    1703             :       type(physics_ptend), intent(inout)          :: ptend
    1704             :       ! Because we can't get a state passed in here, we might have to use values from the 
    1705             :       ! subcolumn generation. This would make any conservation checks invalid if this
    1706             :       ! function is called after another parameterization... hmm.
    1707             : 
    1708           0 :        call subcol_ptend_avg_shr(ptend_sc, ngrdcol, lchnk, ptend, is_filter_set(), is_weight_set())
    1709             : 
    1710           0 :    end subroutine subcol_ptend_avg_SILHS
    1711             : 
    1712           0 :    subroutine subcol_SILHS_var_covar_driver &
    1713             :               ( ztodt, state_sc, ptend_sc, &
    1714             :                 pbuf )
    1715             : 
    1716             :      ! This subroutine calculates microphysical effects on five variances and
    1717             :      ! covariances: rtp2, thlp2, wprtp, wpthlp, and rtpthlp.
    1718             :      !
    1719             :      ! This code is experimental!!
    1720             : 
    1721           0 :      use physics_buffer,          only: physics_buffer_desc, pbuf_get_index, pbuf_get_field
    1722             : #ifdef CLUBB_SGS
    1723             : #ifdef SILHS
    1724             :      use subcol_utils,            only: subcol_get_weight
    1725             :      use subcol_pack_mod,         only: subcol_unpack, subcol_get_nsubcol
    1726             :      use clubb_api_module,        only: T_in_K2thlm_api, &
    1727             :                                         init_pdf_params_api, &
    1728             :                                         copy_multi_pdf_params_to_single,&
    1729             :                                         pdf_parameter
    1730             :      use silhs_api_module,        only: lh_microphys_var_covar_driver_api
    1731             : #endif
    1732             : #endif
    1733             : 
    1734             :      implicit none
    1735             : 
    1736             :      ! Parameters
    1737             :      !  This fill value is set to catch errors; it should not be read.
    1738             :      real(r8), parameter                   :: fillvalue = -999._r8
    1739             : 
    1740             :      ! Input Variables
    1741             :      real(r8), intent(in)                  :: ztodt        ! model time increment
    1742             :      type(physics_state), intent(in)       :: state_sc     ! state for sub-columns
    1743             :      type(physics_ptend), intent(in)       :: ptend_sc     ! ptend for sub-columns
    1744             : 
    1745             :      ! Pointers
    1746             :      type(physics_buffer_desc), pointer    :: pbuf(:)
    1747             : 
    1748             : #ifdef CLUBB_SGS
    1749             : #ifdef SILHS
    1750             :      ! Local Variables
    1751             :      integer :: lchnk, ngrdcol, igrdcol, isubcol, ns, k
    1752             :      integer, dimension(pcols) :: nsubcol
    1753             :      real(r8), dimension(pcols*psubcols)       :: weights_packed
    1754             :      real(r8), dimension(pcols,psubcols)       :: weights
    1755             :      real(r8), dimension(pcols,psubcols,pverp) :: rc_all, rv_all, rt_all, w_all, thl_all
    1756             :      real(r8), dimension(pcols,psubcols,pver ) :: s_all, t_all, zm_all, omega_all, pmid_all
    1757             :      real(r8), dimension(pcols,psubcols)       :: phis_all
    1758             :      real(r8), dimension(pcols,psubcols,pver ) :: stend, ttend
    1759             :      real(r8), dimension(pcols,psubcols,pverp) :: thltend, qctend, qvtend
    1760             : 
    1761             :      real(r8), dimension(pcols,psubcols,pver)  :: dz_g, pdel_all, rho
    1762             :      real(r8), dimension(pcols,psubcols,pverp) :: zi_all
    1763             :  
    1764             :      real(r8), dimension(pcols,psubcols,pver ) :: exner
    1765             : 
    1766             :      ! Inputs to lh_microphys_var_covar_driver
    1767             :      real(r8), dimension(pcols,psubcols,pverp) :: rt_all_clubb, thl_all_clubb, w_all_clubb, &
    1768             :                                                   qctend_clubb, qvtend_clubb, thltend_clubb
    1769             :      real(r8), dimension(pcols,psubcols,pverp-top_lev+1) :: height_depndt_weights
    1770             : 
    1771             :      ! Outputs from lh_microphys_var_covar_driver
    1772             :      real(r8), dimension(:,:), pointer :: rtp2_mc_zt, thlp2_mc_zt, wprtp_mc_zt, &
    1773             :                                           wpthlp_mc_zt, rtpthlp_mc_zt
    1774             : 
    1775             :      ! pbuf indices
    1776             :      integer :: &
    1777             :        rtp2_mc_zt_idx,    &
    1778             :        thlp2_mc_zt_idx,   &
    1779             :        wprtp_mc_zt_idx,   &
    1780             :        wpthlp_mc_zt_idx,  &
    1781             :        rtpthlp_mc_zt_idx
    1782             :        
    1783             :      type(pdf_parameter) :: pdf_params_single_col
    1784             : 
    1785             :      !----- Begin Code -----
    1786             :      
    1787             :      call init_pdf_params_api( pverp+1-top_lev, 1, pdf_params_single_col )
    1788             : 
    1789             :      ! Don't do anything if this option isn't enabled.
    1790             :      if ( .not. subcol_SILHS_var_covar_src ) return
    1791             : 
    1792             :      lchnk = state_sc%lchnk
    1793             :      ngrdcol  = state_sc%ngrdcol
    1794             : 
    1795             :      ! Obtain indices
    1796             :      rtp2_mc_zt_idx = pbuf_get_index('rtp2_mc_zt')
    1797             :      thlp2_mc_zt_idx = pbuf_get_index('thlp2_mc_zt')
    1798             :      wprtp_mc_zt_idx = pbuf_get_index('wprtp_mc_zt')
    1799             :      wpthlp_mc_zt_idx = pbuf_get_index('wpthlp_mc_zt')
    1800             :      rtpthlp_mc_zt_idx = pbuf_get_index('rtpthlp_mc_zt')
    1801             : 
    1802             :      ! Obtain pbuf fields for output
    1803             :      call pbuf_get_field(pbuf, rtp2_mc_zt_idx, rtp2_mc_zt)
    1804             :      call pbuf_get_field(pbuf, thlp2_mc_zt_idx, thlp2_mc_zt)
    1805             :      call pbuf_get_field(pbuf, wprtp_mc_zt_idx, wprtp_mc_zt)
    1806             :      call pbuf_get_field(pbuf, wpthlp_mc_zt_idx, wpthlp_mc_zt)
    1807             :      call pbuf_get_field(pbuf, rtpthlp_mc_zt_idx, rtpthlp_mc_zt)
    1808             : 
    1809             :      ! Unpack needed tendencies from subcolumn ptends
    1810             :      call subcol_unpack(lchnk, ptend_sc%s(:,:), stend, fillvalue)
    1811             :      call subcol_unpack(lchnk, ptend_sc%q(:,:,ixcldliq), qctend(:,:,1:pver), fillvalue)
    1812             :      call subcol_unpack(lchnk, ptend_sc%q(:,:,ixq), qvtend(:,:,1:pver), fillvalue)
    1813             : 
    1814             :      ! Unpack sample point values from subcolumn states
    1815             :      call subcol_unpack(lchnk, state_sc%q(:,:,ixcldliq), rc_all(:,:,1:pver), fillvalue)
    1816             :      call subcol_unpack(lchnk, state_sc%q(:,:,ixq),      rv_all(:,:,1:pver), fillvalue)
    1817             :      call subcol_unpack(lchnk, state_sc%omega(:,:),      omega_all (:,:,:),  fillvalue)
    1818             :      call subcol_unpack(lchnk, state_sc%s(:,:),          s_all,              fillvalue)
    1819             :      call subcol_unpack(lchnk, state_sc%zm,              zm_all,             fillvalue)
    1820             :      call subcol_unpack(lchnk, state_sc%phis,            phis_all,           fillvalue)
    1821             :      call subcol_unpack(lchnk, state_sc%zi,              zi_all,             fillvalue)
    1822             :      call subcol_unpack(lchnk, state_sc%pdel,            pdel_all,           fillvalue)
    1823             :      call subcol_unpack(lchnk, state_sc%pmid,            pmid_all,           fillvalue)
    1824             : 
    1825             :      ! Initialize fields to fillvalue.
    1826             :      rt_all  = fillvalue
    1827             :      thl_all = fillvalue
    1828             :      w_all   = fillvalue
    1829             :      qctend  = fillvalue
    1830             :      qvtend  = fillvalue
    1831             :      thltend = fillvalue
    1832             : 
    1833             :      ! How many subcolumns in each column?
    1834             :      call subcol_get_nsubcol(lchnk, nsubcol)
    1835             : 
    1836             :      do igrdcol = 1, ngrdcol
    1837             :         do isubcol = 1, nsubcol(igrdcol)
    1838             : 
    1839             :            rt_all(igrdcol,isubcol,top_lev:pver) = rc_all(igrdcol,isubcol,top_lev:pver) &
    1840             :                                                   + rv_all(igrdcol,isubcol,top_lev:pver)
    1841             : 
    1842             :            ! Compute dry static density on CLUBB vertical grid
    1843             :            do k = top_lev, pver
    1844             :               dz_g(igrdcol,isubcol,k) = zi_all(igrdcol,isubcol,k) - zi_all(igrdcol,isubcol,k+1) ! thickness
    1845             :               rho(igrdcol,isubcol,k) = (rga)*pdel_all(igrdcol,isubcol,k)/dz_g(igrdcol,isubcol,k)
    1846             :            end do
    1847             : 
    1848             :            ! Compute w from omega
    1849             :            w_all(igrdcol,isubcol,top_lev:pver) = -omega_all(igrdcol,isubcol,top_lev:pver) &
    1850             :                                                   / ( rho(igrdcol,isubcol,top_lev:pver) * gravit )
    1851             : 
    1852             :            ! Convert stend and s_all to ttend and t_all
    1853             :            !  Note 1: With subcolumns, cpair is truly a constant (I think).
    1854             :            !  Note 2: For tendencies, the extra terns zm and phis should
    1855             :            !          not be included in the calculation.
    1856             :            ttend(igrdcol,isubcol,top_lev:pver) = stend(igrdcol,isubcol,top_lev:pver) / cpair
    1857             : 
    1858             :            do k = top_lev, pver
    1859             :               t_all(igrdcol,isubcol,k) = ( s_all(igrdcol,isubcol,k) &
    1860             :                                            - gravit * zm_all(igrdcol,isubcol,k) &
    1861             :                                            - phis_all(igrdcol,isubcol) ) / cpair
    1862             :            end do ! k = 1, pver
    1863             : 
    1864             :            ! This formula is taken from earlier in this file.
    1865             :            exner(igrdcol,isubcol,top_lev:pver) &
    1866             :            = ( pmid_all(igrdcol,isubcol,top_lev:pver) / p0_clubb )**(rair/cpair)
    1867             : 
    1868             :            ! Note: all tendencies or all means should be used in the call to
    1869             :            !       T_in_K2thlm_api (with the exception of exner)
    1870             :            do k = top_lev, pver
    1871             :               thltend(igrdcol,isubcol,k) &
    1872             :               = T_in_K2thlm_api( ttend(igrdcol,isubcol,k), exner(igrdcol,isubcol,k), &
    1873             :                                  qctend(igrdcol,isubcol,k) )
    1874             :               thl_all(igrdcol,isubcol,k) &
    1875             :               = T_in_K2thlm_api( t_all(igrdcol,isubcol,k), exner(igrdcol,isubcol,k), &
    1876             :                                  rc_all(igrdcol,isubcol,k) )
    1877             :            end do ! k = 1, pver
    1878             : 
    1879             :            ! Add ghost points
    1880             :            rt_all (igrdcol,isubcol,pverp) = rt_all (igrdcol,isubcol,pver)
    1881             :            thl_all(igrdcol,isubcol,pverp) = thl_all(igrdcol,isubcol,pver)
    1882             :            w_all  (igrdcol,isubcol,pverp) = w_all  (igrdcol,isubcol,pver)
    1883             :            qctend (igrdcol,isubcol,pverp) = qctend (igrdcol,isubcol,pver)
    1884             :            qvtend (igrdcol,isubcol,pverp) = qvtend (igrdcol,isubcol,pver)
    1885             :            thltend(igrdcol,isubcol,pverp) = thltend(igrdcol,isubcol,pver)
    1886             : 
    1887             :            ! Flip inputs to CLUBB's grid. Note the dimension ordering change.
    1888             :            rt_all_clubb(igrdcol,isubcol,1:pverp) = clubb_flip_grid( rt_all(igrdcol,isubcol,1:pverp) )
    1889             :            thl_all_clubb(igrdcol,isubcol,1:pverp) = clubb_flip_grid( thl_all(igrdcol,isubcol,1:pverp) )
    1890             :            w_all_clubb(igrdcol,isubcol,1:pverp) = clubb_flip_grid( w_all(igrdcol,isubcol,1:pverp) )
    1891             :            qctend_clubb(igrdcol,isubcol,1:pverp) = clubb_flip_grid( qctend(igrdcol,isubcol,1:pverp) )
    1892             :            qvtend_clubb(igrdcol,isubcol,1:pverp) = clubb_flip_grid( qvtend(igrdcol,isubcol,1:pverp) )
    1893             :            thltend_clubb(igrdcol,isubcol,1:pverp) = clubb_flip_grid( thltend(igrdcol,isubcol,1:pverp) )
    1894             : 
    1895             :         end do ! isubcol = 1, nsubcol(igrdcol)
    1896             :      end do ! igrdcol = 1, ngrdcol
    1897             : 
    1898             :      ! Obtain weights
    1899             :      call subcol_get_weight(lchnk, weights_packed)
    1900             :      call subcol_unpack(lchnk, weights_packed, weights, fillvalue)
    1901             : 
    1902             :      ! Call lh_microphys_var_covar_driver for each column
    1903             :      do igrdcol=1, ngrdcol
    1904             :        ns = nsubcol(igrdcol)
    1905             : 
    1906             :        ! This code assumes that the weights are height independent.
    1907             :        ! It will have to change once the weights vary with altitude!
    1908             :        ! I'm not sure whether the grid will need to be flipped.
    1909             :        do k = 1, pverp-top_lev+1
    1910             :           height_depndt_weights(igrdcol,1:ns,k) = weights(igrdcol,1:ns)
    1911             :        end do
    1912             : 
    1913             :        ! Copy the igrdcol column from the multicolumn pdf_params_chnk to the single column 
    1914             :        ! version of pdf_params_single_col since lh_microphys_var_covar_driver_api only
    1915             :        ! works over 1 column currently
    1916             :        call copy_multi_pdf_params_to_single( pdf_params_chnk(lchnk), igrdcol, &
    1917             :                                              pdf_params_single_col )
    1918             : 
    1919             :        ! Make the call!!!!!
    1920             :        call lh_microphys_var_covar_driver_api &
    1921             :             ( pverp-top_lev+1, ns, ztodt, height_depndt_weights(igrdcol,1:ns,1:pverp-top_lev+1), &
    1922             :               pdf_params_single_col, &
    1923             :               rt_all_clubb(igrdcol,1:ns,1:pverp-top_lev+1), thl_all_clubb(igrdcol,1:ns,1:pverp-top_lev+1), &
    1924             :               w_all_clubb(igrdcol,1:ns,1:pverp-top_lev+1), qctend_clubb(igrdcol,1:ns,1:pverp-top_lev+1), &
    1925             :               qvtend_clubb(igrdcol,1:ns,1:pverp-top_lev+1), thltend_clubb(igrdcol,1:ns,1:pverp-top_lev+1), &
    1926             :               silhs_config_flags%l_lh_instant_var_covar_src, &
    1927             :               rtp2_mc_zt(igrdcol,1:pverp-top_lev+1), thlp2_mc_zt(igrdcol,1:pverp-top_lev+1), &
    1928             :               wprtp_mc_zt(igrdcol,1:pverp-top_lev+1), wpthlp_mc_zt(igrdcol,1:pverp-top_lev+1), &
    1929             :               rtpthlp_mc_zt(igrdcol,1:pverp-top_lev+1) )
    1930             : 
    1931             :        ! The *_mc_zt microphysics tendencies are passed out of SILHS and back
    1932             :        ! to CLUBB without being used at all in the rest of the host model code.
    1933             :        ! The arrays aren't flipped for the *_mc_zt microphysics tendencies, and
    1934             :        ! they don't need to be.
    1935             : 
    1936             :        ! CLUBB used pverp vertical levels, but SILHS only uses
    1937             :        ! pverp - top_lev + 1 vertical levels.
    1938             :        ! Fill the upper levels with 0s when necessary.
    1939             :        if ( pverp > pverp-top_lev+1 ) then
    1940             :           rtp2_mc_zt(igrdcol,pverp-top_lev+2:pverp) = 0.0_r8
    1941             :           thlp2_mc_zt(igrdcol,pverp-top_lev+2:pverp) = 0.0_r8
    1942             :           wprtp_mc_zt(igrdcol,pverp-top_lev+2:pverp) = 0.0_r8
    1943             :           wpthlp_mc_zt(igrdcol,pverp-top_lev+2:pverp) = 0.0_r8
    1944             :           rtpthlp_mc_zt(igrdcol,pverp-top_lev+2:pverp) = 0.0_r8
    1945             :        endif ! pverp > pverp-top_lev+1
    1946             : 
    1947             :      end do ! igrdcol = 1, ngrdcol
    1948             : #endif
    1949             : #endif
    1950             : 
    1951           0 :      return
    1952           0 :    end subroutine subcol_SILHS_var_covar_driver
    1953             : #ifdef SILHS
    1954             :    real(r8) function meansc(arr_in, w_in, ns) result(val)
    1955             :       real(r8), intent(in) :: ns                         ! Length of Array
    1956             :       real(r8), dimension(int(ns)), intent(in) :: arr_in      ! Input array
    1957             :       real(r8), dimension(int(ns)), intent(in) :: w_in        ! Weights
    1958             :       real(r8) :: acc  ! accumulator
    1959             :       integer :: i
    1960             :       acc = 0
    1961             :       val = 0
    1962             :       do i=1,ns
    1963             :          acc = acc + arr_in(i)*w_in(i)
    1964             :       end do
    1965             :       val = acc/ns
    1966             :    end function
    1967             : 
    1968             :    real(r8) function stdsc(arr_in, w_in, mn_in, ns) result(val)
    1969             :       real(r8), intent(in) :: ns  ! Number of elements (subcolumns)
    1970             :       real(r8), dimension(int(ns)), intent(in) :: arr_in, w_in  !Input array and weights
    1971             :       real(r8), intent(in) :: mn_in   ! The mean of arr_in
    1972             :       real(r8) :: accvar, var
    1973             :       integer :: i
    1974             :       accvar = 0
    1975             :       do i=1,ns
    1976             :          accvar = accvar + ((arr_in(i)-mn_in)**2)*w_in(i)
    1977             :       end do
    1978             :       var = accvar/ns
    1979             :       val = sqrt(var)
    1980             :    end function
    1981             : 
    1982             :    subroutine THL_profile(nz, ABST_prof, ex_prof, rcm_prof, THL_prof)
    1983             : 
    1984             :       use clubb_api_module,              only : T_in_K2thlm_api
    1985             : 
    1986             :       integer,                 intent(in)  :: nz         ! Num vert levels
    1987             :       real(r8), dimension(nz), intent(in)  :: ABST_prof  ! Abs Temp prof
    1988             :       real(r8), dimension(nz), intent(in)  :: ex_prof    ! Profile of Exner func
    1989             :       real(r8), dimension(nz), intent(in)  :: rcm_prof   ! Profile of Cld Wat MR
    1990             :       real(r8), dimension(nz), intent(out) :: THL_prof  ! LWPT prof
    1991             :       integer :: i
    1992             :  
    1993             :       do i=1,nz
    1994             :          THL_prof(i) = T_in_K2thlm_api(ABST_prof(i), ex_prof(i), rcm_prof(i))
    1995             :       end do
    1996             :       
    1997             :    end subroutine
    1998             : 
    1999             :    subroutine subcol_constrainmn( num_subcols, samples, weights, grid_mean, mean_sc, std_sc )
    2000             : 
    2001             :       ! Input/Output Variables
    2002             :       integer, intent(in) :: num_subcols
    2003             :       real(r8), dimension(num_subcols, pverp), intent(inout) :: samples
    2004             :       real(r8), dimension(num_subcols), intent(in) :: weights
    2005             :       real(r8), dimension(pverp), intent(in) :: grid_mean
    2006             :       real(r8), dimension(pver), intent(out), optional :: mean_sc, std_sc
    2007             : 
    2008             :       ! Local Variables
    2009             :       real(r8) :: meansc_loc, adj_rat
    2010             :       integer :: k
    2011             :    !------------------------------------------------------------------
    2012             :       !----- Begin Code -----
    2013             :       do k=1, pver
    2014             :          meansc_loc = meansc( samples(:,k), weights(:), real(num_subcols, r8) )
    2015             : 
    2016             :          if (present(mean_sc)) &
    2017             :             mean_sc(k) = meansc_loc
    2018             :          if (present(std_sc)) &
    2019             :             std_sc(k) = stdsc( samples(:,k), weights(:), meansc_loc, &
    2020             :                                real(num_subcols, r8) )
    2021             : 
    2022             :          if ( meansc_loc > 0.0_r8 ) then
    2023             :             adj_rat = grid_mean(k)/meansc_loc
    2024             :          else 
    2025             :             ! If the mean is zero, then zero out all subcolumns to avoid
    2026             :             ! negative samples
    2027             :             adj_rat = 0.0_r8
    2028             :          end if
    2029             :          samples(:,k) = samples(:,k) * adj_rat
    2030             :       end do
    2031             :    end subroutine subcol_constrainmn
    2032             : 
    2033             :    ! =============================================================================== !
    2034             :    !                                                                                 !
    2035             :    ! =============================================================================== !
    2036             :    function clubb_flip_grid ( profile ) result( profile_flipped )
    2037             : 
    2038             :      ! Description:
    2039             :      !   Swaps the elements in profile so they are in reverse order. CAM and
    2040             :      !   CLUBB's grids are flipped with respect to each other.
    2041             :      !
    2042             :      !   Usage:
    2043             :      !     clubb_var = clubb_flip_grid( cam_var )
    2044             :      !     cam_var   = clubb_flip_grid( clubb_var )
    2045             : 
    2046             :      implicit none
    2047             : 
    2048             :      ! Input Variable
    2049             :      real(r8), dimension(pverp), intent(in) :: profile
    2050             : 
    2051             :      ! Output Variable
    2052             :      real(r8), dimension(pverp) :: profile_flipped
    2053             : 
    2054             :      ! Local Variable
    2055             :      integer :: k
    2056             : 
    2057             :      do k=1, pverp
    2058             :        profile_flipped(k) = profile(pverp-k+1)
    2059             :      end do ! k=1, pverp
    2060             : 
    2061             :      return
    2062             :    end function clubb_flip_grid
    2063             :    ! =============================================================================== !
    2064             :    !                                                                                 !
    2065             :    ! =============================================================================== !
    2066             : #endif
    2067             :    !============================================================================
    2068           0 :    subroutine subcol_SILHS_fill_holes_conserv( state, dt, ptend, pbuf )
    2069             : 
    2070             :      ! The William F. Buckley Jr. Conservative Hole Filler.
    2071             : 
    2072             :      ! Description:
    2073             :      ! Stops holes from forming in a hydrometeor mixing ratio by reducing the
    2074             :      ! microphysics tendency of that hydrometeor mixing ratio which would
    2075             :      ! otherwise cause that hydrometeor mixing ratio to have a negative value
    2076             :      ! once the microphysics tendency is applied.  This code is used to prevent
    2077             :      ! holes in water mass, not number concentration.
    2078             :      !
    2079             :      ! This subroutine is called after microphysics has completed and after
    2080             :      ! microphysics fields from subcolumns have been averaged back to grid
    2081             :      ! columns, but before the grid-column microphysics tendencies have been
    2082             :      ! applied in physics_update.  This code is meant for use with the SILHS
    2083             :      ! subcolumn approach.  This code needs to be applied to grid columns, not
    2084             :      ! subcolumns.
    2085             :      !
    2086             :      ! This code adjusts the tendencies (ptend) before they are used to update
    2087             :      ! the grid mean fields (state variables).
    2088             :      !
    2089             :      ! The column-integrated total water needs to be conserved during
    2090             :      ! microphysics.  The conserved amount includes the amount of water that
    2091             :      ! precipitated to the ground from sedimentation during microphysics.
    2092             :      ! The conservation equation for each grid column is:
    2093             :      !
    2094             :      ! SUM(k=top_lev:pver) ( rv_start(k) + rc_start(k) + rr_start(k)
    2095             :      !                       + ri_start(k) + rs_start(k) ) * pdel(k) / g
    2096             :      ! = SUM(k=top_lev:pver) ( rv(k) + rc(k) + rr(k) + ri(k) + rs(k) )
    2097             :      !                       * pdel(k) / g
    2098             :      !   + prect * dt * 1000;
    2099             :      !
    2100             :      ! where rv_start, rc_start, rr_start, ri_start, and rs_start are water
    2101             :      ! vapor, cloud water, rain water, cloud ice, and snow mixing ratios before
    2102             :      ! microphysics is called; rv, rc, rr, ri, and rs are water vapor, cloud
    2103             :      ! water, rain water, cloud ice, and snow mixing ratios after being updated
    2104             :      ! by microphysics; pdel is the pressure difference between vertical levels,
    2105             :      ! g is gravity, and prect * dt * 1000 is the total amount of water (from
    2106             :      ! all precipitating hydrometeors) that sedimented to the ground during
    2107             :      ! microphysics (dt is the timestep used for microphysics).  The units of
    2108             :      ! column-integrated total water are kg (water) / m^2.
    2109             :      !
    2110             :      ! All the updated hydrometeor fields are related to the hydrometeor fields
    2111             :      ! at the start by:
    2112             :      !
    2113             :      ! rv(k) = rv_start(k) + rv_tend(k) * dt;
    2114             :      ! rc(k) = rc_start(k) + rc_tend(k) * dt;
    2115             :      ! rr(k) = rr_start(k) + rr_tend(k) * dt;
    2116             :      ! ri(k) = ri_start(k) + ri_tend(k) * dt; and
    2117             :      ! rs(k) = rs_start(k) + rs_tend(k) * dt;
    2118             :      !
    2119             :      ! where rv_tend, rc_tend, rr_tend, ri_tend, and rs_tend are water vapor,
    2120             :      ! cloud water, rain water, cloud ice, and snow mixing ratio tendencies
    2121             :      ! from microphysics, which includes the sum of microphysics process rates
    2122             :      ! and sedimentation.  When these equations are applied to the equation
    2123             :      ! for column-integrated total water, that equation becomes:
    2124             :      !
    2125             :      ! SUM(k=top_lev:pver) ( rv_tend(k) + rc_tend(k) + rr_tend(k)
    2126             :      !                       + ri_tend(k) + rs_tend(k) ) * dt * pdel(k) / g
    2127             :      ! + prect * dt * 1000 = 0.
    2128             :      !
    2129             :      ! As stated above, the hydrometeor tendencies are the sum of tendencies
    2130             :      ! from microphysics process rates and tendencies from sedimentation:
    2131             :      !
    2132             :      ! rv_tend(k) = rv_mc_tend(k);
    2133             :      ! rc_tend(k) = rc_mc_tend(k) + rc_sed_tend(k);
    2134             :      ! rr_tend(k) = rr_mc_tend(k) + rr_sed_tend(k);
    2135             :      ! ri_tend(k) = ri_mc_tend(k) + ri_sed_tend(k); and
    2136             :      ! rs_tend(k) = rs_mc_tend(k) + rs_sed_tend(k);
    2137             :      !
    2138             :      ! where rv_mc_tend, rc_mc_tend, rr_mc_tend, ri_mc_tend, and rs_mc_tend are
    2139             :      ! the tendencies of water vapor, cloud water, rain water, cloud ice, and
    2140             :      ! snow from microphysics process rates, and rc_sed_tend, rr_sed_tend,
    2141             :      ! ri_sed_tend, and rs_sed_tend are the tendencies of cloud water,
    2142             :      ! rain water, cloud ice, and snow from sedimentation.  When these equations
    2143             :      ! are applied to the equation for column-integrated total water, that
    2144             :      ! equation becomes:
    2145             :      !
    2146             :      ! SUM(k=top_lev:pver) ( rv_mc_tend(k) + rc_mc_tend(k) + rr_mc_tend(k)
    2147             :      !                       + ri_mc_tend(k) + rs_mc_tend(k) )
    2148             :      !                     * dt * pdel(k) / g
    2149             :      ! + SUM(k=top_lev:pver) ( rc_sed_tend(k) + rr_sed_tend(k) + ri_sed_tend(k)
    2150             :      !                         + rs_sed_tend(k) ) * dt * pdel(k) / g
    2151             :      ! + prect * dt * 1000 = 0.
    2152             :      !
    2153             :      ! At any vertical level, the tendencies from microphysics process rates
    2154             :      ! (mc_tend variables) must balance:
    2155             :      !
    2156             :      ! rv_mc_tend(k) + rc_mc_tend(k) + rr_mc_tend(k)
    2157             :      ! + ri_mc_tend(k) + rs_mc_tend(k) = 0; for all k from top_lev to pver.
    2158             :      !
    2159             :      ! The column-integrated total water equation can be applied to
    2160             :      ! sedimentation:
    2161             :      !
    2162             :      ! SUM(k=top_lev:pver) ( rc_sed_tend(k) + rr_sed_tend(k) + ri_sed_tend(k)
    2163             :      !                       + rs_sed_tend(k) ) * dt * pdel(k) / g
    2164             :      ! + prect * dt * 1000 = 0.
    2165             :      !
    2166             :      ! The total precipitation rate, prect, can be split into liquid
    2167             :      ! precipitation rate, precl, and frozen precipitation rate, preci:
    2168             :      !
    2169             :      ! prect = precl + preci.
    2170             :      !
    2171             :      ! The microphysics code outputs prect and preci, so precl can be calculated
    2172             :      ! by precl = prect - preci.  The column-integrated total water equation can
    2173             :      ! be split into:
    2174             :      !
    2175             :      ! SUM(k=top_lev:pver) ( rc_sed_tend(k) + rr_sed_tend(k) )
    2176             :      !                     * dt * pdel(k) / g
    2177             :      ! + precl * dt * 1000 = 0; and
    2178             :      !
    2179             :      ! SUM(k=top_lev:pver) ( ri_sed_tend(k) + rs_sed_tend(k) )
    2180             :      !                     * dt * pdel(k) / g
    2181             :      ! + preci * dt * 1000 = 0.
    2182             :      !
    2183             :      ! Overall, the conservation methods used in this subroutine are:
    2184             :      !
    2185             :      ! 1) When adjusting the tendencies from microphysics process rates,
    2186             :      !    conserve:
    2187             :      !
    2188             :      !    rv_mc_tend(k) + rc_mc_tend(k) + rr_mc_tend(k)
    2189             :      !    + ri_mc_tend(k) + rs_mc_tend(k) = 0; for all k from top_lev to pver.
    2190             :      !
    2191             :      ! 2) When adjusting the tendencies from microphysics process rates, adjust
    2192             :      !    dry static energy appropriately.  The change in dry static energy
    2193             :      !    is necessary because of phase changes.  This "puts back" the extra dry
    2194             :      !    static energy that was "taken out" when an excessive phase-changing
    2195             :      !    process rate was produced by microphysics.
    2196             :      !
    2197             :      ! 3) When adjusting the hydrometeor tendency from sedimentation of a
    2198             :      !    liquid hydrometeor (cloud water or rain water), conserve:
    2199             :      !
    2200             :      !    SUM(k=top_lev:pver) ( rc_sed_tend(k) + rr_sed_tend(k) )
    2201             :      !                        * dt * pdel(k) / g
    2202             :      !    + precl * dt * 1000 = 0.
    2203             :      !
    2204             :      ! 4) When adjusting the hydrometeor tendency from sedimentation of a
    2205             :      !    frozen hydrometeor (cloud ice or snow), conserve:
    2206             :      !
    2207             :      !    SUM(k=top_lev:pver) ( ri_sed_tend(k) + rs_sed_tend(k) )
    2208             :      !                        * dt * pdel(k) / g
    2209             :      !    + preci * dt * 1000 = 0.
    2210             :      !
    2211             :      ! The conservative hole filler works as follows.  The total microphysics
    2212             :      ! tendency for each hydrometeor is provided in ptend.  This is the sum of
    2213             :      ! the microphysics process rate tendency and sedimentation tendency for
    2214             :      ! each hydrometeor.  The sedimentation tendency is provided in pbuf.  The
    2215             :      ! sedimentation tendency is subtracted off the total microphysics tendency
    2216             :      ! to produce the microphysics process rate tendency for each hydrometeor.
    2217             :      ! The microphysics process rate tendency is adjusted when necessary so that
    2218             :      ! holes in the hydrometeor are not produced by microphysics process rates.
    2219             :      ! When a hydrometeor's negative microphysics process rate tendency needs to
    2220             :      ! be made smaller in magnitude to avoid a hole, all hydrometeor tendencies
    2221             :      ! that are positive at that grid level are also decreased proportionately
    2222             :      ! to maintain a balance.  Dry static energy tendency is also adjusted
    2223             :      ! appropriately when necessary.  After this, the vertical integral of each
    2224             :      ! hydrometeor species is greater than or equal to 0.
    2225             :      !
    2226             :      ! The sedimentation tendency is then added back onto the new microphysics
    2227             :      ! process rate tendency to produce a new total microphysics tendency for
    2228             :      ! each hydrometeor.  Since the sedimentation tendency was based on the old
    2229             :      ! value of hydrometeor, before the hole-filling adjustment, it is possible
    2230             :      ! that the new total microphysics tendency may produce holes.  When this
    2231             :      ! happens, sedimentation hole filling fills holes in the vertical profile
    2232             :      ! of each hydrometeor.  Holes are filled using mass from other vertical
    2233             :      ! levels for the same hydrometeor (or from a same-phase hydrometeor when
    2234             :      ! necessary).  Since the vertical integral of sedimentation tendency
    2235             :      ! (including surface precipitation rate) is 0, the vertical integral of the
    2236             :      ! hydrometeor must be greater than or equal to 0, which means that all
    2237             :      ! holes can be filled.  The result is that all holes in any hydrometeor
    2238             :      ! mixing ratio are filled completely and conservatively.  The value of
    2239             :      ! ptend is updated appropriately so that it can be applied later in
    2240             :      ! physics_update.
    2241             : 
    2242             :      !----------------------------------------------------------------------
    2243             : 
    2244           0 :      use physics_buffer, only: &
    2245             :          physics_buffer_desc, &
    2246             :          pbuf_get_field
    2247             : 
    2248             :      use ppgrid, only: &
    2249             :          pcols
    2250             : 
    2251             :      use constituents, only: &
    2252             :          qmin
    2253             : 
    2254             :      use ref_pres, only: &
    2255             :          top_lev => trop_cloud_top_lev
    2256             : 
    2257             :      implicit none
    2258             : 
    2259             :      ! Input Variables
    2260             :      type(physics_state), intent(in) :: state     ! Physics state variables
    2261             :      real(r8), intent(in) :: dt                   ! Time step duration
    2262             : 
    2263             :      ! Input/Output Variables
    2264             :      type(physics_ptend),  intent(inout) :: ptend  ! Parameterization tendencies
    2265             :      type(physics_buffer_desc), pointer :: pbuf(:) ! Physics buffer
    2266             : 
    2267             :      ! Local Variables
    2268             :      real(r8), dimension(pcols,pver) :: &
    2269             :        rv_start, & ! Water vapor mixing ratio at start of microphysics  [kg/kg]
    2270             :        rc_start, & ! Cloud water mixing ratio at start of microphysics  [kg/kg]
    2271             :        rr_start, & ! Rain water mixing ratio at start of microphysics   [kg/kg]
    2272             :        ri_start, & ! Cloud ice mixing ratio at start of microphysics    [kg/kg]
    2273             :        rs_start    ! Snow mixing ratio at start of microphysics         [kg/kg]
    2274             : 
    2275             :      real(r8), dimension(pcols,pver) :: &
    2276             :        rv_tend, & ! Water vapor mixing ratio tendency  [kg/kg/s]
    2277             :        rc_tend, & ! Cloud water mixing ratio tendency  [kg/kg/s]
    2278             :        rr_tend, & ! Rain water mixing ratio tendency   [kg/kg/s]
    2279             :        ri_tend, & ! Cloud ice mixing ratio tendency    [kg/kg/s]
    2280             :        rs_tend, & ! Snow mixing ratio tendency         [kg/kg/s]
    2281             :        stend      ! Dry static energy tendency         [J/kg/s]
    2282             : 
    2283             :      real(r8), dimension(:), pointer :: &
    2284           0 :        prect,    & ! Total microphysics precipitation rate (surface)      [m/s]
    2285           0 :        preci,    & ! Ice-phase microphysics precipitation rate (surface)  [m/s]
    2286           0 :        prec_str, & ! Total surface precipitation rate from stratoform     [m/s]
    2287           0 :        snow_str    ! Snow surface precipitation rate from stratoform      [m/s]
    2288             : 
    2289             :      real(r8), dimension(:,:), pointer :: &
    2290           0 :        rc_sed_tend, & ! Mean cloud water sedimentation tendency        [kg/kg/s]
    2291           0 :        rr_sed_tend, & ! Mean rain water sedimentation tendency         [kg/kg/s]
    2292           0 :        ri_sed_tend, & ! Mean cloud ice sedimentation tendency          [kg/kg/s]
    2293           0 :        rs_sed_tend, & ! Mean snow sedimentation tendency               [kg/kg/s]
    2294           0 :        vtrmc,       & ! Mean cloud water sedimentation velocity        [m/s]
    2295           0 :        umr,         & ! Mean rain water sedimentation velocity         [m/s]
    2296           0 :        vtrmi,       & ! Mean cloud ice sedimentation velocity          [m/s]
    2297           0 :        ums,         & ! Mean snow sedimentation velocity               [m/s]
    2298           0 :        rc_sed_evap, & ! Mean evap of cloud water during sedimentation  [kg/kg/s]
    2299           0 :        ri_sed_subl    ! Mean subl of cloud ice during sedimentation    [kg/kg/s]
    2300             : 
    2301             :      real(r8), dimension(pcols,pver) :: &
    2302             :        rv_mc_tend, & ! Water vapor mixing ratio microphysics tendency  [kg/kg/s]
    2303             :        rc_mc_tend, & ! Cloud water mixing ratio microphysics tendency  [kg/kg/s]
    2304             :        rr_mc_tend, & ! Rain water mixing ratio microphysics tendency   [kg/kg/s]
    2305             :        ri_mc_tend, & ! Cloud ice mixing ratio microphysics tendency    [kg/kg/s]
    2306             :        rs_mc_tend    ! Snow mixing ratio microphysics tendency         [kg/kg/s]
    2307             : 
    2308             :      real(r8) :: &
    2309             :        rv_curr, & ! Current water vapor mixing ratio    [kg/kg]
    2310             :        rc_curr, & ! Current cloud water mixing ratio    [kg/kg]
    2311             :        rr_curr, & ! Current rain water mixing ratio     [kg/kg]
    2312             :        ri_curr, & ! Current cloud ice mixing ratio      [kg/kg]
    2313             :        rs_curr    ! Current snow mixing ratio           [kg/kg]
    2314             : 
    2315             :      logical :: &
    2316             :        l_pos_rv_mc_tend, & ! Flag for positive water vapor mixing ratio mc tend.
    2317             :        l_pos_rc_mc_tend, & ! Flag for positive cloud water mixing ratio mc tend.
    2318             :        l_pos_rr_mc_tend, & ! Flag for positive rain water mixing ratio mc tend.
    2319             :        l_pos_ri_mc_tend, & ! Flag for positive cloud ice mixing ratio mc tend.
    2320             :        l_pos_rs_mc_tend    ! Flag for positive snow mixing ratio mc tend.
    2321             : 
    2322             :      real(r8) :: &
    2323             :        mc_tend_max_mag,     & ! Max. allowable mag. of (neg.) mc tend [kg/kg/s]
    2324             :        mc_tend_correction,  & ! Amnt. correction necessary to mc tend [kg/kg/s]
    2325             :        total_mc_positive,   & ! Total of all positive mc tendencies   [kg/kg/s]
    2326             :        mc_correction_ratio    ! Ratio: mc_tend_correction/total_mc_positive [-]
    2327             : 
    2328             :      real(r8), dimension(pcols) :: &
    2329             :        precl    ! Liquid-phase precipitation rate (surface)        [m/s]
    2330             : 
    2331             :      ! Budgeting terms for hole filling.
    2332             :      ! These variables are for use in stats output.
    2333             :      real(r8), dimension(pcols,pver) :: &
    2334             :        rv_hf_tend, & ! Water vapor mixing ratio hole-filling tendency  [kg/kg/s]
    2335             :        rc_hf_tend, & ! Cloud water mixing ratio hole-filling tendency  [kg/kg/s]
    2336             :        rr_hf_tend, & ! Rain water mixing ratio hole-filling tendency   [kg/kg/s]
    2337             :        ri_hf_tend, & ! Cloud ice mixing ratio hole-filling tendency    [kg/kg/s]
    2338             :        rs_hf_tend, & ! Snow mixing ratio hole-filling tendency         [kg/kg/s]
    2339             :        s_hf_tend     ! Dry static energy hole-filling tendency         [J/kg/s]
    2340             : 
    2341             :      integer :: ncol  ! Number of grid columns
    2342             : 
    2343             :      integer :: icol, k  ! Loop indices
    2344             : 
    2345             :      ! Flag to perform hole filling after the original sedimentation tendency
    2346             :      ! is added back on to the new microphysics process tendency.  This calls
    2347             :      ! the sedimentation hole filler.
    2348             :      logical, parameter :: &
    2349             :        l_sed_hole_fill = .true.
    2350             : 
    2351             :      logical, parameter :: &
    2352             :        l_check_conservation = .true. ! Flag to perform water conservation check
    2353             : 
    2354             :      ! Vertically-integrated grand total water (rv+rc+rr+ri+rs)    [kg/m^2]
    2355             :      real(r8), dimension(pcols) :: &
    2356             :        grand_total_water_column_start,  & ! Column integral at start
    2357             :        grand_total_water_column_finish    ! Column integral at finish
    2358             : 
    2359             :      ! Vertically-integrated total water energy    [J/m^2]
    2360             :      real(r8), dimension(pcols) :: &
    2361             :        total_energy_column_start,  & ! Column integral at start
    2362             :        total_energy_column_finish    ! Column integral at finish
    2363             : 
    2364             :      real(r8), dimension(pcols) :: &
    2365             :        tot_water_rel_err,  & ! Relative error: vert-integrated grand total water
    2366             :        tot_energy_rel_err    ! Relative error: vert-integrated total energy
    2367             : 
    2368             :      real(r8), parameter :: &
    2369             :        err_thresh = 1.0e-14_r8  ! Threshold of relative error
    2370             : 
    2371             : 
    2372             :      ! Get the number of grid columns.
    2373           0 :      ncol = state%ncol
    2374             : 
    2375             :      ! Get fields from the pbuf.
    2376           0 :      call pbuf_get_field(pbuf, prec_pcw_idx, prect)
    2377           0 :      call pbuf_get_field(pbuf, snow_pcw_idx, preci)
    2378           0 :      call pbuf_get_field(pbuf, prec_str_idx, prec_str)
    2379           0 :      call pbuf_get_field(pbuf, snow_str_idx, snow_str)
    2380           0 :      call pbuf_get_field(pbuf, qcsedten_idx, rc_sed_tend)
    2381           0 :      call pbuf_get_field(pbuf, qrsedten_idx, rr_sed_tend)
    2382           0 :      call pbuf_get_field(pbuf, qisedten_idx, ri_sed_tend)
    2383           0 :      call pbuf_get_field(pbuf, qssedten_idx, rs_sed_tend)
    2384           0 :      call pbuf_get_field(pbuf, vtrmc_idx, vtrmc)
    2385           0 :      call pbuf_get_field(pbuf, umr_idx, umr)
    2386           0 :      call pbuf_get_field(pbuf, vtrmi_idx, vtrmi)
    2387           0 :      call pbuf_get_field(pbuf, ums_idx, ums)
    2388           0 :      call pbuf_get_field(pbuf, qcsevap_idx, rc_sed_evap)
    2389           0 :      call pbuf_get_field(pbuf, qisevap_idx, ri_sed_subl)
    2390             : 
    2391             :      ! Calculate liquid precipitation rate (precl) from the total precipitation
    2392             :      ! rate (prect) and the frozen preciptation rate (preci).  This should never
    2393             :      ! be negative, but just to be safe, threshold at 0.
    2394           0 :      precl(:ncol) = max( prect(:ncol) - preci(:ncol), 0.0_r8 )
    2395             : 
    2396             :      ! Perform total water and total energy conservation checks.
    2397             :      if ( l_check_conservation ) then
    2398             : 
    2399             :         ! Calculate total water in each column.
    2400             :         ! This calculation is the vertically-integrated grand total water (where
    2401             :         ! grand total water is the sum of water vapor, cloud water, rain water,
    2402             :         ! cloud ice, and snow, as well as the amount of water that precipitated
    2403             :         ! to the surface) in each grid column after microphysics, but at the
    2404             :         ! start of hole filling.
    2405           0 :         do icol = 1, ncol
    2406           0 :            grand_total_water_column_start(icol) = 0.0_r8
    2407           0 :            do k = top_lev, pver
    2408             :               grand_total_water_column_start(icol) &
    2409             :               = grand_total_water_column_start(icol) &
    2410           0 :                 + ( state%q(icol,k,1) + ptend%q(icol,k,1) * dt &
    2411           0 :                     + state%q(icol,k,ixcldliq) &
    2412           0 :                     + ptend%q(icol,k,ixcldliq) * dt &
    2413           0 :                     + state%q(icol,k,ixcldice) &
    2414           0 :                     + ptend%q(icol,k,ixcldice) * dt ) &
    2415           0 :                   * state%pdel(icol,k) * rga
    2416           0 :               if ( ixrain > 0 ) then
    2417             :                  grand_total_water_column_start(icol) &
    2418             :                  = grand_total_water_column_start(icol) &
    2419           0 :                    + ( state%q(icol,k,ixrain) + ptend%q(icol,k,ixrain) * dt ) &
    2420           0 :                      * state%pdel(icol,k) * rga
    2421             :               endif
    2422           0 :               if ( ixsnow > 0 ) then
    2423             :                  grand_total_water_column_start(icol) &
    2424             :                  = grand_total_water_column_start(icol) &
    2425           0 :                    + ( state%q(icol,k,ixsnow) + ptend%q(icol,k,ixsnow) * dt ) &
    2426           0 :                      * state%pdel(icol,k) * rga
    2427             :               endif
    2428             :            end do ! k = top_lev, pver
    2429             :            grand_total_water_column_start(icol) &
    2430             :            = grand_total_water_column_start(icol) &
    2431           0 :              + prect(icol) * dt * 1000.0_r8
    2432             :         end do ! icol = 1, ncol
    2433             : 
    2434             :         ! Calculate total energy in each column.
    2435             :         ! This calculation is the vertically-integrated total energy in each
    2436             :         ! grid column after microphysics, but at the start of hole filling.
    2437             :         ! Since the microphysics and hole filling code does not directly change
    2438             :         ! kinetic energy, 0.5 * ( u^2 + v^2 ), it can be skipped as part of the
    2439             :         ! energy conservation check.
    2440           0 :         do icol = 1, ncol
    2441           0 :            total_energy_column_start(icol) = 0.0_r8
    2442           0 :            do k = top_lev, pver
    2443             :               total_energy_column_start(icol) &
    2444             :               = total_energy_column_start(icol) &
    2445           0 :                 + ( state%s(icol,k) + ptend%s(icol,k) * dt &
    2446             :                     + ( latvap + latice ) &
    2447           0 :                       * ( state%q(icol,k,1) + ptend%q(icol,k,1) * dt ) &
    2448           0 :                     + latice * ( state%q(icol,k,ixcldliq) &
    2449           0 :                                  + ptend%q(icol,k,ixcldliq) * dt ) ) &
    2450           0 :                   * state%pdel(icol,k) * rga
    2451           0 :               if ( ixrain > 0 ) then
    2452             :                  total_energy_column_start(icol) &
    2453             :                  = total_energy_column_start(icol) &
    2454           0 :                    + latice * ( state%q(icol,k,ixrain) &
    2455           0 :                                 + ptend%q(icol,k,ixrain) * dt ) &
    2456           0 :                      * state%pdel(icol,k) * rga
    2457             :               endif
    2458             :            end do ! k = top_lev, pver
    2459             :            total_energy_column_start(icol) &
    2460             :            = total_energy_column_start(icol) &
    2461           0 :              + latice * precl(icol) * dt * 1000.0_r8
    2462             :         end do ! icol = 1, ncol
    2463             : 
    2464             :      endif ! l_check_conservation
    2465             : 
    2466             :      ! The fields within state haven't been updated yet, since this is before
    2467             :      ! the call to physics_update.
    2468           0 :      rv_start = state%q(:,:,1)
    2469           0 :      rc_start = state%q(:,:,ixcldliq)
    2470           0 :      if ( ixrain > 0 ) then
    2471           0 :         rr_start = state%q(:,:,ixrain)
    2472             :      endif
    2473           0 :      ri_start = state%q(:,:,ixcldice)
    2474           0 :      if ( ixsnow > 0 ) then
    2475           0 :         rs_start = state%q(:,:,ixsnow)
    2476             :      endif
    2477             : 
    2478             :      ! Unpack the current total tendencies for hydrometeor mixing ratio fields.
    2479           0 :      rv_tend = ptend%q(:,:,1)
    2480           0 :      rc_tend = ptend%q(:,:,ixcldliq)
    2481           0 :      if ( ixrain > 0 ) then
    2482           0 :         rr_tend = ptend%q(:,:,ixrain)
    2483             :      endif
    2484           0 :      ri_tend = ptend%q(:,:,ixcldice)
    2485           0 :      if ( ixsnow > 0 ) then
    2486           0 :         rs_tend = ptend%q(:,:,ixsnow)
    2487             :      endif
    2488             : 
    2489             :      ! Unpack the current tendency for dry static energy.
    2490           0 :      stend = ptend%s
    2491             : 
    2492             :      ! The total hydrometeor tendencies are the sum of microphysics process
    2493             :      ! rates and sedimentation rates.  Calculate the microphysics process
    2494             :      ! tendencies by subtracting the sedimentation tendencies from the overall
    2495             :      ! tendencies.
    2496             :      ! The sedimentation tendencies for cloud water (rc_sed_tend) and cloud ice
    2497             :      ! (ri_sed_tend) include the evaporation of cloud water during sedimentation
    2498             :      ! and the sublimation of cloud ice during sedimentation, respectively.  The
    2499             :      ! true sedimentation of cloud water is the sum of rc_sed_tend and
    2500             :      ! rc_sed_evap, and the true sedimentation of cloud ice is the sum of
    2501             :      ! ri_sed_tend and ri_sed_subl.  Subtract off only the true sedimentation
    2502             :      ! rates, as evaporation and sublimation need to be included in the
    2503             :      ! microphysics process rates.
    2504           0 :      rv_mc_tend(:ncol,:) = rv_tend(:ncol,:)
    2505           0 :      rc_mc_tend(:ncol,:) = rc_tend(:ncol,:) - ( rc_sed_tend(:ncol,:) + rc_sed_evap(:ncol,:) )
    2506           0 :      if ( ixrain > 0 ) then
    2507           0 :         rr_mc_tend(:ncol,:) = rr_tend(:ncol,:) - rr_sed_tend(:ncol,:)
    2508             :      endif
    2509           0 :      ri_mc_tend(:ncol,:) = ri_tend(:ncol,:) - ( ri_sed_tend(:ncol,:) + ri_sed_subl(:ncol,:) )
    2510           0 :      if ( ixsnow > 0 ) then
    2511           0 :         rs_mc_tend(:ncol,:) = rs_tend(:ncol,:) - rs_sed_tend(:ncol,:)
    2512             :      endif
    2513             : 
    2514             :      ! This section adjusts microphysics process rate tendencies so that the
    2515             :      ! resulting values of all hydrometeor mixing ratios are greater than or
    2516             :      ! equal to qmin after this section is complete.  Once sedimentation is
    2517             :      ! added back on after this section, some of the hydrometeor mixing ratios
    2518             :      ! may become less than qmin again.
    2519             :      !
    2520             :      ! This section, which again is concerned only with adjusting microphysics
    2521             :      ! process rates, makes use of the following two principles:
    2522             :      !
    2523             :      ! 1) When adjusting the tendencies from microphysics process rates,
    2524             :      !    conserve:
    2525             :      !
    2526             :      !    rv_mc_tend(k) + rc_mc_tend(k) + rr_mc_tend(k)
    2527             :      !    + ri_mc_tend(k) + rs_mc_tend(k) = 0; for all k from top_lev to pver.
    2528             :      !
    2529             :      ! 2) When adjusting the tendencies from microphysics process rates, adjust
    2530             :      !    dry static energy appropriately.  The change in dry static energy
    2531             :      !    is necessary because of phase changes.  This "puts back" the extra dry
    2532             :      !    static energy that was "taken out" when an excessive phase-changing
    2533             :      !    process rate was produced by microphysics.
    2534             : 
    2535             :      ! Loop over all columns, performing any tendency adjustments one column
    2536             :      ! at a time.
    2537           0 :      do icol = 1, ncol
    2538             : 
    2539             :         ! Loop over all vertical levels, performing any microphysics process
    2540             :         ! tendency adjustments one level at a time.
    2541           0 :         do k = top_lev, pver
    2542             : 
    2543             :            ! Find which hydrometeors have positive microphysics process
    2544             :            ! tendencies at this level.
    2545           0 :            if ( rv_mc_tend(icol,k) >= 0.0_r8 ) then
    2546             :               l_pos_rv_mc_tend = .true.
    2547             :            else
    2548           0 :               l_pos_rv_mc_tend = .false.
    2549             :            endif
    2550           0 :            if ( rc_mc_tend(icol,k) >= 0.0_r8 ) then
    2551             :               l_pos_rc_mc_tend = .true.
    2552             :            else
    2553           0 :               l_pos_rc_mc_tend = .false.
    2554             :            endif
    2555           0 :            if ( ixrain > 0 ) then
    2556           0 :               if ( rr_mc_tend(icol,k) >= 0.0_r8 ) then
    2557             :                  l_pos_rr_mc_tend = .true.
    2558             :               else
    2559           0 :                  l_pos_rr_mc_tend = .false.
    2560             :               endif
    2561             :            endif
    2562           0 :            if ( ri_mc_tend(icol,k) >= 0.0_r8 ) then
    2563             :               l_pos_ri_mc_tend = .true.
    2564             :            else
    2565           0 :               l_pos_ri_mc_tend = .false.
    2566             :            endif
    2567           0 :            if ( ixsnow > 0 ) then
    2568           0 :               if ( rs_mc_tend(icol,k) >= 0.0_r8 ) then
    2569             :                  l_pos_rs_mc_tend = .true.
    2570             :               else
    2571           0 :                  l_pos_rs_mc_tend = .false.
    2572             :               endif
    2573             :            endif
    2574             : 
    2575             :            !!! Check for holes in water vapor mixing ratio
    2576           0 :            if ( .not. l_pos_rv_mc_tend ) then
    2577             : 
    2578             :               ! Calculate the water vapor mixing ratio as it would be with the
    2579             :               ! current microphysics process tendency.
    2580           0 :               rv_curr = rv_start(icol,k) + rv_mc_tend(icol,k) * dt
    2581             : 
    2582           0 :               if ( rv_curr < qmin(1) ) then
    2583             : 
    2584             :                  ! Microphysics processes are causing a hole in water vapor
    2585             :                  ! mixing ratio.
    2586             : 
    2587             :                  ! Calculate the maximum allowable magnitude of (negative) water
    2588             :                  ! vapor microphysics process tendency.
    2589           0 :                  mc_tend_max_mag = ( qmin(1) - rv_start(icol,k) ) / dt
    2590             : 
    2591             :                  ! Calculate the amount of the correction that needs to be made
    2592             :                  ! to the water vapor mixing ratio microphysics process
    2593             :                  ! tendency.  This number is positive.
    2594           0 :                  mc_tend_correction = mc_tend_max_mag - rv_mc_tend(icol,k)
    2595             : 
    2596             :                  ! Calculate the total amount of positive microphysics process
    2597             :                  ! tendencies for all hydrometeor mixing ratios.
    2598           0 :                  total_mc_positive = 0.0_r8
    2599           0 :                  if ( l_pos_rc_mc_tend ) then
    2600           0 :                     total_mc_positive = total_mc_positive + rc_mc_tend(icol,k)
    2601             :                  endif
    2602           0 :                  if ( ixrain > 0 .and. l_pos_rr_mc_tend ) then
    2603           0 :                     total_mc_positive = total_mc_positive + rr_mc_tend(icol,k)
    2604             :                  endif
    2605           0 :                  if ( l_pos_ri_mc_tend ) then
    2606           0 :                     total_mc_positive = total_mc_positive + ri_mc_tend(icol,k)
    2607             :                  endif
    2608           0 :                  if ( ixsnow > 0 .and. l_pos_rs_mc_tend ) then
    2609           0 :                     total_mc_positive = total_mc_positive + rs_mc_tend(icol,k)
    2610             :                  endif
    2611             : 
    2612             :                  ! Calculate the correction ratio.
    2613             :                  ! In principle, this should never be greater than 1 outside of
    2614             :                  ! numerical round-off errors.  This is limited at 1 to be safe.
    2615             :                  mc_correction_ratio &
    2616             :                  = min( mc_tend_correction &
    2617           0 :                         / max( total_mc_positive, 1.0e-30_r8 ), 1.0_r8 )
    2618             : 
    2619             :                  ! Adjust (decrease) the tendencies of all positive hydrometeor
    2620             :                  ! mixing ratio tendencies to balance the adjustment (increase)
    2621             :                  ! to the excessively negative water vapor mixing ratio.
    2622             :                  ! Transfer dry static energy appropriately (in response to the
    2623             :                  ! excessive depletion of water vapor).
    2624           0 :                  if ( l_pos_rc_mc_tend ) then
    2625             :                     ! Changing cloud water to water vapor cools and reduces
    2626             :                     ! dry static energy.
    2627             :                     stend(icol,k) &
    2628             :                     = stend(icol,k) &
    2629           0 :                       - latvap * mc_correction_ratio * rc_mc_tend(icol,k)
    2630             :                     ! Update cloud water mixing ratio microphysics tendency.
    2631             :                     rc_mc_tend(icol,k) &
    2632           0 :                     = rc_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2633             :                  endif
    2634           0 :                  if ( ixrain > 0 .and. l_pos_rr_mc_tend ) then
    2635             :                     ! Changing rain water to water vapor cools and reduces
    2636             :                     ! dry static energy.
    2637             :                     stend(icol,k) &
    2638             :                     = stend(icol,k) &
    2639           0 :                       - latvap * mc_correction_ratio * rr_mc_tend(icol,k)
    2640             :                     ! Update rain water mixing ratio microphysics tendency.
    2641             :                     rr_mc_tend(icol,k) &
    2642           0 :                     = rr_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2643             :                  endif
    2644           0 :                  if ( l_pos_ri_mc_tend ) then
    2645             :                     ! Changing cloud ice to water vapor cools and reduces
    2646             :                     ! dry static energy.
    2647             :                     stend(icol,k) &
    2648             :                     = stend(icol,k) &
    2649             :                       - ( latvap + latice ) &
    2650           0 :                         * mc_correction_ratio * ri_mc_tend(icol,k)
    2651             :                     ! Update cloud ice mixing ratio microphysics tendency.
    2652             :                     ri_mc_tend(icol,k) &
    2653           0 :                     = ri_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2654             :                  endif
    2655           0 :                  if ( ixsnow > 0 .and. l_pos_rs_mc_tend ) then
    2656             :                     ! Changing snow to water vapor cools and reduces dry
    2657             :                     ! static energy.
    2658             :                     stend(icol,k) &
    2659             :                     = stend(icol,k) &
    2660             :                       - ( latvap + latice ) &
    2661           0 :                         * mc_correction_ratio * rs_mc_tend(icol,k)
    2662             :                     ! Update snow mixing ratio microphysics tendency.
    2663             :                     rs_mc_tend(icol,k) &
    2664           0 :                     = rs_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2665             :                  endif
    2666             : 
    2667             :                  ! Calculate the new water vapor mixing ratio microphysics
    2668             :                  ! process tendency.  This should be equal to the maximum
    2669             :                  ! magnitude (negative) amount allowed, mc_tend_max_mag.
    2670             :                  rv_mc_tend(icol,k) &
    2671             :                  = rv_mc_tend(icol,k) &
    2672           0 :                    + mc_correction_ratio * total_mc_positive
    2673             : 
    2674             :               endif ! rv_curr < qmin(1)
    2675             : 
    2676             :            endif ! .not. l_pos_rv_mc_tend
    2677             : 
    2678             :            !!! Check for holes in cloud water mixing ratio
    2679           0 :            if ( .not. l_pos_rc_mc_tend ) then
    2680             : 
    2681             :               ! Calculate the cloud water mixing ratio as it would be with the
    2682             :               ! current microphysics process tendency.
    2683           0 :               rc_curr = rc_start(icol,k) + rc_mc_tend(icol,k) * dt
    2684             : 
    2685           0 :               if ( rc_curr < qmin(ixcldliq) ) then
    2686             : 
    2687             :                  ! Microphysics processes are causing a hole in cloud water
    2688             :                  ! mixing ratio.
    2689             : 
    2690             :                  ! Calculate the maximum allowable magnitude of (negative) cloud
    2691             :                  ! water microphysics process tendency.
    2692           0 :                  mc_tend_max_mag = ( qmin(ixcldliq) - rc_start(icol,k) ) / dt
    2693             : 
    2694             :                  ! Calculate the amount of the correction that needs to be made
    2695             :                  ! to the cloud water mixing ratio microphysics process
    2696             :                  ! tendency.  This number is positive.
    2697           0 :                  mc_tend_correction = mc_tend_max_mag - rc_mc_tend(icol,k)
    2698             : 
    2699             :                  ! Calculate the total amount of positive microphysics process
    2700             :                  ! tendencies for all hydrometeor mixing ratios.
    2701           0 :                  total_mc_positive = 0.0_r8
    2702           0 :                  if ( l_pos_rv_mc_tend ) then
    2703           0 :                     total_mc_positive = total_mc_positive + rv_mc_tend(icol,k)
    2704             :                  endif
    2705           0 :                  if ( ixrain > 0 .and. l_pos_rr_mc_tend ) then
    2706           0 :                     total_mc_positive = total_mc_positive + rr_mc_tend(icol,k)
    2707             :                  endif
    2708           0 :                  if ( l_pos_ri_mc_tend ) then
    2709           0 :                     total_mc_positive = total_mc_positive + ri_mc_tend(icol,k)
    2710             :                  endif
    2711           0 :                  if ( ixsnow > 0 .and. l_pos_rs_mc_tend ) then
    2712           0 :                     total_mc_positive = total_mc_positive + rs_mc_tend(icol,k)
    2713             :                  endif
    2714             : 
    2715             :                  ! Calculate the correction ratio.
    2716             :                  ! In principle, this should never be greater than 1 outside of
    2717             :                  ! numerical round-off errors.  This is limited at 1 to be safe.
    2718             :                  mc_correction_ratio &
    2719             :                  = min( mc_tend_correction &
    2720           0 :                         / max( total_mc_positive, 1.0e-30_r8 ), 1.0_r8 )
    2721             : 
    2722             :                  ! Adjust (decrease) the tendencies of all positive hydrometeor
    2723             :                  ! mixing ratio tendencies to balance the adjustment (increase)
    2724             :                  ! to the excessively negative cloud water mixing ratio.
    2725             :                  ! Transfer dry static energy appropriately (in response to the
    2726             :                  ! excessive depletion of cloud water).
    2727           0 :                  if ( l_pos_rv_mc_tend ) then
    2728             :                     ! Changing water vapor to cloud water heats and increases
    2729             :                     ! dry static energy.
    2730             :                     stend(icol,k) &
    2731             :                     = stend(icol,k) &
    2732           0 :                       + latvap * mc_correction_ratio * rv_mc_tend(icol,k)
    2733             :                     ! Update water vapor mixing ratio microphysics tendency.
    2734             :                     rv_mc_tend(icol,k) &
    2735           0 :                     = rv_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2736             :                  endif
    2737           0 :                  if ( ixrain > 0 .and. l_pos_rr_mc_tend ) then
    2738             :                     ! Changing rain water to cloud water does not change
    2739             :                     ! dry static energy.
    2740             :                     ! Update rain water mixing ratio microphysics tendency.
    2741             :                     rr_mc_tend(icol,k) &
    2742           0 :                     = rr_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2743             :                  endif
    2744           0 :                  if ( l_pos_ri_mc_tend ) then
    2745             :                     ! Changing cloud ice to cloud water cools and reduces
    2746             :                     ! dry static energy.
    2747             :                     stend(icol,k) &
    2748             :                     = stend(icol,k) &
    2749           0 :                       - latice * mc_correction_ratio * ri_mc_tend(icol,k)
    2750             :                     ! Update cloud ice mixing ratio microphysics tendency.
    2751             :                     ri_mc_tend(icol,k) &
    2752           0 :                     = ri_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2753             :                  endif
    2754           0 :                  if ( ixsnow > 0 .and. l_pos_rs_mc_tend ) then
    2755             :                     ! Changing snow to cloud water cools and reduces dry
    2756             :                     ! static energy.
    2757             :                     stend(icol,k) &
    2758             :                     = stend(icol,k) &
    2759           0 :                       - latice * mc_correction_ratio * rs_mc_tend(icol,k)
    2760             :                     ! Update snow mixing ratio microphysics tendency.
    2761             :                     rs_mc_tend(icol,k) &
    2762           0 :                     = rs_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2763             :                  endif
    2764             : 
    2765             :                  ! Calculate the new cloud water mixing ratio microphysics
    2766             :                  ! process tendency.  This should be equal to the maximum
    2767             :                  ! magnitude (negative) amount allowed, mc_tend_max_mag.
    2768             :                  rc_mc_tend(icol,k) &
    2769             :                  = rc_mc_tend(icol,k) &
    2770           0 :                    + mc_correction_ratio * total_mc_positive
    2771             : 
    2772             :               endif ! rc_curr < qmin(ixcldliq)
    2773             : 
    2774             :            endif ! .not. l_pos_rc_mc_tend
    2775             : 
    2776             :            !!! Check for holes in rain water mixing ratio
    2777           0 :            if ( ixrain > 0 .and. ( .not. l_pos_rr_mc_tend ) ) then
    2778             : 
    2779             :               ! Calculate the rain water mixing ratio as it would be with the
    2780             :               ! current microphysics process tendency.
    2781           0 :               rr_curr = rr_start(icol,k) + rr_mc_tend(icol,k) * dt
    2782             : 
    2783           0 :               if ( rr_curr < qmin(ixrain) ) then
    2784             : 
    2785             :                  ! Microphysics processes are causing a hole in rain water
    2786             :                  ! mixing ratio.
    2787             : 
    2788             :                  ! Calculate the maximum allowable magnitude of (negative) rain
    2789             :                  ! water microphysics process tendency.
    2790           0 :                  mc_tend_max_mag = ( qmin(ixrain) - rr_start(icol,k) ) / dt
    2791             : 
    2792             :                  ! Calculate the amount of the correction that needs to be made
    2793             :                  ! to the rain water mixing ratio microphysics process
    2794             :                  ! tendency.  This number is positive.
    2795           0 :                  mc_tend_correction = mc_tend_max_mag - rr_mc_tend(icol,k)
    2796             : 
    2797             :                  ! Calculate the total amount of positive microphysics process
    2798             :                  ! tendencies for all hydrometeor mixing ratios.
    2799           0 :                  total_mc_positive = 0.0_r8
    2800           0 :                  if ( l_pos_rv_mc_tend ) then
    2801           0 :                     total_mc_positive = total_mc_positive + rv_mc_tend(icol,k)
    2802             :                  endif
    2803           0 :                  if ( l_pos_rc_mc_tend ) then
    2804           0 :                     total_mc_positive = total_mc_positive + rc_mc_tend(icol,k)
    2805             :                  endif
    2806           0 :                  if ( l_pos_ri_mc_tend ) then
    2807           0 :                     total_mc_positive = total_mc_positive + ri_mc_tend(icol,k)
    2808             :                  endif
    2809           0 :                  if ( ixsnow > 0 .and. l_pos_rs_mc_tend ) then
    2810           0 :                     total_mc_positive = total_mc_positive + rs_mc_tend(icol,k)
    2811             :                  endif
    2812             : 
    2813             :                  ! Calculate the correction ratio.
    2814             :                  ! In principle, this should never be greater than 1 outside of
    2815             :                  ! numerical round-off errors.  This is limited at 1 to be safe.
    2816             :                  mc_correction_ratio &
    2817             :                  = min( mc_tend_correction &
    2818           0 :                         / max( total_mc_positive, 1.0e-30_r8 ), 1.0_r8 )
    2819             : 
    2820             :                  ! Adjust (decrease) the tendencies of all positive hydrometeor
    2821             :                  ! mixing ratio tendencies to balance the adjustment (increase)
    2822             :                  ! to the excessively negative rain water mixing ratio.
    2823             :                  ! Transfer dry static energy appropriately (in response to the
    2824             :                  ! excessive depletion of rain water).
    2825           0 :                  if ( l_pos_rv_mc_tend ) then
    2826             :                     ! Changing water vapor to rain water heats and increases
    2827             :                     ! dry static energy.
    2828             :                     stend(icol,k) &
    2829             :                     = stend(icol,k) &
    2830           0 :                       + latvap * mc_correction_ratio * rv_mc_tend(icol,k)
    2831             :                     ! Update water vapor mixing ratio microphysics tendency.
    2832             :                     rv_mc_tend(icol,k) &
    2833           0 :                     = rv_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2834             :                  endif
    2835           0 :                  if ( l_pos_rc_mc_tend ) then
    2836             :                     ! Changing cloud water to rain water does not change
    2837             :                     ! dry static energy.
    2838             :                     ! Update cloud water mixing ratio microphysics tendency.
    2839             :                     rc_mc_tend(icol,k) &
    2840           0 :                     = rc_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2841             :                  endif
    2842           0 :                  if ( l_pos_ri_mc_tend ) then
    2843             :                     ! Changing cloud ice to rain water cools and reduces
    2844             :                     ! dry static energy.
    2845             :                     stend(icol,k) &
    2846             :                     = stend(icol,k) &
    2847           0 :                       - latice * mc_correction_ratio * ri_mc_tend(icol,k)
    2848             :                     ! Update cloud ice mixing ratio microphysics tendency.
    2849             :                     ri_mc_tend(icol,k) &
    2850           0 :                     = ri_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2851             :                  endif
    2852           0 :                  if ( ixsnow > 0 .and. l_pos_rs_mc_tend ) then
    2853             :                     ! Changing snow to rain water cools and reduces dry
    2854             :                     ! static energy.
    2855             :                     stend(icol,k) &
    2856             :                     = stend(icol,k) &
    2857           0 :                       - latice * mc_correction_ratio * rs_mc_tend(icol,k)
    2858             :                     ! Update snow mixing ratio microphysics tendency.
    2859             :                     rs_mc_tend(icol,k) &
    2860           0 :                     = rs_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2861             :                  endif
    2862             : 
    2863             :                  ! Calculate the new rain water mixing ratio microphysics
    2864             :                  ! process tendency.  This should be equal to the maximum
    2865             :                  ! magnitude (negative) amount allowed, mc_tend_max_mag.
    2866             :                  rr_mc_tend(icol,k) &
    2867             :                  = rr_mc_tend(icol,k) &
    2868           0 :                    + mc_correction_ratio * total_mc_positive
    2869             : 
    2870             :               endif ! rr_curr < qmin(ixrain)
    2871             : 
    2872             :            endif ! ixrain > 0 .and. ( .not. l_pos_rr_mc_tend )
    2873             : 
    2874             :            !!! Check for holes in cloud ice mixing ratio
    2875           0 :            if ( .not. l_pos_ri_mc_tend ) then
    2876             : 
    2877             :               ! Calculate the cloud ice mixing ratio as it would be with the
    2878             :               ! current microphysics process tendency.
    2879           0 :               ri_curr = ri_start(icol,k) + ri_mc_tend(icol,k) * dt
    2880             : 
    2881           0 :               if ( ri_curr < qmin(ixcldice) ) then
    2882             : 
    2883             :                  ! Microphysics processes are causing a hole in cloud ice
    2884             :                  ! mixing ratio.
    2885             : 
    2886             :                  ! Calculate the maximum allowable magnitude of (negative) cloud
    2887             :                  ! ice microphysics process tendency.
    2888           0 :                  mc_tend_max_mag = ( qmin(ixcldice) - ri_start(icol,k) ) / dt
    2889             : 
    2890             :                  ! Calculate the amount of the correction that needs to be made
    2891             :                  ! to the cloud ice mixing ratio microphysics process
    2892             :                  ! tendency.  This number is positive.
    2893           0 :                  mc_tend_correction = mc_tend_max_mag - ri_mc_tend(icol,k)
    2894             : 
    2895             :                  ! Calculate the total amount of positive microphysics process
    2896             :                  ! tendencies for all hydrometeor mixing ratios.
    2897           0 :                  total_mc_positive = 0.0_r8
    2898           0 :                  if ( l_pos_rv_mc_tend ) then
    2899           0 :                     total_mc_positive = total_mc_positive + rv_mc_tend(icol,k)
    2900             :                  endif
    2901           0 :                  if ( l_pos_rc_mc_tend ) then
    2902           0 :                     total_mc_positive = total_mc_positive + rc_mc_tend(icol,k)
    2903             :                  endif
    2904           0 :                  if ( ixrain > 0 .and. l_pos_rr_mc_tend ) then
    2905           0 :                     total_mc_positive = total_mc_positive + rr_mc_tend(icol,k)
    2906             :                  endif
    2907           0 :                  if ( ixsnow > 0 .and. l_pos_rs_mc_tend ) then
    2908           0 :                     total_mc_positive = total_mc_positive + rs_mc_tend(icol,k)
    2909             :                  endif
    2910             : 
    2911             :                  ! Calculate the correction ratio.
    2912             :                  ! In principle, this should never be greater than 1 outside of
    2913             :                  ! numerical round-off errors.  This is limited at 1 to be safe.
    2914             :                  mc_correction_ratio &
    2915             :                  = min( mc_tend_correction &
    2916           0 :                         / max( total_mc_positive, 1.0e-30_r8 ), 1.0_r8 )
    2917             : 
    2918             :                  ! Adjust (decrease) the tendencies of all positive hydrometeor
    2919             :                  ! mixing ratio tendencies to balance the adjustment (increase)
    2920             :                  ! to the excessively negative cloud ice mixing ratio.
    2921             :                  ! Transfer dry static energy appropriately (in response to the
    2922             :                  ! excessive depletion of cloud ice).
    2923           0 :                  if ( l_pos_rv_mc_tend ) then
    2924             :                     ! Changing water vapor to cloud ice heats and increases
    2925             :                     ! dry static energy.
    2926             :                     stend(icol,k) &
    2927             :                     = stend(icol,k) &
    2928             :                       + ( latvap + latice ) &
    2929           0 :                         * mc_correction_ratio * rv_mc_tend(icol,k)
    2930             :                     ! Update water vapor mixing ratio microphysics tendency.
    2931             :                     rv_mc_tend(icol,k) &
    2932           0 :                     = rv_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2933             :                  endif
    2934           0 :                  if ( l_pos_rc_mc_tend ) then
    2935             :                     ! Changing cloud water to cloud ice heats and increases
    2936             :                     ! dry static energy.
    2937             :                     stend(icol,k) &
    2938             :                     = stend(icol,k) &
    2939           0 :                       + latice * mc_correction_ratio * rc_mc_tend(icol,k)
    2940             :                     ! Update cloud water mixing ratio microphysics tendency.
    2941             :                     rc_mc_tend(icol,k) &
    2942           0 :                     = rc_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2943             :                  endif
    2944           0 :                  if ( ixrain > 0 .and. l_pos_rr_mc_tend ) then
    2945             :                     ! Changing rain water to cloud ice heats and increases
    2946             :                     ! dry static energy.
    2947             :                     stend(icol,k) &
    2948             :                     = stend(icol,k) &
    2949           0 :                       + latice * mc_correction_ratio * rr_mc_tend(icol,k)
    2950             :                     ! Update rain water mixing ratio microphysics tendency.
    2951             :                     rr_mc_tend(icol,k) &
    2952           0 :                     = rr_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2953             :                  endif
    2954           0 :                  if ( ixsnow > 0 .and. l_pos_rs_mc_tend ) then
    2955             :                     ! Changing snow to cloud ice does not change dry static
    2956             :                     ! energy.
    2957             :                     ! Update snow mixing ratio microphysics tendency.
    2958             :                     rs_mc_tend(icol,k) &
    2959           0 :                     = rs_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    2960             :                  endif
    2961             : 
    2962             :                  ! Calculate the new cloud ice mixing ratio microphysics
    2963             :                  ! process tendency.  This should be equal to the maximum
    2964             :                  ! magnitude (negative) amount allowed, mc_tend_max_mag.
    2965             :                  ri_mc_tend(icol,k) &
    2966             :                  = ri_mc_tend(icol,k) &
    2967           0 :                    + mc_correction_ratio * total_mc_positive
    2968             : 
    2969             :               endif ! ri_curr < qmin(ixcldice)
    2970             : 
    2971             :            endif ! .not. l_pos_ri_mc_tend
    2972             : 
    2973             :            !!! Check for holes in snow mixing ratio
    2974           0 :            if ( ixsnow > 0 .and. ( .not. l_pos_rs_mc_tend ) ) then
    2975             : 
    2976             :               ! Calculate the snow mixing ratio as it would be with the
    2977             :               ! current microphysics process tendency.
    2978           0 :               rs_curr = rs_start(icol,k) + rs_mc_tend(icol,k) * dt
    2979             : 
    2980           0 :               if ( rs_curr < qmin(ixsnow) ) then
    2981             : 
    2982             :                  ! Microphysics processes are causing a hole in snow mixing
    2983             :                  ! ratio.
    2984             : 
    2985             :                  ! Calculate the maximum allowable magnitude of (negative) snow
    2986             :                  ! microphysics process tendency.
    2987           0 :                  mc_tend_max_mag = ( qmin(ixsnow) - rs_start(icol,k) ) / dt
    2988             : 
    2989             :                  ! Calculate the amount of the correction that needs to be made
    2990             :                  ! to the snow mixing ratio microphysics process tendency.
    2991             :                  ! This number is positive.
    2992           0 :                  mc_tend_correction = mc_tend_max_mag - rs_mc_tend(icol,k)
    2993             : 
    2994             :                  ! Calculate the total amount of positive microphysics process
    2995             :                  ! tendencies for all hydrometeor mixing ratios.
    2996           0 :                  total_mc_positive = 0.0_r8
    2997           0 :                  if ( l_pos_rv_mc_tend ) then
    2998           0 :                     total_mc_positive = total_mc_positive + rv_mc_tend(icol,k)
    2999             :                  endif
    3000           0 :                  if ( l_pos_rc_mc_tend ) then
    3001           0 :                     total_mc_positive = total_mc_positive + rc_mc_tend(icol,k)
    3002             :                  endif
    3003           0 :                  if ( ixrain > 0 .and. l_pos_rr_mc_tend ) then
    3004           0 :                     total_mc_positive = total_mc_positive + rr_mc_tend(icol,k)
    3005             :                  endif
    3006           0 :                  if ( l_pos_ri_mc_tend ) then
    3007           0 :                     total_mc_positive = total_mc_positive + ri_mc_tend(icol,k)
    3008             :                  endif
    3009             : 
    3010             :                  ! Calculate the correction ratio.
    3011             :                  ! In principle, this should never be greater than 1 outside of
    3012             :                  ! numerical round-off errors.  This is limited at 1 to be safe.
    3013             :                  mc_correction_ratio &
    3014             :                  = min( mc_tend_correction &
    3015           0 :                         / max( total_mc_positive, 1.0e-30_r8 ), 1.0_r8 )
    3016             : 
    3017             :                  ! Adjust (decrease) the tendencies of all positive hydrometeor
    3018             :                  ! mixing ratio tendencies to balance the adjustment (increase)
    3019             :                  ! to the excessively negative snow mixing ratio.
    3020             :                  ! Transfer dry static energy appropriately (in response to the
    3021             :                  ! excessive depletion of snow).
    3022           0 :                  if ( l_pos_rv_mc_tend ) then
    3023             :                     ! Changing water vapor to snow heats and increases dry
    3024             :                     ! static energy.
    3025             :                     stend(icol,k) &
    3026             :                     = stend(icol,k) &
    3027             :                       + ( latvap + latice ) &
    3028           0 :                         * mc_correction_ratio * rv_mc_tend(icol,k)
    3029             :                     ! Update water vapor mixing ratio microphysics tendency.
    3030             :                     rv_mc_tend(icol,k) &
    3031           0 :                     = rv_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    3032             :                  endif
    3033           0 :                  if ( l_pos_rc_mc_tend ) then
    3034             :                     ! Changing cloud water to snow heats and increases dry
    3035             :                     ! static energy.
    3036             :                     stend(icol,k) &
    3037             :                     = stend(icol,k) &
    3038           0 :                       + latice * mc_correction_ratio * rc_mc_tend(icol,k)
    3039             :                     ! Update cloud water mixing ratio microphysics tendency.
    3040             :                     rc_mc_tend(icol,k) &
    3041           0 :                     = rc_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    3042             :                  endif
    3043           0 :                  if ( ixrain > 0 .and. l_pos_rr_mc_tend ) then
    3044             :                     ! Changing rain water to snow heats and increases dry
    3045             :                     ! static energy.
    3046             :                     stend(icol,k) &
    3047             :                     = stend(icol,k) &
    3048           0 :                       + latice * mc_correction_ratio * rr_mc_tend(icol,k)
    3049             :                     ! Update rain water mixing ratio microphysics tendency.
    3050             :                     rr_mc_tend(icol,k) &
    3051           0 :                     = rr_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    3052             :                  endif
    3053           0 :                  if ( l_pos_ri_mc_tend ) then
    3054             :                     ! Changing cloud ice to snow does not change dry static
    3055             :                     ! energy.
    3056             :                     ! Update cloud ice mixing ratio microphysics tendency.
    3057             :                     ri_mc_tend(icol,k) &
    3058           0 :                     = ri_mc_tend(icol,k) * ( 1.0_r8 - mc_correction_ratio )
    3059             :                  endif
    3060             : 
    3061             :                  ! Calculate the new snow mixing ratio microphysics process
    3062             :                  ! tendency.  This should be equal to the maximum magnitude
    3063             :                  ! (negative) amount allowed, mc_tend_max_mag.
    3064             :                  rs_mc_tend(icol,k) &
    3065             :                  = rs_mc_tend(icol,k) &
    3066           0 :                    + mc_correction_ratio * total_mc_positive
    3067             : 
    3068             :               endif ! rs_curr < qmin(ixsnow)
    3069             : 
    3070             :            endif ! ixsnow > 0 .and. ( .not. l_pos_rs_mc_tend )
    3071             : 
    3072             :         end do ! k = top_lev, pver
    3073             : 
    3074             :      end do ! icol = 1, ncol
    3075             : 
    3076             :      ! Calculate the new overall tendencies by adding the sedimentation
    3077             :      ! tendencies back onto the new microphysics process tendencies.
    3078             :      ! For cloud water and cloud ice, the sedimentation tendencies that are
    3079             :      ! added back on are the true sedimentation tendencies.  For cloud water,
    3080             :      ! this is the sum of rc_sed_tend and rc_sed_evap, and for cloud ice, this
    3081             :      ! is the sum of ri_sed_tend and ri_sed_subl.
    3082           0 :      rv_tend(:ncol,:) = rv_mc_tend(:ncol,:)
    3083           0 :      rc_tend(:ncol,:) = rc_mc_tend(:ncol,:) + ( rc_sed_tend(:ncol,:) + rc_sed_evap(:ncol,:) )
    3084           0 :      if ( ixrain > 0 ) then
    3085           0 :         rr_tend(:ncol,:) = rr_mc_tend(:ncol,:) + rr_sed_tend(:ncol,:)
    3086             :      endif
    3087           0 :      ri_tend(:ncol,:) = ri_mc_tend(:ncol,:) + ( ri_sed_tend(:ncol,:) + ri_sed_subl(:ncol,:) )
    3088           0 :      if ( ixsnow > 0 ) then
    3089           0 :         rs_tend(:ncol,:) = rs_mc_tend(:ncol,:) + rs_sed_tend(:ncol,:)
    3090             :      endif
    3091             : 
    3092             :      ! Now that the original sedimentation tendency has been added to the
    3093             :      ! new microphysics process tendency, the new total microphysics tendency
    3094             :      ! can still cause holes to form.  After the microphysics process rates were
    3095             :      ! adjusted, the values of the hydrometeor fields were greater than or equal
    3096             :      ! to 0 at all grid levels, which means their vertical integrals were also
    3097             :      ! greater than or equal to 0.  Sedimentation by itself has a vertical
    3098             :      ! integral of 0 (including the amount that sedimented to the surface).
    3099             :      ! This means that after the microphysics process rates have been adjusted
    3100             :      ! and sedimentation has been added back on, the resulting hydrometeor
    3101             :      ! fields all still have vertical integrals that are greater than or equal
    3102             :      ! to 0.  Holes that develop at any particular grid level can be filled.
    3103             :      ! These holes can be filled conservatively using the sedimentation hole
    3104             :      ! filler.
    3105             :      if ( l_sed_hole_fill ) then
    3106             : 
    3107             :         ! This section makes use of the following principle:
    3108             :         !
    3109             :         ! 3) When adjusting the hydrometeor tendency from sedimentation of a
    3110             :         !    liquid hydrometeor (cloud water or rain water), conserve:
    3111             :         !
    3112             :         !    SUM(k=top_lev:pver) ( rc_sed_tend(k) + rr_sed_tend(k) )
    3113             :         !                        * dt * pdel(k) / g
    3114             :         !    + precl * dt * 1000 = 0.
    3115             : 
    3116             :         ! Call the sedimentation hole filler for rain water mixing ratio.
    3117             :         ! This can update rr_tend and precl.
    3118           0 :         if ( ixrain > 0 ) then
    3119             :            call fill_holes_sedimentation( dt, ncol, rr_start, state%pdel, &
    3120           0 :                                           umr, state%zi, qmin(ixrain), &
    3121           0 :                                           rr_tend, precl )
    3122             :         endif ! ixrain > 0
    3123             : 
    3124             :         ! Call the sedimentation hole filler for cloud water mixing ratio.
    3125             :         ! This can update rc_tend and precl.
    3126             :         call fill_holes_sedimentation( dt, ncol, rc_start, state%pdel, &
    3127           0 :                                        vtrmc, state%zi, qmin(ixcldliq), &
    3128           0 :                                        rc_tend, precl )
    3129             : 
    3130             :         ! Occasionally, a situation can occur where filling a hole in rain can
    3131             :         ! deplete all the surface liquid-phase precipitation (precl), resulting
    3132             :         ! in not enough water mass in the vertical profile of cloud water to
    3133             :         ! fill a hole in cloud water.  When this happens, there must be liquid
    3134             :         ! water found in the vertical profile of rain, so pull the water from
    3135             :         ! rain to fill any remaining holes in cloud water.
    3136           0 :         if ( ixrain > 0 ) then
    3137             :            call fill_holes_same_phase_vert( dt, ncol, rc_start, rr_start, &
    3138           0 :                                             state%pdel, qmin(ixcldliq), &
    3139           0 :                                             qmin(ixrain), &
    3140           0 :                                             rc_tend, rr_tend )
    3141             :         endif ! ixrain > 0
    3142             : 
    3143             :         ! This section makes use of the following principle:
    3144             :         !
    3145             :         ! 4) When adjusting the hydrometeor tendency from sedimentation of a
    3146             :         !    frozen hydrometeor (cloud ice or snow), conserve:
    3147             :         !
    3148             :         !    SUM(k=top_lev:pver) ( ri_sed_tend(k) + rs_sed_tend(k) )
    3149             :         !                        * dt * pdel(k) / g
    3150             :         !    + preci * dt * 1000 = 0.
    3151             : 
    3152             :         ! Call the sedimentation hole filler for snow mixing ratio.
    3153             :         ! This can update rs_tend and preci.
    3154           0 :         if ( ixsnow > 0 ) then
    3155             :            call fill_holes_sedimentation( dt, ncol, rs_start, state%pdel, &
    3156           0 :                                           ums, state%zi, qmin(ixsnow), &
    3157           0 :                                           rs_tend, preci )
    3158             :         endif ! ixsnow > 0
    3159             : 
    3160             :         ! Call the sedimentation hole filler for cloud ice mixing ratio.
    3161             :         ! This can update ri_tend and preci.
    3162             :         call fill_holes_sedimentation( dt, ncol, ri_start, state%pdel, &
    3163           0 :                                        vtrmi, state%zi, qmin(ixcldice), &
    3164           0 :                                        ri_tend, preci )
    3165             : 
    3166             :         ! Occasionally, a situation can occur where filling a hole in snow can
    3167             :         ! deplete all the surface ice-phase precipitation (preci), resulting
    3168             :         ! in not enough water mass in the vertical profile of cloud ice to
    3169             :         ! fill a hole in cloud ice.  When this happens, there must be ice-phase
    3170             :         ! water found in the vertical profile of snow, so pull the water from
    3171             :         ! snow to fill any remaining holes in cloud ice.
    3172           0 :         if ( ixsnow > 0 ) then
    3173             :            call fill_holes_same_phase_vert( dt, ncol, ri_start, rs_start, &
    3174           0 :                                             state%pdel, qmin(ixcldice), &
    3175           0 :                                             qmin(ixsnow), &
    3176           0 :                                             ri_tend, rs_tend )
    3177             :         endif  ! ixsnow > 0
    3178             : 
    3179             :         ! Update the total precipitation rate (prect) from the updated liquid
    3180             :         ! precipitation rate (precl) and the updated frozen preciptation rate
    3181             :         ! (preci).
    3182           0 :         prect(:ncol) = precl(:ncol) + preci(:ncol)
    3183             : 
    3184             :         ! The MG code sets prec_str equal to prect (prec_pcw) and snow_str equal
    3185             :         ! to preci (snow_pcw).  The prec_str and snow_str variables are used
    3186             :         ! in the calculations for energy and water conservation.  Since prect
    3187             :         ! and preci are adjusted here, when necessary, prec_str and snow_str
    3188             :         ! also need to be adjusted.
    3189           0 :         prec_str(:ncol) = prect(:ncol)
    3190           0 :         snow_str(:ncol) = preci(:ncol)
    3191             : 
    3192             :      endif ! l_sed_hole_fill
    3193             : 
    3194             :      ! The updated total microphysics tendencies after hole filling have not
    3195             :      ! been used to update ptend yet, so record the budget terms for hole
    3196             :      ! filling first.
    3197           0 :      rv_hf_tend = rv_tend - ptend%q(:,:,1)
    3198           0 :      rc_hf_tend = rc_tend - ptend%q(:,:,ixcldliq)
    3199           0 :      if ( ixrain > 0 ) then
    3200           0 :         rr_hf_tend = rr_tend - ptend%q(:,:,ixrain)
    3201             :      endif ! ixrain > 0
    3202           0 :      ri_hf_tend = ri_tend - ptend%q(:,:,ixcldice)
    3203           0 :      if ( ixsnow > 0 ) then
    3204           0 :         rs_hf_tend = rs_tend - ptend%q(:,:,ixsnow)
    3205             :      endif ! ixsnow > 0
    3206             : 
    3207             :      ! The updated dry static energy tendency after hole filling has not been
    3208             :      ! used to update ptend yet, so record the budget term for hole filling
    3209             :      ! first.
    3210           0 :      s_hf_tend = stend - ptend%s
    3211             : 
    3212             :      ! Pack the current total tendencies for hydrometeor mixing ratio fields.
    3213           0 :      ptend%q(:,:,1) = rv_tend
    3214           0 :      ptend%q(:,:,ixcldliq) = rc_tend
    3215           0 :      if ( ixrain > 0 ) then
    3216           0 :         ptend%q(:,:,ixrain) = rr_tend
    3217             :      endif
    3218           0 :      ptend%q(:,:,ixcldice) = ri_tend
    3219           0 :      if ( ixsnow > 0 ) then
    3220           0 :         ptend%q(:,:,ixsnow) = rs_tend
    3221             :      endif
    3222             : 
    3223             :      ! Pack the current tendency for dry static energy.
    3224           0 :      ptend%s = stend
    3225             : 
    3226             :      ! Output stats for hole filling tendencies.
    3227           0 :      call outfld( 'QVHFTEN', rv_hf_tend, pcols, state%lchnk )
    3228           0 :      call outfld( 'QCHFTEN', rc_hf_tend, pcols, state%lchnk )
    3229           0 :      call outfld( 'QRHFTEN', rr_hf_tend, pcols, state%lchnk )
    3230           0 :      call outfld( 'QIHFTEN', ri_hf_tend, pcols, state%lchnk )
    3231           0 :      call outfld( 'QSHFTEN', rs_hf_tend, pcols, state%lchnk )
    3232           0 :      call outfld( 'THFTEN', s_hf_tend / cpair, pcols, state%lchnk )
    3233             : 
    3234             :      ! Perform total water and total energy conservation checks.
    3235             :      if ( l_check_conservation ) then
    3236             : 
    3237             :         ! Calculate total water in each grid column.
    3238             :         ! This calculation is the vertically-integrated grand total water
    3239             :         ! in each grid column updated for all microphysics and hole filling.
    3240             :         ! This includes the amount that precipitated to the surface.
    3241           0 :         do icol = 1, ncol
    3242           0 :            grand_total_water_column_finish(icol) = 0.0_r8
    3243           0 :            do k = top_lev, pver
    3244             :               grand_total_water_column_finish(icol) &
    3245             :               = grand_total_water_column_finish(icol) &
    3246           0 :                 + ( state%q(icol,k,1) &
    3247           0 :                     + ptend%q(icol,k,1) * dt &
    3248           0 :                     + state%q(icol,k,ixcldliq) &
    3249           0 :                     + ptend%q(icol,k,ixcldliq) * dt &
    3250           0 :                     + state%q(icol,k,ixcldice) &
    3251           0 :                     + ptend%q(icol,k,ixcldice) * dt ) &
    3252           0 :                   * state%pdel(icol,k) * rga
    3253           0 :               if ( ixrain > 0 ) then
    3254             :                  grand_total_water_column_finish(icol) &
    3255             :                  = grand_total_water_column_finish(icol) &
    3256           0 :                    + ( state%q(icol,k,ixrain) + ptend%q(icol,k,ixrain) * dt ) &
    3257           0 :                      * state%pdel(icol,k) * rga
    3258             :               endif
    3259           0 :               if ( ixsnow > 0 ) then
    3260             :                  grand_total_water_column_finish(icol) &
    3261             :                  = grand_total_water_column_finish(icol) &
    3262           0 :                    + ( state%q(icol,k,ixsnow) + ptend%q(icol,k,ixsnow) * dt ) &
    3263           0 :                      * state%pdel(icol,k) * rga
    3264             :               endif
    3265             :            end do ! k = top_lev, pver
    3266             :            grand_total_water_column_finish(icol) &
    3267             :            = grand_total_water_column_finish(icol) &
    3268           0 :              + prect(icol) * dt * 1000.0_r8
    3269             :         end do ! icol = 1, ncol
    3270             : 
    3271             :         ! Calculate total energy in each column.
    3272             :         ! This calculation is the vertically-integrated total energy in each
    3273             :         ! grid column updated for all microphysics and hole filling.  This
    3274             :         ! includes the amount that precipitated to the surface.  Since, the
    3275             :         ! microphysics code does not directly change kinetic energy,
    3276             :         ! 0.5 * ( u^2 + v^2 ), it can be skipped as part of the energy
    3277             :         ! conservation check.
    3278           0 :         do icol = 1, ncol
    3279           0 :            total_energy_column_finish(icol) = 0.0_r8
    3280           0 :            do k = top_lev, pver
    3281             :               total_energy_column_finish(icol) &
    3282             :               = total_energy_column_finish(icol) &
    3283           0 :                 + ( state%s(icol,k) + ptend%s(icol,k) * dt &
    3284             :                     + ( latvap + latice ) &
    3285           0 :                       * ( state%q(icol,k,1) + ptend%q(icol,k,1) * dt ) &
    3286           0 :                     + latice * ( state%q(icol,k,ixcldliq) &
    3287           0 :                                  + ptend%q(icol,k,ixcldliq) * dt ) ) &
    3288           0 :                   * state%pdel(icol,k) * rga
    3289           0 :               if ( ixrain > 0 ) then
    3290             :                  total_energy_column_finish(icol) &
    3291             :                  = total_energy_column_finish(icol) &
    3292           0 :                    + latice * ( state%q(icol,k,ixrain) &
    3293           0 :                                 + ptend%q(icol,k,ixrain) * dt ) &
    3294           0 :                      * state%pdel(icol,k) * rga
    3295             :               endif
    3296             :            end do ! k = top_lev, pver
    3297             :            total_energy_column_finish(icol) &
    3298             :            = total_energy_column_finish(icol) &
    3299           0 :              + latice * precl(icol) * dt * 1000.0_r8
    3300             :         end do ! icol = 1, ncol
    3301             : 
    3302             :         ! Calculate the total relative error in each grid column.
    3303           0 :         do icol = 1, ncol
    3304             : 
    3305           0 :            tot_water_rel_err(icol) &
    3306             :            = abs( ( grand_total_water_column_finish(icol) &
    3307             :                     - grand_total_water_column_start(icol) ) ) &
    3308             :              / min( grand_total_water_column_finish(icol), &
    3309           0 :                     grand_total_water_column_start(icol) )
    3310             : 
    3311             :            tot_energy_rel_err(icol) &
    3312             :            = abs( ( total_energy_column_finish(icol) &
    3313             :                     - total_energy_column_start(icol) ) ) &
    3314             :              / min( total_energy_column_finish(icol), &
    3315           0 :                     total_energy_column_start(icol) )
    3316             : 
    3317             :         end do ! icol = 1, ncol
    3318             : 
    3319             :         ! Print an error message if any total water relative error is found to
    3320             :         ! be greater than the threshold.
    3321           0 :         if ( any( tot_water_rel_err(:ncol) >= err_thresh ) ) then
    3322           0 :            write(iulog,*) "Water conservation error reported in hole filling"
    3323           0 :            do icol = 1, ncol
    3324           0 :               if ( tot_water_rel_err(icol) >= err_thresh ) then
    3325           0 :                  write(iulog,*) "Column = ", icol, &
    3326           0 :                           "Relative error = ", tot_water_rel_err(icol), &
    3327           0 :                           "Column-integrated grand total water at start = ", &
    3328           0 :                           grand_total_water_column_start(icol), &
    3329           0 :                           "Column-integrated grand total water at finish = ", &
    3330           0 :                           grand_total_water_column_finish(icol)
    3331             :               endif ! tot_water_rel_err(icol) >= err_thresh
    3332             :            end do ! icol = 1, ncol
    3333             :         endif ! any( tot_water_rel_err >= err_thresh )
    3334             : 
    3335             :         ! Print an error message if any total energy relative error is found to
    3336             :         ! be greater than the threshold.
    3337           0 :         if ( any( tot_energy_rel_err(:ncol) >= err_thresh ) ) then
    3338           0 :            write(iulog,*) "Energy conservation error reported in hole filling"
    3339           0 :            do icol = 1, ncol
    3340           0 :               if ( tot_energy_rel_err(icol) >= err_thresh ) then
    3341           0 :                  write(iulog,*) "Column = ", icol, &
    3342           0 :                           "Relative error = ", tot_energy_rel_err(icol), &
    3343           0 :                           "Column-integrated total energy at start = ", &
    3344           0 :                           total_energy_column_start(icol), &
    3345           0 :                           "Column-integrated total energy at finish = ", &
    3346           0 :                           total_energy_column_finish(icol)
    3347             :               endif ! tot_energy_rel_err(icol) >= err_thresh
    3348             :            end do ! icol = 1, ncol
    3349             :         endif ! any( tot_energy_rel_err >= err_thresh )
    3350             : 
    3351             :      endif ! l_check_conservation
    3352             : 
    3353             : 
    3354           0 :      return
    3355             : 
    3356           0 :    end subroutine subcol_SILHS_fill_holes_conserv
    3357             : 
    3358             :    !============================================================================
    3359           0 :    subroutine fill_holes_sedimentation( dt, ncol, hm_start, pdel, &
    3360             :                                         fallspeed_m_per_s, zi, qmin_hm, &
    3361             :                                         hm_tend, prec )
    3362             : 
    3363             :      ! Description:
    3364             :      ! After hydrometeor tendencies from microphysics processes were adjusted
    3365             :      ! so that holes don't form in a hydrometeor field from microphysics
    3366             :      ! processes, the sedimentation tendency was added back on to produce an
    3367             :      ! updated total microphysics tendency.  The first-order "up-gravity"
    3368             :      ! sedimentation method that was originally used is positive definite.
    3369             :      ! However, since the microphysics process tendencies were altered so that
    3370             :      ! holes don't form, it is possible that adding the old sedimentation
    3371             :      ! tendencies back onto the new microphysics process tendencies could
    3372             :      ! produce new total microphysics tendencies that cause holes to form.
    3373             :      !
    3374             :      ! In this subroutine, holes in a hydrometeor field are checked for after
    3375             :      ! the updated microphysics tendency is applied.  If any are found, they are
    3376             :      ! filled from positive hydrometeor mass found at grid levels below where
    3377             :      ! the hole is found.  The levels that are used to fill are within range
    3378             :      ! based on fallspeed of the hydrometeor.  If the level that contains the
    3379             :      ! hole is within proximity to the surface, then the water that sedimented
    3380             :      ! to the surface can be used to fill the hole, as well.
    3381             :      !
    3382             :      ! If there isn't enough total hydrometeor mass within the fall range to
    3383             :      ! fill the hole, then positive hydrometeor mass from levels below the fall
    3384             :      ! range is to be added to the total available mass to fill the hole.  Mass
    3385             :      ! is added one level at a time until enough mass is found to fill the hole
    3386             :      ! or until the surface is reached and the surface precipitation is added to
    3387             :      ! the total available fill mass.
    3388             :      !
    3389             :      ! After this, if there still isn't enough available mass to fill the hole,
    3390             :      ! then positive hydrometeor mass is added from all levels above the hole to
    3391             :      ! the total mass that is available to fill the hole.
    3392             : 
    3393             :      !----------------------------------------------------------------------
    3394             : 
    3395           0 :      use ppgrid, only: &
    3396             :          pcols
    3397             : 
    3398             :      use ref_pres, only: &
    3399             :          top_lev => trop_cloud_top_lev
    3400             : 
    3401             :      implicit none
    3402             : 
    3403             :      ! Input Variables
    3404             :      real(r8), intent(in) :: dt                   ! Time step duration
    3405             : 
    3406             :      integer, intent(in) :: ncol                  ! Number of grid columns
    3407             : 
    3408             :      real(r8), dimension(pcols,pver), intent(in) :: &
    3409             :        hm_start, & ! Hydrometeor mixing ratio at start of microphysics  [kg/kg]
    3410             :        pdel        ! Pressure difference between grid levels            [Pa]
    3411             : 
    3412             :      real(r8), dimension(pcols,pver), intent(in) :: &
    3413             :        fallspeed_m_per_s    ! Hydrometeor mixing ratio fall speed     [m/s]
    3414             : 
    3415             :      real(r8), dimension(pcols,pverp), intent(in) :: &
    3416             :        zi    ! Height of momentum (interface) grid levels    [m]
    3417             : 
    3418             :      real(r8), intent(in) :: &
    3419             :        qmin_hm    ! Minimum threshold value of hydrometeor mixing ratio  [kg/kg]
    3420             : 
    3421             :      ! Input/Output Variables
    3422             :      real(r8), dimension(pcols,pver), intent(inout) :: &
    3423             :        hm_tend    ! Hydrometeor mixing ratio tendency  [kg/kg/s]
    3424             : 
    3425             :      real(r8), dimension(pcols), intent(inout) :: &
    3426             :        prec    ! Precipitation rate (surface)        [m/s]
    3427             : 
    3428             :      ! Local Variables
    3429             :      real(r8), dimension(pver) :: &
    3430             :        hm_update, & ! Hydrometeor mixing ratio; start of sed. hole fill  [kg/kg]
    3431             :        hm_curr      ! Current value of hydrometeor mixing ratio          [kg/kg]
    3432             : 
    3433             :      real(r8) :: &
    3434             :        total_hole,          & ! Total mass of hole in hydrometeor       [kg/m^2]
    3435             :        total_fill_mass,     & ! Total mass available to fill hole       [kg/m^2]
    3436             :        hole_fillmass_ratio, & ! Ratio: total_hole / total_fill_mass     [-]
    3437             :        fallspeed_Pa_per_s,  & ! Hydrometeor mixing ratio fall speed     [Pa/s]
    3438             :        total_fall_Pa,       & ! Pressure "distance" hydrometeor fell    [Pa]
    3439             :        sum_pdel               ! Sum of pdel over levels                 [Pa]
    3440             : 
    3441             :      logical, dimension(pver) :: &
    3442             :        l_pos_hm  ! Flag for a hydrometeor having a positive (>= qmin_hm) value
    3443             : 
    3444             :      ! Flag for whether surface precipitation mass needs to be included in
    3445             :      ! the total_fill_mass for hole filling.
    3446             :      logical :: l_reached_surface
    3447             : 
    3448             :      ! Flag for whether hydrometeor mass from levels above the hole needs to be
    3449             :      ! included in the total_fill_mass for hole filling.
    3450             :      logical :: l_fill_from_above
    3451             : 
    3452             :      integer :: icol  ! Grid column index
    3453             : 
    3454             :      integer :: k, idx  ! Vertical grid level indices
    3455             : 
    3456             :      ! Index of the lowest vertical grid level that needs to be included in the
    3457             :      ! total_fill_mass for hole filling.
    3458             :      integer :: lowest_level_idx
    3459             : 
    3460             : 
    3461             :      ! Loop over all columns, performing any adjustments one column at a time.
    3462           0 :      do icol = 1, ncol
    3463             : 
    3464             :         ! Calculate the updated value of the hydrometeor field based on the
    3465             :         ! updated microphysics tendency.  Since the original sedimentation
    3466             :         ! tendency has been added to the updated microphysics process tendency
    3467             :         ! to produce the updated total microphysics tendency (hm_tend), the
    3468             :         ! updated value of the hydrometeor field (hm_update) could be negative.
    3469           0 :         hm_update = hm_start(icol,:) + hm_tend(icol,:) * dt
    3470           0 :         hm_curr = hm_update
    3471             : 
    3472             :         ! Check for any holes in the vertical profile
    3473           0 :         if ( any( hm_curr(top_lev:pver) < qmin_hm ) ) then
    3474             : 
    3475             :            ! At least one hole is found in this hydrometeor species in this
    3476             :            ! grid column.  The holes must be filled conservatively.
    3477             : 
    3478             :            ! Check which levels have values of the hydrometeor that are at or
    3479             :            ! above the minimum threshold value.
    3480           0 :            do k = top_lev, pver
    3481           0 :               if ( hm_curr(k) >= qmin_hm ) then
    3482           0 :                 l_pos_hm(k) = .true.
    3483             :               else ! hm_curr < qmin_hm
    3484           0 :                 l_pos_hm(k) = .false.
    3485             :               endif ! hm_curr >= qmin_hm
    3486             :            end do ! k = top_lev, pver
    3487             : 
    3488           0 :            do k = pver, top_lev, -1
    3489             : 
    3490           0 :               if ( .not. l_pos_hm(k) ) then
    3491             : 
    3492             :                  ! A hole is found in the hydrometeor at this grid level.
    3493             : 
    3494             :                  ! Calculate the total hydrometeor mass of the hole that needs
    3495             :                  ! to be filled.
    3496             :                  ! The value of the hydrometeor mixing ratio is negative, but
    3497             :                  ! the value of total_hole is positive.
    3498           0 :                  total_hole = ( qmin_hm - hm_curr(k) ) * pdel(icol,k) * rga
    3499             : 
    3500             :                  ! Calculate the total hydrometeor mass available from below
    3501             :                  ! to fill the hole.
    3502           0 :                  if ( k == pver ) then
    3503             : 
    3504             :                     ! A hole is found at the lowermost level.
    3505             :                     ! The only place the hydrometeor could have sedimented
    3506             :                     ! to is the surface, so fill from only the surface.
    3507           0 :                     l_reached_surface = .true.
    3508             : 
    3509             :                     ! Calculate the available amount of hydrometeor mass to
    3510             :                     ! fill the hole.
    3511           0 :                     total_fill_mass = prec(icol) * dt * 1000.0_r8
    3512             : 
    3513             :                  else ! top_lev <= k < pver
    3514             : 
    3515             :                     ! Calculate the hydrometeor fallspeed in Pa/s.
    3516             :                     ! In MG2, the equation for this is given by:
    3517             :                     !
    3518             :                     ! fallspeed([Pa/s]) = g * rho * fallspeed([m/s]).
    3519             :                     !
    3520             :                     ! The value of rho is typically calculated from the
    3521             :                     ! hydrostatic approximation:
    3522             :                     !
    3523             :                     ! rho = - ( 1 / g ) * dp/dz.
    3524             :                     !
    3525             :                     ! The equation for fallspeed in Pa/s becomes:
    3526             :                     !
    3527             :                     ! fallspeed([Pa/s]) = - dp/dz * fallspeed([m/s]).
    3528             :                     fallspeed_Pa_per_s &
    3529             :                     = fallspeed_m_per_s(icol,k) &
    3530           0 :                       * pdel(icol,k) / ( zi(icol,k) - zi(icol,k+1) )
    3531             : 
    3532             :                     ! Calculate the fall "distance" in Pa.
    3533           0 :                     total_fall_Pa = fallspeed_Pa_per_s * dt
    3534             : 
    3535             :                     ! Find the index of the vertical level that the hydrometeor
    3536             :                     ! sedimented to in one timestep.  It must sediment at least
    3537             :                     ! one level.
    3538           0 :                     sum_pdel = 0.0_r8
    3539           0 :                     idx = k + 1
    3540           0 :                     do
    3541             :                        ! Update the total pressure difference between the
    3542             :                        ! level of origin and the current level.
    3543           0 :                        sum_pdel = sum_pdel + pdel(icol,idx)
    3544           0 :                        if ( sum_pdel >= total_fall_Pa ) then
    3545             :                           ! The total pressure difference between the level of
    3546             :                           ! origin and the current level exceeds the total
    3547             :                           ! hydrometeor fall "distance" (in Pa).
    3548             :                           lowest_level_idx = idx
    3549             :                           l_reached_surface = .false.
    3550             :                           exit
    3551             :                        else ! sum_pdel < total_fall_Pa
    3552             :                           ! The total hydrometeor fall "distance" (in Pa)
    3553             :                           ! exceeds the total pressure difference between the
    3554             :                           ! level of origin and the current level.
    3555           0 :                           if ( idx == pver ) then
    3556             :                              ! The lowest level of the model has been reached.
    3557             :                              ! The hydrometeor sedimented to the surface.
    3558             :                              lowest_level_idx = pver
    3559             :                              l_reached_surface = .true.
    3560             :                              exit
    3561             :                           else ! idx < pver
    3562             :                              ! Increment idx and keep going.
    3563           0 :                              idx = idx + 1
    3564             :                           endif ! idx == pver
    3565             :                        endif ! sum_pdel >= total_fall_Pa
    3566             :                     end do
    3567             : 
    3568             :                     ! Calculate the available amount of hydrometeor mass to
    3569             :                     ! fill the hole.
    3570             :                     total_fill_mass = 0.0_r8
    3571             :                     if ( l_reached_surface ) then
    3572             :                        ! The hydrometeor sedimented to the surface, so
    3573             :                        ! automatically loop down to pver and include the
    3574             :                        ! surface mass.
    3575           0 :                        do idx = k+1, pver, 1
    3576           0 :                           if ( l_pos_hm(idx) ) then
    3577             :                              total_fill_mass &
    3578             :                              = total_fill_mass &
    3579             :                                + ( hm_curr(idx) - qmin_hm ) &
    3580           0 :                                  * pdel(icol,idx) * rga
    3581             :                           endif ! l_pos_hm(idx)
    3582             :                        end do ! idx = k+1, pver, 1
    3583             :                        ! Contribution to total fill mass from the surface.
    3584             :                        total_fill_mass &
    3585           0 :                        = total_fill_mass + prec(icol) * dt * 1000.0_r8
    3586             :                     else ! .not. l_reached_surface
    3587             :                        ! The hydrometeor sedimented to lowest_level_idx.
    3588             :                        idx = k + 1
    3589             :                        do
    3590           0 :                           if ( l_pos_hm(idx) ) then
    3591             :                              total_fill_mass &
    3592             :                              = total_fill_mass &
    3593             :                                + ( hm_curr(idx) - qmin_hm ) &
    3594           0 :                                  * pdel(icol,idx) * rga
    3595             :                           endif ! l_pos_hm(idx)
    3596           0 :                           if ( idx >= lowest_level_idx ) then
    3597             :                              ! Check if enough mass has been gathered in
    3598             :                              ! total_fill_mass to fill the hole.
    3599           0 :                              if ( total_fill_mass >= total_hole ) then
    3600             :                                 ! There has been enough total_fill_mass
    3601             :                                 ! gathered to completely fill the hole.
    3602             :                                 lowest_level_idx = idx
    3603             :                                 exit
    3604             :                              else ! total_fill_mass < total_hole
    3605             :                                 ! Even though lowest_level_idx has been reached,
    3606             :                                 ! more total_fill_mass needs to be added in
    3607             :                                 ! order to completely fill the hole, so keep
    3608             :                                 ! going.
    3609           0 :                                 if ( idx == pver ) then
    3610             :                                    ! The lowest vertical level has already been
    3611             :                                    ! reached, so go to the surface.
    3612           0 :                                    lowest_level_idx = pver
    3613           0 :                                    l_reached_surface = .true.
    3614             :                                    ! Contribution to total fill mass from the
    3615             :                                    ! surface.
    3616             :                                    total_fill_mass &
    3617             :                                    = total_fill_mass &
    3618           0 :                                      + prec(icol) * dt * 1000.0_r8
    3619           0 :                                    exit
    3620             :                                 else ! idx < pver
    3621             :                                    ! Haven't reached pver yet, so increment
    3622             :                                    ! and keep going.
    3623           0 :                                    idx = idx + 1
    3624             :                                 endif ! idx == pver
    3625             :                              endif ! total_fill_mass >= total_hole
    3626             :                           else ! idx < lowest_level_idx
    3627             :                              ! Haven't reached lowest_level_idx yet, so
    3628             :                              ! increment and keep going.
    3629           0 :                              idx = idx + 1
    3630             :                           endif ! idx >= lowest_level_idx
    3631             :                        end do
    3632             :                     endif ! l_reached_surface
    3633             : 
    3634             :                  endif ! k == pver
    3635             : 
    3636             :                  ! If mass has been added all the way down to the surface and
    3637             :                  ! there's still not enough mass to fill the hole, then fill the
    3638             :                  ! hole pulling mass from above.
    3639           0 :                  if ( total_fill_mass >= total_hole ) then
    3640             :                     l_fill_from_above = .false.
    3641             :                  else ! total_fill_mass < total_hole
    3642           0 :                     l_fill_from_above = .true.
    3643           0 :                     do idx = top_lev, k-1, 1
    3644           0 :                        if ( l_pos_hm(idx) ) then
    3645             :                           total_fill_mass &
    3646             :                           = total_fill_mass &
    3647             :                             + ( hm_curr(idx) - qmin_hm ) &
    3648           0 :                               * pdel(icol,idx) * rga
    3649             :                        endif ! l_pos_hm(idx)
    3650             :                     end do ! idx = top_lev, k-1, 1
    3651             :                  endif ! total_fill_mass >= total_hole
    3652             : 
    3653             :                  ! Calculate the ratio of total hole to total fill mass.  This
    3654             :                  ! should not exceed 1 except as a result of numerical round-off
    3655             :                  ! errors.  Use thresholding to be safe.
    3656             :                  hole_fillmass_ratio &
    3657             :                  = min( total_hole / max( total_fill_mass, 1.0e-30_r8 ), &
    3658           0 :                         1.0_r8 )
    3659             : 
    3660           0 :                  if ( k < pver ) then
    3661             :                     ! Modify (reduce) the amount of the hydrometeor at levels
    3662             :                     ! that were used to fill the hole.
    3663           0 :                     do idx = k+1, lowest_level_idx
    3664           0 :                        if ( l_pos_hm(idx) ) then
    3665             :                           ! Since pdel at a grid level does not change and
    3666             :                           ! gravit is constant, the only variable that needs to
    3667             :                           ! be modified proportionately is hm_curr.
    3668             :                           hm_curr(idx) &
    3669             :                           = qmin_hm &
    3670             :                             + ( hm_curr(idx) - qmin_hm ) &
    3671           0 :                               * ( 1.0_r8 - hole_fillmass_ratio )
    3672             :                        endif ! l_pos_hm(idx)
    3673             :                     end do ! idx = k+1, lowest_level_idx
    3674             :                  endif ! k < pver
    3675             : 
    3676           0 :                  if ( l_reached_surface ) then
    3677             :                     ! Modify (reduce) the amount of surface precipitation in
    3678             :                     ! order to fill the hole.  Since dt and 1000 are constants,
    3679             :                     ! the only variable that needs to be modified
    3680             :                     ! proportionately is prec.
    3681           0 :                     prec(icol) = prec(icol) * ( 1.0_r8 - hole_fillmass_ratio )
    3682             :                  endif ! l_reached_surface
    3683             : 
    3684           0 :                  if ( l_fill_from_above ) then
    3685             :                     ! Modify (reduce) the amount of the hydrometeor at levels
    3686             :                     ! that were used to fill the hole.
    3687           0 :                     do idx = top_lev, k-1
    3688           0 :                        if ( l_pos_hm(idx) ) then
    3689             :                           ! Since pdel at a grid level does not change and
    3690             :                           ! gravit is constant, the only variable that needs to
    3691             :                           ! be modified proportionately is hm_curr.
    3692             :                           hm_curr(idx) &
    3693             :                           = qmin_hm &
    3694             :                             + ( hm_curr(idx) - qmin_hm ) &
    3695           0 :                               * ( 1.0_r8 - hole_fillmass_ratio )
    3696             :                        endif ! l_pos_hm(idx)
    3697             :                     end do ! idx = top_lev, k-1
    3698             :                  endif ! l_fill_from_above
    3699             : 
    3700             :                  ! Update the value of the hydrometeor at the level where the
    3701             :                  ! hole was found.  Mathematically, as long as the available
    3702             :                  ! mass was able to fill the entire hole, the new value of the
    3703             :                  ! hydrometeor mixing ratio (hm_curr) should be qmin_hm.
    3704             :                  hm_curr(k) &
    3705             :                  = hm_curr(k) &
    3706             :                    + hole_fillmass_ratio * total_fill_mass &
    3707           0 :                      * gravit / pdel(icol,k)
    3708             : 
    3709             :               endif ! .not. l_pos_hm(k)
    3710             : 
    3711             :            end do ! k = pver, top_lev, -1
    3712             : 
    3713             :         endif ! any( hm_curr(top_lev:pver) < qmin_hm )
    3714             : 
    3715             :         ! Update the value of total microphysics tendency after hole filling.
    3716           0 :         hm_tend(icol,:) = hm_tend(icol,:) + ( hm_curr - hm_update ) / dt
    3717             : 
    3718             :      end do ! icol = 1, ncol
    3719             : 
    3720             : 
    3721           0 :      return
    3722             : 
    3723           0 :    end subroutine fill_holes_sedimentation
    3724             : 
    3725             :    !============================================================================
    3726           0 :    subroutine fill_holes_same_phase_vert( dt, ncol, hm_start, hm_start_filler, &
    3727             :                                           pdel, qmin_hm, qmin_hm_filler, &
    3728             :                                           hm_tend, hm_tend_filler )
    3729             : 
    3730             :      ! Description:
    3731             :      ! Fills remaining holes in a hydrometeor with mass from the the vertical
    3732             :      ! profile of another hydrometeor of the same phase.  Remaining holes in
    3733             :      ! cloud water are filled with rain water and remaining holes in snow are
    3734             :      ! filled with cloud ice.
    3735             :      !
    3736             :      ! This subroutine, combined with subroutine fill_holes_sedimentation, fill
    3737             :      ! holes making use of the following principles:
    3738             :      !
    3739             :      ! 3) When adjusting the hydrometeor tendency from sedimentation of a
    3740             :      !    liquid hydrometeor (cloud water or rain water), conserve:
    3741             :      !
    3742             :      !    SUM(k=top_lev:pver) ( rc_sed_tend(k) + rr_sed_tend(k) )
    3743             :      !                        * dt * pdel(k) / g
    3744             :      !    + precl * dt * 1000 = 0.
    3745             :      !
    3746             :      ! 4) When adjusting the hydrometeor tendency from sedimentation of a
    3747             :      !    frozen hydrometeor (cloud ice or snow), conserve:
    3748             :      !
    3749             :      !    SUM(k=top_lev:pver) ( ri_sed_tend(k) + rs_sed_tend(k) )
    3750             :      !                        * dt * pdel(k) / g
    3751             :      !    + preci * dt * 1000 = 0.
    3752             :      !
    3753             :      ! These two equations (one for liquid-phase hydrometeors and one for
    3754             :      ! ice-phase hydrometeors) could be further split into one equation for
    3755             :      ! each hydrometeor if there was prec output for each hydrometeor.  However,
    3756             :      ! there's only prec output for ice-phase precipitation rate and total
    3757             :      ! precipitation rate (liquid preciptation rate is total rate minus
    3758             :      ! ice-phase rate).
    3759             :      !
    3760             :      ! Since only liquid-phase precipitation rate (precl) and ice-phase
    3761             :      ! precipitation rate (preci) are available, and there are two hydrometeors
    3762             :      ! in each category, one hydrometeor from each category must fill before
    3763             :      ! the other hydrometeor from its category and get priority access to precl
    3764             :      ! or preci.  Since a vast majority of liquid precipitation comes from rain
    3765             :      ! rather than sedimenting cloud water, rain is filled before cloud water
    3766             :      ! and gets priority access to precl.  Likewise, since a vast majority of
    3767             :      ! frozen precipitation comes from snow rather than sedimenting cloud ice,
    3768             :      ! snow is filled before cloud ice and gets priority access to preci.
    3769             :      !
    3770             :      ! The order of sedimentation hole filling is as follows.  First, a level
    3771             :      ! with a hole in it is identified.  The fall distance for the hydrometeor
    3772             :      ! that originated at a level is calculated.  Total mass to fill the hole is
    3773             :      ! calculated from all levels within the fall range that have positive
    3774             :      ! values of the hydrometeor.  The amount that precipitated to the surface
    3775             :      ! is also included if the hydrometeor fell that far.  If that isn't enough
    3776             :      ! mass to fill the hole, then levels that are lower in the profile are
    3777             :      ! included (if the hydrometeor has a positive value) until enough mass is
    3778             :      ! found to fill the hole or until the surface is reached.  If there isn't
    3779             :      ! enough mass found in all levels below the hole, including the amount that
    3780             :      ! precipitated to the ground, to fill the hole, then the hydrometeor mass
    3781             :      ! from all levels above the hole (again, where a positive value of the
    3782             :      ! hydrometeor is found) are included in the total available mass to fill
    3783             :      ! the hole.
    3784             :      !
    3785             :      ! Occasionally, a situation can occur where both hydrometeors in a category
    3786             :      ! contributed to surface precipitation rate, and filling a hole in rain
    3787             :      ! (or snow) can deplete all the surface precl (or preci), resulting in not
    3788             :      ! enough water mass in the vertical profile (including the surface) of
    3789             :      ! cloud water (or cloud ice) to fill a hole in cloud water (or cloud ice).
    3790             :      ! When this happens, there must still be liquid water (or frozen water)
    3791             :      ! found in the vertical profile of rain (or snow), so pull the water from
    3792             :      ! rain (or snow) to fill any remaining holes in cloud water (or cloud ice).
    3793             : 
    3794             :      !----------------------------------------------------------------------
    3795             : 
    3796           0 :      use ppgrid, only: &
    3797             :          pcols
    3798             : 
    3799             :      use ref_pres, only: &
    3800             :          top_lev => trop_cloud_top_lev
    3801             : 
    3802             :      implicit none
    3803             : 
    3804             :      ! Input Variables
    3805             :      real(r8), intent(in) :: dt                   ! Time step duration
    3806             : 
    3807             :      integer, intent(in) :: ncol                  ! Number of grid columns
    3808             : 
    3809             :      real(r8), dimension(pcols,pver), intent(in) :: &
    3810             :        hm_start,        & ! Hydrometeor mixing ratio (microphys start)   [kg/kg]
    3811             :        hm_start_filler, & ! Filler hydromet mix ratio (microphys start)  [kg/kg]
    3812             :        pdel               ! Pressure difference between grid levels      [Pa]
    3813             : 
    3814             :      real(r8), intent(in) :: &
    3815             :        qmin_hm,        & ! Minimum threshold hydrometeor mixing ratio  [kg/kg]
    3816             :        qmin_hm_filler    ! Min threshold filler hydromet mixing ratio  [kg/kg]
    3817             : 
    3818             :      ! Input/Output Variables
    3819             :      real(r8), dimension(pcols,pver), intent(inout) :: &
    3820             :        hm_tend,        & ! Hydrometeor mixing ratio tendency         [kg/kg/s]
    3821             :        hm_tend_filler    ! Filler hydrometeor mixing ratio tendency  [kg/kg/s]
    3822             : 
    3823             :      ! Local Variables
    3824             :      real(r8), dimension(pver) :: &
    3825             :        hm_update,        & ! Hydrometeor mixing ratio; start           [kg/kg]
    3826             :        hm_update_filler, & ! Filler Hydrometeor mixing ratio; start    [kg/kg]
    3827             :        hm_curr,          & ! Current hydrometeor mixing ratio          [kg/kg]
    3828             :        hm_curr_filler      ! Current filler hydrometeor mixing ratio   [kg/kg]
    3829             : 
    3830             :      real(r8) :: &
    3831             :        total_hole,          & ! Total mass of hole in hydrometeor       [kg/m^2]
    3832             :        total_fill_mass,     & ! Total mass available to fill hole       [kg/m^2]
    3833             :        hole_fillmass_ratio    ! Ratio: total_hole / total_fill_mass     [-]
    3834             : 
    3835             :      logical, dimension(pver) :: &
    3836             :        l_pos_hm,        & ! Flag: hydrometeor has positive (>= qmin_hm) value
    3837             :        l_pos_hm_filler    ! Flag: filler hydrometeor has positive value
    3838             : 
    3839             :      integer :: icol  ! Grid column index
    3840             : 
    3841             :      integer :: k, idx  ! Vertical grid level indices
    3842             : 
    3843             : 
    3844             :      ! Loop over all columns, performing any adjustments one column at a time.
    3845           0 :      do icol = 1, ncol
    3846             : 
    3847             :         ! Calculate the updated value of the hydrometeor field based on the
    3848             :         ! updated microphysics tendency.
    3849           0 :         hm_update = hm_start(icol,:) + hm_tend(icol,:) * dt
    3850           0 :         hm_curr = hm_update
    3851             : 
    3852             :         ! Calculate the updated value of the filler hydrometeor field based on
    3853             :         ! the updated microphysics tendency.
    3854           0 :         hm_update_filler = hm_start_filler(icol,:) + hm_tend_filler(icol,:) * dt
    3855           0 :         hm_curr_filler = hm_update_filler
    3856             : 
    3857             :         ! Check for any holes in the vertical profile
    3858           0 :         if ( any( hm_curr(top_lev:pver) < qmin_hm ) ) then
    3859             : 
    3860             :            ! At least one hole is found in this hydrometeor species in this
    3861             :            ! grid column.  The holes must be filled conservatively.
    3862             : 
    3863             :            ! Check which levels have values of the hydrometeor that are at or
    3864             :            ! above the minimum threshold value.
    3865           0 :            do k = top_lev, pver
    3866             :               ! Check for the hydrometeor that might need to be filled.
    3867           0 :               if ( hm_curr(k) >= qmin_hm ) then
    3868           0 :                 l_pos_hm(k) = .true.
    3869             :               else ! hm_curr < qmin_hm
    3870           0 :                 l_pos_hm(k) = .false.
    3871             :               endif ! hm_curr >= qmin_hm
    3872             :               ! Check for the filler hydrometeor, as some levels might have
    3873             :               ! numerical round-off level, small negative values.
    3874           0 :               if ( hm_curr_filler(k) >= qmin_hm_filler ) then
    3875           0 :                 l_pos_hm_filler(k) = .true.
    3876             :               else ! hm_curr_filler < qmin_hm_filler
    3877           0 :                 l_pos_hm_filler(k) = .false.
    3878             :               endif ! hm_curr_filler >= qmin_hm_filler
    3879             :            end do ! k = top_lev, pver
    3880             : 
    3881           0 :            do k = top_lev, pver
    3882             : 
    3883           0 :               if ( .not. l_pos_hm(k) ) then
    3884             : 
    3885             :                  ! A hole is found in the hydrometeor at this grid level.
    3886             : 
    3887             :                  ! Calculate the total hydrometeor mass of the hole that needs
    3888             :                  ! to be filled.
    3889             :                  ! The value of the hydrometeor mixing ratio is negative, but
    3890             :                  ! the value of total_hole is positive.
    3891           0 :                  total_hole = ( qmin_hm - hm_curr(k) ) * pdel(icol,k) * rga
    3892             : 
    3893             :                  ! Calculate the total hydrometeor mass available from the
    3894             :                  ! filler hydrometeor to fill the hole.
    3895           0 :                  total_fill_mass = 0.0_r8
    3896           0 :                  do idx = top_lev, pver, 1
    3897           0 :                     if ( l_pos_hm_filler(idx) ) then
    3898             :                         total_fill_mass &
    3899             :                         = total_fill_mass &
    3900             :                           + ( hm_curr_filler(idx) - qmin_hm_filler ) &
    3901           0 :                             * pdel(icol,idx) * rga
    3902             :                      endif ! l_pos_hm_filler(idx)
    3903             :                  end do ! idx = top_lev, pver, 1
    3904             : 
    3905             :                  ! Calculate the ratio of total hole to total fill mass.  This
    3906             :                  ! should not exceed 1 except as a result of numerical round-off
    3907             :                  ! errors.  Use thresholding to be safe.
    3908             :                  hole_fillmass_ratio &
    3909             :                  = min( total_hole / max( total_fill_mass, 1.0e-30_r8 ), &
    3910           0 :                         1.0_r8 )
    3911             : 
    3912             :                  ! Modify (reduce) the amount of the filler hydrometeor.
    3913           0 :                  do idx = top_lev, pver
    3914           0 :                     if ( l_pos_hm_filler(idx) ) then
    3915             :                        ! Since pdel at a grid level does not change and gravit
    3916             :                        ! is constant, the only variable that needs to be
    3917             :                        ! modified proportionately is hm_curr_filler.
    3918             :                        hm_curr_filler(idx) &
    3919             :                        = qmin_hm_filler &
    3920             :                          + ( hm_curr_filler(idx) - qmin_hm_filler ) &
    3921           0 :                            * ( 1.0_r8 - hole_fillmass_ratio )
    3922             :                     endif ! l_pos_hm_filler(idx)
    3923             :                  end do ! idx = top_lev, pver
    3924             : 
    3925             :                  ! Update the value of the hydrometeor at the level where the
    3926             :                  ! hole was found.  Mathematically, as long as the available
    3927             :                  ! mass was able to fill the entire hole, the new value of the
    3928             :                  ! hydrometeor mixing ratio (hm_curr) should be qmin_hm.
    3929             :                  hm_curr(k) &
    3930             :                  = hm_curr(k) &
    3931             :                    + hole_fillmass_ratio * total_fill_mass &
    3932           0 :                      * gravit / pdel(icol,k)
    3933             : 
    3934             :               endif ! .not. l_pos_hm(k)
    3935             : 
    3936             :            end do ! k = top_lev, pver
    3937             : 
    3938             :         endif ! any( hm_curr(top_lev:pver) < qmin_hm )
    3939             : 
    3940             :         ! Update the value of total microphysics tendency after hole filling.
    3941           0 :         hm_tend(icol,:) = hm_tend(icol,:) + ( hm_curr - hm_update ) / dt
    3942             : 
    3943             :         ! Update the value of total microphysics tendency after hole filling for
    3944             :         ! the filler hydrometeor.
    3945             :         hm_tend_filler(icol,:) &
    3946           0 :         = hm_tend_filler(icol,:) + ( hm_curr_filler - hm_update_filler ) / dt
    3947             : 
    3948             :      end do ! icol = 1, ncol
    3949             : 
    3950             : 
    3951           0 :      return
    3952             : 
    3953           0 :    end subroutine fill_holes_same_phase_vert
    3954             : 
    3955             :    !============================================================================
    3956           0 :    subroutine subcol_SILHS_hydromet_conc_tend_lim( state, dt, ptend )
    3957             : 
    3958             :      ! Description:
    3959             :      ! Limits the values of mean hydrometeor concentrations so that the mean
    3960             :      ! drop size for the hydrometeor type remains reasonable and does not become
    3961             :      ! too large.
    3962             : 
    3963             :      !----------------------------------------------------------------------
    3964             : 
    3965           0 :      use shr_const_mod, only: &
    3966             :          shr_const_pi, &
    3967             :          shr_const_rhofw
    3968             : 
    3969             :      use constituents, only: &
    3970             :          qmin
    3971             : 
    3972             :      use ref_pres, only: &
    3973             :          top_lev => trop_cloud_top_lev
    3974             : 
    3975             :      implicit none
    3976             : 
    3977             :      ! Input Variables
    3978             :      type(physics_state), intent(in) :: state     ! Physics state variables
    3979             :      real(r8), intent(in) :: dt                   ! Time step duration
    3980             : 
    3981             :      ! Input/Output Variable
    3982             :      type(physics_ptend),  intent(inout) :: ptend  ! Parameterization tendencies
    3983             : 
    3984             :      ! Local Variables
    3985             :      real( r8 ) :: &
    3986             :        rcm_update, & ! New value of mean cloud water mixing ratio    [kg/kg]
    3987             :        rrm_update, & ! New value of mean rain water mixing ratio     [kg/kg]
    3988             :        rim_update, & ! New value of mean ice mixing ratio            [kg/kg]
    3989             :        rsm_update    ! New value of mean snow mixing ratio           [kg/kg]
    3990             : 
    3991             :      real( r8 ) :: &
    3992             :        Nc_tend_min, & ! Minimum value of cloud droplet conc. tendency [num/kg/s]
    3993             :        Nr_tend_min, & ! Minimum value of rain drop conc. tendency     [num/kg/s]
    3994             :        Ni_tend_min, & ! Minimum value of ice conc. tendency           [num/kg/s]
    3995             :        Ns_tend_min    ! Minimum value of snow conc. tendency          [num/kg/s]
    3996             : 
    3997             :      real( r8 ), parameter :: &
    3998             :        four_thirds = 4.0_r8/3.0_r8,    & ! 4/3
    3999             :        rho_ice     = 917.0_r8,         & ! Density of ice            [kg/m^3]
    4000             :        rho_lw      = shr_const_rhofw,  & ! Density of liquid water   [kg/m^3]
    4001             :        pi          = shr_const_pi        ! Pi
    4002             : 
    4003             :      real( r8 ), parameter :: &
    4004             :        mvr_cloud_max = 1.6E-5_r8, & ! Max. avg. mean vol. rad. cloud   [m]
    4005             :        mvr_rain_max  = 5.0E-3_r8, & ! Max. avg. mean vol. rad. rain    [m]
    4006             :        mvr_ice_max   = 1.3E-4_r8, & ! Max. avg. mean vol. rad. ice     [m]
    4007             :        mvr_snow_max  = 1.0E-2_r8    ! Max. avg. mean vol. rad. snow    [m]
    4008             : 
    4009             :      ! Calculate the coefficient for the minimum mean cloud droplet
    4010             :      ! concentration, where <Nc>|_min = Ncm_min_coef * <rc> and has units of
    4011             :      ! 1/kg.
    4012             :      real( r8 ), parameter :: &
    4013             :        Ncm_min_coef = 1.0_r8 / ( four_thirds * pi * rho_lw * mvr_cloud_max**3 )
    4014             : 
    4015             :      ! Calculate the coefficient for the minimum mean rain drop concentration,
    4016             :      ! where <Nr>|_min = Nrm_min_coef * <rr> and has units of 1/kg.
    4017             :      real( r8 ), parameter :: &
    4018             :        Nrm_min_coef = 1.0_r8 / ( four_thirds * pi * rho_lw * mvr_rain_max**3 )
    4019             : 
    4020             :      ! Calculate the coefficient for the minimum mean ice crystal concentration,
    4021             :      ! where <Ni>|_min = Nim_min_coef * <ri> and has units of 1/kg.
    4022             :      real( r8 ), parameter :: &
    4023             :        Nim_min_coef = 1.0_r8 / ( four_thirds * pi * rho_ice * mvr_ice_max**3 )
    4024             : 
    4025             :      ! Calculate the coefficient for the minimum mean snow flake concentration,
    4026             :      ! where <Ns>|_min = Nsm_min_coef * <rs> and has units of 1/kg.
    4027             :      real( r8 ), parameter :: &
    4028             :        Nsm_min_coef = 1.0_r8 / ( four_thirds * pi * rho_ice * mvr_snow_max**3 )
    4029             : 
    4030             :      integer :: ncol  ! Number of grid columns
    4031             : 
    4032             :      integer :: icol    ! Column loop index
    4033             : 
    4034             :      integer :: k    ! Vertical level loop index
    4035             : 
    4036             : 
    4037             :      ! Get the number of grid columns.
    4038           0 :      ncol = state%ncol
    4039             : 
    4040             :      ! Loop over all grid columns.
    4041           0 :      do icol = 1, ncol
    4042             : 
    4043             :         ! Loop over all vertical levels from top_lev to pver.
    4044           0 :         do k = top_lev, pver
    4045             : 
    4046             :            ! Cloud droplet concentration
    4047           0 :            if ( ixcldliq > 0 .and. ixnumliq > 0 ) then
    4048             : 
    4049             :               ! Calculate the value of cloud water mixing ratio after the
    4050             :               ! update.
    4051             :               rcm_update &
    4052           0 :               = max( state%q(icol,k,ixcldliq) + ptend%q(icol,k,ixcldliq) * dt, &
    4053           0 :                      qmin(ixcldliq) )
    4054             : 
    4055             :               ! Calculate the limiting cloud droplet concentration tendency so
    4056             :               ! that cloud maintains a reasonable (not too big) mean volume
    4057             :               ! radius.
    4058             :               Nc_tend_min &
    4059           0 :               = ( Ncm_min_coef * rcm_update - state%q(icol,k,ixnumliq) ) / dt
    4060             : 
    4061             :               ! The cloud droplet concentration tendency needs to be the greater
    4062             :               ! of the current Nc_tend and Nc_tend_min.
    4063           0 :               ptend%q(icol,k,ixnumliq) &
    4064           0 :               = max( ptend%q(icol,k,ixnumliq), Nc_tend_min )
    4065             : 
    4066             :            endif ! ixcldliq > 0 .and. ixnumliq > 0
    4067             : 
    4068             :            ! Rain drop concentration
    4069           0 :            if ( ixrain > 0 .and. ixnumrain > 0 ) then
    4070             : 
    4071             :               ! Calculate the value of rain water mixing ratio after the update.
    4072             :               rrm_update &
    4073           0 :               = max( state%q(icol,k,ixrain) + ptend%q(icol,k,ixrain) * dt, &
    4074           0 :                      qmin(ixrain) )
    4075             : 
    4076             :               ! Calculate the limiting rain drop concentration tendency so that
    4077             :               ! rain maintains a reasonable (not too big) mean volume radius.
    4078             :               Nr_tend_min &
    4079           0 :               = ( Nrm_min_coef * rrm_update - state%q(icol,k,ixnumrain) ) / dt
    4080             : 
    4081             :               ! The rain drop concentration tendency needs to be the greater of
    4082             :               ! the current Nr_tend and Nr_tend_min.
    4083           0 :               ptend%q(icol,k,ixnumrain) &
    4084           0 :               = max( ptend%q(icol,k,ixnumrain), Nr_tend_min )
    4085             : 
    4086             :            endif ! ixrain > 0 .and. ixnumrain > 0
    4087             : 
    4088             :            ! Ice crystal concentration
    4089           0 :            if ( ixcldice > 0 .and. ixnumice > 0 ) then
    4090             : 
    4091             :               ! Calculate the value of ice mixing ratio after the update.
    4092             :               rim_update &
    4093           0 :               = max( state%q(icol,k,ixcldice) + ptend%q(icol,k,ixcldice) * dt, &
    4094           0 :                      qmin(ixcldice) )
    4095             : 
    4096             :               ! Calculate the limiting ice crystal concentration tendency so
    4097             :               ! that ice maintains a reasonable (not too big) mean volume
    4098             :               ! radius.
    4099             :               Ni_tend_min &
    4100           0 :               = ( Nim_min_coef * rim_update - state%q(icol,k,ixnumice) ) / dt
    4101             : 
    4102             :               ! The ice crystal concentration tendency needs to be the greater
    4103             :               ! of the current Ni_tend and Ni_tend_min.
    4104           0 :               ptend%q(icol,k,ixnumice) &
    4105           0 :               = max( ptend%q(icol,k,ixnumice), Ni_tend_min )
    4106             : 
    4107             :            endif ! ixcldice > 0 .and. ixnumice > 0
    4108             : 
    4109             :            ! Snow flake concentration
    4110           0 :            if ( ixsnow > 0 .and. ixnumsnow > 0 ) then
    4111             : 
    4112             :               ! Calculate the value of snow mixing ratio after the update.
    4113             :               rsm_update &
    4114           0 :               = max( state%q(icol,k,ixsnow) + ptend%q(icol,k,ixsnow) * dt, &
    4115           0 :                      qmin(ixsnow) )
    4116             : 
    4117             :               ! Calculate the limiting snow flake concentration tendency so that
    4118             :               ! snow maintains a reasonable (not too big) mean volume radius.
    4119             :               Ns_tend_min &
    4120           0 :               = ( Nsm_min_coef * rsm_update - state%q(icol,k,ixnumsnow) ) / dt
    4121             : 
    4122             :               ! The snow flake concentration tendency needs to be the greater of
    4123             :               ! the current Ns_tend and Ns_tend_min.
    4124           0 :               ptend%q(icol,k,ixnumsnow) &
    4125           0 :               = max( ptend%q(icol,k,ixnumsnow), Ns_tend_min )
    4126             : 
    4127             :            endif ! ixsnow > 0 .and. ixnumsnow > 0
    4128             : 
    4129             :         end do ! k = top_lev, pver
    4130             : 
    4131             :      end do ! icol = 1, ncol
    4132             : 
    4133             : 
    4134           0 :      return
    4135             : 
    4136           0 :    end subroutine subcol_SILHS_hydromet_conc_tend_lim
    4137             : 
    4138             :    !============================================================================
    4139             : 
    4140             :    ! Getunit and Freeunit are depreciated in Fortran going forward, so this is a 
    4141             :    ! small function to get an unused stream identifier to send to setup_corr_varnce_array_api
    4142             :    ! or any other silhs/clubb functions that require a unit number argument
    4143             :    ! This comes directly from the Fortran wiki
    4144             :    integer function newunit(unit)
    4145             :      integer, intent(out), optional :: unit
    4146             :     
    4147             :      integer, parameter :: LUN_MIN=10, LUN_MAX=1000
    4148             :      logical :: opened
    4149             :      integer :: lun
    4150             :    
    4151             :      newunit=-1
    4152             :      do lun=LUN_MIN,LUN_MAX
    4153             :         inquire(unit=lun,opened=opened)
    4154             :         if (.not. opened) then
    4155             :            newunit=lun
    4156             :            exit
    4157             :         end if
    4158             :      end do
    4159             :      if (present(unit)) unit=newunit
    4160           0 :    end function newunit
    4161             :    
    4162             : end module subcol_SILHS 

Generated by: LCOV version 1.14