From 8f232dc6a5ba8cc9be7d7a0c0dede0cae1008162 Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Tue, 26 Sep 2023 17:41:35 -0600 Subject: [PATCH 01/10] Remove ZM microphysics and cleanup for CCPP conversion --- Externals_CAM.cfg | 4 +- bld/build-namelist | 1 - bld/configure | 6 + bld/namelist_files/namelist_defaults_cam.xml | 1 - bld/namelist_files/namelist_definition.xml | 6 - src/physics/cam/clubb_intr.F90 | 1104 ++-- src/physics/cam/convect_shallow.F90 | 129 +- src/physics/cam/macrop_driver.F90 | 190 +- src/physics/cam/zm_conv.F90 | 4825 ------------------ src/physics/cam/zm_conv_intr.F90 | 623 +-- src/physics/cam/zm_microphysics.F90 | 2455 --------- src/physics/spcam/crmclouds_camaerosols.F90 | 12 +- 12 files changed, 739 insertions(+), 8617 deletions(-) delete mode 100644 src/physics/cam/zm_conv.F90 delete mode 100644 src/physics/cam/zm_microphysics.F90 diff --git a/Externals_CAM.cfg b/Externals_CAM.cfg index 7b246381a9..43a8228a0c 100644 --- a/Externals_CAM.cfg +++ b/Externals_CAM.cfg @@ -55,9 +55,9 @@ tag = ALI_ARMS_v1.0.0 required = True [atmos_phys] -tag = atmos_phys0_00_011 +tag = 7883a29d4c protocol = git -repo_url = https://github.com/NCAR/atmospheric_physics +repo_url = https://github.com/cacraigucar/atmospheric_physics required = True local_path = src/atmos_phys diff --git a/bld/build-namelist b/bld/build-namelist index efd42d4949..017f373ba1 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -3474,7 +3474,6 @@ if (!$simple_phys) { add_default($nl, 'zmconv_ke'); add_default($nl, 'zmconv_ke_lnd'); add_default($nl, 'zmconv_org'); - add_default($nl, 'zmconv_microp'); add_default($nl, 'zmconv_num_cin'); add_default($nl, 'zmconv_dmpdz'); add_default($nl, 'zmconv_tiedke_add'); diff --git a/bld/configure b/bld/configure index 262ac38e6d..a9bb065076 100755 --- a/bld/configure +++ b/bld/configure @@ -1802,6 +1802,9 @@ if ($usr_cppdefs and $print>=2) { print "Commandline CPP definitions: \'$usr_cpp # the CPP definitions that were explicitly set in the defaults file or by the user on the commandline. my $cfg_cppdefs = ' '; +# Turn on CCPP "OLD_CAM" +$cfg_cppdefs .= " -DOLD_CAM"; + # Building for perturbation growth tests if ($pergro eq "ON") { $cfg_cppdefs .= " -DPERGRO"; } @@ -2246,6 +2249,9 @@ sub write_filepath # in the list of filepaths. print $fh "$camsrcdir/src/physics/cam\n"; + #Add the CCPP'ized subdirectories + print $fh "$camsrcdir/src/atmos_phys/zm\n"; + # Dynamics package and test utilities print $fh "$camsrcdir/src/dynamics/$dyn\n"; if($dyn eq 'se') { diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 6b583ff69d..fde4087686 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2767,7 +2767,6 @@ .false. .true. - .false. 5 1 1 diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index 98364b80fe..1e27699dd2 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -3197,12 +3197,6 @@ if -zmconv_org is set in configure. Default: .false., unless -zmconv_org set in configure - -Turn on convective microphysics -Default: .false. - - The number of negative buoyancy regions that are allowed before the convection top and CAPE calculations are completed. diff --git a/src/physics/cam/clubb_intr.F90 b/src/physics/cam/clubb_intr.F90 index 07444cbfa3..c9f9a312a1 100644 --- a/src/physics/cam/clubb_intr.F90 +++ b/src/physics/cam/clubb_intr.F90 @@ -4,31 +4,30 @@ module clubb_intr ! Module to interface CAM with Cloud Layers Unified by Bi-normals (CLUBB), developed ! ! by the University of Wisconsin Milwaukee Group (UWM). ! ! ! - ! CLUBB replaces the exisiting turbulence, shallow convection, and macrophysics in CAM5 ! - ! ! + ! CLUBB replaces the exisiting turbulence, shallow convection, and macrophysics in CAM5 ! + ! ! ! Lastly, a implicit diffusion solver is called, and tendencies retrieved by ! ! differencing the diffused and initial states. ! - ! ! + ! ! ! Calling sequence: ! ! ! !---------------------------Code history-------------------------------------------------------------- ! - ! Authors: P. Bogenschutz, C. Craig, A. Gettelman ! - ! Modified by: K Thayer-Calder ! - ! ! + ! Authors: P. Bogenschutz, C. Craig, A. Gettelman ! + ! Modified by: K Thayer-Calder ! + ! ! !----------------------------------------------------------------------------------------------------- ! - use shr_kind_mod, only: r8=>shr_kind_r8 + use shr_kind_mod, only: r8=>shr_kind_r8 use ppgrid, only: pver, pverp, pcols, begchunk, endchunk use phys_control, only: phys_getopts use physconst, only: cpair, gravit, rga, latvap, latice, zvir, rh2o, karman use air_composition, only: rairv, cpairv use cam_history_support, only: max_fieldname_len - use spmd_utils, only: masterproc + use spmd_utils, only: masterproc use constituents, only: pcnst, cnst_add use pbl_utils, only: calc_ustar, calc_obklen - use ref_pres, only: top_lev => trop_cloud_top_lev - use zm_conv_intr, only: zmconv_microp + use ref_pres, only: top_lev => trop_cloud_top_lev #ifdef CLUBB_SGS use clubb_api_module, only: pdf_parameter, implicit_coefs_terms use clubb_api_module, only: clubb_config_flags_type, grid, stats, nu_vertical_res_dep @@ -46,7 +45,7 @@ module clubb_intr stats_rad_zt(pcols), & ! stats_rad_zt grid stats_rad_zm(pcols), & ! stats_rad_zm grid stats_sfc(pcols) ! stats_sfc - + !$omp threadprivate(stats_zt, stats_zm, stats_rad_zt, stats_rad_zm, stats_sfc) #endif @@ -64,7 +63,7 @@ module clubb_intr stats_init_clubb, & stats_zt, stats_zm, stats_sfc, & stats_rad_zt, stats_rad_zm, & - stats_end_timestep_clubb, & + stats_end_timestep_clubb, & #endif clubb_readnl, & clubb_init_cnst, & @@ -90,7 +89,7 @@ module clubb_intr integer, parameter :: & grid_type = 3, & ! The 2 option specifies stretched thermodynamic levels hydromet_dim = 0 ! The hydromet array in SAM-CLUBB is currently 0 elements - + ! Even though sclr_dim is set to 0, the dimension here is set to 1 to prevent compiler errors ! See github ticket larson-group/cam#133 for details real(r8), parameter, dimension(1) :: & @@ -102,28 +101,28 @@ module clubb_intr theta0 = 300._r8, & ! Reference temperature [K] ts_nudge = 86400._r8, & ! Time scale for u/v nudging (not used) [s] p0_clubb = 100000._r8 - - integer, parameter :: & + + integer, parameter :: & sclr_dim = 0 ! Higher-order scalars, set to zero real(r8), parameter :: & wp3_const = 1._r8 ! Constant to add to wp3 when moments are advected - - real(r8), parameter :: & + + real(r8), parameter :: & wpthlp_const = 10.0_r8 ! Constant to add to wpthlp when moments are advected - - real(r8), parameter :: & + + real(r8), parameter :: & wprtp_const = 0.01_r8 ! Constant to add to wprtp when moments are advected - - real(r8), parameter :: & + + real(r8), parameter :: & rtpthlp_const = 0.01_r8 ! Constant to add to rtpthlp when moments are advected - + real(r8), parameter :: unset_r8 = huge(1.0_r8) integer, parameter :: unset_i = huge(1) - ! Commonly used temperature for the melting temp of ice crystals [K] - real(r8), parameter :: meltpt_temp = 268.15_r8 - + ! Commonly used temperature for the melting temp of ice crystals [K] + real(r8), parameter :: meltpt_temp = 268.15_r8 + real(r8) :: clubb_timestep = unset_r8 ! Default CLUBB timestep, unless overwriten by namelist real(r8) :: clubb_rnevap_effic = unset_r8 @@ -179,7 +178,7 @@ module clubb_intr real(r8) :: clubb_detliq_rad = unset_r8 real(r8) :: clubb_detice_rad = unset_r8 real(r8) :: clubb_detphase_lowtemp = unset_r8 - + integer :: & clubb_iiPDF_type, & ! Selected option for the two-component normal ! (double Gaussian) PDF type to use for the w, rt, @@ -191,7 +190,7 @@ module clubb_intr clubb_tridiag_solve_method = unset_i ! Specifier for method to solve tri-diagonal systems - + logical :: & clubb_l_use_precip_frac, & ! Flag to use precipitation fraction in KK microphysics. The ! precipitation fraction is automatically set to 1 when this @@ -254,8 +253,8 @@ module clubb_intr ! that is linearized in terms of wp3. ! (Requires ADG1 PDF and clubb_l_standard_term_ta). clubb_l_godunov_upwind_wpxp_ta, & ! This flag determines whether we want to use an upwind - ! differencing approximation rather than a centered - ! differencing for turbulent advection terms. + ! differencing approximation rather than a centered + ! differencing for turbulent advection terms. ! It affects wpxp only. clubb_l_godunov_upwind_xpyp_ta, & ! This flag determines whether we want to use an upwind ! differencing approximation rather than a centered @@ -305,16 +304,16 @@ module clubb_intr clubb_l_mono_flux_lim_um, & ! Flag to turn on monotonic flux limiter for um clubb_l_mono_flux_lim_vm, & ! Flag to turn on monotonic flux limiter for vm clubb_l_mono_flux_lim_spikefix, & ! Flag to implement monotonic flux limiter code that - ! eliminates spurious drying tendencies at model top + ! eliminates spurious drying tendencies at model top clubb_l_intr_sfc_flux_smooth = .false. ! Add a locally calculated roughness to upwp and vpwp sfc fluxes ! Constant parameters logical, parameter, private :: & l_implemented = .true., & ! Implemented in a host model (always true) l_host_applies_sfc_fluxes = .false. ! Whether the host model applies the surface fluxes - + logical, parameter, private :: & - apply_to_heat = .false. ! Apply WACCM energy fixer to heat or not (.true. = yes (duh)) + apply_to_heat = .false. ! Apply WACCM energy fixer to heat or not (.true. = yes (duh)) logical :: lq(pcnst) logical :: prog_modal_aero @@ -326,8 +325,8 @@ module clubb_intr integer :: history_budget_histfile_num integer :: edsclr_dim ! Number of scalars to transport in CLUBB integer :: offset - -! define physics buffer indicies here + +! define physics buffer indicies here integer :: & wp2_idx, & ! vertical velocity variances wp3_idx, & ! third moment of vertical velocity @@ -386,8 +385,8 @@ module clubb_intr naai_idx, & ! ice number concentration prer_evap_idx, & ! rain evaporation rate qrl_idx, & ! longwave cooling rate - radf_idx, & - qsatfac_idx, & ! subgrid cloud water saturation scaling factor + radf_idx, & + qsatfac_idx, & ! subgrid cloud water saturation scaling factor ice_supersat_idx, & ! ice cloud fraction for SILHS rcm_idx, & ! Cloud water mixing ratio for SILHS ztodt_idx ! physics timestep for SILHS @@ -407,7 +406,7 @@ module clubb_intr pdf_zm_varnce_w_2_idx, & pdf_zm_mixt_frac_idx - integer, public :: & + integer, public :: & ixthlp2 = 0, & ixwpthlp = 0, & ixwprtp = 0, & @@ -426,7 +425,7 @@ module clubb_intr dnlfzm_idx = -1, & ! ZM detrained convective cloud water num concen. dnifzm_idx = -1 ! ZM detrained convective cloud ice num concen. - ! Output arrays for CLUBB statistics + ! Output arrays for CLUBB statistics real(r8), allocatable, dimension(:,:,:) :: out_zt, out_zm, out_radzt, out_radzm, out_sfc character(len=16) :: eddy_scheme ! Default set in phys_control.F90 @@ -440,14 +439,14 @@ module clubb_intr #ifdef CLUBB_SGS type(pdf_parameter), target, allocatable, public, protected :: & pdf_params_chnk(:) ! PDF parameters (thermo. levs.) [units vary] - + type(pdf_parameter), target, allocatable :: pdf_params_zm_chnk(:) ! PDF parameters on momentum levs. [units vary] - + type(implicit_coefs_terms), target, allocatable :: pdf_implicit_coefs_terms_chnk(:) ! PDF impl. coefs. & expl. terms [units vary] #endif contains - + ! =============================================================================== ! ! ! ! =============================================================================== ! @@ -466,12 +465,12 @@ subroutine clubb_register_cam( ) ! Register physics buffer fields and constituents ! !------------------------------------------------ ! - ! Add CLUBB fields to pbuf + ! Add CLUBB fields to pbuf use physics_buffer, only: pbuf_add_field, dtype_r8, dyn_time_lvls use subcol_utils, only: subcol_get_scheme - + call phys_getopts( eddy_scheme_out = eddy_scheme, & - deep_scheme_out = deep_scheme, & + deep_scheme_out = deep_scheme, & history_budget_out = history_budget, & history_budget_histfile_num_out = history_budget_histfile_num ) subcol_scheme = subcol_get_scheme() @@ -486,7 +485,7 @@ subroutine clubb_register_cam( ) cnst_names =(/'THLP2 ','RTP2 ','RTPTHLP','WPTHLP ','WPRTP ','WP2 ','WP3 ','UP2 ','VP2 '/) do_cnst=.true. ! If CLUBB moments are advected, do not output them automatically which is typically done. Some moments - ! need a constant added to them before they are advected, thus this would corrupt the output. + ! need a constant added to them before they are advected, thus this would corrupt the output. ! Users should refer to the "XXXX_CLUBB" (THLP2_CLUBB for instance) output variables for these moments call cnst_add(trim(cnst_names(1)),0._r8,0._r8,0._r8,ixthlp2,longname='second moment vertical velocity',cam_outfld=.false.) call cnst_add(trim(cnst_names(2)),0._r8,0._r8,0._r8,ixrtp2,longname='second moment rtp',cam_outfld=.false.) @@ -516,7 +515,7 @@ subroutine clubb_register_cam( ) call pbuf_add_field('CMELIQ', 'physpkg',dtype_r8, (/pcols,pver/), cmeliq_idx) call pbuf_add_field('QSATFAC', 'physpkg',dtype_r8, (/pcols,pver/), qsatfac_idx) - + call pbuf_add_field('WP2_nadv', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), wp2_idx) call pbuf_add_field('WP3_nadv', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), wp3_idx) call pbuf_add_field('WPTHLP_nadv', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), wpthlp_idx) @@ -525,7 +524,7 @@ subroutine clubb_register_cam( ) call pbuf_add_field('RTP2_nadv', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), rtp2_idx) call pbuf_add_field('THLP2_nadv', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), thlp2_idx) call pbuf_add_field('UP2_nadv', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), up2_idx) - call pbuf_add_field('VP2_nadv', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), vp2_idx) + call pbuf_add_field('VP2_nadv', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), vp2_idx) call pbuf_add_field('RTP3', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), rtp3_idx) call pbuf_add_field('THLP3', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), thlp3_idx) @@ -571,7 +570,7 @@ subroutine clubb_register_cam( ) call pbuf_add_field('pdf_zm_var_w_2', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), pdf_zm_varnce_w_2_idx) call pbuf_add_field('pdf_zm_mixt_frac', 'global', dtype_r8, (/pcols,pverp,dyn_time_lvls/), pdf_zm_mixt_frac_idx) -#endif +#endif end subroutine clubb_register_cam ! =============================================================================== ! @@ -595,14 +594,14 @@ function clubb_implements_cnst(name) end function clubb_implements_cnst - + ! =============================================================================== ! ! ! ! =============================================================================== ! subroutine clubb_init_cnst(name, latvals, lonvals, mask, q) #ifdef CLUBB_SGS - use clubb_api_module, only: w_tol_sqd, rt_tol, thl_tol + use clubb_api_module, only: w_tol_sqd, rt_tol, thl_tol #endif !----------------------------------------------------------------------- ! @@ -675,7 +674,7 @@ subroutine clubb_init_cnst(name, latvals, lonvals, mask, q) end subroutine clubb_init_cnst - + ! =============================================================================== ! ! ! ! =============================================================================== ! @@ -689,7 +688,7 @@ subroutine clubb_readnl(nlfile) use spmd_utils, only: mpicom, mstrid=>masterprocid, mpi_logical, mpi_real8, & mpi_integer use clubb_mf, only: clubb_mf_readnl - + use clubb_api_module, only: & set_default_clubb_config_flags_api, & ! Procedure(s) initialize_clubb_config_flags_type_api, & @@ -702,7 +701,7 @@ subroutine clubb_readnl(nlfile) character(len=*), parameter :: sub = 'clubb_readnl' - logical :: clubb_history = .false., clubb_rad_history = .false. ! Stats enabled (T/F) + logical :: clubb_history = .false., clubb_rad_history = .false. ! Stats enabled (T/F) logical :: clubb_cloudtop_cooling = .false., clubb_rainevap_turb = .false. integer :: iunit, read_status, ierr @@ -740,7 +739,7 @@ subroutine clubb_readnl(nlfile) clubb_C_invrs_tau_N2_wpxp, & clubb_C_invrs_tau_N2_xp2, & clubb_c_K1, & - clubb_c_K10, & + clubb_c_K10, & clubb_c_K10h, & clubb_c_K2, & clubb_c_K8, & @@ -806,16 +805,16 @@ subroutine clubb_readnl(nlfile) clubb_tridiag_solve_method, & clubb_up2_sfc_coef, & clubb_wpxp_L_thresh - + !----- Begin Code ----- - ! Determine if we want clubb_history to be output + ! Determine if we want clubb_history to be output clubb_history = .false. ! Initialize to false l_stats = .false. ! Initialize to false l_output_rad_files = .false. ! Initialize to false do_cldcool = .false. ! Initialize to false do_rainturb = .false. ! Initialize to false - + ! Initialize namelist variables to clubb defaults call set_default_clubb_config_flags_api( clubb_iiPDF_type, & ! Out clubb_ipdf_call_placement, & ! Out @@ -963,7 +962,7 @@ subroutine clubb_readnl(nlfile) call mpi_bcast(clubb_c_K10, 1, mpi_real8, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_c_K10") call mpi_bcast(clubb_c_K10h, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_c_K10h") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_c_K10h") call mpi_bcast(clubb_beta, 1, mpi_real8, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_beta") call mpi_bcast(clubb_C2rt, 1, mpi_real8, mstrid, mpicom, ierr) @@ -1011,21 +1010,21 @@ subroutine clubb_readnl(nlfile) call mpi_bcast(clubb_do_energyfix, 1, mpi_logical, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_do_energyfix") call mpi_bcast(clubb_C_invrs_tau_bkgnd, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_bkgnd") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_bkgnd") call mpi_bcast(clubb_C_invrs_tau_sfc, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_sfc") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_sfc") call mpi_bcast(clubb_C_invrs_tau_shear, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_shear") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_shear") call mpi_bcast(clubb_C_invrs_tau_N2, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2") call mpi_bcast(clubb_C_invrs_tau_N2_wp2, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2_wp2") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2_wp2") call mpi_bcast(clubb_C_invrs_tau_N2_xp2, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2_xp2") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2_xp2") call mpi_bcast(clubb_C_invrs_tau_N2_wpxp, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2_wpxp") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2_wpxp") call mpi_bcast(clubb_C_invrs_tau_N2_clear_wp3, 1, mpi_real8, mstrid, mpicom, ierr) - if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2_clear_wp3") + if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_C_invrs_tau_N2_clear_wp3") call mpi_bcast(clubb_lmin_coef, 1, mpi_real8, mstrid, mpicom, ierr) if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: clubb_lmin_coef") call mpi_bcast(clubb_skw_max_mag, 1, mpi_real8, mstrid, mpicom, ierr) @@ -1124,10 +1123,10 @@ subroutine clubb_readnl(nlfile) ! Overwrite defaults if they are true if (clubb_history) l_stats = .true. - if (clubb_rad_history) l_output_rad_files = .true. + if (clubb_rad_history) l_output_rad_files = .true. if (clubb_cloudtop_cooling) do_cldcool = .true. if (clubb_rainevap_turb) do_rainturb = .true. - + ! Check that all namelists have been set if(clubb_timestep == unset_r8) call endrun(sub//": FATAL: clubb_timestep is not set") if(clubb_rnevap_effic == unset_r8) call endrun(sub//": FATAL:clubb_rnevap_effic is not set") @@ -1187,7 +1186,7 @@ subroutine clubb_readnl(nlfile) if(clubb_detphase_lowtemp == unset_r8) call endrun(sub//": FATAL: clubb_detphase_lowtemp not set") if(clubb_penta_solve_method == unset_i) call endrun(sub//": FATAL: clubb_penta_solve_method not set") if(clubb_tridiag_solve_method == unset_i) call endrun(sub//": FATAL: clubb_tridiag_solve_method not set") - if(clubb_detphase_lowtemp >= meltpt_temp) & + if(clubb_detphase_lowtemp >= meltpt_temp) & call endrun(sub//": ERROR: clubb_detphase_lowtemp must be less than 268.15 K") call initialize_clubb_config_flags_type_api( clubb_iiPDF_type, & ! In @@ -1237,7 +1236,7 @@ subroutine clubb_readnl(nlfile) clubb_l_e3sm_config, & ! In clubb_l_vary_convect_depth, & ! In clubb_l_use_tke_in_wp3_pr_turb_term, & ! In - clubb_l_use_tke_in_wp2_wp3_K_dfsn, & ! In + clubb_l_use_tke_in_wp2_wp3_K_dfsn, & ! In clubb_l_smooth_Heaviside_tau_wpxp, & ! In clubb_l_enable_relaxed_clipping, & ! In clubb_l_linearize_pbl_winds, & ! In @@ -1332,7 +1331,7 @@ subroutine clubb_ini_cam(pbuf2d) #ifdef CLUBB_SGS real(kind=time_precision) :: dum1, dum2, dum3 - + ! The similar name to clubb_history is unfortunate... logical :: history_amwg, history_clubb @@ -1387,10 +1386,10 @@ subroutine clubb_ini_cam(pbuf2d) pdf_implicit_coefs_terms_chnk(begchunk:endchunk) ) ! ----------------------------------------------------------------- ! - ! Determine how many constituents CLUBB will transport. Note that - ! CLUBB does not transport aerosol consituents. Therefore, need to + ! Determine how many constituents CLUBB will transport. Note that + ! CLUBB does not transport aerosol consituents. Therefore, need to ! determine how many aerosols constituents there are and subtract that - ! off of pcnst (the total consituents) + ! off of pcnst (the total consituents) ! ----------------------------------------------------------------- ! call phys_getopts(prog_modal_aero_out=prog_modal_aero, & @@ -1398,7 +1397,7 @@ subroutine clubb_ini_cam(pbuf2d) history_clubb_out=history_clubb) ! Select variables to apply tendencies back to CAM - + ! Initialize all consituents to true to start lq(1:pcnst) = .true. edsclr_dim = pcnst @@ -1412,12 +1411,12 @@ subroutine clubb_ini_cam(pbuf2d) if (prog_modal_aero) then ! Turn off modal aerosols and decrement edsclr_dim accordingly call rad_cnst_get_info(0, nmodes=nmodes) - + do m = 1, nmodes call rad_cnst_get_mode_num_idx(m, lptr) lq(lptr)=.false. edsclr_dim = edsclr_dim-1 - + call rad_cnst_get_info(0, m, nspec=nspec) do l = 1, nspec call rad_cnst_get_mam_mmr_idx(m, l, lptr) @@ -1425,7 +1424,7 @@ subroutine clubb_ini_cam(pbuf2d) edsclr_dim = edsclr_dim-1 end do end do - + ! In addition, if running with MAM, droplet number is transported ! in dropmixnuc, therefore we do NOT want CLUBB to apply transport ! tendencies to avoid double counted. Else, we apply tendencies. @@ -1449,7 +1448,7 @@ subroutine clubb_ini_cam(pbuf2d) l_stats_samp = .false. l_grads = .false. - ! Overwrite defaults if needbe + ! Overwrite defaults if needbe if (l_stats) l_stats_samp = .true. ! Define physics buffers indexes @@ -1458,7 +1457,7 @@ subroutine clubb_ini_cam(pbuf2d) ast_idx = pbuf_get_index('AST') ! Stratiform cloud fraction alst_idx = pbuf_get_index('ALST') ! Liquid stratiform cloud fraction aist_idx = pbuf_get_index('AIST') ! Ice stratiform cloud fraction - qlst_idx = pbuf_get_index('QLST') ! Physical in-stratus LWC + qlst_idx = pbuf_get_index('QLST') ! Physical in-stratus LWC qist_idx = pbuf_get_index('QIST') ! Physical in-stratus IWC dp_frac_idx = pbuf_get_index('DP_FRAC') ! Deep convection cloud fraction icwmrdp_idx = pbuf_get_index('ICWMRDP') ! In-cloud deep convective mixing ratio @@ -1480,26 +1479,19 @@ subroutine clubb_ini_cam(pbuf2d) iiedsclr_thl = -1 iiedsclr_CO2 = -1 - if (zmconv_microp) then - dlfzm_idx = pbuf_get_index('DLFZM') - difzm_idx = pbuf_get_index('DIFZM') - dnlfzm_idx = pbuf_get_index('DNLFZM') - dnifzm_idx = pbuf_get_index('DNIFZM') - end if - ! ----------------------------------------------------------------- ! ! Define number of tracers for CLUBB to diffuse - ! ----------------------------------------------------------------- ! - + ! ----------------------------------------------------------------- ! + if (clubb_l_do_expldiff_rtm_thlm) then offset = 2 ! diffuse temperature and moisture explicitly - edsclr_dim = edsclr_dim + offset + edsclr_dim = edsclr_dim + offset endif - + ! ----------------------------------------------------------------- ! ! Setup CLUBB core ! ----------------------------------------------------------------- ! - + ! Read in parameters for CLUBB. Just read in default values call set_default_parameters_api( & C1, C1b, C1c, C2rt, C2thl, C2rtthl, & @@ -1603,7 +1595,7 @@ subroutine clubb_ini_cam(pbuf2d) clubb_params(iC_invrs_tau_N2_xp2) = clubb_C_invrs_tau_N2_xp2 clubb_params(iC_invrs_tau_N2_wpxp) = clubb_C_invrs_tau_N2_wpxp clubb_params(iC_invrs_tau_N2_clear_wp3) = clubb_C_invrs_tau_N2_clear_wp3 - + ! Set up CLUBB core. Note that some of these inputs are overwritten ! when clubb_tend_cam is called. The reason is that heights can change ! at each time step, which is why dummy arrays are read in here for heights @@ -1650,12 +1642,12 @@ subroutine clubb_ini_cam(pbuf2d) ! ----------------------------------------------------------------- ! ! Initialize eddy diffusivity module - + ntop_eddy = 1 ! if >1, must be <= nbot_molec nbot_eddy = pver ! currently always pver - + call init_hb_diff( gravit, cpair, ntop_eddy, nbot_eddy, pref_mid, karman, eddy_scheme ) - + ! ----------------------------------------------------------------- ! ! Add output fields for the history files ! ----------------------------------------------------------------- ! @@ -1683,7 +1675,7 @@ subroutine clubb_ini_cam(pbuf2d) call addfld ('WPRCP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Liquid Water Flux') call addfld ('CLOUDFRAC_CLUBB', (/ 'lev' /), 'A', 'fraction', 'Cloud Fraction') call addfld ('RCMINLAYER_CLUBB', (/ 'lev' /), 'A', 'kg/kg', 'Cloud Water in Layer') - call addfld ('CLOUDCOVER_CLUBB', (/ 'lev' /), 'A', 'fraction', 'Cloud Cover') + call addfld ('CLOUDCOVER_CLUBB', (/ 'lev' /), 'A', 'fraction', 'Cloud Cover') call addfld ('WPTHVP_CLUBB', (/ 'ilev' /), 'A', 'W/m2', 'Buoyancy Flux') call addfld ('RVMTEND_CLUBB', (/ 'lev' /), 'A', 'kg/kg /s', 'Water vapor tendency') call addfld ('STEND_CLUBB', (/ 'lev' /), 'A', 'J/(kg s)', 'Static energy tendency') @@ -1692,7 +1684,7 @@ subroutine clubb_ini_cam(pbuf2d) call addfld ('UTEND_CLUBB', (/ 'lev' /), 'A', 'm/s /s', 'U-wind Tendency') call addfld ('VTEND_CLUBB', (/ 'lev' /), 'A', 'm/s /s', 'V-wind Tendency') call addfld ('ZT_CLUBB', (/ 'lev' /), 'A', 'm', 'Thermodynamic Heights') - call addfld ('ZM_CLUBB', (/ 'ilev' /), 'A', 'm', 'Momentum Heights') + call addfld ('ZM_CLUBB', (/ 'ilev' /), 'A', 'm', 'Momentum Heights') call addfld ('UM_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Zonal Wind') call addfld ('VM_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Meridional Wind') call addfld ('WM_ZT_CLUBB', (/ 'lev' /), 'A', 'm/s', 'Vertical Velocity') @@ -1710,8 +1702,8 @@ subroutine clubb_ini_cam(pbuf2d) call addfld ('FQTENDICE', (/ 'lev' /), 'A', 'fraction', 'Frequency of Ice Saturation Adjustment') call addfld ('DPDLFLIQ', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained liquid water from deep convection') - call addfld ('DPDLFICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice from deep convection') - call addfld ('DPDLFT', (/ 'lev' /), 'A', 'K/s', 'T-tendency due to deep convective detrainment') + call addfld ('DPDLFICE', (/ 'lev' /), 'A', 'kg/kg/s', 'Detrained ice from deep convection') + call addfld ('DPDLFT', (/ 'lev' /), 'A', 'K/s', 'T-tendency due to deep convective detrainment') call addfld ('RELVAR', (/ 'lev' /), 'A', '-', 'Relative cloud water variance') call addfld ('CLUBB_GRID_SIZE', horiz_only, 'A', 'm', 'Horizontal grid box size seen by CLUBB') @@ -1751,7 +1743,7 @@ subroutine clubb_ini_cam(pbuf2d) call addfld ( 'edmf_S_AWV' , (/ 'ilev' /), 'A', 'm2/s2' , 'Sum of a_i*w_i*v_i (EDMF)' ) call addfld ( 'edmf_thlflx' , (/ 'ilev' /), 'A', 'W/m2' , 'thl flux (EDMF)' ) call addfld ( 'edmf_qtflx' , (/ 'ilev' /), 'A', 'W/m2' , 'qt flux (EDMF)' ) - end if + end if ! Initialize statistics, below are dummy variables dum1 = 300._r8 @@ -1759,13 +1751,13 @@ subroutine clubb_ini_cam(pbuf2d) dum3 = 300._r8 if (l_stats) then - + do i=1, pcols call stats_init_clubb( .true., dum1, dum2, & nlev+1, nlev+1, nlev+1, dum3, & stats_zt(i), stats_zm(i), stats_sfc(i), & stats_rad_zt(i), stats_rad_zm(i)) - end do + end do allocate(out_zt(pcols,pverp,stats_zt(1)%num_output_fields)) allocate(out_zm(pcols,pverp,stats_zm(1)%num_output_fields)) @@ -1775,12 +1767,12 @@ subroutine clubb_ini_cam(pbuf2d) allocate(out_radzm(pcols,pverp,stats_rad_zm(1)%num_output_fields)) endif - + ! ----------------------------------------------------------------- ! ! Make all of this output default, this is not CLUBB history ! ----------------------------------------------------------------- ! - - if (clubb_do_adv .or. history_clubb) then + + if (clubb_do_adv .or. history_clubb) then call add_default('RELVAR', 1, ' ') call add_default('RHO_CLUBB', 1, ' ') call add_default('UP2_CLUBB', 1, ' ') @@ -1813,14 +1805,14 @@ subroutine clubb_ini_cam(pbuf2d) call add_default('UTEND_CLUBB', 1, ' ') call add_default('VTEND_CLUBB', 1, ' ') call add_default('ZT_CLUBB', 1, ' ') - call add_default('ZM_CLUBB', 1, ' ') + call add_default('ZM_CLUBB', 1, ' ') call add_default('UM_CLUBB', 1, ' ') call add_default('VM_CLUBB', 1, ' ') call add_default('WM_ZT_CLUBB', 1, ' ') call add_default('PBLH', 1, ' ') call add_default('CONCLD', 1, ' ') endif - + if (history_amwg) then call add_default('PBLH', 1, ' ') end if @@ -1849,10 +1841,10 @@ subroutine clubb_ini_cam(pbuf2d) call add_default( 'edmf_qtflx' , 1, ' ') end if - if (history_budget) then + if (history_budget) then call add_default('DPDLFLIQ', history_budget_histfile_num, ' ') call add_default('DPDLFICE', history_budget_histfile_num, ' ') - call add_default('DPDLFT', history_budget_histfile_num, ' ') + call add_default('DPDLFT', history_budget_histfile_num, ' ') call add_default('STEND_CLUBB', history_budget_histfile_num, ' ') call add_default('RCMTEND_CLUBB', history_budget_histfile_num, ' ') call add_default('RIMTEND_CLUBB', history_budget_histfile_num, ' ') @@ -1860,7 +1852,7 @@ subroutine clubb_ini_cam(pbuf2d) call add_default('UTEND_CLUBB', history_budget_histfile_num, ' ') call add_default('VTEND_CLUBB', history_budget_histfile_num, ' ') endif - + ! --------------- ! ! First step? ! @@ -1879,12 +1871,12 @@ subroutine clubb_ini_cam(pbuf2d) call pbuf_set_field(pbuf2d, thlp2_idx, thl_tol**2) call pbuf_set_field(pbuf2d, up2_idx, w_tol_sqd) call pbuf_set_field(pbuf2d, vp2_idx, w_tol_sqd) - + call pbuf_set_field(pbuf2d, rtp3_idx, 0.0_r8) call pbuf_set_field(pbuf2d, thlp3_idx, 0.0_r8) call pbuf_set_field(pbuf2d, up3_idx, 0.0_r8) call pbuf_set_field(pbuf2d, vp3_idx, 0.0_r8) - + call pbuf_set_field(pbuf2d, upwp_idx, 0.0_r8) call pbuf_set_field(pbuf2d, vpwp_idx, 0.0_r8) call pbuf_set_field(pbuf2d, wpthvp_idx, 0.0_r8) @@ -1922,10 +1914,10 @@ subroutine clubb_ini_cam(pbuf2d) call pbuf_set_field(pbuf2d, pdf_zm_mixt_frac_idx, 0.0_r8) endif - + ! The following is physpkg, so it needs to be initialized every time call pbuf_set_field(pbuf2d, fice_idx, 0.0_r8) - + ! --------------- ! ! End ! ! Initialization ! @@ -1933,19 +1925,19 @@ subroutine clubb_ini_cam(pbuf2d) #endif end subroutine clubb_ini_cam - - + + ! =============================================================================== ! ! ! ! =============================================================================== ! subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & - cmfmc, cam_in, & + cmfmc, cam_in, & macmic_it, cld_macmic_num_steps,dlf, det_s, det_ice) !------------------------------------------------------------------------------- - ! Description: Provide tendencies of shallow convection, turbulence, and + ! Description: Provide tendencies of shallow convection, turbulence, and ! macrophysics from CLUBB to CAM - ! + ! ! Author: Cheryl Craig, March 2011 ! Modifications: Pete Bogenschutz, March 2011 and onward ! Origin: Based heavily on UWM clubb_init.F90 @@ -1961,12 +1953,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & use constituents, only: cnst_get_ind, cnst_type use camsrfexch, only: cam_in_t - use time_manager, only: is_first_step + use time_manager, only: is_first_step use cam_abortutils, only: endrun use cam_logfile, only: iulog use tropopause, only: tropopause_findChemTrop use time_manager, only: get_nstep, is_first_restart_step - + #ifdef CLUBB_SGS use hb_diff, only: pblintd use scamMOD, only: single_column,scm_clubb_iop_name @@ -2005,13 +1997,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & use macrop_driver, only: liquid_macro_tend use clubb_mf, only: integrate_mf - + use perf_mod #endif implicit none - + ! ---------------------------------------------------- ! ! Input Auguments ! ! ---------------------------------------------------- ! @@ -2023,11 +2015,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8), intent(in) :: cmfmc(pcols,pverp) ! convective mass flux--m sub c [kg/m2/s] integer, intent(in) :: cld_macmic_num_steps ! number of mac-mic iterations integer, intent(in) :: macmic_it ! number of mac-mic iterations - + ! ---------------------------------------------------- ! ! Input-Output Auguments ! ! ---------------------------------------------------- ! - + type(physics_buffer_desc), pointer :: pbuf(:) ! ---------------------------------------------------- ! @@ -2036,11 +2028,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & type(physics_ptend), intent(out) :: ptend_all ! package tendencies - ! These two variables are needed for energy check + ! These two variables are needed for energy check real(r8), intent(out) :: det_s(pcols) ! Integral of detrained static energy from ice real(r8), intent(out) :: det_ice(pcols) ! Integral of detrained ice for energy check - + ! ---------------------------------------------------- ! ! Local Variables ! ! ---------------------------------------------------- ! @@ -2049,26 +2041,26 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & type(physics_state) :: state1 ! Local copy of state variable type(physics_ptend) :: ptend_loc ! Local tendency from processes, added up to return as ptend_all - + integer :: i, j, k, t, ixind, nadv integer :: ixcldice, ixcldliq, ixnumliq, ixnumice, ixq integer :: itim_old integer :: ncol, lchnk ! # of columns, and chunk identifier integer :: err_code ! Diagnostic, for if some calculation goes amiss. - integer :: icnt + integer :: icnt logical :: lq2(pcnst) integer :: iter - + integer :: clubbtop(pcols) - + real(r8) :: frac_limit, ic_limit - real(r8) :: dtime ! CLUBB time step [s] - real(r8) :: zt_out(pcols,pverp) ! output for the thermo CLUBB grid [m] + real(r8) :: dtime ! CLUBB time step [s] + real(r8) :: zt_out(pcols,pverp) ! output for the thermo CLUBB grid [m] real(r8) :: zi_out(pcols,pverp) ! output for momentum CLUBB grid [m] real(r8) :: ubar ! surface wind [m/s] - real(r8) :: ustar ! surface stress [m/s] + real(r8) :: ustar ! surface stress [m/s] real(r8) :: z0 ! roughness height [m] real(r8) :: bflx22(pcols) ! Variable for buoyancy flux for pbl [K m/s] real(r8) :: qclvar(pcols,pverp) ! cloud water variance [kg^2/kg^2] @@ -2088,7 +2080,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & upwp_sfc_pert, & ! perturbed u'w' at surface [m^2/s^2] vpwp_sfc_pert, & ! perturbed v'w' at surface [m^2/s^2] grid_dx, grid_dy ! CAM grid [m] - + real(r8), dimension(state%ncol,sclr_dim) :: & wpsclrp_sfc ! Scalar flux at surface [{units vary} m/s] @@ -2099,7 +2091,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! NOTE: THESE VARIABLS SHOULD NOT BE USED IN PBUF OR OUTFLD (HISTORY) SUBROUTINES real(r8), dimension(state%ncol,pverp+1-top_lev) :: & thlm_forcing, & ! theta_l forcing (thermodynamic levels) [K/s] - rtm_forcing, & ! r_t forcing (thermodynamic levels) [(kg/kg)/s] + rtm_forcing, & ! r_t forcing (thermodynamic levels) [(kg/kg)/s] um_forcing, & ! u wind forcing (thermodynamic levels) [m/s/s] vm_forcing, & ! v wind forcing (thermodynamic levels) [m/s/s] wprtp_forcing, & @@ -2174,7 +2166,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rcm_in_layer_out, & ! CLUBB output of in-cloud liq. wat. mix. ratio [kg/kg] cloud_cover_out, & ! CLUBB output of in-cloud cloud fraction [fraction] invrs_tau_zm_out, & ! CLUBB output of 1 divided by time-scale [1/s] - rtp2_mc_out, & ! total water tendency from rain evap + rtp2_mc_out, & ! total water tendency from rain evap thlp2_mc_out, & ! thetal tendency from rain evap wprtp_mc_out, & wpthlp_mc_out, & @@ -2205,7 +2197,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & sclrprtp, & ! sclr'rt' (momentum levels) [{units vary} (kg/kg)] sclrpthlp, & ! sclr'thlp' (momentum levels) [{units vary} (K)] wpsclrp ! w'sclr' (momentum levels) [{units vary} m/s] - + real(r8), dimension(state%ncol,pverp,sclr_dim) :: & sclrpthvp_inout ! sclr'th_v' (momentum levels) [{units vary} (K)] @@ -2250,7 +2242,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8) :: pdfp_rtp2(pcols, pverp) ! Calculated R-tot variance from pdf_params [kg^2/kg^2] real(r8) :: rtp2_zt_out(pcols, pverp) ! CLUBB R-tot variance on thermo levs [kg^2/kg^2] real(r8) :: thl2_zt_out(pcols, pverp) ! CLUBB Theta-l variance on thermo levs - real(r8) :: wp2_zt_out(pcols, pverp) + real(r8) :: wp2_zt_out(pcols, pverp) real(r8) :: dlf_liq_out(pcols, pverp) ! Detrained liquid water from ZM [kg/kg/s] real(r8) :: dlf_ice_out(pcols, pverp) ! Detrained ice water from ZM [kg/kg/s] real(r8) :: wm_zt_out(pcols, pverp) ! CLUBB mean W on thermo levs output [m/s] @@ -2280,7 +2272,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! ---------------------------------------------------- ! ! Pointers ! ! ---------------------------------------------------- ! - + real(r8), pointer, dimension(:,:) :: wp2 ! vertical velocity variance [m^2/s^2] real(r8), pointer, dimension(:,:) :: wp3 ! third moment of vertical velocity [m^3/s^3] real(r8), pointer, dimension(:,:) :: wpthlp ! turbulent flux of thetal [m/s K] @@ -2330,16 +2322,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & real(r8), pointer, dimension(:,:) :: qlst ! Physical in-stratus LWC [kg/kg] real(r8), pointer, dimension(:,:) :: qist ! Physical in-stratus IWC [kg/kg] real(r8), pointer, dimension(:,:) :: deepcu ! deep convection cloud fraction [fraction] - real(r8), pointer, dimension(:,:) :: shalcu ! shallow convection cloud fraction [fraction] + real(r8), pointer, dimension(:,:) :: shalcu ! shallow convection cloud fraction [fraction] real(r8), pointer, dimension(:,:) :: khzm ! CLUBB's eddy diffusivity of heat/moisture on momentum (i.e. interface) levels [m^2/s] real(r8), pointer, dimension(:) :: pblh ! planetary boundary layer height [m] real(r8), pointer, dimension(:,:) :: tke ! turbulent kinetic energy [m^2/s^2] real(r8), pointer, dimension(:,:) :: dp_icwmr ! deep convection in cloud mixing ratio [kg/kg] - real(r8), pointer, dimension(:,:) :: ice_supersat_frac ! Cloud fraction of ice clouds (pverp)[fraction] + real(r8), pointer, dimension(:,:) :: ice_supersat_frac ! Cloud fraction of ice clouds (pverp)[fraction] real(r8), pointer, dimension(:,:) :: relvar ! relative cloud water variance [-] real(r8), pointer, dimension(:,:) :: accre_enhan ! accretion enhancement factor [-] real(r8), pointer, dimension(:,:) :: naai - real(r8), pointer, dimension(:,:) :: cmeliq + real(r8), pointer, dimension(:,:) :: cmeliq real(r8), pointer, dimension(:,:) :: cmfmc_sh ! Shallow convective mass flux--m subc (pcols,pverp) [kg/m2/s/] real(r8), pointer, dimension(:,:) :: qsatfac @@ -2421,13 +2413,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & intrinsic :: max character(len=*), parameter :: subr='clubb_tend_cam' - + type(grid) :: gr integer :: begin_height, end_height - + type(nu_vertical_res_dep) :: nu_vert_res_dep ! Vertical resolution dependent nu values real(r8) :: lmin - + #endif det_s(:) = 0.0_r8 det_ice(:) = 0.0_r8 @@ -2448,7 +2440,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & pdfp_rtp2 = 0._r8 wm_zt_out = 0._r8 - temp2d = 0._r8 + temp2d = 0._r8 temp2dp = 0._r8 dl_rad = clubb_detliq_rad @@ -2459,7 +2451,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ic_limit = 1.e-12_r8 inv_rh2o = 1._r8/rh2o - if (clubb_do_adv) then + if (clubb_do_adv) then apply_const = 1._r8 ! Initialize to one, only if CLUBB's moments are advected else apply_const = 0._r8 ! Never want this if CLUBB's moments are not advected @@ -2496,7 +2488,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Determine time step of physics buffer itim_old = pbuf_old_tim_idx() - ! Establish associations between pointers and physics buffer fields + ! Establish associations between pointers and physics buffer fields call pbuf_get_field(pbuf, wp2_idx, wp2, start=(/1,1,itim_old/), kount=(/pcols,pverp,1/)) call pbuf_get_field(pbuf, wp3_idx, wp3, start=(/1,1,itim_old/), kount=(/pcols,pverp,1/)) call pbuf_get_field(pbuf, wpthlp_idx, wpthlp, start=(/1,1,itim_old/), kount=(/pcols,pverp,1/)) @@ -2541,7 +2533,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call pbuf_get_field(pbuf, rtm_idx, rtm, start=(/1,1,itim_old/), kount=(/pcols,pverp,1/)) call pbuf_get_field(pbuf, um_idx, um, start=(/1,1,itim_old/), kount=(/pcols,pverp,1/)) call pbuf_get_field(pbuf, vm_idx, vm, start=(/1,1,itim_old/), kount=(/pcols,pverp,1/)) - + call pbuf_get_field(pbuf, tke_idx, tke) call pbuf_get_field(pbuf, qrl_idx, qrl) call pbuf_get_field(pbuf, radf_idx, radf_clubb) @@ -2575,13 +2567,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call pbuf_get_field(pbuf, wprtp_mc_zt_idx, wprtp_mc_zt) call pbuf_get_field(pbuf, wpthlp_mc_zt_idx, wpthlp_mc_zt) call pbuf_get_field(pbuf, rtpthlp_mc_zt_idx, rtpthlp_mc_zt) - + ! Allocate pdf_params only if they aren't allocated already. if ( .not. allocated(pdf_params_chnk(lchnk)%mixt_frac) ) then call init_pdf_params_api( pverp+1-top_lev, ncol, pdf_params_chnk(lchnk) ) call init_pdf_params_api( pverp+1-top_lev, ncol, pdf_params_zm_chnk(lchnk) ) end if - + if ( .not. allocated(pdf_implicit_coefs_terms_chnk(lchnk)%coef_wp4_implicit) ) then call init_pdf_implicit_coefs_terms_api( pverp+1-top_lev, ncol, sclr_dim, & pdf_implicit_coefs_terms_chnk(lchnk) ) @@ -2589,15 +2581,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Initialize the apply_const variable (note special logic is due to eularian backstepping) if (clubb_do_adv .and. (is_first_step() .or. all(wpthlp(1:ncol,1:pver) == 0._r8))) then - apply_const = 0._r8 ! On first time through do not remove constant - ! from moments since it has not been added yet + apply_const = 0._r8 ! On first time through do not remove constant + ! from moments since it has not been added yet endif ! Set the ztodt timestep in pbuf for SILHS ztodtptr(:) = 1.0_r8*hdtime ! Define the grid box size. CLUBB needs this information to determine what - ! the maximum length scale should be. This depends on the column for + ! the maximum length scale should be. This depends on the column for ! variable mesh grids and lat-lon grids if (single_column) then ! If single column specify grid box size to be something @@ -2605,7 +2597,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & grid_dx(:) = 100000._r8 grid_dy(:) = 100000._r8 else - + call grid_size(state1, grid_dx, grid_dy) end if @@ -2620,11 +2612,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & lq2(1) = .TRUE. lq2(ixcldice) = .TRUE. lq2(ixnumice) = .TRUE. - + latsub = latvap + latice - + call physics_ptend_init(ptend_loc, state%psetcols, 'iceadj', ls=.true., lq=lq2 ) - + stend(:ncol,:)=0._r8 qvtend(:ncol,:)=0._r8 qitend(:ncol,:)=0._r8 @@ -2638,9 +2630,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! update local copy of state with the tendencies ptend_loc%q(:ncol,top_lev:pver,1)=qvtend(:ncol,top_lev:pver) - ptend_loc%q(:ncol,top_lev:pver,ixcldice)=qitend(:ncol,top_lev:pver) + ptend_loc%q(:ncol,top_lev:pver,ixcldice)=qitend(:ncol,top_lev:pver) ptend_loc%q(:ncol,top_lev:pver,ixnumice)=initend(:ncol,top_lev:pver) - ptend_loc%s(:ncol,top_lev:pver)=stend(:ncol,top_lev:pver) + ptend_loc%s(:ncol,top_lev:pver)=stend(:ncol,top_lev:pver) ! Add the ice tendency to the output tendency call physics_ptend_sum(ptend_loc, ptend_all, ncol) @@ -2654,56 +2646,56 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'QVTENDICE', qvtend, pcols, lchnk ) call outfld( 'QITENDICE', qitend, pcols, lchnk ) call outfld( 'NITENDICE', initend, pcols, lchnk ) - + endif ! Determine CLUBB time step and make it sub-step friendly - ! For now we want CLUBB time step to be 5 min since that is + ! For now we want CLUBB time step to be 5 min since that is ! what has been scientifically validated. However, there are certain - ! instances when a 5 min time step will not be possible (based on + ! instances when a 5 min time step will not be possible (based on ! host model time step or on macro-micro sub-stepping - dtime = clubb_timestep - - ! Now check to see if dtime is greater than the host model - ! (or sub stepped) time step. If it is, then simply - ! set it equal to the host (or sub step) time step. + dtime = clubb_timestep + + ! Now check to see if dtime is greater than the host model + ! (or sub stepped) time step. If it is, then simply + ! set it equal to the host (or sub step) time step. ! This section is mostly to deal with small host model - ! time steps (or small sub-steps) + ! time steps (or small sub-steps) if (dtime > hdtime) then dtime = hdtime endif - + ! Now check to see if CLUBB time step divides evenly into ! the host model time step. If not, force it to divide evenly. ! We also want it to be 5 minutes or less. This section is ! mainly for host model time steps that are not evenly divisible - ! by 5 minutes + ! by 5 minutes if (mod(hdtime,dtime) .ne. 0) then dtime = hdtime/2._r8 - do while (dtime > clubb_timestep) + do while (dtime > clubb_timestep) dtime = dtime/2._r8 end do - endif + endif ! If resulting host model time step and CLUBB time step do not divide evenly - ! into each other, have model throw a fit. + ! into each other, have model throw a fit. if (mod(hdtime,dtime) .ne. 0) then call endrun(subr//': CLUBB time step and HOST time step NOT compatible') endif - - ! determine number of timesteps CLUBB core should be advanced, - ! host time step divided by CLUBB time step + + ! determine number of timesteps CLUBB core should be advanced, + ! host time step divided by CLUBB time step nadv = max(hdtime/dtime,1._r8) - - ! Initialize forcings for transported scalars to zero + + ! Initialize forcings for transported scalars to zero sclrm_forcing(:,:,:) = 0._r8 edsclrm_forcing(:,:,:) = 0._r8 sclrm(:,:,:) = 0._r8 - + ! Compute inverse exner function consistent with CLUBB's definition, which uses a constant - ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent - ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables + ! surface pressure. CAM's exner (in state) does not. Therefore, for consistent + ! treatment with CLUBB code, anytime exner is needed to treat CLUBB variables ! (such as thlm), use "inv_exner_clubb" otherwise use the exner in state do k=1,pver do i=1,ncol @@ -2717,8 +2709,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & inv_exner_clubb_surf(i) = 1._r8/((state1%pmid(i,pver)/p0_clubb)**(rairv(i,pver,lchnk)/cpairv(i,pver,lchnk))) enddo - ! At each CLUBB call, initialize mean momentum and thermo CLUBB state - ! from the CAM state + ! At each CLUBB call, initialize mean momentum and thermo CLUBB state + ! from the CAM state do k=1,pver ! loop over levels do i=1,ncol ! loop over columns @@ -2731,11 +2723,11 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & * inv_exner_clubb(i,k) if (clubb_do_adv) then - if (macmic_it == 1) then + if (macmic_it == 1) then - ! Note that some of the moments below can be positive or negative. - ! Remove a constant that was added to prevent dynamics from clipping - ! them to prevent dynamics from making them positive. + ! Note that some of the moments below can be positive or negative. + ! Remove a constant that was added to prevent dynamics from clipping + ! them to prevent dynamics from making them positive. thlp2(i,k) = state1%q(i,k,ixthlp2) rtp2(i,k) = state1%q(i,k,ixrtp2) rtpthlp(i,k) = state1%q(i,k,ixrtpthlp) - (rtpthlp_const*apply_const) @@ -2750,23 +2742,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo enddo - + if (clubb_do_adv) then - ! If not last step of macmic loop then set apply_const back to - ! zero to prevent output from being corrupted. - if (macmic_it == cld_macmic_num_steps) then - apply_const = 1._r8 + ! If not last step of macmic loop then set apply_const back to + ! zero to prevent output from being corrupted. + if (macmic_it == cld_macmic_num_steps) then + apply_const = 1._r8 else apply_const = 0._r8 endif - endif + endif rtm(1:ncol,pverp) = rtm(1:ncol,pver) um(1:ncol,pverp) = state1%u(1:ncol,pver) vm(1:ncol,pverp) = state1%v(1:ncol,pver) thlm(1:ncol,pverp) = thlm(1:ncol,pver) - - if (clubb_do_adv) then + + if (clubb_do_adv) then thlp2(1:ncol,pverp) = thlp2(1:ncol,pver) rtp2(1:ncol,pverp) = rtp2(1:ncol,pver) rtpthlp(1:ncol,pverp) = rtpthlp(1:ncol,pver) @@ -2778,7 +2770,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vp2(1:ncol,pverp) = vp2(1:ncol,pver) endif - ! Compute virtual potential temperature, which is needed for CLUBB + ! Compute virtual potential temperature, which is needed for CLUBB do k=1,pver do i=1,ncol thv(i,k) = state1%t(i,k)*inv_exner_clubb(i,k)*(1._r8+zvir*state1%q(i,k,ixq)& @@ -2816,24 +2808,24 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & mf_thlflx_output(:,:) = 0._r8 mf_qtflx_output(:,:) = 0._r8 end if - + call t_startf("clubb_tend_cam_i_loop") ! Determine Coriolis force at given latitude. This is never used ! when CLUBB is implemented in a host model, therefore just set ! to zero. - fcor(:) = 0._r8 + fcor(:) = 0._r8 ! Define the CLUBB momentum grid (in height, units of m) do k=1, nlev+1 - do i=1, ncol + do i=1, ncol zi_g(i,k) = state1%zi(i,pverp-k+1)-state1%zi(i,pver+1) - end do + end do end do ! Define the CLUBB thermodynamic grid (in units of m) do k=1, nlev - do i=1, ncol + do i=1, ncol zt_g(i,k+1) = state1%zm(i,pver-k+1)-state1%zi(i,pver+1) end do end do @@ -2843,18 +2835,18 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & dz_g(i,k) = state1%zi(i,k)-state1%zi(i,k+1) ! compute thickness end do end do - - ! Thermodynamic ghost point is below surface + + ! Thermodynamic ghost point is below surface do i=1, ncol zt_g(i,1) = -1._r8*zt_g(i,2) end do - + do i=1, ncol ! Set the elevation of the surface sfc_elevation(i) = state1%zi(i,pver+1) end do - ! Compute thermodynamic stuff needed for CLUBB on thermo levels. + ! Compute thermodynamic stuff needed for CLUBB on thermo levels. ! Inputs for the momentum levels are set below setup_clubb core do k=1,nlev do i=1, ncol @@ -2863,7 +2855,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & invrs_rho_ds_zt(i,k+1) = 1._r8/(rho_ds_zt(i,k+1)) ! full state (moist) variables - p_in_Pa(i,k+1) = state1%pmid(i,pver-k+1) + p_in_Pa(i,k+1) = state1%pmid(i,pver-k+1) exner(i,k+1) = 1._r8/inv_exner_clubb(i,pver-k+1) thv(i,k+1) = state1%t(i,pver-k+1)*inv_exner_clubb(i,pver-k+1)*(1._r8+zvir*state1%q(i,pver-k+1,ixq) & -state1%q(i,pver-k+1,ixcldliq)) @@ -2872,13 +2864,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! exception - setting this to moist thv thv_ds_zt(i,k+1) = thv(i,k+1) - rfrzm(i,k+1) = state1%q(i,pver-k+1,ixcldice) + rfrzm(i,k+1) = state1%q(i,pver-k+1,ixcldice) radf(i,k+1) = radf_clubb(i,pver-k+1) qrl_clubb(i,k+1) = qrl(i,pver-k+1)/(cpairv(i,k,lchnk)*state1%pdeldry(i,pver-k+1)) end do end do - - ! Compute mean w wind on thermo grid, convert from omega to w + + ! Compute mean w wind on thermo grid, convert from omega to w do k=1,nlev do i=1,ncol wm_zt(i,k+1) = -1._r8*(state1%omega(i,pver-k+1)-state1%omega(i,pver))/(rho_zt(i,k+1)*gravit) @@ -2900,8 +2892,8 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & qrl_clubb(i,1) = qrl_clubb(i,2) wm_zt(i,1) = wm_zt(i,2) end do - - + + ! ------------------------------------------------- ! ! Begin case specific code for SCAM cases. ! ! This section of code block is NOT called in ! @@ -2919,21 +2911,21 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Compute surface wind (ubar) ubar = sqrt(um(1,pver)**2+vm(1,pver)**2) if (ubar < 0.25_r8) ubar = 0.25_r8 - + ! Below denotes case specifics for surface momentum ! and thermodynamic fluxes, depending on the case - ! Define ustar (based on case, if not variable) + ! Define ustar (based on case, if not variable) ustar = 0.25_r8 ! Initialize ustar in case no case - + if(trim(scm_clubb_iop_name) == 'BOMEX_5day') then ustar = 0.28_r8 endif - + if(trim(scm_clubb_iop_name) == 'ATEX_48hr') then ustar = 0.30_r8 endif - + if(trim(scm_clubb_iop_name) == 'RICO_3day') then ustar = 0.28_r8 endif @@ -2941,23 +2933,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & if(trim(scm_clubb_iop_name) == 'arm97' .or. trim(scm_clubb_iop_name) == 'gate' .or. & trim(scm_clubb_iop_name) == 'toga' .or. trim(scm_clubb_iop_name) == 'mpace' .or. & trim(scm_clubb_iop_name) == 'ARM_CC') then - + bflx22(1) = (gravit/theta0)*wpthlp_sfc(1) - ustar = diag_ustar(zt_g(1,2),bflx22(1),ubar,zo(1)) + ustar = diag_ustar(zt_g(1,2),bflx22(1),ubar,zo(1)) endif - - ! Compute the surface momentum fluxes, if this is a SCAM simulation + + ! Compute the surface momentum fluxes, if this is a SCAM simulation upwp_sfc(1) = -um(1,pver)*ustar**2/ubar vpwp_sfc(1) = -vm(1,pver)*ustar**2/ubar - + end if - ! Define surface sources for transported variables for diffusion, will + ! Define surface sources for transported variables for diffusion, will ! be zero as these tendencies are done in vertical_diffusion do ixind=1,edsclr_dim do i=1,ncol wpedsclrp_sfc(i,ixind) = 0._r8 - end do + end do end do ! Set stats output and increment equal to CLUBB and host dt @@ -2966,10 +2958,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & stats_nsamp = nint(stats_tsamp/dtime) stats_nout = nint(stats_tout/dtime) - - ! Heights need to be set at each timestep. Therefore, recall - ! setup_grid and setup_parameters for this. - + + ! Heights need to be set at each timestep. Therefore, recall + ! setup_grid and setup_parameters for this. + ! Set-up CLUBB core at each CLUBB call because heights can change ! Important note: do not make any calls that use CLUBB grid-height ! operators (such as zt2zm_api, etc.) until AFTER the @@ -3002,7 +2994,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vm_ref(:,:) = 0.0_r8 ug(:,:) = 0.0_r8 vg(:,:) = 0.0_r8 - + ! Add forcings for SILHS covariance contributions rtp2_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, rtp2_mc_zt(1:ncol,:) ) thlp2_forcing = zt2zm_api( pverp+1-top_lev, ncol, gr, thlp2_mc_zt(1:ncol,:) ) @@ -3016,7 +3008,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wprtp_mc_zt(:,:) = 0.0_r8 wpthlp_mc_zt(:,:) = 0.0_r8 rtpthlp_mc_zt(:,:) = 0.0_r8 - + ! Compute some inputs from the thermodynamic grid ! to the momentum grid @@ -3025,9 +3017,9 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & invrs_rho_ds_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, invrs_rho_ds_zt ) thv_ds_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, thv_ds_zt ) wm_zm = zt2zm_api( pverp+1-top_lev, ncol, gr, wm_zt ) - + ! Surface fluxes provided by host model - do i=1,ncol + do i=1,ncol wpthlp_sfc(i) = cam_in%shf(i)/(cpairv(i,pver,lchnk)*rho_ds_zm(i,1)) ! Sensible heat flux wpthlp_sfc(i) = wpthlp_sfc(i)*inv_exner_clubb_surf(i) ! Potential temperature flux wprtp_sfc(i) = cam_in%cflx(i,1)/rho_ds_zm(i,1) ! Moisture flux @@ -3043,7 +3035,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call calc_ustar( state1%t(i,pver), state1%pmid(i,pver), cam_in%wsx(i), cam_in%wsy(i), & rrho(i), ustar ) - + upwp_sfc(i) = -state1%u(i,pver)*ustar**2/ubar vpwp_sfc(i) = -state1%v(i,pver)*ustar**2/ubar end do @@ -3057,12 +3049,12 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Perturbed winds are not used in CAM upwp_sfc_pert = 0.0_r8 vpwp_sfc_pert = 0.0_r8 - + ! Need to flip arrays around for CLUBB core do k=1,nlev+1 do i=1,ncol - um_in(i,k) = um(i,pverp-k+1) - vm_in(i,k) = vm(i,pverp-k+1) + um_in(i,k) = um(i,pverp-k+1) + vm_in(i,k) = vm(i,pverp-k+1) upwp_in(i,k) = upwp(i,pverp-k+1) vpwp_in(i,k) = vpwp(i,pverp-k+1) wpthvp_in(i,k) = wpthvp(i,pverp-k+1) @@ -3121,13 +3113,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vm_pert_inout = 0.0_r8 upwp_pert_inout = 0.0_r8 vpwp_pert_inout = 0.0_r8 - + do k=2,nlev+1 do i=1,ncol pre_in(i,k) = prer_evap(i,pverp-k+1) end do end do - + do i=1,ncol pre_in(i,1) = pre_in(i,2) end do @@ -3135,7 +3127,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & do i=1,ncol rcm_inout(i,1) = rcm_inout(i,2) end do - + ! Initialize these to prevent crashing behavior do k=1,nlev+1 do i=1,ncol @@ -3162,7 +3154,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do end do - + do ixind=1, hydromet_dim do k=1, nlev+1 do i=1, ncol @@ -3177,7 +3169,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! pressure,exner on momentum grid needed for mass flux calc. if (do_clubb_mf) then - + do k=1,pver do i=1,ncol kappa_zt(i,k+1) = (rairv(i,pver-k+1,lchnk)/cpairv(i,pver-k+1,lchnk)) @@ -3185,7 +3177,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & invrs_exner_zt(i,k+1) = inv_exner_clubb(i,pver-k+1) end do end do - + do i=1,ncol kappa_zt(i,1) = kappa_zt(i,2) qc_zt(i,1) = qc_zt(i,2) @@ -3193,21 +3185,21 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do kappa_zm(1:ncol,:) = zt2zm_api(pverp+1-top_lev, ncol, gr, kappa_zt(1:ncol,:)) - + do k=1,pverp do i=1,ncol p_in_Pa_zm(i,k) = state1%pint(i,pverp-k+1) invrs_exner_zm(i,k) = 1._r8/((p_in_Pa_zm(i,k)/p0_clubb)**(kappa_zm(i,k))) end do end do - + end if - - + + if (clubb_do_adv) then if (macmic_it == 1) then - - wp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wp2_in ) + + wp2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wp2_in ) wpthlp_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wpthlp_in ) wprtp_in = zt2zm_api(pverp+1-top_lev, ncol, gr, wprtp_in ) up2_in = zt2zm_api(pverp+1-top_lev, ncol, gr, up2_in ) @@ -3225,49 +3217,49 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vp2_in(i,k) = max(w_tol_sqd,vp2_in(i,k)) end do end do - + end if end if - ! Do the same for tracers + ! Do the same for tracers icnt=0 do ixind=1,pcnst - if (lq(ixind)) then - + if (lq(ixind)) then + icnt = icnt+1 - + do k=1,nlev do i=1,ncol edsclr_in(i,k+1,icnt) = state1%q(i,pver-k+1,ixind) end do end do - + do i=1,ncol edsclr_in(i,1,icnt) = edsclr_in(i,2,icnt) end do - + end if end do - - if (clubb_l_do_expldiff_rtm_thlm) then + + if (clubb_l_do_expldiff_rtm_thlm) then do k=1,nlev do i=1, ncol edsclr_in(i,k+1,icnt+1) = thlm(i,pver-k+1) edsclr_in(i,k+1,icnt+2) = rtm(i,pver-k+1) end do end do - + do i=1, ncol edsclr_in(i,1,icnt+1) = edsclr_in(i,2,icnt+1) - edsclr_in(i,1,icnt+2) = edsclr_in(i,2,icnt+2) + edsclr_in(i,1,icnt+2) = edsclr_in(i,2,icnt+2) end do - + endif do t=1,nadv ! do needed number of "sub" timesteps for each CAM step - + ! Increment the statistics then being stats timestep if (l_stats) then call stats_begin_timestep_api(t, stats_nsamp, stats_nout) @@ -3277,18 +3269,18 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & !###################### CALL MF DIAGNOSTIC PLUMES ###################### !####################################################################### if (do_clubb_mf) then - + do k=2,pverp do i=1, ncol dzt(i,k) = zi_g(i,k) - zi_g(i,k-1) end do end do - + do i=1, ncol dzt(i,1) = dzt(i,2) invrs_dzt(i,:) = 1._r8/dzt(i,:) end do - + rtm_zm_in(1:ncol,:) = zt2zm_api( pverp+1-top_lev, ncol, gr, rtm_in(1:ncol,:) ) thlm_zm_in(1:ncol,:) = zt2zm_api( pverp+1-top_lev, ncol, gr, thlm_in(1:ncol,:) ) @@ -3317,19 +3309,19 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rtm_forcing(i,1) = 0._r8 thlm_forcing(i,1)= 0._r8 end do - + do k=2,pverp do i=1, ncol rtm_forcing(i,k) = rtm_forcing(i,k) - invrs_rho_ds_zt(i,k) * invrs_dzt(i,k) * & ((rho_ds_zm(i,k) * mf_qtflx(i,k)) - (rho_ds_zm(i,k-1) * mf_qtflx(i,k-1))) - + thlm_forcing(i,k) = thlm_forcing(i,k) - invrs_rho_ds_zt(i,k) * invrs_dzt(i,k) * & ((rho_ds_zm(i,k) * mf_thlflx(i,k)) - (rho_ds_zm(i,k-1) * mf_thlflx(i,k-1))) end do end do end if - + ! Advance CLUBB CORE one timestep in the future call advance_clubb_core_api( gr, pverp+1-top_lev, ncol, & l_implemented, dtime, fcor, sfc_elevation, hydromet_dim, & @@ -3371,7 +3363,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wprcp_out, w_up_in_cloud_out, w_down_in_cloud_out, & cloudy_updraft_frac_out, cloudy_downdraft_frac_out, & rcm_in_layer_out, cloud_cover_out, invrs_tau_zm_out ) - + ! Note that CLUBB does not produce an error code specific to any column, and ! one value only for the entire chunk if ( err_code == clubb_fatal_error ) then @@ -3380,15 +3372,15 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & write(fstderr,*) "LON: Range:", state1%lon(1), " -- ", state1%lon(ncol) call endrun(subr//': Fatal error in CLUBB library') end if - + if (do_rainturb) then - + do k=1,nlev+1 do i=1,ncol - rvm_in(i,k) = rtm_in(i,k) - rcm_inout(i,k) + rvm_in(i,k) = rtm_in(i,k) - rcm_inout(i,k) end do end do - + call update_xp2_mc_api( gr, nlev+1, ncol, dtime, cloud_frac_inout, & rcm_inout, rvm_in, thlm_in, wm_zt, & exner, pre_in, pdf_params_chnk(lchnk), & @@ -3400,35 +3392,35 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & do i=1,ncol dum1 = (1._r8 - cam_in%landfrac(i)) - ! update turbulent moments based on rain evaporation + ! update turbulent moments based on rain evaporation rtp2_in(i,k) = rtp2_in(i,k) + clubb_rnevap_effic * dum1 * rtp2_mc_out(i,k) * dtime - thlp2_in(i,k) = thlp2_in(i,k) + clubb_rnevap_effic * dum1 * thlp2_mc_out(i,k) * dtime + thlp2_in(i,k) = thlp2_in(i,k) + clubb_rnevap_effic * dum1 * thlp2_mc_out(i,k) * dtime wprtp_in(i,k) = wprtp_in(i,k) + clubb_rnevap_effic * dum1 * wprtp_mc_out(i,k) * dtime wpthlp_in(i,k) = wpthlp_in(i,k) + clubb_rnevap_effic * dum1 * wpthlp_mc_out(i,k) * dtime end do end do - - end if - + + end if + if (do_cldcool) then - + rcm_out_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, rcm_inout ) qrl_zm = zt2zm_api(pverp+1-top_lev, ncol, gr, qrl_clubb ) thlp2_rad_out(:,:) = 0._r8 - + do i=1, ncol call calculate_thlp2_rad_api(nlev+1, rcm_out_zm(i,:), thlprcp_out(i,:), qrl_zm(i,:), clubb_params, & thlp2_rad_out(i,:)) end do - + do i=1, ncol thlp2_in(i,:) = thlp2_in(i,:) + thlp2_rad_out(i,:) * dtime thlp2_in(i,:) = max(thl_tol**2,thlp2_in(i,:)) end do - + end if - + ! Check to see if stats should be output, here stats are read into ! output arrays to make them conformable to CAM output if (l_stats) then @@ -3441,16 +3433,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & enddo ! end time loop if (clubb_do_adv) then - if (macmic_it == cld_macmic_num_steps) then - - wp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) + if (macmic_it == cld_macmic_num_steps) then + + wp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) wpthlp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wpthlp_in ) wprtp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, wprtp_in ) up2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, up2_in ) vp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, vp2_in ) thlp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, thlp2_in ) rtp2_in = zm2zt_api( pverp+1-top_lev, ncol, gr, rtp2_in ) - rtpthlp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, rtpthlp_in ) + rtpthlp_in = zm2zt_api( pverp+1-top_lev, ncol, gr, rtpthlp_in ) do k=1,nlev+1 do i=1, ncol @@ -3461,16 +3453,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & vp2_in(i,k) = max(w_tol_sqd, vp2_in(i,k)) end do end do - + end if end if - + ! Convert RTP2 and THLP2 to thermo grid for output rtp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, rtp2_in ) thl2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, thlp2_in ) wp2_zt = zm2zt_api( pverp+1-top_lev, ncol, gr, wp2_in ) - ! Arrays need to be "flipped" to CAM grid + ! Arrays need to be "flipped" to CAM grid do k=1, nlev+1 do i=1, ncol um(i,pverp-k+1) = um_in(i,k) @@ -3526,18 +3518,18 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & rtp2_zt_out(i,pverp-k+1) = rtp2_zt(i,k) thl2_zt_out(i,pverp-k+1) = thl2_zt(i,k) wp2_zt_out(i,pverp-k+1) = wp2_zt(i,k) - + end do end do do k=1, nlev+1 do i=1, ncol - + mean_rt = pdf_params_chnk(lchnk)%mixt_frac(i,k) & * pdf_params_chnk(lchnk)%rt_1(i,k) & + ( 1.0_r8 - pdf_params_chnk(lchnk)%mixt_frac(i,k) ) & * pdf_params_chnk(lchnk)%rt_2(i,k) - + pdfp_rtp2(i,pverp-k+1) = pdf_params_chnk(lchnk)%mixt_frac(i,k) & * ( ( pdf_params_chnk(lchnk)%rt_1(i,k) - mean_rt )**2 & + pdf_params_chnk(lchnk)%varnce_rt_1(i,k) ) & @@ -3603,18 +3595,18 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & khzm(i,k) = 0._r8 qclvar(i,k) = 2._r8 end do - end do + end do ! enforce zero tracer tendencies above the top_lev level -- no change icnt=0 do ixind=1,pcnst - if (lq(ixind)) then + if (lq(ixind)) then icnt=icnt+1 - + do i=1, ncol edsclr_out(i,:top_lev-1,icnt) = state1%q(i,:top_lev-1,ixind) end do - + end if end do @@ -3632,7 +3624,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do ! Section below is concentrated on energy fixing for conservation. - ! because CLUBB and CAM's thermodynamic variables are different. + ! because CLUBB and CAM's thermodynamic variables are different. ! Initialize clubbtop to top_lev, for finding the highlest level CLUBB is ! active for informing where to apply the energy fixer. @@ -3640,16 +3632,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & clubbtop(i) = top_lev do while ((rtp2(i,clubbtop(i)) <= 1.e-15_r8 .and. rcm(i,clubbtop(i)) == 0._r8) .and. clubbtop(i) < pver) clubbtop(i) = clubbtop(i) + 1 - end do + end do end do - + ! Compute integrals for static energy, kinetic energy, water vapor, and liquid water ! after CLUBB is called. This is for energy conservation purposes. se_a(:) = 0._r8 ke_a(:) = 0._r8 wv_a(:) = 0._r8 wl_a(:) = 0._r8 - + do k=1,pver do i=1, ncol se_a(i) = se_a(i) + clubb_s(i,k)*state1%pdel(i,k)*rga @@ -3657,14 +3649,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wv_a(i) = wv_a(i) + (rtm(i,k)-rcm(i,k))*state1%pdeldry(i,k)*rga wl_a(i) = wl_a(i) + (rcm(i,k))*state1%pdeldry(i,k)*rga end do - end do - + end do + ! Do the same as above, but for before CLUBB was called. se_b(:) = 0._r8 ke_b(:) = 0._r8 wv_b(:) = 0._r8 - wl_b(:) = 0._r8 - + wl_b(:) = 0._r8 + do k=1, pver do i=1, ncol se_b(i) = se_b(i) + state1%s(i,k)*state1%pdel(i,k)*rga @@ -3673,23 +3665,23 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wl_b(i) = wl_b(i) + state1%q(i,k,ixcldliq)*state1%pdeldry(i,k)*rga end do end do - - + + do i=1, ncol ! Based on these integrals, compute the total energy before and after CLUBB call te_a(i) = se_a(i) + ke_a(i) + (latvap+latice) * wv_a(i) + latice * wl_a(i) te_b(i) = se_b(i) + ke_b(i) + (latvap+latice) * wv_b(i) + latice * wl_b(i) - + ! Take into account the surface fluxes of heat and moisture ! Use correct qflux from cam_in, not lhf/latvap as was done previously - te_b(i) = te_b(i) + (cam_in%shf(i)+cam_in%cflx(i,1)*(latvap+latice)) * hdtime + te_b(i) = te_b(i) + (cam_in%shf(i)+cam_in%cflx(i,1)*(latvap+latice)) * hdtime ! Compute the disbalance of total energy, over depth where CLUBB is active se_dis(i) = (te_a(i) - te_b(i))/(state1%pint(i,pverp)-state1%pint(i,clubbtop(i))) end do ! Fix the total energy coming out of CLUBB so it achieves energy conservation. - ! Apply this fixer throughout the column evenly, but only at layers where + ! Apply this fixer throughout the column evenly, but only at layers where ! CLUBB is active. ! ! NOTE: The energy fixer seems to cause the climate to change significantly @@ -3705,7 +3697,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do endif - + ! Now compute the tendencies of CLUBB to CAM, note that pverp is the ghost point ! for all variables and therefore is never called in this loop do k=1, pver @@ -3719,17 +3711,17 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end do end do - - + + if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then - + do k=1, pver do i=1, ncol - ! Here add a constant to moments which can be either positive or + ! Here add a constant to moments which can be either positive or ! negative. This is to prevent clipping when dynamics tries to - ! make all constituents positive + ! make all constituents positive wp3(i,k) = wp3(i,k) + wp3_const rtpthlp(i,k) = rtpthlp(i,k) + rtpthlp_const wpthlp(i,k) = wpthlp(i,k) + wpthlp_const @@ -3738,18 +3730,18 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ptend_loc%q(i,k,ixthlp2) = (thlp2(i,k) - state1%q(i,k,ixthlp2)) / hdtime ! THLP Variance ptend_loc%q(i,k,ixrtp2) = (rtp2(i,k) - state1%q(i,k,ixrtp2)) / hdtime ! RTP Variance ptend_loc%q(i,k,ixrtpthlp) = (rtpthlp(i,k) - state1%q(i,k,ixrtpthlp)) / hdtime ! RTP THLP covariance - ptend_loc%q(i,k,ixwpthlp) = (wpthlp(i,k) - state1%q(i,k,ixwpthlp)) / hdtime ! WPTHLP + ptend_loc%q(i,k,ixwpthlp) = (wpthlp(i,k) - state1%q(i,k,ixwpthlp)) / hdtime ! WPTHLP ptend_loc%q(i,k,ixwprtp) = (wprtp(i,k) - state1%q(i,k,ixwprtp)) / hdtime ! WPRTP ptend_loc%q(i,k,ixwp2) = (wp2(i,k) - state1%q(i,k,ixwp2)) / hdtime ! WP2 ptend_loc%q(i,k,ixwp3) = (wp3(i,k) - state1%q(i,k,ixwp3)) / hdtime ! WP3 ptend_loc%q(i,k,ixup2) = (up2(i,k) - state1%q(i,k,ixup2)) / hdtime ! UP2 ptend_loc%q(i,k,ixvp2) = (vp2(i,k) - state1%q(i,k,ixvp2)) / hdtime ! VP2 - + end do end do - + else - + do k=1, pver do i=1, ncol ptend_loc%q(i,k,ixthlp2) = 0._r8 @@ -3760,16 +3752,16 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ptend_loc%q(i,k,ixwp2) = 0._r8 ptend_loc%q(i,k,ixwp3) = 0._r8 ptend_loc%q(i,k,ixup2) = 0._r8 - ptend_loc%q(i,k,ixvp2) = 0._r8 + ptend_loc%q(i,k,ixvp2) = 0._r8 end do end do - + end if end if - + ! Apply tendencies to ice mixing ratio, liquid and ice number, and aerosol constituents. - ! Loading up this array doesn't mean the tendencies are applied. + ! Loading up this array doesn't mean the tendencies are applied. ! edsclr_out is compressed with just the constituents being used, ptend and state are not compressed icnt=0 do ixind=1,pcnst @@ -3780,17 +3772,17 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & (ixind /= ixrtpthlp) .and. (ixind /= ixwpthlp) .and.& (ixind /= ixwprtp) .and. (ixind /= ixwp2) .and.& (ixind /= ixwp3) .and. (ixind /= ixup2) .and. (ixind /= ixvp2) ) then - + do k=1, pver do i=1, ncol - ptend_loc%q(i,k,ixind) = (edsclr_out(i,k,icnt)-state1%q(i,k,ixind))/hdtime ! transported constituents + ptend_loc%q(i,k,ixind) = (edsclr_out(i,k,icnt)-state1%q(i,k,ixind))/hdtime ! transported constituents end do end do - + end if end if end do - + call t_stopf("clubb_tend_cam_i_loop") call outfld('KVH_CLUBB', khzm, pcols, lchnk) @@ -3799,7 +3791,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld('ELEAK_CLUBB', eleak, pcols, lchnk) call outfld('TFIX_CLUBB', se_dis, pcols, lchnk) - ! Add constant to ghost point so that output is not corrupted + ! Add constant to ghost point so that output is not corrupted if (clubb_do_adv) then if (macmic_it == cld_macmic_num_steps) then wp3(:,pverp) = wp3(:,pverp) + wp3_const @@ -3807,7 +3799,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & wpthlp(:,pverp) = wpthlp(:,pverp) + wpthlp_const wprtp(:,pverp) = wprtp(:,pverp) + wprtp_const end if - end if + end if ! ------------------------------------------------- ! ! End column computation of CLUBB, begin to apply ! @@ -3833,32 +3825,32 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call physics_ptend_sum(ptend_loc,ptend_all,ncol) call physics_update(state1,ptend_loc,hdtime) - - ! Due to the order of operation of CLUBB, which closes on liquid first, - ! then advances it's predictive equations second, this can lead to - ! RHliq > 1 directly before microphysics is called. Therefore, we use - ! ice_macro_tend to enforce RHliq <= 1 everywhere before microphysics is called. - + + ! Due to the order of operation of CLUBB, which closes on liquid first, + ! then advances it's predictive equations second, this can lead to + ! RHliq > 1 directly before microphysics is called. Therefore, we use + ! ice_macro_tend to enforce RHliq <= 1 everywhere before microphysics is called. + if (clubb_do_liqsupersat) then - + ! -------------------------------------- ! ! Ice Saturation Adjustment Computation ! ! -------------------------------------- ! - + latsub = latvap + latice lq2(:) = .FALSE. lq2(ixq) = .TRUE. lq2(ixcldliq) = .TRUE. lq2(ixnumliq) = .TRUE. - + call physics_ptend_init(ptend_loc, state%psetcols, 'iceadj', ls=.true., lq=lq2 ) - + stend(:ncol,:)=0._r8 qvtend(:ncol,:)=0._r8 qctend(:ncol,:)=0._r8 inctend(:ncol,:)=0._r8 - + call liquid_macro_tend(npccn(1:ncol,top_lev:pver), state1%t(1:ncol,top_lev:pver), & state1%pmid(1:ncol,top_lev:pver), state1%q(1:ncol,top_lev:pver,ixq), & state1%q(1:ncol,top_lev:pver,ixcldliq), state1%q(1:ncol,top_lev:pver,ixnumliq), & @@ -3870,13 +3862,13 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ptend_loc%q(:ncol,top_lev:pver,ixcldliq)=qctend(:ncol,top_lev:pver) ptend_loc%q(:ncol,top_lev:pver,ixnumliq)=inctend(:ncol,top_lev:pver) ptend_loc%s(:ncol,top_lev:pver)=stend(:ncol,top_lev:pver) - + ! Add the ice tendency to the output tendency call physics_ptend_sum(ptend_loc, ptend_all, ncol) - + ! ptend_loc is reset to zero by this call call physics_update(state1, ptend_loc, hdtime) - + ! Write output for tendencies: ! oufld: QVTENDICE,QCTENDICE,NCTENDICE,FQTENDICE temp2d(:ncol,:pver) = stend(:ncol,:pver)/cpairv(:ncol,:pver,lchnk) @@ -3884,25 +3876,25 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'QVTENDICE', qvtend, pcols, lchnk ) call outfld( 'QCTENDICE', qctend, pcols, lchnk ) call outfld( 'NCTENDICE', inctend, pcols, lchnk ) - + where(qctend .ne. 0._r8) fqtend = 1._r8 elsewhere fqtend = 0._r8 end where - + call outfld( 'FQTENDICE', fqtend, pcols, lchnk ) end if - + ! ------------------------------------------------------------ ! ! The rest of the code deals with diagnosing variables ! ! for microphysics/radiation computation and macrophysics ! ! ------------------------------------------------------------ ! - - ! --------------------------------------------------------------------------------- ! + + ! --------------------------------------------------------------------------------- ! ! COMPUTE THE ICE CLOUD DETRAINMENT ! ! Detrainment of convective condensate into the environment or stratiform cloud ! - ! --------------------------------------------------------------------------------- ! + ! --------------------------------------------------------------------------------- ! ! Initialize the shallow convective detrainment rate, will always be zero dlf2(:,:) = 0.0_r8 @@ -3917,13 +3909,6 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call physics_ptend_init(ptend_loc,state%psetcols, 'clubb', ls=.true., lq=lqice) - if (zmconv_microp) then - call pbuf_get_field(pbuf, dlfzm_idx, dlfzm) - call pbuf_get_field(pbuf, difzm_idx, difzm) - call pbuf_get_field(pbuf, dnlfzm_idx, dnlfzm) - call pbuf_get_field(pbuf, dnifzm_idx, dnifzm) - end if - do k=1,pver do i=1,ncol if( state1%t(i,k) > meltpt_temp ) then @@ -3931,35 +3916,24 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & elseif ( state1%t(i,k) < dt_low ) then dum1 = 1.0_r8 else - dum1 = ( meltpt_temp - state1%t(i,k) ) / ( meltpt_temp - dt_low ) + dum1 = ( meltpt_temp - state1%t(i,k) ) / ( meltpt_temp - dt_low ) endif - if (zmconv_microp) then - ptend_loc%q(i,k,ixcldliq) = dlfzm(i,k) + dlf2(i,k) * ( 1._r8 - dum1 ) - ptend_loc%q(i,k,ixcldice) = difzm(i,k) + dlf2(i,k) * dum1 - - ptend_loc%q(i,k,ixnumliq) = dnlfzm(i,k) + 3._r8 * ( dlf2(i,k) * ( 1._r8 - dum1 ) ) & - / (4._r8*3.14_r8*dl_rad**3*997._r8) ! Shallow Convection - ptend_loc%q(i,k,ixnumice) = dnifzm(i,k) + 3._r8 * ( dlf2(i,k) * dum1 ) & - / (4._r8*3.14_r8*di_rad**3*500._r8) ! Shallow Convection - ptend_loc%s(i,k) = dlf2(i,k) * dum1 * latice - else - - ptend_loc%q(i,k,ixcldliq) = dlf(i,k) * ( 1._r8 - dum1 ) - ptend_loc%q(i,k,ixcldice) = dlf(i,k) * dum1 - ptend_loc%q(i,k,ixnumliq) = 3._r8 * ( max(0._r8, ( dlf(i,k) - dlf2(i,k) )) * ( 1._r8 - dum1 ) ) & + ptend_loc%q(i,k,ixcldliq) = dlf(i,k) * ( 1._r8 - dum1 ) + ptend_loc%q(i,k,ixcldice) = dlf(i,k) * dum1 + ptend_loc%q(i,k,ixnumliq) = 3._r8 * ( max(0._r8, ( dlf(i,k) - dlf2(i,k) )) * ( 1._r8 - dum1 ) ) & / (4._r8*3.14_r8*dl_rad**3*997._r8) + & ! Deep Convection 3._r8 * ( dlf2(i,k) * ( 1._r8 - dum1 ) ) & - / (4._r8*3.14_r8*10.e-6_r8**3*997._r8) ! Shallow Convection - ptend_loc%q(i,k,ixnumice) = 3._r8 * ( max(0._r8, ( dlf(i,k) - dlf2(i,k) )) * dum1 ) & + / (4._r8*3.14_r8*10.e-6_r8**3*997._r8) ! Shallow Convection + ptend_loc%q(i,k,ixnumice) = 3._r8 * ( max(0._r8, ( dlf(i,k) - dlf2(i,k) )) * dum1 ) & / (4._r8*3.14_r8*di_rad**3*500._r8) + & ! Deep Convection 3._r8 * ( dlf2(i,k) * dum1 ) & / (4._r8*3.14_r8*50.e-6_r8**3*500._r8) ! Shallow Convection - ptend_loc%s(i,k) = dlf(i,k) * dum1 * latice + ptend_loc%s(i,k) = dlf(i,k) * dum1 * latice + + dlf_liq_out(i,k) = dlf(i,k) * ( 1._r8 - dum1 ) + dlf_ice_out(i,k) = dlf(i,k) * dum1 - dlf_liq_out(i,k) = dlf(i,k) * ( 1._r8 - dum1 ) - dlf_ice_out(i,k) = dlf(i,k) * dum1 - end if ! convert moist dlf tendencies to dry ptend_loc%q(i,k,ixcldliq) = ptend_loc%q(i,k,ixcldliq)*state1%pdel(i,k)/state1%pdeldry(i,k) ptend_loc%q(i,k,ixcldice) = ptend_loc%q(i,k,ixcldice)*state1%pdel(i,k)/state1%pdeldry(i,k) @@ -3971,20 +3945,20 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & det_ice(i) = det_ice(i) - ptend_loc%q(i,k,ixcldice)*state1%pdeldry(i,k)*rga enddo enddo - + det_ice(:ncol) = det_ice(:ncol)/1000._r8 ! divide by density of water ! output moist basis to be consistent with history variable definition - temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) + temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldliq)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) call outfld( 'DPDLFLIQ', temp2d, pcols, lchnk) ! output moist basis to be consistent with history variable definition temp2d(:ncol,:pver) = ptend_loc%q(:ncol,:pver,ixcldice)*state1%pdeldry(:ncol,:pver)/state1%pdel(:ncol,:pver) call outfld( 'DPDLFICE', temp2d, pcols, lchnk) - + temp2d(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpairv(:ncol,:pver, lchnk) call outfld( 'DPDLFT', temp2d, pcols, lchnk) - + call outfld( 'DETNLIQTND', ptend_loc%q(:,:,ixnumliq),pcols, lchnk ) call physics_ptend_sum(ptend_loc,ptend_all,ncol) @@ -4011,19 +3985,19 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & else relvarmax = 10.0_r8 endif - + relvar(:,:) = relvarmax ! default - if (deep_scheme .ne. 'CLUBB_SGS') then + if (deep_scheme .ne. 'CLUBB_SGS') then where (rcm(:ncol,:pver) /= 0 .and. qclvar(:ncol,:pver) /= 0) & relvar(:ncol,:pver) = min(relvarmax,max(0.001_r8,rcm(:ncol,:pver)**2/qclvar(:ncol,:pver))) endif - + ! ------------------------------------------------- ! ! Optional Accretion enhancement factor ! - ! ------------------------------------------------- ! + ! ------------------------------------------------- ! accre_enhan(:ncol,:pver) = 1._r8 - + ! ------------------------------------------------- ! ! Diagnose some output variables ! ! ------------------------------------------------- ! @@ -4049,7 +4023,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & sl_output(i,k) = cpairv(i,k,lchnk)*state1%t(i,k)+gravit*state1%zm(i,k)-latvap*state1%q(i,k,ixcldliq) enddo enddo - + do k=1,pverp do i=1,ncol wpthlp_output(i,k) = (wpthlp(i,k)-(apply_const*wpthlp_const))*rho(i,k)*cpair ! liquid water potential temperature flux @@ -4063,53 +4037,53 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if enddo enddo - - ! --------------------------------------------------------------------------------- ! + + ! --------------------------------------------------------------------------------- ! ! Diagnose some quantities that are computed in macrop_tend here. ! ! These are inputs required for the microphysics calculation. ! ! ! ! FIRST PART COMPUTES THE STRATIFORM CLOUD FRACTION FROM CLUBB CLOUD FRACTION ! - ! --------------------------------------------------------------------------------- ! - - ! initialize variables + ! --------------------------------------------------------------------------------- ! + + ! initialize variables alst(:,:) = 0.0_r8 - qlst(:,:) = 0.0_r8 - + qlst(:,:) = 0.0_r8 + do k=1,pver do i=1,ncol - alst(i,k) = cloud_frac(i,k) + alst(i,k) = cloud_frac(i,k) qlst(i,k) = rcm(i,k)/max(0.01_r8,alst(i,k)) ! Incloud stratus condensate mixing ratio enddo enddo - - ! --------------------------------------------------------------------------------- ! + + ! --------------------------------------------------------------------------------- ! ! THIS PART COMPUTES CONVECTIVE AND DEEP CONVECTIVE CLOUD FRACTION ! - ! --------------------------------------------------------------------------------- ! - + ! --------------------------------------------------------------------------------- ! + deepcu(:,:) = 0.0_r8 shalcu(:,:) = 0.0_r8 - + do k=1,pver-1 do i=1,ncol - ! diagnose the deep convective cloud fraction, as done in macrophysics based on the - ! deep convective mass flux, read in from pbuf. Since shallow convection is never + ! diagnose the deep convective cloud fraction, as done in macrophysics based on the + ! deep convective mass flux, read in from pbuf. Since shallow convection is never ! called, the shallow convective mass flux will ALWAYS be zero, ensuring that this cloud - ! fraction is purely from deep convection scheme. + ! fraction is purely from deep convection scheme. deepcu(i,k) = max(0.0_r8,min(dp1*log(1.0_r8+dp2*(cmfmc(i,k+1)-cmfmc_sh(i,k+1))),0.6_r8)) shalcu(i,k) = 0._r8 - + if (deepcu(i,k) <= frac_limit .or. dp_icwmr(i,k) < ic_limit) then deepcu(i,k) = 0._r8 endif - - ! using the deep convective cloud fraction, and CLUBB cloud fraction (variable + + ! using the deep convective cloud fraction, and CLUBB cloud fraction (variable ! "cloud_frac"), compute the convective cloud fraction. This follows the formulation - ! found in macrophysics code. Assumes that convective cloud is all nonstratiform cloud + ! found in macrophysics code. Assumes that convective cloud is all nonstratiform cloud ! from CLUBB plus the deep convective cloud fraction concld(i,k) = min(cloud_frac(i,k)-alst(i,k)+deepcu(i,k),0.80_r8) enddo enddo - + if (single_column) then if (trim(scm_clubb_iop_name) == 'ATEX_48hr' .or. & trim(scm_clubb_iop_name) == 'BOMEX_5day' .or. & @@ -4117,20 +4091,20 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & trim(scm_clubb_iop_name) == 'DYCOMSrf02_06hr' .or. & trim(scm_clubb_iop_name) == 'RICO_3day' .or. & trim(scm_clubb_iop_name) == 'ARM_CC') then - + deepcu(:,:) = 0.0_r8 concld(:,:) = 0.0_r8 - - endif + + endif endif - - ! --------------------------------------------------------------------------------- ! + + ! --------------------------------------------------------------------------------- ! ! COMPUTE THE ICE CLOUD FRACTION PORTION ! ! use the aist_vector function to compute the ice cloud fraction ! - ! --------------------------------------------------------------------------------- ! + ! --------------------------------------------------------------------------------- ! aist(:,:top_lev-1) = 0._r8 - qsatfac(:, :) = 0._r8 ! Zero out entire profile in case qsatfac is left undefined in aist_vector below + qsatfac(:, :) = 0._r8 ! Zero out entire profile in case qsatfac is left undefined in aist_vector below do k = top_lev, pver @@ -4159,37 +4133,37 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & qsatfac_out=qsatfac(:,k), rhmini_in=rhmini, rhmaxi_in=rhmaxi) endif enddo - - ! --------------------------------------------------------------------------------- ! + + ! --------------------------------------------------------------------------------- ! ! THIS PART COMPUTES THE LIQUID STRATUS FRACTION ! ! ! ! For now leave the computation of ice stratus fraction from macrop_driver intact ! - ! because CLUBB does nothing with ice. Here I simply overwrite the liquid stratus ! + ! because CLUBB does nothing with ice. Here I simply overwrite the liquid stratus ! ! fraction that was coded in macrop_driver ! - ! --------------------------------------------------------------------------------- ! - + ! --------------------------------------------------------------------------------- ! + ! Recompute net stratus fraction using maximum over-lapping assumption, as done ! in macrophysics code, using alst computed above and aist read in from physics buffer - + do k=1,pver do i=1,ncol ast(i,k) = max(alst(i,k),aist(i,k)) - qist(i,k) = state1%q(i,k,ixcldice)/max(0.01_r8,aist(i,k)) + qist(i,k) = state1%q(i,k,ixcldice)/max(0.01_r8,aist(i,k)) enddo enddo - - ! Probably need to add deepcu cloud fraction to the cloud fraction array, else would just - ! be outputting the shallow convective cloud fraction + + ! Probably need to add deepcu cloud fraction to the cloud fraction array, else would just + ! be outputting the shallow convective cloud fraction do k=1,pver do i=1,ncol cloud_frac(i,k) = min(ast(i,k)+deepcu(i,k),1.0_r8) enddo enddo - - ! --------------------------------------------------------------------------------- ! + + ! --------------------------------------------------------------------------------- ! ! DIAGNOSE THE PBL DEPTH ! ! this is needed for aerosol code ! - ! --------------------------------------------------------------------------------- ! + ! --------------------------------------------------------------------------------- ! do i=1,ncol do k=1,pver !use local exner since state%exner is not a proper exner @@ -4198,7 +4172,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & thv(i,k) = th(i,k)*(1.0_r8+zvir*state1%q(i,k,ixq) - state1%q(i,k,ixcldliq)) enddo enddo - + ! diagnose surface friction and obukhov length (inputs to diagnose PBL depth) rrho(1:ncol) = (rga)*(state1%pdel(1:ncol,pver)/dz_g(1:ncol,pver)) call calc_ustar( ncol, state1%t(1:ncol,pver), state1%pmid(1:ncol,pver), cam_in%wsx(1:ncol), cam_in%wsy(1:ncol), & @@ -4207,10 +4181,10 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call calc_obklen( ncol, th(1:ncol,pver), thv(1:ncol,pver), cam_in%cflx(1:ncol,1), cam_in%shf(1:ncol), & rrho(1:ncol), ustar2(1:ncol), kinheat(1:ncol), kinwat(1:ncol), kbfs(1:ncol), & obklen(1:ncol)) - + dummy2(:) = 0._r8 dummy3(:) = 0._r8 - + where (kbfs(:ncol) == -0.0_r8) kbfs(:ncol) = 0.0_r8 ! Compute PBL depth according to Holtslag-Boville Scheme @@ -4220,14 +4194,14 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & ! Output the PBL depth call outfld('PBLH', pblh, pcols, lchnk) - + ! Assign the first pver levels of cloud_frac back to cld cld(:,1:pver) = cloud_frac(:,1:pver) - ! --------------------------------------------------------------------------------- ! + ! --------------------------------------------------------------------------------- ! ! END CLOUD FRACTION DIAGNOSIS, begin to store variables back into buffer ! - ! --------------------------------------------------------------------------------- ! - + ! --------------------------------------------------------------------------------- ! + ! Output calls of variables goes here call outfld( 'RELVAR', relvar, pcols, lchnk ) call outfld( 'RHO_CLUBB', rho(:,1:pver), pcols, lchnk ) @@ -4271,7 +4245,7 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & call outfld( 'CLUBB_GRID_SIZE', grid_dx, pcols, lchnk ) call outfld( 'QSATFAC', qsatfac, pcols, lchnk) - + ! --------------------------------------------------------------- ! ! Writing state variables after EDMF scheme for detailed analysis ! ! --------------------------------------------------------------- ! @@ -4300,44 +4274,44 @@ subroutine clubb_tend_cam( state, ptend_all, pbuf, hdtime, & end if ! Output CLUBB history here - if (l_stats) then - + if (l_stats) then + do j=1,stats_zt(1)%num_output_fields - + temp1 = trim(stats_zt(1)%file%grid_avg_var(j)%name) sub = temp1 if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len) - + call outfld(trim(sub), out_zt(:,:,j), pcols, lchnk ) enddo - + do j=1,stats_zm(1)%num_output_fields - + temp1 = trim(stats_zm(1)%file%grid_avg_var(j)%name) sub = temp1 if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len) - + call outfld(trim(sub),out_zm(:,:,j), pcols, lchnk) enddo - if (l_output_rad_files) then + if (l_output_rad_files) then do j=1,stats_rad_zt(1)%num_output_fields call outfld(trim(stats_rad_zt(1)%file%grid_avg_var(j)%name), out_radzt(:,:,j), pcols, lchnk) enddo - + do j=1,stats_rad_zm(1)%num_output_fields call outfld(trim(stats_rad_zm(1)%file%grid_avg_var(j)%name), out_radzm(:,:,j), pcols, lchnk) enddo endif - + do j=1,stats_sfc(1)%num_output_fields call outfld(trim(stats_sfc(1)%file%grid_avg_var(j)%name), out_sfc(:,:,j), pcols, lchnk) enddo - + endif - + call t_stopf("clubb_tend_cam") - + return #endif end subroutine clubb_tend_cam @@ -4371,7 +4345,7 @@ subroutine clubb_emissions_cam (state, cam_in, ptend) ! --------------- ! ! Local Variables ! ! --------------- ! - integer :: m, ncol + integer :: m, ncol logical :: lq(pcnst) ! ----------------------- ! @@ -4395,7 +4369,7 @@ subroutine clubb_emissions_cam (state, cam_in, ptend) endif end do - end subroutine clubb_emissions_cam + end subroutine clubb_emissions_cam ! =============================================================================== ! ! ! @@ -4403,12 +4377,12 @@ end subroutine clubb_emissions_cam ! Saturation adjustment for ice ! Add ice mass if supersaturated -subroutine ice_macro_tend(naai,t,p,qv,qi,ni,xxls,deltat,stend,qvtend,qitend,nitend,vlen) +subroutine ice_macro_tend(naai,t,p,qv,qi,ni,xxls,deltat,stend,qvtend,qitend,nitend,vlen) use wv_sat_methods, only: wv_sat_qsat_ice integer, intent(in) :: vlen - real(r8), dimension(vlen), intent(in) :: naai !Activated number of ice nuclei + real(r8), dimension(vlen), intent(in) :: naai !Activated number of ice nuclei real(r8), dimension(vlen), intent(in) :: t !temperature (k) real(r8), dimension(vlen), intent(in) :: p !pressure (pa) real(r8), dimension(vlen), intent(in) :: qv !water vapor mixing ratio @@ -4416,11 +4390,11 @@ subroutine ice_macro_tend(naai,t,p,qv,qi,ni,xxls,deltat,stend,qvtend,qitend,nite real(r8), dimension(vlen), intent(in) :: ni !ice number concentration real(r8), intent(in) :: xxls !latent heat of freezing real(r8), intent(in) :: deltat !timestep - real(r8), dimension(vlen), intent(out) :: stend ! 'temperature' tendency + real(r8), dimension(vlen), intent(out) :: stend ! 'temperature' tendency real(r8), dimension(vlen), intent(out) :: qvtend !vapor tendency real(r8), dimension(vlen), intent(out) :: qitend !ice mass tendency - real(r8), dimension(vlen), intent(out) :: nitend !ice number tendency - + real(r8), dimension(vlen), intent(out) :: nitend !ice number tendency + real(r8) :: ESI(vlen) real(r8) :: QSI(vlen) integer :: i @@ -4443,7 +4417,7 @@ subroutine ice_macro_tend(naai,t,p,qv,qi,ni,xxls,deltat,stend,qvtend,qitend,nite qitend(i) = (qv(i)-QSI(i))/deltat qvtend(i) = 0._r8 - qitend(i) stend(i) = qitend(i) * xxls ! moist static energy tend...[J/kg/s] ! - + ! if ice exists (more than 1 L-1) and there is condensation, do not add to number (= growth), else, add 10um ice if (ni(i) < 1.e3_r8 .and. (qi(i)+qitend(i)*deltat) > 1.e-18_r8) then nitend(i) = nitend(i) + 3._r8 * qitend(i)/(4._r8*3.14_r8* 10.e-6_r8**3*997._r8) @@ -4477,7 +4451,7 @@ end subroutine ice_macro_tend ! Code writen March, 1999 by Bjorn Stevens ! -real(r8) function diag_ustar( z, bflx, wnd, z0 ) +real(r8) function diag_ustar( z, bflx, wnd, z0 ) use shr_const_mod, only : shr_const_karman, shr_const_pi, shr_const_g @@ -4546,59 +4520,59 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Description: Initializes the statistics saving functionality of ! the CLUBB model. This is for purpose of CAM-CLUBB interface. Here ! the traditional stats_init of CLUBB is not called, as it is not compatible - ! with CAM output. - + ! with CAM output. + !----------------------------------------------------------------------- use clubb_api_module, only: & - ztscr01, & - ztscr02, & - ztscr03, & - ztscr04, & - ztscr05, & - ztscr06, & - ztscr07, & - ztscr08, & - ztscr09, & - ztscr10, & - ztscr11, & - ztscr12, & - ztscr13, & - ztscr14, & - ztscr15, & - ztscr16, & - ztscr17, & - ztscr18, & - ztscr19, & - ztscr20, & + ztscr01, & + ztscr02, & + ztscr03, & + ztscr04, & + ztscr05, & + ztscr06, & + ztscr07, & + ztscr08, & + ztscr09, & + ztscr10, & + ztscr11, & + ztscr12, & + ztscr13, & + ztscr14, & + ztscr15, & + ztscr16, & + ztscr17, & + ztscr18, & + ztscr19, & + ztscr20, & ztscr21 use clubb_api_module, only: & - zmscr01, & - zmscr02, & - zmscr03, & - zmscr04, & - zmscr05, & - zmscr06, & - zmscr07, & - zmscr08, & - zmscr09, & - zmscr10, & - zmscr11, & - zmscr12, & - zmscr13, & - zmscr14, & + zmscr01, & + zmscr02, & + zmscr03, & + zmscr04, & + zmscr05, & + zmscr06, & + zmscr07, & + zmscr08, & + zmscr09, & + zmscr10, & + zmscr11, & + zmscr12, & + zmscr13, & + zmscr14, & zmscr15, & zmscr16, & zmscr17, & l_stats, & - l_output_rad_files, & - stats_tsamp, & - stats_tout, & - l_stats_samp, & - l_stats_last, & - l_netcdf, & + l_output_rad_files, & + stats_tsamp, & + stats_tout, & + l_stats_samp, & + l_stats_last, & + l_netcdf, & l_grads use clubb_api_module, only: time_precision, & ! @@ -4620,16 +4594,16 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & logical, intent(in) :: l_stats_in ! Stats on? T/F - real(kind=time_precision), intent(in) :: & + real(kind=time_precision), intent(in) :: & stats_tsamp_in, & ! Sampling interval [s] stats_tout_in ! Output interval [s] integer, intent(in) :: nnzp ! Grid points in the vertical [count] - integer, intent(in) :: nnrad_zt ! Grid points in the radiation grid [count] + integer, intent(in) :: nnrad_zt ! Grid points in the radiation grid [count] integer, intent(in) :: nnrad_zm ! Grid points in the radiation grid [count] real(kind=time_precision), intent(in) :: delt ! Timestep (dtmain in CLUBB) [s] - + ! Output Variables type (stats), intent(out) :: stats_zt, & ! stats_zt grid stats_zm, & ! stats_zm grid @@ -4650,11 +4624,11 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & character(len=var_length), dimension(nvarmax_rad_zm) :: clubb_vars_rad_zm ! Variables on the radiation levels character(len=var_length), dimension(nvarmax_sfc) :: clubb_vars_sfc ! Variables at the model surface - namelist /clubb_stats_nl/ & - clubb_vars_zt, & + namelist /clubb_stats_nl/ & + clubb_vars_zt, & clubb_vars_zm, & clubb_vars_rad_zt, & - clubb_vars_rad_zm, & + clubb_vars_rad_zm, & clubb_vars_sfc ! Local Variables @@ -4672,7 +4646,7 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Set stats_variables variables with inputs from calling subroutine l_stats = l_stats_in - + stats_tsamp = stats_tsamp_in stats_tout = stats_tout_in @@ -4690,7 +4664,7 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & clubb_vars_rad_zm = '' clubb_vars_sfc = '' - ! Read variables to compute from the namelist + ! Read variables to compute from the namelist if (masterproc) then iunit= getunit() open(unit=iunit,file="atm_in",status='old') @@ -4737,8 +4711,8 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Initialize zt (mass points) i = 1 - do while ( ichar(clubb_vars_zt(i)(1:1)) /= 0 .and. & - len_trim(clubb_vars_zt(i)) /= 0 .and. & + do while ( ichar(clubb_vars_zt(i)(1:1)) /= 0 .and. & + len_trim(clubb_vars_zt(i)) /= 0 .and. & i <= nvarmax_zt ) i = i + 1 enddo @@ -4822,8 +4796,8 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Initialize zm (momentum points) i = 1 - do while ( ichar(clubb_vars_zm(i)(1:1)) /= 0 .and. & - len_trim(clubb_vars_zm(i)) /= 0 .and. & + do while ( ichar(clubb_vars_zm(i)(1:1)) /= 0 .and. & + len_trim(clubb_vars_zm(i)) /= 0 .and. & i <= nvarmax_zm ) i = i + 1 end do @@ -4897,10 +4871,10 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Initialize rad_zt (radiation points) if (l_output_rad_files) then - + i = 1 - do while ( ichar(clubb_vars_rad_zt(i)(1:1)) /= 0 .and. & - len_trim(clubb_vars_rad_zt(i)) /= 0 .and. & + do while ( ichar(clubb_vars_rad_zt(i)(1:1)) /= 0 .and. & + len_trim(clubb_vars_rad_zt(i)) /= 0 .and. & i <= nvarmax_rad_zt ) i = i + 1 end do @@ -4933,10 +4907,10 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & stats_rad_zt ) ! Initialize rad_zm (radiation points) - + i = 1 - do while ( ichar(clubb_vars_rad_zm(i)(1:1)) /= 0 .and. & - len_trim(clubb_vars_rad_zm(i)) /= 0 .and. & + do while ( ichar(clubb_vars_rad_zm(i)(1:1)) /= 0 .and. & + len_trim(clubb_vars_rad_zm(i)) /= 0 .and. & i <= nvarmax_rad_zm ) i = i + 1 end do @@ -4964,7 +4938,7 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & allocate( stats_rad_zm%file%grid_avg_var( stats_rad_zm%num_output_fields ) ) allocate( stats_rad_zm%file%z( stats_rad_zm%kk ) ) - + call stats_init_rad_zm_api( clubb_vars_rad_zm, l_error, & stats_rad_zm ) end if ! l_output_rad_files @@ -4973,8 +4947,8 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Initialize sfc (surface point) i = 1 - do while ( ichar(clubb_vars_sfc(i)(1:1)) /= 0 .and. & - len_trim(clubb_vars_sfc(i)) /= 0 .and. & + do while ( ichar(clubb_vars_sfc(i)(1:1)) /= 0 .and. & + len_trim(clubb_vars_sfc(i)) /= 0 .and. & i <= nvarmax_sfc ) i = i + 1 end do @@ -5016,58 +4990,58 @@ subroutine stats_init_clubb( l_stats_in, stats_tsamp_in, stats_tout_in, & ! Now call add fields if (first_call) then - + do i = 1, stats_zt%num_output_fields - + temp1 = trim(stats_zt%file%grid_avg_var(i)%name) sub = temp1 if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len) - + call addfld(trim(sub),(/ 'ilev' /),& 'A',trim(stats_zt%file%grid_avg_var(i)%units),trim(stats_zt%file%grid_avg_var(i)%description)) enddo - + do i = 1, stats_zm%num_output_fields - + temp1 = trim(stats_zm%file%grid_avg_var(i)%name) sub = temp1 if (len(temp1) > max_fieldname_len) sub = temp1(1:max_fieldname_len) - + call addfld(trim(sub),(/ 'ilev' /),& 'A',trim(stats_zm%file%grid_avg_var(i)%units),trim(stats_zm%file%grid_avg_var(i)%description)) enddo - if (l_output_rad_files) then + if (l_output_rad_files) then do i = 1, stats_rad_zt%num_output_fields call addfld(trim(stats_rad_zt%file%grid_avg_var(i)%name),(/ 'ilev' /),& 'A',trim(stats_rad_zt%file%grid_avg_var(i)%units),trim(stats_rad_zt%file%grid_avg_var(i)%description)) enddo - + do i = 1, stats_rad_zm%num_output_fields call addfld(trim(stats_rad_zm%file%grid_avg_var(i)%name),(/ 'ilev' /),& 'A',trim(stats_rad_zm%file%grid_avg_var(i)%units),trim(stats_rad_zm%file%grid_avg_var(i)%description)) enddo endif - + do i = 1, stats_sfc%num_output_fields call addfld(trim(stats_sfc%file%grid_avg_var(i)%name),horiz_only,& 'A',trim(stats_sfc%file%grid_avg_var(i)%units),trim(stats_sfc%file%grid_avg_var(i)%description)) enddo - + end if return - end subroutine stats_init_clubb - + end subroutine stats_init_clubb + #endif ! =============================================================================== ! ! ! ! =============================================================================== ! -#ifdef CLUBB_SGS +#ifdef CLUBB_SGS subroutine stats_end_timestep_clubb(thecol, stats_zt, stats_zm, stats_rad_zt, stats_rad_zm, stats_sfc, & out_zt, out_zm, out_radzt, out_radzm, out_sfc) !----------------------------------------------------------------------- @@ -5082,8 +5056,8 @@ subroutine stats_end_timestep_clubb(thecol, stats_zt, stats_zm, stats_rad_zt, st use clubb_api_module, only: & fstderr, & ! Constant(s) - l_stats_last, & - stats_tsamp, & + l_stats_last, & + stats_tsamp, & stats_tout, & l_output_rad_files, & clubb_at_least_debug_level_api ! Procedure(s) @@ -5093,14 +5067,14 @@ subroutine stats_end_timestep_clubb(thecol, stats_zt, stats_zm, stats_rad_zt, st implicit none integer :: thecol - + ! Input Variables type (stats), intent(inout) :: stats_zt, & ! stats_zt grid stats_zm, & ! stats_zm grid stats_rad_zt, & ! stats_rad_zt grid stats_rad_zm, & ! stats_rad_zm grid stats_sfc ! stats_sfc - + ! Inout variables real(r8), intent(inout) :: out_zt(:,:,:) ! (pcols,pverp,stats_zt%num_output_fields) real(r8), intent(inout) :: out_zm(:,:,:) ! (pcols,pverp,stats_zt%num_output_fields) @@ -5131,36 +5105,36 @@ subroutine stats_end_timestep_clubb(thecol, stats_zt, stats_zm, stats_rad_zt, st end if call stats_avg( stats_sfc%kk, stats_sfc%num_output_fields, stats_sfc%accum_field_values, stats_sfc%accum_num_samples ) - ! Here we are not outputting the data, rather reading the stats into + ! Here we are not outputting the data, rather reading the stats into ! arrays which are conformable to CAM output. Also, the data is "flipped" - ! in the vertical level to be the same as CAM output. + ! in the vertical level to be the same as CAM output. do i = 1, stats_zt%num_output_fields - do k = 1, stats_zt%kk + do k = 1, stats_zt%kk out_zt(thecol,pverp-k+1,i) = stats_zt%accum_field_values(1,1,k,i) if(is_nan(out_zt(thecol,k,i))) out_zt(thecol,k,i) = 0.0_r8 - enddo + enddo enddo do i = 1, stats_zm%num_output_fields - do k = 1, stats_zt%kk + do k = 1, stats_zt%kk out_zm(thecol,pverp-k+1,i) = stats_zm%accum_field_values(1,1,k,i) if(is_nan(out_zm(thecol,k,i))) out_zm(thecol,k,i) = 0.0_r8 - enddo + enddo enddo - if (l_output_rad_files) then + if (l_output_rad_files) then do i = 1, stats_rad_zt%num_output_fields - do k = 1, stats_rad_zt%kk + do k = 1, stats_rad_zt%kk out_radzt(thecol,pverp-k+1,i) = stats_rad_zt%accum_field_values(1,1,k,i) if(is_nan(out_radzt(thecol,k,i))) out_radzt(thecol,k,i) = 0.0_r8 - enddo + enddo enddo - + do i = 1, stats_rad_zm%num_output_fields - do k = 1, stats_rad_zm%kk + do k = 1, stats_rad_zm%kk out_radzm(thecol,pverp-k+1,i) = stats_rad_zm%accum_field_values(1,1,k,i) if(is_nan(out_radzm(thecol,k,i))) out_radzm(thecol,k,i) = 0.0_r8 - enddo + enddo enddo ! Fill in values above the CLUBB top. @@ -5170,9 +5144,9 @@ subroutine stats_end_timestep_clubb(thecol, stats_zt, stats_zm, stats_rad_zt, st out_radzm(thecol,:top_lev-1,:) = 0.0_r8 endif ! l_output_rad_files - + do i = 1, stats_sfc%num_output_fields - out_sfc(thecol,1,i) = stats_sfc%accum_field_values(1,1,1,i) + out_sfc(thecol,1,i) = stats_sfc%accum_field_values(1,1,1,i) if(is_nan(out_sfc(thecol,1,i))) out_sfc(thecol,1,i) = 0.0_r8 enddo @@ -5193,14 +5167,14 @@ subroutine stats_end_timestep_clubb(thecol, stats_zt, stats_zm, stats_rad_zt, st return end subroutine stats_end_timestep_clubb -#endif - +#endif + ! =============================================================================== ! ! ! ! =============================================================================== ! #ifdef CLUBB_SGS - + !----------------------------------------------------------------------- subroutine stats_zero( kk, num_output_fields, x, n, l_in_update ) @@ -5234,14 +5208,14 @@ subroutine stats_zero( kk, num_output_fields, x, n, l_in_update ) return end subroutine stats_zero - + #endif ! =============================================================================== ! ! ! ! =============================================================================== ! - + #ifdef CLUBB_SGS !----------------------------------------------------------------------- subroutine stats_avg( kk, num_output_fields, x, n ) @@ -5289,7 +5263,7 @@ subroutine grid_size(state, grid_dx, grid_dy) use shr_const_mod, only: shr_const_pi use physics_types, only: physics_state - + type(physics_state), intent(in) :: state real(r8), intent(out) :: grid_dx(state%ncol), grid_dy(state%ncol) ! CAM grid [m] @@ -5304,17 +5278,17 @@ subroutine grid_size(state, grid_dx, grid_dy) do i=1,state%ncol column_area = get_area_p(state%lchnk,i) degree = sqrt(column_area)*(180._r8/shr_const_pi) - + ! Now find meters per degree latitude ! Below equation finds distance between two points on an ellipsoid, derived from expansion - ! taking into account ellipsoid using World Geodetic System (WGS84) reference + ! taking into account ellipsoid using World Geodetic System (WGS84) reference mpdeglat = earth_ellipsoid1 - earth_ellipsoid2 * cos(2._r8*state%lat(i)) + earth_ellipsoid3 * cos(4._r8*state%lat(i)) grid_dx(i) = mpdeglat * degree grid_dy(i) = grid_dx(i) ! Assume these are the same - enddo + enddo - end subroutine grid_size + end subroutine grid_size #endif - + end module clubb_intr diff --git a/src/physics/cam/convect_shallow.F90 b/src/physics/cam/convect_shallow.F90 index 0fa7e3b83d..4f0844fd24 100644 --- a/src/physics/cam/convect_shallow.F90 +++ b/src/physics/cam/convect_shallow.F90 @@ -13,25 +13,25 @@ module convect_shallow use shr_kind_mod, only : r8=>shr_kind_r8 use physconst, only : cpair, zvir use ppgrid, only : pver, pcols, pverp - use zm_conv, only : zm_conv_evap + use zm_conv_evap_mod, only : zm_conv_evap_run use cam_history, only : outfld, addfld, horiz_only use cam_logfile, only : iulog use phys_control, only : phys_getopts implicit none - private + private save public :: & convect_shallow_register, & ! Register fields in physics buffer convect_shallow_init, & ! Initialize shallow module convect_shallow_tend, & ! Return tendencies - convect_shallow_use_shfrc ! + convect_shallow_use_shfrc ! ! The following namelist variable controls which shallow convection package is used. ! 'Hack' = Hack shallow convection (default) ! 'UW' = UW shallow convection by Sungsu Park and Christopher S. Bretherton - ! 'UNICON' = General Convection Model by Sungsu Park + ! 'UNICON' = General Convection Model by Sungsu Park ! 'off' = No shallow convection character(len=16) :: shallow_scheme ! Default set in phys_control.F90, use namelist to change @@ -40,16 +40,16 @@ module convect_shallow logical :: history_budget ! Output tendencies and state variables for CAM4 T, qv, ql, qi integer :: history_budget_histfile_num ! output history file number for budget fields - ! Physics buffer indices - integer :: icwmrsh_idx = 0 - integer :: rprdsh_idx = 0 - integer :: rprdtot_idx = 0 - integer :: cldtop_idx = 0 - integer :: cldbot_idx = 0 - integer :: cush_idx = 0 + ! Physics buffer indices + integer :: icwmrsh_idx = 0 + integer :: rprdsh_idx = 0 + integer :: rprdtot_idx = 0 + integer :: cldtop_idx = 0 + integer :: cldbot_idx = 0 + integer :: cush_idx = 0 integer :: nevapr_shcu_idx = 0 - integer :: shfrc_idx = 0 - integer :: cld_idx = 0 + integer :: shfrc_idx = 0 + integer :: cld_idx = 0 integer :: concld_idx = 0 integer :: rprddp_idx = 0 integer :: tke_idx = 0 @@ -84,9 +84,9 @@ subroutine convect_shallow_register use physics_buffer, only : pbuf_add_field, dtype_r8, dyn_time_lvls use phys_control, only: use_gw_convect_sh use unicon_cam, only: unicon_cam_register - + call phys_getopts( shallow_scheme_out = shallow_scheme, microp_scheme_out = microp_scheme) - + ! SPCAM registers its own fields if (shallow_scheme == 'SPCAM') return @@ -95,7 +95,7 @@ subroutine convect_shallow_register call pbuf_add_field('RPRDTOT', 'physpkg' ,dtype_r8,(/pcols,pver/), rprdtot_idx ) call pbuf_add_field('CLDTOP', 'physpkg' ,dtype_r8,(/pcols,1/), cldtop_idx ) call pbuf_add_field('CLDBOT', 'physpkg' ,dtype_r8,(/pcols,1/), cldbot_idx ) - call pbuf_add_field('cush', 'global' ,dtype_r8,(/pcols,dyn_time_lvls/), cush_idx ) + call pbuf_add_field('cush', 'global' ,dtype_r8,(/pcols,dyn_time_lvls/), cush_idx ) call pbuf_add_field('NEVAPR_SHCU','physpkg' ,dtype_r8,(/pcols,pver/), nevapr_shcu_idx ) call pbuf_add_field('PREC_SH', 'physpkg' ,dtype_r8,(/pcols/), prec_sh_idx ) call pbuf_add_field('SNOW_SH', 'physpkg' ,dtype_r8,(/pcols/), snow_sh_idx ) @@ -110,16 +110,16 @@ subroutine convect_shallow_register endif ! shallow interface gbm flux_convective_cloud_rain+snow (kg/m2/s) - call pbuf_add_field('SH_FLXPRC','physpkg',dtype_r8,(/pcols,pverp/),sh_flxprc_idx) + call pbuf_add_field('SH_FLXPRC','physpkg',dtype_r8,(/pcols,pverp/),sh_flxprc_idx) ! shallow interface gbm flux_convective_cloud_snow (kg/m2/s) - call pbuf_add_field('SH_FLXSNW','physpkg',dtype_r8,(/pcols,pverp/),sh_flxsnw_idx) + call pbuf_add_field('SH_FLXSNW','physpkg',dtype_r8,(/pcols,pverp/),sh_flxsnw_idx) ! shallow gbm cloud liquid water (kg/kg) - call pbuf_add_field('SH_CLDLIQ','physpkg',dtype_r8,(/pcols,pver/),sh_cldliq_idx) + call pbuf_add_field('SH_CLDLIQ','physpkg',dtype_r8,(/pcols,pver/),sh_cldliq_idx) ! shallow gbm cloud ice water (kg/kg) - call pbuf_add_field('SH_CLDICE','physpkg',dtype_r8,(/pcols,pver/),sh_cldice_idx) + call pbuf_add_field('SH_CLDICE','physpkg',dtype_r8,(/pcols,pver/),sh_cldice_idx) ! If gravity waves from shallow convection are on, output this field. if (use_gw_convect_sh) then @@ -154,7 +154,7 @@ subroutine convect_shallow_init(pref_edge, pbuf2d) use spmd_utils, only : masterproc use cam_abortutils, only : endrun use phys_control, only : cam_physpkg_is - + use physics_buffer, only : pbuf_get_index, physics_buffer_desc, pbuf_set_field real(r8), intent(in) :: pref_edge(plevp) ! Reference pressures at interfaces @@ -163,7 +163,7 @@ subroutine convect_shallow_init(pref_edge, pbuf2d) integer limcnv ! Top interface level limit for convection integer k character(len=16) :: eddy_scheme - + ! SPCAM does its own convection if (shallow_scheme == 'SPCAM') return @@ -221,7 +221,7 @@ subroutine convect_shallow_init(pref_edge, pbuf2d) call addfld( 'PCLDBOT', horiz_only, 'A', '1', 'Pressure of cloud base' ) call addfld( 'FREQSH', horiz_only, 'A', 'fraction', 'Fractional occurance of shallow convection' ) - + call addfld( 'HKFLXPRC', (/ 'ilev' /), 'A', 'kg/m2/s', 'Flux of precipitation from HK convection' ) call addfld( 'HKFLXSNW', (/ 'ilev' /), 'A', 'kg/m2/s', 'Flux of snow from HK convection' ) call addfld( 'HKNTPRPD', (/ 'lev' /), 'A', 'kg/kg/s', 'Net precipitation production from HK convection' ) @@ -286,7 +286,7 @@ subroutine convect_shallow_init(pref_edge, pbuf2d) if( masterproc ) then write(iulog,*) 'MFINTI: Convection will be capped at intfc ', limcnv, ' which is ', pref_edge(limcnv), ' pascals' end if - + call mfinti( rair, cpair, gravit, latvap, rhoh2o, limcnv) ! Get args from inti.F90 case('UW') ! Park and Bretherton shallow convection scheme @@ -346,7 +346,7 @@ end function convect_shallow_use_shfrc !=============================================================================== ! subroutine convect_shallow_tend( ztodt , cmfmc , & - qc , qc2 , rliq , rliq2 , & + qc , qc2 , rliq , rliq2 , & state , ptend_all, pbuf, cam_in) use physics_buffer, only : physics_buffer_desc, pbuf_get_field, pbuf_set_field, pbuf_old_tim_idx @@ -357,7 +357,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & use physics_types, only : physics_ptend_dealloc use physics_types, only : physics_ptend_sum use camsrfexch, only : cam_in_t - + use constituents, only : pcnst, cnst_get_ind, cnst_get_type_byind use hk_conv, only : cmfmca use uwshcu, only : compute_uwshcu_inv @@ -365,7 +365,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & use time_manager, only : get_nstep use wv_saturation, only : qsat - use physconst, only : latice, latvap, rhoh2o + use physconst, only : latice, latvap, rhoh2o, tmelt, gravit use spmd_utils, only : iam implicit none @@ -381,7 +381,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & real(r8), intent(out) :: rliq2(pcols) ! Vertically-integrated reserved cloud condensate [ m/s ] real(r8), intent(out) :: qc2(pcols,pver) ! Same as qc but only from shallow convection scheme - + real(r8), intent(inout) :: cmfmc(pcols,pverp) ! Moist deep + shallow convection cloud mass flux [ kg/s/m2 ] real(r8), intent(inout) :: qc(pcols,pver) ! dq/dt due to export of cloud water into environment by shallow @@ -392,7 +392,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & ! --------------- ! - ! Local Variables ! + ! Local Variables ! ! --------------- ! integer :: i, k, m integer :: n, x @@ -432,7 +432,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & real(r8) :: pcnb(pcols) ! Bottom pressure level of shallow + deep convective activity real(r8) :: cmfsl(pcols,pverp ) ! Convective flux of liquid water static energy real(r8) :: cmflq(pcols,pverp ) ! Convective flux of total water in energy unit - + real(r8) :: ftem_preCu(pcols,pver) ! Saturation vapor pressure after shallow Cu convection real(r8) :: tem2(pcols,pver) ! Saturation specific humidity and RH real(r8) :: t_preCu(pcols,pver) ! Temperature after shallow Cu convection @@ -442,7 +442,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & real(r8) :: icwmr_UW(pcols,pver) ! In-cloud Cumulus LWC [ kg/m2 ] real(r8) :: icimr_UW(pcols,pver) ! In-cloud Cumulus IWC [ kg/m2 ] real(r8) :: ptend_tracer(pcols,pver,pcnst) ! Tendencies of tracers - real(r8) :: sum1, sum2, sum3, pdelx + real(r8) :: sum1, sum2, sum3, pdelx real(r8) :: landfracdum(pcols) real(r8), dimension(pcols,pver) :: sl, qt, slv @@ -476,14 +476,14 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & type(unicon_out_t) :: unicon_out ! ----------------------- ! - ! Main Computation Begins ! + ! Main Computation Begins ! ! ----------------------- ! zero = 0._r8 nstep = get_nstep() lchnk = state%lchnk ncol = state%ncol - + call physics_state_copy( state, state1 ) ! Copy state to local state1. ! Associate pointers with physics buffer fields @@ -553,7 +553,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & snow = 0._r8 case('Hack') ! Hack scheme - + lq(:) = .TRUE. call physics_ptend_init( ptend_loc, state%psetcols, 'cmfmca', ls=.true., lq=lq ) ! Initialize local ptend type @@ -565,7 +565,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & state%rpdel , state%zm , tpert , qpert , state%phis , & pblh , state%t , state%q , ptend_loc%s , ptend_loc%q , & cmfmc2 , rprdsh , cmfsl , cmflq , precc , & - qc2 , cnt2 , cnb2 , icwmr , rliq2 , & + qc2 , cnt2 , cnb2 , icwmr , rliq2 , & state%pmiddry, state%pdeldry, state%rpdeldry ) case('UW') ! UW shallow convection scheme @@ -576,7 +576,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & ! Initialize local ptend type lq(:) = .TRUE. - call physics_ptend_init( ptend_loc, state%psetcols, 'UWSHCU', ls=.true., lu=.true., lv=.true., lq=lq ) + call physics_ptend_init( ptend_loc, state%psetcols, 'UWSHCU', ls=.true., lu=.true., lv=.true., lq=lq ) call pbuf_get_field(pbuf, cush_idx, cush ,(/1,itim_old/), (/pcols,1/)) call pbuf_get_field(pbuf, tke_idx, tke) @@ -587,7 +587,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & call pbuf_get_field(pbuf, sh_e_ed_ratio_idx, sh_e_ed_ratio) call compute_uwshcu_inv( pcols , pver , ncol , pcnst , ztodt , & - state%pint, state%zi, state%pmid , state%zm , state%pdel , & + state%pint, state%zi, state%pmid , state%zm , state%pdel , & state%u , state%v , state%q(:,:,1) , state%q(:,:,ixcldliq), state%q(:,:,ixcldice), & state%t , state%s , state%q(:,:,:) , & tke , cld , concld , pblh , cush , & @@ -606,14 +606,14 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & ! In addition, define 'icwmr' which includes both liquid and ice. ! ! --------------------------------------------------------------------- ! - icwmr(:ncol,:) = iccmr_UW(:ncol,:) + icwmr(:ncol,:) = iccmr_UW(:ncol,:) rprdsh(:ncol,:) = rprdsh(:ncol,:) + cmfdqs(:ncol,:) do m = 4, pcnst ptend_loc%q(:ncol,:pver,m) = ptend_tracer(:ncol,:pver,m) enddo ! Conservation check - + ! do i = 1, ncol ! do m = 1, pcnst ! sum1 = 0._r8 @@ -626,8 +626,8 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & ! pdelx = state%pdeldry(i,k) ! endif ! sum1 = sum1 + state%q(i,k,m)*pdelx - ! sum2 = sum2 +(state%q(i,k,m)+ptend_loc%q(i,k,m)*ztodt)*pdelx - ! sum3 = sum3 + ptend_loc%q(i,k,m)*pdelx + ! sum2 = sum2 +(state%q(i,k,m)+ptend_loc%q(i,k,m)*ztodt)*pdelx + ! sum3 = sum3 + ptend_loc%q(i,k,m)*pdelx ! enddo ! if( m .gt. 3 .and. abs(sum1) .gt. 1.e-13_r8 .and. abs(sum2-sum1)/sum1 .gt. 1.e-12_r8 ) then !! if( m .gt. 3 .and. abs(sum3) .gt. 1.e-13_r8 ) then @@ -671,7 +671,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & end select - ! --------------------------------------------------------! + ! --------------------------------------------------------! ! Calculate fractional occurance of shallow convection ! ! --------------------------------------------------------! @@ -696,7 +696,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & ! -------------------------------------------------------------- ! ! 'cnt2' & 'cnb2' are from shallow, 'cnt' & 'cnb' are from deep ! - ! 'cnt2' & 'cnb2' are the interface indices of cloud top & base: ! + ! 'cnt2' & 'cnb2' are the interface indices of cloud top & base: ! ! cnt2 = float(kpen) ! ! cnb2 = float(krel - 1) ! ! Note that indices decreases with height. ! @@ -707,28 +707,28 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & if( cnb2(i) > cnb(i)) cnb(i) = cnb2(i) if( cnb(i) == 1._r8 ) cnb(i) = cnt(i) pcnt(i) = state%pmid(i,int(cnt(i))) - pcnb(i) = state%pmid(i,int(cnb(i))) + pcnb(i) = state%pmid(i,int(cnb(i))) end do - + ! ----------------------------------------------- ! ! This quantity was previously known as CMFDQR. ! ! Now CMFDQR is the shallow rain production only. ! ! ----------------------------------------------- ! - + call pbuf_set_field(pbuf, rprdtot_idx, rprdsh(:ncol,:pver) + rprddp(:ncol,:pver), start=(/1,1/), kount=(/ncol,pver/)) - - ! ----------------------------------------------------------------------- ! + + ! ----------------------------------------------------------------------- ! ! Add shallow reserved cloud condensate to deep reserved cloud condensate ! ! qc [ kg/kg/s] , rliq [ m/s ] ! ! ----------------------------------------------------------------------- ! qc(:ncol,:pver) = qc(:ncol,:pver) + qc2(:ncol,:pver) - rliq(:ncol) = rliq(:ncol) + rliq2(:ncol) + rliq(:ncol) = rliq(:ncol) + rliq2(:ncol) ! ---------------------------------------------------------------------------- ! ! Output new partition of cloud condensate variables, as well as precipitation ! - ! ---------------------------------------------------------------------------- ! + ! ---------------------------------------------------------------------------- ! if( microp_scheme == 'MG' ) then call cnst_get_ind( 'NUMLIQ', ixnumliq ) @@ -752,12 +752,12 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & call outfld( 'CLDTOP' , cnt , pcols , lchnk ) call outfld( 'CLDBOT' , cnb , pcols , lchnk ) call outfld( 'PCLDTOP', pcnt , pcols , lchnk ) - call outfld( 'PCLDBOT', pcnb , pcols , lchnk ) + call outfld( 'PCLDBOT', pcnb , pcols , lchnk ) call outfld( 'FREQSH' , freqsh , pcols , lchnk ) if( shallow_scheme .eq. 'UW' ) then call outfld( 'CBMF' , cbmf , pcols , lchnk ) - call outfld( 'UWFLXPRC', flxprec , pcols , lchnk ) + call outfld( 'UWFLXPRC', flxprec , pcols , lchnk ) call outfld( 'UWFLXSNW' , flxsnow , pcols , lchnk ) endif @@ -795,8 +795,8 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & call outfld( 't_pre_Cu ', state1%t , pcols, lchnk ) call outfld( 'rh_pre_Cu ', ftem_preCu , pcols, lchnk ) - ! ----------------------------------------------- ! - ! Update physics state type state1 with ptend_loc ! + ! ----------------------------------------------- ! + ! Update physics state type state1 with ptend_loc ! ! ----------------------------------------------- ! call physics_update( state1, ptend_loc, ztodt ) @@ -827,8 +827,8 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & call outfld( 't_aft_Cu ', state1%t , pcols, lchnk ) call outfld( 'rh_aft_Cu ', ftem , pcols, lchnk ) - tten(:ncol,:) = ( state1%t(:ncol,:pver) - t_preCu(:ncol,:) ) / ztodt - rhten(:ncol,:) = ( ftem(:ncol,:) - ftem_preCu(:ncol,:) ) / ztodt + tten(:ncol,:) = ( state1%t(:ncol,:pver) - t_preCu(:ncol,:) ) / ztodt + rhten(:ncol,:) = ( ftem(:ncol,:) - ftem_preCu(:ncol,:) ) / ztodt call outfld( 'tten_Cu ', tten , pcols, lchnk ) call outfld( 'rhten_Cu ', rhten , pcols, lchnk ) @@ -837,7 +837,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & ! ------------------------------------------------------------------------ ! ! UW-Shallow Cumulus scheme includes ! ! evaporation physics inside in it. So when 'shallow_scheme = UW', we must ! - ! NOT perform below 'zm_conv_evap'. ! + ! NOT perform below 'zm_conv_evap_run'. ! ! ------------------------------------------------------------------------ ! if( shallow_scheme .eq. 'Hack' ) then @@ -855,7 +855,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & lq(1) = .TRUE. lq(2:) = .FALSE. - call physics_ptend_init(ptend_loc, state1%psetcols, 'zm_conv_evap', ls=.true., lq=lq) + call physics_ptend_init(ptend_loc, state1%psetcols, 'zm_conv_evap_run', ls=.true., lq=lq) call pbuf_get_field(pbuf, sh_flxprc_idx, flxprec ) call pbuf_get_field(pbuf, sh_flxsnw_idx, flxsnow ) @@ -866,17 +866,18 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & sh_cldliq(:ncol,:) = 0._r8 sh_cldice(:ncol,:) = 0._r8 - call zm_conv_evap( state1%ncol, state1%lchnk, & + call zm_conv_evap_run( state1%ncol, pcols, pver, pverp, & + gravit, latice, latvap, tmelt, & state1%t, state1%pmid, state1%pdel, state1%q(:pcols,:pver,1), & landfracdum, & - ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, & + ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, & ptend_loc%q(:pcols,:pver,1), & rprdsh, cld, ztodt, & precc, snow, ntprprd, ntsnprd , flxprec, flxsnow ) - ! ------------------------------------------ ! - ! record history variables from zm_conv_evap ! - ! ------------------------------------------ ! + ! ---------------------------------------------- ! + ! record history variables from zm_conv_evap_run ! + ! ---------------------------------------------- ! evapcsh(:ncol,:pver) = ptend_loc%q(:ncol,:pver,1) @@ -894,7 +895,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & call outfld( 'HKNTSNPD' , ntsnprd , pcols, lchnk ) call outfld( 'HKEIHEAT' , ptend_loc%s , pcols, lchnk ) - ! ---------------------------------------------------------------- ! + ! ---------------------------------------------------------------- ! ! Add tendency from this process to tend from other processes here ! ! ---------------------------------------------------------------- ! diff --git a/src/physics/cam/macrop_driver.F90 b/src/physics/cam/macrop_driver.F90 index 3e7c276b3c..092848dd0e 100644 --- a/src/physics/cam/macrop_driver.F90 +++ b/src/physics/cam/macrop_driver.F90 @@ -6,7 +6,7 @@ module macrop_driver ! Provides the CAM interface to the prognostic cloud macrophysics ! ! Author: Andrew Gettelman, Cheryl Craig October 2010 - ! Origin: modified from stratiform.F90 elements + ! Origin: modified from stratiform.F90 elements ! (Boville 2002, Coleman 2004, Park 2009, Kay 2010) !------------------------------------------------------------------------------------------------------- @@ -22,7 +22,6 @@ module macrop_driver use perf_mod, only: t_startf, t_stopf use cam_logfile, only: iulog use cam_abortutils, only: endrun - use zm_conv_intr, only: zmconv_microp implicit none private @@ -42,12 +41,12 @@ module macrop_driver ! Private Module Parameters ! ! ------------------------- ! - ! 'cu_det_st' : If .true. (.false.), detrain cumulus liquid condensate into the pre-existing liquid stratus - ! (environment) without (with) macrophysical evaporation. If there is no pre-esisting stratus, + ! 'cu_det_st' : If .true. (.false.), detrain cumulus liquid condensate into the pre-existing liquid stratus + ! (environment) without (with) macrophysical evaporation. If there is no pre-esisting stratus, ! evaporate cumulus liquid condensate. This option only influences the treatment of cumulus ! liquid condensate, not cumulus ice condensate. - logical, parameter :: cu_det_st = .false. + logical, parameter :: cu_det_st = .false. ! Parameters used for selecting generalized critical RH for liquid and ice stratus integer :: rhminl_opt = 0 @@ -79,11 +78,11 @@ module macrop_driver ast_idx, &! stratiform cloud fraction index in physics buffer aist_idx, &! ice stratiform cloud fraction index in physics buffer alst_idx, &! liquid stratiform cloud fraction index in physics buffer - qist_idx, &! ice stratiform in-cloud IWC - qlst_idx, &! liquid stratiform in-cloud LWC + qist_idx, &! ice stratiform in-cloud IWC + qlst_idx, &! liquid stratiform in-cloud LWC concld_idx, &! concld index in physics buffer - fice_idx, & - cmeliq_idx, & + fice_idx, & + cmeliq_idx, & shfrc_idx integer :: & @@ -98,8 +97,8 @@ module macrop_driver qtl_flx_idx = -1, &! overbar(w'qtl' where qtl = qv + ql) from the PBL scheme qti_flx_idx = -1, &! overbar(w'qti' where qti = qv + qi) from the PBL scheme cmfr_det_idx = -1, &! detrained convective mass flux from UNICON - qlr_det_idx = -1, &! detrained convective ql from UNICON - qir_det_idx = -1, &! detrained convective qi from UNICON + qlr_det_idx = -1, &! detrained convective ql from UNICON + qir_det_idx = -1, &! detrained convective qi from UNICON cmfmc_sh_idx = -1 contains @@ -166,7 +165,7 @@ subroutine macrop_driver_register ! ! !---------------------------------------------------------------------- ! - + use physics_buffer, only : pbuf_add_field, dtype_r8, dyn_time_lvls !----------------------------------------------------------------------- @@ -203,12 +202,12 @@ subroutine macrop_driver_init(pbuf2d) !-------------------------------------------- ! ! ! ! Initialize the cloud water parameterization ! - ! ! + ! ! !-------------------------------------------- ! use physics_buffer, only : pbuf_get_index use cam_history, only: addfld, add_default use convect_shallow, only: convect_shallow_use_shfrc - + type(physics_buffer_desc), pointer :: pbuf2d(:,:) logical :: history_aerosol ! Output the MAM aerosol tendencies @@ -234,7 +233,7 @@ subroutine macrop_driver_init(pbuf2d) if( convect_shallow_use_shfrc() ) then use_shfrc = .true. shfrc_idx = pbuf_get_index('shfrc') - else + else use_shfrc = .false. endif @@ -269,7 +268,7 @@ subroutine macrop_driver_init(pbuf2d) call addfld ('CLDST', (/ 'lev' /), 'A', 'fraction', 'Stratus cloud fraction' ) call addfld ('CONCLD', (/ 'lev' /), 'A', 'fraction', 'Convective cloud cover' ) - + call addfld ('CLR_LIQ', (/ 'lev' /), 'A', 'fraction', 'Clear sky fraction for liquid stratus' ) call addfld ('CLR_ICE', (/ 'lev' /), 'A', 'fraction', 'Clear sky fraction for ice stratus' ) @@ -299,7 +298,7 @@ subroutine macrop_driver_init(pbuf2d) call add_default ('MACPDQ ', history_budget_histfile_num, ' ') call add_default ('MACPDLIQ ', history_budget_histfile_num, ' ') call add_default ('MACPDICE ', history_budget_histfile_num, ' ') - + call add_default ('CLDVAPADJ', history_budget_histfile_num, ' ') call add_default ('CLDLIQLIM', history_budget_histfile_num, ' ') call add_default ('CLDLIQDET', history_budget_histfile_num, ' ') @@ -328,14 +327,6 @@ subroutine macrop_driver_init(pbuf2d) CC_qlst_idx = pbuf_get_index('CC_qlst') cmfmc_sh_idx = pbuf_get_index('CMFMC_SH') - if (zmconv_microp) then - dlfzm_idx = pbuf_get_index('DLFZM') - difzm_idx = pbuf_get_index('DIFZM') - dnlfzm_idx = pbuf_get_index('DNLFZM') - dnifzm_idx = pbuf_get_index('DNIFZM') - end if - - if (rhminl_opt > 0 .or. rhmini_opt > 0) then cmfr_det_idx = pbuf_get_index('cmfr_det', istat) if (istat < 0) call endrun(subname//': macrop option requires cmfr_det in pbuf') @@ -361,7 +352,7 @@ subroutine macrop_driver_init(pbuf2d) end if end if - ! Init pbuf fields. Note that the fields CLD, CONCLD, QCWAT, LCWAT, + ! Init pbuf fields. Note that the fields CLD, CONCLD, QCWAT, LCWAT, ! ICCWAT, and TCWAT are initialized in phys_inidat. if (is_first_step()) then call pbuf_set_field(pbuf2d, ast_idx, 0._r8) @@ -392,13 +383,13 @@ subroutine macrop_driver_tend( & pbuf, & det_s, det_ice) - !-------------------------------------------------------- ! - ! ! + !-------------------------------------------------------- ! + ! ! ! Purpose: ! ! ! ! Interface to detrain, cloud fraction and ! ! cloud macrophysics subroutines ! - ! ! + ! ! ! Author: A. Gettelman, C. Craig, Oct 2010 ! ! based on stratiform_tend by D.B. Coleman 4/2010 ! ! ! @@ -438,7 +429,7 @@ subroutine macrop_driver_tend( & real(r8), intent(in) :: zdu(pcols,pver) ! Detrainment rate from deep convection - ! These two variables are needed for energy check + ! These two variables are needed for energy check real(r8), intent(out) :: det_s(pcols) ! Integral of detrained static energy from ice real(r8), intent(out) :: det_ice(pcols) ! Integral of detrained ice for energy check @@ -525,13 +516,13 @@ subroutine macrop_driver_tend( & real(r8) ltend(pcols,pver) ! Cloud liquid water tendencies real(r8) fice(pcols,pver) ! Fractional ice content within cloud real(r8) fsnow(pcols,pver) ! Fractional snow production - real(r8) homoo(pcols,pver) - real(r8) qcreso(pcols,pver) - real(r8) prcio(pcols,pver) - real(r8) praio(pcols,pver) + real(r8) homoo(pcols,pver) + real(r8) qcreso(pcols,pver) + real(r8) prcio(pcols,pver) + real(r8) praio(pcols,pver) real(r8) qireso(pcols,pver) real(r8) ftem(pcols,pver) - real(r8) pracso (pcols,pver) + real(r8) pracso (pcols,pver) real(r8) dpdlfliq(pcols,pver) real(r8) dpdlfice(pcols,pver) real(r8) shdlfliq(pcols,pver) @@ -575,11 +566,11 @@ subroutine macrop_driver_tend( & real(r8) qi_inout(pcols,pver) real(r8) concld_old(pcols,pver) - ! Note that below 'clr_old' is defined using 'alst_old' not 'ast_old' for full consistency with the - ! liquid condensation process which is using 'alst' not 'ast'. + ! Note that below 'clr_old' is defined using 'alst_old' not 'ast_old' for full consistency with the + ! liquid condensation process which is using 'alst' not 'ast'. ! For microconsistency use 'concld_old', since 'alst_old' was computed using 'concld_old'. ! Since convective updraft fractional area is small, it does not matter whether 'concld' or 'concld_old' is used. - ! Note also that 'clri_old' is defined using 'ast_old' since current microphysics is operating on 'ast_old' + ! Note also that 'clri_old' is defined using 'ast_old' since current microphysics is operating on 'ast_old' real(r8) clrw_old(pcols,pver) ! (1 - concld_old - alst_old) real(r8) clri_old(pcols,pver) ! (1 - concld_old - ast_old) @@ -669,7 +660,7 @@ subroutine macrop_driver_tend( & dlf_ni(:,:) = 0._r8 ! ------------------------------------- ! - ! From here, process computation begins ! + ! From here, process computation begins ! ! ------------------------------------- ! ! ----------------------------------------------------------------------------- ! @@ -689,23 +680,16 @@ subroutine macrop_driver_tend( & ! If convection scheme can handle this internally, this step is not necssary. ! (2) Assuming a certain effective droplet radius, computes number concentration ! of detrained convective cloud liquid and ice. - ! (3) If 'cu_det_st = .true' ('false'), detrain convective cloud 'liquid' into + ! (3) If 'cu_det_st = .true' ('false'), detrain convective cloud 'liquid' into ! the pre-existing 'liquid' stratus ( mean environment ). The former does ! not involve any macrophysical evaporation while the latter does. This is - ! a kind of 'targetted' deposition. Then, force in-stratus LWC to be bounded + ! a kind of 'targetted' deposition. Then, force in-stratus LWC to be bounded ! by qcst_min and qcst_max in mmacro_pcond. - ! (4) In contrast to liquid, convective ice is detrained into the environment + ! (4) In contrast to liquid, convective ice is detrained into the environment ! and involved in the sublimation. Similar bounds as liquid stratus are imposed. ! This is the key procesure generating upper-level cirrus clouds. ! The unit of dlf : [ kg/kg/s ] - if (zmconv_microp) then - call pbuf_get_field(pbuf, dlfzm_idx, dlfzm) - call pbuf_get_field(pbuf, difzm_idx, difzm) - call pbuf_get_field(pbuf, dnlfzm_idx, dnlfzm) - call pbuf_get_field(pbuf, dnifzm_idx, dnifzm) - end if - det_s(:) = 0._r8 det_ice(:) = 0._r8 @@ -729,57 +713,43 @@ subroutine macrop_driver_tend( & ! If detrainment was done elsewhere, still update the variables used for output ! assuming that the temperature split between liquid and ice is the same as assumed ! here. - if (zmconv_microp) then - ptend_loc%q(i,k,ixcldliq) = dlfzm(i,k) + dlf2(i,k) * ( 1._r8 - dum1 ) - ptend_loc%q(i,k,ixcldice) = difzm(i,k) + dlf2(i,k) * dum1 - - ptend_loc%q(i,k,ixnumliq) = dnlfzm(i,k) + 3._r8 * ( dlf2(i,k) * ( 1._r8 - dum1 ) ) & - / (4._r8*3.14_r8*10.e-6_r8**3*997._r8) ! Shallow Convection - ptend_loc%q(i,k,ixnumice) = dnifzm(i,k) + 3._r8 * ( dlf2(i,k) * dum1 ) & - / (4._r8*3.14_r8*50.e-6_r8**3*500._r8) ! Shallow Convection - ptend_loc%s(i,k) = dlf2(i,k) * dum1 * latice - - else - if (do_detrain) then + if (do_detrain) then ptend_loc%q(i,k,ixcldliq) = dlf(i,k) * ( 1._r8 - dum1 ) ptend_loc%q(i,k,ixcldice) = dlf(i,k) * dum1 ! dum2 = dlf(i,k) * ( 1._r8 - dum1 ) ptend_loc%q(i,k,ixnumliq) = 3._r8 * ( max(0._r8, ( dlf(i,k) - dlf2(i,k) )) * ( 1._r8 - dum1 ) ) / & (4._r8*3.14_r8* 8.e-6_r8**3*997._r8) + & ! Deep Convection 3._r8 * ( dlf2(i,k) * ( 1._r8 - dum1 ) ) / & - (4._r8*3.14_r8*10.e-6_r8**3*997._r8) ! Shallow Convection + (4._r8*3.14_r8*10.e-6_r8**3*997._r8) ! Shallow Convection ! dum2 = dlf(i,k) * dum1 ptend_loc%q(i,k,ixnumice) = 3._r8 * ( max(0._r8, ( dlf(i,k) - dlf2(i,k) )) * dum1 ) / & (4._r8*3.14_r8*25.e-6_r8**3*500._r8) + & ! Deep Convection 3._r8 * ( dlf2(i,k) * dum1 ) / & (4._r8*3.14_r8*50.e-6_r8**3*500._r8) ! Shallow Convection ptend_loc%s(i,k) = dlf(i,k) * dum1 * latice - else + else ptend_loc%q(i,k,ixcldliq) = 0._r8 ptend_loc%q(i,k,ixcldice) = 0._r8 ptend_loc%q(i,k,ixnumliq) = 0._r8 ptend_loc%q(i,k,ixnumice) = 0._r8 ptend_loc%s(i,k) = 0._r8 - end if - - end if ! Only rliq is saved from deep convection, which is the reserved liquid. We need to keep ! track of the integrals of ice and static energy that is effected from conversion to ice ! so that the energy checker doesn't complain. det_s(i) = det_s(i) + ptend_loc%s(i,k)*state_loc%pdel(i,k)/gravit - det_ice(i) = det_ice(i) - ptend_loc%q(i,k,ixcldice)*state_loc%pdel(i,k)/gravit + det_ice(i) = det_ice(i) - ptend_loc%q(i,k,ixcldice)*state_loc%pdel(i,k)/gravit ! Targetted detrainment of convective liquid water either directly into the - ! existing liquid stratus or into the environment. + ! existing liquid stratus or into the environment. if( cu_det_st ) then dlf_T(i,k) = ptend_loc%s(i,k)/cpair dlf_qv(i,k) = 0._r8 dlf_ql(i,k) = ptend_loc%q(i,k,ixcldliq) dlf_qi(i,k) = ptend_loc%q(i,k,ixcldice) dlf_nl(i,k) = ptend_loc%q(i,k,ixnumliq) - dlf_ni(i,k) = ptend_loc%q(i,k,ixnumice) + dlf_ni(i,k) = ptend_loc%q(i,k,ixnumice) ptend_loc%q(i,k,ixcldliq) = 0._r8 ptend_loc%q(i,k,ixcldice) = 0._r8 ptend_loc%q(i,k,ixnumliq) = 0._r8 @@ -792,15 +762,9 @@ subroutine macrop_driver_tend( & dpdlft (i,k) = 0._r8 shdlft (i,k) = 0._r8 else - if (zmconv_microp) then - dpdlfliq(i,k) = dlfzm(i,k) - dpdlfice(i,k) = difzm(i,k) - dpdlft (i,k) = 0._r8 - else - dpdlfliq(i,k) = ( dlf(i,k) - dlf2(i,k) ) * ( 1._r8 - dum1 ) - dpdlfice(i,k) = ( dlf(i,k) - dlf2(i,k) ) * ( dum1 ) - dpdlft (i,k) = ( dlf(i,k) - dlf2(i,k) ) * dum1 * latice/cpair - end if + dpdlfliq(i,k) = ( dlf(i,k) - dlf2(i,k) ) * ( 1._r8 - dum1 ) + dpdlfice(i,k) = ( dlf(i,k) - dlf2(i,k) ) * ( dum1 ) + dpdlft (i,k) = ( dlf(i,k) - dlf2(i,k) ) * dum1 * latice/cpair shdlfliq(i,k) = dlf2(i,k) * ( 1._r8 - dum1 ) shdlfice(i,k) = dlf2(i,k) * ( dum1 ) @@ -833,7 +797,7 @@ subroutine macrop_driver_tend( & ! -------------------------------------- ! ! ----------------------------------------------------------------------------- ! - ! Treatment of cloud fraction in CAM4 and CAM5 differs ! + ! Treatment of cloud fraction in CAM4 and CAM5 differs ! ! (1) CAM4 ! ! . Cumulus AMT = Deep Cumulus AMT ( empirical fcn of mass flux ) + ! ! Shallow Cumulus AMT ( empirical fcn of mass flux ) ! @@ -846,7 +810,7 @@ subroutine macrop_driver_tend( & ! . Stratus AMT = fcn of environmental-mean RH ( no Stability Stratus ) ! ! . Cumulus and Stratus are non-overlapped with higher priority on Cumulus ! ! . Cumulus ( both Deep and Shallow ) has its own LWC and IWC. ! - ! ----------------------------------------------------------------------------- ! + ! ----------------------------------------------------------------------------- ! concld_old(:ncol,top_lev:pver) = concld(:ncol,top_lev:pver) @@ -862,22 +826,22 @@ subroutine macrop_driver_tend( & clri_old(:ncol,:top_lev-1) = 0._r8 do k = top_lev, pver do i = 1, ncol - clrw_old(i,k) = max( 0._r8, min( 1._r8, 1._r8 - concld(i,k) - alst(i,k) ) ) - clri_old(i,k) = max( 0._r8, min( 1._r8, 1._r8 - concld(i,k) - ast(i,k) ) ) + clrw_old(i,k) = max( 0._r8, min( 1._r8, 1._r8 - concld(i,k) - alst(i,k) ) ) + clri_old(i,k) = max( 0._r8, min( 1._r8, 1._r8 - concld(i,k) - ast(i,k) ) ) end do end do if( use_shfrc ) then call pbuf_get_field(pbuf, shfrc_idx, shfrc ) - else + else allocate(shfrc(pcols,pver)) shfrc(:,:) = 0._r8 endif - ! CAM5 only uses 'concld' output from the below subroutine. + ! CAM5 only uses 'concld' output from the below subroutine. ! Stratus ('ast' = max(alst,aist)) and total cloud fraction ('cld = ast + concld') - ! will be computed using this updated 'concld' in the stratiform macrophysics - ! scheme (mmacro_pcond) later below. + ! will be computed using this updated 'concld' in the stratiform macrophysics + ! scheme (mmacro_pcond) later below. call t_startf("cldfrc") @@ -901,7 +865,7 @@ subroutine macrop_driver_tend( & rdtime = 1._r8/dtime ! Define fractional amount of stratus condensate and precipitation in ice phase. - ! This uses a ramp ( -30 ~ -10 for fice, -5 ~ 0 for fsnow ). + ! This uses a ramp ( -30 ~ -10 for fice, -5 ~ 0 for fsnow ). ! The ramp within convective cloud may be different call cldfrc_fice( ncol, state_loc%t, fice, fsnow ) @@ -918,7 +882,7 @@ subroutine macrop_driver_tend( & ! Initialize local physics_ptend object again call physics_ptend_init(ptend_loc, state%psetcols, 'macro_park', & - ls=.true., lq=lq ) + ls=.true., lq=lq ) ! --------------------------------- ! ! Liquid Macrop_Driver Macrophysics ! @@ -932,9 +896,9 @@ subroutine macrop_driver_tend( & nc(:ncol,top_lev:pver) = state_loc%q(:ncol,top_lev:pver,ixnumliq) ni(:ncol,top_lev:pver) = state_loc%q(:ncol,top_lev:pver,ixnumice) - ! In CAM5, 'microphysical forcing' ( CC_... ) and 'the other advective forcings' ( ttend, ... ) + ! In CAM5, 'microphysical forcing' ( CC_... ) and 'the other advective forcings' ( ttend, ... ) ! are separately provided into the prognostic microp_driver macrophysics scheme. This is an - ! attempt to resolve in-cloud and out-cloud forcings. + ! attempt to resolve in-cloud and out-cloud forcings. if( get_nstep() .le. 1 ) then tcwat(:ncol,top_lev:pver) = state_loc%t(:ncol,top_lev:pver) @@ -958,7 +922,7 @@ subroutine macrop_driver_tend( & CC_qlst(:ncol,:) = 0._r8 else ttend(:ncol,top_lev:pver) = ( state_loc%t(:ncol,top_lev:pver) - tcwat(:ncol,top_lev:pver)) * rdtime & - - CC_T(:ncol,top_lev:pver) + - CC_T(:ncol,top_lev:pver) qtend(:ncol,top_lev:pver) = ( state_loc%q(:ncol,top_lev:pver,1) - qcwat(:ncol,top_lev:pver)) * rdtime & - CC_qv(:ncol,top_lev:pver) ltend(:ncol,top_lev:pver) = ( qc(:ncol,top_lev:pver) + qi(:ncol,top_lev:pver) - lcwat(:ncol,top_lev:pver) ) * rdtime & @@ -972,7 +936,7 @@ subroutine macrop_driver_tend( & endif lmitend(:ncol,top_lev:pver) = ltend(:ncol,top_lev:pver) - itend(:ncol,top_lev:pver) - t_inout(:ncol,top_lev:pver) = tcwat(:ncol,top_lev:pver) + t_inout(:ncol,top_lev:pver) = tcwat(:ncol,top_lev:pver) qv_inout(:ncol,top_lev:pver) = qcwat(:ncol,top_lev:pver) ql_inout(:ncol,top_lev:pver) = lcwat(:ncol,top_lev:pver) - iccwat(:ncol,top_lev:pver) qi_inout(:ncol,top_lev:pver) = iccwat(:ncol,top_lev:pver) @@ -982,20 +946,20 @@ subroutine macrop_driver_tend( & ! Liquid Microp_Driver Macrophysics. ! The main roles of this subroutines are ! (1) compute net condensation rate of stratiform liquid ( cmeliq ) - ! (2) compute liquid stratus and ice stratus fractions. + ! (2) compute liquid stratus and ice stratus fractions. ! Note 'ttend...' are advective tendencies except microphysical process while - ! 'CC...' are microphysical tendencies. + ! 'CC...' are microphysical tendencies. call mmacro_pcond( lchnk, ncol, dtime, state_loc%pmid, state_loc%pdel, & - t_inout, qv_inout, ql_inout, qi_inout, nl_inout, ni_inout, & + t_inout, qv_inout, ql_inout, qi_inout, nl_inout, ni_inout, & ttend, qtend, lmitend, itend, nltend, nitend, & - CC_T, CC_qv, CC_ql, CC_qi, CC_nl, CC_ni, CC_qlst, & + CC_T, CC_qv, CC_ql, CC_qi, CC_nl, CC_ni, CC_qlst, & dlf_T, dlf_qv, dlf_ql, dlf_qi, dlf_nl, dlf_ni, & concld_old, concld, clrw_old, clri_old, landfrac, snowh, & tke, qtl_flx, qti_flx, cmfr_det, qlr_det, qir_det, & tlat, qvlat, qcten, qiten, ncten, niten, & cmeliq, qvadj, qladj, qiadj, qllim, qilim, & - cld, alst, aist, qlst, qist, do_cldice ) + cld, alst, aist, qlst, qist, do_cldice ) ! Copy of concld/fice to put in physics buffer ! Below are used only for convective cloud. @@ -1021,20 +985,20 @@ subroutine macrop_driver_tend( & ! Check to make sure that the macrophysics code is respecting the flags that control ! whether cldwat should be prognosing cloud ice and cloud liquid or not. - if ((.not. do_cldice) .and. (qiten(i,k) /= 0.0_r8)) then + if ((.not. do_cldice) .and. (qiten(i,k) /= 0.0_r8)) then call endrun("macrop_driver:ERROR - "// & "Cldwat is configured not to prognose cloud ice, but mmacro_pcond has ice mass tendencies.") end if - if ((.not. do_cldice) .and. (niten(i,k) /= 0.0_r8)) then + if ((.not. do_cldice) .and. (niten(i,k) /= 0.0_r8)) then call endrun("macrop_driver:ERROR -"// & " Cldwat is configured not to prognose cloud ice, but mmacro_pcond has ice number tendencies.") end if - if ((.not. do_cldliq) .and. (qcten(i,k) /= 0.0_r8)) then + if ((.not. do_cldliq) .and. (qcten(i,k) /= 0.0_r8)) then call endrun("macrop_driver:ERROR - "// & "Cldwat is configured not to prognose cloud liquid, but mmacro_pcond has liquid mass tendencies.") end if - if ((.not. do_cldliq) .and. (ncten(i,k) /= 0.0_r8)) then + if ((.not. do_cldliq) .and. (ncten(i,k) /= 0.0_r8)) then call endrun("macrop_driver:ERROR - "// & "Cldwat is configured not to prognose cloud liquid, but mmacro_pcond has liquid number tendencies.") end if @@ -1064,7 +1028,7 @@ subroutine macrop_driver_tend( & call outfld( 'ICECLDF ', aist, pcols, lchnk ) call outfld( 'LIQCLDF ', alst, pcols, lchnk ) - call outfld( 'AST', ast, pcols, lchnk ) + call outfld( 'AST', ast, pcols, lchnk ) call outfld( 'CONCLD ', concld, pcols, lchnk ) call outfld( 'CLDST ', cldst, pcols, lchnk ) @@ -1075,7 +1039,7 @@ subroutine macrop_driver_tend( & ! calculations and outfld calls for CLDLIQSTR, CLDICESTR, CLDLIQCON, CLDICECON for CFMIP ! initialize local variables - mr_ccliq = 0._r8 !! not seen by radiation, so setting to 0 + mr_ccliq = 0._r8 !! not seen by radiation, so setting to 0 mr_ccice = 0._r8 !! not seen by radiation, so setting to 0 mr_lsliq = 0._r8 mr_lsice = 0._r8 @@ -1098,7 +1062,7 @@ subroutine macrop_driver_tend( & call outfld( 'CLDICECON ', mr_ccice, pcols, lchnk ) ! ------------------------------------------------- ! - ! Save equilibrium state variables for macrophysics ! + ! Save equilibrium state variables for macrophysics ! ! at the next time step ! ! ------------------------------------------------- ! cldsice = 0._r8 @@ -1125,7 +1089,7 @@ end subroutine macrop_driver_tend ! With CLUBB, we are seeing relative humidity with respect to water ! greater than 1. This should not be happening and is not what the ! microphsyics expects from the macrophysics. As a work around while -! this issue is investigated in CLUBB, this routine will enfornce a +! this issue is investigated in CLUBB, this routine will enfornce a ! maximum RHliq of 1 everywhere in the atmosphere. Any excess water will ! be converted into cloud drops. subroutine liquid_macro_tend(npccn,t,p,qv,qc,nc,xxlv,deltat,stend,qvtend,qctend,nctend,vlen) @@ -1136,7 +1100,7 @@ subroutine liquid_macro_tend(npccn,t,p,qv,qc,nc,xxlv,deltat,stend,qvtend,qctend, use cldfrc2m, only: rhmini_const, rhmaxi_const integer, intent(in) :: vlen - real(r8), dimension(vlen), intent(in) :: npccn !Activated number of cloud condensation nuclei + real(r8), dimension(vlen), intent(in) :: npccn !Activated number of cloud condensation nuclei real(r8), dimension(vlen), intent(in) :: t !temperature (k) real(r8), dimension(vlen), intent(in) :: p !pressure (pa) real(r8), dimension(vlen), intent(in) :: qv !water vapor mixing ratio @@ -1144,18 +1108,18 @@ subroutine liquid_macro_tend(npccn,t,p,qv,qc,nc,xxlv,deltat,stend,qvtend,qctend, real(r8), dimension(vlen), intent(in) :: nc !liquid number concentration real(r8), intent(in) :: xxlv !latent heat of vaporization real(r8), intent(in) :: deltat !timestep - real(r8), dimension(vlen), intent(out) :: stend ! 'temperature' tendency + real(r8), dimension(vlen), intent(out) :: stend ! 'temperature' tendency real(r8), dimension(vlen), intent(out) :: qvtend !vapor tendency real(r8), dimension(vlen), intent(out) :: qctend !liquid mass tendency - real(r8), dimension(vlen), intent(out) :: nctend !liquid number tendency + real(r8), dimension(vlen), intent(out) :: nctend !liquid number tendency real(r8) :: ESL(vlen) real(r8) :: QSL(vlen) - real(r8) :: drop_size_param + real(r8) :: drop_size_param integer :: i drop_size_param = 3._r8/(4._r8*3.14_r8*6.e-6_r8**3*rhow) - + do i = 1, vlen stend(i) = 0._r8 qvtend(i) = 0._r8 @@ -1164,18 +1128,18 @@ subroutine liquid_macro_tend(npccn,t,p,qv,qc,nc,xxlv,deltat,stend,qvtend,qctend, end do ! calculate qsatl from t,p,q - !$acc data copyin(t,p) copyout(ESL,QSL) + !$acc data copyin(t,p) copyout(ESL,QSL) call wv_sat_qsat_water_vect(t, p, ESL, QSL, vlen) !$acc end data do i = 1, vlen ! Don't allow supersaturation with respect to liquid. if (qv(i) > QSL(i)) then - + qctend(i) = (qv(i) - QSL(i)) / deltat qvtend(i) = 0._r8 - qctend(i) stend(i) = qctend(i) * xxlv ! moist static energy tend...[J/kg/s] ! - + ! If drops exists (more than 1 L-1) and there is condensation, ! do not add to number (= growth), otherwise add 6um drops. ! diff --git a/src/physics/cam/zm_conv.F90 b/src/physics/cam/zm_conv.F90 deleted file mode 100644 index 6305f6ba6d..0000000000 --- a/src/physics/cam/zm_conv.F90 +++ /dev/null @@ -1,4825 +0,0 @@ -module zm_conv - -!--------------------------------------------------------------------------------- -! Purpose: -! -! Interface from Zhang-McFarlane convection scheme, includes evaporation of convective -! precip from the ZM scheme -! -! Apr 2006: RBN: Code added to perform a dilute ascent for closure of the CM mass flux -! based on an entraining plume a la Raymond and Blythe (1992) -! -! Author: Byron Boville, from code in tphysbc -! -!--------------------------------------------------------------------------------- - use shr_kind_mod, only: r8 => shr_kind_r8 - use spmd_utils, only: masterproc - use ppgrid, only: pcols, pver, pverp - use cloud_fraction, only: cldfrc_fice - use physconst, only: cpair, epsilo, gravit, latice, latvap, tmelt, rair, & - cpwv, cpliq, rh2o - use cam_abortutils, only: endrun - use cam_logfile, only: iulog - use zm_microphysics, only: zm_mphy, zm_aero_t, zm_conv_t - use cam_history, only: outfld - - implicit none - - save - private ! Make default type private to the module -! -! PUBLIC: interfaces -! - public zm_convi ! ZM schemea - public zm_convr ! ZM schemea - public zm_conv_evap ! evaporation of precip from ZM schemea - public convtran ! convective transport - public momtran ! convective momentum transport - -! -! Private data -! - real(r8) rl ! wg latent heat of vaporization. - real(r8) cpres ! specific heat at constant pressure in j/kg-degk. - real(r8) :: capelmt ! namelist configurable: - ! threshold value for cape for deep convection. - real(r8) :: ke ! Tunable evaporation efficiency set from namelist input zmconv_ke - real(r8) :: ke_lnd - real(r8) :: c0_lnd ! set from namelist input zmconv_c0_lnd - real(r8) :: c0_ocn ! set from namelist input zmconv_c0_ocn - integer :: num_cin ! set from namelist input zmconv_num_cin - ! The number of negative buoyancy regions that are allowed - ! before the convection top and CAPE calculations are completed. - logical :: zm_org - real(r8) tau ! convective time scale - real(r8),parameter :: c1 = 6.112_r8 - real(r8),parameter :: c2 = 17.67_r8 - real(r8),parameter :: c3 = 243.5_r8 - real(r8) :: tfreez - real(r8) :: eps1 - real(r8) :: momcu - real(r8) :: momcd - - logical :: zmconv_microp - - logical :: no_deep_pbl ! default = .false. - ! no_deep_pbl = .true. eliminates deep convection entirely within PBL - - -!moved from moistconvection.F90 - real(r8) :: rgrav ! reciprocal of grav - real(r8) :: rgas ! gas constant for dry air - real(r8) :: grav ! = gravit - real(r8) :: cp ! = cpres = cpair - - integer limcnv ! top interface level limit for convection - - logical :: lparcel_pbl ! Switch to turn on mixing of parcel MSE air, and picking launch level to be the top of the PBL. - - - real(r8) :: tiedke_add ! namelist configurable - real(r8) :: dmpdz_param ! namelist configurable - -contains - - -subroutine zm_convi(limcnv_in, zmconv_c0_lnd, zmconv_c0_ocn, zmconv_ke, zmconv_ke_lnd, & - zmconv_momcu, zmconv_momcd, zmconv_num_cin, zmconv_org, & - zmconv_microp_in, no_deep_pbl_in, zmconv_tiedke_add, & - zmconv_capelmt, zmconv_dmpdz, zmconv_parcel_pbl, zmconv_tau) - - integer, intent(in) :: limcnv_in ! top interface level limit for convection - integer, intent(in) :: zmconv_num_cin ! Number negative buoyancy regions that are allowed - ! before the convection top and CAPE calculations are completed. - real(r8),intent(in) :: zmconv_c0_lnd - real(r8),intent(in) :: zmconv_c0_ocn - real(r8),intent(in) :: zmconv_ke - real(r8),intent(in) :: zmconv_ke_lnd - real(r8),intent(in) :: zmconv_momcu - real(r8),intent(in) :: zmconv_momcd - logical :: zmconv_org - logical, intent(in) :: zmconv_microp_in - logical, intent(in) :: no_deep_pbl_in ! no_deep_pbl = .true. eliminates ZM convection entirely within PBL - real(r8),intent(in) :: zmconv_tiedke_add - real(r8),intent(in) :: zmconv_capelmt - real(r8),intent(in) :: zmconv_dmpdz - logical, intent(in) :: zmconv_parcel_pbl ! Should the parcel properties include PBL mixing? - real(r8),intent(in) :: zmconv_tau - - ! Initialization of ZM constants - limcnv = limcnv_in - tfreez = tmelt - eps1 = epsilo - rl = latvap - cpres = cpair - rgrav = 1.0_r8/gravit - rgas = rair - grav = gravit - cp = cpres - - c0_lnd = zmconv_c0_lnd - c0_ocn = zmconv_c0_ocn - num_cin = zmconv_num_cin - ke = zmconv_ke - ke_lnd = zmconv_ke_lnd - zm_org = zmconv_org - momcu = zmconv_momcu - momcd = zmconv_momcd - - zmconv_microp = zmconv_microp_in - - tiedke_add = zmconv_tiedke_add - capelmt = zmconv_capelmt - dmpdz_param = zmconv_dmpdz - no_deep_pbl = no_deep_pbl_in - lparcel_pbl = zmconv_parcel_pbl - - tau = zmconv_tau - - if ( masterproc ) then - write(iulog,*) 'tuning parameters zm_convi: tau',tau - write(iulog,*) 'tuning parameters zm_convi: c0_lnd',c0_lnd, ', c0_ocn', c0_ocn - write(iulog,*) 'tuning parameters zm_convi: num_cin', num_cin - write(iulog,*) 'tuning parameters zm_convi: ke',ke - write(iulog,*) 'tuning parameters zm_convi: no_deep_pbl',no_deep_pbl - write(iulog,*) 'tuning parameters zm_convi: zm_capelmt', capelmt - write(iulog,*) 'tuning parameters zm_convi: zm_dmpdz', dmpdz_param - write(iulog,*) 'tuning parameters zm_convi: zm_tiedke_add', tiedke_add - write(iulog,*) 'tuning parameters zm_convi: zm_parcel_pbl', lparcel_pbl - endif - - if (masterproc) write(iulog,*)'**** ZM: DILUTE Buoyancy Calculation ****' - -end subroutine zm_convi - - - -subroutine zm_convr(lchnk ,ncol , & - t ,qh ,prec ,jctop ,jcbot , & - pblh ,zm ,geos ,zi ,qtnd , & - heat ,pap ,paph ,dpp , & - delt ,mcon ,cme ,cape , & - tpert ,dlf ,pflx ,zdu ,rprd , & - mu ,md ,du ,eu ,ed , & - dp ,dsubcld ,jt ,maxg ,ideep , & - ql ,rliq ,landfrac, & - org ,orgt ,org2d , & - dif ,dnlf ,dnif ,conv , & - aero , rice) -!----------------------------------------------------------------------- -! -! Purpose: -! Main driver for zhang-mcfarlane convection scheme -! -! Method: -! performs deep convective adjustment based on mass-flux closure -! algorithm. -! -! Author:guang jun zhang, m.lazare, n.mcfarlane. CAM Contact: P. Rasch -! -! This is contributed code not fully standardized by the CAM core group. -! All variables have been typed, where most are identified in comments -! The current procedure will be reimplemented in a subsequent version -! of the CAM where it will include a more straightforward formulation -! and will make use of the standard CAM nomenclature -! -!----------------------------------------------------------------------- - use phys_control, only: cam_physpkg_is - -! -! ************************ index of variables ********************** -! -! wg * alpha array of vertical differencing used (=1. for upstream). -! w * cape convective available potential energy. -! wg * capeg gathered convective available potential energy. -! c * capelmt threshold value for cape for deep convection. -! ic * cpres specific heat at constant pressure in j/kg-degk. -! i * dpp -! ic * delt length of model time-step in seconds. -! wg * dp layer thickness in mbs (between upper/lower interface). -! wg * dqdt mixing ratio tendency at gathered points. -! wg * dsdt dry static energy ("temp") tendency at gathered points. -! wg * dudt u-wind tendency at gathered points. -! wg * dvdt v-wind tendency at gathered points. -! wg * dsubcld layer thickness in mbs between lcl and maxi. -! ic * grav acceleration due to gravity in m/sec2. -! wg * du detrainment in updraft. specified in mid-layer -! wg * ed entrainment in downdraft. -! wg * eu entrainment in updraft. -! wg * hmn moist static energy. -! wg * hsat saturated moist static energy. -! w * ideep holds position of gathered points vs longitude index. -! ic * pver number of model levels. -! wg * j0 detrainment initiation level index. -! wg * jd downdraft initiation level index. -! ic * jlatpr gaussian latitude index for printing grids (if needed). -! wg * jt top level index of deep cumulus convection. -! w * lcl base level index of deep cumulus convection. -! wg * lclg gathered values of lcl. -! w * lel index of highest theoretical convective plume. -! wg * lelg gathered values of lel. -! w * lon index of onset level for deep convection. -! w * maxi index of level with largest moist static energy. -! wg * maxg gathered values of maxi. -! wg * mb cloud base mass flux. -! wg * mc net upward (scaled by mb) cloud mass flux. -! wg * md downward cloud mass flux (positive up). -! wg * mu upward cloud mass flux (positive up). specified -! at interface -! ic * msg number of missing moisture levels at the top of model. -! w * p grid slice of ambient mid-layer pressure in mbs. -! i * pblt row of pbl top indices. -! w * pcpdh scaled surface pressure. -! w * pf grid slice of ambient interface pressure in mbs. -! wg * pg grid slice of gathered values of p. -! w * q grid slice of mixing ratio. -! wg * qd grid slice of mixing ratio in downdraft. -! wg * qg grid slice of gathered values of q. -! i/o * qh grid slice of specific humidity. -! w * qh0 grid slice of initial specific humidity. -! wg * qhat grid slice of upper interface mixing ratio. -! wg * ql grid slice of cloud liquid water. -! wg * qs grid slice of saturation mixing ratio. -! w * qstp grid slice of parcel temp. saturation mixing ratio. -! wg * qstpg grid slice of gathered values of qstp. -! wg * qu grid slice of mixing ratio in updraft. -! ic * rgas dry air gas constant. -! wg * rl latent heat of vaporization. -! w * s grid slice of scaled dry static energy (t+gz/cp). -! wg * sd grid slice of dry static energy in downdraft. -! wg * sg grid slice of gathered values of s. -! wg * shat grid slice of upper interface dry static energy. -! wg * su grid slice of dry static energy in updraft. -! i/o * t -! o * jctop row of top-of-deep-convection indices passed out. -! O * jcbot row of base of cloud indices passed out. -! wg * tg grid slice of gathered values of t. -! w * tl row of parcel temperature at lcl. -! wg * tlg grid slice of gathered values of tl. -! w * tp grid slice of parcel temperatures. -! wg * tpg grid slice of gathered values of tp. -! i/o * u grid slice of u-wind (real). -! wg * ug grid slice of gathered values of u. -! i/o * utg grid slice of u-wind tendency (real). -! i/o * v grid slice of v-wind (real). -! w * va work array re-used by called subroutines. -! wg * vg grid slice of gathered values of v. -! i/o * vtg grid slice of v-wind tendency (real). -! i * w grid slice of diagnosed large-scale vertical velocity. -! w * z grid slice of ambient mid-layer height in metres. -! w * zf grid slice of ambient interface height in metres. -! wg * zfg grid slice of gathered values of zf. -! wg * zg grid slice of gathered values of z. -! -!----------------------------------------------------------------------- -! -! multi-level i/o fields: -! i => input arrays. -! i/o => input/output arrays. -! w => work arrays. -! wg => work arrays operating only on gathered points. -! ic => input data constants. -! c => data constants pertaining to subroutine itself. -! -! input arguments -! - integer, intent(in) :: lchnk ! chunk identifier - integer, intent(in) :: ncol ! number of atmospheric columns - - real(r8), intent(in) :: t(pcols,pver) ! grid slice of temperature at mid-layer. - real(r8), intent(in) :: qh(pcols,pver) ! grid slice of specific humidity. - real(r8), intent(in) :: pap(pcols,pver) - real(r8), intent(in) :: paph(pcols,pver+1) - real(r8), intent(in) :: dpp(pcols,pver) ! local sigma half-level thickness (i.e. dshj). - real(r8), intent(in) :: zm(pcols,pver) - real(r8), intent(in) :: geos(pcols) - real(r8), intent(in) :: zi(pcols,pver+1) - real(r8), intent(in) :: pblh(pcols) - real(r8), intent(in) :: tpert(pcols) - real(r8), intent(in) :: landfrac(pcols) ! RBN Landfrac - - type(zm_conv_t), intent(inout) :: conv - type(zm_aero_t), intent(inout) :: aero ! aerosol object. intent(inout) because the - ! gathered arrays are set here - ! before passing object - ! to microphysics -! output arguments -! - real(r8), intent(out) :: qtnd(pcols,pver) ! specific humidity tendency (kg/kg/s) - real(r8), intent(out) :: heat(pcols,pver) ! heating rate (dry static energy tendency, W/kg) - real(r8), intent(out) :: mcon(pcols,pverp) - real(r8), intent(out) :: dlf(pcols,pver) ! scattrd version of the detraining cld h2o tend - real(r8), intent(out) :: pflx(pcols,pverp) ! scattered precip flux at each level - real(r8), intent(out) :: cme(pcols,pver) - real(r8), intent(out) :: cape(pcols) ! w convective available potential energy. - real(r8), intent(out) :: zdu(pcols,pver) - real(r8), intent(out) :: rprd(pcols,pver) ! rain production rate - real(r8), intent(out) :: dif(pcols,pver) ! detrained convective cloud ice mixing ratio. - real(r8), intent(out) :: dnlf(pcols,pver) ! detrained convective cloud water num concen. - real(r8), intent(out) :: dnif(pcols,pver) ! detrained convective cloud ice num concen. - -! move these vars from local storage to output so that convective -! transports can be done in outside of conv_cam. - real(r8), intent(out) :: mu(pcols,pver) - real(r8), intent(out) :: eu(pcols,pver) - real(r8), intent(out) :: du(pcols,pver) - real(r8), intent(out) :: md(pcols,pver) - real(r8), intent(out) :: ed(pcols,pver) - real(r8), intent(out) :: dp(pcols,pver) ! wg layer thickness in mbs (between upper/lower interface). - real(r8), intent(out) :: dsubcld(pcols) ! wg layer thickness in mbs between lcl and maxi. - real(r8), intent(out) :: jctop(pcols) ! o row of top-of-deep-convection indices passed out. - real(r8), intent(out) :: jcbot(pcols) ! o row of base of cloud indices passed out. - real(r8), intent(out) :: prec(pcols) - real(r8), intent(out) :: rliq(pcols) ! reserved liquid (not yet in cldliq) for energy integrals - real(r8), intent(out) :: rice(pcols) ! reserved ice (not yet in cldce) for energy integrals - - integer, intent(out) :: ideep(pcols) ! column indices of gathered points - - type(zm_conv_t) :: loc_conv - - real(r8), pointer :: org(:,:) ! Only used if zm_org is true - real(r8), pointer :: orgt(:,:) ! Only used if zm_org is true - real(r8), pointer :: org2d(:,:) ! Only used if zm_org is true - - real(r8) zs(pcols) - real(r8) dlg(pcols,pver) ! gathrd version of the detraining cld h2o tend - real(r8) pflxg(pcols,pverp) ! gather precip flux at each level - real(r8) cug(pcols,pver) ! gathered condensation rate - - real(r8) evpg(pcols,pver) ! gathered evap rate of rain in downdraft - real(r8) orgavg(pcols) - real(r8) dptot(pcols) - real(r8) mumax(pcols) - integer jt(pcols) ! wg top level index of deep cumulus convection. - integer maxg(pcols) ! wg gathered values of maxi. - integer lengath -! diagnostic field used by chem/wetdep codes - real(r8) ql(pcols,pver) ! wg grid slice of cloud liquid water. -! - real(r8) pblt(pcols) ! i row of pbl top indices. - - - - -! -!----------------------------------------------------------------------- -! -! general work fields (local variables): -! - real(r8) q(pcols,pver) ! w grid slice of mixing ratio. - real(r8) p(pcols,pver) ! w grid slice of ambient mid-layer pressure in mbs. - real(r8) z(pcols,pver) ! w grid slice of ambient mid-layer height in metres. - real(r8) s(pcols,pver) ! w grid slice of scaled dry static energy (t+gz/cp). - real(r8) tp(pcols,pver) ! w grid slice of parcel temperatures. - real(r8) zf(pcols,pver+1) ! w grid slice of ambient interface height in metres. - real(r8) pf(pcols,pver+1) ! w grid slice of ambient interface pressure in mbs. - real(r8) qstp(pcols,pver) ! w grid slice of parcel temp. saturation mixing ratio. - - real(r8) tl(pcols) ! w row of parcel temperature at lcl. - - integer lcl(pcols) ! w base level index of deep cumulus convection. - integer lel(pcols) ! w index of highest theoretical convective plume. - integer lon(pcols) ! w index of onset level for deep convection. - integer maxi(pcols) ! w index of level with largest moist static energy. - - real(r8) precip -! -! gathered work fields: -! - real(r8) qg(pcols,pver) ! wg grid slice of gathered values of q. - real(r8) tg(pcols,pver) ! w grid slice of temperature at interface. - real(r8) pg(pcols,pver) ! wg grid slice of gathered values of p. - real(r8) zg(pcols,pver) ! wg grid slice of gathered values of z. - real(r8) sg(pcols,pver) ! wg grid slice of gathered values of s. - real(r8) tpg(pcols,pver) ! wg grid slice of gathered values of tp. - real(r8) zfg(pcols,pver+1) ! wg grid slice of gathered values of zf. - real(r8) qstpg(pcols,pver) ! wg grid slice of gathered values of qstp. - real(r8) ug(pcols,pver) ! wg grid slice of gathered values of u. - real(r8) vg(pcols,pver) ! wg grid slice of gathered values of v. - real(r8) cmeg(pcols,pver) - - real(r8) rprdg(pcols,pver) ! wg gathered rain production rate - real(r8) capeg(pcols) ! wg gathered convective available potential energy. - real(r8) tlg(pcols) ! wg grid slice of gathered values of tl. - real(r8) landfracg(pcols) ! wg grid slice of landfrac - - integer lclg(pcols) ! wg gathered values of lcl. - integer lelg(pcols) -! -! work fields arising from gathered calculations. -! - real(r8) dqdt(pcols,pver) ! wg mixing ratio tendency at gathered points. - real(r8) dsdt(pcols,pver) ! wg dry static energy ("temp") tendency at gathered points. -! real(r8) alpha(pcols,pver) ! array of vertical differencing used (=1. for upstream). - real(r8) sd(pcols,pver) ! wg grid slice of dry static energy in downdraft. - real(r8) qd(pcols,pver) ! wg grid slice of mixing ratio in downdraft. - real(r8) mc(pcols,pver) ! wg net upward (scaled by mb) cloud mass flux. - real(r8) qhat(pcols,pver) ! wg grid slice of upper interface mixing ratio. - real(r8) qu(pcols,pver) ! wg grid slice of mixing ratio in updraft. - real(r8) su(pcols,pver) ! wg grid slice of dry static energy in updraft. - real(r8) qs(pcols,pver) ! wg grid slice of saturation mixing ratio. - real(r8) shat(pcols,pver) ! wg grid slice of upper interface dry static energy. - real(r8) hmn(pcols,pver) ! wg moist static energy. - real(r8) hsat(pcols,pver) ! wg saturated moist static energy. - real(r8) qlg(pcols,pver) - real(r8) dudt(pcols,pver) ! wg u-wind tendency at gathered points. - real(r8) dvdt(pcols,pver) ! wg v-wind tendency at gathered points. -! real(r8) ud(pcols,pver) -! real(r8) vd(pcols,pver) - - - - - - - - real(r8) qldeg(pcols,pver) ! cloud liquid water mixing ratio for detrainment (kg/kg) - real(r8) mb(pcols) ! wg cloud base mass flux. - - integer jlcl(pcols) - integer j0(pcols) ! wg detrainment initiation level index. - integer jd(pcols) ! wg downdraft initiation level index. - - real(r8) delt ! length of model time-step in seconds. - - integer i - integer ii - integer k, kk, l, m - - integer msg ! ic number of missing moisture levels at the top of model. - real(r8) qdifr - real(r8) sdifr - - real(r8), parameter :: dcon = 25.e-6_r8 - real(r8), parameter :: mucon = 5.3_r8 - real(r8) negadq - logical doliq - - -! -!--------------------------Data statements------------------------------ - -! -! Set internal variable "msg" (convection limit) to "limcnv-1" -! - msg = limcnv - 1 -! -! initialize necessary arrays. -! zero out variables not used in cam -! - - if (zm_org) then - orgt(:,:) = 0._r8 - end if - - qtnd(:,:) = 0._r8 - heat(:,:) = 0._r8 - mcon(:,:) = 0._r8 - rliq(:ncol) = 0._r8 - rice(:ncol) = 0._r8 - - if (zmconv_microp) then - allocate( & - loc_conv%frz(pcols,pver), & - loc_conv%sprd(pcols,pver), & - loc_conv%wu(pcols,pver), & - loc_conv%qi(pcols,pver), & - loc_conv%qliq(pcols,pver), & - loc_conv%qice(pcols,pver), & - loc_conv%qrain(pcols,pver), & - loc_conv%qsnow(pcols,pver), & - loc_conv%di(pcols,pver), & - loc_conv%dnl(pcols,pver), & - loc_conv%dni(pcols,pver), & - loc_conv%qnl(pcols,pver), & - loc_conv%qni(pcols,pver), & - loc_conv%qnr(pcols,pver), & - loc_conv%qns(pcols,pver), & - loc_conv%qide(pcols,pver), & - loc_conv%qncde(pcols,pver), & - loc_conv%qnide(pcols,pver), & - loc_conv%autolm(pcols,pver), & - loc_conv%accrlm(pcols,pver), & - loc_conv%bergnm(pcols,pver), & - loc_conv%fhtimm(pcols,pver), & - loc_conv%fhtctm(pcols,pver), & - loc_conv%fhmlm(pcols,pver), & - loc_conv%hmpim(pcols,pver), & - loc_conv%accslm(pcols,pver), & - loc_conv%dlfm(pcols,pver), & - loc_conv%cmel(pcols,pver), & - loc_conv%autoln(pcols,pver), & - loc_conv%accrln(pcols,pver), & - loc_conv%bergnn(pcols,pver), & - loc_conv%fhtimn(pcols,pver), & - loc_conv%fhtctn(pcols,pver), & - loc_conv%fhmln(pcols,pver), & - loc_conv%accsln(pcols,pver), & - loc_conv%activn(pcols,pver), & - loc_conv%dlfn(pcols,pver), & - loc_conv%autoim(pcols,pver), & - loc_conv%accsim(pcols,pver), & - loc_conv%difm(pcols,pver), & - loc_conv%cmei(pcols,pver), & - loc_conv%nuclin(pcols,pver), & - loc_conv%autoin(pcols,pver), & - loc_conv%accsin(pcols,pver), & - loc_conv%hmpin(pcols,pver), & - loc_conv%difn(pcols,pver), & - loc_conv%trspcm(pcols,pver), & - loc_conv%trspcn(pcols,pver), & - loc_conv%trspim(pcols,pver), & - loc_conv%trspin(pcols,pver), & - loc_conv%lambdadpcu(pcols,pver), & - loc_conv%mudpcu(pcols,pver), & - loc_conv%dcape(pcols) ) - end if - -! -! initialize convective tendencies -! - prec(:ncol) = 0._r8 - do k = 1,pver - do i = 1,ncol - dqdt(i,k) = 0._r8 - dsdt(i,k) = 0._r8 - dudt(i,k) = 0._r8 - dvdt(i,k) = 0._r8 - pflx(i,k) = 0._r8 - pflxg(i,k) = 0._r8 - cme(i,k) = 0._r8 - rprd(i,k) = 0._r8 - zdu(i,k) = 0._r8 - ql(i,k) = 0._r8 - qlg(i,k) = 0._r8 - dlf(i,k) = 0._r8 - dlg(i,k) = 0._r8 - qldeg(i,k) = 0._r8 - - dif(i,k) = 0._r8 - dnlf(i,k) = 0._r8 - dnif(i,k) = 0._r8 - - end do - end do - - if (zmconv_microp) then - do k = 1,pver - do i = 1,ncol - loc_conv%qliq(i,k) = 0._r8 - loc_conv%qice(i,k) = 0._r8 - loc_conv%di(i,k) = 0._r8 - loc_conv%qrain(i,k)= 0._r8 - loc_conv%qsnow(i,k)= 0._r8 - loc_conv%dnl(i,k) = 0._r8 - loc_conv%dni(i,k) = 0._r8 - loc_conv%wu(i,k) = 0._r8 - loc_conv%qnl(i,k) = 0._r8 - loc_conv%qni(i,k) = 0._r8 - loc_conv%qnr(i,k) = 0._r8 - loc_conv%qns(i,k) = 0._r8 - loc_conv%frz(i,k) = 0._r8 - loc_conv%sprd(i,k) = 0._r8 - loc_conv%qide(i,k) = 0._r8 - loc_conv%qncde(i,k) = 0._r8 - loc_conv%qnide(i,k) = 0._r8 - - loc_conv%autolm(i,k) = 0._r8 - loc_conv%accrlm(i,k) = 0._r8 - loc_conv%bergnm(i,k) = 0._r8 - loc_conv%fhtimm(i,k) = 0._r8 - loc_conv%fhtctm(i,k) = 0._r8 - loc_conv%fhmlm (i,k) = 0._r8 - loc_conv%hmpim (i,k) = 0._r8 - loc_conv%accslm(i,k) = 0._r8 - loc_conv%dlfm (i,k) = 0._r8 - - loc_conv%autoln(i,k) = 0._r8 - loc_conv%accrln(i,k) = 0._r8 - loc_conv%bergnn(i,k) = 0._r8 - loc_conv%fhtimn(i,k) = 0._r8 - loc_conv%fhtctn(i,k) = 0._r8 - loc_conv%fhmln (i,k) = 0._r8 - loc_conv%accsln(i,k) = 0._r8 - loc_conv%activn(i,k) = 0._r8 - loc_conv%dlfn (i,k) = 0._r8 - loc_conv%cmel (i,k) = 0._r8 - - loc_conv%autoim(i,k) = 0._r8 - loc_conv%accsim(i,k) = 0._r8 - loc_conv%difm (i,k) = 0._r8 - loc_conv%cmei (i,k) = 0._r8 - - loc_conv%nuclin(i,k) = 0._r8 - loc_conv%autoin(i,k) = 0._r8 - loc_conv%accsin(i,k) = 0._r8 - loc_conv%hmpin (i,k) = 0._r8 - loc_conv%difn (i,k) = 0._r8 - - loc_conv%trspcm(i,k) = 0._r8 - loc_conv%trspcn(i,k) = 0._r8 - loc_conv%trspim(i,k) = 0._r8 - loc_conv%trspin(i,k) = 0._r8 - - conv%qi(i,k) = 0._r8 - conv%frz(i,k) = 0._r8 - conv%sprd(i,k) = 0._r8 - conv%qi(i,k) = 0._r8 - conv%qliq(i,k) = 0._r8 - conv%qice(i,k) = 0._r8 - conv%qnl(i,k) = 0._r8 - conv%qni(i,k) = 0._r8 - conv%qnr(i,k) = 0._r8 - conv%qns(i,k) = 0._r8 - conv%qrain(i,k) = 0._r8 - conv%qsnow(i,k) = 0._r8 - conv%wu(i,k) = 0._r8 - - conv%autolm(i,k) = 0._r8 - conv%accrlm(i,k) = 0._r8 - conv%bergnm(i,k) = 0._r8 - conv%fhtimm(i,k) = 0._r8 - conv%fhtctm(i,k) = 0._r8 - conv%fhmlm (i,k) = 0._r8 - conv%hmpim (i,k) = 0._r8 - conv%accslm(i,k) = 0._r8 - conv%dlfm (i,k) = 0._r8 - - conv%autoln(i,k) = 0._r8 - conv%accrln(i,k) = 0._r8 - conv%bergnn(i,k) = 0._r8 - conv%fhtimn(i,k) = 0._r8 - conv%fhtctn(i,k) = 0._r8 - conv%fhmln (i,k) = 0._r8 - conv%accsln(i,k) = 0._r8 - conv%activn(i,k) = 0._r8 - conv%dlfn (i,k) = 0._r8 - conv%cmel (i,k) = 0._r8 - - conv%autoim(i,k) = 0._r8 - conv%accsim(i,k) = 0._r8 - conv%difm (i,k) = 0._r8 - conv%cmei (i,k) = 0._r8 - - conv%nuclin(i,k) = 0._r8 - conv%autoin(i,k) = 0._r8 - conv%accsin(i,k) = 0._r8 - conv%hmpin (i,k) = 0._r8 - conv%difn (i,k) = 0._r8 - - conv%trspcm(i,k) = 0._r8 - conv%trspcn(i,k) = 0._r8 - conv%trspim(i,k) = 0._r8 - conv%trspin(i,k) = 0._r8 - - end do - end do - - conv%lambdadpcu = (mucon + 1._r8)/dcon - conv%mudpcu = mucon - loc_conv%lambdadpcu = conv%lambdadpcu - loc_conv%mudpcu = conv%mudpcu - - end if - - do i = 1,ncol - pflx(i,pverp) = 0 - pflxg(i,pverp) = 0 - end do -! - do i = 1,ncol - pblt(i) = pver - dsubcld(i) = 0._r8 - - - jctop(i) = pver - jcbot(i) = 1 - - end do - - if (zmconv_microp) then - do i = 1,ncol - conv%dcape(i) = 0._r8 - loc_conv%dcape(i) = 0._r8 - end do - end if - - if (zm_org) then -! compute vertical average here - orgavg(:) = 0._r8 - dptot(:) = 0._r8 - - do k = 1, pver - do i = 1,ncol - if (org(i,k) .gt. 0) then - orgavg(i) = orgavg(i)+dpp(i,k)*org(i,k) - dptot(i) = dptot(i)+dpp(i,k) - endif - enddo - enddo - - do i = 1,ncol - if (dptot(i) .gt. 0) then - orgavg(i) = orgavg(i)/dptot(i) - endif - enddo - - do k = 1, pver - do i = 1, ncol - org2d(i,k) = orgavg(i) - enddo - enddo - - endif - -! -! calculate local pressure (mbs) and height (m) for both interface -! and mid-layer locations. -! - do i = 1,ncol - zs(i) = geos(i)*rgrav - pf(i,pver+1) = paph(i,pver+1)*0.01_r8 - zf(i,pver+1) = zi(i,pver+1) + zs(i) - end do - do k = 1,pver - do i = 1,ncol - p(i,k) = pap(i,k)*0.01_r8 - pf(i,k) = paph(i,k)*0.01_r8 - z(i,k) = zm(i,k) + zs(i) - zf(i,k) = zi(i,k) + zs(i) - end do - end do -! - do k = pver - 1,msg + 1,-1 - do i = 1,ncol - if (abs(z(i,k)-zs(i)-pblh(i)) < (zf(i,k)-zf(i,k+1))*0.5_r8) pblt(i) = k - end do - end do -! -! store incoming specific humidity field for subsequent calculation -! of precipitation (through change in storage). -! define dry static energy (normalized by cp). -! - do k = 1,pver - do i = 1,ncol - q(i,k) = qh(i,k) - s(i,k) = t(i,k) + (grav/cpres)*z(i,k) - tp(i,k)=0.0_r8 - shat(i,k) = s(i,k) - qhat(i,k) = q(i,k) - end do - end do - - do i = 1,ncol - capeg(i) = 0._r8 - lclg(i) = 1 - lelg(i) = pver - maxg(i) = 1 - tlg(i) = 400._r8 - dsubcld(i) = 0._r8 - end do - - if( cam_physpkg_is('cam3')) then - - ! For cam3 physics package, call non-dilute - - call buoyan(lchnk ,ncol , & - q ,t ,p ,z ,pf , & - tp ,qstp ,tl ,rl ,cape , & - pblt ,lcl ,lel ,lon ,maxi , & - rgas ,grav ,cpres ,msg , & - tpert ) - else - - ! Evaluate Tparcel, qs(Tparcel), buoyancy and CAPE, - ! lcl, lel, parcel launch level at index maxi()=hmax - - call buoyan_dilute(lchnk ,ncol , & - q ,t ,p ,z ,pf , & - tp ,qstp ,tl ,rl ,cape , & - pblt ,lcl ,lel ,lon ,maxi , & - rgas ,grav ,cpres ,msg , & - zi ,zs ,tpert , org2d , landfrac) - end if - -! -! determine whether grid points will undergo some deep convection -! (ideep=1) or not (ideep=0), based on values of cape,lcl,lel -! (require cape.gt. 0 and lel capelmt) then - lengath = lengath + 1 - ideep(lengath) = i - end if - end do - - if (lengath.eq.0) return -! -! obtain gathered arrays necessary for ensuing calculations. -! - do k = 1,pver - do i = 1,lengath - dp(i,k) = 0.01_r8*dpp(ideep(i),k) - qg(i,k) = q(ideep(i),k) - tg(i,k) = t(ideep(i),k) - pg(i,k) = p(ideep(i),k) - zg(i,k) = z(ideep(i),k) - sg(i,k) = s(ideep(i),k) - tpg(i,k) = tp(ideep(i),k) - zfg(i,k) = zf(ideep(i),k) - qstpg(i,k) = qstp(ideep(i),k) - ug(i,k) = 0._r8 - vg(i,k) = 0._r8 - end do - end do - - if (zmconv_microp) then - - if (aero%scheme == 'modal') then - - do m = 1, aero%nmodes - - do k = 1,pver - do i = 1,lengath - aero%numg_a(i,k,m) = aero%num_a(m)%val(ideep(i),k) - aero%dgnumg(i,k,m) = aero%dgnum(m)%val(ideep(i),k) - end do - end do - - do l = 1, aero%nspec(m) - do k = 1,pver - do i = 1,lengath - aero%mmrg_a(i,k,l,m) = aero%mmr_a(l,m)%val(ideep(i),k) - end do - end do - end do - - end do - - else if (aero%scheme == 'bulk') then - - do m = 1, aero%nbulk - do k = 1,pver - do i = 1,lengath - aero%mmrg_bulk(i,k,m) = aero%mmr_bulk(m)%val(ideep(i),k) - end do - end do - end do - - end if - - end if - -! - do i = 1,lengath - zfg(i,pver+1) = zf(ideep(i),pver+1) - end do - do i = 1,lengath - capeg(i) = cape(ideep(i)) - lclg(i) = lcl(ideep(i)) - lelg(i) = lel(ideep(i)) - maxg(i) = maxi(ideep(i)) - tlg(i) = tl(ideep(i)) - landfracg(i) = landfrac(ideep(i)) - end do -! -! calculate sub-cloud layer pressure "thickness" for use in -! closure and tendency routines. -! - do k = msg + 1,pver - do i = 1,lengath - if (k >= maxg(i)) then - dsubcld(i) = dsubcld(i) + dp(i,k) - end if - end do - end do -! -! define array of factors (alpha) which defines interfacial -! values, as well as interfacial values for (q,s) used in -! subsequent routines. -! - do k = msg + 2,pver - do i = 1,lengath -! alpha(i,k) = 0.5 - sdifr = 0._r8 - qdifr = 0._r8 - if (sg(i,k) > 0._r8 .or. sg(i,k-1) > 0._r8) & - sdifr = abs((sg(i,k)-sg(i,k-1))/max(sg(i,k-1),sg(i,k))) - if (qg(i,k) > 0._r8 .or. qg(i,k-1) > 0._r8) & - qdifr = abs((qg(i,k)-qg(i,k-1))/max(qg(i,k-1),qg(i,k))) - if (sdifr > 1.E-6_r8) then - shat(i,k) = log(sg(i,k-1)/sg(i,k))*sg(i,k-1)*sg(i,k)/(sg(i,k-1)-sg(i,k)) - else - shat(i,k) = 0.5_r8* (sg(i,k)+sg(i,k-1)) - end if - if (qdifr > 1.E-6_r8) then - qhat(i,k) = log(qg(i,k-1)/qg(i,k))*qg(i,k-1)*qg(i,k)/(qg(i,k-1)-qg(i,k)) - else - qhat(i,k) = 0.5_r8* (qg(i,k)+qg(i,k-1)) - end if - end do - end do -! -! obtain cloud properties. -! - - call cldprp(lchnk , & - qg ,tg ,ug ,vg ,pg , & - zg ,sg ,mu ,eu ,du , & - md ,ed ,sd ,qd ,mc , & - qu ,su ,zfg ,qs ,hmn , & - hsat ,shat ,qlg , & - cmeg ,maxg ,lelg ,jt ,jlcl , & - maxg ,j0 ,jd ,rl ,lengath , & - rgas ,grav ,cpres ,msg , & - pflxg ,evpg ,cug ,rprdg ,limcnv ,landfracg , & - qldeg ,aero ,loc_conv,qhat ) - - if (zmconv_microp) then - do i = 1,lengath - capeg(i) = capeg(i)+ loc_conv%dcape(i) - end do - end if - -! -! convert detrainment from units of "1/m" to "1/mb". -! - - do k = msg + 1,pver - do i = 1,lengath - du (i,k) = du (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - eu (i,k) = eu (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - ed (i,k) = ed (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - cug (i,k) = cug (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - cmeg (i,k) = cmeg (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - rprdg(i,k) = rprdg(i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - evpg (i,k) = evpg (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - end do - end do - - if (zmconv_microp) then - do k = msg + 1,pver - do i = 1,lengath - loc_conv%sprd(i,k) = loc_conv%sprd(i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - loc_conv%frz (i,k) = loc_conv%frz (i,k)* (zfg(i,k)-zfg(i,k+1))/dp(i,k) - end do - end do - end if - - call closure(lchnk , & - qg ,tg ,pg ,zg ,sg , & - tpg ,qs ,qu ,su ,mc , & - du ,mu ,md ,qd ,sd , & - qhat ,shat ,dp ,qstpg ,zfg , & - qlg ,dsubcld ,mb ,capeg ,tlg , & - lclg ,lelg ,jt ,maxg ,1 , & - lengath ,rgas ,grav ,cpres ,rl , & - msg ,capelmt ) -! -! limit cloud base mass flux to theoretical upper bound. -! - do i=1,lengath - mumax(i) = 0 - end do - do k=msg + 2,pver - do i=1,lengath - mumax(i) = max(mumax(i), mu(i,k)/dp(i,k)) - end do - end do - - do i=1,lengath - if (mumax(i) > 0._r8) then - mb(i) = min(mb(i),0.5_r8/(delt*mumax(i))) - else - mb(i) = 0._r8 - endif - end do - ! If no_deep_pbl = .true., don't allow convection entirely - ! within PBL (suggestion of Bjorn Stevens, 8-2000) - - if (no_deep_pbl) then - do i=1,lengath - if (zm(ideep(i),jt(i)) < pblh(ideep(i))) mb(i) = 0 - end do - end if - - if (zmconv_microp) then - do k=msg+1,pver - do i=1,lengath - loc_conv%sprd(i,k) = loc_conv%sprd(i,k)*mb(i) - loc_conv%frz (i,k) = loc_conv%frz (i,k)*mb(i) - end do - end do - end if - - do k=msg+1,pver - do i=1,lengath - mu (i,k) = mu (i,k)*mb(i) - md (i,k) = md (i,k)*mb(i) - mc (i,k) = mc (i,k)*mb(i) - du (i,k) = du (i,k)*mb(i) - eu (i,k) = eu (i,k)*mb(i) - ed (i,k) = ed (i,k)*mb(i) - cmeg (i,k) = cmeg (i,k)*mb(i) - rprdg(i,k) = rprdg(i,k)*mb(i) - cug (i,k) = cug (i,k)*mb(i) - evpg (i,k) = evpg (i,k)*mb(i) - pflxg(i,k+1)= pflxg(i,k+1)*mb(i)*100._r8/grav - - - if ( zmconv_microp .and. mb(i).eq.0._r8) then - qlg (i,k) = 0._r8 - loc_conv%qliq (i,k) = 0._r8 - loc_conv%qice (i,k) = 0._r8 - loc_conv%qrain(i,k) = 0._r8 - loc_conv%qsnow(i,k) = 0._r8 - loc_conv%wu(i,k) = 0._r8 - loc_conv%qnl (i,k) = 0._r8 - loc_conv%qni (i,k) = 0._r8 - loc_conv%qnr (i,k) = 0._r8 - loc_conv%qns (i,k) = 0._r8 - - loc_conv%autolm(i,k) = 0._r8 - loc_conv%accrlm(i,k) = 0._r8 - loc_conv%bergnm(i,k) = 0._r8 - loc_conv%fhtimm(i,k) = 0._r8 - loc_conv%fhtctm(i,k) = 0._r8 - loc_conv%fhmlm (i,k) = 0._r8 - loc_conv%hmpim (i,k) = 0._r8 - loc_conv%accslm(i,k) = 0._r8 - loc_conv%dlfm (i,k) = 0._r8 - - loc_conv%autoln(i,k) = 0._r8 - loc_conv%accrln(i,k) = 0._r8 - loc_conv%bergnn(i,k) = 0._r8 - loc_conv%fhtimn(i,k) = 0._r8 - loc_conv%fhtctn(i,k) = 0._r8 - loc_conv%fhmln (i,k) = 0._r8 - loc_conv%accsln(i,k) = 0._r8 - loc_conv%activn(i,k) = 0._r8 - loc_conv%dlfn (i,k) = 0._r8 - loc_conv%cmel (i,k) = 0._r8 - - loc_conv%autoim(i,k) = 0._r8 - loc_conv%accsim(i,k) = 0._r8 - loc_conv%difm (i,k) = 0._r8 - loc_conv%cmei (i,k) = 0._r8 - - loc_conv%nuclin(i,k) = 0._r8 - loc_conv%autoin(i,k) = 0._r8 - loc_conv%accsin(i,k) = 0._r8 - loc_conv%hmpin (i,k) = 0._r8 - loc_conv%difn (i,k) = 0._r8 - - loc_conv%trspcm(i,k) = 0._r8 - loc_conv%trspcn(i,k) = 0._r8 - loc_conv%trspim(i,k) = 0._r8 - loc_conv%trspin(i,k) = 0._r8 - end if - end do - end do -! -! compute temperature and moisture changes due to convection. -! - call q1q2_pjr(lchnk , & - dqdt ,dsdt ,qg ,qs ,qu , & - su ,du ,qhat ,shat ,dp , & - mu ,md ,sd ,qd ,qldeg , & - dsubcld ,jt ,maxg ,1 ,lengath , & - cpres ,rl ,msg , & - dlg ,evpg ,cug , & - loc_conv ) -! -! gather back temperature and mixing ratio. -! - - if (zmconv_microp) then - do k = msg + 1,pver - do i = 1,lengath - if (dqdt(i,k)*2._r8*delt+qg(i,k)<0._r8) then - negadq = (dqdt(i,k)+0.5_r8*qg(i,k)/delt)/0.9999_r8 - dqdt(i,k) = dqdt(i,k)-negadq - - do kk=k,jt(i),-1 - if (negadq<0._r8) then - if (rprdg(i,kk)> -negadq*dp(i,k)/dp(i,kk)) then - dsdt(i,k) = dsdt(i,k) + negadq*rl/cpres - if (rprdg(i,kk)>loc_conv%sprd(i,kk)) then - if(rprdg(i,kk)-loc_conv%sprd(i,kk)<-negadq*dp(i,k)/dp(i,kk)) then - dsdt(i,k) = dsdt(i,k) + (negadq+ (rprdg(i,kk)-loc_conv%sprd(i,kk))*dp(i,kk)/dp(i,k))*latice/cpres - loc_conv%sprd(i,kk) = negadq*dp(i,k)/dp(i,kk)+rprdg(i,kk) - end if - else - loc_conv%sprd(i,kk) = loc_conv%sprd(i,kk)+negadq*dp(i,k)/dp(i,kk) - dsdt(i,k) = dsdt(i,k) + negadq*latice/cpres - end if - rprdg(i,kk) = rprdg(i,kk)+negadq*dp(i,k)/dp(i,kk) - negadq = 0._r8 - else - negadq = rprdg(i,kk)*dp(i,kk)/dp(i,k)+negadq - dsdt(i,k) = dsdt(i,k) - rprdg(i,kk)*rl/cpres*dp(i,kk)/dp(i,k) - if (rprdg(i,kk)>loc_conv%sprd(i,kk)) then - dsdt(i,k) = dsdt(i,k) - loc_conv%sprd(i,kk)*latice/cpres*dp(i,kk)/dp(i,k) - loc_conv%sprd(i,kk) = 0._r8 - else - dsdt(i,k) = dsdt(i,k) -rprdg(i,kk)*latice/cpres*dp(i,kk)/dp(i,k) - loc_conv%sprd(i,kk)= loc_conv%sprd(i,kk)- rprdg(i,kk) - end if - rprdg(i,kk) = 0._r8 - end if - - if (dlg(i,kk)>loc_conv%di(i,kk)) then - doliq= .true. - else - doliq= .false. - end if - - if (negadq<0._r8) then - if (doliq) then - if (dlg(i,kk)> -negadq*dp(i,k)/dp(i,kk)) then - dsdt(i,k) = dsdt(i,k) + negadq*rl/cpres - loc_conv%dnl(i,kk) = loc_conv%dnl(i,kk)*(1._r8+negadq*dp(i,k)/dp(i,kk)/dlg(i,kk)) - dlg(i,kk) = dlg(i,kk)+negadq*dp(i,k)/dp(i,kk) - negadq = 0._r8 - else - negadq = negadq + dlg(i,kk)*dp(i,kk)/dp(i,k) - dsdt(i,k) = dsdt(i,k) - dlg(i,kk)*dp(i,kk)/dp(i,k)*rl/cpres - dlg(i,kk) = 0._r8 - loc_conv%dnl(i,kk) = 0._r8 - end if - else - if (loc_conv%di(i,kk)> -negadq*dp(i,k)/dp(i,kk)) then - dsdt(i,k) = dsdt(i,k) + negadq*(rl+latice)/cpres - loc_conv%dni(i,kk) = loc_conv%dni(i,kk)*(1._r8+negadq*dp(i,k)/dp(i,kk)/loc_conv%di(i,kk)) - loc_conv%di(i,kk) = loc_conv%di(i,kk)+negadq*dp(i,k)/dp(i,kk) - negadq = 0._r8 - else - negadq = negadq + loc_conv%di(i,kk)*dp(i,kk)/dp(i,k) - dsdt(i,k) = dsdt(i,k) - loc_conv%di(i,kk)*dp(i,kk)/dp(i,k)*(rl+latice)/cpres - loc_conv%di(i,kk) = 0._r8 - loc_conv%dni(i,kk) = 0._r8 - end if - doliq= .false. - end if - end if - if (negadq<0._r8 .and. doliq ) then - if (dlg(i,kk)> -negadq*dp(i,k)/dp(i,kk)) then - dsdt(i,k) = dsdt(i,k) + negadq*rl/cpres - loc_conv%dnl(i,kk) = loc_conv%dnl(i,kk)*(1._r8+negadq*dp(i,k)/dp(i,kk)/dlg(i,kk)) - dlg(i,kk) = dlg(i,kk)+negadq*dp(i,k)/dp(i,kk) - negadq = 0._r8 - else - negadq = negadq + dlg(i,kk)*dp(i,kk)/dp(i,k) - dsdt(i,k) = dsdt(i,k) - dlg(i,kk)*dp(i,kk)/dp(i,k)*rl/cpres - dlg(i,kk) = 0._r8 - loc_conv%dnl(i,kk) = 0._r8 - end if - end if - - end if - end do - - if (negadq<0._r8) then - dqdt(i,k) = dqdt(i,k) + negadq - end if - - end if - end do - end do - end if - - do k = msg + 1,pver - do i = 1,lengath -! -! q is updated to compute net precip. -! - q(ideep(i),k) = qh(ideep(i),k) + 2._r8*delt*dqdt(i,k) - qtnd(ideep(i),k) = dqdt (i,k) - cme (ideep(i),k) = cmeg (i,k) - rprd(ideep(i),k) = rprdg(i,k) - zdu (ideep(i),k) = du (i,k) - mcon(ideep(i),k) = mc (i,k) - heat(ideep(i),k) = dsdt (i,k)*cpres - dlf (ideep(i),k) = dlg (i,k) - pflx(ideep(i),k) = pflxg(i,k) - ql (ideep(i),k) = qlg (i,k) - end do - end do - - if (zmconv_microp) then - do k = msg + 1,pver - do i = 1,lengath - dif (ideep(i),k) = loc_conv%di (i,k) - dnlf(ideep(i),k) = loc_conv%dnl (i,k) - dnif(ideep(i),k) = loc_conv%dni (i,k) - - conv%qi (ideep(i),k) = loc_conv%qice(i,k) - conv%frz(ideep(i),k) = loc_conv%frz(i,k)*latice/cpres - conv%sprd(ideep(i),k) = loc_conv%sprd(i,k) - conv%wu (ideep(i),k) = loc_conv%wu (i,k) - conv%qliq(ideep(i),k) = loc_conv%qliq (i,k) - conv%qice(ideep(i),k) = loc_conv%qice (i,k) - conv%qrain(ideep(i),k) = loc_conv%qrain (i,k) - conv%qsnow(ideep(i),k) = loc_conv%qsnow (i,k) - conv%qnl(ideep(i),k) = loc_conv%qnl(i,k) - conv%qni(ideep(i),k) = loc_conv%qni(i,k) - conv%qnr(ideep(i),k) = loc_conv%qnr(i,k) - conv%qns(ideep(i),k) = loc_conv%qns(i,k) - - conv%autolm(ideep(i),k) = loc_conv%autolm(i,k) - conv%accrlm(ideep(i),k) = loc_conv%accrlm(i,k) - conv%bergnm(ideep(i),k) = loc_conv%bergnm(i,k) - conv%fhtimm(ideep(i),k) = loc_conv%fhtimm(i,k) - conv%fhtctm(ideep(i),k) = loc_conv%fhtctm(i,k) - conv%fhmlm (ideep(i),k) = loc_conv%fhmlm (i,k) - conv%hmpim (ideep(i),k) = loc_conv%hmpim (i,k) - conv%accslm(ideep(i),k) = loc_conv%accslm(i,k) - conv%dlfm (ideep(i),k) = loc_conv%dlfm (i,k) - - conv%autoln(ideep(i),k) = loc_conv%autoln(i,k) - conv%accrln(ideep(i),k) = loc_conv%accrln(i,k) - conv%bergnn(ideep(i),k) = loc_conv%bergnn(i,k) - conv%fhtimn(ideep(i),k) = loc_conv%fhtimn(i,k) - conv%fhtctn(ideep(i),k) = loc_conv%fhtctn(i,k) - conv%fhmln (ideep(i),k) = loc_conv%fhmln (i,k) - conv%accsln(ideep(i),k) = loc_conv%accsln(i,k) - conv%activn(ideep(i),k) = loc_conv%activn(i,k) - conv%dlfn (ideep(i),k) = loc_conv%dlfn (i,k) - conv%cmel (ideep(i),k) = loc_conv%cmel (i,k) - - conv%autoim(ideep(i),k) = loc_conv%autoim(i,k) - conv%accsim(ideep(i),k) = loc_conv%accsim(i,k) - conv%difm (ideep(i),k) = loc_conv%difm (i,k) - conv%cmei (ideep(i),k) = loc_conv%cmei (i,k) - - conv%nuclin(ideep(i),k) = loc_conv%nuclin(i,k) - conv%autoin(ideep(i),k) = loc_conv%autoin(i,k) - conv%accsin(ideep(i),k) = loc_conv%accsin(i,k) - conv%hmpin (ideep(i),k) = loc_conv%hmpin (i,k) - conv%difn (ideep(i),k) = loc_conv%difn (i,k) - - conv%trspcm(ideep(i),k) = loc_conv%trspcm(i,k) - conv%trspcn(ideep(i),k) = loc_conv%trspcn(i,k) - conv%trspim(ideep(i),k) = loc_conv%trspim(i,k) - conv%trspin(ideep(i),k) = loc_conv%trspin(i,k) - conv%lambdadpcu(ideep(i),k) = loc_conv%lambdadpcu(i,k) - conv%mudpcu(ideep(i),k) = loc_conv%mudpcu(i,k) - - end do - end do - - do k = msg + 1,pver - do i = 1,ncol - - !convert it from units of "kg/kg" to "g/m3" - - if(k.lt.pver) then - conv%qice (i,k) = 0.5_r8*(conv%qice(i,k)+conv%qice(i,k+1)) - conv%qliq (i,k) = 0.5_r8*(conv%qliq(i,k)+conv%qliq(i,k+1)) - conv%qrain (i,k) = 0.5_r8*(conv%qrain(i,k)+conv%qrain(i,k+1)) - conv%qsnow (i,k) = 0.5_r8*(conv%qsnow(i,k)+conv%qsnow(i,k+1)) - conv%qni (i,k) = 0.5_r8*(conv%qni(i,k)+conv%qni(i,k+1)) - conv%qnl (i,k) = 0.5_r8*(conv%qnl(i,k)+conv%qnl(i,k+1)) - conv%qnr (i,k) = 0.5_r8*(conv%qnr(i,k)+conv%qnr(i,k+1)) - conv%qns (i,k) = 0.5_r8*(conv%qns(i,k)+conv%qns(i,k+1)) - conv%wu(i,k) = 0.5_r8*(conv%wu(i,k)+conv%wu(i,k+1)) - end if - - if (t(i,k).gt. 273.15_r8 .and. t(i,k-1).le.273.15_r8) then - conv%qice (i,k-1) = conv%qice (i,k-1) + conv%qice (i,k) - conv%qice (i,k) = 0._r8 - conv%qni (i,k-1) = conv%qni (i,k-1) + conv%qni (i,k) - conv%qni (i,k) = 0._r8 - conv%qsnow (i,k-1) = conv%qsnow (i,k-1) + conv%qsnow (i,k) - conv%qsnow (i,k) = 0._r8 - conv%qns (i,k-1) = conv%qns (i,k-1) + conv%qns (i,k) - conv%qns (i,k) = 0._r8 - end if - - conv%qice (i,k) = conv%qice(i,k) * pap(i,k)/t(i,k)/rgas *1000._r8 - conv%qliq (i,k) = conv%qliq(i,k) * pap(i,k)/t(i,k)/rgas *1000._r8 - conv%qrain (i,k) = conv%qrain(i,k) * pap(i,k)/t(i,k)/rgas *1000._r8 - conv%qsnow (i,k) = conv%qsnow(i,k) * pap(i,k)/t(i,k)/rgas *1000._r8 - conv%qni (i,k) = conv%qni(i,k) * pap(i,k)/t(i,k)/rgas - conv%qnl (i,k) = conv%qnl(i,k) * pap(i,k)/t(i,k)/rgas - conv%qnr (i,k) = conv%qnr(i,k) * pap(i,k)/t(i,k)/rgas - conv%qns (i,k) = conv%qns(i,k) * pap(i,k)/t(i,k)/rgas - end do - end do - end if - -! - do i = 1,lengath - jctop(ideep(i)) = jt(i) - jcbot(ideep(i)) = maxg(i) - pflx(ideep(i),pverp) = pflxg(i,pverp) - end do - - if (zmconv_microp) then - do i = 1,lengath - conv%dcape(ideep(i)) = loc_conv%dcape(i) - end do - end if - -! Compute precip by integrating change in water vapor minus detrained cloud water - do k = pver,msg + 1,-1 - do i = 1,ncol - prec(i) = prec(i) - dpp(i,k)* (q(i,k)-qh(i,k)) - dpp(i,k)*(dlf(i,k)+dif(i,k))*2._r8*delt - end do - end do - -! obtain final precipitation rate in m/s. - do i = 1,ncol - prec(i) = rgrav*max(prec(i),0._r8)/ (2._r8*delt)/1000._r8 - end do - -! Compute reserved liquid (not yet in cldliq) for energy integrals. -! Treat rliq as flux out bottom, to be added back later. - do k = 1, pver - do i = 1, ncol - rliq(i) = rliq(i) + (dlf(i,k)+dif(i,k))*dpp(i,k)/gravit - rice(i) = rice(i) + dif(i,k)*dpp(i,k)/gravit - end do - end do - rliq(:ncol) = rliq(:ncol) /1000._r8 - rice(:ncol) = rice(:ncol) /1000._r8 - - if (zmconv_microp) then - deallocate( & - loc_conv%frz, & - loc_conv%sprd, & - loc_conv%wu, & - loc_conv%qi, & - loc_conv%qliq, & - loc_conv%qice, & - loc_conv%qrain, & - loc_conv%qsnow, & - loc_conv%di, & - loc_conv%dnl, & - loc_conv%dni, & - loc_conv%qnl, & - loc_conv%qni, & - loc_conv%qnr, & - loc_conv%qns, & - loc_conv%qide, & - loc_conv%qncde, & - loc_conv%qnide, & - loc_conv%autolm, & - loc_conv%accrlm, & - loc_conv%bergnm, & - loc_conv%fhtimm, & - loc_conv%fhtctm, & - loc_conv%fhmlm, & - loc_conv%hmpim, & - loc_conv%accslm, & - loc_conv%dlfm, & - loc_conv%cmel, & - loc_conv%autoln, & - loc_conv%accrln, & - loc_conv%bergnn, & - loc_conv%fhtimn, & - loc_conv%fhtctn, & - loc_conv%fhmln, & - loc_conv%accsln, & - loc_conv%activn, & - loc_conv%dlfn, & - loc_conv%autoim, & - loc_conv%accsim, & - loc_conv%difm, & - loc_conv%cmei, & - loc_conv%nuclin, & - loc_conv%autoin, & - loc_conv%accsin, & - loc_conv%hmpin, & - loc_conv%difn, & - loc_conv%trspcm, & - loc_conv%trspcn, & - loc_conv%trspim, & - loc_conv%trspin, & - loc_conv%lambdadpcu, & - loc_conv%mudpcu, & - loc_conv%dcape ) - end if - - return -end subroutine zm_convr - -!=============================================================================== -subroutine zm_conv_evap(ncol,lchnk, & - t,pmid,pdel,q, & - landfrac, & - tend_s, tend_s_snwprd, tend_s_snwevmlt, tend_q, & - prdprec, cldfrc, deltat, & - prec, snow, ntprprd, ntsnprd, flxprec, flxsnow, prdsnow) - - -!----------------------------------------------------------------------- -! Compute tendencies due to evaporation of rain from ZM scheme -!-- -! Compute the total precipitation and snow fluxes at the surface. -! Add in the latent heat of fusion for snow formation and melt, since it not dealt with -! in the Zhang-MacFarlane parameterization. -! Evaporate some of the precip directly into the environment using a Sundqvist type algorithm -!----------------------------------------------------------------------- - - use wv_saturation, only: qsat - use phys_grid, only: get_rlat_all_p - -!------------------------------Arguments-------------------------------- - integer,intent(in) :: ncol, lchnk ! number of columns and chunk index - real(r8),intent(in), dimension(pcols,pver) :: t ! temperature (K) - real(r8),intent(in), dimension(pcols,pver) :: pmid ! midpoint pressure (Pa) - real(r8),intent(in), dimension(pcols,pver) :: pdel ! layer thickness (Pa) - real(r8),intent(in), dimension(pcols,pver) :: q ! water vapor (kg/kg) - real(r8),intent(in), dimension(pcols) :: landfrac - real(r8),intent(inout), dimension(pcols,pver) :: tend_s ! heating rate (J/kg/s) - real(r8),intent(inout), dimension(pcols,pver) :: tend_q ! water vapor tendency (kg/kg/s) - real(r8),intent(out ), dimension(pcols,pver) :: tend_s_snwprd ! Heating rate of snow production - real(r8),intent(out ), dimension(pcols,pver) :: tend_s_snwevmlt ! Heating rate of evap/melting of snow - - - - real(r8), intent(in ) :: prdprec(pcols,pver)! precipitation production (kg/ks/s) - real(r8), intent(in ) :: cldfrc(pcols,pver) ! cloud fraction - real(r8), intent(in ) :: deltat ! time step - - real(r8), intent(inout) :: prec(pcols) ! Convective-scale preciptn rate - real(r8), intent(out) :: snow(pcols) ! Convective-scale snowfall rate - - real(r8), optional, intent(in), allocatable :: prdsnow(:,:) ! snow production (kg/ks/s) - -! -!---------------------------Local storage------------------------------- - - real(r8) :: es (pcols,pver) ! Saturation vapor pressure - real(r8) :: fice (pcols,pver) ! ice fraction in precip production - real(r8) :: fsnow_conv(pcols,pver) ! snow fraction in precip production - real(r8) :: qs (pcols,pver) ! saturation specific humidity - real(r8),intent(out) :: flxprec(pcols,pverp) ! Convective-scale flux of precip at interfaces (kg/m2/s) - real(r8),intent(out) :: flxsnow(pcols,pverp) ! Convective-scale flux of snow at interfaces (kg/m2/s) - real(r8),intent(out) :: ntprprd(pcols,pver) ! net precip production in layer - real(r8),intent(out) :: ntsnprd(pcols,pver) ! net snow production in layer - real(r8) :: work1 ! temp variable (pjr) - real(r8) :: work2 ! temp variable (pjr) - - real(r8) :: evpvint(pcols) ! vertical integral of evaporation - real(r8) :: evpprec(pcols) ! evaporation of precipitation (kg/kg/s) - real(r8) :: evpsnow(pcols) ! evaporation of snowfall (kg/kg/s) - real(r8) :: snowmlt(pcols) ! snow melt tendency in layer - real(r8) :: flxsntm(pcols) ! flux of snow into layer, after melting - - real(r8) :: kemask - real(r8) :: evplimit ! temp variable for evaporation limits - real(r8) :: rlat(pcols) - real(r8) :: dum - real(r8) :: omsm - - integer :: i,k ! longitude,level indices - logical :: old_snow - - -!----------------------------------------------------------------------- - - ! If prdsnow is passed in and allocated, then use it in the calculation, otherwise - ! use the old snow calculation - old_snow=.true. - if (present(prdsnow)) then - if (allocated(prdsnow)) then - old_snow=.false. - end if - end if - -! convert input precip to kg/m2/s - prec(:ncol) = prec(:ncol)*1000._r8 - -! determine saturation vapor pressure - do k = 1,pver - call qsat(t(1:ncol,k), pmid(1:ncol,k), es(1:ncol,k), qs(1:ncol,k), ncol) - end do -! determine ice fraction in rain production (use cloud water parameterization fraction at present) - call cldfrc_fice(ncol, t, fice, fsnow_conv) - -! zero the flux integrals on the top boundary - flxprec(:ncol,1) = 0._r8 - flxsnow(:ncol,1) = 0._r8 - evpvint(:ncol) = 0._r8 - omsm=0.9999_r8 - - do k = 1, pver - do i = 1, ncol - -! Melt snow falling into layer, if necessary. - if( old_snow ) then - if (t(i,k) > tmelt) then - flxsntm(i) = 0._r8 - snowmlt(i) = flxsnow(i,k) * gravit/ pdel(i,k) - else - flxsntm(i) = flxsnow(i,k) - snowmlt(i) = 0._r8 - end if - else - ! make sure melting snow doesn't reduce temperature below threshold - if (t(i,k) > tmelt) then - dum = -latice/cpres*flxsnow(i,k)*gravit/pdel(i,k)*deltat - if (t(i,k) + dum .le. tmelt) then - dum = (t(i,k)-tmelt)*cpres/latice/deltat - dum = dum/(flxsnow(i,k)*gravit/pdel(i,k)) - dum = max(0._r8,dum) - dum = min(1._r8,dum) - else - dum = 1._r8 - end if - dum = dum*omsm - flxsntm(i) = flxsnow(i,k)*(1.0_r8-dum) - snowmlt(i) = dum*flxsnow(i,k)*gravit/ pdel(i,k) - else - flxsntm(i) = flxsnow(i,k) - snowmlt(i) = 0._r8 - end if - end if - -! relative humidity depression must be > 0 for evaporation - evplimit = max(1._r8 - q(i,k)/qs(i,k), 0._r8) - - if (zm_org) then - kemask = ke * (1._r8 - landfrac(i)) + ke_lnd * landfrac(i) - else - kemask = ke - endif - -! total evaporation depends on flux in the top of the layer -! flux prec is the net production above layer minus evaporation into environmet - evpprec(i) = kemask * (1._r8 - cldfrc(i,k)) * evplimit * sqrt(flxprec(i,k)) -!********************************************************** -!! evpprec(i) = 0. ! turn off evaporation for now -!********************************************************** - -! Don't let evaporation supersaturate layer (approx). Layer may already be saturated. -! Currently does not include heating/cooling change to qs - evplimit = max(0._r8, (qs(i,k)-q(i,k)) / deltat) - -! Don't evaporate more than is falling into the layer - do not evaporate rain formed -! in this layer but if precip production is negative, remove from the available precip -! Negative precip production occurs because of evaporation in downdrafts. -!!$ evplimit = flxprec(i,k) * gravit / pdel(i,k) + min(prdprec(i,k), 0.) - evplimit = min(evplimit, flxprec(i,k) * gravit / pdel(i,k)) - -! Total evaporation cannot exceed input precipitation - evplimit = min(evplimit, (prec(i) - evpvint(i)) * gravit / pdel(i,k)) - - evpprec(i) = min(evplimit, evpprec(i)) - if( .not.old_snow ) then - evpprec(i) = max(0._r8, evpprec(i)) - evpprec(i) = evpprec(i)*omsm - end if - - -! evaporation of snow depends on snow fraction of total precipitation in the top after melting - if (flxprec(i,k) > 0._r8) then -! evpsnow(i) = evpprec(i) * flxsntm(i) / flxprec(i,k) -! prevent roundoff problems - work1 = min(max(0._r8,flxsntm(i)/flxprec(i,k)),1._r8) - evpsnow(i) = evpprec(i) * work1 - else - evpsnow(i) = 0._r8 - end if - -! vertically integrated evaporation - evpvint(i) = evpvint(i) + evpprec(i) * pdel(i,k)/gravit - -! net precip production is production - evaporation - ntprprd(i,k) = prdprec(i,k) - evpprec(i) -! net snow production is precip production * ice fraction - evaporation - melting -!pjrworks ntsnprd(i,k) = prdprec(i,k)*fice(i,k) - evpsnow(i) - snowmlt(i) -!pjrwrks2 ntsnprd(i,k) = prdprec(i,k)*fsnow_conv(i,k) - evpsnow(i) - snowmlt(i) -! the small amount added to flxprec in the work1 expression has been increased from -! 1e-36 to 8.64e-11 (1e-5 mm/day). This causes the temperature based partitioning -! scheme to be used for small flxprec amounts. This is to address error growth problems. - - if( old_snow ) then - if (flxprec(i,k).gt.0._r8) then - work1 = min(max(0._r8,flxsnow(i,k)/flxprec(i,k)),1._r8) - else - work1 = 0._r8 - endif - - work2 = max(fsnow_conv(i,k), work1) - if (snowmlt(i).gt.0._r8) work2 = 0._r8 -! work2 = fsnow_conv(i,k) - ntsnprd(i,k) = prdprec(i,k)*work2 - evpsnow(i) - snowmlt(i) - tend_s_snwprd (i,k) = prdprec(i,k)*work2*latice - tend_s_snwevmlt(i,k) = - ( evpsnow(i) + snowmlt(i) )*latice - else - ntsnprd(i,k) = prdsnow(i,k) - min(flxsnow(i,k)*gravit/pdel(i,k), evpsnow(i)+snowmlt(i)) - tend_s_snwprd (i,k) = prdsnow(i,k)*latice - tend_s_snwevmlt(i,k) = -min(flxsnow(i,k)*gravit/pdel(i,k), evpsnow(i)+snowmlt(i) )*latice - end if - -! precipitation fluxes - flxprec(i,k+1) = flxprec(i,k) + ntprprd(i,k) * pdel(i,k)/gravit - flxsnow(i,k+1) = flxsnow(i,k) + ntsnprd(i,k) * pdel(i,k)/gravit - -! protect against rounding error - flxprec(i,k+1) = max(flxprec(i,k+1), 0._r8) - flxsnow(i,k+1) = max(flxsnow(i,k+1), 0._r8) -! more protection (pjr) -! flxsnow(i,k+1) = min(flxsnow(i,k+1), flxprec(i,k+1)) - -! heating (cooling) and moistening due to evaporation -! - latent heat of vaporization for precip production has already been accounted for -! - snow is contained in prec - if( old_snow ) then - tend_s(i,k) =-evpprec(i)*latvap + ntsnprd(i,k)*latice - else - tend_s(i,k) =-evpprec(i)*latvap + tend_s_snwevmlt(i,k) - end if - tend_q(i,k) = evpprec(i) - end do - end do - -! set output precipitation rates (m/s) - prec(:ncol) = flxprec(:ncol,pver+1) / 1000._r8 - snow(:ncol) = flxsnow(:ncol,pver+1) / 1000._r8 - -!********************************************************** -!!$ tend_s(:ncol,:) = 0. ! turn heating off -!********************************************************** - - end subroutine zm_conv_evap - - - -subroutine convtran(lchnk , & - doconvtran,q ,ncnst ,mu ,md , & - du ,eu ,ed ,dp ,dsubcld , & - jt ,mx ,ideep ,il1g ,il2g , & - nstep ,fracis ,dqdt ,dpdry ,dt) -!----------------------------------------------------------------------- -! -! Purpose: -! Convective transport of trace species -! -! Mixing ratios may be with respect to either dry or moist air -! -! Method: -! -! -! -! Author: P. Rasch -! -!----------------------------------------------------------------------- - use shr_kind_mod, only: r8 => shr_kind_r8 - use constituents, only: cnst_get_type_byind - use ppgrid - - implicit none -!----------------------------------------------------------------------- -! -! Input arguments -! - integer, intent(in) :: lchnk ! chunk identifier - integer, intent(in) :: ncnst ! number of tracers to transport - logical, intent(in) :: doconvtran(ncnst) ! flag for doing convective transport - real(r8), intent(in) :: q(pcols,pver,ncnst) ! Tracer array including moisture - real(r8), intent(in) :: mu(pcols,pver) ! Mass flux up - real(r8), intent(in) :: md(pcols,pver) ! Mass flux down - real(r8), intent(in) :: du(pcols,pver) ! Mass detraining from updraft - real(r8), intent(in) :: eu(pcols,pver) ! Mass entraining from updraft - real(r8), intent(in) :: ed(pcols,pver) ! Mass entraining from downdraft - real(r8), intent(in) :: dp(pcols,pver) ! Delta pressure between interfaces - real(r8), intent(in) :: dsubcld(pcols) ! Delta pressure from cloud base to sfc - real(r8), intent(in) :: fracis(pcols,pver,ncnst) ! fraction of tracer that is insoluble - - integer, intent(in) :: jt(pcols) ! Index of cloud top for each column - integer, intent(in) :: mx(pcols) ! Index of cloud top for each column - integer, intent(in) :: ideep(pcols) ! Gathering array - integer, intent(in) :: il1g ! Gathered min lon indices over which to operate - integer, intent(in) :: il2g ! Gathered max lon indices over which to operate - integer, intent(in) :: nstep ! Time step index - - real(r8), intent(in) :: dpdry(pcols,pver) ! Delta pressure between interfaces - - real(r8), intent(in) :: dt ! 2 delta t (model time increment) - -! input/output - - real(r8), intent(out) :: dqdt(pcols,pver,ncnst) ! Tracer tendency array - -!--------------------------Local Variables------------------------------ - - integer i ! Work index - integer k ! Work index - integer kbm ! Highest altitude index of cloud base - integer kk ! Work index - integer kkp1 ! Work index - integer km1 ! Work index - integer kp1 ! Work index - integer ktm ! Highest altitude index of cloud top - integer m ! Work index - - real(r8) cabv ! Mix ratio of constituent above - real(r8) cbel ! Mix ratio of constituent below - real(r8) cdifr ! Normalized diff between cabv and cbel - real(r8) chat(pcols,pver) ! Mix ratio in env at interfaces - real(r8) cond(pcols,pver) ! Mix ratio in downdraft at interfaces - real(r8) const(pcols,pver) ! Gathered tracer array - real(r8) fisg(pcols,pver) ! gathered insoluble fraction of tracer - real(r8) conu(pcols,pver) ! Mix ratio in updraft at interfaces - real(r8) dcondt(pcols,pver) ! Gathered tend array - real(r8) small ! A small number - real(r8) mbsth ! Threshold for mass fluxes - real(r8) mupdudp ! A work variable - real(r8) minc ! A work variable - real(r8) maxc ! A work variable - real(r8) fluxin ! A work variable - real(r8) fluxout ! A work variable - real(r8) netflux ! A work variable - - real(r8) dutmp(pcols,pver) ! Mass detraining from updraft - real(r8) eutmp(pcols,pver) ! Mass entraining from updraft - real(r8) edtmp(pcols,pver) ! Mass entraining from downdraft - real(r8) dptmp(pcols,pver) ! Delta pressure between interfaces - real(r8) total(pcols) - real(r8) negadt,qtmp - -!----------------------------------------------------------------------- -! - small = 1.e-36_r8 -! mbsth is the threshold below which we treat the mass fluxes as zero (in mb/s) - mbsth = 1.e-15_r8 - -! Find the highest level top and bottom levels of convection - ktm = pver - kbm = pver - do i = il1g, il2g - ktm = min(ktm,jt(i)) - kbm = min(kbm,mx(i)) - end do - -! Loop ever each constituent - do m = 2, ncnst - if (doconvtran(m)) then - - if (cnst_get_type_byind(m).eq.'dry') then - do k = 1,pver - do i =il1g,il2g - dptmp(i,k) = dpdry(i,k) - dutmp(i,k) = du(i,k)*dp(i,k)/dpdry(i,k) - eutmp(i,k) = eu(i,k)*dp(i,k)/dpdry(i,k) - edtmp(i,k) = ed(i,k)*dp(i,k)/dpdry(i,k) - end do - end do - else - do k = 1,pver - do i =il1g,il2g - dptmp(i,k) = dp(i,k) - dutmp(i,k) = du(i,k) - eutmp(i,k) = eu(i,k) - edtmp(i,k) = ed(i,k) - end do - end do - endif -! dptmp = dp - -! Gather up the constituent and set tend to zero - do k = 1,pver - do i =il1g,il2g - const(i,k) = q(ideep(i),k,m) - fisg(i,k) = fracis(ideep(i),k,m) - end do - end do - -! From now on work only with gathered data - -! Interpolate environment tracer values to interfaces - do k = 1,pver - km1 = max(1,k-1) - do i = il1g, il2g - minc = min(const(i,km1),const(i,k)) - maxc = max(const(i,km1),const(i,k)) - if (minc < 0) then - cdifr = 0._r8 - else - cdifr = abs(const(i,k)-const(i,km1))/max(maxc,small) - endif - -! If the two layers differ significantly use a geometric averaging -! procedure - if (cdifr > 1.E-6_r8) then - cabv = max(const(i,km1),maxc*1.e-12_r8) - cbel = max(const(i,k),maxc*1.e-12_r8) - chat(i,k) = log(cabv/cbel)/(cabv-cbel)*cabv*cbel - - else ! Small diff, so just arithmetic mean - chat(i,k) = 0.5_r8* (const(i,k)+const(i,km1)) - end if - -! Provisional up and down draft values - conu(i,k) = chat(i,k) - cond(i,k) = chat(i,k) - -! provisional tends - dcondt(i,k) = 0._r8 - - end do - end do - -! Do levels adjacent to top and bottom - k = 2 - km1 = 1 - kk = pver - do i = il1g,il2g - mupdudp = mu(i,kk) + dutmp(i,kk)*dptmp(i,kk) - if (mupdudp > mbsth) then - conu(i,kk) = (+eutmp(i,kk)*fisg(i,kk)*const(i,kk)*dptmp(i,kk))/mupdudp - endif - if (md(i,k) < -mbsth) then - cond(i,k) = (-edtmp(i,km1)*fisg(i,km1)*const(i,km1)*dptmp(i,km1))/md(i,k) - endif - end do - -! Updraft from bottom to top - do kk = pver-1,1,-1 - kkp1 = min(pver,kk+1) - do i = il1g,il2g - mupdudp = mu(i,kk) + dutmp(i,kk)*dptmp(i,kk) - if (mupdudp > mbsth) then - conu(i,kk) = ( mu(i,kkp1)*conu(i,kkp1)+eutmp(i,kk)*fisg(i,kk)* & - const(i,kk)*dptmp(i,kk) )/mupdudp - endif - end do - end do - -! Downdraft from top to bottom - do k = 3,pver - km1 = max(1,k-1) - do i = il1g,il2g - if (md(i,k) < -mbsth) then - cond(i,k) = ( md(i,km1)*cond(i,km1)-edtmp(i,km1)*fisg(i,km1)*const(i,km1) & - *dptmp(i,km1) )/md(i,k) - endif - end do - end do - - - do k = ktm,pver - km1 = max(1,k-1) - kp1 = min(pver,k+1) - do i = il1g,il2g - -! version 1 hard to check for roundoff errors -! dcondt(i,k) = -! $ +(+mu(i,kp1)* (conu(i,kp1)-chat(i,kp1)) -! $ -mu(i,k)* (conu(i,k)-chat(i,k)) -! $ +md(i,kp1)* (cond(i,kp1)-chat(i,kp1)) -! $ -md(i,k)* (cond(i,k)-chat(i,k)) -! $ )/dp(i,k) - -! version 2 hard to limit fluxes -! fluxin = mu(i,kp1)*conu(i,kp1) + mu(i,k)*chat(i,k) -! $ -(md(i,k) *cond(i,k) + md(i,kp1)*chat(i,kp1)) -! fluxout = mu(i,k)*conu(i,k) + mu(i,kp1)*chat(i,kp1) -! $ -(md(i,kp1)*cond(i,kp1) + md(i,k)*chat(i,k)) - -! version 3 limit fluxes outside convection to mass in appropriate layer -! these limiters are probably only safe for positive definite quantitities -! it assumes that mu and md already satify a courant number limit of 1 - fluxin = mu(i,kp1)*conu(i,kp1)+ mu(i,k)*min(chat(i,k),const(i,km1)) & - -(md(i,k) *cond(i,k) + md(i,kp1)*min(chat(i,kp1),const(i,kp1))) - fluxout = mu(i,k)*conu(i,k) + mu(i,kp1)*min(chat(i,kp1),const(i,k)) & - -(md(i,kp1)*cond(i,kp1) + md(i,k)*min(chat(i,k),const(i,k))) - - netflux = fluxin - fluxout - if (abs(netflux) < max(fluxin,fluxout)*1.e-12_r8) then - netflux = 0._r8 - endif - dcondt(i,k) = netflux/dptmp(i,k) - end do - end do -! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -! - do k = kbm,pver - km1 = max(1,k-1) - do i = il1g,il2g - if (k == mx(i)) then - -! version 1 -! dcondt(i,k) = (1./dsubcld(i))* -! $ (-mu(i,k)*(conu(i,k)-chat(i,k)) -! $ -md(i,k)*(cond(i,k)-chat(i,k)) -! $ ) - -! version 2 -! fluxin = mu(i,k)*chat(i,k) - md(i,k)*cond(i,k) -! fluxout = mu(i,k)*conu(i,k) - md(i,k)*chat(i,k) -! version 3 - fluxin = mu(i,k)*min(chat(i,k),const(i,km1)) - md(i,k)*cond(i,k) - fluxout = mu(i,k)*conu(i,k) - md(i,k)*min(chat(i,k),const(i,k)) - - netflux = fluxin - fluxout - if (abs(netflux) < max(fluxin,fluxout)*1.e-12_r8) then - netflux = 0._r8 - endif -! dcondt(i,k) = netflux/dsubcld(i) - dcondt(i,k) = netflux/dptmp(i,k) - else if (k > mx(i)) then -! dcondt(i,k) = dcondt(i,k-1) - dcondt(i,k) = 0._r8 - end if - end do - end do - - if (zmconv_microp) then - do i = il1g,il2g - do k = jt(i),mx(i) - if (dcondt(i,k)*dt+const(i,k)<0._r8) then - negadt = dcondt(i,k)+const(i,k)/dt - dcondt(i,k) = -const(i,k)/dt - do kk= k+1, mx(i) - if (negadt<0._r8 .and. dcondt(i,kk)*dt+const(i,kk)>0._r8 ) then - qtmp = dcondt(i,kk)+negadt*dptmp(i,k)/dptmp(i,kk) - if (qtmp*dt+const(i,kk)>0._r8) then - dcondt(i,kk)= qtmp - negadt=0._r8 - else - negadt= negadt+(const(i,kk)/dt+dcondt(i,kk))*dptmp(i,kk)/dptmp(i,k) - dcondt(i,kk)= -const(i,kk)/dt - end if - - end if - end do - do kk= k-1, jt(i), -1 - if (negadt<0._r8 .and. dcondt(i,kk)*dt+const(i,kk)>0._r8 ) then - qtmp = dcondt(i,kk)+negadt*dptmp(i,k)/dptmp(i,kk) - if (qtmp*dt+const(i,kk)>0._r8) then - dcondt(i,kk)= qtmp - negadt=0._r8 - else - negadt= negadt+(const(i,kk)/dt+dcondt(i,kk))*dptmp(i,kk)/dptmp(i,k) - dcondt(i,kk)= -const(i,kk)/dt - end if - end if - end do - - if (negadt<0._r8) then - dcondt(i,k) = dcondt(i,k) + negadt - end if - end if - end do - end do - end if - - -! Initialize to zero everywhere, then scatter tendency back to full array - dqdt(:,:,m) = 0._r8 - do k = 1,pver - kp1 = min(pver,k+1) - do i = il1g,il2g - dqdt(ideep(i),k,m) = dcondt(i,k) - end do - end do - - end if ! for doconvtran - - end do - - return -end subroutine convtran - -!========================================================================================= - -subroutine momtran(lchnk, ncol, & - domomtran,q ,ncnst ,mu ,md , & - du ,eu ,ed ,dp ,dsubcld , & - jt ,mx ,ideep ,il1g ,il2g , & - nstep ,dqdt ,pguall ,pgdall, icwu, icwd, dt, seten ) -!----------------------------------------------------------------------- -! -! Purpose: -! Convective transport of momentum -! -! Mixing ratios may be with respect to either dry or moist air -! -! Method: -! Based on the convtran subroutine by P. Rasch -! -! -! Author: J. Richter and P. Rasch -! -!----------------------------------------------------------------------- - use shr_kind_mod, only: r8 => shr_kind_r8 - use constituents, only: cnst_get_type_byind - use ppgrid - - implicit none -!----------------------------------------------------------------------- -! -! Input arguments -! - integer, intent(in) :: lchnk ! chunk identifier - integer, intent(in) :: ncol ! number of atmospheric columns - integer, intent(in) :: ncnst ! number of tracers to transport - logical, intent(in) :: domomtran(ncnst) ! flag for doing convective transport - real(r8), intent(in) :: q(pcols,pver,ncnst) ! Wind array - real(r8), intent(in) :: mu(pcols,pver) ! Mass flux up - real(r8), intent(in) :: md(pcols,pver) ! Mass flux down - real(r8), intent(in) :: du(pcols,pver) ! Mass detraining from updraft - real(r8), intent(in) :: eu(pcols,pver) ! Mass entraining from updraft - real(r8), intent(in) :: ed(pcols,pver) ! Mass entraining from downdraft - real(r8), intent(in) :: dp(pcols,pver) ! Delta pressure between interfaces - real(r8), intent(in) :: dsubcld(pcols) ! Delta pressure from cloud base to sfc - real(r8), intent(in) :: dt ! time step in seconds : 2*delta_t - - integer, intent(in) :: jt(pcols) ! Index of cloud top for each column - integer, intent(in) :: mx(pcols) ! Index of cloud top for each column - integer, intent(in) :: ideep(pcols) ! Gathering array - integer, intent(in) :: il1g ! Gathered min lon indices over which to operate - integer, intent(in) :: il2g ! Gathered max lon indices over which to operate - integer, intent(in) :: nstep ! Time step index - - - -! input/output - - real(r8), intent(out) :: dqdt(pcols,pver,ncnst) ! Tracer tendency array - -!--------------------------Local Variables------------------------------ - - integer i ! Work index - integer k ! Work index - integer kbm ! Highest altitude index of cloud base - integer kk ! Work index - integer kkp1 ! Work index - integer kkm1 ! Work index - integer km1 ! Work index - integer kp1 ! Work index - integer ktm ! Highest altitude index of cloud top - integer m ! Work index - integer ii ! Work index - - real(r8) cabv ! Mix ratio of constituent above - real(r8) cbel ! Mix ratio of constituent below - real(r8) cdifr ! Normalized diff between cabv and cbel - real(r8) chat(pcols,pver) ! Mix ratio in env at interfaces - real(r8) cond(pcols,pver) ! Mix ratio in downdraft at interfaces - real(r8) const(pcols,pver) ! Gathered wind array - real(r8) conu(pcols,pver) ! Mix ratio in updraft at interfaces - real(r8) dcondt(pcols,pver) ! Gathered tend array - real(r8) mbsth ! Threshold for mass fluxes - real(r8) mupdudp ! A work variable - real(r8) minc ! A work variable - real(r8) maxc ! A work variable - real(r8) fluxin ! A work variable - real(r8) fluxout ! A work variable - real(r8) netflux ! A work variable - - real(r8) sum ! sum - real(r8) sum2 ! sum2 - - real(r8) mududp(pcols,pver) ! working variable - real(r8) mddudp(pcols,pver) ! working variable - - real(r8) pgu(pcols,pver) ! Pressure gradient term for updraft - real(r8) pgd(pcols,pver) ! Pressure gradient term for downdraft - - real(r8),intent(out) :: pguall(pcols,pver,ncnst) ! Apparent force from updraft PG - real(r8),intent(out) :: pgdall(pcols,pver,ncnst) ! Apparent force from downdraft PG - - real(r8),intent(out) :: icwu(pcols,pver,ncnst) ! In-cloud winds in updraft - real(r8),intent(out) :: icwd(pcols,pver,ncnst) ! In-cloud winds in downdraft - - real(r8),intent(out) :: seten(pcols,pver) ! Dry static energy tendency - real(r8) gseten(pcols,pver) ! Gathered dry static energy tendency - - real(r8) mflux(pcols,pverp,ncnst) ! Gathered momentum flux - - real(r8) wind0(pcols,pver,ncnst) ! gathered wind before time step - real(r8) windf(pcols,pver,ncnst) ! gathered wind after time step - real(r8) fkeb, fket, ketend_cons, ketend, utop, ubot, vtop, vbot, gset2 - - -!----------------------------------------------------------------------- -! - -! Initialize outgoing fields - pguall(:,:,:) = 0.0_r8 - pgdall(:,:,:) = 0.0_r8 -! Initialize in-cloud winds to environmental wind - icwu(:ncol,:,:) = q(:ncol,:,:) - icwd(:ncol,:,:) = q(:ncol,:,:) - -! Initialize momentum flux and final winds - mflux(:,:,:) = 0.0_r8 - wind0(:,:,:) = 0.0_r8 - windf(:,:,:) = 0.0_r8 - -! Initialize dry static energy - - seten(:,:) = 0.0_r8 - gseten(:,:) = 0.0_r8 - -! mbsth is the threshold below which we treat the mass fluxes as zero (in mb/s) - mbsth = 1.e-15_r8 - -! Find the highest level top and bottom levels of convection - ktm = pver - kbm = pver - do i = il1g, il2g - ktm = min(ktm,jt(i)) - kbm = min(kbm,mx(i)) - end do - -! Loop ever each wind component - do m = 1, ncnst !start at m = 1 to transport momentum - if (domomtran(m)) then - -! Gather up the winds and set tend to zero - do k = 1,pver - do i =il1g,il2g - const(i,k) = q(ideep(i),k,m) - wind0(i,k,m) = const(i,k) - end do - end do - - -! From now on work only with gathered data - -! Interpolate winds to interfaces - - do k = 1,pver - km1 = max(1,k-1) - do i = il1g, il2g - - ! use arithmetic mean - chat(i,k) = 0.5_r8* (const(i,k)+const(i,km1)) - -! Provisional up and down draft values - conu(i,k) = chat(i,k) - cond(i,k) = chat(i,k) - -! provisional tends - dcondt(i,k) = 0._r8 - - end do - end do - - -! -! Pressure Perturbation Term -! - - !Top boundary: assume mu is zero - - k=1 - pgu(:il2g,k) = 0.0_r8 - pgd(:il2g,k) = 0.0_r8 - - do k=2,pver-1 - km1 = max(1,k-1) - kp1 = min(pver,k+1) - do i = il1g,il2g - - !interior points - - mududp(i,k) = ( mu(i,k) * (const(i,k)- const(i,km1))/dp(i,km1) & - + mu(i,kp1) * (const(i,kp1) - const(i,k))/dp(i,k)) - - pgu(i,k) = - momcu * 0.5_r8 * mududp(i,k) - - - mddudp(i,k) = ( md(i,k) * (const(i,k)- const(i,km1))/dp(i,km1) & - + md(i,kp1) * (const(i,kp1) - const(i,k))/dp(i,k)) - - pgd(i,k) = - momcd * 0.5_r8 * mddudp(i,k) - - - end do - end do - - ! bottom boundary - k = pver - km1 = max(1,k-1) - do i=il1g,il2g - - mududp(i,k) = mu(i,k) * (const(i,k)- const(i,km1))/dp(i,km1) - pgu(i,k) = - momcu * mududp(i,k) - - mddudp(i,k) = md(i,k) * (const(i,k)- const(i,km1))/dp(i,km1) - - pgd(i,k) = - momcd * mddudp(i,k) - - end do - - -! -! In-cloud velocity calculations -! - -! Do levels adjacent to top and bottom - k = 2 - km1 = 1 - kk = pver - kkm1 = max(1,kk-1) - do i = il1g,il2g - mupdudp = mu(i,kk) + du(i,kk)*dp(i,kk) - if (mupdudp > mbsth) then - - conu(i,kk) = (+eu(i,kk)*const(i,kk)*dp(i,kk)+pgu(i,kk)*dp(i,kk))/mupdudp - endif - if (md(i,k) < -mbsth) then - cond(i,k) = (-ed(i,km1)*const(i,km1)*dp(i,km1))-pgd(i,km1)*dp(i,km1)/md(i,k) - endif - - - end do - - - -! Updraft from bottom to top - do kk = pver-1,1,-1 - kkm1 = max(1,kk-1) - kkp1 = min(pver,kk+1) - do i = il1g,il2g - mupdudp = mu(i,kk) + du(i,kk)*dp(i,kk) - if (mupdudp > mbsth) then - - conu(i,kk) = ( mu(i,kkp1)*conu(i,kkp1)+eu(i,kk)* & - const(i,kk)*dp(i,kk)+pgu(i,kk)*dp(i,kk))/mupdudp - endif - end do - - end do - - -! Downdraft from top to bottom - do k = 3,pver - km1 = max(1,k-1) - do i = il1g,il2g - if (md(i,k) < -mbsth) then - - cond(i,k) = ( md(i,km1)*cond(i,km1)-ed(i,km1)*const(i,km1) & - *dp(i,km1)-pgd(i,km1)*dp(i,km1) )/md(i,k) - - endif - end do - end do - - - sum = 0._r8 - sum2 = 0._r8 - - - do k = ktm,pver - km1 = max(1,k-1) - kp1 = min(pver,k+1) - do i = il1g,il2g - ii = ideep(i) - -! version 1 hard to check for roundoff errors - dcondt(i,k) = & - +(mu(i,kp1)* (conu(i,kp1)-chat(i,kp1)) & - -mu(i,k)* (conu(i,k)-chat(i,k)) & - +md(i,kp1)* (cond(i,kp1)-chat(i,kp1)) & - -md(i,k)* (cond(i,k)-chat(i,k)) & - )/dp(i,k) - - end do - end do - - ! dcont for bottom layer - ! - do k = kbm,pver - km1 = max(1,k-1) - do i = il1g,il2g - if (k == mx(i)) then - - ! version 1 - dcondt(i,k) = (1._r8/dp(i,k))* & - (-mu(i,k)*(conu(i,k)-chat(i,k)) & - -md(i,k)*(cond(i,k)-chat(i,k)) & - ) - end if - end do - end do - -! Initialize to zero everywhere, then scatter tendency back to full array - dqdt(:,:,m) = 0._r8 - - do k = 1,pver - do i = il1g,il2g - ii = ideep(i) - dqdt(ii,k,m) = dcondt(i,k) - ! Output apparent force on the mean flow from pressure gradient - pguall(ii,k,m) = -pgu(i,k) - pgdall(ii,k,m) = -pgd(i,k) - icwu(ii,k,m) = conu(i,k) - icwd(ii,k,m) = cond(i,k) - end do - end do - - ! Calculate momentum flux in units of mb*m/s2 - - do k = ktm,pver - do i = il1g,il2g - ii = ideep(i) - mflux(i,k,m) = & - -mu(i,k)* (conu(i,k)-chat(i,k)) & - -md(i,k)* (cond(i,k)-chat(i,k)) - end do - end do - - - ! Calculate winds at the end of the time step - - do k = ktm,pver - do i = il1g,il2g - ii = ideep(i) - km1 = max(1,k-1) - kp1 = k+1 - windf(i,k,m) = const(i,k) - (mflux(i,kp1,m) - mflux(i,k,m)) * dt /dp(i,k) - - end do - end do - - end if ! for domomtran - end do - - ! Need to add an energy fix to account for the dissipation of kinetic energy - ! Formulation follows from Boville and Bretherton (2003) - ! formulation by PJR - - do k = ktm,pver - km1 = max(1,k-1) - kp1 = min(pver,k+1) - do i = il1g,il2g - - ii = ideep(i) - - ! calculate the KE fluxes at top and bot of layer - ! based on a discrete approximation to b&b eq(35) F_KE = u*F_u + v*F_v at interface - utop = (wind0(i,k,1)+wind0(i,km1,1))/2._r8 - vtop = (wind0(i,k,2)+wind0(i,km1,2))/2._r8 - ubot = (wind0(i,kp1,1)+wind0(i,k,1))/2._r8 - vbot = (wind0(i,kp1,2)+wind0(i,k,2))/2._r8 - fket = utop*mflux(i,k,1) + vtop*mflux(i,k,2) ! top of layer - fkeb = ubot*mflux(i,k+1,1) + vbot*mflux(i,k+1,2) ! bot of layer - - ! divergence of these fluxes should give a conservative redistribution of KE - ketend_cons = (fket-fkeb)/dp(i,k) - - ! tendency in kinetic energy resulting from the momentum transport - ketend = ((windf(i,k,1)**2 + windf(i,k,2)**2) - (wind0(i,k,1)**2 + wind0(i,k,2)**2))*0.5_r8/dt - - ! the difference should be the dissipation - gset2 = ketend_cons - ketend - gseten(i,k) = gset2 - - end do - - end do - - ! Scatter dry static energy to full array - do k = 1,pver - do i = il1g,il2g - ii = ideep(i) - seten(ii,k) = gseten(i,k) - - end do - end do - - return -end subroutine momtran - -!========================================================================================= - -subroutine buoyan(lchnk ,ncol , & - q ,t ,p ,z ,pf , & - tp ,qstp ,tl ,rl ,cape , & - pblt ,lcl ,lel ,lon ,mx , & - rd ,grav ,cp ,msg , & - tpert ) -!----------------------------------------------------------------------- -! -! Purpose: -! -! -! Method: -! -! -! -! Author: -! This is contributed code not fully standardized by the CCM core group. -! The documentation has been enhanced to the degree that we are able. -! Reviewed: P. Rasch, April 1996 -! -!----------------------------------------------------------------------- - implicit none -!----------------------------------------------------------------------- -! -! input arguments -! - integer, intent(in) :: lchnk ! chunk identifier - integer, intent(in) :: ncol ! number of atmospheric columns - - real(r8), intent(in) :: q(pcols,pver) ! spec. humidity - real(r8), intent(in) :: t(pcols,pver) ! temperature - real(r8), intent(in) :: p(pcols,pver) ! pressure - real(r8), intent(in) :: z(pcols,pver) ! height - real(r8), intent(in) :: pf(pcols,pver+1) ! pressure at interfaces - real(r8), intent(in) :: pblt(pcols) ! index of pbl depth - real(r8), intent(in) :: tpert(pcols) ! perturbation temperature by pbl processes - -! -! output arguments -! - real(r8), intent(out) :: tp(pcols,pver) ! parcel temperature - real(r8), intent(out) :: qstp(pcols,pver) ! saturation mixing ratio of parcel - real(r8), intent(out) :: tl(pcols) ! parcel temperature at lcl - real(r8), intent(out) :: cape(pcols) ! convective aval. pot. energy. - integer lcl(pcols) ! - integer lel(pcols) ! - integer lon(pcols) ! level of onset of deep convection - integer mx(pcols) ! level of max moist static energy -! -!--------------------------Local Variables------------------------------ -! - real(r8) capeten(pcols,num_cin) ! provisional value of cape - real(r8) tv(pcols,pver) ! - real(r8) tpv(pcols,pver) ! - real(r8) buoy(pcols,pver) - - real(r8) a1(pcols) - real(r8) a2(pcols) - real(r8) estp(pcols) - real(r8) pl(pcols) - real(r8) plexp(pcols) - real(r8) hmax(pcols) - real(r8) hmn(pcols) - real(r8) y(pcols) - - logical plge600(pcols) - integer knt(pcols) - integer lelten(pcols,num_cin) - - real(r8) cp - real(r8) e - real(r8) grav - - integer i - integer k - integer msg - integer n - - real(r8) rd - real(r8) rl -! -!----------------------------------------------------------------------- -! - do n = 1,num_cin - do i = 1,ncol - lelten(i,n) = pver - capeten(i,n) = 0._r8 - end do - end do -! - do i = 1,ncol - lon(i) = pver - knt(i) = 0 - lel(i) = pver - mx(i) = lon(i) - cape(i) = 0._r8 - hmax(i) = 0._r8 - end do - - tp(:ncol,:) = t(:ncol,:) - qstp(:ncol,:) = q(:ncol,:) - -!!! RBN - Initialize tv and buoy for output. -!!! tv=tv : tpv=tpv : qstp=q : buoy=0. - tv(:ncol,:) = t(:ncol,:) *(1._r8+1.608_r8*q(:ncol,:))/ (1._r8+q(:ncol,:)) - tpv(:ncol,:) = tv(:ncol,:) - buoy(:ncol,:) = 0._r8 - -! -! set "launching" level(mx) to be at maximum moist static energy. -! search for this level stops at planetary boundary layer top. -! - do k = pver,msg + 1,-1 - do i = 1,ncol - hmn(i) = cp*t(i,k) + grav*z(i,k) + rl*q(i,k) - if (k >= nint(pblt(i)) .and. k <= lon(i) .and. hmn(i) > hmax(i)) then - hmax(i) = hmn(i) - mx(i) = k - end if - end do - end do - -! - do i = 1,ncol - lcl(i) = mx(i) - e = p(i,mx(i))*q(i,mx(i))/ (eps1+q(i,mx(i))) - tl(i) = 2840._r8/ (3.5_r8*log(t(i,mx(i)))-log(e)-4.805_r8) + 55._r8 - if (tl(i) < t(i,mx(i))) then - plexp(i) = (1._r8/ (0.2854_r8* (1._r8-0.28_r8*q(i,mx(i))))) - pl(i) = p(i,mx(i))* (tl(i)/t(i,mx(i)))**plexp(i) - else - tl(i) = t(i,mx(i)) - pl(i) = p(i,mx(i)) - end if - end do - -! -! calculate lifting condensation level (lcl). -! - do k = pver,msg + 2,-1 - do i = 1,ncol - if (k <= mx(i) .and. (p(i,k) > pl(i) .and. p(i,k-1) <= pl(i))) then - lcl(i) = k - 1 - end if - end do - end do -! -! if lcl is above the nominal level of non-divergence (600 mbs), -! no deep convection is permitted (ensuing calculations -! skipped and cape retains initialized value of zero). -! - do i = 1,ncol - plge600(i) = pl(i).ge.600._r8 - end do -! -! initialize parcel properties in sub-cloud layer below lcl. -! - do k = pver,msg + 1,-1 - do i=1,ncol - if (k > lcl(i) .and. k <= mx(i) .and. plge600(i)) then - tv(i,k) = t(i,k)* (1._r8+1.608_r8*q(i,k))/ (1._r8+q(i,k)) - qstp(i,k) = q(i,mx(i)) - tp(i,k) = t(i,mx(i))* (p(i,k)/p(i,mx(i)))**(0.2854_r8* (1._r8-0.28_r8*q(i,mx(i)))) -! -! buoyancy is increased by 0.5 k as in tiedtke -! -!-jjh tpv (i,k)=tp(i,k)*(1.+1.608*q(i,mx(i)))/ -!-jjh 1 (1.+q(i,mx(i))) - tpv(i,k) = (tp(i,k)+tpert(i))*(1._r8+1.608_r8*q(i,mx(i)))/ (1._r8+q(i,mx(i))) - buoy(i,k) = tpv(i,k) - tv(i,k) + tiedke_add - end if - end do - end do - -! -! define parcel properties at lcl (i.e. level immediately above pl). -! - do k = pver,msg + 1,-1 - do i=1,ncol - if (k == lcl(i) .and. plge600(i)) then - tv(i,k) = t(i,k)* (1._r8+1.608_r8*q(i,k))/ (1._r8+q(i,k)) - qstp(i,k) = q(i,mx(i)) - tp(i,k) = tl(i)* (p(i,k)/pl(i))**(0.2854_r8* (1._r8-0.28_r8*qstp(i,k))) -! estp(i) =exp(21.656_r8 - 5418._r8/tp(i,k)) -! use of different formulas for es has about 1 g/kg difference -! in qs at t= 300k, and 0.02 g/kg at t=263k, with the formula -! above giving larger qs. - call qsat_hPa(tp(i,k), p(i,k), estp(i), qstp(i,k)) - a1(i) = cp / rl + qstp(i,k) * (1._r8+ qstp(i,k) / eps1) * rl * eps1 / & - (rd * tp(i,k) ** 2) - a2(i) = .5_r8* (qstp(i,k)* (1._r8+2._r8/eps1*qstp(i,k))* & - (1._r8+qstp(i,k)/eps1)*eps1**2*rl*rl/ & - (rd**2*tp(i,k)**4)-qstp(i,k)* & - (1._r8+qstp(i,k)/eps1)*2._r8*eps1*rl/ & - (rd*tp(i,k)**3)) - a1(i) = 1._r8/a1(i) - a2(i) = -a2(i)*a1(i)**3 - y(i) = q(i,mx(i)) - qstp(i,k) - tp(i,k) = tp(i,k) + a1(i)*y(i) + a2(i)*y(i)**2 - call qsat_hPa(tp(i,k), p(i,k), estp(i), qstp(i,k)) -! -! buoyancy is increased by 0.5 k in cape calculation. -! dec. 9, 1994 -!-jjh tpv(i,k) =tp(i,k)*(1.+1.608*qstp(i,k))/(1.+q(i,mx(i))) -! - tpv(i,k) = (tp(i,k)+tpert(i))* (1._r8+1.608_r8*qstp(i,k)) / (1._r8+q(i,mx(i))) - buoy(i,k) = tpv(i,k) - tv(i,k) + tiedke_add - end if - end do - end do -! -! main buoyancy calculation. -! - do k = pver - 1,msg + 1,-1 - do i=1,ncol - if (k < lcl(i) .and. plge600(i)) then - tv(i,k) = t(i,k)* (1._r8+1.608_r8*q(i,k))/ (1._r8+q(i,k)) - qstp(i,k) = qstp(i,k+1) - tp(i,k) = tp(i,k+1)* (p(i,k)/p(i,k+1))**(0.2854_r8* (1._r8-0.28_r8*qstp(i,k))) - call qsat_hPa(tp(i,k), p(i,k), estp(i), qstp(i,k)) - a1(i) = cp/rl + qstp(i,k)* (1._r8+qstp(i,k)/eps1)*rl*eps1/ (rd*tp(i,k)**2) - a2(i) = .5_r8* (qstp(i,k)* (1._r8+2._r8/eps1*qstp(i,k))* & - (1._r8+qstp(i,k)/eps1)*eps1**2*rl*rl/ & - (rd**2*tp(i,k)**4)-qstp(i,k)* & - (1._r8+qstp(i,k)/eps1)*2._r8*eps1*rl/ & - (rd*tp(i,k)**3)) - a1(i) = 1._r8/a1(i) - a2(i) = -a2(i)*a1(i)**3 - y(i) = qstp(i,k+1) - qstp(i,k) - tp(i,k) = tp(i,k) + a1(i)*y(i) + a2(i)*y(i)**2 - call qsat_hPa(tp(i,k), p(i,k), estp(i), qstp(i,k)) -!-jjh tpv(i,k) =tp(i,k)*(1.+1.608*qstp(i,k))/ -!jt (1.+q(i,mx(i))) - tpv(i,k) = (tp(i,k)+tpert(i))* (1._r8+1.608_r8*qstp(i,k))/(1._r8+q(i,mx(i))) - buoy(i,k) = tpv(i,k) - tv(i,k) + tiedke_add - end if - end do - end do - -! - do k = msg + 2,pver - do i = 1,ncol - if (k < lcl(i) .and. plge600(i)) then - if (buoy(i,k+1) > 0._r8 .and. buoy(i,k) <= 0._r8) then - knt(i) = min(5,knt(i) + 1) - lelten(i,knt(i)) = k - end if - end if - end do - end do -! -! calculate convective available potential energy (cape). -! - do n = 1,5 - do k = msg + 1,pver - do i = 1,ncol - if (plge600(i) .and. k <= mx(i) .and. k > lelten(i,n)) then - capeten(i,n) = capeten(i,n) + rd*buoy(i,k)*log(pf(i,k+1)/pf(i,k)) - end if - end do - end do - end do -! -! find maximum cape from all possible tentative capes from -! one sounding, -! and use it as the final cape, april 26, 1995 -! - do n = 1,5 - do i = 1,ncol - if (capeten(i,n) > cape(i)) then - cape(i) = capeten(i,n) - lel(i) = lelten(i,n) - end if - end do - end do -! -! put lower bound on cape for diagnostic purposes. -! - do i = 1,ncol - cape(i) = max(cape(i), 0._r8) - end do -! - return -end subroutine buoyan - -subroutine cldprp(lchnk , & - q ,t ,u ,v ,p , & - z ,s ,mu ,eu ,du , & - md ,ed ,sd ,qd ,mc , & - qu ,su ,zf ,qst ,hmn , & - hsat ,shat ,ql , & - cmeg ,jb ,lel ,jt ,jlcl , & - mx ,j0 ,jd ,rl ,il2g , & - rd ,grav ,cp ,msg , & - pflx ,evp ,cu ,rprd ,limcnv ,landfrac, & - qcde ,aero ,loc_conv,qhat ) - -!----------------------------------------------------------------------- -! -! Purpose: -! -! -! Method: -! may 09/91 - guang jun zhang, m.lazare, n.mcfarlane. -! original version cldprop. -! -! Author: See above, modified by P. Rasch -! This is contributed code not fully standardized by the CCM core group. -! -! this code is very much rougher than virtually anything else in the CCM -! there are debug statements left strewn about and code segments disabled -! these are to facilitate future development. We expect to release a -! cleaner code in a future release -! -! the documentation has been enhanced to the degree that we are able -! -!----------------------------------------------------------------------- - - implicit none - -!------------------------------------------------------------------------------ -! -! Input arguments -! - integer, intent(in) :: lchnk ! chunk identifier - - real(r8), intent(in) :: q(pcols,pver) ! spec. humidity of env - real(r8), intent(in) :: t(pcols,pver) ! temp of env - real(r8), intent(in) :: p(pcols,pver) ! pressure of env - real(r8), intent(in) :: z(pcols,pver) ! height of env - real(r8), intent(in) :: s(pcols,pver) ! normalized dry static energy of env - real(r8), intent(in) :: zf(pcols,pverp) ! height of interfaces - real(r8), intent(in) :: u(pcols,pver) ! zonal velocity of env - real(r8), intent(in) :: v(pcols,pver) ! merid. velocity of env - - real(r8), intent(in) :: landfrac(pcols) ! RBN Landfrac - - integer, intent(in) :: jb(pcols) ! updraft base level - integer, intent(in) :: lel(pcols) ! updraft launch level - integer, intent(out) :: jt(pcols) ! updraft plume top - integer, intent(out) :: jlcl(pcols) ! updraft lifting cond level - integer, intent(in) :: mx(pcols) ! updraft base level (same is jb) - integer, intent(out) :: j0(pcols) ! level where updraft begins detraining - integer, intent(out) :: jd(pcols) ! level of downdraft - integer, intent(in) :: limcnv ! convection limiting level - integer, intent(in) :: il2g !CORE GROUP REMOVE - integer, intent(in) :: msg ! missing moisture vals (always 0) - real(r8), intent(in) :: rl ! latent heat of vap - real(r8), intent(in) :: shat(pcols,pver) ! interface values of dry stat energy - real(r8), intent(in) :: qhat(pcols,pver) ! wg grid slice of upper interface mixing ratio. - type(zm_aero_t), intent(in) :: aero ! aerosol object - -! -! output -! - real(r8), intent(out) :: rprd(pcols,pver) ! rate of production of precip at that layer - real(r8), intent(out) :: du(pcols,pver) ! detrainement rate of updraft - real(r8), intent(out) :: ed(pcols,pver) ! entrainment rate of downdraft - real(r8), intent(out) :: eu(pcols,pver) ! entrainment rate of updraft - real(r8), intent(out) :: hmn(pcols,pver) ! moist stat energy of env - real(r8), intent(out) :: hsat(pcols,pver) ! sat moist stat energy of env - real(r8), intent(out) :: mc(pcols,pver) ! net mass flux - real(r8), intent(out) :: md(pcols,pver) ! downdraft mass flux - real(r8), intent(out) :: mu(pcols,pver) ! updraft mass flux - real(r8), intent(out) :: pflx(pcols,pverp) ! precipitation flux thru layer - real(r8), intent(out) :: qd(pcols,pver) ! spec humidity of downdraft - real(r8), intent(out) :: ql(pcols,pver) ! liq water of updraft - real(r8), intent(out) :: qst(pcols,pver) ! saturation mixing ratio of env. - real(r8), intent(out) :: qu(pcols,pver) ! spec hum of updraft - real(r8), intent(out) :: sd(pcols,pver) ! normalized dry stat energy of downdraft - real(r8), intent(out) :: su(pcols,pver) ! normalized dry stat energy of updraft - real(r8), intent(out) :: qcde(pcols,pver) ! cloud water mixing ratio for detrainment (kg/kg) - - type(zm_conv_t) :: loc_conv - - real(r8) rd ! gas constant for dry air - real(r8) grav ! gravity - real(r8) cp ! heat capacity of dry air - -! -! Local workspace -! - real(r8) gamma(pcols,pver) - real(r8) dz(pcols,pver) - real(r8) iprm(pcols,pver) - real(r8) hu(pcols,pver) - real(r8) hd(pcols,pver) - real(r8) eps(pcols,pver) - real(r8) f(pcols,pver) - real(r8) k1(pcols,pver) - real(r8) i2(pcols,pver) - real(r8) ihat(pcols,pver) - real(r8) i3(pcols,pver) - real(r8) idag(pcols,pver) - real(r8) i4(pcols,pver) - real(r8) qsthat(pcols,pver) - real(r8) hsthat(pcols,pver) - real(r8) gamhat(pcols,pver) - real(r8) cu(pcols,pver) - real(r8) evp(pcols,pver) - real(r8) cmeg(pcols,pver) - real(r8) qds(pcols,pver) -! RBN For c0mask - real(r8) c0mask(pcols) - - real(r8) hmin(pcols) - real(r8) expdif(pcols) - real(r8) expnum(pcols) - real(r8) ftemp(pcols) - real(r8) eps0(pcols) - real(r8) rmue(pcols) - real(r8) zuef(pcols) - real(r8) zdef(pcols) - real(r8) epsm(pcols) - real(r8) ratmjb(pcols) - real(r8) est(pcols) - real(r8) totpcp(pcols) - real(r8) totevp(pcols) - real(r8) alfa(pcols) - real(r8) ql1 - real(r8) tu - real(r8) estu - real(r8) qstu - - real(r8) small - real(r8) mdt - - real(r8) fice(pcols,pver) ! ice fraction in precip production - real(r8) tug(pcols,pver) - - real(r8) tvuo(pcols,pver) ! updraft virtual T w/o freezing heating - real(r8) tvu(pcols,pver) ! updraft virtual T with freezing heating - real(r8) totfrz(pcols) - real(r8) frz (pcols,pver) ! rate of freezing - integer jto(pcols) ! updraft plume old top - integer tmplel(pcols) - - integer iter, itnum - integer m - - integer khighest - integer klowest - integer kount - integer i,k - - logical doit(pcols) - logical done(pcols) -! -!------------------------------------------------------------------------------ -! - if (zmconv_microp) then - loc_conv%autolm(:il2g,:) = 0._r8 - loc_conv%accrlm(:il2g,:) = 0._r8 - loc_conv%bergnm(:il2g,:) = 0._r8 - loc_conv%fhtimm(:il2g,:) = 0._r8 - loc_conv%fhtctm(:il2g,:) = 0._r8 - loc_conv%fhmlm (:il2g,:) = 0._r8 - loc_conv%hmpim (:il2g,:) = 0._r8 - loc_conv%accslm(:il2g,:) = 0._r8 - loc_conv%dlfm (:il2g,:) = 0._r8 - - loc_conv%autoln(:il2g,:) = 0._r8 - loc_conv%accrln(:il2g,:) = 0._r8 - loc_conv%bergnn(:il2g,:) = 0._r8 - loc_conv%fhtimn(:il2g,:) = 0._r8 - loc_conv%fhtctn(:il2g,:) = 0._r8 - loc_conv%fhmln (:il2g,:) = 0._r8 - loc_conv%accsln(:il2g,:) = 0._r8 - loc_conv%activn(:il2g,:) = 0._r8 - loc_conv%dlfn (:il2g,:) = 0._r8 - - loc_conv%autoim(:il2g,:) = 0._r8 - loc_conv%accsim(:il2g,:) = 0._r8 - loc_conv%difm (:il2g,:) = 0._r8 - - loc_conv%nuclin(:il2g,:) = 0._r8 - loc_conv%autoin(:il2g,:) = 0._r8 - loc_conv%accsin(:il2g,:) = 0._r8 - loc_conv%hmpin (:il2g,:) = 0._r8 - loc_conv%difn (:il2g,:) = 0._r8 - - loc_conv%trspcm(:il2g,:) = 0._r8 - loc_conv%trspcn(:il2g,:) = 0._r8 - loc_conv%trspim(:il2g,:) = 0._r8 - loc_conv%trspin(:il2g,:) = 0._r8 - - loc_conv%dcape (:il2g) = 0._r8 - - end if - - do i = 1,il2g - ftemp(i) = 0._r8 - expnum(i) = 0._r8 - expdif(i) = 0._r8 - c0mask(i) = c0_ocn * (1._r8-landfrac(i)) + c0_lnd * landfrac(i) - end do -! -!jr Change from msg+1 to 1 to prevent blowup -! - do k = 1,pver - do i = 1,il2g - dz(i,k) = zf(i,k) - zf(i,k+1) - end do - end do - -! -! initialize many output and work variables to zero -! - pflx(:il2g,1) = 0 - - do k = 1,pver - do i = 1,il2g - k1(i,k) = 0._r8 - i2(i,k) = 0._r8 - i3(i,k) = 0._r8 - i4(i,k) = 0._r8 - mu(i,k) = 0._r8 - f(i,k) = 0._r8 - eps(i,k) = 0._r8 - eu(i,k) = 0._r8 - du(i,k) = 0._r8 - ql(i,k) = 0._r8 - cu(i,k) = 0._r8 - evp(i,k) = 0._r8 - cmeg(i,k) = 0._r8 - qds(i,k) = q(i,k) - md(i,k) = 0._r8 - ed(i,k) = 0._r8 - sd(i,k) = s(i,k) - qd(i,k) = q(i,k) - mc(i,k) = 0._r8 - qu(i,k) = q(i,k) - su(i,k) = s(i,k) - call qsat_hPa(t(i,k), p(i,k), est(i), qst(i,k)) - - if ( p(i,k)-est(i) <= 0._r8 ) then - qst(i,k) = 1.0_r8 - end if - - gamma(i,k) = qst(i,k)*(1._r8 + qst(i,k)/eps1)*eps1*rl/(rd*t(i,k)**2)*rl/cp - hmn(i,k) = cp*t(i,k) + grav*z(i,k) + rl*q(i,k) - hsat(i,k) = cp*t(i,k) + grav*z(i,k) + rl*qst(i,k) - hu(i,k) = hmn(i,k) - hd(i,k) = hmn(i,k) - rprd(i,k) = 0._r8 - - fice(i,k) = 0._r8 - tug(i,k) = 0._r8 - qcde(i,k) = 0._r8 - tvuo(i,k) = (shat(i,k) - grav/cp*zf(i,k))*(1._r8 + 0.608_r8*qhat(i,k)) - tvu(i,k) = tvuo(i,k) - frz(i,k) = 0._r8 - - end do - end do - if (zmconv_microp) then - do k = 1,pver - do i = 1,il2g - loc_conv%sprd(i,k) = 0._r8 - loc_conv%wu(i,k) = 0._r8 - loc_conv%cmel(i,k) = 0._r8 - loc_conv%cmei(i,k) = 0._r8 - loc_conv%qliq(i,k) = 0._r8 - loc_conv%qice(i,k) = 0._r8 - loc_conv%qnl(i,k) = 0._r8 - loc_conv%qni(i,k) = 0._r8 - loc_conv%qide(i,k) = 0._r8 - loc_conv%qncde(i,k) = 0._r8 - loc_conv%qnide(i,k) = 0._r8 - loc_conv%qnr(i,k) = 0._r8 - loc_conv%qns(i,k) = 0._r8 - loc_conv%qrain(i,k)= 0._r8 - loc_conv%qsnow(i,k)= 0._r8 - loc_conv%frz(i,k) = 0._r8 - end do - end do - end if -! -!jr Set to zero things which make this routine blow up -! - do k=1,msg - do i=1,il2g - rprd(i,k) = 0._r8 - end do - end do -! -! interpolate the layer values of qst, hsat and gamma to -! layer interfaces -! - do k = 1, msg+1 - do i = 1,il2g - hsthat(i,k) = hsat(i,k) - qsthat(i,k) = qst(i,k) - gamhat(i,k) = gamma(i,k) - end do - end do - do i = 1,il2g - totpcp(i) = 0._r8 - totevp(i) = 0._r8 - end do - do k = msg + 2,pver - do i = 1,il2g - if (abs(qst(i,k-1)-qst(i,k)) > 1.E-6_r8) then - qsthat(i,k) = log(qst(i,k-1)/qst(i,k))*qst(i,k-1)*qst(i,k)/ (qst(i,k-1)-qst(i,k)) - else - qsthat(i,k) = qst(i,k) - end if - hsthat(i,k) = cp*shat(i,k) + rl*qsthat(i,k) - if (abs(gamma(i,k-1)-gamma(i,k)) > 1.E-6_r8) then - gamhat(i,k) = log(gamma(i,k-1)/gamma(i,k))*gamma(i,k-1)*gamma(i,k)/ & - (gamma(i,k-1)-gamma(i,k)) - else - gamhat(i,k) = gamma(i,k) - end if - end do - end do -! -! initialize cloud top to highest plume top. -!jr changed hard-wired 4 to limcnv+1 (not to exceed pver) -! - jt(:) = pver - do i = 1,il2g - jt(i) = max(lel(i),limcnv+1) - jt(i) = min(jt(i),pver) - jd(i) = pver - jlcl(i) = lel(i) - hmin(i) = 1.E6_r8 - end do -! -! find the level of minimum hsat, where detrainment starts -! - - do k = msg + 1,pver - do i = 1,il2g - if (hsat(i,k) <= hmin(i) .and. k >= jt(i) .and. k <= jb(i)) then - hmin(i) = hsat(i,k) - j0(i) = k - end if - end do - end do - do i = 1,il2g - j0(i) = min(j0(i),jb(i)-2) - j0(i) = max(j0(i),jt(i)+2) -! -! Fix from Guang Zhang to address out of bounds array reference -! - j0(i) = min(j0(i),pver) - end do -! -! Initialize certain arrays inside cloud -! - do k = msg + 1,pver - do i = 1,il2g - if (k >= jt(i) .and. k <= jb(i)) then - hu(i,k) = hmn(i,mx(i)) + cp*tiedke_add - su(i,k) = s(i,mx(i)) + tiedke_add - end if - end do - end do -! -! ********************************************************* -! compute taylor series for approximate eps(z) below -! ********************************************************* -! - do k = pver - 1,msg + 1,-1 - do i = 1,il2g - if (k < jb(i) .and. k >= jt(i)) then - k1(i,k) = k1(i,k+1) + (hmn(i,mx(i))-hmn(i,k))*dz(i,k) - ihat(i,k) = 0.5_r8* (k1(i,k+1)+k1(i,k)) - i2(i,k) = i2(i,k+1) + ihat(i,k)*dz(i,k) - idag(i,k) = 0.5_r8* (i2(i,k+1)+i2(i,k)) - i3(i,k) = i3(i,k+1) + idag(i,k)*dz(i,k) - iprm(i,k) = 0.5_r8* (i3(i,k+1)+i3(i,k)) - i4(i,k) = i4(i,k+1) + iprm(i,k)*dz(i,k) - end if - end do - end do -! -! re-initialize hmin array for ensuing calculation. -! - do i = 1,il2g - hmin(i) = 1.E6_r8 - end do - do k = msg + 1,pver - do i = 1,il2g - if (k >= j0(i) .and. k <= jb(i) .and. hmn(i,k) <= hmin(i)) then - hmin(i) = hmn(i,k) - expdif(i) = hmn(i,mx(i)) - hmin(i) - end if - end do - end do -! -! ********************************************************* -! compute approximate eps(z) using above taylor series -! ********************************************************* -! - do k = msg + 2,pver - do i = 1,il2g - expnum(i) = 0._r8 - ftemp(i) = 0._r8 - if (k < jt(i) .or. k >= jb(i)) then - k1(i,k) = 0._r8 - expnum(i) = 0._r8 - else - expnum(i) = hmn(i,mx(i)) - (hsat(i,k-1)*(zf(i,k)-z(i,k)) + & - hsat(i,k)* (z(i,k-1)-zf(i,k)))/(z(i,k-1)-z(i,k)) - end if - if ((expdif(i) > 100._r8 .and. expnum(i) > 0._r8) .and. & - k1(i,k) > expnum(i)*dz(i,k)) then - ftemp(i) = expnum(i)/k1(i,k) - f(i,k) = ftemp(i) + i2(i,k)/k1(i,k)*ftemp(i)**2 + & - (2._r8*i2(i,k)**2-k1(i,k)*i3(i,k))/k1(i,k)**2* & - ftemp(i)**3 + (-5._r8*k1(i,k)*i2(i,k)*i3(i,k)+ & - 5._r8*i2(i,k)**3+k1(i,k)**2*i4(i,k))/ & - k1(i,k)**3*ftemp(i)**4 - f(i,k) = max(f(i,k),0._r8) - f(i,k) = min(f(i,k),0.0002_r8) - end if - end do - end do - do i = 1,il2g - if (j0(i) < jb(i)) then - if (f(i,j0(i)) < 1.E-6_r8 .and. f(i,j0(i)+1) > f(i,j0(i))) j0(i) = j0(i) + 1 - end if - end do - do k = msg + 2,pver - do i = 1,il2g - if (k >= jt(i) .and. k <= j0(i)) then - f(i,k) = max(f(i,k),f(i,k-1)) - end if - end do - end do - do i = 1,il2g - eps0(i) = f(i,j0(i)) - eps(i,jb(i)) = eps0(i) - end do -! -! This is set to match the Rasch and Kristjansson paper -! - do k = pver,msg + 1,-1 - do i = 1,il2g - if (k >= j0(i) .and. k <= jb(i)) then - eps(i,k) = f(i,j0(i)) - end if - end do - end do - do k = pver,msg + 1,-1 - do i = 1,il2g - if (k < j0(i) .and. k >= jt(i)) eps(i,k) = f(i,k) - end do - end do - - if (zmconv_microp) then - itnum = 2 - else - itnum = 1 - end if - - do iter=1, itnum - - if (zmconv_microp) then - do k = pver,msg + 1,-1 - do i = 1,il2g - cu(i,k) = 0._r8 - loc_conv%qliq(i,k) = 0._r8 - loc_conv%qice(i,k) = 0._r8 - ql(i,k) = 0._r8 - loc_conv%frz(i,k) = 0._r8 - end do - end do - do i = 1,il2g - totpcp(i) = 0._r8 - hu(i,jb(i)) = hmn(i,jb(i)) + cp*tiedke_add - end do - - end if - -! -! specify the updraft mass flux mu, entrainment eu, detrainment du -! and moist static energy hu. -! here and below mu, eu,du, md and ed are all normalized by mb -! - do i = 1,il2g - if (eps0(i) > 0._r8) then - mu(i,jb(i)) = 1._r8 - eu(i,jb(i)) = mu(i,jb(i))/dz(i,jb(i)) - end if - if (zmconv_microp) then - tmplel(i) = lel(i) - else - tmplel(i) = jt(i) - end if - end do - do k = pver,msg + 1,-1 - do i = 1,il2g - if (eps0(i) > 0._r8 .and. (k >= tmplel(i) .and. k < jb(i))) then - zuef(i) = zf(i,k) - zf(i,jb(i)) - rmue(i) = (1._r8/eps0(i))* (exp(eps(i,k+1)*zuef(i))-1._r8)/zuef(i) - mu(i,k) = (1._r8/eps0(i))* (exp(eps(i,k )*zuef(i))-1._r8)/zuef(i) - eu(i,k) = (rmue(i)-mu(i,k+1))/dz(i,k) - du(i,k) = (rmue(i)-mu(i,k))/dz(i,k) - end if - end do - end do - - khighest = pverp - klowest = 1 - do i=1,il2g - khighest = min(khighest,lel(i)) - klowest = max(klowest,jb(i)) - end do - do k = klowest-1,khighest,-1 - do i = 1,il2g - if (k <= jb(i)-1 .and. k >= lel(i) .and. eps0(i) > 0._r8) then - if (mu(i,k) < 0.02_r8) then - hu(i,k) = hmn(i,k) - mu(i,k) = 0._r8 - eu(i,k) = 0._r8 - du(i,k) = mu(i,k+1)/dz(i,k) - else - if (zmconv_microp) then - hu(i,k) = (mu(i,k+1)*hu(i,k+1) + dz(i,k)*(eu(i,k)*hmn(i,k) + & - latice*frz(i,k)))/(mu(i,k)+ dz(i,k)*du(i,k)) - else - hu(i,k) = mu(i,k+1)/mu(i,k)*hu(i,k+1) + & - dz(i,k)/mu(i,k)* (eu(i,k)*hmn(i,k)- du(i,k)*hsat(i,k)) - end if - end if - end if - end do - end do -! -! reset cloud top index beginning from two layers above the -! cloud base (i.e. if cloud is only one layer thick, top is not reset -! - do i=1,il2g - doit(i) = .true. - totfrz(i)= 0._r8 - do k = pver,msg + 1,-1 - totfrz(i)= totfrz(i)+ frz(i,k)*dz(i,k) - end do - end do - do k=klowest-2,khighest-1,-1 - do i=1,il2g - if (doit(i) .and. k <= jb(i)-2 .and. k >= lel(i)-1) then - if (hu(i,k) <= hsthat(i,k) .and. hu(i,k+1) > hsthat(i,k+1) & - .and. mu(i,k) >= 0.02_r8) then - if (hu(i,k)-hsthat(i,k) < -2000._r8) then - jt(i) = k + 1 - doit(i) = .false. - else - jt(i) = k - doit(i) = .false. - end if - else if ( (hu(i,k) > hu(i,jb(i)) .and. totfrz(i)<=0._r8) .or. mu(i,k) < 0.02_r8) then - jt(i) = k + 1 - doit(i) = .false. - end if - end if - end do - end do - - if (iter == 1) jto(:) = jt(:) - - do k = pver,msg + 1,-1 - do i = 1,il2g - if (k >= lel(i) .and. k <= jt(i) .and. eps0(i) > 0._r8) then - mu(i,k) = 0._r8 - eu(i,k) = 0._r8 - du(i,k) = 0._r8 - hu(i,k) = hmn(i,k) - end if - if (k == jt(i) .and. eps0(i) > 0._r8) then - du(i,k) = mu(i,k+1)/dz(i,k) - eu(i,k) = 0._r8 - mu(i,k) = 0._r8 - end if - end do - end do - - do i = 1,il2g - done(i) = .false. - end do - kount = 0 - do k = pver,msg + 2,-1 - do i = 1,il2g - if (k == jb(i) .and. eps0(i) > 0._r8) then - qu(i,k) = q(i,mx(i)) - su(i,k) = (hu(i,k)-rl*qu(i,k))/cp - end if - if (( .not. done(i) .and. k > jt(i) .and. k < jb(i)) .and. eps0(i) > 0._r8) then - su(i,k) = mu(i,k+1)/mu(i,k)*su(i,k+1) + & - dz(i,k)/mu(i,k)* (eu(i,k)-du(i,k))*s(i,k) - qu(i,k) = mu(i,k+1)/mu(i,k)*qu(i,k+1) + dz(i,k)/mu(i,k)* (eu(i,k)*q(i,k)- & - du(i,k)*qst(i,k)) - tu = su(i,k) - grav/cp*zf(i,k) - call qsat_hPa(tu, (p(i,k)+p(i,k-1))/2._r8, estu, qstu) - if (qu(i,k) >= qstu) then - jlcl(i) = k - kount = kount + 1 - done(i) = .true. - end if - end if - end do - if (kount >= il2g) goto 690 - end do -690 continue - do k = msg + 2,pver - do i = 1,il2g - if ((k > jt(i) .and. k <= jlcl(i)) .and. eps0(i) > 0._r8) then - su(i,k) = shat(i,k) + (hu(i,k)-hsthat(i,k))/(cp* (1._r8+gamhat(i,k))) - qu(i,k) = qsthat(i,k) + gamhat(i,k)*(hu(i,k)-hsthat(i,k))/ & - (rl* (1._r8+gamhat(i,k))) - end if - end do - end do - -! compute condensation in updraft - if (zmconv_microp) then - tmplel(:il2g) = jlcl(:il2g)+1 - else - tmplel(:il2g) = jb(:il2g) - end if - - do k = pver,msg + 2,-1 - do i = 1,il2g - if (k >= jt(i) .and. k < tmplel(i) .and. eps0(i) > 0._r8) then - if (zmconv_microp) then - cu(i,k) = ((mu(i,k)*su(i,k)-mu(i,k+1)*su(i,k+1))/ & - dz(i,k)- eu(i,k)*s(i,k)+du(i,k)*su(i,k))/(rl/cp) & - - latice*frz(i,k)/rl - else - - cu(i,k) = ((mu(i,k)*su(i,k)-mu(i,k+1)*su(i,k+1))/ & - dz(i,k)- (eu(i,k)-du(i,k))*s(i,k))/(rl/cp) - end if - if (k == jt(i)) cu(i,k) = 0._r8 - cu(i,k) = max(0._r8,cu(i,k)) - end if - end do - end do - - - if (zmconv_microp) then - - tug(:il2g,:) = t(:il2g,:) - fice(:,:) = 0._r8 - - do k = pver, msg+2, -1 - do i = 1, il2g - tug(i,k) = su(i,k) - grav/cp*zf(i,k) - end do - end do - - do k = 1, pver-1 - do i = 1, il2g - - if (tug(i,k+1) > 273.15_r8) then - ! If warmer than tmax then water phase - fice(i,k) = 0._r8 - - else if (tug(i,k+1) < 233.15_r8) then - ! If colder than tmin then ice phase - fice(i,k) = 1._r8 - - else - ! Otherwise mixed phase, with ice fraction decreasing linearly - ! from tmin to tmax - fice(i,k) =(273.15_r8 - tug(i,k+1)) / 40._r8 - end if - end do - end do - - do k = 1, pver - do i = 1,il2g - loc_conv%cmei(i,k) = cu(i,k)* fice(i,k) - loc_conv%cmel(i,k) = cu(i,k) * (1._r8-fice(i,k)) - end do - end do - - call zm_mphy(su, qu, mu, du, eu, loc_conv%cmel, loc_conv%cmei, zf, p, t, q, & - eps0, jb, jt, jlcl, msg, il2g, grav, cp, rd, aero, gamhat, & - loc_conv%qliq, loc_conv%qice, loc_conv%qnl, loc_conv%qni, qcde, loc_conv%qide, & - loc_conv%qncde, loc_conv%qnide, rprd, loc_conv%sprd, frz, & - loc_conv%wu, loc_conv%qrain, loc_conv%qsnow, loc_conv%qnr, loc_conv%qns, & - loc_conv%autolm, loc_conv%accrlm, loc_conv%bergnm, loc_conv%fhtimm, loc_conv%fhtctm, & - loc_conv%fhmlm, loc_conv%hmpim, loc_conv%accslm, loc_conv%dlfm, loc_conv%autoln, & - loc_conv%accrln, loc_conv%bergnn, loc_conv%fhtimn, loc_conv%fhtctn, & - loc_conv%fhmln, loc_conv%accsln, loc_conv%activn, loc_conv%dlfn, loc_conv%autoim, & - loc_conv%accsim, loc_conv%difm, loc_conv%nuclin, loc_conv%autoin, & - loc_conv%accsin, loc_conv%hmpin, loc_conv%difn, loc_conv%trspcm, loc_conv%trspcn, & - loc_conv%trspim, loc_conv%trspin, loc_conv%lambdadpcu, loc_conv%mudpcu ) - - - do k = pver,msg + 2,-1 - do i = 1,il2g - ql(i,k) = loc_conv%qliq(i,k)+ loc_conv%qice(i,k) - loc_conv%frz(i,k) = frz(i,k) - end do - end do - - do i = 1,il2g - if (iter == 2 .and. jt(i)> jto(i)) then - do k = jt(i), jto(i), -1 - loc_conv%frz(i,k) = 0.0_r8 - cu(i,k)=0.0_r8 - end do - end if - end do - - - do k = pver,msg + 2,-1 - do i = 1,il2g - if (k >= jt(i) .and. k < jb(i) .and. eps0(i) > 0._r8 .and. mu(i,k) >= 0.0_r8) then - totpcp(i) = totpcp(i) + dz(i,k)*(cu(i,k)-du(i,k)*(qcde(i,k+1)+loc_conv%qide(i,k+1) )) - end if - end do - end do - - do k = msg + 2,pver - do i = 1,il2g - if ((k > jt(i) .and. k <= jlcl(i)) .and. eps0(i) > 0._r8) then - if (iter == 1) tvuo(i,k)= (su(i,k) - grav/cp*zf(i,k))*(1._r8+0.608_r8*qu(i,k)) - if (iter == 2 .and. k > max(jt(i),jto(i)) ) then - tvu(i,k) = (su(i,k) - grav/cp*zf(i,k))*(1._r8 +0.608_r8*qu(i,k)) - loc_conv%dcape(i) = loc_conv%dcape(i)+ rd*(tvu(i,k)-tvuo(i,k))*log(p(i,k)/p(i,k-1)) - end if - end if - end do - end do - - else ! no convective microphysics - -! compute condensed liquid, rain production rate -! accumulate total precipitation (condensation - detrainment of liquid) -! Note ql1 = ql(k) + rprd(k)*dz(k)/mu(k) -! The differencing is somewhat strange (e.g. du(i,k)*ql(i,k+1)) but is -! consistently applied. -! mu, ql are interface quantities -! cu, du, eu, rprd are midpoint quantites - - do k = pver,msg + 2,-1 - do i = 1,il2g - rprd(i,k) = 0._r8 - if (k >= jt(i) .and. k < jb(i) .and. eps0(i) > 0._r8 .and. mu(i,k) >= 0.0_r8) then - if (mu(i,k) > 0._r8) then - ql1 = 1._r8/mu(i,k)* (mu(i,k+1)*ql(i,k+1)- & - dz(i,k)*du(i,k)*ql(i,k+1)+dz(i,k)*cu(i,k)) - ql(i,k) = ql1/ (1._r8+dz(i,k)*c0mask(i)) - else - ql(i,k) = 0._r8 - end if - totpcp(i) = totpcp(i) + dz(i,k)*(cu(i,k)-du(i,k)*ql(i,k+1)) - rprd(i,k) = c0mask(i)*mu(i,k)*ql(i,k) - qcde(i,k) = ql(i,k) - - if (zmconv_microp) then - loc_conv%qide(i,k) = 0._r8 - loc_conv%qncde(i,k) = 0._r8 - loc_conv%qnide(i,k) = 0._r8 - loc_conv%sprd(i,k) = 0._r8 - end if - - end if - end do - end do -! - end if ! zmconv_microp - - end do !iter -! -! specify downdraft properties (no downdrafts if jd.ge.jb). -! scale down downward mass flux profile so that net flux -! (up-down) at cloud base in not negative. -! - do i = 1,il2g -! -! in normal downdraft strength run alfa=0.2. In test4 alfa=0.1 -! - alfa(i) = 0.1_r8 - jt(i) = min(jt(i),jb(i)-1) - jd(i) = max(j0(i),jt(i)+1) - jd(i) = min(jd(i),jb(i)) - hd(i,jd(i)) = hmn(i,jd(i)-1) - if (jd(i) < jb(i) .and. eps0(i) > 0._r8) then - epsm(i) = eps0(i) - md(i,jd(i)) = -alfa(i)*epsm(i)/eps0(i) - end if - end do - do k = msg + 1,pver - do i = 1,il2g - if ((k > jd(i) .and. k <= jb(i)) .and. eps0(i) > 0._r8) then - zdef(i) = zf(i,jd(i)) - zf(i,k) - md(i,k) = -alfa(i)/ (2._r8*eps0(i))*(exp(2._r8*epsm(i)*zdef(i))-1._r8)/zdef(i) - end if - end do - end do - - do k = msg + 1,pver - do i = 1,il2g - if ((k >= jt(i) .and. k <= jb(i)) .and. eps0(i) > 0._r8 .and. jd(i) < jb(i)) then - ratmjb(i) = min(abs(mu(i,jb(i))/md(i,jb(i))),1._r8) - md(i,k) = md(i,k)*ratmjb(i) - end if - end do - end do - - small = 1.e-20_r8 - do k = msg + 1,pver - do i = 1,il2g - if ((k >= jt(i) .and. k <= pver) .and. eps0(i) > 0._r8) then - ed(i,k-1) = (md(i,k-1)-md(i,k))/dz(i,k-1) - mdt = min(md(i,k),-small) - hd(i,k) = (md(i,k-1)*hd(i,k-1) - dz(i,k-1)*ed(i,k-1)*hmn(i,k-1))/mdt - end if - end do - end do -! -! calculate updraft and downdraft properties. -! - do k = msg + 2,pver - do i = 1,il2g - if ((k >= jd(i) .and. k <= jb(i)) .and. eps0(i) > 0._r8 .and. jd(i) < jb(i)) then - qds(i,k) = qsthat(i,k) + gamhat(i,k)*(hd(i,k)-hsthat(i,k))/ & - (rl*(1._r8 + gamhat(i,k))) - end if - end do - end do - - do i = 1,il2g - qd(i,jd(i)) = qds(i,jd(i)) - sd(i,jd(i)) = (hd(i,jd(i)) - rl*qd(i,jd(i)))/cp - end do -! - do k = msg + 2,pver - do i = 1,il2g - if (k >= jd(i) .and. k < jb(i) .and. eps0(i) > 0._r8) then - qd(i,k+1) = qds(i,k+1) - evp(i,k) = -ed(i,k)*q(i,k) + (md(i,k)*qd(i,k)-md(i,k+1)*qd(i,k+1))/dz(i,k) - evp(i,k) = max(evp(i,k),0._r8) - mdt = min(md(i,k+1),-small) - if (zmconv_microp) then - evp(i,k) = min(evp(i,k),rprd(i,k)) - end if - sd(i,k+1) = ((rl/cp*evp(i,k)-ed(i,k)*s(i,k))*dz(i,k) + md(i,k)*sd(i,k))/mdt - totevp(i) = totevp(i) - dz(i,k)*ed(i,k)*q(i,k) - end if - end do - end do - do i = 1,il2g -!*guang totevp(i) = totevp(i) + md(i,jd(i))*q(i,jd(i)-1) - - totevp(i) = totevp(i) + md(i,jd(i))*qd(i,jd(i)) - md(i,jb(i))*qd(i,jb(i)) - end do -!!$ if (.true.) then - if (.false.) then - do i = 1,il2g - k = jb(i) - if (eps0(i) > 0._r8) then - evp(i,k) = -ed(i,k)*q(i,k) + (md(i,k)*qd(i,k))/dz(i,k) - evp(i,k) = max(evp(i,k),0._r8) - totevp(i) = totevp(i) - dz(i,k)*ed(i,k)*q(i,k) - end if - end do - endif - - do i = 1,il2g - totpcp(i) = max(totpcp(i),0._r8) - totevp(i) = max(totevp(i),0._r8) - end do -! - do k = msg + 2,pver - do i = 1,il2g - if (totevp(i) > 0._r8 .and. totpcp(i) > 0._r8) then - md(i,k) = md (i,k)*min(1._r8, totpcp(i)/(totevp(i)+totpcp(i))) - ed(i,k) = ed (i,k)*min(1._r8, totpcp(i)/(totevp(i)+totpcp(i))) - evp(i,k) = evp(i,k)*min(1._r8, totpcp(i)/(totevp(i)+totpcp(i))) - else - md(i,k) = 0._r8 - ed(i,k) = 0._r8 - evp(i,k) = 0._r8 - end if -! cmeg is the cloud water condensed - rain water evaporated -! rprd is the cloud water converted to rain - (rain evaporated) - cmeg(i,k) = cu(i,k) - evp(i,k) - rprd(i,k) = rprd(i,k)-evp(i,k) - end do - end do - -! compute the net precipitation flux across interfaces - pflx(:il2g,1) = 0._r8 - do k = 2,pverp - do i = 1,il2g - pflx(i,k) = pflx(i,k-1) + rprd(i,k-1)*dz(i,k-1) - end do - end do -! - do k = msg + 1,pver - do i = 1,il2g - mc(i,k) = mu(i,k) + md(i,k) - end do - end do -! - return -end subroutine cldprp - -subroutine closure(lchnk , & - q ,t ,p ,z ,s , & - tp ,qs ,qu ,su ,mc , & - du ,mu ,md ,qd ,sd , & - qhat ,shat ,dp ,qstp ,zf , & - ql ,dsubcld ,mb ,cape ,tl , & - lcl ,lel ,jt ,mx ,il1g , & - il2g ,rd ,grav ,cp ,rl , & - msg ,capelmt ) -!----------------------------------------------------------------------- -! -! Purpose: -! -! -! Method: -! -! -! -! Author: G. Zhang and collaborators. CCM contact:P. Rasch -! This is contributed code not fully standardized by the CCM core group. -! -! this code is very much rougher than virtually anything else in the CCM -! We expect to release cleaner code in a future release -! -! the documentation has been enhanced to the degree that we are able -! -!----------------------------------------------------------------------- - -! -!-----------------------------Arguments--------------------------------- -! - integer, intent(in) :: lchnk ! chunk identifier - - real(r8), intent(inout) :: q(pcols,pver) ! spec humidity - real(r8), intent(inout) :: t(pcols,pver) ! temperature - real(r8), intent(inout) :: p(pcols,pver) ! pressure (mb) - real(r8), intent(inout) :: mb(pcols) ! cloud base mass flux - real(r8), intent(in) :: z(pcols,pver) ! height (m) - real(r8), intent(in) :: s(pcols,pver) ! normalized dry static energy - real(r8), intent(in) :: tp(pcols,pver) ! parcel temp - real(r8), intent(in) :: qs(pcols,pver) ! sat spec humidity - real(r8), intent(in) :: qu(pcols,pver) ! updraft spec. humidity - real(r8), intent(in) :: su(pcols,pver) ! normalized dry stat energy of updraft - real(r8), intent(in) :: mc(pcols,pver) ! net convective mass flux - real(r8), intent(in) :: du(pcols,pver) ! detrainment from updraft - real(r8), intent(in) :: mu(pcols,pver) ! mass flux of updraft - real(r8), intent(in) :: md(pcols,pver) ! mass flux of downdraft - real(r8), intent(in) :: qd(pcols,pver) ! spec. humidity of downdraft - real(r8), intent(in) :: sd(pcols,pver) ! dry static energy of downdraft - real(r8), intent(in) :: qhat(pcols,pver) ! environment spec humidity at interfaces - real(r8), intent(in) :: shat(pcols,pver) ! env. normalized dry static energy at intrfcs - real(r8), intent(in) :: dp(pcols,pver) ! pressure thickness of layers - real(r8), intent(in) :: qstp(pcols,pver) ! spec humidity of parcel - real(r8), intent(in) :: zf(pcols,pver+1) ! height of interface levels - real(r8), intent(in) :: ql(pcols,pver) ! liquid water mixing ratio - - real(r8), intent(in) :: cape(pcols) ! available pot. energy of column - real(r8), intent(in) :: tl(pcols) - real(r8), intent(in) :: dsubcld(pcols) ! thickness of subcloud layer - - integer, intent(in) :: lcl(pcols) ! index of lcl - integer, intent(in) :: lel(pcols) ! index of launch leve - integer, intent(in) :: jt(pcols) ! top of updraft - integer, intent(in) :: mx(pcols) ! base of updraft -! -!--------------------------Local variables------------------------------ -! - real(r8) dtpdt(pcols,pver) - real(r8) dqsdtp(pcols,pver) - real(r8) dtmdt(pcols,pver) - real(r8) dqmdt(pcols,pver) - real(r8) dboydt(pcols,pver) - real(r8) thetavp(pcols,pver) - real(r8) thetavm(pcols,pver) - - real(r8) dtbdt(pcols),dqbdt(pcols),dtldt(pcols) - real(r8) beta - real(r8) capelmt - real(r8) cp - real(r8) dadt(pcols) - real(r8) debdt - real(r8) dltaa - real(r8) eb - real(r8) grav - - integer i - integer il1g - integer il2g - integer k, kmin, kmax - integer msg - - real(r8) rd - real(r8) rl -! change of subcloud layer properties due to convection is -! related to cumulus updrafts and downdrafts. -! mc(z)=f(z)*mb, mub=betau*mb, mdb=betad*mb are used -! to define betau, betad and f(z). -! note that this implies all time derivatives are in effect -! time derivatives per unit cloud-base mass flux, i.e. they -! have units of 1/mb instead of 1/sec. -! - do i = il1g,il2g - mb(i) = 0._r8 - eb = p(i,mx(i))*q(i,mx(i))/ (eps1+q(i,mx(i))) - dtbdt(i) = (1._r8/dsubcld(i))* (mu(i,mx(i))*(shat(i,mx(i))-su(i,mx(i)))+ & - md(i,mx(i))* (shat(i,mx(i))-sd(i,mx(i)))) - dqbdt(i) = (1._r8/dsubcld(i))* (mu(i,mx(i))*(qhat(i,mx(i))-qu(i,mx(i)))+ & - md(i,mx(i))* (qhat(i,mx(i))-qd(i,mx(i)))) - debdt = eps1*p(i,mx(i))/ (eps1+q(i,mx(i)))**2*dqbdt(i) - dtldt(i) = -2840._r8* (3.5_r8/t(i,mx(i))*dtbdt(i)-debdt/eb)/ & - (3.5_r8*log(t(i,mx(i)))-log(eb)-4.805_r8)**2 - end do -! -! dtmdt and dqmdt are cumulus heating and drying. -! - do k = msg + 1,pver - do i = il1g,il2g - dtmdt(i,k) = 0._r8 - dqmdt(i,k) = 0._r8 - end do - end do -! - do k = msg + 1,pver - 1 - do i = il1g,il2g - if (k == jt(i)) then - dtmdt(i,k) = (1._r8/dp(i,k))*(mu(i,k+1)* (su(i,k+1)-shat(i,k+1)- & - rl/cp*ql(i,k+1))+md(i,k+1)* (sd(i,k+1)-shat(i,k+1))) - dqmdt(i,k) = (1._r8/dp(i,k))*(mu(i,k+1)* (qu(i,k+1)- & - qhat(i,k+1)+ql(i,k+1))+md(i,k+1)*(qd(i,k+1)-qhat(i,k+1))) - end if - end do - end do -! - beta = 0._r8 - do k = msg + 1,pver - 1 - do i = il1g,il2g - if (k > jt(i) .and. k < mx(i)) then - dtmdt(i,k) = (mc(i,k)* (shat(i,k)-s(i,k))+mc(i,k+1)* (s(i,k)-shat(i,k+1)))/ & - dp(i,k) - rl/cp*du(i,k)*(beta*ql(i,k)+ (1-beta)*ql(i,k+1)) -! dqmdt(i,k)=(mc(i,k)*(qhat(i,k)-q(i,k)) -! 1 +mc(i,k+1)*(q(i,k)-qhat(i,k+1)))/dp(i,k) -! 2 +du(i,k)*(qs(i,k)-q(i,k)) -! 3 +du(i,k)*(beta*ql(i,k)+(1-beta)*ql(i,k+1)) - - dqmdt(i,k) = (mu(i,k+1)* (qu(i,k+1)-qhat(i,k+1)+cp/rl* (su(i,k+1)-s(i,k)))- & - mu(i,k)* (qu(i,k)-qhat(i,k)+cp/rl*(su(i,k)-s(i,k)))+md(i,k+1)* & - (qd(i,k+1)-qhat(i,k+1)+cp/rl*(sd(i,k+1)-s(i,k)))-md(i,k)* & - (qd(i,k)-qhat(i,k)+cp/rl*(sd(i,k)-s(i,k))))/dp(i,k) + & - du(i,k)* (beta*ql(i,k)+(1-beta)*ql(i,k+1)) - end if - end do - end do -! - do k = msg + 1,pver - do i = il1g,il2g - if (k >= lel(i) .and. k <= lcl(i)) then - thetavp(i,k) = tp(i,k)* (1000._r8/p(i,k))** (rd/cp)*(1._r8+1.608_r8*qstp(i,k)-q(i,mx(i))) - thetavm(i,k) = t(i,k)* (1000._r8/p(i,k))** (rd/cp)*(1._r8+0.608_r8*q(i,k)) - dqsdtp(i,k) = qstp(i,k)* (1._r8+qstp(i,k)/eps1)*eps1*rl/(rd*tp(i,k)**2) -! -! dtpdt is the parcel temperature change due to change of -! subcloud layer properties during convection. -! - dtpdt(i,k) = tp(i,k)/ (1._r8+rl/cp* (dqsdtp(i,k)-qstp(i,k)/tp(i,k)))* & - (dtbdt(i)/t(i,mx(i))+rl/cp* (dqbdt(i)/tl(i)-q(i,mx(i))/ & - tl(i)**2*dtldt(i))) -! -! dboydt is the integrand of cape change. -! - dboydt(i,k) = ((dtpdt(i,k)/tp(i,k)+1._r8/(1._r8+1.608_r8*qstp(i,k)-q(i,mx(i)))* & - (1.608_r8 * dqsdtp(i,k) * dtpdt(i,k) -dqbdt(i))) - (dtmdt(i,k)/t(i,k)+0.608_r8/ & - (1._r8+0.608_r8*q(i,k))*dqmdt(i,k)))*grav*thetavp(i,k)/thetavm(i,k) - end if - end do - end do -! - do k = msg + 1,pver - do i = il1g,il2g - if (k > lcl(i) .and. k < mx(i)) then - thetavp(i,k) = tp(i,k)* (1000._r8/p(i,k))** (rd/cp)*(1._r8+0.608_r8*q(i,mx(i))) - thetavm(i,k) = t(i,k)* (1000._r8/p(i,k))** (rd/cp)*(1._r8+0.608_r8*q(i,k)) -! -! dboydt is the integrand of cape change. -! - dboydt(i,k) = (dtbdt(i)/t(i,mx(i))+0.608_r8/ (1._r8+0.608_r8*q(i,mx(i)))*dqbdt(i)- & - dtmdt(i,k)/t(i,k)-0.608_r8/ (1._r8+0.608_r8*q(i,k))*dqmdt(i,k))* & - grav*thetavp(i,k)/thetavm(i,k) - end if - end do - end do - -! -! buoyant energy change is set to 2/3*excess cape per 3 hours -! - dadt(il1g:il2g) = 0._r8 - kmin = minval(lel(il1g:il2g)) - kmax = maxval(mx(il1g:il2g)) - 1 - do k = kmin, kmax - do i = il1g,il2g - if ( k >= lel(i) .and. k <= mx(i) - 1) then - dadt(i) = dadt(i) + dboydt(i,k)* (zf(i,k)-zf(i,k+1)) - endif - end do - end do - do i = il1g,il2g - dltaa = -1._r8* (cape(i)-capelmt) - if (dadt(i) /= 0._r8) mb(i) = max(dltaa/tau/dadt(i),0._r8) - end do -! - return -end subroutine closure - -subroutine q1q2_pjr(lchnk , & - dqdt ,dsdt ,q ,qs ,qu , & - su ,du ,qhat ,shat ,dp , & - mu ,md ,sd ,qd ,ql , & - dsubcld ,jt ,mx ,il1g ,il2g , & - cp ,rl ,msg , & - dl ,evp ,cu , & - loc_conv) - - - implicit none - -!----------------------------------------------------------------------- -! -! Purpose: -! -! -! Method: -! -! -! -! Author: phil rasch dec 19 1995 -! -!----------------------------------------------------------------------- - - - real(r8), intent(in) :: cp - - integer, intent(in) :: lchnk ! chunk identifier - integer, intent(in) :: il1g - integer, intent(in) :: il2g - integer, intent(in) :: msg - - real(r8), intent(in) :: q(pcols,pver) - real(r8), intent(in) :: qs(pcols,pver) - real(r8), intent(in) :: qu(pcols,pver) - real(r8), intent(in) :: su(pcols,pver) - real(r8), intent(in) :: du(pcols,pver) - real(r8), intent(in) :: qhat(pcols,pver) - real(r8), intent(in) :: shat(pcols,pver) - real(r8), intent(in) :: dp(pcols,pver) - real(r8), intent(in) :: mu(pcols,pver) - real(r8), intent(in) :: md(pcols,pver) - real(r8), intent(in) :: sd(pcols,pver) - real(r8), intent(in) :: qd(pcols,pver) - real(r8), intent(in) :: ql(pcols,pver) - real(r8), intent(in) :: evp(pcols,pver) - real(r8), intent(in) :: cu(pcols,pver) - real(r8), intent(in) :: dsubcld(pcols) - - real(r8),intent(out) :: dqdt(pcols,pver),dsdt(pcols,pver) - real(r8),intent(out) :: dl(pcols,pver) - - type(zm_conv_t) :: loc_conv - - integer kbm - integer ktm - integer jt(pcols) - integer mx(pcols) -! -! work fields: -! - integer i - integer k - - real(r8) emc - real(r8) rl -!------------------------------------------------------------------- - do k = msg + 1,pver - do i = il1g,il2g - dsdt(i,k) = 0._r8 - dqdt(i,k) = 0._r8 - dl(i,k) = 0._r8 - end do - end do - - if (zmconv_microp) then - do k = msg + 1,pver - do i = il1g,il2g - loc_conv%di(i,k) = 0._r8 - loc_conv%dnl(i,k) = 0._r8 - loc_conv%dni(i,k) = 0._r8 - end do - end do - end if -! -! find the highest level top and bottom levels of convection -! - ktm = pver - kbm = pver - do i = il1g, il2g - ktm = min(ktm,jt(i)) - kbm = min(kbm,mx(i)) - end do - - do k = ktm,pver-1 - do i = il1g,il2g - emc = -cu (i,k) & ! condensation in updraft - +evp(i,k) ! evaporating rain in downdraft - - dsdt(i,k) = -rl/cp*emc & - + (+mu(i,k+1)* (su(i,k+1)-shat(i,k+1)) & - -mu(i,k)* (su(i,k)-shat(i,k)) & - +md(i,k+1)* (sd(i,k+1)-shat(i,k+1)) & - -md(i,k)* (sd(i,k)-shat(i,k)) & - )/dp(i,k) - - if (zmconv_microp) dsdt(i,k) = dsdt(i,k) + latice/cp*loc_conv%frz(i,k) - - dqdt(i,k) = emc + & - (+mu(i,k+1)* (qu(i,k+1)-qhat(i,k+1)) & - -mu(i,k)* (qu(i,k)-qhat(i,k)) & - +md(i,k+1)* (qd(i,k+1)-qhat(i,k+1)) & - -md(i,k)* (qd(i,k)-qhat(i,k)) & - )/dp(i,k) - - dl(i,k) = du(i,k)*ql(i,k+1) - - if (zmconv_microp) then - loc_conv%di(i,k) = du(i,k)*loc_conv%qide(i,k+1) - loc_conv%dnl(i,k) = du(i,k)*loc_conv%qncde(i,k+1) - loc_conv%dni(i,k) = du(i,k)*loc_conv%qnide(i,k+1) - end if - - end do - end do - -! - do k = kbm,pver - do i = il1g,il2g - if (k == mx(i)) then - dsdt(i,k) = (1._r8/dsubcld(i))* & - (-mu(i,k)* (su(i,k)-shat(i,k)) & - -md(i,k)* (sd(i,k)-shat(i,k)) & - ) - dqdt(i,k) = (1._r8/dsubcld(i))* & - (-mu(i,k)*(qu(i,k)-qhat(i,k)) & - -md(i,k)*(qd(i,k)-qhat(i,k)) & - ) - else if (k > mx(i)) then - dsdt(i,k) = dsdt(i,k-1) - dqdt(i,k) = dqdt(i,k-1) - end if - end do - end do -! - return -end subroutine q1q2_pjr - -subroutine buoyan_dilute(lchnk ,ncol , & - q ,t ,p ,z ,pf , & - tp ,qstp ,tl ,rl ,cape , & - pblt ,lcl ,lel ,lon ,mx , & - rd ,grav ,cp ,msg , & - zi ,zs ,tpert ,org , landfrac) -!----------------------------------------------------------------------- -! -! Purpose: -! Calculates CAPE the lifting condensation level and the convective top -! where buoyancy is first -ve. -! -! Method: Calculates the parcel temperature based on a simple constant -! entraining plume model. CAPE is integrated from buoyancy. -! 09/09/04 - Simplest approach using an assumed entrainment rate for -! testing (dmpdp). -! 08/04/05 - Swap to convert dmpdz to dmpdp -! -! SCAM Logical Switches - DILUTE:RBN - Now Disabled -! --------------------- -! switch(1) = .T. - Uses the dilute parcel calculation to obtain tendencies. -! switch(2) = .T. - Includes entropy/q changes due to condensate loss and freezing. -! switch(3) = .T. - Adds the PBL Tpert for the parcel temperature at all levels. -! -! References: -! Raymond and Blythe (1992) JAS -! -! Author: -! Richard Neale - September 2004 -! -!----------------------------------------------------------------------- - implicit none -!----------------------------------------------------------------------- -! -! input arguments -! - integer, intent(in) :: lchnk ! chunk identifier - integer, intent(in) :: ncol ! number of atmospheric columns - - real(r8), intent(in) :: q(pcols,pver) ! spec. humidity - real(r8), intent(in) :: t(pcols,pver) ! temperature - real(r8), intent(in) :: p(pcols,pver) ! pressure - real(r8), intent(in) :: z(pcols,pver) ! height - real(r8), intent(in) :: pf(pcols,pver+1) ! pressure at interfaces - real(r8), intent(in) :: pblt(pcols) ! index of pbl depth - real(r8), intent(in) :: tpert(pcols) ! perturbation temperature by pbl processes - -! Use z interface/surface relative values for PBL parcel calculations. - real(r8), intent(in) :: zi(pcols,pver+1) - real(r8), intent(in) :: zs(pcols) - -! -! output arguments -! - real(r8), intent(out) :: tp(pcols,pver) ! parcel temperature - real(r8), intent(out) :: qstp(pcols,pver) ! saturation mixing ratio of parcel (only above lcl, just q below). - real(r8), intent(out) :: tl(pcols) ! parcel temperature at lcl - real(r8), intent(out) :: cape(pcols) ! convective aval. pot. energy. - integer lcl(pcols) ! - integer lel(pcols) ! - integer lon(pcols) ! level of onset of deep convection - integer mx(pcols) ! level of max moist static energy - - real(r8), pointer :: org(:,:) ! organization parameter - real(r8), intent(in) :: landfrac(pcols) -! -!--------------------------Local Variables------------------------------ -! - real(r8) capeten(pcols,5) ! provisional value of cape - real(r8) tv(pcols,pver) ! - real(r8) tpv(pcols,pver) ! - real(r8) buoy(pcols,pver) - - real(r8) a1(pcols) - real(r8) a2(pcols) - real(r8) estp(pcols) - real(r8) pl(pcols) - real(r8) plexp(pcols) - real(r8) hmax(pcols) - real(r8) hmn(pcols) - real(r8) y(pcols) - - logical plge600(pcols) - integer knt(pcols) - integer lelten(pcols,5) - - - - -! Parcel property variables - - real(r8) :: hmn_lev(pcols,pver) ! Vertical profile of moist static energy for each column - real(r8) :: dp_lev(pcols,pver) ! Level dpressure between interfaces - real(r8) :: hmn_zdp(pcols,pver) ! Integrals of hmn_lev*dp_lev at each level - real(r8) :: q_zdp(pcols,pver) ! Integrals of q*dp_lev at each level - real(r8) :: dp_zfrac ! Fraction of vertical grid box below mixing top (usually pblt) - real(r8) :: parcel_dz(pcols) ! Depth of parcel mixing (usually parcel_hscale*parcel_dz) - real(r8) :: parcel_ztop(pcols) ! Height of parcel mixing (usually parcel_ztop+zm(nlev)) - real(r8) :: parcel_dp(pcols) ! Pressure integral over parcel mixing depth (usually pblt) - real(r8) :: parcel_hdp(pcols) ! Pressure*MSE integral over parcel mixing depth (usually pblt) - real(r8) :: parcel_qdp(pcols) ! Pressure*q integral over parcel mixing depth (usually pblt) - real(r8) :: pbl_dz(pcols) ! Previously diagnosed PBL height - real(r8) :: hpar(pcols) ! Initial MSE of the parcel - real(r8) :: qpar(pcols) ! Initial humidity of the parcel - real(r8) :: ql(pcols) ! Initial parcel humidity (for ientropy routine) - integer :: ipar ! Index for top of parcel mixing/launch level. - - - - - real(r8) cp - real(r8) e - real(r8) grav - - integer i - integer k - integer msg - integer n - - real(r8) rd - real(r8) rl - - -! Scaling of PBL height to give parcel mixing length for lparcel_pbl=True - - real(r8), parameter :: parcel_hscale = 0.5_r8 - - -! -!----------------------------------------------------------------------- -! - do n = 1,5 - do i = 1,ncol - lelten(i,n) = pver - capeten(i,n) = 0._r8 - end do - end do -! - do i = 1,ncol - lon(i) = pver - knt(i) = 0 - lel(i) = pver - mx(i) = lon(i) - cape(i) = 0._r8 - hmax(i) = 0._r8 - pbl_dz(i) = z(i,nint(pblt(i)))-zs(i) ! mid-point z (zm) reference to PBL depth - parcel_dz(i) = max(zi(i,pver),parcel_hscale*pbl_dz(i)) ! PBL mixing depth [parcel_hscale*Boundary, but no thinner than zi(i,pver)] - parcel_ztop(i) = parcel_dz(i)+zs(i) ! PBL mixing height ztop this is wrt zs=0 - parcel_hdp(i) = 0._r8 - parcel_dp(i) = 0._r8 - parcel_qdp(i) = 0._r8 - hpar(i) = 0._r8 - qpar(i) = 0._r8 - end do - - tp(:ncol,:) = t(:ncol,:) - qstp(:ncol,:) = q(:ncol,:) - hmn_lev(:ncol,:) = 0._r8 - - - -!!! Initialize tv and buoy for output. -!!! tv=tv : tpv=tpv : qstp=q : buoy=0. - tv(:ncol,:) = t(:ncol,:) *(1._r8+1.608_r8*q(:ncol,:))/ (1._r8+q(:ncol,:)) - tpv(:ncol,:) = tv(:ncol,:) - buoy(:ncol,:) = 0._r8 - - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -! Mix the parcel over a certain dp or dz and take the launch level as the top level -! of this mixing region and the parcel properties as this mixed value -! Should be well mixed by other processes in the very near PBL. -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - - -if (lparcel_pbl) then - -! Vertical profile of MSE and pressure weighted of the same. - hmn_lev(:ncol,1:pver) = cp*t(:ncol,1:pver) + grav*z(:ncol,1:pver) + rl*q(:ncol,1:pver) - dp_lev(:ncol,1:pver) = pf(:ncol,2:pver+1)-pf(:ncol,1:pver) - hmn_zdp(:ncol,1:pver) = hmn_lev(:ncol,1:pver)*dp_lev(:ncol,1:pver) - q_zdp(:ncol,1:pver) = q(:ncol,1:pver)*dp_lev(:ncol,1:pver) - - -! Mix profile over vertical length scale of 0.5*PBLH. - - do i = 1,ncol ! Loop columns - do k = pver,msg + 1,-1 - - if (zi(i,k+1)<= parcel_dz(i)) then ! Has to be relative to near-surface layer center elevation - ipar = k - - if (k == pver) then ! Always at least the full depth of lowest model layer. - dp_zfrac = 1._r8 - else - ! Fraction of grid cell depth (mostly 1, except when parcel_ztop is in between levels. - dp_zfrac = min(1._r8,(parcel_dz(i)-zi(i,k+1))/(zi(i,k)-zi(i,k+1))) - end if - - parcel_hdp(i) = parcel_hdp(i)+hmn_zdp(i,k)*dp_zfrac ! Sum parcel profile up to a certain level. - parcel_qdp(i) = parcel_qdp(i)+q_zdp(i,k)*dp_zfrac ! Sum parcel profile up to a certain level. - parcel_dp(i) = parcel_dp(i)+dp_lev(i,k)*dp_zfrac ! SUM dp's for weighting of parcel_hdp - - end if - end do - hpar(i) = parcel_hdp(i)/parcel_dp(i) - qpar(i) = parcel_qdp(i)/parcel_dp(i) - mx(i) = ipar - end do - -else ! Default method finding level of MSE maximum (nlev sensitive though) - ! - ! set "launching" level(mx) to be at maximum moist static energy. - ! search for this level stops at planetary boundary layer top. - ! - do k = pver,msg + 1,-1 - do i = 1,ncol - hmn(i) = cp*t(i,k) + grav*z(i,k) + rl*q(i,k) - if (k >= nint(pblt(i)) .and. k <= lon(i) .and. hmn(i) > hmax(i)) then - hmax(i) = hmn(i) - mx(i) = k - end if - end do - end do - -end if ! Default method of determining parcel launch properties. - - - - - -! LCL dilute calculation - initialize to mx(i) -! Determine lcl in parcel_dilute and get pl,tl after parcel_dilute -! Original code actually sets LCL as level above wher condensate forms. -! Therefore in parcel_dilute lcl(i) will be at first level where qsmix < qtmix. - -if (lparcel_pbl) then - -! For parcel dilute need to invert hpar and qpar. -! Now need to supply ql(i) as it is mixed parcel version, just q(i,max(i)) in default - - do i = 1,ncol ! Initialise LCL variables. - lcl(i) = mx(i) - tl(i) = (hpar(i)-rl*qpar(i)-grav*parcel_ztop(i))/cp - ql(i) = qpar(i) - pl(i) = p(i,mx(i)) - end do - -else - - do i = 1,ncol - lcl(i) = mx(i) - tl(i) = t(i,mx(i)) - ql(i) = q(i,mx(i)) - pl(i) = p(i,mx(i)) - end do - -end if ! Mixed parcel properties - - - -! -! main buoyancy calculation. -! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!!! DILUTE PLUME CALCULATION USING ENTRAINING PLUME !!! -!!! RBN 9/9/04 !!! - - call parcel_dilute(lchnk, ncol, msg, mx, p, t, q, & - tpert, tp, tpv, qstp, pl, tl, ql, lcl, & - org, landfrac) - - -! If lcl is above the nominal level of non-divergence (600 mbs), -! no deep convection is permitted (ensuing calculations -! skipped and cape retains initialized value of zero). -! - do i = 1,ncol - plge600(i) = pl(i).ge.600._r8 ! Just change to always allow buoy calculation. - end do - -! -! Main buoyancy calculation. -! - do k = pver,msg + 1,-1 - do i=1,ncol - if (k <= mx(i) .and. plge600(i)) then ! Define buoy from launch level to cloud top. - tv(i,k) = t(i,k)* (1._r8+1.608_r8*q(i,k))/ (1._r8+q(i,k)) - buoy(i,k) = tpv(i,k) - tv(i,k) + tiedke_add ! +0.5K or not? - else - qstp(i,k) = q(i,k) - tp(i,k) = t(i,k) - tpv(i,k) = tv(i,k) - endif - end do - end do - - - -!------------------------------------------------------------------------------- - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - - -! - do k = msg + 2,pver - do i = 1,ncol - if (k < lcl(i) .and. plge600(i)) then - if (buoy(i,k+1) > 0._r8 .and. buoy(i,k) <= 0._r8) then - knt(i) = min(num_cin,knt(i) + 1) - lelten(i,knt(i)) = k - end if - end if - end do - end do -! -! calculate convective available potential energy (cape). -! - do n = 1,num_cin - do k = msg + 1,pver - do i = 1,ncol - if (plge600(i) .and. k <= mx(i) .and. k > lelten(i,n)) then - capeten(i,n) = capeten(i,n) + rd*buoy(i,k)*log(pf(i,k+1)/pf(i,k)) - end if - end do - end do - end do -! -! find maximum cape from all possible tentative capes from -! one sounding, -! and use it as the final cape, april 26, 1995 -! - do n = 1,num_cin - do i = 1,ncol - if (capeten(i,n) > cape(i)) then - cape(i) = capeten(i,n) - lel(i) = lelten(i,n) - end if - end do - end do -! -! put lower bound on cape for diagnostic purposes. -! - do i = 1,ncol - cape(i) = max(cape(i), 0._r8) - end do -! - return -end subroutine buoyan_dilute - -subroutine parcel_dilute (lchnk, ncol, msg, klaunch, p, t, q, & - tpert, tp, tpv, qstp, pl, tl, ql, lcl, & - org, landfrac) - -! Routine to determine -! 1. Tp - Parcel temperature -! 2. qstp - Saturated mixing ratio at the parcel temperature. - -!-------------------- -implicit none -!-------------------- - -integer, intent(in) :: lchnk -integer, intent(in) :: ncol -integer, intent(in) :: msg - -integer, intent(in), dimension(pcols) :: klaunch(pcols) - -real(r8), intent(in), dimension(pcols,pver) :: p -real(r8), intent(in), dimension(pcols,pver) :: t -real(r8), intent(in), dimension(pcols,pver) :: q -real(r8), intent(in), dimension(pcols) :: tpert ! PBL temperature perturbation. - -real(r8), intent(inout), dimension(pcols,pver) :: tp ! Parcel temp. -real(r8), intent(inout), dimension(pcols,pver) :: qstp ! Parcel water vapour (sat value above lcl). -real(r8), intent(inout), dimension(pcols) :: tl ! Actual temp of LCL. -real(r8), intent(inout), dimension(pcols) :: ql ! Actual humidity of LCL -real(r8), intent(inout), dimension(pcols) :: pl ! Actual pressure of LCL. - -integer, intent(inout), dimension(pcols) :: lcl ! Lifting condesation level (first model level with saturation). - -real(r8), intent(out), dimension(pcols,pver) :: tpv ! Define tpv within this routine. - -real(r8), pointer, dimension(:,:) :: org -real(r8), intent(in), dimension(pcols) :: landfrac -!-------------------- - -! Have to be careful as s is also dry static energy. - - -! If we are to retain the fact that CAM loops over grid-points in the internal -! loop then we need to dimension sp,atp,mp,xsh2o with ncol. - - -real(r8) tmix(pcols,pver) ! Tempertaure of the entraining parcel. -real(r8) qtmix(pcols,pver) ! Total water of the entraining parcel. -real(r8) qsmix(pcols,pver) ! Saturated mixing ratio at the tmix. -real(r8) smix(pcols,pver) ! Entropy of the entraining parcel. -real(r8) xsh2o(pcols,pver) ! Precipitate lost from parcel. -real(r8) ds_xsh2o(pcols,pver) ! Entropy change due to loss of condensate. -real(r8) ds_freeze(pcols,pver) ! Entropy change sue to freezing of precip. -real(r8) dmpdz2d(pcols,pver) ! variable detrainment rate - -real(r8) mp(pcols) ! Parcel mass flux. -real(r8) qtp(pcols) ! Parcel total water. -real(r8) sp(pcols) ! Parcel entropy. - -real(r8) sp0(pcols) ! Parcel launch entropy. -real(r8) qtp0(pcols) ! Parcel launch total water. -real(r8) mp0(pcols) ! Parcel launch relative mass flux. - -real(r8) lwmax ! Maximum condesate that can be held in cloud before rainout. -real(r8) dmpdp ! Parcel fractional mass entrainment rate (/mb). -!real(r8) dmpdpc ! In cloud parcel mass entrainment rate (/mb). -real(r8) dmpdz ! Parcel fractional mass entrainment rate (/m) -real(r8) dpdz,dzdp ! Hydrstatic relation and inverse of. -real(r8) senv ! Environmental entropy at each grid point. -real(r8) qtenv ! Environmental total water " " ". -real(r8) penv ! Environmental total pressure " " ". -real(r8) tenv ! Environmental total temperature " " ". -real(r8) new_s ! Hold value for entropy after condensation/freezing adjustments. -real(r8) new_q ! Hold value for total water after condensation/freezing adjustments. -real(r8) dp ! Layer thickness (center to center) -real(r8) tfguess ! First guess for entropy inversion - crucial for efficiency! -real(r8) tscool ! Super cooled temperature offset (in degC) (eg -35). - -real(r8) qxsk, qxskp1 ! LCL excess water (k, k+1) -real(r8) dsdp, dqtdp, dqxsdp ! LCL s, qt, p gradients (k, k+1) -real(r8) slcl,qtlcl,qslcl ! LCL s, qt, qs values. -real(r8) org2rkm, org2Tpert -real(r8) dmpdz_lnd, dmpdz_mask - -integer rcall ! Number of ientropy call for errors recording -integer nit_lheat ! Number of iterations for condensation/freezing loop. -integer i,k,ii ! Loop counters. - -!====================================================================== -! SUMMARY -! -! 9/9/04 - Assumes parcel is initiated from level of maxh (klaunch) -! and entrains at each level with a specified entrainment rate. -! -! 15/9/04 - Calculates lcl(i) based on k where qsmix is first < qtmix. -! -!====================================================================== -! -! Set some values that may be changed frequently. -! - -if (zm_org) then - org2rkm = 10._r8 - org2Tpert = 0._r8 -endif -nit_lheat = 2 ! iterations for ds,dq changes from condensation freezing. -dmpdz=dmpdz_param ! Entrainment rate. (-ve for /m) -dmpdz_lnd=-1.e-3_r8 -!dmpdpc = 3.e-2_r8 ! In cloud entrainment rate (/mb). -lwmax = 1.e-3_r8 ! Need to put formula in for this. -tscool = 0.0_r8 ! Temp at which water loading freezes in the cloud. - -qtmix=0._r8 -smix=0._r8 - -qtenv = 0._r8 -senv = 0._r8 -tenv = 0._r8 -penv = 0._r8 - -qtp0 = 0._r8 -sp0 = 0._r8 -mp0 = 0._r8 - -qtp = 0._r8 -sp = 0._r8 -mp = 0._r8 - -new_q = 0._r8 -new_s = 0._r8 - -! **** Begin loops **** - -do k = pver, msg+1, -1 - do i=1,ncol - -! Initialize parcel values at launch level. - - if (k == klaunch(i)) then - - if (lparcel_pbl) then ! Modifcations to parcel properties if lparcel_pbl set. - - qtp0(i) = ql(i) ! Parcel launch q (PBL mixed value). - sp0(i) = entropy(tl(i),pl(i),qtp0(i)) ! Parcel launch entropy could be a mixed parcel. - - else - - qtp0(i) = q(i,k) ! Parcel launch total water (assuming subsaturated) - sp0(i) = entropy(t(i,k),p(i,k),qtp0(i)) ! Parcel launch entropy. - - end if - - mp0(i) = 1._r8 ! Parcel launch relative mass (i.e. 1 parcel stays 1 parcel for dmpdp=0, undilute). - smix(i,k) = sp0(i) - qtmix(i,k) = qtp0(i) - tfguess = t(i,k) - rcall = 1 - call ientropy (rcall,i,lchnk,smix(i,k),p(i,k),qtmix(i,k),tmix(i,k),qsmix(i,k),tfguess) - end if - -! Entraining levels - - if (k < klaunch(i)) then - -! Set environmental values for this level. - - dp = (p(i,k)-p(i,k+1)) ! In -ve mb as p decreasing with height - difference between center of layers. - qtenv = 0.5_r8*(q(i,k)+q(i,k+1)) ! Total water of environment. - tenv = 0.5_r8*(t(i,k)+t(i,k+1)) - penv = 0.5_r8*(p(i,k)+p(i,k+1)) - - senv = entropy(tenv,penv,qtenv) ! Entropy of environment. - -! Determine fractional entrainment rate /pa given value /m. - - dpdz = -(penv*grav)/(rgas*tenv) ! in mb/m since p in mb. - dzdp = 1._r8/dpdz ! in m/mb - if (zm_org) then - dmpdz_mask = landfrac(i) * dmpdz_lnd + (1._r8 - landfrac(i)) * dmpdz - dmpdp = (dmpdz_mask/(1._r8+org(i,k)*org2rkm))*dzdp ! /mb Fractional entrainment - else - dmpdp = dmpdz*dzdp - endif - -! Sum entrainment to current level -! entrains q,s out of intervening dp layers, in which linear variation is assumed -! so really it entrains the mean of the 2 stored values. - - sp(i) = sp(i) - dmpdp*dp*senv - qtp(i) = qtp(i) - dmpdp*dp*qtenv - mp(i) = mp(i) - dmpdp*dp - -! Entrain s and qt to next level. - - smix(i,k) = (sp0(i) + sp(i)) / (mp0(i) + mp(i)) - qtmix(i,k) = (qtp0(i) + qtp(i)) / (mp0(i) + mp(i)) - -! Invert entropy from s and q to determine T and saturation-capped q of mixture. -! t(i,k) used as a first guess so that it converges faster. - - tfguess = tmix(i,k+1) - rcall = 2 - call ientropy(rcall,i,lchnk,smix(i,k),p(i,k),qtmix(i,k),tmix(i,k),qsmix(i,k),tfguess) - -! -! Determine if this is lcl of this column if qsmix <= qtmix. -! FIRST LEVEL where this happens on ascending. - - if (qsmix(i,k) <= qtmix(i,k) .and. qsmix(i,k+1) > qtmix(i,k+1)) then - lcl(i) = k - qxsk = qtmix(i,k) - qsmix(i,k) - qxskp1 = qtmix(i,k+1) - qsmix(i,k+1) - dqxsdp = (qxsk - qxskp1)/dp - pl(i) = p(i,k+1) - qxskp1/dqxsdp ! pressure level of actual lcl. - dsdp = (smix(i,k) - smix(i,k+1))/dp - dqtdp = (qtmix(i,k) - qtmix(i,k+1))/dp - slcl = smix(i,k+1) + dsdp* (pl(i)-p(i,k+1)) - qtlcl = qtmix(i,k+1) + dqtdp*(pl(i)-p(i,k+1)) - - tfguess = tmix(i,k) - rcall = 3 - call ientropy (rcall,i,lchnk,slcl,pl(i),qtlcl,tl(i),qslcl,tfguess) - -! write(iulog,*)' ' -! write(iulog,*)' p',p(i,k+1),pl(i),p(i,lcl(i)) -! write(iulog,*)' t',tmix(i,k+1),tl(i),tmix(i,lcl(i)) -! write(iulog,*)' s',smix(i,k+1),slcl,smix(i,lcl(i)) -! write(iulog,*)'qt',qtmix(i,k+1),qtlcl,qtmix(i,lcl(i)) -! write(iulog,*)'qs',qsmix(i,k+1),qslcl,qsmix(i,lcl(i)) - - endif -! - end if ! k < klaunch - - - end do ! Levels loop -end do ! Columns loop - -!!!!!!!!!!!!!!!!!!!!!!!!!!END ENTRAINMENT LOOP!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -!! Could stop now and test with this as it will provide some estimate of buoyancy -!! without the effects of freezing/condensation taken into account for tmix. - -!! So we now have a profile of entropy and total water of the entraining parcel -!! Varying with height from the launch level klaunch parcel=environment. To the -!! top allowed level for the existence of convection. - -!! Now we have to adjust these values such that the water held in vaopor is < or -!! = to qsmix. Therefore, we assume that the cloud holds a certain amount of -!! condensate (lwmax) and the rest is rained out (xsh2o). This, obviously -!! provides latent heating to the mixed parcel and so this has to be added back -!! to it. But does this also increase qsmix as well? Also freezing processes - - -xsh2o = 0._r8 -ds_xsh2o = 0._r8 -ds_freeze = 0._r8 - -!!!!!!!!!!!!!!!!!!!!!!!!!PRECIPITATION/FREEZING LOOP!!!!!!!!!!!!!!!!!!!!!!!!!! -!! Iterate solution twice for accuracy - - - -do k = pver, msg+1, -1 - do i=1,ncol - -! Initialize variables at k=klaunch - - if (k == klaunch(i)) then - -! Set parcel values at launch level assume no liquid water. - - tp(i,k) = tmix(i,k) - qstp(i,k) = q(i,k) - if (zm_org) then - tpv(i,k) = (tp(i,k) + (org2Tpert*org(i,k)+tpert(i))) * (1._r8+1.608_r8*qstp(i,k)) / (1._r8+qstp(i,k)) - else - tpv(i,k) = (tp(i,k) + tpert(i)) * (1._r8+1.608_r8*qstp(i,k)) / (1._r8+qstp(i,k)) - endif - - end if - - if (k < klaunch(i)) then - -! Initiaite loop if switch(2) = .T. - RBN:DILUTE - TAKEN OUT BUT COULD BE RETURNED LATER. - -! Iterate nit_lheat times for s,qt changes. - - do ii=0,nit_lheat-1 - -! Rain (xsh2o) is excess condensate, bar LWMAX (Accumulated loss from qtmix). - - xsh2o(i,k) = max (0._r8, qtmix(i,k) - qsmix(i,k) - lwmax) - -! Contribution to ds from precip loss of condensate (Accumulated change from smix).(-ve) - - ds_xsh2o(i,k) = ds_xsh2o(i,k+1) - cpliq * log (tmix(i,k)/tfreez) * max(0._r8,(xsh2o(i,k)-xsh2o(i,k+1))) -! -! Entropy of freezing: latice times amount of water involved divided by T. -! - - if (tmix(i,k) <= tfreez+tscool .and. ds_freeze(i,k+1) == 0._r8) then ! One off freezing of condensate. - ds_freeze(i,k) = (latice/tmix(i,k)) * max(0._r8,qtmix(i,k)-qsmix(i,k)-xsh2o(i,k)) ! Gain of LH - end if - - if (tmix(i,k) <= tfreez+tscool .and. ds_freeze(i,k+1) /= 0._r8) then ! Continual freezing of additional condensate. - ds_freeze(i,k) = ds_freeze(i,k+1)+(latice/tmix(i,k)) * max(0._r8,(qsmix(i,k+1)-qsmix(i,k))) - end if - -! Adjust entropy and accordingly to sum of ds (be careful of signs). - - new_s = smix(i,k) + ds_xsh2o(i,k) + ds_freeze(i,k) - -! Adjust liquid water and accordingly to xsh2o. - - new_q = qtmix(i,k) - xsh2o(i,k) - -! Invert entropy to get updated Tmix and qsmix of parcel. - - tfguess = tmix(i,k) - rcall =4 - call ientropy (rcall,i,lchnk,new_s, p(i,k), new_q, tmix(i,k), qsmix(i,k), tfguess) - - end do ! Iteration loop for freezing processes. - -! tp - Parcel temp is temp of mixture. -! tpv - Parcel v. temp should be density temp with new_q total water. - - tp(i,k) = tmix(i,k) - -! tpv = tprho in the presence of condensate (i.e. when new_q > qsmix) - - if (new_q > qsmix(i,k)) then ! Super-saturated so condensate present - reduces buoyancy. - qstp(i,k) = qsmix(i,k) - else ! Just saturated/sub-saturated - no condensate virtual effects. - qstp(i,k) = new_q - end if - - if (zm_org) then - tpv(i,k) = (tp(i,k)+(org2Tpert*org(i,k)+tpert(i)))* (1._r8+1.608_r8*qstp(i,k)) / (1._r8+ new_q) - else - tpv(i,k) = (tp(i,k)+tpert(i))* (1._r8+1.608_r8*qstp(i,k)) / (1._r8+ new_q) - endif - - end if ! k < klaunch - - end do ! Loop for columns - -end do ! Loop for vertical levels. - - -return -end subroutine parcel_dilute - -!----------------------------------------------------------------------------------------- -real(r8) function entropy(TK,p,qtot) -!----------------------------------------------------------------------------------------- -! -! TK(K),p(mb),qtot(kg/kg) -! from Raymond and Blyth 1992 -! - real(r8), intent(in) :: p,qtot,TK - real(r8) :: qv,qst,e,est,L - real(r8), parameter :: pref = 1000._r8 - -L = rl - (cpliq - cpwv)*(TK-tfreez) ! T IN CENTIGRADE - -call qsat_hPa(TK, p, est, qst) - -qv = min(qtot,qst) ! Partition qtot into vapor part only. -e = qv*p / (eps1 +qv) - -entropy = (cpres + qtot*cpliq)*log( TK/tfreez) - rgas*log( (p-e)/pref ) + & - L*qv/TK - qv*rh2o*log(qv/qst) - -end FUNCTION entropy - -! -!----------------------------------------------------------------------------------------- -SUBROUTINE ientropy (rcall,icol,lchnk,s,p,qt,T,qst,Tfg) -!----------------------------------------------------------------------------------------- -! -! p(mb), Tfg/T(K), qt/qv(kg/kg), s(J/kg). -! Inverts entropy, pressure and total water qt -! for T and saturated vapor mixing ratio -! - - use phys_grid, only: get_rlon_p, get_rlat_p - - integer, intent(in) :: icol, lchnk, rcall - real(r8), intent(in) :: s, p, Tfg, qt - real(r8), intent(out) :: qst, T - real(r8) :: est, this_lat,this_lon - real(r8) :: a,b,c,d,ebr,fa,fb,fc,pbr,qbr,rbr,sbr,tol1,xm,tol - integer :: i - - logical :: converged - - ! Max number of iteration loops. - integer, parameter :: LOOPMAX = 100 - real(r8), parameter :: EPS = 3.e-8_r8 - - converged = .false. - - ! Invert the entropy equation -- use Brent's method - ! Brent, R. P. Ch. 3-4 in Algorithms for Minimization Without Derivatives. Englewood Cliffs, NJ: Prentice-Hall, 1973. - - T = Tfg ! Better first guess based on Tprofile from conv. - - a = Tfg-10 !low bracket - b = Tfg+10 !high bracket - - fa = entropy(a, p, qt) - s - fb = entropy(b, p, qt) - s - - c=b - fc=fb - tol=0.001_r8 - - converge: do i=0, LOOPMAX - if ((fb > 0.0_r8 .and. fc > 0.0_r8) .or. & - (fb < 0.0_r8 .and. fc < 0.0_r8)) then - c=a - fc=fa - d=b-a - ebr=d - end if - if (abs(fc) < abs(fb)) then - a=b - b=c - c=a - fa=fb - fb=fc - fc=fa - end if - - tol1=2.0_r8*EPS*abs(b)+0.5_r8*tol - xm=0.5_r8*(c-b) - converged = (abs(xm) <= tol1 .or. fb == 0.0_r8) - if (converged) exit converge - - if (abs(ebr) >= tol1 .and. abs(fa) > abs(fb)) then - sbr=fb/fa - if (a == c) then - pbr=2.0_r8*xm*sbr - qbr=1.0_r8-sbr - else - qbr=fa/fc - rbr=fb/fc - pbr=sbr*(2.0_r8*xm*qbr*(qbr-rbr)-(b-a)*(rbr-1.0_r8)) - qbr=(qbr-1.0_r8)*(rbr-1.0_r8)*(sbr-1.0_r8) - end if - if (pbr > 0.0_r8) qbr=-qbr - pbr=abs(pbr) - if (2.0_r8*pbr < min(3.0_r8*xm*qbr-abs(tol1*qbr),abs(ebr*qbr))) then - ebr=d - d=pbr/qbr - else - d=xm - ebr=d - end if - else - d=xm - ebr=d - end if - a=b - fa=fb - b=b+merge(d,sign(tol1,xm), abs(d) > tol1 ) - - fb = entropy(b, p, qt) - s - - end do converge - - T = b - call qsat_hPa(T, p, est, qst) - - if (.not. converged) then - this_lat = get_rlat_p(lchnk, icol)*57.296_r8 - this_lon = get_rlon_p(lchnk, icol)*57.296_r8 - write(iulog,*) '*** ZM_CONV: IENTROPY: Failed and about to exit, info follows ****' - write(iulog,100) 'ZM_CONV: IENTROPY. Details: call#,lchnk,icol= ',rcall,lchnk,icol, & - ' lat: ',this_lat,' lon: ',this_lon, & - ' P(mb)= ', p, ' Tfg(K)= ', Tfg, ' qt(g/kg) = ', 1000._r8*qt, & - ' qst(g/kg) = ', 1000._r8*qst,', s(J/kg) = ',s - call endrun('**** ZM_CONV IENTROPY: Tmix did not converge ****') - end if - -100 format (A,I1,I4,I4,7(A,F6.2)) - -end SUBROUTINE ientropy - -! Wrapper for qsat_water that does translation between Pa and hPa -! qsat_water uses Pa internally, so get it right, need to pass in Pa. -! Afterward, set es back to hPa. -subroutine qsat_hPa(t, p, es, qm) - use wv_saturation, only: qsat_water - - ! Inputs - real(r8), intent(in) :: t ! Temperature (K) - real(r8), intent(in) :: p ! Pressure (hPa) - ! Outputs - real(r8), intent(out) :: es ! Saturation vapor pressure (hPa) - real(r8), intent(out) :: qm ! Saturation mass mixing ratio - ! (vapor mass over dry mass, kg/kg) - - call qsat_water(t, p*100._r8, es, qm) - - es = es*0.01_r8 - -end subroutine qsat_hPa - -end module zm_conv diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index 48e8d5e932..2e44af000e 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -8,11 +8,13 @@ module zm_conv_intr ! January 2010 modified by J. Kay to add COSP simulator fields to physics buffer !--------------------------------------------------------------------------------- use shr_kind_mod, only: r8=>shr_kind_r8 - use physconst, only: cpair + use physconst, only: cpair, epsilo, gravit, latvap, tmelt, rair use ppgrid, only: pver, pcols, pverp, begchunk, endchunk - use zm_conv, only: zm_conv_evap, zm_convr, convtran, momtran - - use zm_microphysics, only: zm_aero_t, zm_conv_t + use zm_conv_evap_mod, only: zm_conv_evap_run + use zm_convr_mod, only: zm_convr_init, zm_convr_run + use zm_conv_convtran_mod, only: zm_conv_convtran_run + use zm_conv_momtran_mod, only: zm_conv_momtran_run + use rad_constituents, only: rad_cnst_get_info, rad_cnst_get_mode_num, rad_cnst_get_aer_mmr, & rad_cnst_get_aer_props, rad_cnst_get_mode_props !, & use ndrop_bam, only: ndrop_bam_init @@ -36,7 +38,6 @@ module zm_conv_intr zm_conv_tend, &! return tendencies zm_conv_tend_2 ! return tendencies - public :: zmconv_microp integer ::& ! indices for fields in the physics buffer zm_mu_idx, & @@ -73,7 +74,6 @@ module zm_conv_intr ! before the convection top and CAPE calculations are completed. logical :: zmconv_org ! Parameterization for sub-grid scale convective organization for the ZM deep ! convective scheme based on Mapes and Neale (2011) - logical :: zmconv_microp = .false. ! switch for microphysics real(r8) :: zmconv_dmpdz = unset_r8 ! Parcel fractional mass entrainment rate real(r8) :: zmconv_tiedke_add = unset_r8 ! Convective parcel temperature perturbation real(r8) :: zmconv_capelmt = unset_r8 ! Triggering thereshold for ZM convection @@ -92,8 +92,6 @@ module zm_conv_intr integer :: nmodes integer :: nbulk - type(zm_aero_t), allocatable :: aero(:) ! object contains information about the aerosols - !========================================================================================= contains !========================================================================================= @@ -156,15 +154,6 @@ subroutine zm_conv_register ! convective mass fluxes call pbuf_add_field('CMFMC_DP', 'physpkg', dtype_r8, (/pcols,pverp/), mconzm_idx) - if (zmconv_microp) then - ! Only add the number conc fields if the microphysics is active. - - ! detrained convective cloud water num concen. - call pbuf_add_field('DNLFZM', 'physpkg', dtype_r8, (/pcols,pver/), dnlfzm_idx) - ! detrained convective cloud ice num concen. - call pbuf_add_field('DNIFZM', 'physpkg', dtype_r8, (/pcols,pver/), dnifzm_idx) - end if - if (zmconv_org) then call cnst_add('ZM_ORG',0._r8,0._r8,0._r8,ixorg,longname='organization parameter') endif @@ -187,7 +176,7 @@ subroutine zm_conv_readnl(nlfile) namelist /zmconv_nl/ zmconv_c0_lnd, zmconv_c0_ocn, zmconv_num_cin, & zmconv_ke, zmconv_ke_lnd, zmconv_org, & - zmconv_momcu, zmconv_momcd, zmconv_microp, & + zmconv_momcu, zmconv_momcd, & zmconv_dmpdz, zmconv_tiedke_add, zmconv_capelmt, & zmconv_parcel_pbl, zmconv_tau !----------------------------------------------------------------------------- @@ -224,8 +213,6 @@ subroutine zm_conv_readnl(nlfile) if (ierr /= 0) call endrun("zm_conv_readnl: FATAL: mpi_bcast: zmconv_momcd") call mpi_bcast(zmconv_org, 1, mpi_logical, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun("zm_conv_readnl: FATAL: mpi_bcast: zmconv_org") - call mpi_bcast(zmconv_microp, 1, mpi_logical, masterprocid, mpicom, ierr) - if (ierr /= 0) call endrun("zm_conv_readnl: FATAL: mpi_bcast: zmconv_microp") call mpi_bcast(zmconv_dmpdz, 1, mpi_real8, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun("zm_conv_readnl: FATAL: mpi_bcast: zmconv_dmpdz") call mpi_bcast(zmconv_tiedke_add, 1, mpi_real8, masterprocid, mpicom, ierr) @@ -233,7 +220,7 @@ subroutine zm_conv_readnl(nlfile) call mpi_bcast(zmconv_capelmt, 1, mpi_real8, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun("zm_conv_readnl: FATAL: mpi_bcast: zmconv_capelmt") call mpi_bcast(zmconv_parcel_pbl, 1, mpi_logical, masterprocid, mpicom, ierr) - if (ierr /= 0) call endrun("zm_conv_readnl: FATAL: mpi_bcast: zmconv_parcel_pbl") + if (ierr /= 0) call endrun("zm_conv_readnl: FATAL: mpi_bcast: zmconv_parcel_pbl") call mpi_bcast(zmconv_tau, 1, mpi_real8, masterprocid, mpicom, ierr) if (ierr /= 0) call endrun("zm_conv_readnl: FATAL: mpi_bcast: zmconv_tau") @@ -249,7 +236,7 @@ subroutine zm_conv_init(pref_edge) use cam_history, only: addfld, add_default, horiz_only use ppgrid, only: pcols, pver - use zm_conv, only: zm_convi + use zm_convr_mod, only: zm_convr_init use pmgrid, only: plev,plevp use spmd_utils, only: masterproc use phys_control, only: phys_deepconv_pbl, phys_getopts, cam_physpkg_is @@ -259,6 +246,8 @@ subroutine zm_conv_init(pref_edge) real(r8),intent(in) :: pref_edge(plevp) ! reference pressures at interfaces + character(len=512) :: errmsg + integer :: errflg logical :: no_deep_pbl ! if true, no deep convection in PBL integer limcnv ! top interface level limit for convection @@ -268,12 +257,6 @@ subroutine zm_conv_init(pref_edge) ! liquid budgets. integer :: history_budget_histfile_num ! output history file number for budget fields -! Allocate the basic aero structure outside the zmconv_microp logical -! This allows the aero structure to be passed -! Note that all of the arrays inside this structure are conditionally allocated - - allocate(aero(begchunk:endchunk)) - ! ! Register fields with the output buffer ! @@ -344,10 +327,6 @@ subroutine zm_conv_init(pref_edge) call add_default('ZMMTT ', history_budget_histfile_num, ' ') end if - if (zmconv_microp) then - call add_default ('DIFZM', 1, ' ') - call add_default ('DLFZM', 1, ' ') - end if ! ! Limit deep convection to regions below 40 mb ! Note this calculation is repeated in the shallow convection interface @@ -371,16 +350,16 @@ subroutine zm_conv_init(pref_edge) end if no_deep_pbl = phys_deepconv_pbl() - call zm_convi(limcnv,zmconv_c0_lnd, zmconv_c0_ocn, zmconv_ke, zmconv_ke_lnd, & +!CACNOTE - Need to check errflg and report errors + call zm_convr_init(cpair, epsilo, gravit, latvap, tmelt, rair, & + limcnv,zmconv_c0_lnd, zmconv_c0_ocn, zmconv_ke, zmconv_ke_lnd, & zmconv_momcu, zmconv_momcd, zmconv_num_cin, zmconv_org, & - zmconv_microp, no_deep_pbl, zmconv_tiedke_add, & - zmconv_capelmt, zmconv_dmpdz,zmconv_parcel_pbl, zmconv_tau) + no_deep_pbl, zmconv_tiedke_add, & + zmconv_capelmt, zmconv_dmpdz,zmconv_parcel_pbl, zmconv_tau, errmsg, errflg) cld_idx = pbuf_get_index('CLD') fracis_idx = pbuf_get_index('FRACIS') - if (zmconv_microp) call zm_conv_micro_init() - end subroutine zm_conv_init !========================================================================================= !subroutine zm_conv_tend(state, ptend, tdt) @@ -402,7 +381,8 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & use physics_buffer, only : pbuf_get_field, physics_buffer_desc, pbuf_old_tim_idx use constituents, only: pcnst, cnst_get_ind, cnst_is_convtran1 use check_energy, only: check_energy_chng - use physconst, only: gravit + use physconst, only: gravit, latice, latvap, tmelt, cpwv, cpliq, rh2o + use phys_control, only: cam_physpkg_is ! Arguments @@ -426,8 +406,8 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & ! Local variables - - type(zm_conv_t) :: conv + character(len=512) :: errmsg + integer :: errflg integer :: i,k,l,m integer :: ilon ! global longitude index of a column @@ -515,57 +495,6 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & ncol = state%ncol nstep = get_nstep() - if (zmconv_microp) then - allocate( & - conv%qi(pcols,pver), & - conv%qliq(pcols,pver), & - conv%qice(pcols,pver), & - conv%wu(pcols,pver), & - conv%sprd(pcols,pver), & - conv%qrain(pcols,pver), & - conv%qsnow(pcols,pver), & - conv%qnl(pcols,pver), & - conv%qni(pcols,pver), & - conv%qnr(pcols,pver), & - conv%qns(pcols,pver), & - conv%frz(pcols,pver), & - conv%autolm(pcols,pver), & - conv%accrlm(pcols,pver), & - conv%bergnm(pcols,pver), & - conv%fhtimm(pcols,pver), & - conv%fhtctm(pcols,pver), & - conv%fhmlm (pcols,pver), & - conv%hmpim (pcols,pver), & - conv%accslm(pcols,pver), & - conv%dlfm (pcols,pver), & - conv%autoln(pcols,pver), & - conv%accrln(pcols,pver), & - conv%bergnn(pcols,pver), & - conv%fhtimn(pcols,pver), & - conv%fhtctn(pcols,pver), & - conv%fhmln (pcols,pver), & - conv%accsln(pcols,pver), & - conv%activn(pcols,pver), & - conv%dlfn (pcols,pver), & - conv%autoim(pcols,pver), & - conv%accsim(pcols,pver), & - conv%difm (pcols,pver), & - conv%nuclin(pcols,pver), & - conv%autoin(pcols,pver), & - conv%accsin(pcols,pver), & - conv%hmpin (pcols,pver), & - conv%difn (pcols,pver), & - conv%cmel (pcols,pver), & - conv%cmei (pcols,pver), & - conv%trspcm(pcols,pver), & - conv%trspcn(pcols,pver), & - conv%trspim(pcols,pver), & - conv%trspin(pcols,pver), & - conv%lambdadpcu(pcols,pver), & - conv%mudpcu(pcols,pver), & - conv%dcape(pcols) ) - end if - ftem = 0._r8 mu_out(:,:) = 0._r8 md_out(:,:) = 0._r8 @@ -578,7 +507,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & if (zmconv_org) then lq(ixorg) = .TRUE. endif - call physics_ptend_init(ptend_loc, state%psetcols, 'zm_convr', ls=.true., lq=lq)! initialize local ptend type + call physics_ptend_init(ptend_loc, state%psetcols, 'zm_convr_run', ls=.true., lq=lq)! initialize local ptend type ! ! Associate pointers with physics buffer fields @@ -608,45 +537,12 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & call pbuf_get_field(pbuf, difzm_idx, dif) call pbuf_get_field(pbuf, mconzm_idx, mconzm) - if (zmconv_microp) then - call pbuf_get_field(pbuf, dnlfzm_idx, dnlf) - call pbuf_get_field(pbuf, dnifzm_idx, dnif) - else - allocate(dnlf(pcols,pver), dnif(pcols,pver)) - end if - - if (zmconv_microp) then - - if (nmodes > 0) then - - ! Associate pointers with the modes and species that affect the climate - ! (list 0) - - do m = 1, nmodes - call rad_cnst_get_mode_num(0, m, 'a', state, pbuf, aero(lchnk)%num_a(m)%val) - call pbuf_get_field(pbuf, dgnum_idx, aero(lchnk)%dgnum(m)%val, start=(/1,1,m/), kount=(/pcols,pver,1/)) - - do l = 1, aero(lchnk)%nspec(m) - call rad_cnst_get_aer_mmr(0, m, l, 'a', state, pbuf, aero(lchnk)%mmr_a(l,m)%val) - end do - end do - - else if (nbulk > 0) then - - ! Associate pointers with the bulk aerosols that affect the climate - ! (list 0) - - do m = 1, nbulk - call rad_cnst_get_aer_mmr(0, m, state, pbuf, aero(lchnk)%mmr_bulk(m)%val) - end do - - end if - end if + allocate(dnlf(pcols,pver), dnif(pcols,pver)) ! ! Begin with Zhang-McFarlane (1996) convection parameterization ! - call t_startf ('zm_convr') + call t_startf ('zm_convr_run') if (zmconv_org) then allocate(zm_org2d(pcols,pver)) @@ -654,7 +550,10 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & orgt => ptend_loc%q(:,:,ixorg) endif - call zm_convr( lchnk ,ncol , & +!CACNOTE - Need to check errflg and report errors + call zm_convr_run( ncol , pcols, pver, & + pverp, gravit ,latice ,cpwv ,cpliq ,& + rh2o,& state%t ,state%q(:,:,1), prec ,jctop ,jcbot , & pblh ,state%zm ,state%phis ,state%zi ,ptend_loc%q(:,:,1) , & ptend_loc%s , state%pmid ,state%pint ,state%pdel , & @@ -664,8 +563,8 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & dp, dsubcld, jt, maxg, ideep, & ql, rliq, landfrac, & org, orgt, zm_org2d, & - dif, dnlf, dnif, conv, & - aero(lchnk), rice) + dif, dnlf, dnif, & + rice, errmsg, errflg) lengath = count(ideep > 0) @@ -702,13 +601,11 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & ftem(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpair call outfld('ZMDT ',ftem ,pcols ,lchnk ) call outfld('ZMDQ ',ptend_loc%q(1,1,1) ,pcols ,lchnk ) - call t_stopf ('zm_convr') + call t_stopf ('zm_convr_run') call outfld('DIFZM' ,dif ,pcols, lchnk) call outfld('DLFZM' ,dlf ,pcols, lchnk) - if (zmconv_microp) call zm_conv_micro_outfld(conv, dnif, dnlf, lchnk, ncol) - pcont(:ncol) = state%ps(:ncol) pconb(:ncol) = state%ps(:ncol) do i = 1,lengath @@ -735,9 +632,9 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & if (zmconv_org) then lq(ixorg) = .TRUE. endif - call physics_ptend_init(ptend_loc, state1%psetcols, 'zm_conv_evap', ls=.true., lq=lq) + call physics_ptend_init(ptend_loc, state1%psetcols, 'zm_conv_evap_run', ls=.true., lq=lq) - call t_startf ('zm_conv_evap') + call t_startf ('zm_conv_evap_run') ! ! Determine the phase of the precipitation produced and add latent heat of fusion ! Evaporate some of the precip directly into the environment (Sundqvist) @@ -752,12 +649,13 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & dp_cldliq(:ncol,:) = 0._r8 dp_cldice(:ncol,:) = 0._r8 - call zm_conv_evap(state1%ncol,state1%lchnk, & + call zm_conv_evap_run(state1%ncol, pcols, pver, pverp, & + gravit, latice, latvap, tmelt, & state1%t,state1%pmid,state1%pdel,state1%q(:pcols,:pver,1), & landfrac, & ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, ptend_loc%q(:pcols,:pver,1), & rprd, cld, ztodt, & - prec, snow, ntprprd, ntsnprd , flxprec, flxsnow, conv%sprd) + prec, snow, ntprprd, ntsnprd , flxprec, flxsnow) evapcdp(:ncol,:pver) = ptend_loc%q(:ncol,:pver,1) @@ -768,7 +666,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & endif ! -! Write out variables from zm_conv_evap +! Write out variables from zm_conv_evap_run ! ftem(:ncol,:pver) = ptend_loc%s(:ncol,:pver)/cpair call outfld('EVAPTZM ',ftem ,pcols ,lchnk ) @@ -786,7 +684,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & call outfld('PRECCDZM ',prec, pcols ,lchnk ) - call t_stopf ('zm_conv_evap') + call t_stopf ('zm_conv_evap_run') call outfld('PRECZ ', prec , pcols, lchnk) @@ -801,7 +699,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & if ( .not. cam_physpkg_is('cam3')) then - call physics_ptend_init(ptend_loc, state1%psetcols, 'momtran', ls=.true., lu=.true., lv=.true.) + call physics_ptend_init(ptend_loc, state1%psetcols, 'zm_conv_momtran_run', ls=.true., lu=.true., lv=.true.) winds(:ncol,:pver,1) = state1%u(:ncol,:pver) winds(:ncol,:pver,2) = state1%v(:ncol,:pver) @@ -809,13 +707,13 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & l_windt(1) = .true. l_windt(2) = .true. - call t_startf ('momtran') - call momtran (lchnk, ncol, & + call t_startf ('zm_conv_momtran_run') + call zm_conv_momtran_run (ncol, pcols, pver, pverp, & l_windt,winds, 2, mu, md, & du, eu, ed, dp, dsubcld, & jt, maxg, ideep, 1, lengath, & nstep, wind_tends, pguall, pgdall, icwu, icwd, ztodt, seten ) - call t_stopf ('momtran') + call t_stopf ('zm_conv_momtran_run') ptend_loc%u(:ncol,:pver) = wind_tends(:ncol,:pver,1) ptend_loc%v(:ncol,:pver) = wind_tends(:ncol,:pver,2) @@ -863,7 +761,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & fake_dpdry(:,:) = 0._r8 call t_startf ('convtran1') - call convtran (lchnk, & + call zm_conv_convtran_run (pcols, pver, & ptend_loc%lq,state1%q, pcnst, mu, md, & du, eu, ed, dp, dsubcld, & jt,maxg, ideep, 1, lengath, & @@ -883,61 +781,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & deallocate(zm_org2d) end if - if (zmconv_microp) then - deallocate( & - conv%qi, & - conv%qliq, & - conv%qice, & - conv%wu, & - conv%sprd, & - conv%qrain, & - conv%qsnow, & - conv%qnl, & - conv%qni, & - conv%qnr, & - conv%qns, & - conv%frz, & - conv%autolm, & - conv%accrlm, & - conv%bergnm, & - conv%fhtimm, & - conv%fhtctm, & - conv%fhmlm , & - conv%hmpim , & - conv%accslm, & - conv%dlfm , & - conv%autoln, & - conv%accrln, & - conv%bergnn, & - conv%fhtimn, & - conv%fhtctn, & - conv%fhmln , & - conv%accsln, & - conv%activn, & - conv%dlfn , & - conv%autoim, & - conv%accsim, & - conv%difm , & - conv%nuclin, & - conv%autoin, & - conv%accsin, & - conv%hmpin , & - conv%difn , & - conv%cmel , & - conv%cmei , & - conv%trspcm, & - conv%trspcn, & - conv%trspim, & - conv%trspin, & - conv%lambdadpcu, & - conv%mudpcu, & - conv%dcape ) - - else - - deallocate(dnlf, dnif) - - end if + deallocate(dnlf, dnif) end subroutine zm_conv_tend !========================================================================================= @@ -1008,7 +852,7 @@ subroutine zm_conv_tend_2( state, ptend, ztodt, pbuf) end do call t_startf ('convtran2') - call convtran (lchnk, & + call zm_conv_convtran_run (pcols, pver, & ptend%lq,state%q, pcnst, mu, md, & du, eu, ed, dp, dsubcld, & jt, maxg, ideep, 1, lengath, & @@ -1020,384 +864,5 @@ end subroutine zm_conv_tend_2 !========================================================================================= -subroutine zm_conv_micro_init() - - use cam_history, only: addfld, add_default, horiz_only - use ppgrid, only: pcols, pver - use pmgrid, only: plev,plevp - use phys_control, only: cam_physpkg_is - use physics_buffer, only: pbuf_get_index - use zm_microphysics, only: zm_mphyi - - implicit none - - integer :: i - - ! - ! Register fields with the output buffer - ! - call addfld ('ICIMRDP', (/ 'lev' /), 'A','kg/kg', 'Deep Convection in-cloud ice mixing ratio ') - call addfld ('CLDLIQZM',(/ 'lev' /), 'A','g/m3' ,'Cloud liquid water - ZM convection') - call addfld ('CLDICEZM',(/ 'lev' /), 'A','g/m3' ,'Cloud ice water - ZM convection') - call addfld ('CLIQSNUM',(/ 'lev' /), 'A','1' ,'Cloud liquid water sample number - ZM convection') - call addfld ('CICESNUM',(/ 'lev' /), 'A','1' ,'Cloud ice water sample number - ZM convection') - call addfld ('QRAINZM' ,(/ 'lev' /), 'A','g/m3' ,'rain water - ZM convection') - call addfld ('QSNOWZM' ,(/ 'lev' /), 'A','g/m3' ,'snow - ZM convection') - call addfld ('CRAINNUM',(/ 'lev' /), 'A','1' ,'Cloud rain water sample number - ZM convection') - call addfld ('CSNOWNUM',(/ 'lev' /), 'A','1' ,'Cloud snow sample number - ZM convection') - - call addfld ('DNIFZM' ,(/ 'lev' /), 'A','1/kg/s ' ,'Detrained ice water num concen from ZM convection') - call addfld ('DNLFZM' ,(/ 'lev' /), 'A','1/kg/s ' ,'Detrained liquid water num concen from ZM convection') - call addfld ('WUZM' ,(/ 'lev' /), 'A','m/s' ,'vertical velocity - ZM convection') - call addfld ('WUZMSNUM',(/ 'lev' /), 'A','1' ,'vertical velocity sample number - ZM convection') - - call addfld ('QNLZM',(/ 'lev' /), 'A','1/m3' ,'Cloud liquid water number concen - ZM convection') - call addfld ('QNIZM',(/ 'lev' /), 'A','1/m3' ,'Cloud ice number concen - ZM convection') - call addfld ('QNRZM',(/ 'lev' /), 'A','1/m3' ,'Cloud rain water number concen - ZM convection') - call addfld ('QNSZM',(/ 'lev' /), 'A','1/m3' ,'Cloud snow number concen - ZM convection') - - call addfld ('FRZZM',(/ 'lev' /), 'A','1/s' ,'mass tendency due to freezing - ZM convection') - - call addfld ('AUTOL_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to autoconversion of droplets to rain') - call addfld ('ACCRL_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to accretion of droplets by rain') - call addfld ('BERGN_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to Bergeron process') - call addfld ('FHTIM_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to immersion freezing') - call addfld ('FHTCT_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to contact freezing') - call addfld ('FHML_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to homogeneous freezing of droplet') - call addfld ('HMPI_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to HM process') - call addfld ('ACCSL_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to accretion of droplet by snow') - call addfld ('DLF_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to detrainment of droplet') - call addfld ('COND_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to condensation') - - call addfld ('AUTOL_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to autoconversion of droplets to rain') - call addfld ('ACCRL_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to accretion of droplets by rain') - call addfld ('BERGN_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to Bergeron process') - call addfld ('FHTIM_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to immersion freezing') - call addfld ('FHTCT_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to contact freezing') - call addfld ('FHML_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to homogeneous freezing of droplet') - call addfld ('ACCSL_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to accretion of droplet by snow') - call addfld ('ACTIV_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to droplets activation') - call addfld ('DLF_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to detrainment of droplet') - - call addfld ('AUTOI_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to autoconversion of ice to snow') - call addfld ('ACCSI_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to accretion of ice by snow') - call addfld ('DIF_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to detrainment of cloud ice') - call addfld ('DEPOS_M' ,(/ 'lev' /), 'A','kg/kg/m' ,'mass tendency due to deposition') - - call addfld ('NUCLI_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to ice nucleation') - call addfld ('AUTOI_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to autoconversion of ice to snow') - call addfld ('ACCSI_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to accretion of ice by snow') - call addfld ('HMPI_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to HM process') - call addfld ('DIF_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency due to detrainment of cloud ice') - - call addfld ('TRSPC_M' ,(/ 'lev' /), 'A','kg/kg/m','mass tendency of droplets due to convective transport') - call addfld ('TRSPC_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency of droplets due to convective transport') - call addfld ('TRSPI_M' ,(/ 'lev' /), 'A','kg/kg/m','mass tendency of ice crystal due to convective transport') - call addfld ('TRSPI_N' ,(/ 'lev' /), 'A','1/kg/m' ,'num tendency of ice crystal due to convective transport') - - - call add_default ('CLDLIQZM', 1, ' ') - call add_default ('CLDICEZM', 1, ' ') - call add_default ('CLIQSNUM', 1, ' ') - call add_default ('CICESNUM', 1, ' ') - call add_default ('DNIFZM', 1, ' ') - call add_default ('DNLFZM', 1, ' ') - call add_default ('WUZM', 1, ' ') - call add_default ('QRAINZM', 1, ' ') - call add_default ('QSNOWZM', 1, ' ') - call add_default ('CRAINNUM', 1, ' ') - call add_default ('CSNOWNUM', 1, ' ') - call add_default ('QNLZM', 1, ' ') - call add_default ('QNIZM', 1, ' ') - call add_default ('QNRZM', 1, ' ') - call add_default ('QNSZM', 1, ' ') - call add_default ('FRZZM', 1, ' ') - - ! Initialization for the microphysics - - call zm_mphyi() - - ! Initialize the aerosol object with data from the modes/species - ! affecting climate, - ! i.e., the list index is hardcoded to 0. - - call rad_cnst_get_info(0, nmodes=nmodes, naero=nbulk) - - - do i = begchunk, endchunk - call zm_aero_init(nmodes, nbulk, aero(i)) - end do - - if (nmodes > 0) then - - dgnum_idx = pbuf_get_index('DGNUM') - - else if (nbulk > 0 .and. cam_physpkg_is('cam4')) then - - ! This call is needed to allow running the ZM microphysics with the - ! cam4 physics package. - call ndrop_bam_init() - - end if - - end subroutine zm_conv_micro_init - - - subroutine zm_aero_init(nmodes, nbulk, aero) - - use pmgrid, only: plev,plevp - - ! Initialize the zm_aero_t object for modal aerosols - - integer, intent(in) :: nmodes - integer, intent(in) :: nbulk - type(zm_aero_t), intent(out) :: aero - - integer :: iaer, l, m - integer :: nspecmx ! max number of species in a mode - - character(len=20), allocatable :: aername(:) - character(len=32) :: str32 - character(len=*), parameter :: routine = 'zm_conv_init' - - real(r8) :: sigmag, dgnumlo, dgnumhi - real(r8) :: alnsg - !---------------------------------------------------------------------------------- - - aero%nmodes = nmodes - aero%nbulk = nbulk - - if (nmodes > 0) then - - ! Initialize the modal aerosol information - - aero%scheme = 'modal' - - ! Get number of species in each mode, and find max. - allocate(aero%nspec(aero%nmodes)) - nspecmx = 0 - do m = 1, aero%nmodes - - call rad_cnst_get_info(0, m, nspec=aero%nspec(m), mode_type=str32) - - nspecmx = max(nspecmx, aero%nspec(m)) - - ! save mode index for specified mode types - select case (trim(str32)) - case ('accum') - aero%mode_accum_idx = m - case ('aitken') - aero%mode_aitken_idx = m - case ('coarse') - aero%mode_coarse_idx = m - end select - - end do - - ! Check that required mode types were found - if (aero%mode_accum_idx == -1 .or. aero%mode_aitken_idx == -1 .or. aero%mode_coarse_idx == -1) then - write(iulog,*) routine//': ERROR required mode type not found - mode idx:', & - aero%mode_accum_idx, aero%mode_aitken_idx, aero%mode_coarse_idx - call endrun(routine//': ERROR required mode type not found') - end if - - ! find indices for the dust and seasalt species in the coarse mode - do l = 1, aero%nspec(aero%mode_coarse_idx) - call rad_cnst_get_info(0, aero%mode_coarse_idx, l, spec_type=str32) - select case (trim(str32)) - case ('dust') - aero%coarse_dust_idx = l - case ('seasalt') - aero%coarse_nacl_idx = l - end select - end do - ! Check that required modal specie types were found - if (aero%coarse_dust_idx == -1 .or. aero%coarse_nacl_idx == -1) then - write(iulog,*) routine//': ERROR required mode-species type not found - indicies:', & - aero%coarse_dust_idx, aero%coarse_nacl_idx - call endrun(routine//': ERROR required mode-species type not found') - end if - - allocate( & - aero%num_a(nmodes), & - aero%mmr_a(nspecmx,nmodes), & - aero%numg_a(pcols,pver,nmodes), & - aero%mmrg_a(pcols,pver,nspecmx,nmodes), & - aero%voltonumblo(nmodes), & - aero%voltonumbhi(nmodes), & - aero%specdens(nspecmx,nmodes), & - aero%spechygro(nspecmx,nmodes), & - aero%dgnum(nmodes), & - aero%dgnumg(pcols,pver,nmodes) ) - - - do m = 1, nmodes - - ! Properties of modes - call rad_cnst_get_mode_props(0, m, & - sigmag=sigmag, dgnumlo=dgnumlo, dgnumhi=dgnumhi) - - alnsg = log(sigmag) - aero%voltonumblo(m) = 1._r8 / ( (pi/6._r8)*(dgnumlo**3._r8)*exp(4.5_r8*alnsg**2._r8) ) - aero%voltonumbhi(m) = 1._r8 / ( (pi/6._r8)*(dgnumhi**3._r8)*exp(4.5_r8*alnsg**2._r8) ) - - ! save sigmag of aitken mode - if (m == aero%mode_aitken_idx) aero%sigmag_aitken = sigmag - - ! Properties of modal species - do l = 1, aero%nspec(m) - call rad_cnst_get_aer_props(0, m, l, density_aer=aero%specdens(l,m), & - hygro_aer=aero%spechygro(l,m)) - end do - end do - - else if (nbulk > 0) then - - aero%scheme = 'bulk' - - ! Props needed for BAM number concentration calcs. - allocate( & - aername(nbulk), & - aero%num_to_mass_aer(nbulk), & - aero%mmr_bulk(nbulk), & - aero%mmrg_bulk(pcols,plev,nbulk) ) - - do iaer = 1, aero%nbulk - call rad_cnst_get_aer_props(0, iaer, & - aername = aername(iaer), & - num_to_mass_aer = aero%num_to_mass_aer(iaer) ) - - ! Look for sulfate aerosol in this list (Bulk aerosol only) - if (trim(aername(iaer)) == 'SULFATE') aero%idxsul = iaer - if (trim(aername(iaer)) == 'DUST1') aero%idxdst1 = iaer - if (trim(aername(iaer)) == 'DUST2') aero%idxdst2 = iaer - if (trim(aername(iaer)) == 'DUST3') aero%idxdst3 = iaer - if (trim(aername(iaer)) == 'DUST4') aero%idxdst4 = iaer - if (trim(aername(iaer)) == 'BCPHI') aero%idxbcphi = iaer - end do - - end if - - end subroutine zm_aero_init - - subroutine zm_conv_micro_outfld(conv, dnif, dnlf, lchnk, ncol) - - use cam_history, only: outfld - - type(zm_conv_t),intent(in) :: conv - real(r8), intent(in) :: dnlf(:,:) ! detrained convective cloud water num concen. - real(r8), intent(in) :: dnif(:,:) ! detrained convective cloud ice num concen. - integer, intent(in) :: lchnk - integer, intent(in) :: ncol - - integer :: i,k - - real(r8) :: cice_snum(pcols,pver) ! convective cloud ice sample number. - real(r8) :: cliq_snum(pcols,pver) ! convective cloud liquid sample number. - real(r8) :: crain_snum(pcols,pver) ! convective rain water sample number. - real(r8) :: csnow_snum(pcols,pver) ! convective snow sample number. - real(r8) :: wu_snum(pcols,pver) ! vertical velocity sample number - - real(r8) :: qni_snum(pcols,pver) ! convective cloud ice number sample number. - real(r8) :: qnl_snum(pcols,pver) ! convective cloud liquid number sample number. - - do k = 1,pver - do i = 1,ncol - if (conv%qice(i,k) .gt. 0.0_r8) then - cice_snum(i,k) = 1.0_r8 - else - cice_snum(i,k) = 0.0_r8 - end if - if (conv%qliq(i,k) .gt. 0.0_r8) then - cliq_snum(i,k) = 1.0_r8 - else - cliq_snum(i,k) = 0.0_r8 - end if - if (conv%qsnow(i,k) .gt. 0.0_r8) then - csnow_snum(i,k) = 1.0_r8 - else - csnow_snum(i,k) = 0.0_r8 - end if - if (conv%qrain(i,k) .gt. 0.0_r8) then - crain_snum(i,k) = 1.0_r8 - else - crain_snum(i,k) = 0.0_r8 - end if - - if (conv%qnl(i,k) .gt. 0.0_r8) then - qnl_snum(i,k) = 1.0_r8 - else - qnl_snum(i,k) = 0.0_r8 - end if - if (conv%qni(i,k) .gt. 0.0_r8) then - qni_snum(i,k) = 1.0_r8 - else - qni_snum(i,k) = 0.0_r8 - end if - if (conv%wu(i,k) .gt. 0.0_r8) then - wu_snum(i,k) = 1.0_r8 - else - wu_snum(i,k) = 0.0_r8 - end if - - end do - end do - - call outfld('ICIMRDP ',conv%qi ,pcols, lchnk ) - call outfld('CLDLIQZM',conv%qliq ,pcols, lchnk) - call outfld('CLDICEZM',conv%qice ,pcols, lchnk) - call outfld('CLIQSNUM',cliq_snum ,pcols, lchnk) - call outfld('CICESNUM',cice_snum ,pcols, lchnk) - call outfld('QRAINZM' ,conv%qrain ,pcols, lchnk) - call outfld('QSNOWZM' ,conv%qsnow ,pcols, lchnk) - call outfld('CRAINNUM',crain_snum ,pcols, lchnk) - call outfld('CSNOWNUM',csnow_snum ,pcols, lchnk) - - call outfld('WUZM' ,conv%wu ,pcols, lchnk) - call outfld('WUZMSNUM',wu_snum ,pcols, lchnk) - call outfld('QNLZM' ,conv%qnl ,pcols, lchnk) - call outfld('QNIZM' ,conv%qni ,pcols, lchnk) - call outfld('QNRZM' ,conv%qnr ,pcols, lchnk) - call outfld('QNSZM' ,conv%qns ,pcols, lchnk) - call outfld('FRZZM' ,conv%frz ,pcols, lchnk) - - call outfld('AUTOL_M' ,conv%autolm ,pcols, lchnk) - call outfld('ACCRL_M' ,conv%accrlm ,pcols, lchnk) - call outfld('BERGN_M' ,conv%bergnm ,pcols, lchnk) - call outfld('FHTIM_M' ,conv%fhtimm ,pcols, lchnk) - call outfld('FHTCT_M' ,conv%fhtctm ,pcols, lchnk) - call outfld('FHML_M' ,conv%fhmlm ,pcols, lchnk) - call outfld('HMPI_M' ,conv%hmpim ,pcols, lchnk) - call outfld('ACCSL_M' ,conv%accslm ,pcols, lchnk) - call outfld('DLF_M' ,conv%dlfm ,pcols, lchnk) - - call outfld('AUTOL_N' ,conv%autoln ,pcols, lchnk) - call outfld('ACCRL_N' ,conv%accrln ,pcols, lchnk) - call outfld('BERGN_N' ,conv%bergnn ,pcols, lchnk) - call outfld('FHTIM_N' ,conv%fhtimn ,pcols, lchnk) - call outfld('FHTCT_N' ,conv%fhtctn ,pcols, lchnk) - call outfld('FHML_N' ,conv%fhmln ,pcols, lchnk) - call outfld('ACCSL_N' ,conv%accsln ,pcols, lchnk) - call outfld('ACTIV_N' ,conv%activn ,pcols, lchnk) - call outfld('DLF_N' ,conv%dlfn ,pcols, lchnk) - call outfld('AUTOI_M' ,conv%autoim ,pcols, lchnk) - call outfld('ACCSI_M' ,conv%accsim ,pcols, lchnk) - call outfld('DIF_M' ,conv%difm ,pcols, lchnk) - call outfld('NUCLI_N' ,conv%nuclin ,pcols, lchnk) - call outfld('AUTOI_N' ,conv%autoin ,pcols, lchnk) - call outfld('ACCSI_N' ,conv%accsin ,pcols, lchnk) - call outfld('HMPI_N' ,conv%hmpin ,pcols, lchnk) - call outfld('DIF_N' ,conv%difn ,pcols, lchnk) - call outfld('COND_M' ,conv%cmel ,pcols, lchnk) - call outfld('DEPOS_M' ,conv%cmei ,pcols, lchnk) - - call outfld('TRSPC_M' ,conv%trspcm ,pcols, lchnk) - call outfld('TRSPC_N' ,conv%trspcn ,pcols, lchnk) - call outfld('TRSPI_M' ,conv%trspim ,pcols, lchnk) - call outfld('TRSPI_N' ,conv%trspin ,pcols, lchnk) - call outfld('DNIFZM' ,dnif ,pcols, lchnk) - call outfld('DNLFZM' ,dnlf ,pcols, lchnk) - - end subroutine zm_conv_micro_outfld end module zm_conv_intr diff --git a/src/physics/cam/zm_microphysics.F90 b/src/physics/cam/zm_microphysics.F90 deleted file mode 100644 index b54e1e684e..0000000000 --- a/src/physics/cam/zm_microphysics.F90 +++ /dev/null @@ -1,2455 +0,0 @@ -module zm_microphysics - -!--------------------------------------------------------------------------------- -! Purpose: -! CAM Interface for cumulus microphysics -! -! Author: Xialiang Song and Guang Jun Zhang, June 2010 -!--------------------------------------------------------------------------------- - -use shr_kind_mod, only: r8=>shr_kind_r8 -use spmd_utils, only: masterproc -use ppgrid, only: pcols, pver, pverp -use physconst, only: gravit, rair, tmelt, cpair, rh2o, r_universal, mwh2o, rhoh2o -use physconst, only: latvap, latice -!use activate_drop_mam, only: actdrop_mam_calc -use ndrop, only: activate_aerosol -use ndrop_bam, only: ndrop_bam_run -use nucleate_ice, only: nucleati -use shr_spfn_mod, only: erf => shr_spfn_erf -use shr_spfn_mod, only: gamma => shr_spfn_gamma -use wv_saturation, only: svp_water, svp_ice -use cam_logfile, only: iulog -use cam_abortutils, only: endrun -use micro_pumas_utils, only:ice_autoconversion, snow_self_aggregation, accrete_cloud_water_snow, & - secondary_ice_production, accrete_rain_snow, heterogeneous_rain_freezing, & - accrete_cloud_water_rain, self_collection_rain, accrete_cloud_ice_snow -use microp_aero, only: aerosol_properties_object -use aerosol_properties_mod, only: aerosol_properties - -implicit none -private -save - -public :: & - zm_mphyi, & - zm_mphy, & - zm_conv_t,& - zm_aero_t - -! Private module data - -! constants remaped -real(r8) :: g ! gravity -real(r8) :: mw ! molecular weight of water -real(r8) :: r ! Dry air Gas constant -real(r8) :: rv ! water vapor gas contstant -real(r8) :: rr ! universal gas constant -real(r8) :: cpp ! specific heat of dry air -real(r8) :: rhow ! density of liquid water -real(r8) :: xlf ! latent heat of freezing - -!from 'microconstants' -real(r8) :: rhosn ! bulk density snow -real(r8) :: rhoi ! bulk density ice - -real(r8) :: ac,bc,as,bs,ai,bi,ar,br !fall speed parameters -real(r8) :: ci,di !ice mass-diameter relation parameters -real(r8) :: cs,ds !snow mass-diameter relation parameters -real(r8) :: cr,dr !drop mass-diameter relation parameters -real(r8) :: Eii !collection efficiency aggregation of ice -real(r8) :: Ecc !collection efficiency -real(r8) :: Ecr !collection efficiency cloud droplets/rain -real(r8) :: DCS !autoconversion size threshold -real(r8) :: bimm,aimm !immersion freezing -real(r8) :: rhosu !typical 850mn air density -real(r8) :: mi0 ! new crystal mass -real(r8) :: rin ! radius of contact nuclei -real(r8) :: pi ! pi - -! contact freezing due to dust -! dust number mean radius (m), Zender et al JGR 2003 assuming number mode radius of 0.6 micron, sigma=2 -real(r8), parameter :: rn_dst1 = 0.258e-6_r8 -real(r8), parameter :: rn_dst2 = 0.717e-6_r8 -real(r8), parameter :: rn_dst3 = 1.576e-6_r8 -real(r8), parameter :: rn_dst4 = 3.026e-6_r8 - -! smallest mixing ratio considered in microphysics -real(r8), parameter :: qsmall = 1.e-18_r8 - - -type, public :: ptr2d - real(r8), pointer :: val(:,:) -end type ptr2d - -! Aerosols -type :: zm_aero_t - - ! Aerosol treatment - character(len=5) :: scheme ! either 'bulk' or 'modal' - - ! Bulk aerosols - integer :: nbulk = 0 ! number of bulk aerosols affecting climate - integer :: idxsul = -1 ! index in aerosol list for sulfate - integer :: idxdst1 = -1 ! index in aerosol list for dust1 - integer :: idxdst2 = -1 ! index in aerosol list for dust2 - integer :: idxdst3 = -1 ! index in aerosol list for dust3 - integer :: idxdst4 = -1 ! index in aerosol list for dust4 - integer :: idxbcphi = -1 ! index in aerosol list for Soot (BCPHI) - - real(r8), allocatable :: num_to_mass_aer(:) ! conversion of mmr to number conc for bulk aerosols - type(ptr2d), allocatable :: mmr_bulk(:) ! array of pointers to bulk aerosol mmr - real(r8), allocatable :: mmrg_bulk(:,:,:) ! gathered bulk aerosol mmr - - ! Modal aerosols - integer :: nmodes = 0 ! number of modes - integer, allocatable :: nspec(:) ! number of species in each mode - type(ptr2d), allocatable :: num_a(:) ! number mixing ratio of modes (interstitial phase) - type(ptr2d), allocatable :: mmr_a(:,:) ! species mmr in each mode (interstitial phase) - real(r8), allocatable :: numg_a(:,:,:) ! gathered number mixing ratio of modes (interstitial phase) - real(r8), allocatable :: mmrg_a(:,:,:,:) ! gathered species mmr in each mode (interstitial phase) - real(r8), allocatable :: voltonumblo(:) ! volume to number conversion (lower bound) for each mode - real(r8), allocatable :: voltonumbhi(:) ! volume to number conversion (upper bound) for each mode - real(r8), allocatable :: specdens(:,:) ! density of modal species - real(r8), allocatable :: spechygro(:,:) ! hygroscopicity of modal species - - integer :: mode_accum_idx = -1 ! index of accumulation mode - integer :: mode_aitken_idx = -1 ! index of aitken mode - integer :: mode_coarse_idx = -1 ! index of coarse mode - integer :: coarse_dust_idx = -1 ! index of dust in coarse mode - integer :: coarse_nacl_idx = -1 ! index of nacl in coarse mode - - type(ptr2d), allocatable :: dgnum(:) ! mode dry radius - real(r8), allocatable :: dgnumg(:,:,:) ! gathered mode dry radius - - real(r8) :: sigmag_aitken - -end type zm_aero_t - -type :: zm_conv_t - - real(r8), allocatable :: qi(:,:) ! wg grid slice of cloud ice. - real(r8), allocatable :: qliq(:,:) ! convective cloud liquid water. - real(r8), allocatable :: qice(:,:) ! convective cloud ice. - real(r8), allocatable :: wu(:,:) ! vertical velocity - real(r8), allocatable :: sprd(:,:) ! rate of production of snow at that layer - real(r8), allocatable :: qrain(:,:) ! convective rain water. - real(r8), allocatable :: qsnow(:,:) ! convective snow. - real(r8), allocatable :: qnl(:,:) ! convective cloud liquid water num concen. - real(r8), allocatable :: qni(:,:) ! convective cloud ice num concen. - real(r8), allocatable :: qnr(:,:) ! convective rain water num concen. - real(r8), allocatable :: qns(:,:) ! convective snow num concen. - real(r8), allocatable :: frz(:,:) ! heating rate due to freezing - real(r8), allocatable :: autolm(:,:) !mass tendency due to autoconversion of droplets to rain - real(r8), allocatable :: accrlm(:,:) !mass tendency due to accretion of droplets by rain - real(r8), allocatable :: bergnm(:,:) !mass tendency due to Bergeron process - real(r8), allocatable :: fhtimm(:,:) !mass tendency due to immersion freezing - real(r8), allocatable :: fhtctm(:,:) !mass tendency due to contact freezing - real(r8), allocatable :: fhmlm (:,:) !mass tendency due to homogeneous freezing - real(r8), allocatable :: hmpim (:,:) !mass tendency due to HM process - real(r8), allocatable :: accslm(:,:) !mass tendency due to accretion of droplets by snow - real(r8), allocatable :: dlfm (:,:) !mass tendency due to detrainment of droplet - real(r8), allocatable :: autoln(:,:) !num tendency due to autoconversion of droplets to rain - real(r8), allocatable :: accrln(:,:) !num tendency due to accretion of droplets by rain - real(r8), allocatable :: bergnn(:,:) !num tendency due to Bergeron process - real(r8), allocatable :: fhtimn(:,:) !num tendency due to immersion freezing - real(r8), allocatable :: fhtctn(:,:) !num tendency due to contact freezing - real(r8), allocatable :: fhmln (:,:) !num tendency due to homogeneous freezing - real(r8), allocatable :: accsln(:,:) !num tendency due to accretion of droplets by snow - real(r8), allocatable :: activn(:,:) !num tendency due to droplets activation - real(r8), allocatable :: dlfn (:,:) !num tendency due to detrainment of droplet - real(r8), allocatable :: autoim(:,:) !mass tendency due to autoconversion of cloud ice to snow - real(r8), allocatable :: accsim(:,:) !mass tendency due to accretion of cloud ice by snow - real(r8), allocatable :: difm (:,:) !mass tendency due to detrainment of cloud ice - real(r8), allocatable :: nuclin(:,:) !num tendency due to ice nucleation - real(r8), allocatable :: autoin(:,:) !num tendency due to autoconversion of cloud ice to snow - real(r8), allocatable :: accsin(:,:) !num tendency due to accretion of cloud ice by snow - real(r8), allocatable :: hmpin (:,:) !num tendency due to HM process - real(r8), allocatable :: difn (:,:) !num tendency due to detrainment of cloud ice - real(r8), allocatable :: cmel (:,:) !mass tendency due to condensation - real(r8), allocatable :: cmei (:,:) !mass tendency due to deposition - real(r8), allocatable :: trspcm(:,:) !LWC tendency due to convective transport - real(r8), allocatable :: trspcn(:,:) !droplet num tendency due to convective transport - real(r8), allocatable :: trspim(:,:) !IWC tendency due to convective transport - real(r8), allocatable :: trspin(:,:) !ice crystal num tendency due to convective transport - real(r8), allocatable :: dcape(:) ! CAPE change due to freezing heating - real(r8), allocatable :: lambdadpcu(:,:)! slope of cloud liquid size distr - real(r8), allocatable :: mudpcu(:,:) ! width parameter of droplet size distr - real(r8), allocatable :: di(:,:) - real(r8), allocatable :: dnl(:,:) - real(r8), allocatable :: dni(:,:) - real(r8), allocatable :: qide(:,:) ! cloud ice mixing ratio for detrainment (kg/kg) - real(r8), allocatable :: qncde(:,:) ! cloud water number concentration for detrainment (1/kg) - real(r8), allocatable :: qnide(:,:) ! cloud ice number concentration for detrainment (1/kg) - - -end type zm_conv_t - -real(r8), parameter :: dcon = 25.e-6_r8 -real(r8), parameter :: mucon = 5.3_r8 -real(r8), parameter :: lambdadpcu = (mucon + 1._r8)/dcon - -!=============================================================================== -contains -!=============================================================================== - -subroutine zm_mphyi - -!----------------------------------------------------------------------- -! -! Purpose: -! initialize constants for the cumulus microphysics -! called from zm_conv_init() in zm_conv_intr.F90 -! -! Author: Xialiang Song, June 2010 -! -!----------------------------------------------------------------------- - -!NOTE: -! latent heats should probably be fixed with temperature -! for energy conservation with the rest of the model -! (this looks like a +/- 3 or 4% effect, but will mess up energy balance) - - xlf = latice ! latent heat freezing - -! from microconstants - -! parameters below from Reisner et al. (1998) -! density parameters (kg/m3) - - rhosn = 100._r8 ! bulk density snow - rhoi = 500._r8 ! bulk density ice - rhow = 1000._r8 ! bulk density liquid - -! fall speed parameters, V = aD^b -! V is in m/s - -! droplets - ac = 3.e7_r8 - bc = 2._r8 - -! snow - as = 11.72_r8 - bs = 0.41_r8 - -! cloud ice - ai = 700._r8 - bi = 1._r8 - -! rain - ar = 841.99667_r8 - br = 0.8_r8 - -! particle mass-diameter relationship -! currently we assume spherical particles for cloud ice/snow -! m = cD^d - - pi= 3.14159265358979323846_r8 - -! cloud ice mass-diameter relationship - - ci = rhoi*pi/6._r8 - di = 3._r8 - -! snow mass-diameter relationship - - cs = rhosn*pi/6._r8 - ds = 3._r8 - -! drop mass-diameter relationship - - cr = rhow*pi/6._r8 - dr = 3._r8 - -! collection efficiency, aggregation of cloud ice and snow - - Eii = 0.1_r8 - -! collection efficiency, accretion of cloud water by rain - - Ecr = 1.0_r8 - -! autoconversion size threshold for cloud ice to snow (m) - - Dcs = 150.e-6_r8 -! immersion freezing parameters, bigg 1953 - - bimm = 100._r8 - aimm = 0.66_r8 - -! typical air density at 850 mb - - rhosu = 85000._r8/(rair * tmelt) - -! mass of new crystal due to aerosol freezing and growth (kg) - - mi0 = 4._r8/3._r8*pi*rhoi*(10.e-6_r8)*(10.e-6_r8)*(10.e-6_r8) - -! radius of contact nuclei aerosol (m) - - rin = 0.1e-6_r8 - -end subroutine zm_mphyi - -!=============================================================================== - -subroutine zm_mphy(su, qu, mu, du, eu, cmel, cmei, zf, pm, te, qe, & - eps0, jb, jt, jlcl, msg, il2g, grav, cp, rd, aero, gamhat, & - qc, qi, nc, ni, qcde, qide, ncde, nide, rprd, sprd, frz, & - wu, qr, qni, nr, ns, autolm, accrlm, bergnm, fhtimm, fhtctm, & - fhmlm, hmpim, accslm, dlfm, autoln, accrln, bergnn, fhtimn, fhtctn, & - fhmln, accsln, activn, dlfn, autoim, accsim, difm, nuclin, autoin, & - accsin, hmpin, difn, trspcm, trspcn, trspim, trspin, lamc, pgam ) - - -! Purpose: -! microphysic parameterization for Zhang-McFarlane convection scheme -! called from cldprp() in zm_conv.F90 -! -! Author: Xialiang Song, June 2010 - - use time_manager, only: get_step_size - -! variable declarations - - implicit none - -! input variables - real(r8), intent(in) :: su(pcols,pver) ! normalized dry stat energy of updraft - real(r8), intent(in) :: qu(pcols,pver) ! spec hum of updraft - real(r8), intent(in) :: mu(pcols,pver) ! updraft mass flux - real(r8), intent(in) :: du(pcols,pver) ! detrainement rate of updraft - real(r8), intent(in) :: eu(pcols,pver) ! entrainment rate of updraft - real(r8), intent(in) :: cmel(pcols,pver) ! condensation rate of updraft - real(r8), intent(in) :: cmei(pcols,pver) ! condensation rate of updraft - real(r8), intent(in) :: zf(pcols,pverp) ! height of interfaces - real(r8), intent(in) :: pm(pcols,pver) ! pressure of env - real(r8), intent(in) :: te(pcols,pver) ! temp of env - real(r8), intent(in) :: qe(pcols,pver) ! spec. humidity of env - real(r8), intent(in) :: eps0(pcols) - real(r8), intent(in) :: gamhat(pcols,pver) ! gamma=L/cp(dq*/dT) at interface - - integer, intent(in) :: jb(pcols) ! updraft base level - integer, intent(in) :: jt(pcols) ! updraft plume top - integer, intent(in) :: jlcl(pcols) ! updraft lifting cond level - integer, intent(in) :: msg ! missing moisture vals - integer, intent(in) :: il2g ! number of columns in gathered arrays - - type(zm_aero_t), intent(in) :: aero ! aerosol object - - real(r8) grav ! gravity - real(r8) cp ! heat capacity of dry air - real(r8) rd ! gas constant for dry air - -! output variables - real(r8), intent(out) :: qc(pcols,pver) ! cloud water mixing ratio (kg/kg) - real(r8), intent(out) :: qi(pcols,pver) ! cloud ice mixing ratio (kg/kg) - real(r8), intent(out) :: nc(pcols,pver) ! cloud water number conc (1/kg) - real(r8), intent(out) :: ni(pcols,pver) ! cloud ice number conc (1/kg) - real(r8), intent(out) :: qcde(pcols,pver) ! cloud water mixing ratio for detrainment(kg/kg) - real(r8), intent(out) :: qide(pcols,pver) ! cloud ice mixing ratio for detrainment (kg/kg) - real(r8), intent(out) :: ncde(pcols,pver) ! cloud water number conc for detrainment (1/kg) - real(r8), intent(out) :: nide(pcols,pver) ! cloud ice number conc for detrainment (1/kg) - real(r8), intent(out) :: wu(pcols,pver) - real(r8), intent(out) :: qni(pcols,pver) ! snow mixing ratio - real(r8), intent(out) :: qr(pcols,pver) ! rain mixing ratio - real(r8), intent(out) :: ns(pcols,pver) ! snow number conc - real(r8), intent(out) :: nr(pcols,pver) ! rain number conc - real(r8), intent(out) :: rprd(pcols,pver) ! rate of production of precip at that layer - real(r8), intent(out) :: sprd(pcols,pver) ! rate of production of snow at that layer - real(r8), intent(out) :: frz(pcols,pver) ! rate of freezing - - - real(r8), intent(inout) :: lamc(pcols,pver) ! slope of cloud liquid size distr - real(r8), intent(inout) :: pgam(pcols,pver) ! spectral width parameter of droplet size distr - -! tendency for output - real(r8),intent(out) :: autolm(pcols,pver) !mass tendency due to autoconversion of droplets to rain - real(r8),intent(out) :: accrlm(pcols,pver) !mass tendency due to accretion of droplets by rain - real(r8),intent(out) :: bergnm(pcols,pver) !mass tendency due to Bergeron process - real(r8),intent(out) :: fhtimm(pcols,pver) !mass tendency due to immersion freezing - real(r8),intent(out) :: fhtctm(pcols,pver) !mass tendency due to contact freezing - real(r8),intent(out) :: fhmlm (pcols,pver) !mass tendency due to homogeneous freezing - real(r8),intent(out) :: hmpim (pcols,pver) !mass tendency due to HM process - real(r8),intent(out) :: accslm(pcols,pver) !mass tendency due to accretion of droplets by snow - real(r8),intent(out) :: dlfm (pcols,pver) !mass tendency due to detrainment of droplet - real(r8),intent(out) :: trspcm(pcols,pver) !mass tendency of droplets due to convective transport - - real(r8),intent(out) :: autoln(pcols,pver) !num tendency due to autoconversion of droplets to rain - real(r8),intent(out) :: accrln(pcols,pver) !num tendency due to accretion of droplets by rain - real(r8),intent(out) :: bergnn(pcols,pver) !num tendency due to Bergeron process - real(r8),intent(out) :: fhtimn(pcols,pver) !num tendency due to immersion freezing - real(r8),intent(out) :: fhtctn(pcols,pver) !num tendency due to contact freezing - real(r8),intent(out) :: fhmln (pcols,pver) !num tendency due to homogeneous freezing - real(r8),intent(out) :: accsln(pcols,pver) !num tendency due to accretion of droplets by snow - real(r8),intent(out) :: activn(pcols,pver) !num tendency due to droplets activation - real(r8),intent(out) :: dlfn (pcols,pver) !num tendency due to detrainment of droplet - real(r8),intent(out) :: trspcn(pcols,pver) !num tendency of droplets due to convective transport - - real(r8),intent(out) :: autoim(pcols,pver) !mass tendency due to autoconversion of cloud ice to snow - real(r8),intent(out) :: accsim(pcols,pver) !mass tendency due to accretion of cloud ice by snow - real(r8),intent(out) :: difm (pcols,pver) !mass tendency due to detrainment of cloud ice - real(r8),intent(out) :: trspim(pcols,pver) !mass tendency of ice crystal due to convective transport - - real(r8),intent(out) :: nuclin(pcols,pver) !num tendency due to ice nucleation - real(r8),intent(out) :: autoin(pcols,pver) !num tendency due to autoconversion of cloud ice to snow - real(r8),intent(out) :: accsin(pcols,pver) !num tendency due to accretion of cloud ice by snow - real(r8),intent(out) :: hmpin (pcols,pver) !num tendency due to HM process - real(r8),intent(out) :: difn (pcols,pver) !num tendency due to detrainment of cloud ice - real(r8),intent(out) :: trspin(pcols,pver) !num tendency of ice crystal due to convective transport - -!................................................................................ -! local workspace -! all units mks unless otherwise stated - real(r8) :: deltat ! time step (s) - real(r8) :: omsm ! number near unity for round-off issues - real(r8) :: dum ! temporary dummy variable - real(r8) :: dum1 ! temporary dummy variable - real(r8) :: dum2 ! temporary dummy variable - - real(r8) :: q(pcols,pver) ! water vapor mixing ratio (kg/kg) - real(r8) :: t(pcols,pver) ! temperature (K) - real(r8) :: rho(pcols,pver) ! air density (kg m-3) - real(r8) :: dz(pcols,pver) ! height difference across model vertical level - - real(r8) :: qcic(pcols,pver) ! in-cloud cloud liquid mixing ratio - real(r8) :: qiic(pcols,pver) ! in-cloud cloud ice mixing ratio - real(r8) :: qniic(pcols,pver) ! in-precip snow mixing ratio - real(r8) :: qric(pcols,pver) ! in-precip rain mixing ratio - real(r8) :: ncic(pcols,pver) ! in-cloud droplet number conc - real(r8) :: niic(pcols,pver) ! in-cloud cloud ice number conc - real(r8) :: nsic(pcols,pver) ! in-precip snow number conc - real(r8) :: nric(pcols,pver) ! in-precip rain number conc - - real(r8) :: lami(pver) ! slope of cloud ice size distr - real(r8) :: n0i(pver) ! intercept of cloud ice size distr - real(r8) :: n0c(pver) ! intercept of cloud liquid size distr - real(r8) :: lams(pver) ! slope of snow size distr - real(r8) :: n0s(pver) ! intercept of snow size distr - real(r8) :: lamr(pver) ! slope of rain size distr - real(r8) :: n0r(pver) ! intercept of rain size distr - real(r8) :: cdist1(pver) ! size distr parameter to calculate droplet freezing - real(r8) :: lammax ! maximum allowed slope of size distr - real(r8) :: lammin ! minimum allowed slope of size distr - - real(r8) :: mnuccc(pver) ! mixing ratio tendency due to freezing of cloud water - real(r8) :: nnuccc(pver) ! number conc tendency due to freezing of cloud water - real(r8) :: mnucct(pver) ! mixing ratio tendency due to contact freezing of cloud water - real(r8) :: nnucct(pver) ! number conc tendency due to contact freezing of cloud water - real(r8) :: msacwi(pver) ! mixing ratio tendency due to HM ice multiplication - real(r8) :: nsacwi(pver) ! number conc tendency due to HM ice multiplication - real(r8) :: prf(pver) ! mixing ratio tendency due to fallout of rain - real(r8) :: psf(pver) ! mixing ratio tendency due to fallout of snow - real(r8) :: pnrf(pver) ! number conc tendency due to fallout of rain - real(r8) :: pnsf(pver) ! number conc tendency due to fallout of snow - real(r8) :: prc(pver) ! mixing ratio tendency due to autoconversion of cloud droplets - real(r8) :: nprc(pver) ! number conc tendency due to autoconversion of cloud droplets - real(r8) :: nprc1(pver) ! qr tendency due to autoconversion of cloud droplets - real(r8) :: nsagg(pver) ! ns tendency due to self-aggregation of snow - real(r8) :: dc0 ! mean size droplet size distr - real(r8) :: ds0 ! mean size snow size distr (area weighted) - real(r8) :: eci ! collection efficiency for riming of snow by droplets - real(r8) :: dv(pcols,pver) ! diffusivity of water vapor in air - real(r8) :: mua(pcols,pver) ! viscocity of air - real(r8) :: psacws(pver) ! mixing rat tendency due to collection of droplets by snow - real(r8) :: npsacws(pver) ! number conc tendency due to collection of droplets by snow - real(r8) :: pracs(pver) ! mixing rat tendency due to collection of rain by snow - real(r8) :: npracs(pver) ! number conc tendency due to collection of rain by snow - real(r8) :: mnuccr(pver) ! mixing rat tendency due to freezing of rain - real(r8) :: nnuccr(pver) ! number conc tendency due to freezing of rain - real(r8) :: pra(pver) ! mixing rat tendnency due to accretion of droplets by rain - real(r8) :: npra(pver) ! nc tendnency due to accretion of droplets by rain - real(r8) :: nragg(pver) ! nr tendency due to self-collection of rain - real(r8) :: prci(pver) ! mixing rat tendency due to autoconversion of cloud ice to snow - real(r8) :: nprci(pver) ! number conc tendency due to autoconversion of cloud ice to snow - real(r8) :: prai(pver) ! mixing rat tendency due to accretion of cloud ice by snow - real(r8) :: nprai(pver) ! number conc tendency due to accretion of cloud ice by snow - real(r8) :: prb(pver) ! rain mixing rat tendency due to Bergeron process - real(r8) :: nprb(pver) ! number conc tendency due to Bergeron process - real(r8) :: fhmrm (pcols,pver) !mass tendency due to homogeneous freezing of rain - -! fall speed - real(r8) :: arn(pcols,pver) ! air density corrected rain fallspeed parameter - real(r8) :: asn(pcols,pver) ! air density corrected snow fallspeed parameter - real(r8) :: acn(pcols,pver) ! air density corrected cloud droplet fallspeed parameter - real(r8) :: ain(pcols,pver) ! air density corrected cloud ice fallspeed parameter - real(r8) :: uns(pver) ! number-weighted snow fallspeed - real(r8) :: ums(pver) ! mass-weighted snow fallspeed - real(r8) :: unr(pver) ! number-weighted rain fallspeed - real(r8) :: umr(pver) ! mass-weighted rain fallspeed - -! conservation check - real(r8) :: qce ! dummy qc for conservation check - real(r8) :: qie ! dummy qi for conservation check - real(r8) :: nce ! dummy nc for conservation check - real(r8) :: nie ! dummy ni for conservation check - real(r8) :: qre ! dummy qr for conservation check - real(r8) :: nre ! dummy nr for conservation check - real(r8) :: qnie ! dummy qni for conservation check - real(r8) :: nse ! dummy ns for conservation check - real(r8) :: ratio ! parameter for conservation check - -! sum of source/sink terms for cloud hydrometeor - real(r8) :: qctend(pcols,pver) ! microphysical tendency qc (1/s) - real(r8) :: qitend(pcols,pver) ! microphysical tendency qi (1/s) - real(r8) :: nctend(pcols,pver) ! microphysical tendency nc (1/(kg*s)) - real(r8) :: nitend(pcols,pver) ! microphysical tendency ni (1/(kg*s)) - real(r8) :: qnitend(pcols,pver) ! snow mixing ratio source/sink term - real(r8) :: nstend(pcols,pver) ! snow number concentration source/sink term - real(r8) :: qrtend(pcols,pver) ! rain mixing ratio source/sink term - real(r8) :: nrtend(pcols,pver) ! rain number concentration source/sink term - -! terms for Bergeron process - real(r8) :: bergtsf !bergeron timescale to remove all liquid - real(r8) :: plevap ! cloud liquid water evaporation rate - -! variables for droplet activation by modal aerosols - real(r8) :: wmix, wmin, wmax, wdiab - real(r8) :: vol, nlsrc - real(r8), allocatable :: vaerosol(:), hygro(:), naermod(:) - real(r8), allocatable :: fn(:) ! number fraction of aerosols activated - real(r8), allocatable :: fm(:) ! mass fraction of aerosols activated - real(r8), allocatable :: fluxn(:) ! flux of activated aerosol number fraction into cloud (cm/s) - real(r8), allocatable :: fluxm(:) ! flux of activated aerosol mass fraction into cloud (cm/s) - real(r8) :: flux_fullact ! flux of activated aerosol fraction assuming 100% activation (cm/s) - real(r8) :: dmc - real(r8) :: ssmc - real(r8) :: dgnum_aitken - -! bulk aerosol variables - real(r8), allocatable :: naer2(:,:,:) ! new aerosol number concentration (/m3) - real(r8), allocatable :: naer2h(:,:,:) ! new aerosol number concentration (/m3) - real(r8), allocatable :: maerosol(:) ! aerosol mass conc (kg/m3) - real(r8) :: so4_num - real(r8) :: soot_num - real(r8) :: dst1_num - real(r8) :: dst2_num - real(r8) :: dst3_num - real(r8) :: dst4_num - real(r8) :: dst_num - -! droplet activation - logical :: in_cloud ! true when above cloud base layer (k > jb) - real(r8) :: smax_f ! droplet and rain size distr factor used in the - ! in-cloud smax calculation - real(r8) :: dum2l(pcols,pver) ! number conc of CCN (1/kg) - real(r8) :: npccn(pver) ! droplet activation rate - real(r8) :: ncmax - real(r8) :: mtimec ! factor to account for droplet activation timescale - -! ice nucleation - real(r8) :: dum2i(pcols,pver) ! number conc of ice nuclei available (1/kg) - real(r8) :: qs(pcols,pver) ! liquid-ice weighted sat mixing rat (kg/kg) - real(r8) :: es(pcols,pver) ! sat vapor press (pa) over water - real(r8) :: relhum(pcols,pver) ! relative humidity - real(r8) :: esi(pcols,pver) ! sat vapor press (pa) over ice - real(r8) :: nnuccd(pver) ! ice nucleation rate from deposition/cond.-freezing - real(r8) :: mnuccd(pver) ! mass tendency from ice nucleation - real(r8) :: mtime ! factor to account for ice nucleation timescale - -! output for ice nucleation - real(r8) :: nimey(pcols,pver) !number conc of ice nuclei due to meyers deposition (1/m3) - real(r8) :: nihf(pcols,pver) !number conc of ice nuclei due to heterogenous freezing (1/m3) - real(r8) :: nidep(pcols,pver) !number conc of ice nuclei due to deoposion nucleation (hetero nuc) (1/m3) - real(r8) :: niimm(pcols,pver) !number conc of ice nuclei due to immersion freezing (hetero nuc) (1/m3) - - real(r8) :: wpice, weff, fhom ! unused dummies - -! loop array variables - integer i,k, n, l - integer ii,kk, m - -! loop variables for iteration solution - integer iter,it,ltrue(pcols) - -! used in contact freezing via dust particles - real(r8) tcnt, viscosity, mfp - real(r8) slip1, slip2, slip3, slip4 - real(r8) dfaer1, dfaer2, dfaer3, dfaer4 - real(r8) nacon1,nacon2,nacon3,nacon4 - -! used in immersion freezing via soot - real(r8) ttend(pver) - real(r8) naimm - real(r8) :: ntaer(pcols,pver) - real(r8) :: ntaerh(pcols,pver) - -! used in homogeneous freezing - real(r8) :: fholm (pcols,pver) !mass tendency due to homogeneous freezing - real(r8) :: fholn (pcols,pver) !number conc tendency due to homogeneous freezing - -! used in secondary ice production - real(r8) ni_secp - -! used in vertical velocity calculation - real(r8) th(pcols,pver) - real(r8) qh(pcols,pver) - real(r8) zkine(pcols,pver) - real(r8) zbuo(pcols,pver) - real(r8) zfacbuo, cwdrag, cwifrac, retv, zbuoc - real(r8) zbc, zbe, zdkbuo, zdken - real(r8) arcf(pcols,pver) - real(r8) p(pcols,pver) - real(r8) ph(pcols,pver) - -! used in vertical integreation - logical qcimp(pver) ! true to solve qc with implicit formula - logical ncimp(pver) ! true to solve nc with implicit formula - logical qiimp(pver) ! true to solve qi with implicit formula - logical niimp(pver) ! true to solve ni with implicit formula - -! tendency due to adjustment - real(r8) :: ncadj(pcols,pver) !droplet num tendency due to adjustment - real(r8) :: niadj(pcols,pver) !ice crystal num tendency due to adjustment - real(r8) :: ncorg, niorg, total - - real(r8) :: rhoh(pcols,pver) ! air density (kg m-3) at interface - real(r8) :: rhom(pcols,pver) ! air density (kg m-3) at mid-level - real(r8) :: tu(pcols,pver) ! temperature in updraft (K) - - integer kqi(pcols),kqc(pcols) - logical lcbase(pcols), libase(pcols) - - real(r8) :: nai_bcphi, nai_dst1, nai_dst2, nai_dst3, nai_dst4 - - real(r8) flxrm, mvtrm, flxrn, mvtrn, flxsm, mvtsm, flxsn, mvtsn - integer nlr, nls - - real(r8) rmean, beta6, beta66, r6, r6c - real(r8) temp1, temp2, temp3, temp4 ! variable to store output which is not required by this routine - - class(aerosol_properties), pointer :: aero_props_obj => null() - -! Aerosol properties - aero_props_obj => aerosol_properties_object() - -!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -! initialization -!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - if (aero%scheme == 'modal') then - - allocate(vaerosol(aero%nmodes), hygro(aero%nmodes), naermod(aero%nmodes), & - fn(aero%nmodes), fm(aero%nmodes), fluxn(aero%nmodes), fluxm(aero%nmodes)) - - else if (aero%scheme == 'bulk') then - - allocate( & - naer2(pcols,pver,aero%nbulk), & - naer2h(pcols,pver,aero%nbulk), & - maerosol(aero%nbulk)) - - end if - - deltat= get_step_size() !for FV dynamical core - - ! parameters for scheme - omsm=0.99999_r8 - zfacbuo = 0.5_r8/(1._r8+0.5_r8) - cwdrag = 1.875_r8*0.506_r8 - cwifrac = 0.5_r8 - retv = 0.608_r8 - bergtsf = 1800._r8 - - ! initialize multi-level fields - do i=1,il2g - do k=1,pver - q(i,k) = qu(i,k) - tu(i,k)= su(i,k) - grav/cp*zf(i,k) - t(i,k) = su(i,k) - grav/cp*zf(i,k) - p(i,k) = 100._r8*pm(i,k) - wu(i,k) = 0._r8 - zkine(i,k)= 0._r8 - arcf(i,k) = 0._r8 - zbuo(i,k) = 0._r8 - nc(i,k) = 0._r8 - ni(i,k) = 0._r8 - qc(i,k) = 0._r8 - qi(i,k) = 0._r8 - ncde(i,k) = 0._r8 - nide(i,k) = 0._r8 - qcde(i,k) = 0._r8 - qide(i,k) = 0._r8 - rprd(i,k) = 0._r8 - sprd(i,k) = 0._r8 - frz(i,k) = 0._r8 - qcic(i,k) = 0._r8 - qiic(i,k) = 0._r8 - ncic(i,k) = 0._r8 - niic(i,k) = 0._r8 - qr(i,k) = 0._r8 - qni(i,k) = 0._r8 - nr(i,k) = 0._r8 - ns(i,k) = 0._r8 - qric(i,k) = 0._r8 - qniic(i,k) = 0._r8 - nric(i,k) = 0._r8 - nsic(i,k) = 0._r8 - nimey(i,k) = 0._r8 - nihf(i,k) = 0._r8 - nidep(i,k) = 0._r8 - niimm(i,k) = 0._r8 - fhmrm(i,k) = 0._r8 - - autolm(i,k) = 0._r8 - accrlm(i,k) = 0._r8 - bergnm(i,k) = 0._r8 - fhtimm(i,k) = 0._r8 - fhtctm(i,k) = 0._r8 - fhmlm (i,k) = 0._r8 - fholm (i,k) = 0._r8 - hmpim (i,k) = 0._r8 - accslm(i,k) = 0._r8 - dlfm (i,k) = 0._r8 - - autoln(i,k) = 0._r8 - accrln(i,k) = 0._r8 - bergnn(i,k) = 0._r8 - fhtimn(i,k) = 0._r8 - fhtctn(i,k) = 0._r8 - fhmln (i,k) = 0._r8 - fholn (i,k) = 0._r8 - accsln(i,k) = 0._r8 - activn(i,k) = 0._r8 - dlfn (i,k) = 0._r8 - - autoim(i,k) = 0._r8 - accsim(i,k) = 0._r8 - difm (i,k) = 0._r8 - - nuclin(i,k) = 0._r8 - autoin(i,k) = 0._r8 - accsin(i,k) = 0._r8 - hmpin (i,k) = 0._r8 - difn (i,k) = 0._r8 - - trspcm(i,k) = 0._r8 - trspcn(i,k) = 0._r8 - trspim(i,k) = 0._r8 - trspin(i,k) = 0._r8 - - ncadj (i,k) = 0._r8 - niadj (i,k) = 0._r8 - end do - end do - - ! initialize time-varying parameters - do k=1,pver - do i=1,il2g - if (k .eq.1) then - rhoh(i,k) = p(i,k)/(t(i,k)*rd) - rhom(i,k) = p(i,k)/(t(i,k)*rd) - th (i,k) = te(i,k) - qh (i,k) = qe(i,k) - dz (i,k) = zf(i,k) - zf(i,k+1) - ph(i,k) = p(i,k) - else - rhoh(i,k) = 0.5_r8*(p(i,k)+p(i,k-1))/(t(i,k)*rd) - if (k .eq. pver) then - rhom(i,k) = p(i,k)/(rd*t(i,k)) - else - rhom(i,k) = 2.0_r8*p(i,k)/(rd*(t(i,k)+t(i,k+1))) - end if - th (i,k) = 0.5_r8*(te(i,k)+te(i,k-1)) - qh (i,k) = 0.5_r8*(qe(i,k)+qe(i,k-1)) - dz(i,k) = zf(i,k-1) - zf(i,k) - ph(i,k) = 0.5_r8*(p(i,k) + p(i,k-1)) - end if - dv(i,k) = 8.794E-5_r8*t(i,k)**1.81_r8/ph(i,k) - mua(i,k) = 1.496E-6_r8*t(i,k)**1.5_r8/ & - (t(i,k)+120._r8) - - rho(i,k) = rhoh(i,k) - - ! air density adjustment for fallspeed parameters - ! add air density correction factor to the power of - ! 0.54 following Heymsfield and Bansemer 2006 - - arn(i,k)=ar*(rhosu/rho(i,k))**0.54_r8 - asn(i,k)=as*(rhosu/rho(i,k))**0.54_r8 - acn(i,k)=ac*(rhosu/rho(i,k))**0.54_r8 - ain(i,k)=ai*(rhosu/rho(i,k))**0.54_r8 - - end do - end do - - if (aero%scheme == 'modal') then - - wmix = 0._r8 - wmin = 0._r8 - wmax = 10._r8 - wdiab = 0._r8 - - do k=1,pver - do i=1,il2g - dum2l(i,k)=0._r8 - dum2i(i,k)=0._r8 - ntaer(i,k) = 0.0_r8 - ntaerh(i,k) = 0.0_r8 - do m = 1, aero%nmodes - ntaer(i,k) = ntaer(i,k) + aero%numg_a(i,k,m)*rhom(i,k) - enddo - end do - end do - - else if (aero%scheme == 'bulk') then - - ! initialize aerosol number - do k=1,pver - do i=1,il2g - naer2(i,k,:)=0._r8 - naer2h(i,k,:)=0._r8 - dum2l(i,k)=0._r8 - dum2i(i,k)=0._r8 - end do - end do - - do k=1,pver - do i=1,il2g - ntaer(i,k) = 0.0_r8 - ntaerh(i,k) = 0.0_r8 - do m = 1, aero%nbulk - maerosol(m) = aero%mmrg_bulk(i,k,m)*rhom(i,k) - - ! set number nucleated for sulfate based on Lohmann et al. 2000 (JGR) Eq.2 - ! Na=340.*(massSO4)^0.58 where Na=cm-3 and massSO4=ug/m3 - ! convert units to Na [m-3] and SO4 [kgm-3] - ! Na(m-3)= 1.e6 cm3 m-3 Na(cm-3)=340. *(massSO4[kg/m3]*1.e9ug/kg)^0.58 - ! or Na(m-3)= 1.e6* 340.*(1.e9ug/kg)^0.58 * (massSO4[kg/m3])^0.58 - - if (m .eq. aero%idxsul) then - naer2(i,k,m)= 5.64259e13_r8 * maerosol(m)**0.58_r8 - else - naer2(i,k,m)=maerosol(m)*aero%num_to_mass_aer(m) - end if - ntaer(i,k) = ntaer(i,k) + naer2(i,k,m) - end do - end do - end do - - end if - - do i=1,il2g - ltrue(i)=0 - do k=1,pver - if (qc(i,k).ge.qsmall.or.qi(i,k).ge.qsmall.or.cmel(i,k).ge.qsmall.or.cmei(i,k).ge.qsmall) ltrue(i)=1 - end do - end do - - ! skip microphysical calculations if no cloud water - do i=1,il2g - if (ltrue(i).eq.0) then - do k=1,pver - qctend(i,k)=0._r8 - qitend(i,k)=0._r8 - qnitend(i,k)=0._r8 - qrtend(i,k)=0._r8 - nctend(i,k)=0._r8 - nitend(i,k)=0._r8 - nrtend(i,k)=0._r8 - nstend(i,k)=0._r8 - qniic(i,k)=0._r8 - qric(i,k)=0._r8 - nsic(i,k)=0._r8 - nric(i,k)=0._r8 - qni(i,k)=0._r8 - qr(i,k)=0._r8 - ns(i,k)=0._r8 - nr(i,k)=0._r8 - qc(i,k) = 0._r8 - qi(i,k) = 0._r8 - nc(i,k) = 0._r8 - ni(i,k) = 0._r8 - qcde(i,k) = 0._r8 - qide(i,k) = 0._r8 - ncde(i,k) = 0._r8 - nide(i,k) = 0._r8 - rprd(i,k) = 0._r8 - sprd(i,k) = 0._r8 - frz(i,k) = 0._r8 - end do - goto 300 - end if - - kqc(i) = 1 - kqi(i) = 1 - lcbase(i) = .true. - libase(i) = .true. - - ! assign number of steps for iteration - ! use 2 steps following Song and Zhang, 2011, J. Clim. - iter = 2 - - !cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - ! iteration - !cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - do it=1,iter - - ! initialize sub-step microphysical tendencies - do k=1,pver - qctend(i,k)=0._r8 - qitend(i,k)=0._r8 - qnitend(i,k)=0._r8 - qrtend(i,k)=0._r8 - nctend(i,k)=0._r8 - nitend(i,k)=0._r8 - nrtend(i,k)=0._r8 - nstend(i,k)=0._r8 - rprd(i,k) = 0._r8 - sprd(i,k) = 0._r8 - frz(i,k) = 0._r8 - qniic(i,k)=0._r8 - qric(i,k)=0._r8 - nsic(i,k)=0._r8 - nric(i,k)=0._r8 - qiic(i,k)=0._r8 - qcic(i,k)=0._r8 - niic(i,k)=0._r8 - ncic(i,k)=0._r8 - qcimp(k) = .false. - ncimp(k) = .false. - qiimp(k) = .false. - niimp(k) = .false. - dum2l(i,k)=0._r8 - dum2i(i,k)=0._r8 - autolm(i,k) = 0._r8 - accrlm(i,k) = 0._r8 - bergnm(i,k) = 0._r8 - fhtimm(i,k) = 0._r8 - fhtctm(i,k) = 0._r8 - fhmlm (i,k) = 0._r8 - fholm (i,k) = 0._r8 - hmpim (i,k) = 0._r8 - accslm(i,k) = 0._r8 - dlfm (i,k) = 0._r8 - - autoln(i,k) = 0._r8 - accrln(i,k) = 0._r8 - bergnn(i,k) = 0._r8 - fhtimn(i,k) = 0._r8 - fhtctn(i,k) = 0._r8 - fhmln (i,k) = 0._r8 - fholn (i,k) = 0._r8 - accsln(i,k) = 0._r8 - activn(i,k) = 0._r8 - dlfn (i,k) = 0._r8 - ncadj (i,k) = 0._r8 - - autoim(i,k) = 0._r8 - accsim(i,k) = 0._r8 - difm (i,k) = 0._r8 - - nuclin(i,k) = 0._r8 - autoin(i,k) = 0._r8 - accsin(i,k) = 0._r8 - hmpin (i,k) = 0._r8 - difn (i,k) = 0._r8 - niadj (i,k) = 0._r8 - - trspcm(i,k) = 0._r8 - trspcn(i,k) = 0._r8 - trspim(i,k) = 0._r8 - trspin(i,k) = 0._r8 - - fhmrm (i,k) = 0._r8 - end do - - do k = pver,msg+2,-1 - - es(i,k) = svp_water(t(i,k)) ! over water in mixed clouds - esi(i,k) = svp_ice(t(i,k)) ! over ice - - if (k > jt(i) .and. k <= jb(i) .and. eps0(i) > 0._r8 & - .and.mu(i,k).gt.0._r8 .and. mu(i,k-1).gt.0._r8) then - - ! initialize precip fallspeeds to zero - if (it.eq.1) then - ums(k)=0._r8 - uns(k)=0._r8 - umr(k)=0._r8 - unr(k)=0._r8 - prf(k)=0._r8 - pnrf(k)=0._r8 - psf(k) =0._r8 - pnsf(k) = 0._r8 - end if - ttend(k)=0._r8 - nnuccd(k)=0._r8 - npccn(k)=0._r8 - - !************************************************************************************ - ! obtain values of cloud water/ice mixing ratios and number concentrations in updraft - ! for microphysical process calculations - ! units are kg/kg for mixing ratio, 1/kg for number conc - !************************************************************************************ - - - if (it.eq.1) then - qcic(i,k) = qc(i,k) - qiic(i,k) = qi(i,k) - ncic(i,k) = nc(i,k) - niic(i,k) = ni(i,k) - qniic(i,k)= qni(i,k) - qric(i,k) = qr(i,k) - nsic(i,k) = ns(i,k) - nric(i,k) = nr(i,k) - else - if (k.le.kqc(i)) then - qcic(i,k) = qc(i,k) - ncic(i,k) = nc(i,k) - - ! consider rain falling from above - flxrm = 0._r8 - mvtrm = 0._r8 - flxrn = 0._r8 - mvtrn = 0._r8 - nlr = 0 - - do kk= k,jt(i)+3,-1 - if (qr(i,kk-1) .gt. 0._r8) then - nlr = nlr + 1 - flxrm = flxrm + umr(kk-1)*qr(i,kk-1)*arcf(i,kk-1) - flxrn = flxrn + unr(kk-1)*nr(i,kk-1)*arcf(i,kk-1) - mvtrm = mvtrm + umr(kk-1)*arcf(i,kk-1) - mvtrn = mvtrn + unr(kk-1)*arcf(i,kk-1) - end if - end do - if (mvtrm.gt.0) then - qric(i,k) = (qr(i,k)*mu(i,k)+flxrm)/(mu(i,k)+mvtrm) - else - qric(i,k) = qr(i,k) - end if - if (mvtrn.gt.0) then - nric(i,k) = (nr(i,k)*mu(i,k)+flxrn)/(mu(i,k)+mvtrn) - else - nric(i,k) = nr(i,k) - end if - - end if - if (k.eq.kqc(i)) then - qcic(i,k) = qc(i,k-1) - ncic(i,k) = nc(i,k-1) - end if - if(k.le.kqi(i)) then - qiic(i,k) = qi(i,k) - niic(i,k) = ni(i,k) -! consider snow falling from above - flxsm = 0._r8 - mvtsm = 0._r8 - flxsn = 0._r8 - mvtsn = 0._r8 - nls = 0 - - do kk= k,jt(i)+3,-1 - if (qni(i,kk-1) .gt. 0._r8) then - nls = nls + 1 - flxsm = flxsm + ums(kk-1)*qni(i,kk-1)*arcf(i,kk-1) - mvtsm = mvtsm + ums(kk-1)*arcf(i,kk-1) - flxsn = flxsn + uns(kk-1)*ns(i,kk-1)*arcf(i,kk-1) - mvtsn = mvtsn + uns(kk-1)*arcf(i,kk-1) - end if - end do - - if (mvtsm.gt.0) then - qniic(i,k) = (qni(i,k)*mu(i,k)+flxsm)/(mu(i,k)+mvtsm) - else - qniic(i,k) = qni(i,k) - end if - if (mvtsn.gt.0) then - nsic(i,k) = (ns(i,k)*mu(i,k)+flxsn)/(mu(i,k)+mvtsn) - else - nsic(i,k) = ns(i,k) - end if - end if - if(k.eq.kqi(i)) then - qiic(i,k) = qi(i,k-1) - niic(i,k) = ni(i,k-1) - end if - end if - - !********************************************************************** - ! boundary condition for cloud liquid water and cloud ice - !*********************************************************************** - - ! boundary condition for provisional cloud water - if (cmel(i,k-1).gt.qsmall .and. lcbase(i) .and. it.eq.1 ) then - kqc(i) = k - lcbase(i) = .false. - qcic(i,k) = dz(i,k)*cmel(i,k-1)/(mu(i,k-1)+dz(i,k)*du(i,k-1)) - ncic(i,k) = qcic(i,k)/(4._r8/3._r8*pi*10.e-6_r8**3*rhow) - end if - - ! boundary condition for provisional cloud ice - if (qiic(i,k).gt.qsmall .and. libase(i) .and. it.eq.1 ) then - kqi(i) = k - libase(i) = .false. - else if ( cmei(i,k-1).gt.qsmall .and. & - cmei(i,k).lt.qsmall .and. k.le.jb(i) .and. libase(i) .and. it.eq.1 ) then - kqi(i)=k - libase(i) = .false. - qiic(i,k) = dz(i,k)*cmei(i,k-1)/(mu(i,k-1)+dz(i,k)*du(i,k-1)) - niic(i,k) = qiic(i,k)/(4._r8/3._r8*pi*25.e-6_r8**3*rhoi) - end if - - !*************************************************************************** - ! get size distribution parameters based on in-cloud cloud water/ice - ! these calculations also ensure consistency between number and mixing ratio - !*************************************************************************** - ! cloud ice - if (qiic(i,k).ge.qsmall) then - - ! add upper limit to in-cloud number concentration to prevent numerical error - niic(i,k)=min(niic(i,k),qiic(i,k)*1.e20_r8) - lami(k) = (gamma(1._r8+di)*ci* & - niic(i,k)/qiic(i,k))**(1._r8/di) - n0i(k) = niic(i,k)*lami(k) - - ! check for slope - lammax = 1._r8/10.e-6_r8 - lammin = 1._r8/(2._r8*dcs) - - ! adjust vars - if (lami(k).lt.lammin) then - lami(k) = lammin - n0i(k) = lami(k)**(di+1._r8)*qiic(i,k)/(ci*gamma(1._r8+di)) - niic(i,k) = n0i(k)/lami(k) - else if (lami(k).gt.lammax) then - lami(k) = lammax - n0i(k) = lami(k)**(di+1._r8)*qiic(i,k)/(ci*gamma(1._r8+di)) - niic(i,k) = n0i(k)/lami(k) - end if - else - lami(k) = 0._r8 - n0i(k) = 0._r8 - end if - - ! cloud water - if (qcic(i,k).ge.qsmall) then - - ! add upper limit to in-cloud number concentration to prevent numerical error - ncic(i,k)=min(ncic(i,k),qcic(i,k)*1.e20_r8) - - ! get pgam from fit to observations of martin et al. 1994 - - pgam(i,k)=0.0005714_r8*(ncic(i,k)/1.e6_r8/rho(i,k))+0.2714_r8 - pgam(i,k)=1._r8/(pgam(i,k)**2)-1._r8 - pgam(i,k)=max(pgam(i,k),2._r8) - pgam(i,k)=min(pgam(i,k),15._r8) - - ! calculate lamc - lamc(i,k) = (pi/6._r8*rhow*ncic(i,k)*gamma(pgam(i,k)+4._r8)/ & - (qcic(i,k)*gamma(pgam(i,k)+1._r8)))**(1._r8/3._r8) - - ! lammin, 50 micron diameter max mean size - lammin = (pgam(i,k)+1._r8)/40.e-6_r8 - lammax = (pgam(i,k)+1._r8)/1.e-6_r8 - - if (lamc(i,k).lt.lammin) then - lamc(i,k) = lammin - ncic(i,k) = 6._r8*lamc(i,k)**3*qcic(i,k)* & - gamma(pgam(i,k)+1._r8)/ & - (pi*rhow*gamma(pgam(i,k)+4._r8)) - else if (lamc(i,k).gt.lammax) then - lamc(i,k) = lammax - ncic(i,k) = 6._r8*lamc(i,k)**3*qcic(i,k)* & - gamma(pgam(i,k)+1._r8)/ & - (pi*rhow*gamma(pgam(i,k)+4._r8)) - end if - - ! parameter to calculate droplet freezing - - cdist1(k) = ncic(i,k)/gamma(pgam(i,k)+1._r8) - else - lamc(i,k) = 0._r8 - cdist1(k) = 0._r8 - end if - - ! boundary condition for cloud liquid water - if ( kqc(i) .eq. k ) then - qc(i,k) = 0._r8 - nc(i,k) = 0._r8 - end if - - ! boundary condition for cloud ice - if (kqi(i).eq.k ) then - qi(i,k) = 0._r8 - ni(i,k) = 0._r8 - end if - - !************************************************************************** - ! begin micropysical process calculations - !************************************************************************** - - !................................................................. - ! autoconversion of cloud liquid water to rain - ! formula from Khrouditnov and Kogan (2000) - ! minimum qc of 1 x 10^-8 prevents floating point error - - if (qcic(i,k).ge.1.e-8_r8) then - - ! nprc is increase in rain number conc due to autoconversion - ! nprc1 is decrease in cloud droplet conc due to autoconversion - ! Khrouditnov and Kogan (2000) -! prc(k) = 1350._r8*qcic(i,k)**2.47_r8* & -! (ncic(i,k)/1.e6_r8*rho(i,k))**(-1.79_r8) - - ! Liu and Daum(2004)(modified), Wood(2005) - rmean = 1.e6_r8*((qcic(i,k)/ncic(i,k))/(4._r8/3._r8*pi*rhow))**(1._r8/3._r8) - - if (rmean .ge. 15._r8) then - - beta6 = (1._r8+3._r8/rmean)**(1._r8/3._r8) - beta66 = (1._r8+3._r8/rmean)**2._r8 - r6 = beta6*rmean - r6c = 7.5_r8/(r6**0.5_r8*(qcic(i,k)*rho(i,k))**(1._r8/6._r8)) - prc(k) = 1.3e9_r8*beta66*(qcic(i,k)*rho(i,k))**3._r8/ & - (ncic(i,k)*rho(i,k))*max(0._r8,r6-r6c)/rho(i,k) - - nprc1(k) = prc(k)/(qcic(i,k)/ncic(i,k)) - nprc(k) = nprc1(k)*0.5_r8 - else - prc(k)=0._r8 - nprc(k)=0._r8 - nprc1(k)=0._r8 - end if - else - prc(k)=0._r8 - nprc(k)=0._r8 - nprc1(k)=0._r8 - end if - - ! provisional rain mixing ratio and number concentration (qric and nric) - ! at boundary are estimated via autoconversion - - if (k.eq.kqc(i) .and. it.eq.1) then - qric(i,k) = prc(k)*dz(i,k)/0.55_r8 - nric(i,k) = nprc(k)*dz(i,k)/0.55_r8 - qr(i,k) = 0.0_r8 - nr(i,k) = 0.0_r8 - end if - - !....................................................................... - ! Autoconversion of cloud ice to snow - ! similar to Ferrier (1994) - - call ice_autoconversion(t(i,k), qiic(i,k), lami(k), n0i(k), dcs, prci(k), nprci(k), 1) - - ! provisional snow mixing ratio and number concentration (qniic and nsic) - ! at boundary are estimated via autoconversion - - if (k.eq.kqi(i) .and. it.eq.1) then - qniic(i,k)= prci(k)*dz(i,k)*0.25_r8 - nsic(i,k)= nprci(k)*dz(i,k)*0.25_r8 - qni(i,k)= 0.0_r8 - ns(i,k)= 0.0_r8 - end if - - ! if precip mix ratio is zero so should number concentration - if (qniic(i,k).lt.qsmall) then - qniic(i,k)=0._r8 - nsic(i,k)=0._r8 - end if - if (qric(i,k).lt.qsmall) then - qric(i,k)=0._r8 - nric(i,k)=0._r8 - end if - - ! make sure number concentration is a positive number to avoid - ! taking root of negative later - nric(i,k)=max(nric(i,k),0._r8) - nsic(i,k)=max(nsic(i,k),0._r8) - - !********************************************************************** - ! get size distribution parameters for precip - !********************************************************************** - ! rain - - if (qric(i,k).ge.qsmall) then - lamr(k) = (pi*rhow*nric(i,k)/qric(i,k))**(1._r8/3._r8) - n0r(k) = nric(i,k)*lamr(k) - - ! check for slope - lammax = 1._r8/150.e-6_r8 - lammin = 1._r8/3000.e-6_r8 - - ! adjust vars - if (lamr(k).lt.lammin) then - lamr(k) = lammin - n0r(k) = lamr(k)**4*qric(i,k)/(pi*rhow) - nric(i,k) = n0r(k)/lamr(k) - else if (lamr(k).gt.lammax) then - lamr(k) = lammax - n0r(k) = lamr(k)**4*qric(i,k)/(pi*rhow) - nric(i,k) = n0r(k)/lamr(k) - end if - - ! provisional rain number and mass weighted mean fallspeed (m/s) - ! Eq.18 of Morrison and Gettelman, 2008, J. Climate - unr(k) = min(arn(i,k)*gamma(1._r8+br)/lamr(k)**br,10._r8) - umr(k) = min(arn(i,k)*gamma(4._r8+br)/(6._r8*lamr(k)**br),10._r8) - else - lamr(k) = 0._r8 - n0r(k) = 0._r8 - umr(k) = 0._r8 - unr(k) = 0._r8 - end if - - !...................................................................... - ! snow - if (qniic(i,k).ge.qsmall) then - lams(k) = (gamma(1._r8+ds)*cs*nsic(i,k)/ & - qniic(i,k))**(1._r8/ds) - n0s(k) = nsic(i,k)*lams(k) - - ! check for slope - lammax = 1._r8/10.e-6_r8 - lammin = 1._r8/2000.e-6_r8 - - ! adjust vars - if (lams(k).lt.lammin) then - lams(k) = lammin - n0s(k) = lams(k)**(ds+1._r8)*qniic(i,k)/(cs*gamma(1._r8+ds)) - nsic(i,k) = n0s(k)/lams(k) - else if (lams(k).gt.lammax) then - lams(k) = lammax - n0s(k) = lams(k)**(ds+1._r8)*qniic(i,k)/(cs*gamma(1._r8+ds)) - nsic(i,k) = n0s(k)/lams(k) - end if - - ! provisional snow number and mass weighted mean fallspeed (m/s) - ums(k) = min(asn(i,k)*gamma(4._r8+bs)/(6._r8*lams(k)**bs),3.6_r8) - uns(k) = min(asn(i,k)*gamma(1._r8+bs)/lams(k)**bs,3.6_r8) - else - lams(k) = 0._r8 - n0s(k) = 0._r8 - ums(k) = 0._r8 - uns(k) = 0._r8 - end if - - !....................................................................... - ! snow self-aggregation from passarelli, 1978, used by Reisner(1998,Eq.A.35) - ! this is hard-wired for bs = 0.4 for now - ! ignore self-collection of cloud ice - - call snow_self_aggregation(t(i,k), rho(i,k), asn(i,k), rhosn, qniic(i,k), nsic(i,k), nsagg(k), 1) - - !....................................................................... - ! accretion of cloud droplets onto snow/graupel - ! here use continuous collection equation with - ! simple gravitational collection kernel - ! ignore collisions between droplets/cloud ice - - ! ignore collision of snow with droplets above freezing - - call accrete_cloud_water_snow(t(i,k), rho(i,k), asn(i,k), uns(k), mua(i,k), & - qcic(i,k), ncic(i,k), qniic(i,k), pgam(i,k), lamc(i,k), lams(k), n0s(k), & - psacws(k), npsacws(k), 1) - - ! secondary ice production due to accretion of droplets by snow - ! (Hallet-Mossop process) (from Cotton et al., 1986) - - call secondary_ice_production(t(i,k), psacws(k), msacwi(k), nsacwi(k), 1) - - !....................................................................... - ! accretion of rain water by snow - ! formula from ikawa and saito, 1991, used by reisner et al., 1998 - - call accrete_rain_snow(t(i,k), rho(i,k), umr(k), ums(k), unr(k), uns(k), qric(i,k), & - qniic(i,k), lamr(k), n0r(k), lams(k), n0s(k), pracs(k), npracs(k), 1 ) - - !....................................................................... - ! heterogeneous freezing of rain drops - ! follows from Bigg (1953) - - call heterogeneous_rain_freezing(t(i,k), qric(i,k), nric(i,k), lamr(k), mnuccr(k), nnuccr(k), 1) - - !....................................................................... - ! accretion of cloud liquid water by rain - ! formula from Khrouditnov and Kogan (2000) - ! gravitational collection kernel, droplet fall speed neglected - - call accrete_cloud_water_rain(.true., qric(i,k), qcic(i,k), ncic(i,k), [1._r8], [0._r8], pra(k), npra(k), 1) - - !....................................................................... - ! Self-collection of rain drops - ! from Beheng(1994) - - call self_collection_rain(rho(i,k), qric(i,k), nric(i,k), nragg(k), 1) - - !....................................................................... - ! Accretion of cloud ice by snow - ! For this calculation, it is assumed that the Vs >> Vi - ! and Ds >> Di for continuous collection - - call accrete_cloud_ice_snow(t(i,k), rho(i,k), asn(i,k), qiic(i,k), niic(i,k), & - qniic(i,k), lams(k), n0s(k), prai(k), nprai(k), 1) - - !....................................................................... - ! fallout term - prf(k) = -umr(k)*qric(i,k)/dz(i,k) - pnrf(k) = -unr(k)*nric(i,k)/dz(i,k) - psf(k) = -ums(k)*qniic(i,k)/dz(i,k) - pnsf(k) = -uns(k)*nsic(i,k)/dz(i,k) - - !........................................................................ - ! calculate vertical velocity in cumulus updraft - - if (k.eq.jb(i)) then - zkine(i,jb(i)) = 0.5_r8 - wu (i,jb(i)) = 1._r8 - zbuo (i,jb(i)) = (tu(i,jb(i))*(1._r8+retv*qu(i,jb(i)))- & - th(i,jb(i))*(1._r8+retv*qh(i,jb(i))))/ & - (th(i,jb(i))*(1._r8+retv*qh(i,jb(i)))) - else - if (.true.) then - ! ECMWF formula - zbc = tu(i,k)*(1._r8+retv*qu(i,k)-qr(i,k)-qni(i,k)-qi(i,k)-qc(i,k)) - zbe = th(i,k)*(1._r8+retv*qh(i,k)) - zbuo(i,k) = (zbc-zbe)/zbe - zbuoc= (zbuo(i,k)+zbuo(i,k+1))*0.5_r8 - zdkbuo = dz(i,k+1)*grav*zfacbuo*zbuoc - zdken = min(.99_r8,(1._r8+cwdrag)*max(du(i,k),eu(i,k))*dz(i,k+1)/ & - max(1.e-10_r8,mu(i,k+1))) - zkine(i,k) = (zkine(i,k+1)*(1._r8-zdken)+zdkbuo)/ & - (1._r8+zdken) - else - ! Gregory formula - zbc = tu(i,k)*(1._r8+retv*qu(i,k)) - zbe = th(i,k)*(1._r8+retv*qh(i,k)) - zbuo(i,k) = (zbc-zbe)/zbe-qr(i,k)-qni(i,k)-qi(i,k)-qc(i,k) - zbuoc= (zbuo(i,k)+zbuo(i,k+1))*0.5_r8 - zdkbuo = dz(i,k+1)*grav*zbuoc*(1.0_r8-0.25_r8)/6._r8 - zdken = du(i,k)*dz(i,k+1)/max(1.e-10_r8,mu(i,k+1)) - zkine(i,k) = (zkine(i,k+1)*(1._r8-zdken)+zdkbuo)/ & - (1._r8+zdken) - end if - wu(i,k) = min(15._r8,sqrt(2._r8*max(0.1_r8,zkine(i,k) ))) - end if - - arcf(i,k)= mu(i,k)/wu(i,k) - - !............................................................................ - ! droplet activation - ! calculate potential for droplet activation if cloud water is present - ! formulation from Abdul-Razzak and Ghan (2000) and Abdul-Razzak et al. (1998), AR98 - - if (aero%scheme == 'bulk') then - naer2h(i,k,:) = 0.5_r8*(naer2(i,k,:) + naer2(i,k-1,:)) - end if - - ntaerh(i,k) = 0.5_r8*(ntaer(i,k) + ntaer(i,k-1)) - - if (qcic(i,k).ge.qsmall ) then - - if (aero%scheme == 'modal') then - - nlsrc = 0._r8 - - do m = 1, aero%nmodes - vaerosol(m) = 0._r8 - hygro(m) = 0._r8 - do l = 1, aero%nspec(m) - vol = max(0.5_r8*(aero%mmrg_a(i,k,l,m)+aero%mmrg_a(i,k-1,l,m)) , 0._r8)/aero%specdens(l,m) - vaerosol(m) = vaerosol(m) + vol - hygro(m) = hygro(m) + vol*aero%spechygro(l,m) - end do - if (vaerosol(m) > 1.0e-30_r8) then - hygro(m) = hygro(m)/(vaerosol(m)) - vaerosol(m) = vaerosol(m)*rho(i,k) - else - hygro(m) = 0.0_r8 - vaerosol(m) = 0.0_r8 - endif - naermod(m) = 0.5_r8*(aero%numg_a(i,k,m)+aero%numg_a(i,k-1,m))*rho(i,k) - naermod(m) = max(naermod(m), vaerosol(m)*aero%voltonumbhi(m)) - naermod(m) = min(naermod(m), vaerosol(m)*aero%voltonumblo(m)) - end do - - in_cloud = (k < jb(i)) - smax_f = 0.0_r8 - if (in_cloud) then - if ( qcic(i,k).ge.qsmall ) & - smax_f = ncic(i,k)/lamc(i,k) * gamma(2.0_r8 + pgam(i,k))/gamma(1.0_r8 + pgam(i,k)) - if ( qric(i,k).ge.qsmall) smax_f = smax_f + nric(i,k)/lamr(k) - - end if - - call activate_aerosol( & - wu(i,k), wmix, wdiab, wmin, wmax, & - t(i,k), rho(i,k), naermod, aero%nmodes, vaerosol, & - hygro, aero_props_obj, fn, fm, & - fluxn, fluxm, flux_fullact, in_cloud_in=in_cloud, smax_f=smax_f) - - do m = 1, aero%nmodes - nlsrc = nlsrc + fn(m)*naermod(m) ! number nucleated - end do - - if (nlsrc .ne. nlsrc) then - write(iulog,*) "nlsrc=",nlsrc,"wu(i,k)=",wu(i,k) - write(iulog,*) "fn(m)=",fn,"naermod(m)=",naermod,"aero%specdens(l,m)=",aero%specdens - write(iulog,*) "vaerosol(m)=",vaerosol,"aero%voltonumbhi(m)=",aero%voltonumbhi - write(iulog,*) "aero%voltonumblo(m)=",aero%voltonumblo,"k=",k,"i=",i - write(iulog,*) "aero%numg_a(i,k,m)=",aero%numg_a(i,k,:),"rho(i,k)=",rho(i,k) - write(iulog,*) "aero%mmrg_a(i,k,l,m)=",aero%mmrg_a(i,k,:,:) - end if - - dum2l(i,k) = nlsrc - - else if (aero%scheme == 'bulk') then - - call ndrop_bam_run( & - wu(i,k), t(i,k), rho(i,k), naer2h(i,k,:), aero%nbulk, & - aero%nbulk, maerosol, dum2) - - dum2l(i,k) = dum2 - - end if - - else - dum2l(i,k) = 0._r8 - end if - - ! get droplet activation rate - if (qcic(i,k).ge.qsmall .and. t(i,k).gt.238.15_r8 .and. k.gt.jt(i)+2 ) then - - ! assume aerosols already activated are equal number of existing droplets for simplicity - if (k.eq.kqc(i)) then - npccn(k) = dum2l(i,k)/deltat - else - npccn(k) = (dum2l(i,k)-ncic(i,k))/deltat - end if - - ! make sure number activated > 0 - npccn(k) = max(0._r8,npccn(k)) - ncmax = dum2l(i,k) - else - npccn(k)=0._r8 - ncmax = 0._r8 - end if - - !.............................................................................. - !ice nucleation - es(i,k) = svp_water(t(i,k)) ! over water in mixed clouds - esi(i,k) = svp_ice(t(i,k)) ! over ice - qs(i,k) = 0.622_r8*es(i,k)/(ph(i,k) - (1.0_r8-0.622_r8)*es(i,k)) - qs(i,k) = min(1.0_r8,qs(i,k)) - if (qs(i,k) < 0.0_r8) qs(i,k) = 1.0_r8 - - relhum(i,k)= 1.0_r8 - - if (t(i,k).lt.tmelt ) then - - ! compute aerosol number for so4, soot, and dust with units #/cm^3 - so4_num = 0._r8 - soot_num = 0._r8 - dst1_num = 0._r8 - dst2_num = 0._r8 - dst3_num = 0._r8 - dst4_num = 0._r8 - - if (aero%scheme == 'modal') then - - !For modal aerosols, assume for the upper troposphere: - ! soot = accumulation mode - ! sulfate = aiken mode - ! dust = coarse mode - ! since modal has internal mixtures. - soot_num = 0.5_r8*(aero%numg_a(i,k-1,aero%mode_accum_idx) & - +aero%numg_a(i,k,aero%mode_accum_idx))*rho(i,k)*1.0e-6_r8 - dmc = 0.5_r8*(aero%mmrg_a(i,k-1,aero%coarse_dust_idx,aero%mode_coarse_idx) & - +aero%mmrg_a(i,k,aero%coarse_dust_idx,aero%mode_coarse_idx)) - ssmc = 0.5_r8*(aero%mmrg_a(i,k-1,aero%coarse_nacl_idx,aero%mode_coarse_idx) & - +aero%mmrg_a(i,k,aero%coarse_nacl_idx,aero%mode_coarse_idx)) - if (dmc > 0._r8) then - dst_num = dmc/(ssmc + dmc) *(aero%numg_a(i,k-1,aero%mode_coarse_idx) & - + aero%numg_a(i,k,aero%mode_coarse_idx))*0.5_r8*rho(i,k)*1.0e-6_r8 - else - dst_num = 0.0_r8 - end if - dgnum_aitken = 0.5_r8*(aero%dgnumg(i,k,aero%mode_aitken_idx)+ & - aero%dgnumg(i,k-1,aero%mode_aitken_idx)) - if (dgnum_aitken > 0._r8) then - ! only allow so4 with D>0.1 um in ice nucleation - so4_num = 0.5_r8*(aero%numg_a(i,k-1,aero%mode_aitken_idx)+ & - aero%numg_a(i,k,aero%mode_aitken_idx))*rho(i,k)*1.0e-6_r8 & - * (0.5_r8 - 0.5_r8*erf(log(0.1e-6_r8/dgnum_aitken)/ & - (2._r8**0.5_r8*log(aero%sigmag_aitken)))) - else - so4_num = 0.0_r8 - end if - so4_num = max(0.0_r8, so4_num) - - else if (aero%scheme == 'bulk') then - - if (aero%idxsul > 0) then - so4_num = naer2h(i,k,aero%idxsul)/25._r8 *1.0e-6_r8 - end if - if (aero%idxbcphi > 0) then - soot_num = naer2h(i,k,aero%idxbcphi)/25._r8 *1.0e-6_r8 - end if - if (aero%idxdst1 > 0) then - dst1_num = naer2h(i,k,aero%idxdst1)/25._r8 *1.0e-6_r8 - end if - if (aero%idxdst2 > 0) then - dst2_num = naer2h(i,k,aero%idxdst2)/25._r8 *1.0e-6_r8 - end if - if (aero%idxdst3 > 0) then - dst3_num = naer2h(i,k,aero%idxdst3)/25._r8 *1.0e-6_r8 - end if - if (aero%idxdst4 > 0) then - dst4_num = naer2h(i,k,aero%idxdst4)/25._r8 *1.0e-6_r8 - end if - dst_num = dst1_num + dst2_num + dst3_num + dst4_num - - end if - - ! *** Turn off soot nucleation *** - soot_num = 0.0_r8 - - ! Liu et al.,J. climate, 2007 - if ( wu(i,k) .lt. 4.0_r8) then - call nucleati( & - wu(i,k), t(i,k), ph(i,k), relhum(i,k), 1.0_r8, qcic(i,k), & - 1.0e-20_r8, 0.0_r8, rho(i,k), so4_num, dst_num, soot_num, 1.0_r8, & - dum2i(i,k), nihf(i,k), niimm(i,k), nidep(i,k), nimey(i,k), & - wpice, weff, fhom, temp1, temp2, temp3, temp4, .true. ) - end if - nihf(i,k)=nihf(i,k)*rho(i,k) ! convert from #/kg -> #/m3) - niimm(i,k)=niimm(i,k)*rho(i,k) - nidep(i,k)=nidep(i,k)*rho(i,k) - nimey(i,k)=nimey(i,k)*rho(i,k) - - if (.false.) then - ! cooper curve (factor of 1000 is to convert from L-1 to m-3) - !dum2i(i,k)=0.005_r8*exp(0.304_r8*(273.15_r8-t(i,k)))*1000._r8 - - ! put limit on number of nucleated crystals, set to number at T=-30 C - ! cooper (limit to value at -35 C) - !dum2i(i,k)=min(dum2i(i,k),208.9e3_r8)/rho(i,k) ! convert from m-3 to kg-1 - end if - - else - dum2i(i,k)=0._r8 - end if - - ! ice nucleation if activated nuclei exist at t<0C - - if (dum2i(i,k).gt.0._r8.and.t(i,k).lt.tmelt.and. & - relhum(i,k)*es(i,k)/esi(i,k).gt. 1.05_r8 .and. k.gt.jt(i)+1) then - - if (k.eq.kqi(i)) then - nnuccd(k)=dum2i(i,k)/deltat - else - nnuccd(k)=(dum2i(i,k)-niic(i,k))/deltat - end if - nnuccd(k)=max(nnuccd(k),0._r8) - - !Calc mass of new particles using new crystal mass... - !also this will be multiplied by mtime as nnuccd is... - - mnuccd(k) = nnuccd(k) * mi0 - else - nnuccd(k)=0._r8 - mnuccd(k) = 0._r8 - end if - - !................................................................................ - ! Bergeron process - ! If 0C< T <-40C and both ice and liquid exist - - if (t(i,k).le.273.15_r8 .and. t(i,k).gt.233.15_r8 .and. & - qiic(i,k).gt.0.5e-6_r8 .and. qcic(i,k).gt. qsmall) then - plevap = qcic(i,k)/bergtsf - prb(k) = max(0._r8,plevap) - nprb(k) = prb(k)/(qcic(i,k)/ncic(i,k)) - else - prb(k)=0._r8 - nprb(k)=0._r8 - end if - - !................................................................................ - ! heterogeneous freezing of cloud water (-5C < T < -35C) - - if (qcic(i,k).ge.qsmall .and.ncic(i,k).gt.0._r8 .and. ntaerh(i,k).gt.0._r8 .and. & - t(i,k).le.268.15_r8 .and. t(i,k).gt.238.15_r8 ) then - - if (aero%scheme == 'bulk') then - ! immersion freezing (Diehl and Wurzler, 2004) - ttend(k) = -grav*wu(i,k)/cp/(1.0_r8+gamhat(i,k)) - - nai_bcphi = 0.0_r8 - nai_dst1 = 0.0_r8 - nai_dst2 = 0.0_r8 - nai_dst3 = 0.0_r8 - nai_dst4 = 0.0_r8 - - if (aero%idxbcphi > 0) nai_bcphi = naer2h(i,k,aero%idxbcphi) - if (aero%idxdst1 > 0) nai_dst1 = naer2h(i,k,aero%idxdst1) - if (aero%idxdst2 > 0) nai_dst2 = naer2h(i,k,aero%idxdst2) - if (aero%idxdst3 > 0) nai_dst3 = naer2h(i,k,aero%idxdst3) - if (aero%idxdst4 > 0) nai_dst4 = naer2h(i,k,aero%idxdst4) - - naimm = (0.00291_r8*nai_bcphi + 32.3_r8*(nai_dst1 + nai_dst2 + & - nai_dst3 + nai_dst4))/ntaerh(i,k) !m-3 - if (ttend(k) .lt. 0._r8) then - nnuccc(k) = -naimm*exp(273.15_r8-t(i,k))*ttend(k)*qcic(i,k)/rhow ! kg-1s-1 - mnuccc(k) = nnuccc(k)*qcic(i,k)/ncic(i,k) - end if - else - if (.false.) then - ! immersion freezing (Diehl and Wurzler, 2004) - ttend(k) = -grav*wu(i,k)/cp/(1.0_r8+gamhat(i,k)) - naimm = (0.00291_r8*soot_num + 32.3_r8*dst_num )*1.0e6_r8/ntaerh(i,k) !m-3 - if (ttend(k) .lt. 0._r8) then - nnuccc(k) = -naimm*exp(273.15_r8-t(i,k))*ttend(k)*qcic(i,k)/rhow ! kg-1s-1 - mnuccc(k) = nnuccc(k)*qcic(i,k)/ncic(i,k) - end if - else - ! immersion freezing (Bigg, 1953) - mnuccc(k) = pi*pi/36._r8*rhow* & - cdist1(k)*gamma(7._r8+pgam(i,k))* & - bimm*(exp(aimm*(273.15_r8-t(i,k)))-1._r8)/ & - lamc(i,k)**3/lamc(i,k)**3 - - nnuccc(k) = pi/6._r8*cdist1(k)*gamma(pgam(i,k)+4._r8) & - *bimm*(exp(aimm*(273.15_r8-t(i,k)))-1._r8)/lamc(i,k)**3 - end if - end if - - ! contact freezing (Young, 1974) with hooks into simulated dust - - tcnt=(270.16_r8-t(i,k))**1.3_r8 - viscosity=1.8e-5_r8*(t(i,k)/298.0_r8)**0.85_r8 ! Viscosity (kg/m/s) - mfp=2.0_r8*viscosity/(ph(i,k) & ! Mean free path (m) - *sqrt(8.0_r8*28.96e-3_r8/(pi*8.314409_r8*t(i,k)))) - - slip1=1.0_r8+(mfp/rn_dst1)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rn_dst1/mfp))))! Slip correction factor - slip2=1.0_r8+(mfp/rn_dst2)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rn_dst2/mfp)))) - slip3=1.0_r8+(mfp/rn_dst3)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rn_dst3/mfp)))) - slip4=1.0_r8+(mfp/rn_dst4)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rn_dst4/mfp)))) - - dfaer1=1.381e-23_r8*t(i,k)*slip1/(6._r8*pi*viscosity*rn_dst1) ! aerosol diffusivity (m2/s) - dfaer2=1.381e-23_r8*t(i,k)*slip2/(6._r8*pi*viscosity*rn_dst2) - dfaer3=1.381e-23_r8*t(i,k)*slip3/(6._r8*pi*viscosity*rn_dst3) - dfaer4=1.381e-23_r8*t(i,k)*slip4/(6._r8*pi*viscosity*rn_dst4) - - nacon1=0.0_r8 - nacon2=0.0_r8 - nacon3=0.0_r8 - nacon4=0.0_r8 - - if (aero%scheme == 'modal') then - - ! For modal aerosols: - ! use size '3' for dust coarse mode... - ! scale by dust fraction in coarse mode - - dmc = 0.5_r8*(aero%mmrg_a(i,k,aero%coarse_dust_idx,aero%mode_coarse_idx) & - +aero%mmrg_a(i,k-1,aero%coarse_dust_idx,aero%mode_coarse_idx)) - ssmc = 0.5_r8*(aero%mmrg_a(i,k,aero%coarse_nacl_idx,aero%mode_coarse_idx) & - +aero%mmrg_a(i,k-1,aero%coarse_nacl_idx,aero%mode_coarse_idx)) - if (dmc > 0.0_r8) then - nacon3 = dmc/(ssmc + dmc) * (aero%numg_a(i,k,aero%mode_coarse_idx) & - + aero%numg_a(i,k-1,aero%mode_coarse_idx))*0.5_r8*rho(i,k) - end if - - else if (aero%scheme == 'bulk') then - - if (aero%idxdst1.gt.0) then - nacon1=naer2h(i,k,aero%idxdst1)*tcnt *0.0_r8 - endif - if (aero%idxdst2.gt.0) then - nacon2=naer2h(i,k,aero%idxdst2)*tcnt ! 1/m3 - endif - if (aero%idxdst3.gt.0) then - nacon3=naer2h(i,k,aero%idxdst3)*tcnt - endif - if (aero%idxdst4.gt.0) then - nacon4=naer2h(i,k,aero%idxdst4)*tcnt - endif - end if - - mnucct(k) = (dfaer1*nacon1+dfaer2*nacon2+dfaer3*nacon3+dfaer4*nacon4)*pi*pi/3._r8*rhow* & - cdist1(k)*gamma(pgam(i,k)+5._r8)/lamc(i,k)**4 - - nnucct(k) = (dfaer1*nacon1+dfaer2*nacon2+dfaer3*nacon3+dfaer4*nacon4)*2._r8*pi* & - cdist1(k)*gamma(pgam(i,k)+2._r8)/lamc(i,k) - - ! if (nnuccc(k).gt.nnuccd(k)) then - ! dum=nnuccd(k)/nnuccc(k) - ! scale mixing ratio of droplet freezing with limit - ! mnuccc(k)=mnuccc(k)*dum - ! nnuccc(k)=nnuccd(k) - ! end if - - else - mnuccc(k) = 0._r8 - nnuccc(k) = 0._r8 - mnucct(k) = 0._r8 - nnucct(k) = 0._r8 - end if - - ! freeze cloud liquid water homogeneously at -40 C - if (t(i,k) < 233.15_r8 .and. qc(i,k) > 0._r8) then - - ! make sure freezing rain doesn't increase temperature above - ! threshold - dum = xlf/cp*qc(i,k) - if (t(i,k)+dum.gt.233.15_r8) then - dum = -(t(i,k)-233.15_r8)*cp/xlf - dum = dum/qc(i,k) - dum = max(0._r8,dum) - dum = min(1._r8,dum) - else - dum = 1._r8 - end if - fholm(i,k) = mu(i,k)*dum*qc(i,k) - fholn(i,k) = mu(i,k)*dum*nc(i,k) - end if - - - !**************************************************************************************** - ! conservation to ensure no negative values of cloud water/precipitation - ! in case microphysical process rates are large - ! note: for check on conservation, processes are multiplied by omsm - ! to prevent problems due to round off error - - ! since activation/nucleation processes are fast, need to take into account - ! factor mtime = mixing timescale in cloud / model time step - ! for now mixing timescale is assumed to be 15 min - !***************************************************************************************** - - mtime=deltat/900._r8 - mtimec=deltat/900._r8 - - ! conservation of qc - ! ice mass production from ice nucleation(deposition/cond.-freezing), mnuccd, - ! is considered as a part of cmei. - - qce = mu(i,k)*qc(i,k)-fholm(i,k) +dz(i,k)*cmel(i,k-1) - dum = arcf(i,k)*(pra(k)+prc(k)+prb(k)+mnuccc(k)+mnucct(k)+msacwi(k)+ & - psacws(k))*dz(i,k) - if( qce.lt.0._r8) then - qcimp(k) = .true. - prc(k) = 0._r8 - pra(k) = 0._r8 - prb(k) = 0._r8 - mnuccc(k) = 0._r8 - mnucct(k) = 0._r8 - msacwi(k) = 0._r8 - psacws(k) = 0._r8 - else if (dum.gt.qce) then - ratio = qce/dum*omsm - prc(k) = prc(k)*ratio - pra(k) = pra(k)*ratio - prb(k) = prb(k)*ratio - mnuccc(k) = mnuccc(k)*ratio - mnucct(k) = mnucct(k)*ratio - msacwi(k) = msacwi(k)*ratio - psacws(k) = psacws(k)*ratio - end if - - ! conservation of nc - nce = mu(i,k)*nc(i,k)-fholn(i,k) + (arcf(i,k)*npccn(k)*mtimec)*dz(i,k) - dum = arcf(i,k)*dz(i,k)*(nprc1(k)+npra(k)+nnuccc(k)+nnucct(k)+ & - npsacws(k)+ nprb(k) ) - if (nce.lt.0._r8) then - ncimp(k) = .true. - nprc1(k) = 0._r8 - npra(k) = 0._r8 - nnuccc(k) = 0._r8 - nnucct(k) = 0._r8 - npsacws(k) = 0._r8 - nprb(k) = 0._r8 - else if (dum.gt.nce) then - ratio = nce/dum*omsm - nprc1(k) = nprc1(k)*ratio - npra(k) = npra(k)*ratio - nnuccc(k) = nnuccc(k)*ratio - nnucct(k) = nnucct(k)*ratio - npsacws(k) = npsacws(k)*ratio - nprb(k) = nprb(k)*ratio - end if - - ! conservation of qi - qie = mu(i,k)*qi(i,k)+fholm(i,k) +dz(i,k)*(cmei(i,k-1) + & - ( mnuccc(k)+mnucct(k)+msacwi(k)+prb(k))*arcf(i,k) ) - dum = arcf(i,k)*(prci(k)+ prai(k))*dz(i,k) - if (qie.lt.0._r8) then - qiimp(k) = .true. - prci(k) = 0._r8 - prai(k) = 0._r8 - else if (dum.gt.qie) then - ratio = qie/dum*omsm - prci(k) = prci(k)*ratio - prai(k) = prai(k)*ratio - end if - - ! conservation of ni - nie = mu(i,k)*ni(i,k)+fholn(i,k) +dz(i,k)*(nnuccd(k)*mtime*arcf(i,k) & - +(nnuccc(k)+ nnucct(k))*arcf(i,k) ) - dum = arcf(i,k)*dz(i,k)*(-nsacwi(k)+nprci(k)+ nprai(k)) - if( nie.lt.0._r8) then - niimp(k) = .true. - nsacwi(k)= 0._r8 - nprci(k) = 0._r8 - nprai(k) = 0._r8 - else if (dum.gt.nie) then - ratio = nie/dum*omsm - nsacwi(k)= nsacwi(k)*ratio - nprci(k) = nprci(k)*ratio - nprai(k) = nprai(k)*ratio - end if - - ! conservation of qr - - qre = mu(i,k)*qr(i,k)+dz(i,k)*(pra(k)+prc(k))*arcf(i,k) - dum = arcf(i,k)*dz(i,k)*(pracs(k)+ mnuccr(k)-prf(k)) - if (qre.lt.0._r8) then - prf(k) = 0._r8 - pracs(k) = 0._r8 - mnuccr(k) = 0._r8 - else if (dum.gt.qre) then - ratio = qre/dum*omsm - prf(k) = prf(k)*ratio - pracs(k) = pracs(k)*ratio - mnuccr(k) = mnuccr(k)*ratio - end if - - ! conservation of nr - nre = mu(i,k)*nr(i,k) + nprc(k)*arcf(i,k)*dz(i,k) - dum = arcf(i,k)*dz(i,k)*(npracs(k)+nnuccr(k) & - -nragg(k)-pnrf(k)) - if(nre.lt.0._r8) then - npracs(k)= 0._r8 - nnuccr(k)= 0._r8 - nragg(k) = 0._r8 - pnrf(k) = 0._r8 - else if (dum.gt.nre) then - ratio = nre/dum*omsm - npracs(k)= npracs(k)*ratio - nnuccr(k)= nnuccr(k)*ratio - nragg(k) = nragg(k)*ratio - pnrf(k) = pnrf(k)*ratio - end if - - ! conservation of qni - - qnie = mu(i,k)*qni(i,k)+dz(i,k)*( (prai(k)+psacws(k)+prci(k)+ & - pracs(k)+mnuccr(k))*arcf(i,k) ) - dum = arcf(i,k)*dz(i,k)*(-psf(k)) - - if(qnie.lt.0._r8) then - psf(k) = 0._r8 - else if (dum.gt.qnie) then - ratio = qnie/dum*omsm - psf(k) = psf(k)*ratio - end if - - ! conservation of ns - nse = mu(i,k)*ns(i,k)+dz(i,k)*(nprci(k)+nnuccr(k))*arcf(i,k) - dum = arcf(i,k)*dz(i,k)*(-nsagg(k)-pnsf(k)) - if (nse.lt.0._r8) then - nsagg(k) = 0._r8 - pnsf(k) = 0._r8 - else if (dum.gt.nse) then - ratio = nse/dum*omsm - nsagg(k) = nsagg(k)*ratio - pnsf(k) = pnsf(k)*ratio - end if - - !***************************************************************************** - ! get tendencies due to microphysical conversion processes - !***************************************************************************** - - if (k.le.kqc(i)) then - qctend(i,k) = (-pra(k)-prc(k)-prb(k)-mnuccc(k)-mnucct(k)-msacwi(k)- & - psacws(k)) - - qitend(i,k) = (prb(k)+mnuccc(k)+mnucct(k)+msacwi(k)-prci(k)- prai(k)) - - qrtend(i,k) = (pra(k)+prc(k))+(-pracs(k)- mnuccr(k)) - - qnitend(i,k) = (prai(k)+psacws(k)+prci(k))+(pracs(k)+mnuccr(k)) - - ! multiply activation/nucleation by mtime to account for fast timescale - - nctend(i,k) = npccn(k)*mtimec+(-nnuccc(k)-nnucct(k)-npsacws(k) & - -npra(k)-nprc1(k)-nprb(k)) - - nitend(i,k) = nnuccd(k)*mtime+(nnuccc(k)+ nnucct(k)+nsacwi(k)-nprci(k)- & - nprai(k)) - - nstend(i,k) = nsagg(k)+nnuccr(k) + nprci(k) - - nrtend(i,k) = nprc(k)+(-npracs(k)-nnuccr(k) +nragg(k)) - - ! for output - ! cloud liquid water------------- - - autolm(i,k-1) = -prc(k)*arcf(i,k) - accrlm(i,k-1) = -pra(k)*arcf(i,k) - bergnm(i,k-1) = -prb(k)*arcf(i,k) - fhtimm(i,k-1) = -mnuccc(k)*arcf(i,k) - fhtctm(i,k-1) = -mnucct(k)*arcf(i,k) - hmpim (i,k-1) = -msacwi(k)*arcf(i,k) - accslm(i,k-1) = -psacws(k)*arcf(i,k) - fhmlm(i,k-1) = -fholm(i,k)/dz(i,k) - - autoln(i,k-1) = -nprc1(k)*arcf(i,k) - accrln(i,k-1) = -npra(k)*arcf(i,k) - bergnn(i,k-1) = -nprb(k)*arcf(i,k) - fhtimn(i,k-1) = -nnuccc(k)*arcf(i,k) - fhtctn(i,k-1) = -nnucct(k)*arcf(i,k) - accsln(i,k-1) = -npsacws(k)*arcf(i,k) - activn(i,k-1) = npccn(k)*mtimec*arcf(i,k) - fhmln(i,k-1) = -fholn(i,k)/dz(i,k) - - !cloud ice------------------------ - - autoim(i,k-1) = -prci(k)*arcf(i,k) - accsim(i,k-1) = -prai(k)*arcf(i,k) - - nuclin(i,k-1) = nnuccd(k)*mtime*arcf(i,k) - autoin(i,k-1) = -nprci(k)*arcf(i,k) - accsin(i,k-1) = -nprai(k)*arcf(i,k) - hmpin (i,k-1) = nsacwi(k)*arcf(i,k) - - else - qctend(i,k) = 0._r8 - qitend(i,k) = 0._r8 - qrtend(i,k) = 0._r8 - qnitend(i,k) = 0._r8 - nctend(i,k) = 0._r8 - nitend(i,k) = 0._r8 - nstend(i,k) = 0._r8 - nrtend(i,k) = 0._r8 - end if - - !******************************************************************************** - ! vertical integration - !******************************************************************************** - ! snow - if ( k.le.kqi(i) ) then - qni(i,k-1) = 1._r8/mu(i,k-1)* & - (mu(i,k)*qni(i,k)+dz(i,k)*(qnitend(i,k)+psf(k))*arcf(i,k) ) - - ns(i,k-1) = 1._r8/mu(i,k-1)* & - (mu(i,k)*ns(i,k)+dz(i,k)*(nstend(i,k)+pnsf(k))*arcf(i,k) ) - - else - qni(i,k-1)=0._r8 - ns(i,k-1)=0._r8 - end if - - if (qni(i,k-1).le.0._r8) then - qni(i,k-1)=0._r8 - ns(i,k-1)=0._r8 - end if - - ! rain - if (k.le.kqc(i) ) then - qr(i,k-1) = 1._r8/mu(i,k-1)* & - (mu(i,k)*qr(i,k)+dz(i,k)*(qrtend(i,k)+prf(k))*arcf(i,k) ) - - nr(i,k-1) = 1._r8/mu(i,k-1)* & - (mu(i,k)*nr(i,k)+dz(i,k)*(nrtend(i,k)+pnrf(k))*arcf(i,k) ) - - else - qr(i,k-1)=0._r8 - nr(i,k-1)=0._r8 - end if - - if( qr(i,k-1) .le. 0._r8) then - qr(i,k-1)=0._r8 - nr(i,k-1)=0._r8 - end if - - ! freeze rain homogeneously at -40 C - - if (t(i,k-1) < 233.15_r8 .and. qr(i,k-1) > 0._r8) then - - ! make sure freezing rain doesn't increase temperature above threshold - dum = xlf/cp*qr(i,k-1) - if (t(i,k-1)+dum.gt.233.15_r8) then - dum = -(t(i,k-1)-233.15_r8)*cp/xlf - dum = dum/qr(i,k-1) - dum = max(0._r8,dum) - dum = min(1._r8,dum) - else - dum = 1._r8 - end if - qni(i,k-1)=qni(i,k-1)+dum*qr(i,k-1) - ns(i,k-1)=ns(i,k-1)+dum*nr(i,k-1) - qr(i,k-1)=(1._r8-dum)*qr(i,k-1) - nr(i,k-1)=(1._r8-dum)*nr(i,k-1) - fhmrm(i,k-1) = -mu(i,k-1)*dum*qr(i,k-1)/dz(i,k) - end if - - - ! cloud water - if ( k.le.kqc(i) ) then - qc(i,k-1) = (mu(i,k)*qc(i,k)-fholm(i,k)+dz(i,k)*qctend(i,k)*arcf(i,k) & - +dz(i,k)*cmel(i,k-1) )/(mu(i,k-1)+dz(i,k)*du(i,k-1)) - - qcde(i,k) = qc(i,k-1) - - nc(i,k-1) = (mu(i,k)*nc(i,k) -fholn(i,k) +dz(i,k)*nctend(i,k)*arcf(i,k) ) & - /(mu(i,k-1)+dz(i,k)*du(i,k-1)) - - ncde(i,k) = nc(i,k-1) - else - qc(i,k-1)=0._r8 - nc(i,k-1)=0._r8 - end if - - if (qc(i,k-1).lt.0._r8) write(iulog,*) "negative qc(i,k-1)=",qc(i,k-1) - dlfm(i,k-1) = -du(i,k-1)*qcde(i,k) - dlfn(i,k-1) = -du(i,k-1)*ncde(i,k) - - if (qc(i,k-1).le. 0._r8) then - qc(i,k-1)=0._r8 - nc(i,k-1)=0._r8 - end if - - if (nc(i,k-1).lt. 0._r8) then - write(iulog,*) "nc(i,k-1)=",nc(i,k-1),"k-1=",k-1,"arcf(i,k)=",arcf(i,k) - write(iulog,*) "mu(i,k-1)=",mu(i,k-1),"mu(i,k)=",mu(i,k),"nc(i,k)=",ni(i,k) - write(iulog,*) "dz(i,k)=",dz(i,k),"du(i,k-1)=",du(i,k-1),"nctend(i,k)=",nctend(i,k) - write(iulog,*) "eu(i,k-1)=",eu(i,k-1) - end if - - ! cloud ice - if( k.le.kqi(i)) then - qi(i,k-1) = (mu(i,k)*qi(i,k)+fholm(i,k) +dz(i,k)*qitend(i,k)*arcf(i,k) & - +dz(i,k)*cmei(i,k-1) )/(mu(i,k-1)+dz(i,k)*du(i,k-1)) - - qide(i,k) = qi(i,k-1) - - ni(i,k-1) = (mu(i,k)*ni(i,k)+fholn(i,k)+dz(i,k)*nitend(i,k)*arcf(i,k) ) & - /(mu(i,k-1)+dz(i,k)*du(i,k-1)) - - nide(i,k) = ni(i,k-1) - else - qi(i,k-1)=0._r8 - ni(i,k-1)=0._r8 - end if - - if (qi(i,k-1).lt.0._r8) write(iulog,*) "negative qi(i,k-1)=",qi(i,k-1) - difm(i,k-1) = -du(i,k-1)*qide(i,k) - difn(i,k-1) = -du(i,k-1)*nide(i,k) - - if (qi(i,k-1).le. 0._r8) then - qi(i,k-1)=0._r8 - ni(i,k-1)=0._r8 - end if - - - if (ni(i,k-1).lt. 0._r8) then - write(iulog,*) "ni(i,k-1)=",ni(i,k-1),"k-1=",k-1,"arcf(i,k)=",arcf(i,k) - write(iulog,*) "mu(i,k-1)=",mu(i,k-1),"mu(i,k)=",mu(i,k),"ni(i,k)=",ni(i,k) - write(iulog,*) "dz(i,k)=",dz(i,k),"du(i,k-1)=",du(i,k-1),"nitend(i,k)=",nitend(i,k) - write(iulog,*) "eu(i,k-1)=",eu(i,k-1) - end if - - - frz(i,k-1) = cmei(i,k-1) + arcf(i,k)*(prb(k)+mnuccc(k)+mnucct(k)+msacwi(k)+ & - pracs(k)+mnuccr(k)+psacws(k) )-fhmlm(i,k-1)-fhmrm(i,k-1) - - - !****************************************************************************** - ! get size distribution parameters based on in-cloud cloud water/ice - ! these calculations also ensure consistency between number and mixing ratio - - ! following equation(2,3,4) of Morrison and Gettelman, 2008, J. Climate. - ! Gamma(n)= (n-1)! - ! lamc <-> lambda for cloud liquid water - ! pgam <-> meu for cloud liquid water - ! meu=0 for ice,rain and snow - !******************************************************************************* - - ! cloud ice - niorg = ni(i,k-1) - if (qi(i,k-1).ge.qsmall) then - - ! add upper limit to in-cloud number concentration to prevent numerical error - ni(i,k-1)=min(ni(i,k-1),qi(i,k-1)*1.e20_r8) - ! ni should be non-negative - ! ni(i,k-1) = max(ni(i,k-1), 0._r8) - if (ni(i,k-1).lt. 0._r8) write(iulog,*) "ni(i,k-1)=",ni(i,k-1) - - lami(k-1) = (gamma(1._r8+di)*ci* & - ni(i,k-1)/qi(i,k-1))**(1._r8/di) - n0i(k-1) = ni(i,k-1)*lami(k-1) - - ! check for slope - lammax = 1._r8/10.e-6_r8 - lammin = 1._r8/(2._r8*dcs) - - ! adjust vars - if (lami(k-1).lt.lammin) then - lami(k-1) = lammin - n0i(k-1) = lami(k-1)**(di+1._r8)*qi(i,k-1)/(ci*gamma(1._r8+di)) - ni(i,k-1) = n0i(k-1)/lami(k-1) - else if (lami(k-1).gt.lammax) then - lami(k-1) = lammax - n0i(k-1) = lami(k-1)**(di+1._r8)*qi(i,k-1)/(ci*gamma(1._r8+di)) - ni(i,k-1) = n0i(k-1)/lami(k-1) - end if - else - lami(k-1) = 0._r8 - n0i(k-1) = 0._r8 - end if - - nide(i,k) = ni(i,k-1) - difn(i,k-1) = -du(i,k-1)*nide(i,k) - - niadj(i,k-1)= (ni(i,k-1)- niorg)*mu(i,k-1)/dz(i,k) - - if (niadj(i,k-1) .lt. 0._r8) then - total = nuclin(i,k-1)-fhtimn(i,k-1)-fhtctn(i,k-1)-fhmln(i,k-1)+ hmpin (i,k-1) - if (total .ne. 0._r8) then - nuclin(i,k-1) = nuclin(i,k-1) + nuclin(i,k-1)*niadj(i,k-1)/total - fhtimn(i,k-1) = fhtimn(i,k-1) + fhtimn(i,k-1)*niadj(i,k-1)/total - fhtctn(i,k-1) = fhtctn(i,k-1) + fhtctn(i,k-1)*niadj(i,k-1)/total - fhmln (i,k-1) = fhmln (i,k-1) + fhmln (i,k-1)*niadj(i,k-1)/total - hmpin (i,k-1) = hmpin (i,k-1) + hmpin (i,k-1)*niadj(i,k-1)/total - else - total = 5._r8 - nuclin(i,k-1) = nuclin(i,k-1) + niadj(i,k-1)/total - fhtimn(i,k-1) = fhtimn(i,k-1) + niadj(i,k-1)/total - fhtctn(i,k-1) = fhtctn(i,k-1) + niadj(i,k-1)/total - fhmln (i,k-1) = fhmln (i,k-1) + niadj(i,k-1)/total - hmpin (i,k-1) = hmpin (i,k-1) + niadj(i,k-1)/total - end if - else if (niadj(i,k-1) .gt. 0._r8) then - total = autoin(i,k-1)+accsin(i,k-1) - if (total .ne. 0._r8) then - autoin(i,k-1) = autoin(i,k-1) + autoin(i,k-1)*niadj(i,k-1)/total - accsin(i,k-1) = accsin(i,k-1) + accsin(i,k-1)*niadj(i,k-1)/total - else - total = 2._r8 - autoin(i,k-1) = autoin(i,k-1) + niadj(i,k-1)/total - accsin(i,k-1) = accsin(i,k-1) + niadj(i,k-1)/total - end if - end if - - !................................................................................ - !cloud water - ncorg = nc(i,k-1) - if (qc(i,k-1).ge.qsmall) then - - ! add upper limit to in-cloud number concentration to prevent numerical error - nc(i,k-1)=min(nc(i,k-1),qc(i,k-1)*1.e20_r8) - ! and make sure it's non-negative - ! nc(i,k-1) = max(nc(i,k-1), 0._r8) - if (nc(i,k-1).lt. 0._r8) write(iulog,*) "nc(i,k-1)=",nc(i,k-1) - - ! get pgam from fit to observations of martin et al. 1994 - - pgam(i,k-1)=0.0005714_r8*(nc(i,k-1)/1.e6_r8/rho(i,k-1))+0.2714_r8 - pgam(i,k-1)=1._r8/(pgam(i,k-1)**2)-1._r8 - pgam(i,k-1)=max(pgam(i,k-1),2._r8) - pgam(i,k-1)=min(pgam(i,k-1),15._r8) - ! calculate lamc - - lamc(i,k-1) = (pi/6._r8*rhow*nc(i,k-1)*gamma(pgam(i,k-1)+4._r8)/ & - (qc(i,k-1)*gamma(pgam(i,k-1)+1._r8)))**(1._r8/3._r8) - - ! lammin, 50 micron diameter max mean size - lammin = (pgam(i,k-1)+1._r8)/40.e-6_r8 - lammax = (pgam(i,k-1)+1._r8)/1.e-6_r8 - - if (lamc(i,k-1).lt.lammin) then - lamc(i,k-1) = lammin - nc(i,k-1) = 6._r8*lamc(i,k-1)**3*qc(i,k-1)* & - gamma(pgam(i,k-1)+1._r8)/ & - (pi*rhow*gamma(pgam(i,k-1)+4._r8)) - else if (lamc(i,k-1).gt.lammax) then - lamc(i,k-1) = lammax - nc(i,k-1) = 6._r8*lamc(i,k-1)**3*qc(i,k-1)* & - gamma(pgam(i,k-1)+1._r8)/ & - (pi*rhow*gamma(pgam(i,k-1)+4._r8)) - end if - - ! parameter to calculate droplet freezing - - cdist1(k-1) = nc(i,k-1)/gamma(pgam(i,k-1)+1._r8) - else - lamc(i,k-1) = 0._r8 - cdist1(k-1) = 0._r8 - end if - - ncde(i,k) = nc(i,k-1) - dlfn(i,k-1) = -du(i,k-1)*ncde(i,k) - - ncadj(i,k-1) = (nc(i,k-1)- ncorg)*mu(i,k-1)/dz(i,k) - if (ncadj(i,k-1) .lt. 0._r8) then - activn(i,k-1) = activn(i,k-1) + ncadj(i,k-1) - else if (ncadj(i,k-1) .gt. 0._r8) then - total = autoln(i,k-1)+accrln(i,k-1)+bergnn(i,k-1)+accsln(i,k-1) - if (total .ne. 0._r8) then - autoln(i,k-1) = autoln(i,k-1) + autoln(i,k-1)*ncadj(i,k-1)/total - accrln(i,k-1) = accrln(i,k-1) + accrln(i,k-1)*ncadj(i,k-1)/total - bergnn(i,k-1) = bergnn(i,k-1) + bergnn(i,k-1)*ncadj(i,k-1)/total - accsln(i,k-1) = accsln(i,k-1) + accsln(i,k-1)*ncadj(i,k-1)/total - else - total = 4._r8 - autoln(i,k-1) = autoln(i,k-1) + ncadj(i,k-1)/total - accrln(i,k-1) = accrln(i,k-1) + ncadj(i,k-1)/total - bergnn(i,k-1) = bergnn(i,k-1) + ncadj(i,k-1)/total - accsln(i,k-1) = accsln(i,k-1) + ncadj(i,k-1)/total - end if - end if - - trspcm(i,k-1) = (mu(i,k)*qc(i,k) - mu(i,k-1)*qc(i,k-1))/dz(i,k) - trspcn(i,k-1) = (mu(i,k)*nc(i,k) - mu(i,k-1)*nc(i,k-1))/dz(i,k) - trspim(i,k-1) = (mu(i,k)*qi(i,k) - mu(i,k-1)*qi(i,k-1))/dz(i,k) - trspin(i,k-1) = (mu(i,k)*ni(i,k) - mu(i,k-1)*ni(i,k-1))/dz(i,k) - - if (k-1 .eq. jt(i)+1) then - trspcm(i,k-2) = mu(i,k-1)*qc(i,k-1)/dz(i,k-1) - trspcn(i,k-2) = mu(i,k-1)*nc(i,k-1)/dz(i,k-1) - trspim(i,k-2) = mu(i,k-1)*qi(i,k-1)/dz(i,k-1) - trspin(i,k-2) = mu(i,k-1)*ni(i,k-1)/dz(i,k-1) - qcde(i,k-1) = qc(i,k-1) - ncde(i,k-1) = nc(i,k-1) - qide(i,k-1) = qi(i,k-1) - nide(i,k-1) = ni(i,k-1) - dlfm (i,k-2) = -du(i,k-2)*qcde(i,k-1) - dlfn (i,k-2) = -du(i,k-2)*ncde(i,k-1) - difm (i,k-2) = -du(i,k-2)*qide(i,k-1) - difn (i,k-2) = -du(i,k-2)*nide(i,k-1) - end if - - - !....................................................................... - ! get size distribution parameters for precip - !...................................................................... - ! rain - if (qr(i,k-1).ge.qsmall) then - - lamr(k-1) = (pi*rhow*nr(i,k-1)/qr(i,k-1))**(1._r8/3._r8) - n0r(k-1) = nr(i,k-1)*lamr(k-1) - - ! check for slope - lammax = 1._r8/150.e-6_r8 - lammin = 1._r8/3000.e-6_r8 - ! adjust vars - if (lamr(k-1).lt.lammin) then - lamr(k-1) = lammin - n0r(k-1) = lamr(k-1)**4*qr(i,k-1)/(pi*rhow) - nr(i,k-1) = n0r(k-1)/lamr(k-1) - else if (lamr(k-1).gt.lammax) then - lamr(k-1) = lammax - n0r(k-1) = lamr(k-1)**4*qr(i,k-1)/(pi*rhow) - nr(i,k-1) = n0r(k-1)/lamr(k-1) - end if - - unr(k-1) = min(arn(i,k-1)*gamma(1._r8+br)/lamr(k-1)**br,10._r8) - umr(k-1) = min(arn(i,k-1)*gamma(4._r8+br)/(6._r8*lamr(k-1)**br),10._r8) - else - lamr(k-1) = 0._r8 - n0r(k-1) = 0._r8 - umr(k-1) = 0._r8 - unr(k-1) = 0._r8 - end if - - !...................................................................... - ! snow - if (qni(i,k-1).ge.qsmall) then - lams(k-1) = (gamma(1._r8+ds)*cs*ns(i,k-1)/ & - qni(i,k-1))**(1._r8/ds) - n0s(k-1) = ns(i,k-1)*lams(k-1) - - ! check for slope - lammax = 1._r8/10.e-6_r8 - lammin = 1._r8/2000.e-6_r8 - - ! adjust vars - if (lams(k-1).lt.lammin) then - lams(k-1) = lammin - n0s(k-1) = lams(k-1)**(ds+1._r8)*qni(i,k-1)/(cs*gamma(1._r8+ds)) - ns(i,k-1) = n0s(k-1)/lams(k-1) - else if (lams(k-1).gt.lammax) then - lams(k-1) = lammax - n0s(k-1) = lams(k-1)**(ds+1._r8)*qni(i,k-1)/(cs*gamma(1._r8+ds)) - ns(i,k-1) = n0s(k-1)/lams(k-1) - end if - ums(k-1) = min(asn(i,k-1)*gamma(4._r8+bs)/(6._r8*lams(k-1)**bs),3.6_r8) - uns(k-1) = min(asn(i,k-1)*gamma(1._r8+bs)/lams(k-1)**bs,3.6_r8) - else - lams(k-1) = 0._r8 - n0s(k-1) = 0._r8 - ums(k-1) = 0._r8 - uns(k-1) = 0._r8 - end if - - rprd(i,k-1)= (qnitend(i,k) + qrtend(i,k))*arcf(i,k) - sprd(i,k-1)= qnitend(i,k) *arcf(i,k) -fhmrm(i,k-1) - - end if ! k Date: Wed, 27 Sep 2023 16:52:55 -0600 Subject: [PATCH 02/10] Remove test which tested zmconv_micro --- cime_config/testdefs/testlist_cam.xml | 10 ------- .../cam/outfrq3s_convmic/shell_commands | 4 --- .../cam/outfrq3s_convmic/user_nl_cam | 6 ----- .../cam/outfrq3s_convmic/user_nl_clm | 27 ------------------- .../cam/outfrq3s_convmic/user_nl_cpl | 2 -- 5 files changed, 49 deletions(-) delete mode 100644 cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/shell_commands delete mode 100644 cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cam delete mode 100644 cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_clm delete mode 100644 cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cpl diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index 73219c0c07..2a0156db0d 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -519,16 +519,6 @@ - - - - - - - - - - diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/shell_commands b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/shell_commands deleted file mode 100644 index 3a506cfaa1..0000000000 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/shell_commands +++ /dev/null @@ -1,4 +0,0 @@ -./xmlchange ROF_NCPL=\$ATM_NCPL -./xmlchange GLC_NCPL=\$ATM_NCPL -./xmlchange CAM_NML_USE_CASE=UNSET -./xmlchange RUN_STARTDATE="19950101" diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cam deleted file mode 100644 index f81fb38bfc..0000000000 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cam +++ /dev/null @@ -1,6 +0,0 @@ -zmconv_microp=.true. -mfilt=1,1,1,1,1,1 -ndens=1,1,1,1,1,1 -nhtfrq=3,3,3,3,3,3 -inithist='ENDOFRUN' -pbuf_global_allocate=.false. diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_clm b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_clm deleted file mode 100644 index f3ac27f1e6..0000000000 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_clm +++ /dev/null @@ -1,27 +0,0 @@ -!---------------------------------------------------------------------------------- -! Users should add all user specific namelist changes below in the form of -! namelist_var = new_namelist_value -! -! Include namelist variables for drv_flds_in ONLY if -megan and/or -drydep options -! are set in the CLM_NAMELIST_OPTS env variable. -! -! EXCEPTIONS: -! Set use_cndv by the compset you use and the CLM_BLDNML_OPTS -dynamic_vegetation setting -! Set use_vichydro by the compset you use and the CLM_BLDNML_OPTS -vichydro setting -! Set use_cn by the compset you use and CLM_BLDNML_OPTS -bgc setting -! Set use_crop by the compset you use and CLM_BLDNML_OPTS -crop setting -! Set spinup_state by the CLM_BLDNML_OPTS -bgc_spinup setting -! Set irrigate by the CLM_BLDNML_OPTS -irrig setting -! Set dtime with L_NCPL option -! Set fatmlndfrc with LND_DOMAIN_PATH/LND_DOMAIN_FILE options -! Set finidat with RUN_REFCASE/RUN_REFDATE/RUN_REFTOD options for hybrid or branch cases -! (includes $inst_string for multi-ensemble cases) -! Set glc_grid with CISM_GRID option -! Set glc_smb with GLC_SMB option -! Set maxpatch_glcmec with GLC_NEC option -! Set glc_do_dynglacier with GLC_TWO_WAY_COUPLING env variable -!---------------------------------------------------------------------------------- -hist_nhtfrq = 3 -hist_mfilt = 1 -hist_ndens = 1 - diff --git a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cpl b/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cpl deleted file mode 100644 index 398535cf65..0000000000 --- a/cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cpl +++ /dev/null @@ -1,2 +0,0 @@ -reprosum_diffmax=1.0e-14 -reprosum_recompute=.true. From 3f6d12ddccd19c03fdf7d7fcd18cb444aa679d52 Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Fri, 20 Oct 2023 15:47:02 -0600 Subject: [PATCH 03/10] Modfy calling sequences to allow for removal of zm_common --- src/physics/cam/convect_shallow.F90 | 2 ++ src/physics/cam/zm_conv_intr.F90 | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/physics/cam/convect_shallow.F90 b/src/physics/cam/convect_shallow.F90 index 4f0844fd24..d7b909a375 100644 --- a/src/physics/cam/convect_shallow.F90 +++ b/src/physics/cam/convect_shallow.F90 @@ -14,6 +14,7 @@ module convect_shallow use physconst, only : cpair, zvir use ppgrid, only : pver, pcols, pverp use zm_conv_evap_mod, only : zm_conv_evap_run + use zm_conv_intr, only : zmconv_ke, zmconv_ke_lnd, zmconv_org use cam_history, only : outfld, addfld, horiz_only use cam_logfile, only : iulog use phys_control, only : phys_getopts @@ -868,6 +869,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & call zm_conv_evap_run( state1%ncol, pcols, pver, pverp, & gravit, latice, latvap, tmelt, & + cpair, zmconv_ke, zmconv_ke_lnd, zmconv_org, & state1%t, state1%pmid, state1%pdel, state1%q(:pcols,:pver,1), & landfracdum, & ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, & diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index 2e44af000e..7d8445e688 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -38,6 +38,7 @@ module zm_conv_intr zm_conv_tend, &! return tendencies zm_conv_tend_2 ! return tendencies + public zmconv_ke, zmconv_ke_lnd, zmconv_org ! needed by convect_shallow integer ::& ! indices for fields in the physics buffer zm_mu_idx, & @@ -651,6 +652,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & call zm_conv_evap_run(state1%ncol, pcols, pver, pverp, & gravit, latice, latvap, tmelt, & + cpair, zmconv_ke, zmconv_ke_lnd, zmconv_org, & state1%t,state1%pmid,state1%pdel,state1%q(:pcols,:pver,1), & landfrac, & ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, ptend_loc%q(:pcols,:pver,1), & @@ -710,6 +712,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & call t_startf ('zm_conv_momtran_run') call zm_conv_momtran_run (ncol, pcols, pver, pverp, & l_windt,winds, 2, mu, md, & + zmconv_momcu, zmconv_momcd, & du, eu, ed, dp, dsubcld, & jt, maxg, ideep, 1, lengath, & nstep, wind_tends, pguall, pgdall, icwu, icwd, ztodt, seten ) From 2ed878354b37f5ebd5e946870a945bc9a8b6fb60 Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Wed, 13 Dec 2023 12:59:00 -0700 Subject: [PATCH 04/10] Fix compilation error --- src/physics/cam/convect_shallow.F90 | 2 +- src/physics/cam/zm_conv_intr.F90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/physics/cam/convect_shallow.F90 b/src/physics/cam/convect_shallow.F90 index d7b909a375..bca53640f1 100644 --- a/src/physics/cam/convect_shallow.F90 +++ b/src/physics/cam/convect_shallow.F90 @@ -870,7 +870,7 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & call zm_conv_evap_run( state1%ncol, pcols, pver, pverp, & gravit, latice, latvap, tmelt, & cpair, zmconv_ke, zmconv_ke_lnd, zmconv_org, & - state1%t, state1%pmid, state1%pdel, state1%q(:pcols,:pver,1), & + state1%t(:,:), state1%pmid, state1%pdel, state1%q(:pcols,:pver,1), & landfracdum, & ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, & ptend_loc%q(:pcols,:pver,1), & diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index 7d8445e688..9f2d05afbc 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -653,7 +653,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & call zm_conv_evap_run(state1%ncol, pcols, pver, pverp, & gravit, latice, latvap, tmelt, & cpair, zmconv_ke, zmconv_ke_lnd, zmconv_org, & - state1%t,state1%pmid,state1%pdel,state1%q(:pcols,:pver,1), & + state1%t(:,:),state1%pmid,state1%pdel,state1%q(:pcols,:pver,1), & landfrac, & ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, ptend_loc%q(:pcols,:pver,1), & rprd, cld, ztodt, & From caa528d6ffffd4191873451ec439713eee0cdfbc Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Thu, 14 Dec 2023 16:49:32 -0700 Subject: [PATCH 05/10] address some reviewer comments --- Externals_CAM.cfg | 2 +- bld/configure | 3 -- src/physics/cam/convect_shallow.F90 | 2 +- src/physics/cam/zm_conv_intr.F90 | 47 ++++++++++++++------- src/physics/spcam/crmclouds_camaerosols.F90 | 2 +- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Externals_CAM.cfg b/Externals_CAM.cfg index 4305516b9e..0deba5cb89 100644 --- a/Externals_CAM.cfg +++ b/Externals_CAM.cfg @@ -50,7 +50,7 @@ tag = ALI_ARMS_v1.0.1 required = True [atmos_phys] -tag = 3d03d40923 +tag = 0f5021cbe5 protocol = git repo_url = https://github.com/cacraigucar/atmospheric_physics required = True diff --git a/bld/configure b/bld/configure index a202ccf6f6..678d0a8ac6 100755 --- a/bld/configure +++ b/bld/configure @@ -1802,9 +1802,6 @@ if ($usr_cppdefs and $print>=2) { print "Commandline CPP definitions: \'$usr_cpp # the CPP definitions that were explicitly set in the defaults file or by the user on the commandline. my $cfg_cppdefs = ' '; -# Turn on CCPP "OLD_CAM" -$cfg_cppdefs .= " -DOLD_CAM"; - # Building for perturbation growth tests if ($pergro eq "ON") { $cfg_cppdefs .= " -DPERGRO"; } diff --git a/src/physics/cam/convect_shallow.F90 b/src/physics/cam/convect_shallow.F90 index bca53640f1..2897db6651 100644 --- a/src/physics/cam/convect_shallow.F90 +++ b/src/physics/cam/convect_shallow.F90 @@ -13,7 +13,7 @@ module convect_shallow use shr_kind_mod, only : r8=>shr_kind_r8 use physconst, only : cpair, zvir use ppgrid, only : pver, pcols, pverp - use zm_conv_evap_mod, only : zm_conv_evap_run + use zm_conv_evap, only : zm_conv_evap_run use zm_conv_intr, only : zmconv_ke, zmconv_ke_lnd, zmconv_org use cam_history, only : outfld, addfld, horiz_only use cam_logfile, only : iulog diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index 9f2d05afbc..a245c54778 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -10,10 +10,10 @@ module zm_conv_intr use shr_kind_mod, only: r8=>shr_kind_r8 use physconst, only: cpair, epsilo, gravit, latvap, tmelt, rair use ppgrid, only: pver, pcols, pverp, begchunk, endchunk - use zm_conv_evap_mod, only: zm_conv_evap_run - use zm_convr_mod, only: zm_convr_init, zm_convr_run - use zm_conv_convtran_mod, only: zm_conv_convtran_run - use zm_conv_momtran_mod, only: zm_conv_momtran_run + use zm_conv_evap, only: zm_conv_evap_run + use zm_convr, only: zm_convr_init, zm_convr_run + use zm_conv_convtran, only: zm_conv_convtran_run + use zm_conv_momtran, only: zm_conv_momtran_run use rad_constituents, only: rad_cnst_get_info, rad_cnst_get_mode_num, rad_cnst_get_aer_mmr, & rad_cnst_get_aer_props, rad_cnst_get_mode_props !, & @@ -155,6 +155,7 @@ subroutine zm_conv_register ! convective mass fluxes call pbuf_add_field('CMFMC_DP', 'physpkg', dtype_r8, (/pcols,pverp/), mconzm_idx) +!CACNOTE - Is zm_org really a constituent or was it just a handy structure to use for an allocatable which persists in the run? if (zmconv_org) then call cnst_add('ZM_ORG',0._r8,0._r8,0._r8,ixorg,longname='organization parameter') endif @@ -237,7 +238,7 @@ subroutine zm_conv_init(pref_edge) use cam_history, only: addfld, add_default, horiz_only use ppgrid, only: pcols, pver - use zm_convr_mod, only: zm_convr_init + use zm_convr, only: zm_convr_init use pmgrid, only: plev,plevp use spmd_utils, only: masterproc use phys_control, only: phys_deepconv_pbl, phys_getopts, cam_physpkg_is @@ -545,6 +546,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & ! call t_startf ('zm_convr_run') +!CACNOTE - Need to remove the pointer and may need to copy in/out around the zm_convr_run call if (zmconv_org) then allocate(zm_org2d(pcols,pver)) org => state%q(:,:,ixorg) @@ -552,16 +554,31 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & endif !CACNOTE - Need to check errflg and report errors - call zm_convr_run( ncol , pcols, pver, & - pverp, gravit ,latice ,cpwv ,cpliq ,& - rh2o,& - state%t ,state%q(:,:,1), prec ,jctop ,jcbot , & - pblh ,state%zm ,state%phis ,state%zi ,ptend_loc%q(:,:,1) , & - ptend_loc%s , state%pmid ,state%pint ,state%pdel , & - .5_r8*ztodt ,mcon ,cme , cape, & - tpert ,dlf ,pflx ,zdu ,rprd , & - mu, md, du, eu, ed, & - dp, dsubcld, jt, maxg, ideep, & +! call zm_convr_run(ncol, ncol, pver, & +! pverp, gravit, latice, cpwv, cpliq, rh2o, & +! state%t(:ncol,:), state%q(:ncol,:,1), prec(:ncol), jctop(:ncol), jcbot(:ncol), & +! pblh(:ncol), state%zm(:ncol,:), state%phis, state%zi(:ncol,:), ptend_loc%q(:ncol,:,1), & +! ptend_loc%s(:ncol,:), state%pmid(:ncol,:), state%pint(:ncol,:), state%pdel(:ncol,:), & +! .5_r8*ztodt, mcon(:ncol,:), cme(:ncol,:), cape(:ncol), & +! tpert(:ncol), dlf(:ncol,:), pflx(:ncol,:), zdu(:ncol,:), rprd(:ncol,:), & +! mu(:ncol,:), md(:ncol,:), du(:ncol,:), eu(:ncol,:), ed(:ncol,:), & +! dp(:ncol,:), dsubcld(:ncol), jt(:ncol), maxg(:ncol), ideep(:ncol), & +! ql(:ncol,:), rliq(:ncol), landfrac(:ncol), & +!!CACNOTE - This call needs to be used when the pointer attribute is removed from these variables +!! org(:ncol,:), orgt(:ncol,:), zm_org2d(:ncol,:), & +! org, orgt, zm_org2d, & +! dif(:ncol,:), dnlf(:ncol,:), dnif(:ncol,:), & +! rice(:ncol), errmsg, errflg) + + call zm_convr_run(ncol, pcols, pver, & + pverp, gravit, latice, cpwv, cpliq, rh2o, & + state%t, state%q(:,:,1), prec, jctop, jcbot, & + pblh, state%zm, state%phis, state%zi, ptend_loc%q(:,:,1), & + ptend_loc%s, state%pmid, state%pint, state%pdel, & + .5_r8*ztodt, mcon, cme, cape, & + tpert, dlf, pflx, zdu, rprd, & + mu, md, du, eu, ed, & + dp, dsubcld, jt, maxg, ideep, & ql, rliq, landfrac, & org, orgt, zm_org2d, & dif, dnlf, dnif, & diff --git a/src/physics/spcam/crmclouds_camaerosols.F90 b/src/physics/spcam/crmclouds_camaerosols.F90 index 8ebdb0f016..b3dc07d271 100644 --- a/src/physics/spcam/crmclouds_camaerosols.F90 +++ b/src/physics/spcam/crmclouds_camaerosols.F90 @@ -608,7 +608,7 @@ subroutine crmclouds_convect_tend(state, ptend, ztodt, pbuf) use time_manager, only: get_nstep use physics_buffer, only: physics_buffer_desc, pbuf_old_tim_idx, pbuf_get_index, pbuf_get_field use constituents, only: pcnst, cnst_get_ind - use zm_conv_convtran_mod, only: zm_conv_convtran_run + use zm_conv_convtran,only: zm_conv_convtran_run use error_messages, only: alloc_err ! Arguments From bdb36e6042dc86bcfc86c42fbeb9944165ff04e4 Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Thu, 11 Jan 2024 16:26:18 -0700 Subject: [PATCH 06/10] Only pass ncols to ZM routines --- src/physics/cam/cloud_fraction.F90 | 6 +- src/physics/cam/convect_shallow.F90 | 23 +-- src/physics/cam/macrop_driver.F90 | 6 +- src/physics/cam/rk_stratiform.F90 | 158 ++++++++++---------- src/physics/cam/zm_conv_intr.F90 | 152 ++++++++++++------- src/physics/spcam/crmclouds_camaerosols.F90 | 13 +- 6 files changed, 209 insertions(+), 149 deletions(-) diff --git a/src/physics/cam/cloud_fraction.F90 b/src/physics/cam/cloud_fraction.F90 index 365da98f50..3285862fae 100644 --- a/src/physics/cam/cloud_fraction.F90 +++ b/src/physics/cam/cloud_fraction.F90 @@ -751,10 +751,10 @@ subroutine cldfrc_fice(ncol, t, fice, fsnow) ! Arguments integer, intent(in) :: ncol ! number of active columns - real(r8), intent(in) :: t(pcols,pver) ! temperature + real(r8), intent(in) :: t(:,:) ! temperature - real(r8), intent(out) :: fice(pcols,pver) ! Fractional ice content within cloud - real(r8), intent(out) :: fsnow(pcols,pver) ! Fractional snow content for convection + real(r8), intent(out) :: fice(:,:) ! Fractional ice content within cloud + real(r8), intent(out) :: fsnow(:,:) ! Fractional snow content for convection ! Local variables real(r8) :: tmax_fice ! max temperature for cloud ice formation diff --git a/src/physics/cam/convect_shallow.F90 b/src/physics/cam/convect_shallow.F90 index 2897db6651..ffd1db8f5f 100644 --- a/src/physics/cam/convect_shallow.F90 +++ b/src/physics/cam/convect_shallow.F90 @@ -867,15 +867,20 @@ subroutine convect_shallow_tend( ztodt , cmfmc , & sh_cldliq(:ncol,:) = 0._r8 sh_cldice(:ncol,:) = 0._r8 - call zm_conv_evap_run( state1%ncol, pcols, pver, pverp, & - gravit, latice, latvap, tmelt, & - cpair, zmconv_ke, zmconv_ke_lnd, zmconv_org, & - state1%t(:,:), state1%pmid, state1%pdel, state1%q(:pcols,:pver,1), & - landfracdum, & - ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, & - ptend_loc%q(:pcols,:pver,1), & - rprdsh, cld, ztodt, & - precc, snow, ntprprd, ntsnprd , flxprec, flxsnow ) + !REMOVECAM - no longer need these when CAM is retired and pcols no longer exists + tend_s_snwprd(:,:) = 0._r8 + tend_s_snwevmlt(:,:) = 0._r8 + snow(:) = 0._r8 + !REMOVECAM_END + + call zm_conv_evap_run(state1%ncol, pver, pverp, & + gravit, latice, latvap, tmelt, & + cpair, zmconv_ke, zmconv_ke_lnd, zmconv_org, & + state1%t(:ncol,:),state1%pmid(:ncol,:),state1%pdel(:ncol,:),state1%q(:ncol,:pver,1), & + landfracdum(:ncol), & + ptend_loc%s(:ncol,:), tend_s_snwprd(:ncol,:), tend_s_snwevmlt(:ncol,:), ptend_loc%q(:ncol,:pver,1), & + rprdsh(:ncol,:), cld(:ncol,:), ztodt, & + precc(:ncol), snow(:ncol), ntprprd(:ncol,:), ntsnprd(:ncol,:), flxprec(:ncol,:), flxsnow(:ncol,:) ) ! ---------------------------------------------- ! ! record history variables from zm_conv_evap_run ! diff --git a/src/physics/cam/macrop_driver.F90 b/src/physics/cam/macrop_driver.F90 index 092848dd0e..92d52fff8c 100644 --- a/src/physics/cam/macrop_driver.F90 +++ b/src/physics/cam/macrop_driver.F90 @@ -868,7 +868,11 @@ subroutine macrop_driver_tend( & ! This uses a ramp ( -30 ~ -10 for fice, -5 ~ 0 for fsnow ). ! The ramp within convective cloud may be different - call cldfrc_fice( ncol, state_loc%t, fice, fsnow ) +!REMOVECAM - no longer need these when CAM is retired and pcols no longer exists + fice(:,:) = 0._r8 + fsnow(:,:) = 0._r8 +!REMOVECAM_END + call cldfrc_fice( ncol, state_loc%t(:ncol,:), fice(:ncol,:), fsnow(:ncol,:) ) lq(:) = .FALSE. diff --git a/src/physics/cam/rk_stratiform.F90 b/src/physics/cam/rk_stratiform.F90 index 5d165acc40..84607a20b7 100644 --- a/src/physics/cam/rk_stratiform.F90 +++ b/src/physics/cam/rk_stratiform.F90 @@ -2,7 +2,7 @@ module rk_stratiform !------------------------------------------------------------------------------------------------------- ! -! Provides the CAM interface to the Rasch and Kristjansson (RK) +! Provides the CAM interface to the Rasch and Kristjansson (RK) ! prognostic cloud microphysics, and the cam3/4 macrophysics. ! !------------------------------------------------------------------------------------------------------- @@ -27,26 +27,26 @@ module rk_stratiform public :: rk_stratiform_tend public :: rk_stratiform_readnl -! Physics buffer indices +! Physics buffer indices integer :: landm_idx = 0 -integer :: qcwat_idx = 0 -integer :: lcwat_idx = 0 -integer :: tcwat_idx = 0 +integer :: qcwat_idx = 0 +integer :: lcwat_idx = 0 +integer :: tcwat_idx = 0 -integer :: cld_idx = 0 -integer :: ast_idx = 0 -integer :: concld_idx = 0 -integer :: fice_idx = 0 +integer :: cld_idx = 0 +integer :: ast_idx = 0 +integer :: concld_idx = 0 +integer :: fice_idx = 0 -integer :: qme_idx = 0 -integer :: prain_idx = 0 -integer :: nevapr_idx = 0 +integer :: qme_idx = 0 +integer :: prain_idx = 0 +integer :: nevapr_idx = 0 integer :: wsedl_idx = 0 -integer :: rei_idx = 0 -integer :: rel_idx = 0 +integer :: rei_idx = 0 +integer :: rel_idx = 0 integer :: shfrc_idx = 0 integer :: cmfmc_sh_idx = 0 @@ -92,8 +92,8 @@ subroutine rk_stratiform_readnl(nlfile) character(len=*), parameter :: subname = 'rk_stratiform_readnl' ! Namelist variables - real(r8) :: rk_strat_icritw = unset_r8 ! icritw = threshold for autoconversion of warm ice - real(r8) :: rk_strat_icritc = unset_r8 ! icritc = threshold for autoconversion of cold ice + real(r8) :: rk_strat_icritw = unset_r8 ! icritw = threshold for autoconversion of warm ice + real(r8) :: rk_strat_icritc = unset_r8 ! icritc = threshold for autoconversion of cold ice real(r8) :: rk_strat_conke = unset_r8 ! conke = tunable constant for evaporation of precip real(r8) :: rk_strat_r3lcrit = unset_r8 ! r3lcrit = critical radius where liq conversion begins real(r8) :: rk_strat_polstrat_rhmin = unset_r8 ! condensation threadhold in polar stratosphere @@ -144,7 +144,7 @@ subroutine rk_stratiform_register use constituents, only: cnst_add, pcnst use physconst, only: mwh2o, cpair - + use physics_buffer, only : pbuf_add_field, dtype_r8, dyn_time_lvls !----------------------------------------------------------------------- @@ -166,7 +166,7 @@ subroutine rk_stratiform_register call pbuf_add_field('AST', 'global', dtype_r8, (/pcols,pver,dyn_time_lvls/), ast_idx) call pbuf_add_field('CONCLD', 'global', dtype_r8, (/pcols,pver,dyn_time_lvls/), concld_idx) - call pbuf_add_field('FICE', 'physpkg', dtype_r8, (/pcols,pver/), fice_idx) + call pbuf_add_field('FICE', 'physpkg', dtype_r8, (/pcols,pver/), fice_idx) call pbuf_add_field('QME', 'physpkg', dtype_r8, (/pcols,pver/), qme_idx) call pbuf_add_field('PRAIN', 'physpkg', dtype_r8, (/pcols,pver/), prain_idx) @@ -186,8 +186,8 @@ end subroutine rk_stratiform_register function rk_stratiform_implements_cnst(name) - !----------------------------------------------------------------------------- ! - ! ! + !----------------------------------------------------------------------------- ! + ! ! ! Return true if specified constituent is implemented by this package ! ! ! !----------------------------------------------------------------------------- ! @@ -208,7 +208,7 @@ subroutine rk_stratiform_init_cnst(name, latvals, lonvals, mask, q) !----------------------------------------------------------------------- ! ! ! ! Initialize the cloud water mixing ratios (liquid and ice), if they are ! - ! not read from the initial file ! + ! not read from the initial file ! ! ! !----------------------------------------------------------------------- ! @@ -237,7 +237,7 @@ subroutine rk_stratiform_init() !-------------------------------------------- ! ! ! ! Initialize the cloud water parameterization ! - ! ! + ! ! !-------------------------------------------- ! use physics_buffer, only: physics_buffer_desc, pbuf_get_index @@ -247,7 +247,7 @@ subroutine rk_stratiform_init() use phys_control, only: cam_physpkg_is use physconst, only: tmelt, rhodair, rh2o use cldwat, only: inimc - + integer :: m, mm logical :: history_amwg ! output the variables used by the AMWG diag package logical :: history_aerosol ! Output the MAM aerosol tendencies @@ -258,7 +258,7 @@ subroutine rk_stratiform_init() !----------------------------------------------------------------------- call phys_getopts( history_aerosol_out = history_aerosol , & - history_amwg_out = history_amwg , & + history_amwg_out = history_amwg , & history_budget_out = history_budget , & history_budget_histfile_num_out = history_budget_histfile_num) @@ -268,7 +268,7 @@ subroutine rk_stratiform_init() if( convect_shallow_use_shfrc() ) then use_shfrc = .true. shfrc_idx = pbuf_get_index('shfrc') - else + else use_shfrc = .false. endif @@ -326,7 +326,7 @@ subroutine rk_stratiform_init() call addfld ('ICWMR', (/ 'lev' /), 'A', 'kg/kg' , 'Prognostic in-cloud water mixing ratio' ) call addfld ('ICIMR', (/ 'lev' /), 'A', 'kg/kg' , 'Prognostic in-cloud ice mixing ratio' ) call addfld ('PCSNOW', horiz_only , 'A', 'm/s' , 'Snow fall from prognostic clouds' ) - + call addfld ('DQSED', (/ 'lev' /), 'A', 'kg/kg/s' , 'Water vapor tendency from cloud sedimentation' ) call addfld ('DLSED', (/ 'lev' /), 'A', 'kg/kg/s' , 'Cloud liquid tendency from sedimentation' ) call addfld ('DISED', (/ 'lev' /), 'A', 'kg/kg/s' , 'Cloud ice tendency from sedimentation' ) @@ -339,7 +339,7 @@ subroutine rk_stratiform_init() call addfld ('CNVCLD', horiz_only, 'A', 'fraction', 'Vertically integrated convective cloud amount' ) call addfld ('CLDST', (/ 'lev' /), 'A', 'fraction', 'Stratus cloud fraction' ) call addfld ('CONCLD', (/ 'lev' /), 'A', 'fraction', 'Convective cloud cover' ) - + call addfld ('AST', (/ 'lev' /), 'A','fraction' , 'Stratus cloud fraction' ) call addfld ('LIQCLDF', (/ 'lev' /), 'A', 'fraction', 'Stratus Liquid cloud fraction' ) call addfld ('ICECLDF', (/ 'lev' /), 'A', 'fraction', 'Stratus ICE cloud fraction' ) @@ -420,11 +420,11 @@ subroutine rk_stratiform_tend( & dlf2, rliq, cmfmc, ts, & sst, zdu) - !-------------------------------------------------------- ! - ! ! + !-------------------------------------------------------- ! + ! ! ! Interface to sedimentation, detrain, cloud fraction and ! ! cloud macro - microphysics subroutines ! - ! ! + ! ! !-------------------------------------------------------- ! use cloud_fraction, only: cldfrc, cldfrc_fice @@ -475,7 +475,7 @@ subroutine rk_stratiform_tend( & ! Physics buffer fields real(r8), pointer :: landm(:) ! Land fraction ramped over water - real(r8), pointer :: prec_str(:) ! [Total] Sfc flux of precip from stratiform [ m/s ] + real(r8), pointer :: prec_str(:) ! [Total] Sfc flux of precip from stratiform [ m/s ] real(r8), pointer :: snow_str(:) ! [Total] Sfc flux of snow from stratiform [ m/s ] real(r8), pointer :: prec_sed(:) ! Surface flux of total cloud water from sedimentation real(r8), pointer :: snow_sed(:) ! Surface flux of cloud ice from sedimentation @@ -517,12 +517,12 @@ subroutine rk_stratiform_tend( & real(r8) :: clc(pcols) ! Column convective cloud amount real(r8) :: relhum(pcols,pver) ! RH, output to determine drh/da real(r8) :: rhu00(pcols,pver) - real(r8) :: rhu002(pcols,pver) ! Same as rhu00 but for perturbed rh + real(r8) :: rhu002(pcols,pver) ! Same as rhu00 but for perturbed rh real(r8) :: rhdfda(pcols,pver) real(r8) :: cld2(pcols,pver) ! Same as cld but for perturbed rh - real(r8) :: concld2(pcols,pver) ! Same as concld but for perturbed rh - real(r8) :: cldst2(pcols,pver) ! Same as cldst but for perturbed rh - real(r8) :: relhum2(pcols,pver) ! RH after perturbation + real(r8) :: concld2(pcols,pver) ! Same as concld but for perturbed rh + real(r8) :: cldst2(pcols,pver) ! Same as cldst but for perturbed rh + real(r8) :: relhum2(pcols,pver) ! RH after perturbation real(r8) :: icecldf(pcols,pver) ! Ice cloud fraction real(r8) :: liqcldf(pcols,pver) ! Liquid cloud fraction (combined into cloud) real(r8) :: icecldf_out(pcols,pver) ! Ice cloud fraction @@ -547,11 +547,11 @@ subroutine rk_stratiform_tend( & real(r8) :: repartht(pcols,pver) ! Heating rate due to phase repartition of input precip real(r8) :: icimr(pcols,pver) ! In cloud ice mixing ratio real(r8) :: icwmr(pcols,pver) ! In cloud water mixing ratio - real(r8) :: fwaut(pcols,pver) - real(r8) :: fsaut(pcols,pver) - real(r8) :: fracw(pcols,pver) - real(r8) :: fsacw(pcols,pver) - real(r8) :: fsaci(pcols,pver) + real(r8) :: fwaut(pcols,pver) + real(r8) :: fsaut(pcols,pver) + real(r8) :: fracw(pcols,pver) + real(r8) :: fsacw(pcols,pver) + real(r8) :: fsaci(pcols,pver) real(r8) :: cmeice(pcols,pver) ! Rate of cond-evap of ice within the cloud real(r8) :: cmeliq(pcols,pver) ! Rate of cond-evap of liq within the cloud real(r8) :: ice2pr(pcols,pver) ! Rate of conversion of ice to precip @@ -569,8 +569,8 @@ subroutine rk_stratiform_tend( & real(r8) :: psacio(pcols,pver) ! RK accretion of cloud ice by snow (1/s) real(r8) :: iwc(pcols,pver) ! Grid box average ice water content - real(r8) :: lwc(pcols,pver) ! Grid box average liquid water content - + real(r8) :: lwc(pcols,pver) ! Grid box average liquid water content + logical :: lq(pcnst) integer :: troplev(pcols) real(r8) :: rlat(pcols) @@ -598,7 +598,7 @@ subroutine rk_stratiform_tend( & call pbuf_get_field(pbuf, ast_idx, ast, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) ) call pbuf_get_field(pbuf, fice_idx, fice) - + call pbuf_get_field(pbuf, cmfmc_sh_idx, cmfmc_sh) call pbuf_get_field(pbuf, prec_str_idx, prec_str) @@ -616,7 +616,7 @@ subroutine rk_stratiform_tend( & call pbuf_get_field(pbuf, rei_idx, rei) call pbuf_get_field(pbuf, wsedl_idx, wsedl) - + ! check that qcwat and tcwat were initialized; if not then do it now. if (qcwat(1,1) == huge(1._r8)) then qcwat(:ncol,:) = state%q(:ncol,:,1) @@ -636,16 +636,16 @@ subroutine rk_stratiform_tend( & ! ------------- ! ! Allow the cloud liquid drops and ice particles to sediment. - ! This is done before adding convectively detrained cloud water, + ! This is done before adding convectively detrained cloud water, ! because the phase of the detrained water is unknown. call t_startf('stratiform_sediment') call cld_sediment_vel( ncol, & icefrac, landfrac, ocnfrac, state1%pmid, state1%pdel, state1%t, & - cld, state1%q(:,:,ixcldliq), state1%q(:,:,ixcldice), & + cld, state1%q(:,:,ixcldliq), state1%q(:,:,ixcldice), & pvliq, pvice, landm, snowh ) - + wsedl(:ncol,:pver) = pvliq(:ncol,:pver)/gravit/(state1%pmid(:ncol,:pver)/(287.15_r8*state1%t(:ncol,:pver))) lq(:) = .FALSE. @@ -680,7 +680,7 @@ subroutine rk_stratiform_tend( & call physics_ptend_init(ptend_all, state%psetcols, 'stratiform') call physics_ptend_sum( ptend_loc, ptend_all, ncol ) - ! Update physics state type state1 with ptend_loc + ! Update physics state type state1 with ptend_loc call physics_update( state1, ptend_loc, dtime ) call t_stopf('stratiform_sediment') @@ -695,13 +695,13 @@ subroutine rk_stratiform_tend( & ! Put all of the detraining cloud water from convection into the large scale cloud. ! It all goes in liquid for the moment. - ! Strictly speaking, this approach is detraining all the cconvective water into + ! Strictly speaking, this approach is detraining all the cconvective water into ! the environment, not the large-scale cloud. lq(:) = .FALSE. lq(ixcldliq) = .TRUE. call physics_ptend_init( ptend_loc, state1%psetcols, 'pcwdetrain', lq=lq) - + do k = 1, pver do i = 1, state1%ncol ptend_loc%q(i,k,ixcldliq) = dlf(i,k) @@ -725,7 +725,7 @@ subroutine rk_stratiform_tend( & ! -------------------------------------- ! ! ----------------------------------------------------------------------------- ! - ! Treatment of cloud fraction in CAM4 and CAM5 differs ! + ! Treatment of cloud fraction in CAM4 and CAM5 differs ! ! (1) CAM4 ! ! . Cumulus AMT = Deep Cumulus AMT ( empirical fcn of mass flux ) + ! ! Shallow Cumulus AMT ( empirical fcn of mass flux ) ! @@ -738,7 +738,7 @@ subroutine rk_stratiform_tend( & ! . Stratus AMT = fcn of environmental-mean RH ( no Stability Stratus ) ! ! . Cumulus and Stratus are non-overlapped with higher priority on Cumulus ! ! . Cumulus ( both Deep and Shallow ) has its own LWC and IWC. ! - ! ----------------------------------------------------------------------------- ! + ! ----------------------------------------------------------------------------- ! if( use_shfrc ) then call pbuf_get_field(pbuf, shfrc_idx, shfrc ) @@ -748,8 +748,8 @@ subroutine rk_stratiform_tend( & endif ! Stratus ('ast' = max(alst,aist)) and total cloud fraction ('cld = ast + concld') - ! will be computed using this updated 'concld' in the stratiform macrophysics - ! scheme (mmacro_pcond) later below. + ! will be computed using this updated 'concld' in the stratiform macrophysics + ! scheme (mmacro_pcond) later below. call t_startf("cldfrc") call cldfrc( lchnk, ncol, pbuf, & @@ -759,7 +759,7 @@ subroutine rk_stratiform_tend( & cmfmc, cmfmc_sh, landfrac,snowh, concld, cldst, & ts, sst, state1%pint(:,pverp), zdu, ocnfrac, rhu00, & state1%q(:,:,ixcldice), icecldf, liqcldf, & - relhum, 0 ) + relhum, 0 ) ! Re-calculate cloud with perturbed rh add call cldfrc to estimate rhdfda. @@ -770,7 +770,7 @@ subroutine rk_stratiform_tend( & cmfmc, cmfmc_sh, landfrac, snowh, concld2, cldst2, & ts, sst, state1%pint(:,pverp), zdu, ocnfrac, rhu002, & state1%q(:,:,ixcldice), icecldf2, liqcldf2, & - relhum2, 1 ) + relhum2, 1 ) call t_stopf("cldfrc") @@ -785,7 +785,7 @@ subroutine rk_stratiform_tend( & ! Under certain circumstances, rh+ cause cld not to changed ! when at an upper limit, or w/ strong subsidence if( ( cld2(i,k) - cld(i,k) ) < 1.e-4_r8 ) then - rhdfda(i,k) = 0.01_r8*relhum(i,k)*1.e+4_r8 + rhdfda(i,k) = 0.01_r8*relhum(i,k)*1.e+4_r8 else rhdfda(i,k) = 0.01_r8*relhum(i,k)/(cld2(i,k)-cld(i,k)) endif @@ -802,13 +802,17 @@ subroutine rk_stratiform_tend( & rdtime = 1._r8/dtime ! Define fractional amount of stratus condensate and precipitation in ice phase. - ! This uses a ramp ( -30 ~ -10 for fice, -5 ~ 0 for fsnow ). + ! This uses a ramp ( -30 ~ -10 for fice, -5 ~ 0 for fsnow ). ! The ramp within convective cloud may be different - call cldfrc_fice(ncol, state1%t, fice, fsnow) +!REMOVECAM - no longer need these when CAM is retired and pcols no longer exists + fice(:,:) = 0._r8 + fsnow(:,:) = 0._r8 +!REMOVECAM_END + call cldfrc_fice(ncol, state1%t(1:ncol,:), fice(1:ncol,:), fsnow(1:ncol,:)) - ! Perform repartitioning of stratiform condensate. - ! Corresponding heating tendency will be added later. + ! Perform repartitioning of stratiform condensate. + ! Corresponding heating tendency will be added later. lq(:) = .FALSE. lq(ixcldice) = .true. @@ -830,7 +834,7 @@ subroutine rk_stratiform_tend( & repartht(:ncol,:pver) = (latice/dtime) * ( state1%q(:ncol,:pver,ixcldice) - repartht(:ncol,:pver) ) - ! Non-micro and non-macrophysical external advective forcings to compute net condensation rate. + ! Non-micro and non-macrophysical external advective forcings to compute net condensation rate. ! Note that advective forcing of condensate is aggregated into liquid phase. qtend(:ncol,:pver) = ( state1%q(:ncol,:pver,1) - qcwat(:ncol,:pver) ) * rdtime @@ -869,7 +873,7 @@ subroutine rk_stratiform_tend( & ptend_loc%q(i,k,ixcldliq) = qme(i,k)*(1._r8-fice(i,k)) - liq2pr(i,k) end do end do - + do k = 1, pver do i = 1, ncol ast(i,k) = cld(i,k) @@ -960,7 +964,7 @@ subroutine rk_stratiform_tend( & cmfmc, cmfmc_sh, landfrac, snowh, concld, cldst, & ts, sst, state1%pint(:,pverp), zdu, ocnfrac, rhu00, & state1%q(:,:,ixcldice), icecldf, liqcldf, & - relhum, 0 ) + relhum, 0 ) call t_stopf("cldfrc") endif @@ -968,7 +972,7 @@ subroutine rk_stratiform_tend( & call outfld( 'CONCLD ', concld, pcols, lchnk ) call outfld( 'CLDST ', cldst, pcols, lchnk ) call outfld( 'CNVCLD ', clc, pcols, lchnk ) - call outfld( 'AST', ast, pcols, lchnk ) + call outfld( 'AST', ast, pcols, lchnk ) do k = 1, pver do i = 1, ncol @@ -1000,7 +1004,7 @@ subroutine rk_stratiform_tend( & tcwat(:ncol,k) = state1%t(:ncol,k) lcwat(:ncol,k) = state1%q(:ncol,k,ixcldice) + state1%q(:ncol,k,ixcldliq) end do - + ! Cloud water and ice particle sizes, saved in physics buffer for radiation call cldefr( lchnk, ncol, landfrac, state1%t, rel, rei, state1%ps, state1%pmid, landm, icefrac, snowh ) @@ -1025,7 +1029,7 @@ subroutine debug_microphys_1(state1,ptend,i,k, & use physconst, only: tmelt implicit none - + integer, intent(in) :: i,k type(physics_state), intent(in) :: state1 ! local copy of the state variable type(physics_ptend), intent(in) :: ptend ! local copy of the ptend variable @@ -1058,11 +1062,11 @@ subroutine debug_microphys_1(state1,ptend,i,k, & wv = 0 wi = 0 wlf = 0 - wvf = 0 + wvf = 0 wif = 0 - write(iulog,*) + write(iulog,*) write(iulog,*) ' input state, t, q, l, i ', k, state1%t(i,k), state1%q(i,k,1), state1%q(i,k,ixcldliq), state1%q(i,k,ixcldice) write(iulog,*) ' rain, snow, total from components before accumulation ', qr1, qs1, qr1+qs1 write(iulog,*) ' total precip before accumulation ', k, pr1 @@ -1143,7 +1147,7 @@ subroutine debug_microphys_1(state1,ptend,i,k, & ! + evapheat(i,k) + prfzheat(i,k) + meltheat(i,k) res = qs1+qr1-pr1 - w4 = max(abs(qs1),abs(qr1),abs(pr1)) + w4 = max(abs(qs1),abs(qr1),abs(pr1)) if (w4.gt.0._r8) then if (res/w4.gt.1.e-14_r8) then write(iulog,*) ' imbalance in precips calculated two ways ' @@ -1173,14 +1177,14 @@ subroutine debug_microphys_2(state1,& use ppgrid, only: pver use physconst, only: tmelt use physics_types, only: physics_state - + implicit none type(physics_state), intent(in) :: state1 ! local copy of the state variable real(r8), intent(in) :: snow_pcw(pcols) - real(r8), intent(in) :: fsaut(pcols,pver) - real(r8), intent(in) :: fsacw(pcols,pver) - real(r8), intent(in) :: fsaci(pcols,pver) + real(r8), intent(in) :: fsaut(pcols,pver) + real(r8), intent(in) :: fsacw(pcols,pver) + real(r8), intent(in) :: fsaci(pcols,pver) real(r8), intent(in) :: meltheat(pcols,pver) ! heating rate due to phase change of precip @@ -1189,7 +1193,7 @@ subroutine debug_microphys_2(state1,& ncol = state1%ncol lchnk = state1%lchnk - + do i = 1,ncol if (snow_pcw(i) .gt. 0.01_r8/8.64e4_r8 .and. state1%t(i,pver) .gt. tmelt) then write(iulog,*) ' stratiform: snow, temp, ', i, lchnk, & @@ -1201,7 +1205,7 @@ subroutine debug_microphys_2(state1,& write(iulog,*) ' meltheat ', meltheat(i,:) call endrun ('STRATIFORM_TEND') endif - + if (snow_pcw(i)*8.64e4_r8 .lt. -1.e-5_r8) then write(iulog,*) ' neg snow ', snow_pcw(i)*8.64e4_r8 write(iulog,*) ' stratiform: snow_pcw, temp, ', i, lchnk, & @@ -1214,7 +1218,7 @@ subroutine debug_microphys_2(state1,& call endrun ('STRATIFORM_TEND') endif end do - + end subroutine debug_microphys_2 end module rk_stratiform diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index a245c54778..b69f02d125 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -486,7 +486,10 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & integer :: ii real(r8),pointer :: zm_org2d(:,:) - real(r8),pointer :: orgt(:,:), org(:,:) + real(r8),allocatable :: orgt_alloc(:,:), org_alloc(:,:) + + real(r8) :: zm_org2d_noalloc(state%ncol,pver) + real(r8) :: orgt_noalloc(state%ncol,pver), org_noalloc(state%ncol,pver) logical :: lq(pcnst) @@ -546,43 +549,60 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & ! call t_startf ('zm_convr_run') -!CACNOTE - Need to remove the pointer and may need to copy in/out around the zm_convr_run call if (zmconv_org) then allocate(zm_org2d(pcols,pver)) - org => state%q(:,:,ixorg) - orgt => ptend_loc%q(:,:,ixorg) + allocate(org_alloc(ncol,pver)) + allocate(orgt_alloc(ncol,pver)) + org_noalloc(:ncol,:) = state%q(1:ncol,:,ixorg) endif +!REMOVECAM - no longer need these when CAM is retired and pcols no longer exists + ptend_loc%q(:,:,1) = 0._r8 + ptend_loc%s(:,:) = 0._r8 + mcon(:,:) = 0._r8 + dlf(:,:) = 0._r8 + pflx(:,:) = 0._r8 + cme(:,:) = 0._r8 + cape(:) = 0._r8 + zdu(:,:) = 0._r8 + rprd(:,:) = 0._r8 + dif(:,:) = 0._r8 + dnlf(:,:) = 0._r8 + dnif(:,:) = 0._r8 + mu(:,:) = 0._r8 + eu(:,:) = 0._r8 + du(:,:) = 0._r8 + md(:,:) = 0._r8 + ed(:,:) = 0._r8 + dp(:,:) = 0._r8 + dsubcld(:) = 0._r8 + jctop(:) = 0._r8 + jcbot(:) = 0._r8 + prec(:) = 0._r8 + rliq(:) = 0._r8 + rice(:) = 0._r8 + ideep(:) = 0._r8 +!REMOVECAM_END + !CACNOTE - Need to check errflg and report errors -! call zm_convr_run(ncol, ncol, pver, & -! pverp, gravit, latice, cpwv, cpliq, rh2o, & -! state%t(:ncol,:), state%q(:ncol,:,1), prec(:ncol), jctop(:ncol), jcbot(:ncol), & -! pblh(:ncol), state%zm(:ncol,:), state%phis, state%zi(:ncol,:), ptend_loc%q(:ncol,:,1), & -! ptend_loc%s(:ncol,:), state%pmid(:ncol,:), state%pint(:ncol,:), state%pdel(:ncol,:), & -! .5_r8*ztodt, mcon(:ncol,:), cme(:ncol,:), cape(:ncol), & -! tpert(:ncol), dlf(:ncol,:), pflx(:ncol,:), zdu(:ncol,:), rprd(:ncol,:), & -! mu(:ncol,:), md(:ncol,:), du(:ncol,:), eu(:ncol,:), ed(:ncol,:), & -! dp(:ncol,:), dsubcld(:ncol), jt(:ncol), maxg(:ncol), ideep(:ncol), & -! ql(:ncol,:), rliq(:ncol), landfrac(:ncol), & -!!CACNOTE - This call needs to be used when the pointer attribute is removed from these variables -!! org(:ncol,:), orgt(:ncol,:), zm_org2d(:ncol,:), & -! org, orgt, zm_org2d, & -! dif(:ncol,:), dnlf(:ncol,:), dnif(:ncol,:), & -! rice(:ncol), errmsg, errflg) - - call zm_convr_run(ncol, pcols, pver, & + call zm_convr_run(ncol, pver, & pverp, gravit, latice, cpwv, cpliq, rh2o, & - state%t, state%q(:,:,1), prec, jctop, jcbot, & - pblh, state%zm, state%phis, state%zi, ptend_loc%q(:,:,1), & - ptend_loc%s, state%pmid, state%pint, state%pdel, & - .5_r8*ztodt, mcon, cme, cape, & - tpert, dlf, pflx, zdu, rprd, & - mu, md, du, eu, ed, & - dp, dsubcld, jt, maxg, ideep, & - ql, rliq, landfrac, & - org, orgt, zm_org2d, & - dif, dnlf, dnif, & - rice, errmsg, errflg) + state%t(:ncol,:), state%q(:ncol,:,1), prec(:ncol), jctop(:ncol), jcbot(:ncol), & + pblh(:ncol), state%zm(:ncol,:), state%phis, state%zi(:ncol,:), ptend_loc%q(:ncol,:,1), & + ptend_loc%s(:ncol,:), state%pmid(:ncol,:), state%pint(:ncol,:), state%pdel(:ncol,:), & + .5_r8*ztodt, mcon(:ncol,:), cme(:ncol,:), cape(:ncol), & + tpert(:ncol), dlf(:ncol,:), pflx(:ncol,:), zdu(:ncol,:), rprd(:ncol,:), & + mu(:ncol,:), md(:ncol,:), du(:ncol,:), eu(:ncol,:), ed(:ncol,:), & + dp(:ncol,:), dsubcld(:ncol), jt(:ncol), maxg(:ncol), ideep(:ncol), & + ql(:ncol,:), rliq(:ncol), landfrac(:ncol), & + org_noalloc(:,:), orgt_noalloc(:,:), zm_org2d_noalloc(:,:), & + dif(:ncol,:), dnlf(:ncol,:), dnif(:ncol,:), & + rice(:ncol), errmsg, errflg) + + if (zmconv_org) then + ptend_loc%q(:,:,ixorg)=orgt_noalloc(:ncol,:) + zm_org2d(:ncol,:) = zm_org2d_noalloc(:ncol,:) + endif lengath = count(ideep > 0) @@ -666,15 +686,20 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & call pbuf_get_field(pbuf, dp_cldice_idx, dp_cldice ) dp_cldliq(:ncol,:) = 0._r8 dp_cldice(:ncol,:) = 0._r8 +!REMOVECAM - no longer need these when CAM is retired and pcols no longer exists + flxprec(:,:) = 0._r8 + flxsnow(:,:) = 0._r8 + snow(:) = 0._r8 +!REMOVECAM_END - call zm_conv_evap_run(state1%ncol, pcols, pver, pverp, & + call zm_conv_evap_run(state1%ncol, pver, pverp, & gravit, latice, latvap, tmelt, & cpair, zmconv_ke, zmconv_ke_lnd, zmconv_org, & - state1%t(:,:),state1%pmid,state1%pdel,state1%q(:pcols,:pver,1), & - landfrac, & - ptend_loc%s, tend_s_snwprd, tend_s_snwevmlt, ptend_loc%q(:pcols,:pver,1), & - rprd, cld, ztodt, & - prec, snow, ntprprd, ntsnprd , flxprec, flxsnow) + state1%t(:ncol,:),state1%pmid(:ncol,:),state1%pdel(:ncol,:),state1%q(:ncol,:pver,1), & + landfrac(:ncol), & + ptend_loc%s(:ncol,:), tend_s_snwprd(:ncol,:), tend_s_snwevmlt(:ncol,:), ptend_loc%q(:ncol,:pver,1), & + rprd(:ncol,:), cld(:ncol,:), ztodt, & + prec(:ncol), snow(:ncol), ntprprd(:ncol,:), ntsnprd(:ncol,:), flxprec(:ncol,:), flxsnow(:ncol,:) ) evapcdp(:ncol,:pver) = ptend_loc%q(:ncol,:pver,1) @@ -727,12 +752,18 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & l_windt(2) = .true. call t_startf ('zm_conv_momtran_run') - call zm_conv_momtran_run (ncol, pcols, pver, pverp, & - l_windt,winds, 2, mu, md, & + +!REMOVECAM - no longer need this when CAM is retired and pcols no longer exists + wind_tends(:,:,:) = 0._r8 +!REMOVECAM_END + + call zm_conv_momtran_run (ncol, pver, pverp, & + l_windt,winds(:ncol,:,:), 2, mu(:ncol,:), md(:ncol,:), & zmconv_momcu, zmconv_momcd, & - du, eu, ed, dp, dsubcld, & - jt, maxg, ideep, 1, lengath, & - nstep, wind_tends, pguall, pgdall, icwu, icwd, ztodt, seten ) + du(:ncol,:), eu(:ncol,:), ed(:ncol,:), dp(:ncol,:), dsubcld(:ncol), & + jt(:ncol), maxg(:ncol), ideep(:ncol), 1, lengath, & + nstep, wind_tends(:ncol,:,:), pguall(:ncol,:,:), pgdall(:ncol,:,:), & + icwu(:ncol,:,:), icwd(:ncol,:,:), ztodt, seten(:ncol,:) ) call t_stopf ('zm_conv_momtran_run') ptend_loc%u(:ncol,:pver) = wind_tends(:ncol,:pver,1) @@ -781,11 +812,16 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & fake_dpdry(:,:) = 0._r8 call t_startf ('convtran1') - call zm_conv_convtran_run (pcols, pver, & - ptend_loc%lq,state1%q, pcnst, mu, md, & - du, eu, ed, dp, dsubcld, & - jt,maxg, ideep, 1, lengath, & - nstep, fracis, ptend_loc%q, fake_dpdry, ztodt) + +!REMOVECAM - no longer need this when CAM is retired and pcols no longer exists + ptend_loc%q(:,:,:) = 0._r8 +!REMOVECAM_END + + call zm_conv_convtran_run (ncol, pver, & + ptend_loc%lq,state1%q(:ncol,:,:), pcnst, mu(:ncol,:), md(:ncol,:), & + du(:ncol,:), eu(:ncol,:), ed(:ncol,:), dp(:ncol,:), dsubcld(:ncol), & + jt(:ncol), maxg(:ncol), ideep(:ncol), 1, lengath, & + nstep, fracis(:ncol,:,:), ptend_loc%q(:ncol,:,:), fake_dpdry(:ncol,:), ztodt) call t_stopf ('convtran1') call outfld('ZMDICE ',ptend_loc%q(1,1,ixcldice) ,pcols ,lchnk ) @@ -826,6 +862,7 @@ subroutine zm_conv_tend_2( state, ptend, ztodt, pbuf) integer :: i, lchnk, istat integer :: lengath ! number of columns with deep convection integer :: nstep + integer :: ncol real(r8), dimension(pcols,pver) :: dpdry @@ -858,11 +895,13 @@ subroutine zm_conv_tend_2( state, ptend, ztodt, pbuf) call pbuf_get_field(pbuf, zm_maxg_idx, maxg) call pbuf_get_field(pbuf, zm_ideep_idx, ideep) - lengath = count(ideep > 0) lchnk = state%lchnk + ncol = state%ncol nstep = get_nstep() + lengath = count(ideep > 0) + if (any(ptend%lq(:))) then ! initialize dpdry for call to convtran ! it is used for tracers of dry mixing ratio type @@ -872,11 +911,16 @@ subroutine zm_conv_tend_2( state, ptend, ztodt, pbuf) end do call t_startf ('convtran2') - call zm_conv_convtran_run (pcols, pver, & - ptend%lq,state%q, pcnst, mu, md, & - du, eu, ed, dp, dsubcld, & - jt, maxg, ideep, 1, lengath, & - nstep, fracis, ptend%q, dpdry, ztodt) + +!REMOVECAM - no longer need this when CAM is retired and pcols no longer exists + ptend%q(:,:,:) = 0._r8 +!REMOVECAM_END + + call zm_conv_convtran_run (ncol, pver, & + ptend%lq,state%q(:ncol,:,:), pcnst, mu(:ncol,:), md(:ncol,:), & + du(:ncol,:), eu(:ncol,:), ed(:ncol,:), dp(:ncol,:), dsubcld(:ncol), & + jt(:ncol), maxg(:ncol), ideep(:ncol), 1, lengath, & + nstep, fracis(:ncol,:,:), ptend%q(:ncol,:,:), dpdry(:ncol,:), ztodt) call t_stopf ('convtran2') end if diff --git a/src/physics/spcam/crmclouds_camaerosols.F90 b/src/physics/spcam/crmclouds_camaerosols.F90 index b3dc07d271..3d8f2e315f 100644 --- a/src/physics/spcam/crmclouds_camaerosols.F90 +++ b/src/physics/spcam/crmclouds_camaerosols.F90 @@ -732,11 +732,14 @@ subroutine crmclouds_convect_tend(state, ptend, ztodt, pbuf) dsubcld = 0._r8 - call zm_conv_convtran_run (pcols,pver, & - ptend%lq,state%q, pcnst, mu(:,:), md(:,:), & - du(:,:), eu(:,:), ed(:,:), dp(:,:), dsubcld(:), & - jt(:),maxg(:),ideep(:), 1, lengath, & - nstep, fracis, ptend%q, dpdry, ztodt ) + !REMOVECAM - no longer need these when CAM is retired and pcols no longer exists + ptend%q(:,:,:) = 0._r8 + !REMOVECAM_END + call zm_conv_convtran_run (ncol,pver, & + ptend%lq,state%q(:ncol,:,:), pcnst, mu(:ncol,:), md(:ncol,:), & + du(:ncol,:), eu(:ncol,:), ed(:ncol,:), dp(:ncol,:), dsubcld(:ncol), & + jt(:ncol),maxg(:ncol),ideep(:ncol), 1, lengath, & + nstep, fracis(:ncol,:,:), ptend%q(:ncol,:,:), dpdry(:ncol,:), ztodt ) end subroutine crmclouds_convect_tend !===================================================================================================== From 2171b0154df5ba2a0508e7cbc3a1f28a6671efc4 Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Fri, 19 Jan 2024 15:20:02 -0700 Subject: [PATCH 07/10] address final reviewer comments --- Externals_CAM.cfg | 4 ++-- src/chemistry/modal_aero/modal_aero_convproc.F90 | 1 + src/physics/cam/zm_conv_intr.F90 | 14 ++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Externals_CAM.cfg b/Externals_CAM.cfg index 0deba5cb89..edf568fc89 100644 --- a/Externals_CAM.cfg +++ b/Externals_CAM.cfg @@ -50,9 +50,9 @@ tag = ALI_ARMS_v1.0.1 required = True [atmos_phys] -tag = 0f5021cbe5 +tag = atmos_phys0_02_000 protocol = git -repo_url = https://github.com/cacraigucar/atmospheric_physics +repo_url = https://github.com/ESCOMP/atmospheric_physics required = True local_path = src/atmos_phys diff --git a/src/chemistry/modal_aero/modal_aero_convproc.F90 b/src/chemistry/modal_aero/modal_aero_convproc.F90 index 3d13ed52e3..8f3b4a795e 100644 --- a/src/chemistry/modal_aero/modal_aero_convproc.F90 +++ b/src/chemistry/modal_aero/modal_aero_convproc.F90 @@ -587,6 +587,7 @@ subroutine ma_convproc_dp_intr( & call pbuf_get_field(pbuf, zm_ideep_idx, ideep) lengath = count(ideep > 0) + if (lengath > ncol) lengath = ncol ! should not happen, but force it to not be larger than ncol for safety sake fracice(:,:) = 0.0_r8 diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index b69f02d125..d559ce4be4 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -488,8 +488,8 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & real(r8),pointer :: zm_org2d(:,:) real(r8),allocatable :: orgt_alloc(:,:), org_alloc(:,:) - real(r8) :: zm_org2d_noalloc(state%ncol,pver) - real(r8) :: orgt_noalloc(state%ncol,pver), org_noalloc(state%ncol,pver) + real(r8) :: zm_org2d_ncol(state%ncol,pver) + real(r8) :: orgt_ncol(state%ncol,pver), org_ncol(state%ncol,pver) logical :: lq(pcnst) @@ -553,7 +553,7 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & allocate(zm_org2d(pcols,pver)) allocate(org_alloc(ncol,pver)) allocate(orgt_alloc(ncol,pver)) - org_noalloc(:ncol,:) = state%q(1:ncol,:,ixorg) + org_ncol(:ncol,:) = state%q(1:ncol,:,ixorg) endif !REMOVECAM - no longer need these when CAM is retired and pcols no longer exists @@ -595,16 +595,17 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & mu(:ncol,:), md(:ncol,:), du(:ncol,:), eu(:ncol,:), ed(:ncol,:), & dp(:ncol,:), dsubcld(:ncol), jt(:ncol), maxg(:ncol), ideep(:ncol), & ql(:ncol,:), rliq(:ncol), landfrac(:ncol), & - org_noalloc(:,:), orgt_noalloc(:,:), zm_org2d_noalloc(:,:), & + org_ncol(:,:), orgt_ncol(:,:), zm_org2d_ncol(:,:), & dif(:ncol,:), dnlf(:ncol,:), dnif(:ncol,:), & rice(:ncol), errmsg, errflg) if (zmconv_org) then - ptend_loc%q(:,:,ixorg)=orgt_noalloc(:ncol,:) - zm_org2d(:ncol,:) = zm_org2d_noalloc(:ncol,:) + ptend_loc%q(:,:,ixorg)=orgt_ncol(:ncol,:) + zm_org2d(:ncol,:) = zm_org2d_ncol(:ncol,:) endif lengath = count(ideep > 0) + if (lengath > ncol) lengath = ncol ! should not happen, but force it to not be larger than ncol for safety sake call outfld('CAPE', cape, pcols, lchnk) ! RBN - CAPE output ! @@ -901,6 +902,7 @@ subroutine zm_conv_tend_2( state, ptend, ztodt, pbuf) nstep = get_nstep() lengath = count(ideep > 0) + if (lengath > ncol) lengath = ncol ! should not happen, but force it to not be larger than ncol for safety sake if (any(ptend%lq(:))) then ! initialize dpdry for call to convtran From f2dae331c1ab706a3f0ca0973ebfa605b3743b8d Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Fri, 19 Jan 2024 15:27:33 -0700 Subject: [PATCH 08/10] Remove CAM3 test since no longer supported --- cime_config/testdefs/testlist_cam.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml index 8fcb4e0a6f..384387edc2 100644 --- a/cime_config/testdefs/testlist_cam.xml +++ b/cime_config/testdefs/testlist_cam.xml @@ -329,16 +329,6 @@ - - - - - - - - - - From 50f20f4487f2f9d3132c697ab4484e33bece1b0e Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Tue, 23 Jan 2024 11:42:03 -0700 Subject: [PATCH 09/10] Add missing ncol declaration --- src/chemistry/modal_aero/modal_aero_convproc.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/chemistry/modal_aero/modal_aero_convproc.F90 b/src/chemistry/modal_aero/modal_aero_convproc.F90 index 8f3b4a795e..6c8b7cd441 100644 --- a/src/chemistry/modal_aero/modal_aero_convproc.F90 +++ b/src/chemistry/modal_aero/modal_aero_convproc.F90 @@ -532,7 +532,7 @@ subroutine ma_convproc_dp_intr( & integer :: i integer :: itmpveca(pcols) - integer :: l, lchnk, lun + integer :: l, lchnk, lun, ncol integer :: nstep real(r8) :: dpdry(pcols,pver) ! layer delta-p-dry (mb) @@ -565,6 +565,7 @@ subroutine ma_convproc_dp_intr( & ! Initialize lchnk = state%lchnk + ncol = state%ncol nstep = get_nstep() lun = iulog From bd1f0047ccd5630c571a24ba941f6b9c07a6d548 Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Tue, 23 Jan 2024 16:56:24 -0700 Subject: [PATCH 10/10] ChangeLog for cam6_3_146 --- doc/ChangeLog | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 2cb653ca46..a219f92580 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,94 @@ =============================================================== +Tag name: cam6_3_146 +Originator(s): cacraig +Date: Jan 23, 2024 +One-line Summary: ZM clean up in preparation for using via CCPP and remove zmconv_microp feature +Github PR URL: https://github.com/ESCOMP/CAM/pull/890 + +Purpose of changes (include the issue number and title text for each relevant GitHub issue): + - Work to make ZM compatible with CCPP conversion process + - Removed CAM3 switch from ZM in move to no longer support CAM3 + - Remove microphysics embedded in ZM: https://github.com/ESCOMP/CAM/issues/889 + +Describe any changes made to build system: N/A + +Describe any changes made to the namelist: + - removed zmconv_microp namelist + +List any changes to the defaults for the boundary datasets: N/A + +Describe any substantial timing or memory changes: N/A + +Code reviewed by: nusbaume, mwaxmonsky + +List all files eliminated: +D src/physics/cam/zm_microphysics.F90 + - removed zmconv_microp capability as it is not used + +D src/physics/cam/zm_conv.F90 + - moved ZM to ESCOMP/atcmospheric_physics and broke into separate modules + +D cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/shell_commands +D cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cam +D cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_clm +D cime_config/testdefs/testmods_dirs/cam/outfrq3s_convmic/user_nl_cpl + - removed test which tested zmconv_microp + +List all files added and what they do: N/A + +List all existing files that have been modified, and describe the changes: +M Externals_CAM.cfg + - updated ESCOMP/atmospheric_physics to bring in tag with ZM + +M bld/build-namelist +M bld/namelist_files/namelist_defaults_cam.xml +M bld/namelist_files/namelist_definition.xml +M src/physics/cam/clubb_intr.F90 + - removed zmconv_microp namelist and associated code + +M bld/configure + - add location for src/atmos_phys/zm + +M cime_config/testdefs/testlist_cam.xml + - removed test which tested zmconv_microp and CAM3 + +M src/physics/cam/macrop_driver.F90 + - removed zmconv_microp namelist and associated code + - Changes needed to support ZM no longer having pcols dimension + +M src/chemistry/modal_aero/modal_aero_convproc.F90 +M src/physics/cam/cloud_fraction.F90 +M src/physics/cam/convect_shallow.F90 +M src/physics/cam/rk_stratiform.F90 +M src/physics/spcam/crmclouds_camaerosols.F90 + - Changes needed to support ZM no longer having pcols dimension + +M src/physics/cam/zm_conv_intr.F90 + - Changes to prepare this routine to support CCPP conversion + - Pass in variables which were being "use"d in ZM previously + - Only pass :ncol sections of arrays since pcols has been removed from ZM + - removed zmconv_microp namelist and associated code + +If there were any failures reported from running test_driver.sh on any test +platform, and checkin with these failures has been OK'd by the gatekeeper, +then copy the lines from the td.*.status files for the failed tests to the +appropriate machine below. All failed tests must be justified. + +derecho/intel/aux_cam: all BFB except: + ERP_Ln9_Vnuopc.C96_C96_mg17.F2000climo.derecho_intel.cam-outfrq9s_mg3 (Overall: PEND) details: + ERP_Ln9_Vnuopc.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s (Overall: FAIL) details: + - preexisting failures + +izumi/nag/aux_cam: all BFB except: + DAE_Vnuopc.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details: + - preexisting failure + +izumi/gnu/aux_cam: all BFB + +=============================================================== +=============================================================== + Tag name: cam6_3_145 Originator(s): katetc, cacraigucar, andrewgettelman Date: 05 Jan 2024