module mcshallow,3 use cam_history, only:outfld, addfld, phys_decomp use error_function, only: erfc use cam_logfile, only: iulog implicit none private save public init_mcshallow public compute_mcshallow public compute_mcshallow_inv integer , parameter :: r8 = selected_real_kind(12) ! 8 byte real real(r8) :: xlv ! latent heat of vaporization real(r8) :: xlf ! latent heat of fusion real(r8) :: xls ! latent heat of sublimation real(r8) :: cp ! specific heat of dry air real(r8) :: zvir ! rh2o/rair - 1 real(r8) :: r ! gas constant for dry air real(r8) :: g ! gravitational constant real(r8) :: ep2 ! mol wgt water vapor / mol wgt dry air real(r8) :: p00 ! reference pressure for exner function real(r8) :: rovcp ! R/cp contains real(r8) function exnf(pressure) 26 real(r8), intent(in) :: pressure exnf = (pressure/p00)**rovcp return end function exnf subroutine init_mcshallow(kind,xlv_in,cp_in,xlf_in,zvir_in,r_in,g_in,ep2_in),92 !------------------------------------------------------------------------- ! Purpose: ! Initialize time independent variables of the shallow convection package. !------------------------------------------------------------------------- use cam_history, only:outfld, addfld, phys_decomp use ppgrid, only:pcols, pver, pverp implicit none integer , intent(in) :: kind ! kind of reals being passed in real(r8), intent(in) :: xlv_in ! latent heat of vaporization real(r8), intent(in) :: xlf_in ! latent heat of fusion real(r8), intent(in) :: cp_in ! specific heat of dry air real(r8), intent(in) :: zvir_in ! rh2o/rair - 1 real(r8), intent(in) :: r_in ! gas constant for dry air real(r8), intent(in) :: g_in ! gravitational constant real(r8), intent(in) :: ep2_in ! mol wgt water vapor / mol wgt dry air ! ------------------------- ! ! Internal Output Variables ! ! ------------------------- ! call addfld('qtflx_Cu','kg/m2/s',pverp,'A','Cumulus qt flux',phys_decomp) call addfld('slflx_Cu','J/m2/s',pverp,'A','Cumulus sl flux',phys_decomp) call addfld('uflx_Cu','kg/m/s2',pverp,'A','Cumulus u flux',phys_decomp) call addfld('vflx_Cu','kg/m/s2',pverp,'A','Cumulus v flux',phys_decomp) call addfld('qtten_Cu','kg/kg/s',pver,'A','qt tendency by cumulus convection',phys_decomp) call addfld('slten_Cu','J/kg/s',pver,'A','sl tendency by cumulus convection',phys_decomp) call addfld('uten_Cu','m/s2',pver,'A','u tendency by cumulus convection',phys_decomp) call addfld('vten_Cu','m/s2',pver,'A','v tendency by cumulus convection',phys_decomp) call addfld('qvten_Cu','kg/kg/s',pver,'A','qv tendency by cumulus convection',phys_decomp) call addfld('qlten_Cu','kg/kg/s',pver,'A','ql tendency by cumulus convection',phys_decomp) call addfld('qiten_Cu','kg/kg/s',pver,'A','qi tendency by cumulus convection',phys_decomp) call addfld('cbmf_Cu','kg/m2/s',1,'A','Cumulus Base Mass Flux',phys_decomp) call addfld('ufrcinvbase_Cu','no',1,'A','Cumulus Fraction at PBL Top',phys_decomp) call addfld('ufrclcl_Cu','no',1,'A','Cumulus Fraction at LCL',phys_decomp) call addfld('winvbase_Cu','m/s',1,'A','Cumulus Vertical Velocity at PBL top',phys_decomp) call addfld('wlcl_Cu','m/s',1,'A','Cumulus Vertical Velocity at LCL',phys_decomp) call addfld('plcl_Cu','Pa',1,'A','LCL of Source Air',phys_decomp) call addfld('pinv_Cu','Pa',1,'A','PBL Top Pressure',phys_decomp) call addfld('plfc_Cu','Pa',1,'A','LFC of Source Air',phys_decomp) call addfld('pbup_Cu','Pa',1,'A','Highest Level of Positive Cu Buoyancy',phys_decomp) call addfld('ppen_Cu','Pa',1,'A','Highest Level where Cu W is 0',phys_decomp) call addfld('qtsrc_Cu','kg/kg',1,'A','Source Air qt',phys_decomp) call addfld('thlsrc_Cu','K',1,'A','Source Air thl',phys_decomp) call addfld('thvlsrc_Cu','K',1,'A','Source Air thvl',phys_decomp) call addfld('emfkbup_Cu','kg/m2/s',1,'A','Penetrative Mass Flux at kbup',phys_decomp) call addfld('cin_Cu','J/kg',1,'A','CIN upto LFC',phys_decomp) call addfld('cinlcl_Cu','J/kg',1,'A','CIN upto LCL',phys_decomp) call addfld('cbmflimit_Cu','kg/m2/s',1,'A','cbmflimiter',phys_decomp) call addfld('tkeavg_Cu','m2/s2',1,'A','tkeavg_Cu',phys_decomp) call addfld('zinv_Cu','m',1,'A','PBL Top Height',phys_decomp) call addfld('rcwp_Cu','kg/m2',1,'A','Cumulus LWP+IWP',phys_decomp) call addfld('rlwp_Cu','kg/m2',1,'A','Cumulus LWP',phys_decomp) call addfld('riwp_Cu','kg/m2',1,'A','Cumulus IWP',phys_decomp) call addfld('tophgt_Cu','m',1,'A','Cumulus Top Height',phys_decomp) call addfld('wu_Cu','m/s',pverp,'A','Cumulus Updraft Vertical Velocity',phys_decomp) call addfld('ufrc_Cu','no',pverp,'A','Updraft Fractional Area',phys_decomp) call addfld('qtu_Cu','kg/kg',pverp,'A','Cumulus Updraft qt',phys_decomp) call addfld('thlu_Cu','K',pverp,'A','Cumulus Updraft thl',phys_decomp) call addfld('thvu_Cu','K',pverp,'A','Cumulus Updraft thv',phys_decomp) call addfld('uu_Cu','m/s',pverp,'A','Cumulus Updraft uwnd',phys_decomp) call addfld('vu_Cu','m/s',pverp,'A','Cumulus Updraft vwnd',phys_decomp) call addfld('qtu_emf_Cu','kg/kg',pverp,'A','qt of penatratively entrained air',phys_decomp) call addfld('thlu_emf_Cu','K',pverp,'A','thl of penatratively entrained air',phys_decomp) call addfld('uu_emf_Cu','m/s',pverp,'A','uwnd of penatratively entrained air',phys_decomp) call addfld('vu_emf_Cu','m/s',pverp,'A','vwnd of penatratively entrained air',phys_decomp) call addfld('umf_Cu','kg/m2/s',pverp,'A','Cumulus Updraft Mass Flux',phys_decomp) call addfld('uemf_Cu','kg/m2/s',pverp,'A','Cumulus Net Mass Flux',phys_decomp) call addfld('qcu_Cu','kg/kg',pver,'A','Cumulus updraft LWC+IWC',phys_decomp) call addfld('qlu_Cu','kg/kg',pver,'A','Cumulus updraft LWC',phys_decomp) call addfld('qiu_Cu','kg/kg',pver,'A','Cumulus updraft IWC',phys_decomp) call addfld('cufrc_Cu','no',pver,'A','Cumulus cloud fraction',phys_decomp) call addfld('fer_Cu','1/m',pver,'A','Cumulus lateral fractional entrainment rate',phys_decomp) call addfld('fdr_Cu','1/m',pver,'A','Cumulus lateral fractional detrainment Rate',phys_decomp) call addfld('dwten_Cu','kg/kg/s',pver,'A','Expellsion rate of cumulus cloud water to env.',phys_decomp) call addfld('diten_Cu','kg/kg/s',pver,'A','Expellsion rate of cumulus ice water to env.',phys_decomp) call addfld('qrten_Cu','kg/kg/s',pver,'A','Production rate of rain by cumulus',phys_decomp) call addfld('qsten_Cu','kg/kg/s',pver,'A','Production rate of snow by cumulus',phys_decomp) call addfld('flxrain_Cu','kg/m2/s',pverp,'A','Rain flux induced by Cumulus',phys_decomp) call addfld('flxsnow_Cu','kg/m2/s',pverp,'A','Snow flux induced by Cumulus',phys_decomp) call addfld('ntraprd_Cu','kg/kg/s',pver,'A','Net production rate of rain by Cumulus',phys_decomp) call addfld('ntsnprd_Cu','kg/kg/s',pver,'A','Net production rate of snow by Cumulus',phys_decomp) call addfld('excessu_Cu','no',pver,'A','Updraft Saturation Excess',phys_decomp) call addfld('excess0_Cu','no',pver,'A','Environmental Saturation Excess',phys_decomp) call addfld('xc_Cu','no',pver,'A','Critical MIxing Ratio',phys_decomp) call addfld('aquad_Cu','no',pver,'A','aquad',phys_decomp) call addfld('bquad_Cu','no',pver,'A','bquad',phys_decomp) call addfld('cquad_Cu','no',pver,'A','cquad',phys_decomp) call addfld('bogbot_Cu','no',pver,'A','Cloud Buoyancy at the Bottom Interface',phys_decomp) call addfld('bogtop_Cu','no',pver,'A','Cloud Buoyancy at the Top Interface',phys_decomp) call addfld('exit_UWCu_Cu','no',1,'A','exit_UWCu',phys_decomp) call addfld('exit_conden_Cu','no',1,'A','exit_conden',phys_decomp) call addfld('exit_klclmkx_Cu','no',1,'A','exit_klclmkx',phys_decomp) call addfld('exit_klfcmkx_Cu','no',1,'A','exit_klfcmkx',phys_decomp) call addfld('exit_ufrc_Cu','no',1,'A','exit_ufrc',phys_decomp) call addfld('exit_wtw_Cu','no',1,'A','exit_wtw',phys_decomp) call addfld('exit_drycore_Cu','no',1,'A','exit_drycore',phys_decomp) call addfld('exit_wu_Cu','no',1,'A','exit_wu',phys_decomp) call addfld('exit_cufilter_Cu','no',1,'A','exit_cufilter',phys_decomp) call addfld('exit_kinv1_Cu','no',1,'A','exit_kinv1',phys_decomp) call addfld('exit_rei_Cu','no',1,'A','exit_rei',phys_decomp) call addfld('limit_shcu_Cu','no',1,'A','limit_shcu',phys_decomp) call addfld('limit_negcon_Cu','no',1,'A','limit_negcon',phys_decomp) call addfld('limit_ufrc_Cu','no',1,'A','limit_ufrc',phys_decomp) call addfld('limit_ppen_Cu','no',1,'A','limit_ppen',phys_decomp) call addfld('limit_emf_Cu','no',1,'A','limit_emf',phys_decomp) call addfld('limit_cinlcl_Cu','no',1,'A','limit_cinlcl',phys_decomp) call addfld('limit_cin_Cu','no',1,'A','limit_cin',phys_decomp) call addfld('limit_cbmf_Cu','no',1,'A','limit_cbmf',phys_decomp) call addfld('limit_rei_Cu','no',1,'A','limit_rei',phys_decomp) call addfld('ind_delcin_Cu','no',1,'A','ind_delcin',phys_decomp) if (kind .ne. r8) then write(iulog,*) 'wrong KIND of reals passed to init_mcshallow -- exiting.' stop 'init_mcshallow' endif xlv = xlv_in xlf = xlf_in xls = xlv + xlf cp = cp_in zvir = zvir_in r = r_in g = g_in ep2 = ep2_in p00 = 1.e5_r8 rovcp = r/cp end subroutine init_mcshallow subroutine compute_mcshallow_inv( mix , mkx , iend , ncnst , dt , & ,1 ps0_inv , zs0_inv , p0_inv , z0_inv , dp0_inv, & u0_inv , v0_inv , qv0_inv , ql0_inv , qi0_inv, & t0_inv , s0_inv , & tke_inv , cldfrct_inv, concldfrct_inv, pblh , cush, & umf_inv , slflx_inv, qtflx_inv, & qvten_inv, qlten_inv, qiten_inv, & sten_inv , uten_inv , vten_inv , & qrten_inv, qsten_inv, precip , snow, cufrc_inv, & qcu_inv , qlu_inv , qiu_inv , & cbmf, qc_inv, rliq, cnt_inv, cnb_inv, qsat, lchnk ) implicit none integer , intent(in) :: lchnk integer , intent(in) :: mix integer , intent(in) :: mkx integer , intent(in) :: iend integer , intent(in) :: ncnst real(r8), intent(in) :: dt ! time step in seconds : 2*delta_t real(r8), intent(in) :: ps0_inv(mix,mkx+1) ! environmental pressure at full sigma levels real(r8), intent(in) :: zs0_inv(mix,mkx+1) ! environmental height at full sigma levels real(r8), intent(in) :: p0_inv(mix,mkx) ! environmental pressure at half sigma levels real(r8), intent(in) :: z0_inv(mix,mkx) ! environmental height at half sigma levels real(r8), intent(in) :: dp0_inv(mix,mkx) ! environmental layer pressure thickness real(r8), intent(in) :: u0_inv(mix,mkx) ! environmental zonal wind real(r8), intent(in) :: v0_inv(mix,mkx) ! environmental meridional wind real(r8), intent(in) :: qv0_inv(mix,mkx) ! environmental specific humidity real(r8), intent(in) :: ql0_inv(mix,mkx) ! environmental liquid water mixing ratio real(r8), intent(in) :: qi0_inv(mix,mkx) ! environmental ice mixing ratio real(r8), intent(in) :: t0_inv(mix,mkx) ! environmental temperature real(r8), intent(in) :: s0_inv(mix,mkx) ! environmental dry static energy real(r8), intent(in) :: tke_inv(mix,mkx+1) ! turbulent kinetic energy real(r8), intent(in) :: cldfrct_inv(mix,mkx) ! total cloud fraction of previous time step real(r8), intent(in) :: concldfrct_inv(mix,mkx) ! total convective ( shallow + deep ) cloud fraction of previous time step real(r8), intent(in) :: pblh(mix) ! height of PBL real(r8), intent(inout) :: cush(mix) ! convective scale height real(r8), intent(out) :: umf_inv(mix,mkx+1) ! updraft mass flux at top of layer real(r8), intent(out) :: qvten_inv(mix,mkx) ! tendency of specific humidity real(r8), intent(out) :: qlten_inv(mix,mkx) ! tendency of liquid water mixing ratio real(r8), intent(out) :: qiten_inv(mix,mkx) ! tendency of ice mixing ratio real(r8), intent(out) :: sten_inv(mix,mkx) ! tendency of static energy real(r8), intent(out) :: uten_inv(mix,mkx) ! tendency of zonal wind real(r8), intent(out) :: vten_inv(mix,mkx) ! tendency of meridional wind real(r8), intent(out) :: qrten_inv(mix,mkx) ! tendency of rain water mixing ratio real(r8), intent(out) :: qsten_inv(mix,mkx) ! tendency of snow mixing ratio real(r8), intent(out) :: precip(mix) ! precipitation flux at the surface [m/s] real(r8), intent(out) :: snow(mix) ! snow flux at the surface [m/s] real(r8), intent(out) :: rliq(mix) ! vertical integral of qc real(r8), intent(out) :: slflx_inv(mix,mkx+1) ! updraft liquid static energy flux real(r8), intent(out) :: qtflx_inv(mix,mkx+1) ! updraft total water flux real(r8), intent(out) :: cufrc_inv(mix,mkx) ! shallow cumulus cloud fraction real(r8), intent(out) :: qcu_inv(mix,mkx) ! updraft liquid+ice mixing ratio real(r8), intent(out) :: qlu_inv(mix,mkx) ! updraft liquid water mixing ratio real(r8), intent(out) :: qiu_inv(mix,mkx) ! updraft ice mixing ratio real(r8), intent(out) :: qc_inv(mix,mkx) ! real(r8), intent(out) :: cbmf(mix) ! real(r8), intent(out) :: cnt_inv(mix) ! real(r8), intent(out) :: cnb_inv(mix) ! integer , external :: qsat ! function pointer to sat vap pressure function real(r8) :: ps0(mix,0:mkx) ! environmental pressure at full sigma levels real(r8) :: zs0(mix,0:mkx) ! environmental height at full sigma levels real(r8) :: p0(mix,mkx) ! environmental pressure at half sigma levels real(r8) :: z0(mix,mkx) ! environmental height at half sigma levels real(r8) :: dp0(mix,mkx) ! environmental layer pressure thickness real(r8) :: u0(mix,mkx) ! environmental zonal wind real(r8) :: v0(mix,mkx) ! environmental meridional wind real(r8) :: tke(mix,0:mkx) ! turbulent kinetic energy real(r8) :: cldfrct(mix,mkx) ! total cloud fraction of previous time step real(r8) :: concldfrct(mix,mkx) ! total convective cloud fraction previous time step real(r8) :: qv0(mix,mkx) ! environmental specific humidity real(r8) :: ql0(mix,mkx) ! environmental liquid water mixing ratio real(r8) :: qi0(mix,mkx) ! environmental ice mixing ratio real(r8) :: t0(mix,mkx) ! environmental temperature real(r8) :: s0(mix,mkx) ! environmental dry static energy real(r8) :: umf(mix,0:mkx) ! updraft mass flux at top of layer real(r8) :: qvten(mix,mkx) ! tendency of specific humidity real(r8) :: qlten(mix,mkx) ! tendency of liquid water mixing ratio real(r8) :: qiten(mix,mkx) ! tendency of ice mixing ratio real(r8) :: sten(mix,mkx) ! tendency of static energy real(r8) :: uten(mix,mkx) ! tendency of zonal wind real(r8) :: vten(mix,mkx) ! tendency of meridional wind real(r8) :: qrten(mix,mkx) ! tendency of rain water mixing ratio real(r8) :: qsten(mix,mkx) ! tendency of snow mixing ratio real(r8) :: slflx(mix,0:mkx) ! updraft liquid static energy flux real(r8) :: qtflx(mix,0:mkx) ! updraft total water flux real(r8) :: cufrc(mix,mkx) ! shallow cumulus cloud fraction real(r8) :: qcu(mix,mkx) ! updraft condensate water mixing ratio,'qlu(k)+qiu(k)' real(r8) :: qlu(mix,mkx) ! updraft liquid water mixing ratio real(r8) :: qiu(mix,mkx) ! updraft ice mixing ratio real(r8) :: qc(mix,mkx) ! real(r8) :: cnt(mix) ! real(r8) :: cnb(mix) ! integer :: k ! vertical index for local fields integer :: k_inv ! vertical index for incoming fields do k = 1, mkx k_inv = mkx + 1 - k p0(:iend,k) = p0_inv(:iend,k_inv) u0(:iend,k) = u0_inv(:iend,k_inv) v0(:iend,k) = v0_inv(:iend,k_inv) z0(:iend,k) = z0_inv(:iend,k_inv) dp0(:iend,k) = dp0_inv(:iend,k_inv) qv0(:iend,k) = qv0_inv(:iend,k_inv) ql0(:iend,k) = ql0_inv(:iend,k_inv) qi0(:iend,k) = qi0_inv(:iend,k_inv) t0(:iend,k) = t0_inv(:iend,k_inv) s0(:iend,k) = s0_inv(:iend,k_inv) cldfrct(:iend,k) = cldfrct_inv(:iend,k_inv) concldfrct(:iend,k) = concldfrct_inv(:iend,k_inv) end do do k = 0, mkx k_inv = mkx + 1 - k ps0(:iend,k) = ps0_inv(:iend,k_inv) zs0(:iend,k) = zs0_inv(:iend,k_inv) tke(:iend,k) = tke_inv(:iend,k_inv) end do call compute_mcshallow( mix , mkx , iend , ncnst , dt , & ps0 , zs0 , p0 , z0 , dp0 , & u0 , v0 , qv0 , ql0 , qi0 , & t0 , s0 , & tke , cldfrct, concldfrct, pblh, cush , & umf , slflx, qtflx , & qvten, qlten, qiten , & sten , uten , vten , & qrten, qsten, precip, snow, cufrc, & qcu , qlu , qiu , & cbmf, qc, rliq , cnt, cnb, qsat, lchnk ) ! Reverse cloud top/base interface indices cnt_inv(:iend) = mkx + 1 - cnt(:iend) cnb_inv(:iend) = mkx + 1 - cnb(:iend) do k = 0, mkx k_inv = mkx + 1 - k umf_inv(:iend,k_inv) = umf(:iend,k) ! updraft mass flux at top of layer slflx_inv(:iend,k_inv) = slflx(:iend,k) ! updraft liquid static energy flux qtflx_inv(:iend,k_inv) = qtflx(:iend,k) ! updraft total water flux end do do k = 1, mkx k_inv = mkx + 1 - k qvten_inv(:iend,k_inv) = qvten(:iend,k) ! tendency of specific humidity qlten_inv(:iend,k_inv) = qlten(:iend,k) ! tendency of liquid water mixing ratio qiten_inv(:iend,k_inv) = qiten(:iend,k) ! tendency of ice mixing ratio sten_inv(:iend,k_inv) = sten(:iend,k) ! tendency of static energy uten_inv(:iend,k_inv) = uten(:iend,k) ! tendency of zonal wind vten_inv(:iend,k_inv) = vten(:iend,k) ! tendency of meridional wind qrten_inv(:iend,k_inv) = qrten(:iend,k) ! tendency of rain water mixing ratio qsten_inv(:iend,k_inv) = qsten(:iend,k) ! tendency of snow mixing ratio cufrc_inv(:iend,k_inv) = cufrc(:iend,k) ! shallow cumulus cloud fraction qcu_inv(:iend,k_inv) = qcu(:iend,k) ! updraft liquid+ice water mixing ratio qlu_inv(:iend,k_inv) = qlu(:iend,k) ! updraft liquid water mixing ratio qiu_inv(:iend,k_inv) = qiu(:iend,k) ! updraft ice water mixing ratio qc_inv(:iend,k_inv) = qc(:iend,k) ! reserved "qlten+qiten' associated with cumulus detrained water end do end subroutine compute_mcshallow_inv subroutine compute_mcshallow( mix , mkx , iend , ncnst , dt , & 1,141 ps0_in , zs0_in , p0_in , z0_in , dp0_in , & u0_in , v0_in , qv0_in , ql0_in , qi0_in , & t0_in , s0_in , & tke_in , cldfrct_in, concldfrct_in, pblh_in , cush_inout, & umf_out , slflx_out, qtflx_out , & qvten_out, qlten_out, qiten_out , & sten_out , uten_out , vten_out , & qrten_out, qsten_out, precip_out, snow_out, cufrc_out, & qcu_out , qlu_out , qiu_out , & cbmf_out, qc_out, rliq_out, cnt_out, cnb_out, qsat, lchnk ) !======================================================! ! ! ! SHALLOW CONVECTION SCHEME ! ! Described in McCaa, Bretherton, and Grenier: ! ! (submitted to MWR, December 2001) ! ! ! ! Modified by Sungsu Park. Oct.2005. ! ! ! !======================================================! ! ! Input-Output variables ! use cam_history, only:outfld, addfld, phys_decomp implicit none integer , intent(in) :: lchnk integer , intent(in) :: mix integer , intent(in) :: mkx integer , intent(in) :: iend integer , intent(in) :: ncnst real(r8), intent(in) :: dt ! time step in seconds: 2*delta_t real(r8), intent(in) :: ps0_in(mix,0:mkx) ! environmental pressure at full sigma levels real(r8), intent(in) :: zs0_in(mix,0:mkx) ! environmental height at full sigma levels real(r8), intent(in) :: p0_in(mix,mkx) ! environmental pressure at half sigma levels real(r8), intent(in) :: z0_in(mix,mkx) ! environmental height at half sigma levels real(r8), intent(in) :: dp0_in(mix,mkx) ! environmental layer pressure thickness real(r8), intent(in) :: u0_in(mix,mkx) ! environmental zonal wind real(r8), intent(in) :: v0_in(mix,mkx) ! environmental meridional wind real(r8), intent(in) :: qv0_in(mix,mkx) ! environmental specific humidity real(r8), intent(in) :: ql0_in(mix,mkx) ! environmental liquid water mixing ratio real(r8), intent(in) :: qi0_in(mix,mkx) ! environmental ice mixing ratio real(r8), intent(in) :: t0_in(mix,mkx) ! environmental temperature real(r8), intent(in) :: s0_in(mix,mkx) ! environmental dry static energy real(r8), intent(in) :: tke_in(mix,0:mkx) ! turbulent kinetic energy real(r8), intent(in) :: cldfrct_in(mix,mkx) ! total cloud fraction at the previous time step real(r8), intent(in) :: concldfrct_in(mix,mkx) ! total convective cloud fraction at the previous time step real(r8), intent(in) :: pblh_in(mix) ! height of PBL real(r8), intent(inout) :: cush_inout(mix) ! convective scale height real(r8), intent(out) :: umf_out(mix,0:mkx) ! updraft mass flux at top of layer real(r8), intent(out) :: qvten_out(mix,mkx) ! tendency of specific humidity real(r8), intent(out) :: qlten_out(mix,mkx) ! tendency of liquid water mixing ratio real(r8), intent(out) :: qiten_out(mix,mkx) ! tendency of ice mixing ratio real(r8), intent(out) :: sten_out(mix,mkx) ! tendency of static energy real(r8), intent(out) :: uten_out(mix,mkx) ! tendency of zonal wind real(r8), intent(out) :: vten_out(mix,mkx) ! tendency of meridional wind real(r8), intent(out) :: qrten_out(mix,mkx) ! tendency of rain water mixing ratio real(r8), intent(out) :: qsten_out(mix,mkx) ! tendency of snow mixing ratio real(r8), intent(out) :: precip_out(mix) ! precipitation rate at surface [m/s] real(r8), intent(out) :: snow_out(mix) ! snow rate at surface [m/s] real(r8), intent(out) :: slflx_out(mix,0:mkx) ! updraft/pen.entrainment liquid static energy flux real(r8), intent(out) :: qtflx_out(mix,0:mkx) ! updraft/pen.entrainment total water flux real(r8), intent(out) :: cufrc_out(mix,mkx) ! shallow cumulus cloud fraction real(r8), intent(out) :: qcu_out(mix,mkx) ! updraft condensate water mixing ratio, 'qlu(k)+qiu(k)' real(r8), intent(out) :: qlu_out(mix,mkx) ! updraft liquid water mixing ratio real(r8), intent(out) :: qiu_out(mix,mkx) ! updraft ice water mixing ratio real(r8), intent(out) :: cbmf_out(mix) ! real(r8), intent(out) :: qc_out(mix,mkx) ! [kg/kg/s] real(r8), intent(out) :: rliq_out(mix) ! [m/s] real(r8), intent(out) :: cnt_out(mix) ! real(r8), intent(out) :: cnb_out(mix) ! integer , external :: qsat real(r8) qtten_out(mix,mkx) ! tendency of qt real(r8) slten_out(mix,mkx) ! tendency of sl real(r8) ufrc_out(mix,0:mkx) ! updraft fractional area real(r8) uflx_out(mix,0:mkx) ! updraft/pen.entrainment zonal momentum flux real(r8) vflx_out(mix,0:mkx) ! updraft/pen.entrainment meridional momentum flux real(r8) fer_out(mix,mkx) ! lateral entrainment rate real(r8) fdr_out(mix,mkx) ! lateral detrainment rate real(r8) cinh_out(mix) ! convective inhibition upto LFC (CIN) ([J/kg]) ! ! One-dimensional variables at each grid point ! ! 1. Input variables real(r8) ps0(0:mkx) ! environmental pressure at full sigma levels real(r8) zs0(0:mkx) ! environmental height at full sigma levels real(r8) p0(mkx) ! environmental pressure at half sigma levels real(r8) z0(mkx) ! environmental height at half sigma levels real(r8) dp0(mkx) ! environmental layer pressure thickness real(r8) u0(mkx) ! environmental zonal wind real(r8) v0(mkx) ! environmental meridional wind real(r8) tke(0:mkx) ! turbulent kinetic energy real(r8) cldfrct(mkx) ! total cloud fraction at the previous time step real(r8) concldfrct(mkx) ! total convective cloud fraction at the previous time step real(r8) qv0(mkx) ! environmental specific humidity real(r8) ql0(mkx) ! environmental liquid water mixing ratio real(r8) qi0(mkx) ! environmental ice mixing ratio real(r8) t0(mkx) ! environmental temperature real(r8) s0(mkx) ! environmental dry static energy real(r8) pblh ! height of PBL real(r8) cush ! convective scale height ! 2. Environmental variables directly from the input variables real(r8) qt0(mkx) ! environmental total water mixing ratio real(r8) thl0(mkx) ! environmental liquid potential temperature real(r8) thvl0(mkx) ! environmental liquid virtual potential temperature real(r8) ssqt0(mkx) ! slope of environmental total water mixing ratio real(r8) ssthl0(mkx) ! slope of environmental liquid potential temperature real(r8) ssu0(mkx) ! environmental zonal wind speed vertical gradient real(r8) ssv0(mkx) ! environmental meridional wind speed vertical gradient real(r8) thv0bot(mkx) ! environmental virtual potential temperature, bottom of layer real(r8) thv0top(mkx) ! environmental virtual potential temperature, top of layer real(r8) thvl0bot(mkx) ! environmental liquid virtual potential temperature, bottom of layer real(r8) thvl0top(mkx) ! environmental liquid virtual potential temperature, top of layer real(r8) exn0(mkx) ! exner function at midpoints real(r8) exns0(0:mkx) ! exner function at interfaces ! 3. Variables associated with cumulus convection real(r8) umf(0:mkx) ! updraft mass flux at top of layer real(r8) emf(0:mkx) ! updraft mass flux at top of layer real(r8) qvten(mkx) ! tendency of specific humidity real(r8) qlten(mkx) ! tendency of liquid water mixing ratio real(r8) qiten(mkx) ! tendency of ice mixing ratio real(r8) sten(mkx) ! tendency of static energy real(r8) uten(mkx) ! tendency of zonal wind real(r8) vten(mkx) ! tendency of meridional wind real(r8) qrten(mkx) ! tendency of rain water mixing ratio real(r8) qsten(mkx) ! tendency of snow mixing ratio real(r8) precip ! precipitation rate at the surface [m/s] real(r8) snow ! snow rate at the surface [m/s] real(r8) slflx(0:mkx) ! updraft liquid static energy flux real(r8) qtflx(0:mkx) ! updraft total water flux real(r8) cufrc(mkx) ! shallow cumulus cloud fraction real(r8) qcu(mkx) ! updraft condensate water mixing ratio, 'qlu(k)+qiu(k)' real(r8) qlu(mkx) ! updraft liquid water mixing ratio real(r8) qiu(mkx) ! updraft ice water mixing ratio real(r8) uflx(0:mkx) ! flux of zonal momentum due to convection real(r8) vflx(0:mkx) ! flux of meridional momentum due to convection real(r8) dwten(mkx) ! detrained water tendency from cumulus updraft real(r8) diten(mkx) ! detrained ice tendency from cumulus updraft real(r8) fer(mkx) ! fractional lateral entrainment rate real(r8) fdr(mkx) ! fractional lateral detrainment rate real(r8) uf(mkx) ! zonal wind at end of time step real(r8) vf(mkx) ! meridional wind at end of time step real(r8) qc(mkx) ! [kg/kg/s] reserved 'qlten+qiten' due to detrained 'cloud water + cloud ice' (without rain-snow contribution) real(r8) qc_l(mkx) real(r8) qc_i(mkx) real(r8) rliq ! [m/s] vertical integral of qc real(r8) cnt, cnb real(r8) qtten(mkx) ! tendency of qt real(r8) slten(mkx) ! tendency of sl real(r8) ufrc(0:mkx) ! updraft fractional area !----- Variables used for the calculation of condensation sink associated with compensating subsidence real(r8) uemf(0:mkx) ! net updraft mass flux at the interface of the top of layer ( emf + umf ) real(r8) comsub(mkx) ! compensating subsidence at layer mid-point ( unit of mass flux, umf ) real(r8) qcten_sink(mkx) ! condensate sink ( > 0 -> condensate is generated by subsidence ) real(r8) qlten_sink(mkx) ! liquid condensate sink real(r8) qiten_sink(mkx) ! ice condensate sink real(r8) qs0(mkx) ! saturation specific humidity at layer mid-point !----- Variables describing cumulus updraft real(r8) wu(0:mkx) ! Updraft vertical velocity at top of layer real(r8) thlu(0:mkx) ! Updraft liquid potential temperature at top of layer real(r8) uu(0:mkx) ! Updraft zonal wind speed real(r8) vu(0:mkx) ! Updraft meridional wind speed real(r8) qtu(0:mkx) ! Updraft total water at top of layer real(r8) thvu(0:mkx) ! Updraft virtual potential temperature at top of layer real(r8) rei(mkx) ! Updraft mixing rate of with environment !----- Variables describing conservative scalars of entraining downdrafts at the ! entraining interfaces, i.e., 'kbup <= k < kpen-1'. At the other interfaces, ! belows are simply set to equal to those of updraft for simplicity - but it ! does not influence numerical calculation. real(r8) thlu_emf(0:mkx) ! Downdraft liquid potential temperature at entraining interfaces real(r8) qtu_emf(0:mkx) ! Downdraft total water at entraining interfaces real(r8) uu_emf(0:mkx) ! Downdraft zonal wind at entraining interfaces real(r8) vu_emf(0:mkx) ! Downdraft meridional wind at entraining interfaces !----- Variables associated with evaporations of 'rain' and 'snow' in bulk microphysics real(r8) flxrain(0:mkx) ! Downward rain flux at each interface [ kg/m2/s ] real(r8) flxsnow(0:mkx) ! Downward snow flux at each interface [ kg/m2/s ] real(r8) ntraprd(mkx) ! Net production rate of rain in each layer [ kg/kg/s ] real(r8) ntsnprd(mkx) ! Net production rate of snow in each layer [ kg/kg/s ] real(r8) flxsntm ! Downward snow flux at the top of each layer after melting [ kg/m2/s ] real(r8) snowmlt ! Snow melting tendency [ kg/kg/s ] real(r8) subsat ! Sub-saturation ratio (1-qv/qs) [ no unit ] real(r8) evprain ! Evaporation rate of rain [ kg/kg/s ] real(r8) evpsnow ! Evaporation rate of snow [ kg/kg/s ] real(r8) evplimit_rain ! Limiter of 'evprain' [ kg/kg/s ] real(r8) evplimit_snow ! Limiter of 'evpsnow' [ kg/kg/s ] real(r8) evpint_rain ! Vertically-integrated evaporative flux of rain [ kg/m2/s ] real(r8) evpint_snow ! Vertically-integrated evaporative flux of snow [ kg/m2/s ] real(r8) kevp ! Evaporative efficiency [ complex unit ] !----- Other internal variables integer kk integer id_check logical id_exit logical shallowCu ! Used for testing whether cumulus updraft can overcome the ! buoyancy barrier just above the PBL top. real(r8) thlsrc,qtsrc,usrc,vsrc,uplus,vplus real(r8) plcl,plfc,prel,wrel real(r8) frc_rasn, frc_rasn_remain real(r8) ee2,ud2,wtw,wtwb,wtwh real(r8) cldhgt,dpsum real(r8) xc,xc_2 ! fraction of environmental air in a neutrally buoyant mixture real(r8) cin ! convective inhibition (m2/s2) integer k ! release level (half-sigma level just below lcl) integer i integer leff integer kmin ! layer where 'thvl0' is minimum within the PBL integer klcl ! layer containing LCL of source air integer kinv ! inversion layer with PBL top interface as a lower interface integer krel ! release layer where buoyancy sorting mixing occurs for the first time integer klfc ! LFC layer of cumulus source air integer kbup ! top layer in which cloud buoyancy is positive both at the top and bottom interfaces integer kpen ! highest layer with positive updraft vertical velocity - top layer cumulus can reach integer iteration integer kp1,km1,m real(r8) :: scaleh,nu,tkeavg,thvusrc,qt0bot,qse,cridis,thlxsat,qtxsat,thvxsat,x_cu,x_en,thv_x0,thv_x1 real(r8) :: thj,qvj, qlj,qij,tscaleh,thlu_top,qtu_top,exntop real(r8) :: cinlcl,rbuoy,rdrag,pe,dpe,dpeh,exne,thvebot,thle,qte,ue,ve,thlue,qtue,wue,thluh,qtuh real(r8) :: cbmf,wexp,wcrit,sigmaw,thl0bot,mu,mumin0,mumin1,mumin2,mulcl,mulclstar,winv,wlcl,ufrcinv,ufrclcl real(r8) :: thvj,exql,exqi,PGFc,rle,rkm,rpen,thl0top real(r8) :: qt0top,thl0lcl,qt0lcl,thv0lcl,thv0rel,rho0inv,thvubot,thvutop,autodet real(r8) :: rkfre,thv0j,rho0j,tj,rdqsdt real(r8) :: rbeta,ths0,aquad,bquad,cquad,xc1,xc2,excessu,excess0,xsat,xs,xs1,xs2 real(r8) :: bogbot,bogtop,delbog,expfac,expfach,rhos0j,ppen,rcwp,rlwp,riwp,ufrcbelow,rainflx,ppen2 real(r8) :: dpnb,delbognb,dragenb,expfacnb real(r8) :: snowflx,rmaxfrac,drage,qtdef,qpdef(ncnst),qcubelow,qlubelow,qiubelow,criqc real(r8) :: epsvarw ! vertical velocity variance at inversion base by meso-scale component. real(r8) :: es(1) ! saturation vapor pressure real(r8) :: qs(1) ! saturation spec. humidity real(r8) :: gam(1) ! (L/cp)*dqs/dT integer :: status ! return status of qsat call real(r8) :: thvlmin ! minimum theta_vl in the PBL real(r8) erfarg,qsat_arg,thvlsrc real(r8) dpi ! Full(for internal) or half(for external) interface thickness for tkeavg real(r8) x1,x2,f1,f2,xmid,f_thl,fmid,dx,j ! Used for 'thlsrc' calculation from ' p, qtsrc, thvmin' integer kthvmin,iter_scaleh,iter_xc integer jj real(r8) :: xsrc, xmean, xtop, xbot, xflx(0:mkx) real(r8) :: qt_dt, thl_dt !----- Some diagnostic internal output variables real(r8) ufrcinvbase_out(mix) ! Cumulus updraft fraction at PBL top real(r8) ufrclcl_out(mix) ! Cumulus updraft fraction at LCL ( or PBL top when LCL is below PBL top ) real(r8) winvbase_out(mix) ! Cumulus updraft velocity at PBL top real(r8) wlcl_out(mix) ! Cumulus updraft velocity at LCL ( or PBL top when LCL is below PBL top ) real(r8) plcl_out(mix) ! LCL pressure of source air real(r8) pinv_out(mix) ! PBL top pressure real(r8) plfc_out(mix) ! LFC pressure of source air real(r8) pbup_out(mix) ! Highest level of Positive Buoyancy real(r8) ppen_out(mix) ! Highest Level where Cu W = 0 real(r8) qtsrc_out(mix) ! Sourse air qt real(r8) thlsrc_out(mix) ! Sourse air thl real(r8) thvlsrc_out(mix) ! Sourse air thvl real(r8) emfkbup_out(mix) ! Penetrative mass flux at 'kbup' interface real(r8) cinlclh_out(mix) ! convective inhibition upto LCL (CIN) ([J/kg]) real(r8) tkeavg_out(mix) ! tkeavg over the PBL real(r8) cbmflimit_out(mix) ! Cbmf limiter real(r8) zinv_out(mix) ! PBL top height real(r8) rcwp_out(mix) ! Layer mean Cumulus LWP+IWP [ kg/m2 ] real(r8) rlwp_out(mix) ! Layer mean Cumulus LWP [ kg/m2 ] real(r8) riwp_out(mix) ! Layer mean Cumulus IWP [ kg/m2 ] real(r8) wu_out(mix,0:mkx) ! Cumulus updraft vertical velocity ( defined from the release level, i.e. LCL or PBL top, ! to 'kpen-1' interface. Zero for the other interfaces) real(r8) qtu_out(mix,0:mkx) real(r8) thlu_out(mix,0:mkx) real(r8) thvu_out(mix,0:mkx) real(r8) uu_out(mix,0:mkx) real(r8) vu_out(mix,0:mkx) real(r8) qtu_emf_out(mix,0:mkx) real(r8) thlu_emf_out(mix,0:mkx) real(r8) uu_emf_out(mix,0:mkx) real(r8) vu_emf_out(mix,0:mkx) real(r8) uemf_out(mix,0:mkx) ! Net upward cumulus mass flux including penetrative entrainment flux (umf+emf) real(r8) wu_s(0:mkx) ! Cumulus updraft vertical velocity real(r8) qtu_s(0:mkx) real(r8) thlu_s(0:mkx) real(r8) thvu_s(0:mkx) real(r8) uu_s(0:mkx) real(r8) vu_s(0:mkx) real(r8) qtu_emf_s(0:mkx) real(r8) thlu_emf_s(0:mkx) real(r8) uu_emf_s(0:mkx) real(r8) vu_emf_s(0:mkx) real(r8) uemf_s(0:mkx) real(r8) dwten_out(mix,mkx) real(r8) diten_out(mix,mkx) real(r8) flxrain_out(mix,0:mkx) real(r8) flxsnow_out(mix,0:mkx) real(r8) ntraprd_out(mix,mkx) real(r8) ntsnprd_out(mix,mkx) real(r8) dwten_s(mkx) real(r8) diten_s(mkx) real(r8) flxrain_s(0:mkx) real(r8) flxsnow_s(0:mkx) real(r8) ntraprd_s(mkx) real(r8) ntsnprd_s(mkx) real(r8) excessu_arr_out(mix,mkx) real(r8) excessu_arr(mkx) real(r8) excessu_arr_s(mkx) real(r8) excess0_arr_out(mix,mkx) real(r8) excess0_arr(mkx) real(r8) excess0_arr_s(mkx) real(r8) xc_arr_out(mix,mkx) real(r8) xc_arr(mkx) real(r8) xc_arr_s(mkx) real(r8) aquad_arr_out(mix,mkx) real(r8) aquad_arr(mkx) real(r8) aquad_arr_s(mkx) real(r8) bquad_arr_out(mix,mkx) real(r8) bquad_arr(mkx) real(r8) bquad_arr_s(mkx) real(r8) cquad_arr_out(mix,mkx) real(r8) cquad_arr(mkx) real(r8) cquad_arr_s(mkx) real(r8) bogbot_arr_out(mix,mkx) real(r8) bogbot_arr(mkx) real(r8) bogbot_arr_s(mkx) real(r8) bogtop_arr_out(mix,mkx) real(r8) bogtop_arr(mkx) real(r8) bogtop_arr_s(mkx) real(r8) exit_UWCu(mix) real(r8) exit_conden(mix) real(r8) exit_klclmkx(mix) real(r8) exit_klfcmkx(mix) real(r8) exit_ufrc(mix) real(r8) exit_wtw(mix) real(r8) exit_drycore(mix) real(r8) exit_wu(mix) real(r8) exit_cufilter(mix) real(r8) exit_kinv1(mix) real(r8) exit_rei(mix) real(r8) limit_shcu(mix) real(r8) limit_negcon(mix) real(r8) limit_ufrc(mix) real(r8) limit_ppen(mix) real(r8) limit_emf(mix) real(r8) limit_cinlcl(mix) real(r8) limit_cin(mix) real(r8) limit_cbmf(mix) real(r8) limit_rei(mix) real(r8) ind_delcin(mix) real(r8) :: ufrcinvbase_s, ufrclcl_s, winvbase_s, wlcl_s, plcl_s, pinv_s, plfc_s, & qtsrc_s, thlsrc_s, thvlsrc_s, emfkbup_s, cinlcl_s, pbup_s, ppen_s, cbmflimit_s, & tkeavg_s, zinv_s, rcwp_s, rlwp_s, riwp_s real(r8) :: ufrcinvbase, winvbase, pinv, zinv, emfkbup, cbmflimit, rho0rel !----- Variables for implicit CIN computation real(r8), dimension(mkx) :: qv0_s , ql0_s , qi0_s , s0_s , u0_s , & v0_s , t0_s , qt0_s , thl0_s , thvl0_s , qvten_s , & qlten_s, qiten_s , qrten_s , qsten_s , sten_s , & uten_s , vten_s , cufrc_s , qcu_s , qlu_s , qiu_s , & fer_s , fdr_s , qc_s , qtten_s , slten_s real(r8), dimension(0:mkx) :: umf_s , slflx_s , qtflx_s , ufrc_s , uflx_s , vflx_s real(r8) :: cush_s , precip_s, snow_s , cin_s , rliq_s, cbmf_s, cnt_s, cnb_s real(r8) :: cin_i,cin_f,del_CIN,ke,alpha,thlj real(r8) :: cinlcl_i,cinlcl_f,del_cinlcl integer :: iter !----- Variables for temporary storages real(r8), dimension(mkx) :: qv0_o, ql0_o, qi0_o, t0_o, s0_o, u0_o, v0_o real(r8), dimension(mkx) :: qt0_o , thl0_o , thvl0_o , & qvten_o , qlten_o , qiten_o , qrten_o , qsten_o , & sten_o , uten_o , vten_o , qcu_o , qlu_o , & qiu_o , cufrc_o , & thv0bot_o, thv0top_o, thvl0bot_o, thvl0top_o, & ssthl0_o , ssqt0_o , ssu0_o , ssv0_o , qc_o , & qtten_o , slten_o real(r8), dimension(0:mkx) :: umf_o , slflx_o , qtflx_o , ufrc_o real(r8), dimension(mix) :: cush_o , precip_o , snow_o , rliq_o, cbmf_o, cnt_o, cnb_o real(r8), dimension(0:mkx) :: uflx_o , vflx_o real(r8) :: tkeavg_o , thvlmin_o, qtsrc_o , thvlsrc_o, thlsrc_o , & usrc_o , vsrc_o , plcl_o , plfc_o , & thv0lcl_o, cinlcl_o integer :: kmin_o , kinv_o , klcl_o , klfc_o ! ------------------ ! ! ! ! Define Parameters ! ! ! ! ------------------ ! ! --------------------------------------------------------------------- ! ! Choose new (correct saturated+unsaturated) or old (wrong unsaturated) ! ! buoyancy sorting scheme. ! ! --------------------------------------------------------------------- ! logical , parameter :: use_newbuosort = .true. ! --------------------------------------------------------------------- ! ! Set 'fer(kpen) = zero' (.true.) or use explicitly calculated non-zero ! ! fer(kpen) (.false.) ! ! --------------------------------------------------------------------- ! logical , parameter :: set_zeroferkpen = .false. ! ------------------------ ! ! Iterative xc calculation ! ! ------------------------ ! integer , parameter :: niter_xc = 3 ! ----------------------------------------------------------- ! ! Choice of 'CIN = cin' (.true.) or 'CIN = cinlcl' (.false.). ! ! ----------------------------------------------------------- ! logical , parameter :: use_CINcin = .true. ! --------------------------------------------------------------- ! ! Choice of 'explicit' ( 1 ) or 'implicit' ( 2 ) CIN. ! ! ! ! When choose 'CIN = cinlcl' above, it is recommended not to use ! ! implicit CIN, i.e., do 'NOT' choose simultaneously : ! ! [ 'use_CINcin=.false. & 'iter_cin=2' ] ! ! since 'cinlcl' will be always set to zero whenever LCL is below ! ! the PBL top interface in the current code. So, averaging cinlcl ! ! of two iter_cin steps is likely not so good. Except that, all ! ! the other combinations of 'use_CINcin' & 'iter_cin' are OK. ! ! ! ! Feb 2007, Bundy: Note that use_CINcin = .false. will try to use ! ! a variable (del_cinlcl) that is not currently set ! ! ! ! --------------------------------------------------------------- ! integer , parameter :: iter_cin = 2 ! ---------------------------------------------------------------- ! ! Choice of 'self-detrainment' by negative buoyancy in calculating ! ! cumulus updraft mass flux at the top interface in each layer. ! ! ---------------------------------------------------------------- ! logical , parameter :: use_self_detrain = .false. ! --------------------------------------------------------- ! ! Cumulus momentum flux : turn-on (.true.) or off (.false.) ! ! --------------------------------------------------------- ! logical , parameter :: use_momenflx = .true. ! ----------------------- ! ! For lateral entrainment ! ! ----------------------- ! parameter (rle = 0.1_r8) ! For critical stopping distance for lateral entrainment [no unit] parameter (rkm = 16.0_r8) ! Determine the amount of air that is involved in buoyancy-sorting [no unit] parameter (rpen = 10.0_r8) ! For penetrative entrainment efficiency parameter (rkfre = 1.0_r8) ! Vertical velocity variance as fraction of tke. parameter (rmaxfrac = 0.05_r8) ! Maximum allowable updraft fraction parameter (mumin1 = 1.163_r8) ! Normalized CIN ('mu') corresponding to 'rmaxfrac' at the PBL top ! obtaind by inverting 'rmaxfrac = 0.5*erfc(mumin1)'. ! [ rmaxfrac:mumin1 ] = [ 0.05:1.163, 0.1:0.906, 0.15:0.733, 0.2:0.595, 0.25:0.477 ] parameter (rbuoy = 1.0_r8) ! For nonhydrostatic pressure effects on updraft [no unit] parameter (rdrag = 1.0_r8) ! Drag coefficient [no unit] parameter (epsvarw = 5.e-4_r8) ! Variance of w at PBL top by meso-scale component [m2/s2] parameter (PGFc = 0.7_r8) ! This is used for calculating vertical variations cumulus ! 'u' & 'v' by horizontal PGF during upward motion [no unit] ! ---------------------------------------- ! ! Bulk microphysics controlling parameters ! ! --------------------------------------------------------------------------- ! ! criqc : Maximum condensate that can be hold by cumulus updraft [kg/kg] ! ! frc_rasn : Fraction of precipitable condensate in the expelled cloud water ! ! from cumulus updraft. The remaining fraction ('1-frc_rasn') is ! ! 'suspended condensate'. ! ! 0 : all expelled condensate is 'suspended condensate' ! ! 1 : all expelled condensate is 'precipitable condensate' ! ! kevp : Evaporative efficiency ! ! noevap_krelkpen : No evaporation from 'krel' to 'kpen' layers ! ! --------------------------------------------------------------------------- ! parameter ( criqc = 1.e-3_r8 ) parameter ( frc_rasn = 1.0_r8 ) parameter ( kevp = 2.e-6_r8 ) logical , parameter :: noevap_krelkpen = .false. !------------------------! ! ! ! Start Main Calculation ! ! ! !------------------------! ! ------------------------------------------------------- ! ! Initialize output variables defined for all grid points ! ! ------------------------------------------------------- ! umf_out(:iend,0:mkx) = 0.0_r8 slflx_out(:iend,0:mkx) = 0.0_r8 qtflx_out(:iend,0:mkx) = 0.0_r8 qvten_out(:iend,:mkx) = 0.0_r8 qlten_out(:iend,:mkx) = 0.0_r8 qiten_out(:iend,:mkx) = 0.0_r8 sten_out(:iend,:mkx) = 0.0_r8 uten_out(:iend,:mkx) = 0.0_r8 vten_out(:iend,:mkx) = 0.0_r8 qrten_out(:iend,:mkx) = 0.0_r8 qsten_out(:iend,:mkx) = 0.0_r8 precip_out(:iend) = 0.0_r8 snow_out(:iend) = 0.0_r8 cufrc_out(:iend,:mkx) = 0.0_r8 qcu_out(:iend,:mkx) = 0.0_r8 qlu_out(:iend,:mkx) = 0.0_r8 qiu_out(:iend,:mkx) = 0.0_r8 fer_out(:iend,:mkx) = 0.0_r8 fdr_out(:iend,:mkx) = 0.0_r8 cinh_out(:iend) = -1.0_r8 cinlclh_out(:iend) = -1.0_r8 cbmf_out(:iend) = 0.0_r8 qc_out(:iend,:mkx) = 0.0_r8 rliq_out(:iend) = 0.0_r8 cnt_out(:iend) = real(mkx, r8) cnb_out(:iend) = 0.0_r8 qtten_out(:iend,:mkx) = 0.0_r8 slten_out(:iend,:mkx) = 0.0_r8 ufrc_out(:iend,0:mkx) = 0.0_r8 uflx_out(:iend,0:mkx) = 0.0_r8 vflx_out(:iend,0:mkx) = 0.0_r8 ufrcinvbase_out(:iend) = 0.0_r8 ufrclcl_out(:iend) = 0.0_r8 winvbase_out(:iend) = 0.0_r8 wlcl_out(:iend) = 0.0_r8 plcl_out(:iend) = 0.0_r8 pinv_out(:iend) = 0.0_r8 plfc_out(:iend) = 0.0_r8 pbup_out(:iend) = 0.0_r8 ppen_out(:iend) = 0.0_r8 qtsrc_out(:iend) = 0.0_r8 thlsrc_out(:iend) = 0.0_r8 thvlsrc_out(:iend) = 0.0_r8 emfkbup_out(:iend) = 0.0_r8 cbmflimit_out(:iend) = 0.0_r8 tkeavg_out(:iend) = 0.0_r8 zinv_out(:iend) = 0.0_r8 rcwp_out(:iend) = 0.0_r8 rlwp_out(:iend) = 0.0_r8 riwp_out(:iend) = 0.0_r8 wu_out(:iend,0:mkx) = 0.0_r8 qtu_out(:iend,0:mkx) = 0.0_r8 thlu_out(:iend,0:mkx) = 0.0_r8 thvu_out(:iend,0:mkx) = 0.0_r8 uu_out(:iend,0:mkx) = 0.0_r8 vu_out(:iend,0:mkx) = 0.0_r8 qtu_emf_out(:iend,0:mkx) = 0.0_r8 thlu_emf_out(:iend,0:mkx) = 0.0_r8 uu_emf_out(:iend,0:mkx) = 0.0_r8 vu_emf_out(:iend,0:mkx) = 0.0_r8 uemf_out(:iend,0:mkx) = 0.0_r8 dwten_out(:iend,:mkx) = 0.0_r8 diten_out(:iend,:mkx) = 0.0_r8 flxrain_out(:iend,0:mkx) = 0.0_r8 flxsnow_out(:iend,0:mkx) = 0.0_r8 ntraprd_out(:iend,mkx) = 0.0_r8 ntsnprd_out(:iend,mkx) = 0.0_r8 excessu_arr_out(:iend,:mkx) = 0.0_r8 excess0_arr_out(:iend,:mkx) = 0.0_r8 xc_arr_out(:iend,:mkx) = 0.0_r8 aquad_arr_out(:iend,:mkx) = 0.0_r8 bquad_arr_out(:iend,:mkx) = 0.0_r8 cquad_arr_out(:iend,:mkx) = 0.0_r8 bogbot_arr_out(:iend,:mkx) = 0.0_r8 bogtop_arr_out(:iend,:mkx) = 0.0_r8 exit_UWCu(:iend) = 0.0_r8 exit_conden(:iend) = 0.0_r8 exit_klclmkx(:iend) = 0.0_r8 exit_klfcmkx(:iend) = 0.0_r8 exit_ufrc(:iend) = 0.0_r8 exit_wtw(:iend) = 0.0_r8 exit_drycore(:iend) = 0.0_r8 exit_wu(:iend) = 0.0_r8 exit_cufilter(:iend) = 0.0_r8 exit_kinv1(:iend) = 0.0_r8 exit_rei(:iend) = 0.0_r8 limit_shcu(:iend) = 0.0_r8 limit_negcon(:iend) = 0.0_r8 limit_ufrc(:iend) = 0.0_r8 limit_ppen(:iend) = 0.0_r8 limit_emf(:iend) = 0.0_r8 limit_cinlcl(:iend) = 0.0_r8 limit_cin(:iend) = 0.0_r8 limit_cbmf(:iend) = 0.0_r8 limit_rei(:iend) = 0.0_r8 ind_delcin(:iend) = 0.0_r8 !---------------------------------------------------------! ! ! ! Start the big i loop where i is a horozontal grid index ! ! ! !---------------------------------------------------------! do i = 1, iend ! start of big i loop id_exit = .false. ! --------------------------------------------- ! ! Define new input variables at each grid point ! ! --------------------------------------------- ! ps0(0:mkx) = ps0_in(i,0:mkx) zs0(0:mkx) = zs0_in(i,0:mkx) p0(:mkx) = p0_in(i,:mkx) z0(:mkx) = z0_in(i,:mkx) dp0(:mkx) = dp0_in(i,:mkx) u0(:mkx) = u0_in(i,:mkx) v0(:mkx) = v0_in(i,:mkx) qv0(:mkx) = qv0_in(i,:mkx) ql0(:mkx) = ql0_in(i,:mkx) qi0(:mkx) = qi0_in(i,:mkx) t0(:mkx) = t0_in(i,:mkx) s0(:mkx) = s0_in(i,:mkx) tke(0:mkx) = tke_in(i,0:mkx) cldfrct(:mkx) = cldfrct_in(i,:mkx) concldfrct(:mkx) = concldfrct_in(i,:mkx) pblh = pblh_in(i) cush = cush_inout(i) ! --------------------------------------------------------- ! ! Compute other basic thermodynamic variables directly from ! ! the input variables at each grid point ! ! --------------------------------------------------------- ! !----- 1. Compute internal environmental variables exn0(:mkx) = (p0(:mkx)/p00)**rovcp exns0(0:mkx) = (ps0(0:mkx)/p00)**rovcp qt0(:mkx) = (qv0(:mkx) + ql0(:mkx) + qi0(:mkx)) thl0(:mkx) = (t0(:mkx) - xlv*ql0(:mkx)/cp - xls*qi0(:mkx)/cp)/exn0(:mkx) thvl0(:mkx) = (1._r8 + zvir*qt0(:mkx))*thl0(:mkx) !----- 2. Compute slopes of environmental variables ssthl0 = slope(mkx,thl0,p0) ! Dimension of ssthl0(:mkx) is implicit ssqt0 = slope(mkx,qt0 ,p0) ssu0 = slope(mkx,u0 ,p0) ssv0 = slope(mkx,v0 ,p0) !----- 3. Compute "thv0" and "thvl0" at top/bottom interfaces do k = 1, mkx thl0bot = thl0(k) + ssthl0(k)*(ps0(k-1) - p0(k)) qt0bot = qt0(k) + ssqt0(k) *(ps0(k-1) - p0(k)) call conden(ps0(k-1),thl0bot,qt0bot,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thv0bot(k) = thj*(1._r8 + zvir*qvj - qlj - qij) thvl0bot(k) = thl0bot*(1._r8 + zvir*qt0bot) thl0top = thl0(k) + ssthl0(k)*(ps0(k) - p0(k)) qt0top = qt0(k) + ssqt0(k) *(ps0(k) - p0(k)) call conden(ps0(k),thl0top,qt0top,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thv0top(k) = thj*(1._r8 + zvir*qvj - qlj - qij) thvl0top(k) = thl0top*(1._r8 + zvir*qt0top) end do !----- 4. Compute "qs0(k)" at layer mid-point for condensate sink calculation do k = 1, mkx call conden(p0(k),thl0(k),qt0(k),thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if qs0(k) = qse end do ! -------------------------------------------------------------------- ! ! Save input and related thermodynamic variables ( not associated with ! ! cumulus convection ) for use at "iter_cin=2" when "del_CIN >= 0" ! ! -------------------------------------------------------------------- ! qv0_o(:mkx) = qv0(:mkx) ql0_o(:mkx) = ql0(:mkx) qi0_o(:mkx) = qi0(:mkx) t0_o(:mkx) = t0(:mkx) s0_o(:mkx) = s0(:mkx) u0_o(:mkx) = u0(:mkx) v0_o(:mkx) = v0(:mkx) qt0_o(:mkx) = qt0(:mkx) thl0_o(:mkx) = thl0(:mkx) thvl0_o(:mkx) = thvl0(:mkx) ssthl0_o(:mkx) = ssthl0(:mkx) ssqt0_o(:mkx) = ssqt0(:mkx) thv0bot_o(:mkx) = thv0bot(:mkx) thv0top_o(:mkx) = thv0top(:mkx) thvl0bot_o(:mkx) = thvl0bot(:mkx) thvl0top_o(:mkx) = thvl0top(:mkx) ssu0_o(:mkx) = ssu0(:mkx) ssv0_o(:mkx) = ssv0(:mkx) ! ------------------------------------------------------------------------ ! ! Initialize output variables before cumulus convection at each grid point ! ! ------------------------------------------------------------------------ ! umf(0:mkx) = 0.0_r8 emf(0:mkx) = 0.0_r8 slflx(0:mkx) = 0.0_r8 qtflx(0:mkx) = 0.0_r8 uflx(0:mkx) = 0.0_r8 vflx(0:mkx) = 0.0_r8 qvten(:mkx) = 0.0_r8 qlten(:mkx) = 0.0_r8 qiten(:mkx) = 0.0_r8 sten(:mkx) = 0.0_r8 uten(:mkx) = 0.0_r8 vten(:mkx) = 0.0_r8 qrten(:mkx) = 0.0_r8 qsten(:mkx) = 0.0_r8 dwten(:mkx) = 0.0_r8 diten(:mkx) = 0.0_r8 precip = 0.0_r8 snow = 0.0_r8 cufrc(:mkx) = 0.0_r8 qcu(:mkx) = 0.0_r8 qlu(:mkx) = 0.0_r8 qiu(:mkx) = 0.0_r8 fer(:mkx) = 0.0_r8 fdr(:mkx) = 0.0_r8 cin = 0.0_r8 cbmf = 0.0_r8 qc(:mkx) = 0.0_r8 qc_l(:mkx) = 0.0_r8 qc_i(:mkx) = 0.0_r8 rliq = 0.0_r8 cnt = real(mkx, r8) cnb = 0.0_r8 qtten(:mkx) = 0.0_r8 slten(:mkx) = 0.0_r8 ufrc(0:mkx) = 0.0_r8 thlu(0:mkx) = 0.0_r8 qtu(0:mkx) = 0.0_r8 uu(0:mkx) = 0.0_r8 vu(0:mkx) = 0.0_r8 wu(0:mkx) = 0.0_r8 thvu(0:mkx) = 0.0_r8 thlu_emf(0:mkx) = 0.0_r8 qtu_emf(0:mkx) = 0.0_r8 uu_emf(0:mkx) = 0.0_r8 vu_emf(0:mkx) = 0.0_r8 ufrcinvbase = 0.0_r8 ufrclcl = 0.0_r8 winvbase = 0.0_r8 wlcl = 0.0_r8 emfkbup = 0.0_r8 cbmflimit = 0.0_r8 excessu_arr(:mkx) = 0.0_r8 excess0_arr(:mkx) = 0.0_r8 xc_arr(:mkx) = 0.0_r8 aquad_arr(:mkx) = 0.0_r8 bquad_arr(:mkx) = 0.0_r8 cquad_arr(:mkx) = 0.0_r8 bogbot_arr(:mkx) = 0.0_r8 bogtop_arr(:mkx) = 0.0_r8 uemf(0:mkx) = 0.0_r8 comsub(:mkx) = 0.0_r8 qcten_sink(:mkx) = 0.0_r8 qlten_sink(:mkx) = 0.0_r8 qiten_sink(:mkx) = 0.0_r8 !-----------------------------------------------! ! Below 'iter' loop is for implicit CIN closure ! !-----------------------------------------------! ! ----------------------------------------------------------------------------- ! ! It is important to note that this iterative cin loop is located at the outest ! ! shell of the code. Thus, source air properties can also be changed during the ! ! iterative cin calculation, because cumulus convection induces non-zero fluxes ! ! even at interfaces below PBL top height through 'fluxbelowinv' subroutine. ! ! ----------------------------------------------------------------------------- ! do iter = 1, iter_cin ! ---------------------------------------------------------------------- ! ! Cumulus scale height ! ! In contrast to the premitive code, cumulus scale height is iteratively ! ! calculated at each time step, and at each iterative cin step. ! ! It is not clear whether I should locate below two lines within or out ! ! of the iterative cin loop. ! ! ---------------------------------------------------------------------- ! tscaleh = cush cush = -1._r8 ! ----------------------------------------------------------------------- ! ! Find PBL top height interface index, 'kinv-1' where 'kinv' is the layer ! ! index with PBLH in it. When PBLH is exactly at interface, 'kinv' is the ! ! layer index having PBLH as a lower interface. ! ! In the previous code, I set the lower limit of 'kinv' by 2 in order to ! ! be consistent with the other parts of the code. However in the modified ! ! code, I allowed 'kinv' to be 1 & if 'kinv = 1', I just exit the program ! ! without performing cumulus convection. This new approach seems to be ! ! more reasonable: if PBL height is within 'kinv=1' layer, surface is STL ! ! interface (bflxs <= 0) and interface just above the surface should be ! ! either non-turbulent (Ri>0.19) or stably turbulent (0<=Ri<0.19 but this ! ! interface is identified as a base external interface of upperlying CL. ! ! Thus, when 'kinv=1', PBL scheme guarantees 'bflxs <= 0'. For this case ! ! it is reasonable to assume that cumulus convection does not happen. ! ! When these is SBCL, PBL height from the PBL scheme is likely to be very ! ! close at 'kinv-1' interface, but not exactly, since 'zi' information is ! ! changed between two model time steps. In order to ensure correct identi ! ! fication of 'kinv' for general case including SBCL, I imposed an offset ! ! of 5 [m] in the below 'kinv' finding block. ! ! ----------------------------------------------------------------------- ! do k = mkx - 1, 1, -1 if((pblh + 5._r8 - zs0(k))*(pblh + 5._r8 - zs0(k+1)) .lt. 0._r8) then kinv = k + 1 go to 15 endif end do kinv = 1 15 continue if(kinv.le.1) then ! write(iulog,*) 'PBL height is within the lowest model layer' exit_kinv1(i) = 1._r8 id_exit = .true. go to 333 endif ! From here, it must be 'kinv >= 2' from now on. ! -------------------------------------------------------------------------- ! ! Find PBL averaged tke ('tkeavg') and minimum 'thvl' ('thvlmin') in the PBL ! ! In the current code, 'tkeavg' is obtained by averaging all interfacial TKE ! ! within the PBL. However, in order to be conceptually consistent with PBL ! ! scheme, 'tkeavg' should be calculated by considering surface buoyancy flux.! ! If surface buoyancy flux is positive ( bflxs >0 ), surface interfacial TKE ! ! should be included in calculating 'tkeavg', while if bflxs <= 0, surface ! ! interfacial TKE should not be included in calculating 'tkeavg'. I should ! ! modify the code when 'bflxs' is available as an input of cumulus scheme. ! ! 'thvlmin' is a minimum 'thvl' within PBL obtained by comparing top & base ! ! interface values of 'thvl' in each layers within the PBL. ! ! -------------------------------------------------------------------------- ! dpsum = 0._r8 tkeavg = 0._r8 thvlmin = 1000._r8 kmin = 1 do k = 0, kinv - 1 ! Here, 'k' is an interfacial layer index. if(k .eq. 0) then dpi = ps0(0) - p0(1) elseif(k .eq. (kinv-1)) then dpi = p0(kinv-1) - ps0(kinv-1) else dpi = p0(k) - p0(k+1) endif dpsum = dpsum + dpi tkeavg = tkeavg + dpi*tke(k) if( k.ne.0 ) thvlmin = min(thvlmin,min(thvl0bot(k),thvl0top(k))) end do tkeavg = tkeavg/dpsum ! ------------------------------------------------------------------ ! ! Find characteristics of cumulus source air: qtsrc,thlsrc,usrc,vsrc ! ! Note that 'thlsrc' was con-cocked using 'thvlsrc' and 'qtsrc'. ! ! 'qtsrc' is defined as the lowest layer mid-point value; 'thlsrc' ! ! is from 'qtsrc' and 'thvlmin=thvlsrc'; 'usrc' & 'vsrc' are defined ! ! as the values just below the PBL top interface. ! ! ------------------------------------------------------------------ ! qtsrc = qt0(1) thvlsrc = thvlmin thlsrc = thvlsrc / ( 1._r8 + zvir * qtsrc ) usrc = u0(kinv-1) + ssu0(kinv-1) * ( ps0(kinv-1) - p0(kinv-1) ) vsrc = v0(kinv-1) + ssv0(kinv-1) * ( ps0(kinv-1) - p0(kinv-1) ) ! ------------------------------------------------------------------ ! ! Find LCL of the source air and a layer index containing LCL (klcl) ! ! When the LCL is exactly at the interface, 'klcl' is a layer index ! ! having 'plcl' as the lower interface similar to the 'kinv' case. ! ! In the previous code, I assumed that if LCL is located within the ! ! lowest model layer ( 1 ) or the top model layer ( mkx ), then no ! ! convective adjustment is performed and just exited. However, in ! ! the revised code, I relaxed the first constraint and even though ! ! LCL is at the lowest model layer, I allowed cumulus convection to ! ! be initiated. For this case, cumulus convection should be started ! ! from the PBL top height, as shown in the following code. ! ! When source air is already saturated even at the surface, klcl is ! ! set to 1. ! ! ------------------------------------------------------------------ ! plcl = qsinvert(qtsrc,thlsrc,ps0(0),qsat) do k = 0, mkx if( ps0(k) .lt. plcl ) then klcl = k go to 25 endif end do klcl = mkx 25 continue klcl = max(1,klcl) if(plcl.lt.30000.) then ! if(klcl.eq.mkx) then ! write(iulog,*) 'Too dry source air' exit_klclmkx(i) = 1._r8 id_exit = .true. go to 333 endif ! ------------------------------------------------------------- ! ! Calculate environmental virtual potential temperature at LCL, ! !'thv0lcl' which is solely used in the 'cin' calculation. Note ! ! that 'thv0lcl' is calculated first by calculating 'thl0lcl' ! ! and 'qt0lcl' at the LCL, and performing 'conden' afterward, ! ! in fully consistent with the other parts of the code. ! ! ------------------------------------------------------------- ! thl0lcl = thl0(klcl) + ssthl0(klcl) * ( plcl - p0(klcl) ) qt0lcl = qt0(klcl) + ssqt0(klcl) * ( plcl - p0(klcl) ) call conden(plcl,thl0lcl,qt0lcl,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thv0lcl = thj * (1._r8 + zvir * qvj - qlj - qij ) ! ------------------------------------------------------------------------ ! ! Compute Convective Inhibition, 'cin' & 'cinlcl' [J/kg]=[m2/s2] TKE unit. ! ! ! ! 'cin' (cinlcl) is computed from the PBL top interface to LFC (LCL) using ! ! piecewisely reconstructed environmental profiles, assuming environmental ! ! buoyancy profile within each layer ( or from LCL to upper interface in ! ! each layer ) is simply a linear profile. For the purpose of cin (cinlcl) ! ! calculation, we simply assume that lateral entrainment does not occur in ! ! updrafting cumulus plume, i.e., cumulus source air property is conserved.! ! Below explains some rules used in the calculations of cin (cinlcl). In ! ! general, both 'cin' and 'cinlcl' are calculated from a PBL top interface ! ! to LCL and LFC, respectively : ! ! 1. If LCL is lower than the PBL height, cinlcl = 0 and cin is calculated ! ! from PBL height to LFC. ! ! 2. If LCL is higher than PBL height, 'cinlcl' is calculated by summing ! ! both positive and negative cloud buoyancy up to LCL using 'single_cin'! ! From the LCL to LFC, however, only negative cloud buoyancy is counted ! ! to calculate final 'cin' upto LFC. ! ! 3. If either 'cin' or 'cinlcl' is negative, they are set to be zero. ! ! In the below code, 'klfc' is the layer index containing 'LFC' similar to ! ! 'kinv' and 'klcl'. ! ! ------------------------------------------------------------------------ ! cin = 0._r8 cinlcl = 0._r8 plfc = 0._r8 klfc = mkx ! ------------------------------------------------------------------------- ! ! Case 1. LCL height is higher than PBL interface ( 'pLCL <= ps0(kinv-1)' ) ! ! ------------------------------------------------------------------------- ! if( klcl .ge. kinv ) then do k = kinv, mkx - 1 if( k .lt. klcl ) then thvubot = thvlsrc thvutop = thvlsrc cin = cin + single_cin(ps0(k-1),thv0bot(k),ps0(k),thv0top(k),thvubot,thvutop) elseif( k .eq. klcl ) then !----- Bottom to LCL thvubot = thvlsrc thvutop = thvlsrc cin = cin + single_cin(ps0(k-1),thv0bot(k),plcl,thv0lcl,thvubot,thvutop) if(cin.lt.0) limit_cinlcl(i) = 1._r8 cinlcl = max(cin,0._r8) cin = cinlcl !----- LCL to Top thvubot = thvlsrc call conden(ps0(k),thlsrc,qtsrc,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvutop = thj*(1._r8 + zvir*qvj - qlj - qij ) call getbuoy(plcl,thv0lcl,ps0(k),thv0top(k),thvubot,thvutop,plfc,cin) if(plfc .gt. 0._r8) then klfc = k go to 35 end if else thvubot = thvutop call conden(ps0(k),thlsrc,qtsrc,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvutop = thj*(1._r8 + zvir*qvj - qlj - qij ) call getbuoy(ps0(k-1),thv0bot(k),ps0(k),thv0top(k),thvubot,thvutop,plfc,cin) if(plfc .gt. 0._r8) then klfc = k go to 35 end if endif end do ! ----------------------------------------------------------------------- ! ! Case 2. LCL height is lower than PBL interface ( 'pLCL > ps0(kinv-1)' ) ! ! ----------------------------------------------------------------------- ! else cinlcl = 0._r8 do k = kinv, mkx - 1 call conden(ps0(k-1),thlsrc,qtsrc,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvubot = thj*(1._r8 + zvir*qvj - qlj - qij ) call conden(ps0(k),thlsrc,qtsrc,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvutop = thj*(1._r8 + zvir*qvj - qlj - qij ) call getbuoy(ps0(k-1),thv0bot(k),ps0(k),thv0top(k),thvubot,thvutop,plfc,cin) if(plfc .gt. 0._r8) then klfc = k go to 35 end if end do endif ! End of CIN case selection 35 continue if(cin.lt.0) limit_cin(i) = 1._r8 cin = max(0._r8,cin) if( klfc .ge. mkx ) then klfc = mkx ! write(iulog,*) 'klfc >= mkx' exit_klfcmkx(i) = 1._r8 id_exit = .true. go to 333 endif ! ---------------------------------------------------------------------- ! ! In order to calculate implicit 'cin' (or 'cinlcl'), save the initially ! ! calculated 'cin' and 'cinlcl', and other related variables. These will ! ! be restored after calculating implicit CIN. ! ! ---------------------------------------------------------------------- ! if(iter .eq. 1) then cin_i = cin cinlcl_i = cinlcl ke = rbuoy / ( rkfre * tkeavg + epsvarw ) kmin_o = kmin kinv_o = kinv klcl_o = klcl klfc_o = klfc plcl_o = plcl plfc_o = plfc tkeavg_o = tkeavg thvlmin_o = thvlmin qtsrc_o = qtsrc thvlsrc_o = thvlsrc thlsrc_o = thlsrc usrc_o = usrc vsrc_o = vsrc thv0lcl_o = thv0lcl endif ! -------------------------------------------------------------------------- ! ! Calculate implicit 'cin' by averaging initial and final cins. Note that ! ! implicit CIN is adopted only when cumulus convection stabilized the system,! ! i.e., only when 'del_CIN >0'. If 'del_CIN<=0', just use explicit CIN. Note ! ! also that since 'cinlcl' is set to zero whenever LCL is below the PBL top, ! ! (see above CIN calculation part), the use of 'implicit CIN=cinlcl' is not ! ! good. Thus, when using implicit CIN, always try to only use 'implicit CIN= ! ! cin', not 'implicit CIN=cinlcl'. However, both 'CIN=cin' and 'CIN=cinlcl' ! ! are good when using explicit CIN. ! ! -------------------------------------------------------------------------- ! if(iter .ne. 1) then cin_f = cin cinlcl_f = cinlcl if(use_CINcin) then del_CIN = cin_f - cin_i else del_CIN = cinlcl_f - cinlcl_i endif if(del_CIN .gt. 0._r8) then ! -------------------------------------------------------------- ! ! Calculate implicit 'cin' and 'cinlcl'. Note that when we chose ! ! to use 'implicit CIN = cin', choose 'cinlcl = cinlcl_i' below: ! ! because iterative CIN only aims to obtain implicit CIN, once ! ! we obtained 'implicit CIN=cin', it is good to use the original ! ! profiles information for all the other variables after that. ! ! Note 'cinlcl' will be explicitly used in calculating 'wlcl' & ! ! 'ufrclcl' after calculating 'winv' & 'ufrcinv' at the PBL top ! ! interface later, after calculating 'cbmf'. ! ! -------------------------------------------------------------- ! alpha = compute_alpha( del_CIN, ke ) cin = cin_i + alpha * del_CIN if(use_CINcin) then cinlcl = cinlcl_i else !bundy: warning, del_cinlcl needs to be set if use_CINcin = .false. cinlcl = cinlcl_i + alpha * del_cinlcl endif ! ----------------------------------------------------------------- ! ! Restore the original values from the previous 'iter_cin' step (1) ! ! to compute correct tendencies for (n+1) time step by implicit CIN ! ! ----------------------------------------------------------------- ! kmin = kmin_o kinv = kinv_o klcl = klcl_o klfc = klfc_o plcl = plcl_o plfc = plfc_o tkeavg = tkeavg_o thvlmin = thvlmin_o qtsrc = qtsrc_o thvlsrc = thvlsrc_o thlsrc = thlsrc_o usrc = usrc_o vsrc = vsrc_o thv0lcl = thv0lcl_o qv0(:mkx) = qv0_o(:mkx) ql0(:mkx) = ql0_o(:mkx) qi0(:mkx) = qi0_o(:mkx) t0(:mkx) = t0_o(:mkx) s0(:mkx) = s0_o(:mkx) u0(:mkx) = u0_o(:mkx) v0(:mkx) = v0_o(:mkx) qt0(:mkx) = qt0_o(:mkx) thl0(:mkx) = thl0_o(:mkx) thvl0(:mkx) = thvl0_o(:mkx) ssthl0(:mkx) = ssthl0_o(:mkx) ssqt0(:mkx) = ssqt0_o(:mkx) thv0bot(:mkx) = thv0bot_o(:mkx) thv0top(:mkx) = thv0top_o(:mkx) thvl0bot(:mkx) = thvl0bot_o(:mkx) thvl0top(:mkx) = thvl0top_o(:mkx) ssu0(:mkx) = ssu0_o(:mkx) ssv0(:mkx) = ssv0_o(:mkx) ! ------------------------------------------------------ ! ! Initialize all fluxes, tendencies, and other variables ! ! in association with cumulus convection. ! ! ------------------------------------------------------ ! umf(0:mkx) = 0.0_r8 emf(0:mkx) = 0.0_r8 slflx(0:mkx) = 0.0_r8 qtflx(0:mkx) = 0.0_r8 uflx(0:mkx) = 0.0_r8 vflx(0:mkx) = 0.0_r8 qvten(:mkx) = 0.0_r8 qlten(:mkx) = 0.0_r8 qiten(:mkx) = 0.0_r8 sten(:mkx) = 0.0_r8 uten(:mkx) = 0.0_r8 vten(:mkx) = 0.0_r8 qrten(:mkx) = 0.0_r8 qsten(:mkx) = 0.0_r8 dwten(:mkx) = 0.0_r8 diten(:mkx) = 0.0_r8 precip = 0.0_r8 snow = 0.0_r8 cufrc(:mkx) = 0.0_r8 qcu(:mkx) = 0.0_r8 qlu(:mkx) = 0.0_r8 qiu(:mkx) = 0.0_r8 fer(:mkx) = 0.0_r8 fdr(:mkx) = 0.0_r8 qc(:mkx) = 0.0_r8 qc_l(:mkx) = 0.0_r8 qc_i(:mkx) = 0.0_r8 rliq = 0.0_r8 cbmf = 0.0_r8 cnt = real(mkx, r8) cnb = 0.0_r8 qtten(:mkx) = 0.0_r8 slten(:mkx) = 0.0_r8 ufrc(0:mkx) = 0.0_r8 thlu(0:mkx) = 0.0_r8 qtu(0:mkx) = 0.0_r8 uu(0:mkx) = 0.0_r8 vu(0:mkx) = 0.0_r8 wu(0:mkx) = 0.0_r8 thvu(0:mkx) = 0.0_r8 thlu_emf(0:mkx) = 0.0_r8 qtu_emf(0:mkx) = 0.0_r8 uu_emf(0:mkx) = 0.0_r8 vu_emf(0:mkx) = 0.0_r8 ! -------------------------------------------------- ! ! Below are diagnostic output variables for detailed ! ! analysis of cumulus scheme. ! ! -------------------------------------------------- ! ufrcinvbase = 0.0_r8 ufrclcl = 0.0_r8 winvbase = 0.0_r8 wlcl = 0.0_r8 emfkbup = 0.0_r8 cbmflimit = 0.0_r8 excessu_arr(:mkx) = 0.0_r8 excess0_arr(:mkx) = 0.0_r8 xc_arr(:mkx) = 0.0_r8 aquad_arr(:mkx) = 0.0_r8 bquad_arr(:mkx) = 0.0_r8 cquad_arr(:mkx) = 0.0_r8 bogbot_arr(:mkx) = 0.0_r8 bogtop_arr(:mkx) = 0.0_r8 else ! When 'del_CIN < 0', use explicit CIN instead of implicit CIN. ! ----------------------------------------------------------- ! ! Identifier showing whether explicit or implicit CIN is used ! ! ----------------------------------------------------------- ! ind_delcin(i) = 1._r8 ! --------------------------------------------------------- ! ! Restore original output values of "iter_cin = 1" and exit ! ! --------------------------------------------------------- ! umf_out(i,0:mkx) = umf_s(0:mkx) qvten_out(i,:mkx) = qvten_s(:mkx) qlten_out(i,:mkx) = qlten_s(:mkx) qiten_out(i,:mkx) = qiten_s(:mkx) sten_out(i,:mkx) = sten_s(:mkx) uten_out(i,:mkx) = uten_s(:mkx) vten_out(i,:mkx) = vten_s(:mkx) qrten_out(i,:mkx) = qrten_s(:mkx) qsten_out(i,:mkx) = qsten_s(:mkx) precip_out(i) = precip_s snow_out(i) = snow_s cush_inout(i) = cush_s cufrc_out(i,:mkx) = cufrc_s(:mkx) slflx_out(i,0:mkx) = slflx_s(0:mkx) qtflx_out(i,0:mkx) = qtflx_s(0:mkx) qcu_out(i,:mkx) = qcu_s(:mkx) qlu_out(i,:mkx) = qlu_s(:mkx) qiu_out(i,:mkx) = qiu_s(:mkx) cbmf_out(i) = cbmf_s qc_out(i,:mkx) = qc_s(:mkx) rliq_out(i) = rliq_s cnt_out(i) = cnt_s cnb_out(i) = cnb_s ! -------------------------------------------------- ! ! Below are diagnostic output variables for detailed ! ! analysis of cumulus scheme. ! ! -------------------------------------------------- ! fer_out(i,mkx:1:-1) = fer_s(:mkx) fdr_out(i,mkx:1:-1) = fdr_s(:mkx) cinh_out(i) = cin_s cinlclh_out(i) = cinlcl_s qtten_out(i,mkx:1:-1) = qtten_s(:mkx) slten_out(i,mkx:1:-1) = slten_s(:mkx) ufrc_out(i,mkx:0:-1) = ufrc_s(0:mkx) uflx_out(i,mkx:0:-1) = uflx_s(0:mkx) vflx_out(i,mkx:0:-1) = vflx_s(0:mkx) ufrcinvbase_out(i) = ufrcinvbase_s ufrclcl_out(i) = ufrclcl_s winvbase_out(i) = winvbase_s wlcl_out(i) = wlcl_s plcl_out(i) = plcl_s pinv_out(i) = pinv_s plfc_out(i) = plfc_s pbup_out(i) = pbup_s ppen_out(i) = ppen_s qtsrc_out(i) = qtsrc_s thlsrc_out(i) = thlsrc_s thvlsrc_out(i) = thvlsrc_s emfkbup_out(i) = emfkbup_s cbmflimit_out(i) = cbmflimit_s tkeavg_out(i) = tkeavg_s zinv_out(i) = zinv_s rcwp_out(i) = rcwp_s rlwp_out(i) = rlwp_s riwp_out(i) = riwp_s wu_out(i,mkx:0:-1) = wu_s(0:mkx) qtu_out(i,mkx:0:-1) = qtu_s(0:mkx) thlu_out(i,mkx:0:-1) = thlu_s(0:mkx) thvu_out(i,mkx:0:-1) = thvu_s(0:mkx) uu_out(i,mkx:0:-1) = uu_s(0:mkx) vu_out(i,mkx:0:-1) = vu_s(0:mkx) qtu_emf_out(i,mkx:0:-1) = qtu_emf_s(0:mkx) thlu_emf_out(i,mkx:0:-1) = thlu_emf_s(0:mkx) uu_emf_out(i,mkx:0:-1) = uu_emf_s(0:mkx) vu_emf_out(i,mkx:0:-1) = vu_emf_s(0:mkx) uemf_out(i,mkx:0:-1) = uemf_s(0:mkx) dwten_out(i,mkx:1:-1) = dwten_s(:mkx) diten_out(i,mkx:1:-1) = diten_s(:mkx) flxrain_out(i,mkx:0:-1) = flxrain_s(0:mkx) flxsnow_out(i,mkx:0:-1) = flxsnow_s(0:mkx) ntraprd_out(i,mkx:1:-1) = ntraprd_s(:mkx) ntsnprd_out(i,mkx:1:-1) = ntsnprd_s(:mkx) excessu_arr_out(i,mkx:1:-1) = excessu_arr_s(:mkx) excess0_arr_out(i,mkx:1:-1) = excess0_arr_s(:mkx) xc_arr_out(i,mkx:1:-1) = xc_arr_s(:mkx) aquad_arr_out(i,mkx:1:-1) = aquad_arr_s(:mkx) bquad_arr_out(i,mkx:1:-1) = bquad_arr_s(:mkx) cquad_arr_out(i,mkx:1:-1) = cquad_arr_s(:mkx) bogbot_arr_out(i,mkx:1:-1) = bogbot_arr_s(:mkx) bogtop_arr_out(i,mkx:1:-1) = bogtop_arr_s(:mkx) id_exit = .false. go to 333 endif endif ! ------------------------------------------------------------------ ! ! Define a release level, 'prel' and release layer, 'krel'. ! ! 'prel' is the lowest level from which buoyancy sorting occurs, and ! ! 'krel' is the layer index containing 'prel' in it, similar to the ! ! previous definitions of 'kinv', 'klcl', and 'klfc'. In order to ! ! ensure that only PBL scheme works within the PBL, if LCL is below ! ! PBL top height, then 'krel = kinv', while if LCL is above PBL top ! ! height, then 'krel = klcl'. Note however that regardless of the ! ! definition of 'krel', cumulus convection induces fluxes within PBL ! ! through 'fluxbelowinv'. We can make cumulus convection start from ! ! any level, even within the PBL by appropriately defining 'krel' & ! ! 'prel' here. Then it must be accompanied by appropriate definition ! ! of source air properties, CIN, and re-setting of 'fluxbelowinv', & ! ! many other stuffs. ! ! Probably the simplest way to adjust 'prel' and 'krel' is to adjust ! ! 'kinv' because calculation of CIN is based on 'kinv'. ! ! Note that even when 'prel' is located above the PBL top height, we ! ! still have cumulus convection between PBL top height and 'prel': ! ! we simply assume that no lateral mixing occurs in this range. ! ! ------------------------------------------------------------------ ! if( klcl.lt.kinv ) then krel = kinv prel = ps0(krel-1) thv0rel = thv0bot(krel) else krel = klcl prel = plcl thv0rel = thv0lcl endif ! --------------------------------------------------------------------------- ! ! Calculate cumulus base mass flux ('cbmf'), fractional area ('ufrcinv'), and ! ! and mean vertical velocity (winv) of cumulus updraft at PBL top interface. ! ! Also, calculate updraft fractional area (ufrclcl) and vertical velocity at ! ! the LCL (wlcl). When LCL is below PBLH, cinlcl = 0 and 'ufrclcl = ufrcinv', ! ! and 'wlcl = winv. ! ! Only updrafts strong enough to overcome CIN can rise over PBL top interface.! ! Thus, in order to calculate cumulus mass flux at PBL top interface, 'cbmf',! ! we need to know 'CIN' ( the strength of potential energy barrier ) and ! ! 'sigmaw' ( a standard deviation of updraft vertical velocity at the PBL top ! ! interface, a measure of turbulentce strength in the PBL ). Naturally, the ! ! ratio of these two variables, 'mu' - normalized CIN by TKE- is key variable ! ! controlling 'cbmf'. If 'mu' becomes large, only small fraction of updrafts ! ! with very strong TKE can rise over the PBL - both 'cbmf' and 'ufrc' becomes ! ! small, but 'winv' becomes large ( this can be easily understood by PDF of w ! ! at PBL top ). If 'mu' becomes small, lots of updraft can rise over the PBL ! ! top - both 'cbmf' and 'ufrc' becomes large, but 'winv' becomes small. Thus, ! ! all of the key variables associated with cumulus convection at the PBL top ! ! - 'cbmf', 'ufrc', 'winv' where 'cbmf = rho*ufrc*winv' - are a unique functi ! ! ons of 'mu', normalized CIN. Although these are uniquely determined by 'mu',! ! we usually impose two comstraints on 'cbmf' and 'ufrc': (1) because we will ! ! simply assume that subsidence warming and drying of 'kinv-1' layer in assoc ! ! iation with 'cbmf' at PBL top interface is confined only in 'kinv-1' layer, ! ! cbmf must not be larger than the mass within the 'kinv-1' layer. Otherwise, ! ! instability will occur due to the breaking of CBS condition. If we consider ! ! semi-Lagrangian vertical advection scheme and explicitly consider the exten ! ! t of vertical movement of each layer in association with cumulus mass flux, ! ! we don't need to impose this constraint. However, using a semi-Lagrangian ! ! scheme is a future research subject. Note that this constraint should be ap ! ! plied for all interfaces above PBL top as well as PBL top interface. As a ! ! result, this 'cbmf' constraint impose a 'lower' limit on mu - 'mumin0'. (2) ! ! in order for mass flux parameterization - rho*(w'a')= M*(a_c-a_e) - to be ! ! valid, cumulus updraft fractional area should be much smaller than 1. In ! ! current code, we impose 'rmaxfrac = 0.1 ~ 0.2' through the whole vertical ! ! layers where cumulus convection occurs. At the PBL top interface, the same ! ! constraint is made by imposing another lower 'lower' limit on mu, 'mumin1'. ! ! After that, also limit 'ufrclcl' to be smaller than 'rmaxfrac' by 'mumin2'. ! ! --------------------------------------------------------------------------- ! ! --------------------------------------------------------------------------- ! ! Calculate normalized CIN, 'mu' satisfying all the three constraints imposed ! ! on 'cbmf'('mumin0'), 'ufrc' at the PBL top - 'ufrcinv' - ( by 'mumin1' from ! ! a parameter sentence), and 'ufrc' at the LCL - 'ufrclcl' ( by 'mumin2'). ! ! Note that 'cbmf' does not change between PBL top and LCL because we assume ! ! that buoyancy sorting does not occur when cumulus updraft is unsaturated. ! ! --------------------------------------------------------------------------- ! if(use_CINcin) then wcrit = sqrt( 2._r8 * cin * rbuoy ) else wcrit = sqrt( 2._r8 * cinlcl * rbuoy ) endif sigmaw = sqrt( rkfre * tkeavg + epsvarw ) mu = wcrit/sigmaw/1.4142_r8 if(mu .ge. 3._r8) then ! write(iulog,*) 'mu >= 3' id_exit = .true. go to 333 endif rho0inv = ps0(kinv-1)/(r*thv0top(kinv-1)*exns0(kinv-1)) cbmf = (rho0inv*sigmaw/2.5066_r8)*exp(-mu**2) ! 1. 'cbmf' constraint cbmflimit = 0.9_r8*dp0(kinv-1)/g/dt mumin0 = 0._r8 if(cbmf.gt.cbmflimit) mumin0 = sqrt(-log(2.5066_r8*cbmflimit/rho0inv/sigmaw)) ! 2. 'ufrcinv' constraint mu = max(max(mu,mumin0),mumin1) ! 3. 'ufrclcl' constraint mulcl = sqrt(2.*cinlcl*rbuoy)/1.4142/sigmaw mulclstar = sqrt(max(0._r8,2*(exp(-mu**2)/2.5066_r8)**2*(1/erfc(mu)**2-0.25_r8/rmaxfrac**2))) if(mulcl.gt.1.e-8_r8.and.mulcl.gt.mulclstar) then mumin2 = compute_mumin2(mulcl,rmaxfrac,mu) if(mu.gt.mumin2) then write(iulog,*) 'Critical error in mu calculation in UW_ShCu' stop endif mu = max(mu,mumin2) if(mu.eq.mumin2) limit_ufrc(i) = 1._r8 endif if(mu.eq.mumin0) limit_cbmf(i) = 1._r8 if(mu.eq.mumin1) limit_ufrc(i) = 1._r8 ! ------------------------------------------------------------------- ! ! Calculate final ['cbmf','ufrcinv','winv'] at the PBL top interface. ! ! Note that final 'cbmf' here is obtained in such that 'ufrcinv' and ! ! 'ufrclcl' are smaller than ufrcmax and there is no CBF instability. ! ! ------------------------------------------------------------------- ! cbmf = (rho0inv*sigmaw/2.5066_r8)*exp(-mu**2) winv = sigmaw*(2/2.5066_r8)*exp(-mu**2)/erfc(mu) ufrcinv = cbmf/winv/rho0inv ! ------------------------------------------------------------------- ! ! Calculate ['ufrclcl','wlcl'] at the LCL. When LCL is below PBL top, ! ! it automatically becomes 'ufrclcl = ufrcinv' & 'wlcl = winv', since ! ! it was already set to 'cinlcl=0' if LCL is below PBL top interface. ! ! Note 'cbmf' at the PBL top is the same as 'cbmf' at the LCL. Note ! ! also that final 'cbmf' here is obtained in such that 'ufrcinv' and ! ! 'ufrclcl' are smaller than ufrcmax and there is no CBF instability.! ! By construction, it must be 'wlcl2>0' but for assurance, I checked ! ! this again in the below block. If 'ufrclcl < 0.1%', just exit. ! ! ------------------------------------------------------------------- ! wtw = winv * winv - 2._r8 * cinlcl * rbuoy if(wtw .le. 0._r8) then ! write(iulog,*) 'wlcl2 < 0 at the LCL' exit_wtw(i) = 1._r8 id_exit = .true. go to 333 endif wlcl = sqrt(wtw) ufrclcl = cbmf/wlcl/rho0inv wrel = wlcl if(ufrclcl.le.0.001_r8) then ! write(iulog,*) 'ufrclcl <= 0.001' exit_ufrc(i) = 1._r8 id_exit = .true. go to 333 endif ufrc(krel-1) = ufrclcl ! ----------------------------------------------------------------------- ! ! Below is just diagnostic output for detailed analysis of cumulus scheme ! ! ----------------------------------------------------------------------- ! ufrcinvbase = ufrcinv winvbase = winv umf(kinv-1:krel-1) = cbmf wu(kinv-1:krel-1) = winv ! -------------------------------------------------------------------------- ! ! Define updraft properties at the level where buoyancy sorting starts to be ! ! happening, i.e., by definition, at 'prel' level within the release layer. ! ! Because no lateral entrainment occurs upto 'prel', conservative scalars of ! ! cumulus updraft at release level is same as those of source air. However, ! ! horizontal momentums of source air are modified by horizontal PGF forcings ! ! from PBL top interface to 'prel'. For this case, we should add additional ! ! horizontal momentum from PBL top interface to 'prel' as will be done below ! ! to 'usrc' and 'vsrc'. Note that below cumulus updraft properties - umf, wu,! ! thlu, qtu, thvu, uu, vu - are defined all interfaces not at the layer mid- ! ! point. From the index notation of cumulus scheme, wu(k) is the cumulus up- ! ! draft vertical velocity at the top interface of k layer. ! ! -------------------------------------------------------------------------- ! emf(krel-1) = 0._r8 umf(krel-1) = cbmf wu(krel-1) = wrel thlu(krel-1) = thlsrc qtu(krel-1) = qtsrc call conden(prel,thlsrc,qtsrc,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvu(krel-1) = thj*(1._r8 + zvir*qvj - qlj - qij ) uplus = 0._r8 vplus = 0._r8 if( krel.eq.kinv ) then uplus = PGFc * ssu0(kinv) * ( prel - ps0(kinv-1) ) vplus = PGFc * ssv0(kinv) * ( prel - ps0(kinv-1) ) else do k = kinv, max(krel-1,kinv) uplus = uplus + PGFc * ssu0(k) * ( ps0(k) - ps0(k-1) ) vplus = vplus + PGFc * ssv0(k) * ( ps0(k) - ps0(k-1) ) end do uplus = uplus + PGFc * ssu0(krel) * ( prel - ps0(krel-1) ) vplus = vplus + PGFc * ssv0(krel) * ( prel - ps0(krel-1) ) end if uu(krel-1) = usrc + uplus vu(krel-1) = vsrc + vplus ! -------------------------------------------------------------------------- ! ! Define environmental properties at the level where buoyancy sorting occurs ! ! ('pe', normally, layer midpoint except in the 'krel' layer). In the 'krel' ! ! layer where buoyancy sorting starts to occur, however, 'pe' is defined ! ! differently because LCL is regarded as lower interface for mixing purpose. ! ! -------------------------------------------------------------------------- ! pe = 0.5_r8 * ( prel + ps0(krel) ) dpe = prel - ps0(krel) exne = exnf(pe) thvebot = thv0rel thle = thl0(krel) + ssthl0(krel) * ( pe - p0(krel) ) qte = qt0(krel) + ssqt0(krel) * ( pe - p0(krel) ) ue = u0(krel) + ssu0(krel) * ( pe - p0(krel) ) ve = v0(krel) + ssv0(krel) * ( pe - p0(krel) ) !-------------------------! ! Buoyancy-Sorting Mixing ! !-------------------------!------------------------------------------------ ! ! ! ! In order to complete buoyancy-sorting mixing at layer mid-point, and so ! ! calculate 'updraft mass flux, updraft w velocity, conservative scalars' ! ! at the upper interface of each layer, we need following 3 information. ! ! ! ! 1. Pressure where mixing occurs ('pe'), and temperature at 'pe' which is ! ! necessary to calculate various thermodynamic coefficients at pe. This ! ! temperature is obtained by undiluted cumulus properties lifted to pe. ! ! 2. Undiluted updraft properties at pe - conservative scalar and vertical ! ! velocity -which are assumed to be the same as the properties at lower ! ! interface only for calculation of fractional lateral entrainment and ! ! detrainment rate ( fer(k) and fdr(k) [Pa-1] ), respectively. Final ! ! values of cumulus conservative scalars and w at the top interface are ! ! calculated afterward after obtaining fer(k) & fdr(k). ! ! 3. Environmental properties at pe. ! ! ------------------------------------------------------------------------- ! ! ------------------------------------------------------------------------ ! ! Define cumulus scale height. ! ! Cumulus scale height is defined as the maximum height cumulus can reach. ! ! In case of premitive code, cumulus scale height ('cush') at the current ! ! time step was assumed to be the same as 'cush' of previous time step. ! ! However, I directly calculated cush at each time step using an iterative ! ! method. Note that within the cumulus scheme, 'cush' information is used ! ! only at two places during buoyancy-sorting process: ! ! (1) Even negatively buoyancy mixtures with strong vertical velocity ! ! enough to rise up to 'rle*scaleh' (rle = 0.1) from pe are entrained ! ! into cumulus updraft, ! ! (2) The amount of mass that is involved in buoyancy-sorting mixing ! ! process at pe is rei(k) = rkm/scaleh/rho*g [Pa-1] ! ! In terms of (1), I think critical stopping distance might be replaced by ! ! layer thickness. In future, we will use rei(k) = (0.5*rkm/z0(k)/rho/g). ! ! In the premitive code, 'scaleh' was largely responsible for the jumping ! ! variation of precipitation amount. ! ! ------------------------------------------------------------------------ ! scaleh = tscaleh if(tscaleh .lt. 0.0_r8) scaleh = 1000._r8 do iter_scaleh = 1, 3 ! ---------------------------------------------------------------- ! ! Initialization of 'kbup' and 'kpen' ! ! ---------------------------------------------------------------- ! ! 'kbup' is the top-most layer in which cloud buoyancy is positive ! ! both at the top and bottom interface of the layer. 'kpen' is the ! ! layer upto which cumulus panetrates ,i.e., cumulus w at the base ! ! interface is positive, but becomes negative at the top interface.! ! Here, we initialize 'kbup' and 'kpen'. These initializations are ! ! not trivial but important, expecially in calculating turbulent ! ! fluxes without confliction among several physics as explained in ! ! detail in the part of turbulent fluxes calculation later. Note ! ! that regardless of whether 'kbup' and 'kpen' are updated or not ! ! during updraft motion, penetrative entrainments are dumped down ! ! across the top interface of 'kbup' later. More specifically,! ! penetrative entrainment heat and moisture fluxes are calculated ! ! from the top interface of 'kbup' layer to the base interface of ! ! 'kpen' layer. Because of this, initialization of 'kbup' & 'kpen' ! ! influence the convection system when there are not updated. The ! ! below initialization of 'kbup = krel' assures that penetrative ! ! entrainment fluxes always occur at interfaces above the PBL top ! ! interfaces (i.e., only at interfaces k >=kinv ), which seems to ! ! be attractable considering that the most correct fluxes at the ! ! PBL top interface can be ontained from the 'fluxbelowinv' using ! ! reconstructed PBL height. ! ! The 'kbup = krel'(after going through the whole buoyancy sorting ! ! proces during updraft motion) implies that cumulus updraft from ! ! the PBL top interface can not reach to the LFC,so that 'kbup' is ! ! not updated during upward. This means that cumulus updraft did ! ! not fully overcome the buoyancy barrier above just the PBL top. ! ! If 'kpen' is not updated either ( i.e., cumulus cannot rise over ! ! the top interface of release layer),penetrative entrainment will ! ! not happen at any interfaces. If cumulus updraft can rise above ! ! the release layer but cannot fully overcome the buoyancy barrier ! ! just above PBL top interface, penetratve entrainment occurs at ! ! several above interfaces, including the top interface of release ! ! layer. In the latter case, warming and drying tendencies will be ! ! be initiated in 'krel' layer. Note current choice of 'kbup=krel' ! ! is completely compatible with other flux physics without double ! ! or miss counting turbulent fluxes at any interface. However, the ! ! alternative choice of 'kbup=krel-1' also has itw own advantage - ! ! when cumulus updraft cannot overcome buoyancy barrier just above ! ! PBL top, entrainment warming and drying are concentrated in the ! ! 'kinv-1' layer instead of 'kinv' layer for this case. This might ! ! seems to be more dynamically reasonable, but I will choose the ! ! 'kbup = krel' choice since it is more compatible with the other ! ! parts of the code, expecially, when we chose ' use_emf=.false. ' ! ! as explained in detail in turbulent flux calculation part. ! ! ---------------------------------------------------------------- ! kbup = krel kpen = krel ! ------------------------------------------------------------ ! ! Since 'wtw' is continuously updated during vertical motion, ! ! I need below initialization command within this 'iter_scaleh'! ! do loop. Similarily, I need initializations of environmental ! ! properties at 'krel' layer as below. ! ! ------------------------------------------------------------ ! wtw = wlcl * wlcl pe = 0.5_r8 * ( prel + ps0(krel) ) dpe = prel - ps0(krel) exne = exnf(pe) thvebot = thv0rel thle = thl0(krel) + ssthl0(krel) * ( pe - p0(krel) ) qte = qt0(krel) + ssqt0(krel) * ( pe - p0(krel) ) ue = u0(krel) + ssu0(krel) * ( pe - p0(krel) ) ve = v0(krel) + ssv0(krel) * ( pe - p0(krel) ) ! ----------------------------------------------------------------------- ! ! Cumulus rises upward from 'prel' ( or base interface of 'krel' layer ) ! ! until updraft vertical velocity becomes zero. ! ! Buoyancy sorting is performed via two stages. (1) Using cumulus updraft ! ! properties at the base interface of each layer,perform buoyancy sorting ! ! at the layer mid-point, 'pe', and update cumulus properties at the top ! ! interface, and then (2) by averaging updated cumulus properties at the ! ! top interface and cumulus properties at the base interface, calculate ! ! cumulus updraft properties at pe that will be used in buoyancy sorting ! ! mixing - thlue, qtue and, wue. Using this averaged properties, perform ! ! buoyancy sorting again at pe, and re-calculate fer(k) and fdr(k). Using ! ! this recalculated fer(k) and fdr(k), finally calculate cumulus updraft ! ! properties at the top interface - thlu, qtu, thvu, uu, vu. In the below,! ! 'iter_xc = 1' performs the first stage, while 'iter_xc= 2' performs the ! ! second stage. We can increase the number of iterations, 'nter_xc'.as we ! ! want, but a sample test indicated that about 3 - 5 iterations produced ! ! satisfactory converent solution. Finally, identify 'kbup' and 'kpen'. ! ! ----------------------------------------------------------------------- ! do k = krel, mkx - 1 ! Here, 'k' is a layer index. km1 = k - 1 thlue = thlu(km1) qtue = qtu(km1) wue = wu(km1) wtwb = wtw do iter_xc = 1, niter_xc wtw = wu(km1) * wu(km1) ! ---------------------------------------------------------------- ! ! Calculate environmental and cumulus saturation 'excess' at 'pe'. ! ! Note that in order to calculate saturation excess, we should use ! ! liquid water temperature instead of temperature as the argument ! ! of "qsat". However, normal argument of "qsat" is temperature. ! ! ---------------------------------------------------------------- ! call conden(pe,thle,qte,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thv0j = thj * ( 1._r8 + zvir*qvj - qlj - qij ) rho0j = pe / ( r * thv0j * exne ) qsat_arg = thle*exne status = qsat(qsat_arg,pe,es(1),qs(1),gam(1),1) excess0 = qte - qs(1) call conden(pe,thlue,qtue,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if ! ----------------------------------------------------------------- ! ! Detrain excessive condensate larger than 'criqc' from the cumulus ! ! updraft before performing buoyancy sorting. All I should to do is ! ! to update 'thlue' & 'que' here. Below modification is completely ! ! compatible with the other part of the code since 'thule' & 'qtue' ! ! are used only for buoyancy sorting. I found that as long as I use ! ! 'niter_xc >= 2', detraining excessive condensate before buoyancy ! ! sorting has negligible influence on the buoyancy sorting results. ! ! ----------------------------------------------------------------- ! if( (qlj + qij) .gt. criqc ) then exql = ( ( qlj + qij ) - criqc ) * qlj / ( qlj + qij ) exqi = ( ( qlj + qij ) - criqc ) * qij / ( qlj + qij ) qtue = qtue - exql - exqi thlue = thlue + (xlv/cp/exne)*exql + (xls/cp/exne)*exqi endif call conden(pe,thlue,qtue,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvj = thj * ( 1._r8 + zvir * qvj - qlj - qij ) tj = thj * exne ! This 'tj' is used for computing thermo. coeffs. below qsat_arg = thlue*exne status = qsat(qsat_arg,pe,es(1),qs(1),gam(1),1) excessu = qtue - qs(1) ! ------------------------------------------------------------------- ! ! Calculate critical mixing fraction, 'xc'. Mixture with mixing ratio ! ! smaller than 'xc' will be entrained into cumulus updraft. Both the ! ! saturated updrafts with 'positive buoyancy' or 'negative buoyancy + ! ! strong vertical velocity enough to rise certain threshold distance' ! ! are kept into the updraft in the below program. If the core updraft ! ! is unsaturated, we can set 'xc = 0' and let the cumulus convection ! ! still works or we may exit. ! ! Current below code does not entrain unsaturated mixture. However it ! ! should be modified such that it also entrain unsaturated mixture. ! ! ------------------------------------------------------------------- ! ! ----------------------------------------------------------------- ! ! cridis : Critical stopping distance for buoyancy sorting purpose. ! ! ----------------------------------------------------------------- ! cridis = rle*scaleh ! Original code ! cridis = 1._r8*(zs0(k) - zs0(k-1)) ! New code if(use_newbuosort) then ! ------------------------------ ! ! New Buoyancy Sorting Algorithm ! ! ------------------------------ ! ! ----------------------------------------------------------------- ! ! Case 1 : When both cumulus and env. are unsaturated or saturated. ! ! ----------------------------------------------------------------- ! if((excessu.lt.0.and.excess0.lt.0).or.(excessu.gt.0.and.excess0.gt.0)) then xc = min(1._r8,max(0._r8,1._r8-2._r8*rbuoy*g*cridis/wue**2._r8*(1-thvj/thv0j))) ! Below 3 lines are diagnostic output not influencing ! numerical calculations. aquad = 0._r8 bquad = 0._r8 cquad = 0._r8 else ! -------------------------------------------------- ! ! Case 2 : When either cumulus or env. is saturated. ! ! -------------------------------------------------- ! xsat = excessu / ( excessu - excess0 ); thlxsat = thlue + xsat * ( thle - thlue ); qtxsat = qtue + xsat * ( qte - qtue ); call conden(pe,thlxsat,qtxsat,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvxsat = thj * ( 1._r8 + zvir * qvj - qlj - qij ) ! -------------------------------------------------- ! ! kk=1 : Cumulus Segment, kk=2 : Environment Segment ! ! -------------------------------------------------- ! do kk = 1, 2 if( kk.eq.1 ) then thv_x0 = thvj; thv_x1 = ( 1._r8 - 1._r8/xsat ) * thvj + ( 1._r8/xsat ) * thvxsat; else thv_x1 = thv0j; thv_x0 = ( xsat / ( xsat - 1._r8 ) ) * thv0j + ( 1._r8/( 1._r8 - xsat ) ) * thvxsat; endif aquad = wue**2; bquad = 2._r8*rbuoy*g*cridis*(thv_x1 - thv_x0)/thv0j - 2._r8*wue**2; cquad = 2._r8*rbuoy*g*cridis*(thv_x0 - thv0j) /thv0j + wue**2; if( kk.eq.1 ) then if((bquad**2-4._r8*aquad*cquad).ge.0._r8) then call roots(aquad,bquad,cquad,xs1,xs2,status) x_cu = min(1._r8,max(0._r8,min(xsat,min(xs1,xs2)))) else x_cu = xsat; endif else if((bquad**2-4._r8*aquad*cquad).ge.0._r8) then call roots(aquad,bquad,cquad,xs1,xs2,status) x_en = min(1._r8,max(0._r8,max(xsat,min(xs1,xs2)))) else x_en = 1._r8; endif endif enddo if( x_cu.eq.xsat ) then xc = max(x_cu, x_en); else xc = x_cu; endif endif else ! ------------------------------ ! ! Old Buoyancy Sorting Algorithm ! ! ------------------------------ ! if( excessu.lt.0 ) then ! ----------------------------------------------------- ! ! Ideally, it should be 'xc = 1' when 'thvj > thv0j', ! ! 'xc = 0' when 'thvj < thv0j', ! ! 'xc = 0.5' when 'thvj = thv0j' ! ! This should be modified layer. Also, 'exit_drycore' ! ! should be removed. ! ! ----------------------------------------------------- ! xc = 0. ! write(iulog,*) 'Dry Core Updraft Warning in UW-shallow scheme' exit_drycore(i) = 1._r8 ! id_exit = .true. ! go to 333 elseif( excessu.ge.0.and.excess0.ge.0 ) then ! ---------------------------------------------------------------- ! ! When both cumulus and environment are saturated, I should check ! ! if below calculation assuming that resulting buoyancy of mixture ! ! is a simple linear function of 'x' is correctly or not. ! ! ---------------------------------------------------------------- ! aquad = wue**2 bquad = -2._r8*rbuoy*g*cridis*(thvj - thv0j)/thv0j - 2._r8*wue**2 cquad = 2._r8*rbuoy*g*cridis*(thvj - thv0j)/thv0j + wue**2 if( (-2._r8*aquad-bquad).ge.0._r8 ) then xc = 1._r8 else xc = min(1._r8,max(0._r8,-bquad/aquad-1._r8)) endif elseif ( excessu.ge.0.and.excess0.lt.0 ) then ! --------------------------------------------------------------------- ! ! Below code does not entrain 'unsaturated positively buoyant mixture', ! ! which is clearly wrong. I should modify current below code such that ! ! cumulus also entrain 'unsaturated positively buoyant mixture'. ! ! --------------------------------------------------------------------- ! xsat = excessu / ( excessu - excess0 ) rdqsdt = ep2 * xlv * qse / r / tj**2 rbeta = ( 1._r8 + ( 1._r8 + zvir ) * tj * rdqsdt ) / ( 1._r8 + rdqsdt * xlv / cp ) ths0 = min(thv0j,thvj + rbeta*(thle - thlue) + (rbeta*xlv/cp/exne - thj)*(qte - qtue)) aquad = wue**2 bquad = -2._r8*rbuoy*g*cridis*(thvj - ths0) /thv0j - 2._r8*wue**2 cquad = 2._r8*rbuoy*g*cridis*(thvj - thv0j)/thv0j + wue**2 if((bquad**2-4._r8*aquad*cquad).ge.0._r8) then ! ------------------------------------------------------------------- ! ! I checked that below premitive code produced almost ( not exactly ) ! ! same results as mine. For numerical stability in solving quadrature ! ! equation let's use the primitive. ! ! ------------------------------------------------------------------- ! call roots(aquad,bquad,cquad,xs1,xs2,status) ! Premitive xc = min(1._r8,max(0._r8,min(xsat,min(xs1,xs2)))) ! Premitive ! xc = min(1._r8,max(0._r8,min(xsat,(-bquad-sqrt(bquad**2-4._r8*aquad*cquad))/(2._r8*aquad)))) ! Sungsu else xc = xsat endif endif endif ! ------------------------------------------------------------------------ ! ! Compute fractional lateral entrainment & detrainment rate in each layers.! ! The unit of rei(k), fer(k), and fdr(k) is [Pa-1]. Alternative choice of ! ! 'rei(k)' is also shown below, where coefficient 0.5 was from approximate ! ! tuning against the BOMEX case. ! ! In order to prevent the onset of instability in association with cumulus ! ! induced subsidence advection, cumulus mass flux at the top interface in ! ! any layer should be smaller than ( 90% of ) total mass within that layer.! ! I imposed limits on 'rei(k)' as below, in such that stability condition ! ! is always satisfied. ! ! Below limiter of 'rei(k)' becomes negative for some cases, causing error.! ! So, for the time being, I came back to the original limiter. ! ! ------------------------------------------------------------------------ ! ee2 = xc**2 ud2 = 1._r8 - 2.*xc + xc**2 ! rei(k) = (rkm/scaleh/g/rho0j) ! Default. rei(k) = (0.5_r8*rkm/z0(k)/g/rho0j) ! Alternative. ! ------------------------------ ! ! Below is the original limiter. ! ! ------------------------------ ! if( xc.gt.0.5_r8 ) rei(k) = min(rei(k),0.9*log(dp0(k)/g/dt/umf(km1) + 1._r8)/dpe/(2._r8*xc-1._r8)) ! ------------------------------ ! ! Below is the new limiter. ! ! ------------------------------ ! ! if(xc.gt.0.5_r8) then ! limit_rei(i) = 1._r8 ! rei(k) = min(rei(k),log(0.9*dp0(k)/g/dt/umf(km1))/dpe/(2._r8*xc-1._r8)) ! elseif(xc.eq.0.5_r8) then ! if((0.9_r8*dp0(k)/g/dt/umf(km1)).lt.1._r8) then ! write(iulog,*) 'Impossible to avoid CBS instability in mcshallow.F90' ! id_exit = .true. ! go to 333 ! exit_rei(i) = 1._r8 ! endif ! else ! if((0.9*dp0(k)/g/dt/umf(km1)).lt.1._r8) then ! limit_rei(i) = 1._r8 ! rei(k) = max(rei(k),log(0.9_r8*dp0(k)/g/dt/umf(km1))/dpe/(2._r8*xc-1.)) ! endif ! endif fer(k) = rei(k) * ee2 fdr(k) = rei(k) * ud2 ! ------------------------------------------------------------------------------ ! ! Iteration Start due to 'maxufrc' constraint [ ****************************** ] ! ! ------------------------------------------------------------------------------ ! ! -------------------------------------------------------------------------- ! ! Calculate cumulus updraft mass flux and penetrative entrainment mass flux. ! ! Note that non-zero penetrative entrainment mass flux will be asigned only ! ! to interfaces from the top interface of 'kbup' layer to the base interface ! ! of 'kpen' layer as will be shown later. ! ! -------------------------------------------------------------------------- ! umf(k) = umf(km1) * exp( dpe * ( fer(k) - fdr(k) ) ) emf(k) = 0.0_r8 ! --------------------------------------------------------- ! ! Compute cumulus updraft properties at the top interface. ! ! Also use Tayler expansion in order to treat limiting case ! ! --------------------------------------------------------- ! if( fer(k)*dpe .lt. 1.e-4_r8 ) then thlu(k) = thlu(km1) + ( thle + ssthl0(k) * dpe / 2._r8 - thlu(km1) ) * fer(k) * dpe qtu(k) = qtu(km1) + ( qte + ssqt0(k) * dpe / 2._r8 - qtu(km1) ) * fer(k) * dpe uu(k) = uu(km1) + ( ue + ssu0(k) * dpe / 2._r8 - uu(km1) ) * fer(k) * dpe - PGFc * ssu0(k) * dpe vu(k) = vu(km1) + ( ve + ssv0(k) * dpe / 2._r8 - vu(km1) ) * fer(k) * dpe - PGFc * ssv0(k) * dpe else thlu(k) = ( thle + ssthl0(k) / fer(k) - ssthl0(k) * dpe / 2._r8 ) - & ( thle + ssthl0(k) * dpe / 2._r8 - thlu(km1) + ssthl0(k) / fer(k) ) * exp(-fer(k) * dpe) qtu(k) = ( qte + ssqt0(k) / fer(k) - ssqt0(k) * dpe / 2._r8 ) - & ( qte + ssqt0(k) * dpe / 2._r8 - qtu(km1) + ssqt0(k) / fer(k) ) * exp(-fer(k) * dpe) uu(k) = ( ue + ( 1 - PGFc ) * ssu0(k) / fer(k) - ssu0(k) * dpe / 2._r8 ) - & ( ue + ssu0(k) * dpe / 2._r8 - uu(km1) + ( 1 - PGFc ) * ssu0(k) / fer(k) ) * exp(-fer(k) * dpe) vu(k) = ( ve + ( 1 - PGFc ) * ssv0(k) / fer(k) - ssv0(k) * dpe / 2._r8 ) - & ( ve + ssv0(k) * dpe / 2._r8 - vu(km1) + ( 1 - PGFc ) * ssv0(k) / fer(k) ) * exp(-fer(k) * dpe) end if !------------------------------------------------------------------- ! ! Expel some of cloud water and ice from cumulus updraft at the top ! ! interface. Note that this is not 'detrainment' term but a 'sink' ! ! term of cumulus updraft qt ( or one part of 'source' term of mean ! ! environmental qt ). At this stage, as the most simplest choice, if ! ! condensate amount within cumulus updraft is larger than a critical ! ! value, 'criqc', expels the surplus condensate from cumulus updraft ! ! to the environment. A certain fraction ( e.g., 'frc_sus' ) of this ! ! expelled condesnate will be in a form that can be suspended in the ! ! layer k where it was formed, while the other fraction, '1-frc_sus' ! ! will be in a form of precipitatble (e.g.,can potentially fall down ! ! across the base interface of layer k ). In turn we should describe ! ! subsequent falling of precipitable condensate ('1-frc_sus') across ! ! the base interface of the layer k, & evaporation of precipitating ! ! water in the below layer k-1 and associated evaporative cooling of ! ! the later, k-1, and falling of 'non-evaporated precipitating water ! ! ( which was initially formed in layer k ) and a newly-formed preci ! ! pitable water in the layer, k-1', across the base interface of the ! ! lower layer k-1. Cloud microphysics should correctly describe all ! ! of these process. In a near future, I should significantly modify ! ! this cloud microhpysics, including precipitation-induced downdraft ! ! also. ! ! ------------------------------------------------------------------ ! call conden(ps0(k),thlu(k),qtu(k),thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if if( (qlj + qij) .gt. criqc ) then exql = ( ( qlj + qij ) - criqc ) * qlj / ( qlj + qij ) exqi = ( ( qlj + qij ) - criqc ) * qij / ( qlj + qij ) ! ---------------------------------------------------------------- ! ! It is very important to re-update 'qtu' and 'thlu' at the upper ! ! interface after expelling condensate from cumulus updraft at the ! ! top interface of the layer. As mentioned above, this is a 'sink' ! ! of cumulus qt (or equivalently, a 'source' of environmentasl qt),! ! not a regular convective'detrainment'. ! ! ---------------------------------------------------------------- ! qtu(k) = qtu(k) - exql - exqi thlu(k) = thlu(k) + (xlv/cp/exns0(k))*exql + (xls/cp/exns0(k))*exqi ! ---------------------------------------------------------------- ! ! Expelled cloud condensate into the environment from the updraft. ! ! After all the calculation later, 'dwten' and 'diten' will have a ! ! unit of [ kg/kg/s ], because it is a tendency of qt. Restoration ! ! of 'dwten' and 'diten' to this correct unit through multiplying ! ! 'umf(k)*g/dp0(k)' will be performed later after finally updating ! ! 'umf' using a 'rmaxfrac' constraint near the end of this updraft ! ! buoyancy sorting loop. ! ! ---------------------------------------------------------------- ! dwten(k) = exql diten(k) = exqi else dwten(k) = 0._r8 diten(k) = 0._r8 endif ! ----------------------------------------------------------------- ! ! Update 'thvu(k)' after detraining condensate from cumulus updraft.! ! ----------------------------------------------------------------- ! call conden(ps0(k),thlu(k),qtu(k),thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvu(k) = thj * ( 1._r8 + zvir * qvj - qlj - qij ) ! ----------------------------------------------------------- ! ! Calculate updraft vertical velocity at the upper interface. ! ! In order to calculate 'wtw' at the upper interface, we use ! ! 'wtw' at the lower interface. Note 'wtw' is continuously ! ! updated as cumulus updraft rises. ! ! ----------------------------------------------------------- ! bogbot = rbuoy * ( thvu(km1) / thvebot - 1._r8 ) ! Cloud buoyancy at base interface bogtop = rbuoy * ( thvu(k) / thv0top(k) - 1._r8 ) ! Cloud buoyancy at top interface delbog = bogtop - bogbot drage = fer(k) * ( 1._r8 + rdrag ) expfac = exp(-2._r8*drage*dpe) wtwb = wtw if( drage*dpe .gt. 1.e-3_r8 ) then wtw = wtw*expfac + (delbog + (1._r8-expfac)*(bogbot + delbog/(-2._r8*drage*dpe)))/(rho0j*drage) else wtw = wtw + dpe * ( bogbot + bogtop ) / rho0j endif ! -------------------------------------------------------------- ! ! Repeat 'iter_xc' iteration loop until 'iter_xc = niter_xc'. ! ! Also theat the case even when wtw < 0 at the 'kpen' interface. ! ! -------------------------------------------------------------- ! if(wtw.gt.0._r8) then thlue = 0.5_r8 * (thlu(km1)+thlu(k)) qtue = 0.5_r8 * (qtu(km1)+qtu(k)) wue = 0.5_r8 * sqrt(max(wtwb+wtw,0._r8)) else go to 111 endif enddo ! End of 'iter_xc' loop 111 continue ! --------------------------------------------------------------------------- ! ! Add the contribution of self-detrainment to vertical variations of cumulus ! ! updraft mass flux. The reason why we are trying to include self-detrainment ! ! is as follows. In current scheme, vertical variation of updraft mass flux ! ! is not fully consistent with the vertical variation of updraft vertical w. ! ! For example, within a given layer, let's assume that cumulus w is positive ! ! at the base interface, while negative at the top interface. This means that ! ! cumulus updraft cannot reach to the top interface of the layer. However, ! ! cumulus updraft mass flux at the top interface is not zero according to the ! ! vertical tendency equation of cumulus mass flux. Ideally, cumulus updraft ! ! mass flux at the top interface should be zero for this case. In order to ! ! assures that cumulus updraft mass flux goes to zero when cumulus updraft ! ! vertical velocity goes to zero, we are imposing self-detrainment term as ! ! below by considering layer-mean cloud buoyancy and cumulus updraft vertical ! ! velocity square at the top interface. Use of auto-detrainment term will be ! ! determined by setting 'use_self_detrain=.true.' in the parameter sentence. ! ! --------------------------------------------------------------------------- ! if(use_self_detrain) then autodet = min( 0.5_r8*g*(bogbot+bogtop)/(max(wtw,0._r8)+1.e-4_r8), 0._r8 ) umf(k) = umf(k) * exp( 0.637_r8*(dpe/rho0j/g) * autodet ) end if if(umf(k).eq.0._r8) wtw = -1._r8 ! -------------------------------------- ! ! Below block is just a dignostic output ! ! -------------------------------------- ! excessu_arr(k) = excessu excess0_arr(k) = excess0 xc_arr(k) = xc aquad_arr(k) = aquad bquad_arr(k) = bquad cquad_arr(K) = cquad bogbot_arr(k) = bogbot bogtop_arr(k) = bogtop ! ------------------------------------------------------------------- ! ! 'kbup' is the upper most layer in which cloud buoyancy is positive ! ! both at the base and top interface. 'kpen' is the upper most layer ! ! up to cumulus can reach. Usually, 'kpen' is located higher than the ! ! 'kbup'. Note we initialized these by 'kbup = krel' & 'kpen = krel'. ! ! As explained before, it is possible that only 'kpen' is updated, ! ! while 'kbup' keeps its initialization value. For this case, current ! ! scheme will simply turns-off penetrative entrainment fluxes and use ! ! normal buoyancy-sorting fluxes for 'kbup <= k <= kpen-1' interfaces,! ! in order to describe shallow continental cumulus convection. ! ! ------------------------------------------------------------------- ! if( bogbot .gt. 0._r8 .and. bogtop .gt. 0._r8 ) then kbup = k end if if(wtw .le. 0._r8) then kpen = k go to 45 end if wu(k) = sqrt(wtw) if(wu(k) .gt. 100._r8) then ! write(iulog,*) 'Too strong updraft' exit_wu(i) = 1._r8 id_exit = .true. go to 333 endif ! ---------------------------------------------------------------------------- ! ! Iteration end due to 'rmaxfrac' constraint [ ***************************** ] ! ! ---------------------------------------------------------------------------- ! ! ---------------------------------------------------------------------- ! ! Calculate updraft fractional area at the upper interface and set upper ! ! limit to 'ufrc' by 'rmaxfrac'. In order to keep the consistency among ! ! ['ufrc','umf','wu (or wtw)'], if ufrc is limited by 'rmaxfrac', either ! ! 'umf' or 'wu' should be changed. Although both 'umf' and 'wu (wtw)' at ! ! the current upper interface are used for updating 'umf' & 'wu' at the ! ! next upper interface, 'umf' is a passive variable not influencing the ! ! buoyancy sorting process in contrast to 'wtw'. This is a reason why we ! ! adjusted 'umf' instead of 'wtw'. In turn we updated 'fdr' here instead ! ! of 'fer', which guarantees that all previously updated thermodynamic ! ! variables at the upper interface before applying 'rmaxfrac' constraint ! ! are already internally consistent, even though 'ufrc' is limited by ! ! 'rmaxfrac'. Thus, we don't need to go through interation loop again.If ! ! If we update 'fer' however, we should go through above iteration loop. ! ! ---------------------------------------------------------------------- ! rhos0j = ps0(k) / ( r * 0.5_r8 * ( thv0bot(k+1) + thv0top(k) ) * exns0(k) ) ufrc(k) = umf(k) / ( rhos0j * wu(k) ) if(ufrc(k) .gt. rmaxfrac) then limit_ufrc(i) = 1._r8 ufrc(k) = rmaxfrac umf(k) = rmaxfrac * rhos0j * wu(k) fdr(k) = fer(k) - log( umf(k) / umf(km1) ) / dpe endif ! ------------------------------------------------------------ ! ! Update environmental properties for at the mid-point of next ! ! upper layer for use in buoyancy sorting. ! ! ------------------------------------------------------------ ! pe = p0(k+1) dpe = dp0(k+1) exne = exn0(k+1) thvebot = thv0bot(k+1) thle = thl0(k+1) qte = qt0(k+1) ue = u0(k+1) ve = v0(k+1) end do ! End of cumulus updraft loop from the 'krel' layer to 'kpen' layer. ! ------------------------------------------------------------------------------- ! ! Up to this point, we finished all of buoyancy sorting processes from the 'krel' ! ! layer to 'kpen' layer: at the top interface of individual layers, we calculated ! ! updraft and penetrative mass fluxes [ umf(k) & emf(k) = 0 ], updraft fractional ! ! area [ ufrc(k) ], updraft vertical velocity [ wu(k) ], updraft thermodynamic ! ! variables [thlu(k),qtu(k),uu(k),vu(k),thvu(k)]. In the layer,we also calculated ! ! fractional entrainment-detrainment rate [ fer(k), fdr(k) ], and detrainment ten ! ! dency of water and ice from cumulus updraft [ dwten(k), diten(k) ]. In addition,! ! we updated and identified 'krel' and 'kpen' layer index, if any. In the 'kpen' ! ! layer, we calculated everything mentioned above except the 'wu(k)' and 'ufrc(k)'! ! since a real value of updraft vertical velocity is not defined at the kpen top ! ! interface (note 'ufrc' at the top interface of layer is calculated from 'umf(k)'! ! and 'wu(k)'). As mentioned before, special treatment is required when 'kbup' is ! ! not updated and so 'kbup = krel'. ! ! ------------------------------------------------------------------------------- ! ! ------------------------------------------------------------------------------ ! ! During the 'iter_scaleh' iteration loop, non-physical ( with non-zero values ) ! ! values can remain in the variable arrays above (also 'including' in case of wu ! ! and ufrc at the top interface) the 'kpen' layer. This can happen when the kpen ! ! layer index identified from the 'iter_scaleh = 1' iteration loop is located at ! ! above the kpen layer index identified from 'iter_scaleh = 3' iteration loop. ! ! Thus, in the following calculations, we should only use the values in each ! ! variables only up to finally identified 'kpen' layer & 'kpen' interface except ! ! 'wu' and 'ufrc' at the top interface of 'kpen' layer. Note that in order to ! ! prevent any problems due to these non-physical values, I re-initialized the ! ! values of [ umf(kpen:mkx), emf(kpen:mkx), dwten(kpen+1:mkx), diten(kpen+1:mkx),! ! fer(kpen:mkx), fdr(kpen+1:mkx), ufrc(kpen:mkx) ] to be zero after 'iter_scaleh'! ! do loop. ! ! ------------------------------------------------------------------------------ ! 45 continue ! ----------------------------- ! ! Set fer(kpen) to zero or not. ! ! ----------------------------- ! if( set_zeroferkpen ) then thlu(kpen) = thlu(kpen-1) qtu(kpen) = qtu(kpen-1) call conden(ps0(kpen),thlu(kpen),qtu(kpen),thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if if( (qlj + qij) .gt. criqc ) then exql = ( ( qlj + qij ) - criqc ) * qlj / ( qlj + qij ) exqi = ( ( qlj + qij ) - criqc ) * qij / ( qlj + qij ) qtu(kpen) = qtu(kpen) - exql - exqi thlu(kpen) = thlu(kpen) + (xlv/cp/exns0(kpen))*exql + (xls/cp/exns0(kpen))*exqi endif call conden(ps0(kpen),thlu(kpen),qtu(kpen),thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thvu(kpen) = thj * ( 1._r8 + zvir * qvj - qlj - qij ) bogbot = rbuoy * ( thvu(kpen-1)/thv0bot(kpen) - 1._r8 ) bogtop = rbuoy * ( thvu(kpen)/thv0top(kpen) - 1._r8 ) delbog = bogtop - bogbot drage = 0._r8 fer(kpen) = 0._r8 fdr(kpen) = rei(kpen) xc_arr(kpen) = 0._r8 bogbot_arr(kpen) = bogbot bogtop_arr(kpen) = bogtop endif ! ------------------------------------------------------------------------------ ! ! Calculate 'ppen( < 0 )', updarft penetrative distance from the lower interface ! ! of 'kpen' layer. Note that bogbot & bogtop at the 'kpen' layer either when fer ! ! is zero or non-zero was already calculated above. ! ! It seems that below qudarature solving formula is valid only when bogbot < 0. ! ! Below solving equation is clearly wrong ! I should revise this ! ! ! ------------------------------------------------------------------------------ ! if(drage.eq.0._r8) then aquad = ( bogtop - bogbot ) / ( ps0(kpen) - ps0(kpen-1) ) bquad = 2._r8 * bogbot cquad = -wu(kpen-1)**2 * rho0j call roots(aquad,bquad,cquad,xc1,xc2,status) if( status .eq. 0 ) then if( xc1 .le. 0._r8 .and. xc2 .le. 0._r8 ) then ppen = max( xc1, xc2 ) ppen = min( 0._r8,max( -dp0(kpen), ppen ) ) elseif( xc1 .gt. 0._r8 .and. xc2 .gt. 0._r8 ) then ppen = -dp0(kpen) write(iulog,*) 'Warning : UW-Cumulus penetrates upto kpen interface' else ppen = min( xc1, xc2 ) ppen = min( 0._r8,max( -dp0(kpen), ppen ) ) endif else ppen = -dp0(kpen) write(iulog,*) 'Warning : UW-Cumulus penetrates upto kpen interface' endif else ppen = compute_ppen(wtwb,drage,bogbot,bogtop,rho0j,dp0(kpen)) endif if( ppen.eq.-dp0(kpen).or.ppen.eq.0._r8 ) limit_ppen(i) = 1._r8 ! ----------------------------------------------------------------- ! ! Re-calculate the amount of expelled condensate from cloud updraft ! ! at the cumulus top. This is necessary for refined calculations of ! ! bulk cloud microphysics at the cumulus top. Note that ppen < 0._r8 ! ! In the below, I explicitly calculate 'thlu_top' & 'qtu_top' by ! ! using non-zero 'fer(kpen)'. ! ! ----------------------------------------------------------------- ! if( fer(kpen)*(-ppen) .lt. 1.e-4_r8 ) then thlu_top = thlu(kpen-1) + & ( thl0(kpen) + ssthl0(kpen) * (-ppen) / 2._r8 - thlu(kpen-1) ) * fer(kpen) * (-ppen) qtu_top = qtu(kpen-1) + & ( qt0(kpen) + ssqt0(kpen) * (-ppen) / 2._r8 - qtu(kpen-1) ) * fer(kpen) * (-ppen) else thlu_top = ( thl0(kpen) + ssthl0(kpen) / fer(kpen) - ssthl0(kpen) * (-ppen) / 2._r8 ) - & ( thl0(kpen) + ssthl0(kpen) * (-ppen) / 2._r8 - thlu(kpen-1) + ssthl0(kpen) / fer(kpen) ) * & exp(-fer(kpen) * (-ppen)) qtu_top = ( qt0(kpen) + ssqt0(kpen) / fer(kpen) - ssqt0(kpen) * (-ppen) / 2._r8 ) - & ( qt0(kpen) + ssqt0(kpen) * (-ppen) / 2._r8 - qtu(kpen-1) + ssqt0(kpen) / fer(kpen) ) * & exp(-fer(kpen) * (-ppen)) end if call conden(ps0(kpen-1)+ppen,thlu_top,qtu_top,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if exntop = ((ps0(kpen-1)+ppen)/p00)**rovcp if( (qlj + qij) .gt. criqc ) then dwten(kpen) = ( ( qlj + qij ) - criqc ) * qlj / ( qlj + qij ) diten(kpen) = ( ( qlj + qij ) - criqc ) * qij / ( qlj + qij ) qtu_top = qtu_top - dwten(kpen) - diten(kpen) thlu_top = thlu_top + (xlv/cp/exntop)*dwten(kpen) + (xls/cp/exntop)*diten(kpen) else dwten(kpen) = 0._r8 diten(kpen) = 0._r8 endif ! ----------------------------------------------------------------------- ! ! Calculate cumulus scale height as the top height that cumulus can reach.! ! ----------------------------------------------------------------------- ! rhos0j = ps0(kpen-1)/(r*0.5_r8*(thv0bot(kpen)+thv0top(kpen-1))*exns0(kpen-1)) cush = zs0(kpen-1) - ppen/rhos0j/g scaleh = cush end do ! End of 'iter_scaleh' loop. ! -------------------------------------------------------------------- ! ! The 'shallowCu' is logical identifier saying whether cumulus updraft ! ! overcome the buoyancy barrier just above the PBL top. If it is true, ! ! cumulus did not overcome the barrier - this is a shallow convection ! ! with negative cloud buoyancy, mimicking shallow continental cumulus ! ! convection. Depending on 'shallowCu' parameter, treatment of heat & ! ! moisture fluxes at the entraining interfaces, 'kbup <= k < kpen - 1' ! ! will be set up in a different ways, as will be shown later. ! ! -------------------------------------------------------------------- ! if( kbup.eq.krel ) then shallowCu =.true. limit_shcu(i) = 1._r8 else shallowCu =.false. limit_shcu(i) = 0._r8 endif ! ------------------------------------------------------------------ ! ! Filtering of unerasonable cumulus adjustment here. This is a very ! ! important process which should be done cautiously. Various ways of ! ! filtering are possible depending on cases mainly using the indices ! ! of key layers - 'klcl','kinv','krel','klfc','kbup','kpen'. At this ! ! stage, the followings are all possible : 'kinv >= 2', 'klcl >= 1', ! ! 'krel >= kinv', 'kbup >= krel', 'kpen >= krel'. I must design this ! ! filtering very cautiously, in such that none of realistic cumulus ! ! convection is arbitrarily turned-off. Potentially, I might turn-off! ! cumulus convection if layer-mean 'ql > 0' in the 'kinv-1' layer,in ! ! order to suppress cumulus convection growing, based at the Sc top. ! ! This is one of potential future modifications. Note that ppen < 0. ! ! ------------------------------------------------------------------ ! cldhgt = ps0(kpen-1) + ppen if( shallowCu ) then ! write(iulog,*) 'shallowCu - did not overcome initial buoyancy barrier' exit_cufilter(i) = 1._r8 id_exit = .true. go to 333 end if ! Limit 'additional shallow cumulus' for DYCOMS simulation. ! if( cldhgt.ge.88000._r8 ) then ! id_exit = .true. ! go to 333 ! end if ! ------------------------------------------------------------------------------ ! ! Re-initializing some key variables above the 'kpen' layer in order to suppress ! ! the influence of non-physical values above 'kpen', in association with the use ! ! of 'iter_scaleh' loop. Note that umf, emf, ufrc are defined at the interfaces ! ! (0:mkx), while 'dwten','diten', 'fer', 'fdr' are defined at layer mid-points. ! ! Initialization of 'fer' and 'fdr' is for correct writing purpose of diagnostic ! ! output. Note that we set umf(kpen)=emf(kpen)=ufrc(kpen)=0, in consistent with ! ! wtw < 0 at the top interface of 'kpen' layer. However, we still have non-zero ! ! expelled cloud condensate in the 'kpen' layer. ! ! ------------------------------------------------------------------------------ ! umf(kpen:mkx) = 0._r8 emf(kpen:mkx) = 0._r8 ufrc(kpen:mkx) = 0._r8 dwten(kpen+1:mkx) = 0._r8 diten(kpen+1:mkx) = 0._r8 fer(kpen+1:mkx) = 0._r8 fdr(kpen+1:mkx) = 0._r8 ! fer(kpen) = 0._r8 ! fdr(kpen) = rei(kpen) ! ------------------------------------------------------------------------ ! ! Calculate downward penetrative entrainment mass flux, 'emf(k) < 0', and ! ! thermodynamic properties of penetratively entrained airs at entraining ! ! interfaces. emf(k) is defined from the top interface of the layer kbup ! ! to the bottom interface of the layer 'kpen'. Note even when kbup = krel,! ! i.e.,even when 'kbup' was not updated in the above buoyancy sorting do ! ! loop (i.e., 'kbup' remains as the initialization value), below do loop ! ! of penetrative entrainment flux can be performed without any conceptual ! ! or logical problems, because we have already computed all the variables ! ! necessary for performing below penetrative entrainment block. ! ! In the below 'do' loop, 'k' is an interface index at which non-zero 'emf'! ! (penetrative entrainment mass flux) is calculated. Since cumulus updraft ! ! is negatively buoyant in the layers between the top interface of 'kbup' ! ! layer (interface index, kbup) and the top interface of 'kpen' layer, the ! ! fractional lateral entrainment, fer(k) within these layers will be close ! ! to zero - so it is likely that only strong lateral detrainment occurs in ! ! thses layers. Under this situation,we can easily calculate the amount of ! ! detrainment cumulus air into these negatively buoyanct layers by simply ! ! comparing cumulus updraft mass fluxes between the base and top interface ! ! of each layer: emf(k) = emf(k-1)*exp(-fdr(k)*dp0(k)) ! ! ~ emf(k-1)*(1-rei(k)*dp0(k)) ! ! emf(k-1)-emf(k) ~ emf(k-1)*rei(k)*dp0(k) ! ! Current code assumes that about 'rpen~10' times of these detrained mass ! ! are penetratively re-entrained down into the 'k-1' interface. And all of ! ! these detrained masses are finally dumped down into the top interface of ! ! 'kbup' layer. Thus, the amount of penetratively entrained air across the ! ! top interface of 'kbup' layer with 'rpen~10' becomes too large. ! ! Note that this penetrative entrainment part can be completely turned-off ! ! and we can simply use normal buoyancy-sorting involved turbulent fluxes ! ! by modifying 'penetrative entrainment fluxes' part below. ! ! ------------------------------------------------------------------------ ! ! -----------------------------------------------------------------------! ! Calculate entrainment mass flux and conservative scalars of entraining ! ! free air at interfaces of 'kbup <= k < kpen - 1' ! ! ---------------------------------------------------------------------- ! do k = 0, mkx thlu_emf(k) = thlu(k) qtu_emf(k) = qtu(k) uu_emf(k) = uu(k) vu_emf(k) = vu(k) end do do k = kpen - 1, kbup, -1 ! Here, 'k' is an interface index at which ! penetrative entrainment fluxes are calculated. rhos0j = ps0(k) / ( r * 0.5_r8 * ( thv0bot(k+1) + thv0top(k) ) * exns0(k) ) if( k .eq. kpen - 1 ) then ! ------------------------------------------------------------------------ ! ! Note that 'ppen' has already been calculated in the above 'iter_scaleh' ! ! loop assuming zero lateral entrainmentin the layer 'kpen'. ! ! ------------------------------------------------------------------------ ! ! -------------------------------------------------------------------- ! ! Calculate returning mass flux, emf ( < 0 ) ! ! Current penetrative entrainment rate with 'rpen~10' is too large and ! ! future refinement is necessary including the definition of 'thl','qt'! ! of penetratively entrained air. Penetratively entrained airs across ! ! the 'kpen-1' interface is assumed to have the properties of the base ! ! interface of 'kpen' layer. Note that 'emf ~ - umf/ufrc = - w * rho'. ! ! Thus, below limit sets an upper limit of |emf| to be ~ 10cm/s, which ! ! is very loose constraint. Here, I used more restricted constraint on ! ! the limit of emf, assuming 'emf' cannot exceed a net mass within the ! ! layer above the interface. Similar to the case of warming and drying ! ! due to cumulus updraft induced compensating subsidence, penetrative ! ! entrainment induces compensating upwelling - in order to prevent ! ! numerical instability in association with compensating upwelling, we ! ! should similarily limit the amount of penetrative entrainment at the ! ! interface by the amount of masses within the layer just above the ! ! penetratively entraining interface. ! ! -------------------------------------------------------------------- ! if((umf(k)*ppen*rei(kpen)*rpen).lt.-0.1*rhos0j) limit_emf(i) = 1._r8 if((umf(k)*ppen*rei(kpen)*rpen).lt.-0.9*dp0(kpen)/g/dt) limit_emf(i) = 1._r8 emf(k) = max(max(umf(k)*ppen*rei(kpen)*rpen, -0.1_r8*rhos0j), -0.9_r8*dp0(kpen)/g/dt) thlu_emf(k) = thl0(kpen) + ssthl0(kpen) * ( ps0(k) - p0(kpen) ) qtu_emf(k) = qt0(kpen) + ssqt0(kpen) * ( ps0(k) - p0(kpen) ) uu_emf(k) = u0(kpen) + ssu0(kpen) * ( ps0(k) - p0(kpen) ) vu_emf(k) = v0(kpen) + ssv0(kpen) * ( ps0(k) - p0(kpen) ) else ! if(k.lt.kpen-1). ! --------------------------------------------------------------------------- ! ! Note we are coming down from the higher interfaces to the lower interfaces. ! ! Also note that 'emf < 0'. So, below operation is a summing not subtracting. ! ! In order to ensure numerical stability, I imposed a modified correct limit ! ! of '-0.9*dp0(k+1)/g/dt' on emf(k). ! ! --------------------------------------------------------------------------- ! if((emf(k+1)-umf(k)*dp0(k+1)*rei(k+1)*rpen).lt.-0.1_r8*rhos0j) limit_emf(i) = 1 if((emf(k+1)-umf(k)*dp0(k+1)*rei(k+1)*rpen).lt.-0.9_r8*dp0(k+1)/g/dt) limit_emf(i) = 1 ! new code ! if((emf(k+1)-umf(k)*dp0(k+1)*rei(k+1)*rpen).lt.(emf(k+1)-0.9_r8*dp0(k+1)/g/dt)) limit_emf(i) = 1 ! old code. ! emf(k) = max(max(emf(k+1)-umf(k)*dp0(k+1)*rei(k+1)*rpen, -0.1_r8*rhos0j), emf(k+1)-0.9_r8*dp0(k+1)/g/dt) ! old code. emf(k) = max(max(emf(k+1)-umf(k)*dp0(k+1)*rei(k+1)*rpen, -0.1_r8*rhos0j), -0.9_r8*dp0(k+1)/g/dt ) ! new code if( abs(emf(k)) .gt. abs(emf(k+1)) ) then thlu_emf(k) = ( thlu_emf(k+1) * emf(k+1) + thl0(k+1) * ( emf(k) - emf(k+1) ) ) / emf(k) qtu_emf(k) = ( qtu_emf(k+1) * emf(k+1) + qt0(k+1) * ( emf(k) - emf(k+1) ) ) / emf(k) uu_emf(k) = ( uu_emf(k+1) * emf(k+1) + u0(k+1) * ( emf(k) - emf(k+1) ) ) / emf(k) vu_emf(k) = ( vu_emf(k+1) * emf(k+1) + v0(k+1) * ( emf(k) - emf(k+1) ) ) / emf(k) else thlu_emf(k) = thl0(k+1) qtu_emf(k) = qt0(k+1) uu_emf(k) = u0(k+1) vu_emf(k) = v0(k+1) endif endif ! ---------------------------------------------------------------------------- ! ! In this GCM modeling framework, all what we should do is to calculate heat ! ! and moisture fluxes at the given geometrically-fixed height interfaces - we ! ! don't need to worry about movement of material height surface in association ! ! with compensating subsidence or unwelling, in contrast to the bulk modeling. ! ! In this geometrically fixed height coordinate system, heat and moisture flux ! ! at the geometrically fixed height handle everything - a movement of material ! ! surface is implicitly treated automatically. Note that in terms of turbulent ! ! heat and moisture fluxes at model interfaces, both the cumulus updraft mass ! ! flux and penetratively entraining mass flux play the same role -both of them ! ! warms and dries the 'kbup' layer, cools and moistens the 'kpen' layer, and ! ! cools and moistens any intervening layers between 'kbup' and 'kpen' layers. ! ! It is important to note these identical roles on turbulent heat and moisture ! ! fluxes of 'umf' and 'emf'. ! ! When 'kbup' is a stratocumulus-topped PBL top interface, increase of 'rpen' ! ! is likely to strongly diffuse stratocumulus top interface, resulting in the ! ! reduction of cloud fraction. In this sense, the 'kbup' interface has a very ! ! important meaning and role : across the 'kbup' interface, strong penetrative ! ! entrainment occurs, thus any sharp gradient properties across that interface ! ! are easily diffused through strong mass exchange. Thus, an initialization of ! ! 'kbup' (and also 'kpen') should be done very cautiously as mentioned before. ! ! In order to prevent this stron diffusion for the shallow cumulus convection ! ! based at the Sc top, it seems to be good to initialize 'kbup = krel', rather ! ! that 'kbup = krel-1'. ! ! ---------------------------------------------------------------------------- ! end do !------------------------------------------------------------------ ! ! ! ! Compute turbulent heat, moisture, momentum flux at all interfaces ! ! ! !------------------------------------------------------------------ ! ! It is very important to note that in calculating turbulent fluxes ! ! below, we must not double count turbulent flux at any interefaces.! ! In the below, turbulent fluxes at the interfaces (interface index ! ! k) are calculated by the following 4 blocks in consecutive order: ! ! ! ! (1) " 0 <= k <= kinv - 1 " : PBL fluxes. ! ! From 'fluxbelowinv' using reconstructed PBL height. Currently,! ! the reconstructed PBLs are independently calculated for each ! ! individual conservative scalar variables ( qt, thl, u, v ) in ! ! each 'fluxbelowinv', instead of being uniquely calculated by ! ! using thvl. Turbulent flux at the surface is assumed to be 0. ! ! (2) " kinv <= k <= krel - 1 " : Non-buoyancy sorting fluxes ! ! Assuming cumulus mass flux and cumulus updraft thermodynamic ! ! properties (except u, v which are modified by the PGFc during ! ! upward motion) are conserved during a updraft motion from the ! ! PBL top interface to the release level. If these layers don't ! ! exist (e,g, when 'krel = kinv'), then current routine do not ! ! perform this routine automatically. So I don't need to modify ! ! anything. ! ! (3) " krel <= k <= kbup - 1 " : Buoyancy sorting fluxes ! ! From laterally entraining-detraining buoyancy sorting plumes. ! ! (4) " kbup <= k < kpen-1 " : Penetrative entrainment fluxes ! ! From penetratively entraining plumes, ! ! ! ! In case of normal situation, turbulent interfaces in each groups ! ! are mutually independent of each other. Thus double flux counting ! ! or ambiguous flux counting requiring the choice among the above 4 ! ! groups do not occur normally. However, in case that cumulus plume ! ! could not completely overcome the buoyancy barrier just above the ! ! PBL top interface and so 'kbup = krel' (.shallowCu=.true.) ( here,! ! it can be either 'kpen = krel' as the initialization, or ' kpen > ! ! krel' if cumulus updraft just penetrated over the top of release ! ! layer ). If this happens, we should be very careful in organizing ! ! the sequence of the 4 calculation routines above - note that the ! ! routine located at the later has the higher priority. Additional ! ! feature I must consider is that when 'kbup = kinv - 1' (this is a ! ! combined situation of 'kbup=krel-1' & 'krel = kinv' when I chose ! ! 'kbup=krel-1' instead of current choice of 'kbup=krel'), a strong ! ! penetrative entrainment fluxes exists at the PBL top interface, & ! ! all of these fluxes are concentrated (deposited) within the layer ! ! just below PBL top interface (i.e., 'kinv-1' layer). On the other ! ! hand, in case of 'fluxbelowinv', only the compensating subsidence ! ! effect is concentrated in the 'kinv-1' layer and 'pure' turbulent ! ! heat and moisture fluxes ( 'pure' means the fluxes not associated ! ! with compensating subsidence) are linearly distributed throughout ! ! the whole PBL. Thus different choice of the above flux groups can ! ! produce very different results. Output variable should be written ! ! consistently to the choice of computation sequences. ! ! When the case of 'kbup = krel(-1)' happens,another way to dealing ! ! with this case is to simply ' exit ' the whole cumulus convection ! ! calculation without performing any cumulus convection. We can ! ! choose this approach by specifying a condition in the 'Filtering ! ! of unreasonable cumulus adjustment' just after 'iter_scaleh'. But ! ! this seems not to be a good choice (although this choice was used ! ! previous code ), since it might arbitrary damped-out the shallow ! ! cumulus convection over the continent land, where shallow cumulus ! ! convection tends to be negatively buoyant. ! ! ----------------------------------------------------------------- ! ! --------------------------------------------------- ! ! 1. PBL fluxes : 0 <= k <= kinv - 1 ! ! All the information necessary to reconstruct PBL ! ! height are passed to 'fluxbelowinv'. ! ! --------------------------------------------------- ! xsrc = qtsrc xmean = qt0(kinv) xtop = qt0(kinv+1) + ssqt0(kinv+1) * ( ps0(kinv) - p0(kinv+1) ) xbot = qt0(kinv-1) + ssqt0(kinv-1) * ( ps0(kinv-1) - p0(kinv-1) ) call fluxbelowinv( cbmf, ps0(0:mkx), mkx, kinv, dt, xsrc, xmean, xtop, xbot, xflx ) qtflx(0:kinv-1) = xflx(0:kinv-1) xsrc = thlsrc xmean = thl0(kinv) xtop = thl0(kinv+1) + ssthl0(kinv+1) * ( ps0(kinv) - p0(kinv+1) ) xbot = thl0(kinv-1) + ssthl0(kinv-1) * ( ps0(kinv-1) - p0(kinv-1) ) call fluxbelowinv( cbmf, ps0(0:mkx), mkx, kinv, dt, xsrc, xmean, xtop, xbot, xflx ) slflx(0:kinv-1) = cp * exns0(0:kinv-1) * xflx(0:kinv-1) xsrc = usrc xmean = u0(kinv) xtop = u0(kinv+1) + ssu0(kinv+1) * ( ps0(kinv) - p0(kinv+1) ) xbot = u0(kinv-1) + ssu0(kinv-1) * ( ps0(kinv-1) - p0(kinv-1) ) call fluxbelowinv( cbmf, ps0(0:mkx), mkx, kinv, dt, xsrc, xmean, xtop, xbot, xflx ) uflx(0:kinv-1) = xflx(0:kinv-1) xsrc = vsrc xmean = v0(kinv) xtop = v0(kinv+1) + ssv0(kinv+1) * ( ps0(kinv) - p0(kinv+1) ) xbot = v0(kinv-1) + ssv0(kinv-1) * ( ps0(kinv-1) - p0(kinv-1) ) call fluxbelowinv( cbmf, ps0(0:mkx), mkx, kinv, dt, xsrc, xmean, xtop, xbot, xflx ) vflx(0:kinv-1) = xflx(0:kinv-1) ! -------------------------------------------------------------- ! ! 2. Non-buoyancy sorting fluxes : kinv <= k <= krel - 1 ! ! Note that when 'krel = kinv', below block is never executed ! ! as in a desirable, expected way ( but I must check if this ! ! is the case ). The non-buoyancy sorting fluxes are computed ! ! only when 'krel > kinv'. ! ! -------------------------------------------------------------- ! uplus = 0._r8 vplus = 0._r8 do k = kinv, krel - 1 qtflx(k) = cbmf * ( qtsrc - ( qt0(k+1) + ssqt0(k+1) * ( ps0(k) - p0(k+1) ) ) ) slflx(k) = cbmf * ( thlsrc - ( thl0(k+1) + ssthl0(k+1) * ( ps0(k) - p0(k+1) ) ) ) * cp * exns0(k) uplus = uplus + PGFc * ssu0(k) * ( ps0(k) - ps0(k-1) ) vplus = vplus + PGFc * ssv0(k) * ( ps0(k) - ps0(k-1) ) uflx(k) = cbmf * ( usrc + uplus - ( u0(k+1) + ssu0(k+1) * ( ps0(k) - p0(k+1) ) ) ) vflx(k) = cbmf * ( vsrc + vplus - ( v0(k+1) + ssv0(k+1) * ( ps0(k) - p0(k+1) ) ) ) end do ! ------------------------------------------------------------------------ ! ! 3. Buoyancy sorting fluxes : krel <= k <= kbup - 1 ! ! In case that 'kbup = krel - 1 ' ( or even in case 'kbup = krel' ), ! ! buoyancy sorting fluxes are not calculated, which is consistent, ! ! desirable feature. ! ! ------------------------------------------------------------------------ ! do k = krel, kbup - 1 kp1 = k + 1 slflx(k) = cp * exns0(k) * umf(k)*(thlu(k) - (thl0(kp1) + ssthl0(kp1)*(ps0(k) - p0(kp1)))) qtflx(k) = umf(k)*(qtu(k) - (qt0(kp1) + ssqt0(kp1)*(ps0(k) - p0(kp1)))) uflx(k) = umf(k)*(uu(k) - (u0(kp1) + ssu0(kp1)*(ps0(k) - p0(kp1)))) vflx(k) = umf(k)*(vu(k) - (v0(kp1) + ssv0(kp1)*(ps0(k) - p0(kp1)))) end do ! ------------------------------------------------------------------------- ! ! 4. Penetrative entrainment fluxes : kbup <= k <= kpen - 1 ! ! The only confliction that can happen is when 'kbup = kinv-1'. For this ! ! case, turbulent flux at kinv-1 is calculated both from 'fluxbelowinv' ! ! and here as penetrative entrainment fluxes. Since penetrative flux is ! ! calculated later, flux at 'kinv - 1 ' will be that of penetrative flux.! ! However, turbulent flux calculated at 'kinv - 1' from penetrative entr.! ! is less attractable, since more reasonable turbulent flux at 'kinv-1' ! ! should be obtained from 'fluxbelowinv', by considering re-constructed ! ! inversion base height. This conflicting problem can be solved if we can! ! initialize 'kbup = krel', instead of kbup = krel - 1. This choice seems! ! to be more reasonable since it is not conflicted with 'fluxbelowinv' in! ! calculating fluxes at 'kinv - 1' ( for this case, flux at 'kinv-1' is ! ! always from 'fluxbelowinv' ), and flux at 'krel-1' is calculated from ! ! the non-buoyancy sorting flux without being competed with penetrative ! ! entrainment fluxes. Even when we use normal cumulus flux instead of ! ! penetrative entrainment fluxes at 'kbup <= k <= kpen-1' interfaces, ! ! the initialization of kbup=krel perfectly works without any conceptual ! ! confliction. Thus it seems to be much better to choose 'kbup = krel' ! ! initialization of 'kbup', which is current choice. ! ! Note that below formula uses conventional updraft cumulus fluxes for ! ! shallow cumulus which did not overcome the first buoyancy barrier above! ! PBL top while uses penetrative entrainment fluxes for the other cases ! ! 'kbup <= k <= kpen-1' interfaces. Depending on cases, however, I can ! ! selelct different choice. ! ! --------------------------------------------------------------------------------------------------- ! ! slflx(k) = cp * exns0(k) * umf(k)*(thlu(k) - (thl0(kp1) + ssthl0(kp1)*(ps0(k) - p0(kp1)))) + & ! ! cp * exns0(k) * emf(k)*(thlu_emf(k) - (thl0(k) + ssthl0(k) *(ps0(k) - p0(k)))) ! ! qtflx(k) = umf(k)*(qtu(k) - (qt0(kp1) + ssqt0(kp1)*(ps0(k) - p0(kp1)))) + & ! ! emf(k)*(qtu_emf(k) - (qt0(k) + ssqt0(k) *(ps0(k) - p0(k)))) ! ! uflx(k) = umf(k)*(uu(k) - (u0(kp1) + ssu0(kp1)*(ps0(k) - p0(kp1)))) + & ! ! emf(k)*(uu_emf(k) - (u0(k) + ssu0(k) *(ps0(k) - p0(k)))) ! ! vflx(k) = umf(k)*(vu(k) - (v0(kp1) + ssv0(kp1)*(ps0(k) - p0(kp1)))) + & ! ! emf(k)*(vu_emf(k) - (v0(k) + ssv0(k) *(ps0(k) - p0(k)))) ! ! --------------------------------------------------------------------------------------------------- ! do k = kbup, kpen - 1 kp1 = k + 1 if( shallowCu ) then slflx(k) = cp * exns0(k) * umf(k)*(thlu(k) - (thl0(kp1) + ssthl0(kp1)*(ps0(k) - p0(kp1)))) qtflx(k) = umf(k)*(qtu(k) - (qt0(kp1) + ssqt0(kp1)*(ps0(k) - p0(kp1)))) uflx(k) = umf(k)*(uu(k) - (u0(kp1) + ssu0(kp1)*(ps0(k) - p0(kp1)))) vflx(k) = umf(k)*(vu(k) - (v0(kp1) + ssv0(kp1)*(ps0(k) - p0(kp1)))) else slflx(k) = cp * exns0(k) * emf(k)*(thlu_emf(k) - (thl0(k) + ssthl0(k) *(ps0(k) - p0(k)))) qtflx(k) = emf(k)*(qtu_emf(k) - (qt0(k) + ssqt0(k) *(ps0(k) - p0(k)))) uflx(k) = emf(k)*(uu_emf(k) - (u0(k) + ssu0(k) *(ps0(k) - p0(k)))) vflx(k) = emf(k)*(vu_emf(k) - (v0(k) + ssv0(k) *(ps0(k) - p0(k)))) endif end do ! ------------------------------------------- ! ! Turn-off cumulus momentum flux as an option ! ! ------------------------------------------- ! if(.not.use_momenflx) then uflx(0:mkx) = 0._r8 vflx(0:mkx) = 0._r8 endif ! --------------------------------------------------------------------------------- ! ! Calculate net upward mass flux (uemf(k)) by summing "umf(k)"(>0) and "emf(k)"(<0) ! ! at the interfaces "kinv-1 <= k <= kpen-1". Set to zero for the other interfaces. ! ! Also, calculate net downward compensating subsidence ( comsub > 0 if compensating ! ! subsidence is downward, or if uemf is positive ) at a layer mid-point for layers ! ! 'kinv <= k <= kpen". Set to zero for the other layers. Note that 'uemf(kpen) = 0' ! ! in calculating compensating using the below formula is completely OK. ! ! --------------------------------------------------------------------------------- ! uemf(0:mkx) = 0._r8 uemf(kinv-1:krel-1) = cbmf uemf(krel:kbup-1) = umf(krel:kbup-1) uemf(kbup:kpen-1) = umf(kbup:kpen-1) + emf(kbup:kpen-1) comsub(1:mkx) = 0._r8 do k = kinv, kpen comsub(k) = 0.5_r8 * ( uemf(k) + uemf(k-1) ) end do ! ---------------------------------------------------------------------------------- ! ! Calculate condensate sink term induced by compensating subsidence in association ! ! with cumulus updraft and penetrative entrainment term. Use centered difference for ! ! layers " kinv + 1 <= k <= kpen - 1" while use upward difference for the ambiguous ! ! invesion layer, kinv. Note that "qcten_sink(k) > 0" means "qcten > 0", i.e., ! ! condensate is generated by compensating subsidence. "cldfrct(k)" is total cloud ! ! fraction retrived from the physical buffer of previous time step. ! ! Q : should I do this in the penetrative entrainment layer, kbup+1<=k<kpen-1(kpen)? ! ! I am pretty sure that this is double counting since the effects of compensting sub ! ! sidence or upwelling are already fully incorporated in the calculation of turbulent! ! heat ( slflx ) and moisture ( qtflx ) fluxes. Thus, we should not include this sink! ! tenddency term of condensate in the following equations. ! ! ---------------------------------------------------------------------------------- ! qcten_sink(:mkx) = 0._r8 qlten_sink(:mkx) = 0._r8 qiten_sink(:mkx) = 0._r8 qcten_sink(kinv) = g * comsub(kinv) * ( cldfrct(kinv) - concldfrct(kinv) ) * & ( qs0(kinv+1) - qs0(kinv) ) / ( p0(kinv) - p0(kinv+1) ) qcten_sink(kinv) = min( 0._r8, qcten_sink(kinv) ) do k = kinv + 1, kpen - 1 qcten_sink(k) = g * comsub(k) * ( cldfrct(k) - concldfrct(k) ) * & ( qs0(k+1) - qs0(k-1) ) / ( p0(k-1) - p0(k+1) ) qcten_sink(k) = min( 0._r8, qcten_sink(k) ) end do do k = kinv, kpen - 1 if( ( ql0(k) + qi0(k) ) .gt. 0._r8 ) then qlten_sink(k) = qcten_sink(k) * ql0(k) / ( ql0(k) + qi0(k) ) qiten_sink(k) = qcten_sink(k) * qi0(k) / ( ql0(k) + qi0(k) ) else qlten_sink(k) = 0._r8 qiten_sink(k) = 0._r8 end if end do ! --------------------------------------------- ! ! ! ! Calculate convective tendencies at each layer ! ! ! ! --------------------------------------------- ! ! ----------------- ! ! Momentum tendency ! ! ----------------- ! do k = 1, kpen km1 = k - 1 uten(k) = ( uflx(km1) - uflx(k) ) * g / dp0(k) vten(k) = ( vflx(km1) - vflx(k) ) * g / dp0(k) uf(k) = u0(k) + uten(k) * dt vf(k) = v0(k) + vten(k) * dt end do ! ----------------------------------------------------------------- ! ! Tendencies of thermodynamic variables. ! ! This part requires a careful treatment of bulk cloud microphysics.! ! Relocations of 'precipitable condensates' either into the surface ! ! or into the tendency of 'krel' layer will be performed just after ! ! finishing the below 'do-loop'. ! ! ----------------------------------------------------------------- ! rliq = 0._r8 rainflx = 0._r8 snowflx = 0._r8 do k = 1, kpen km1 = k - 1 ! ------------------------------------------------------------------------------ ! ! Compute 'slten', 'qtten', 'qvten', 'qlten', 'qiten', and 'sten' ! ! ! ! Key assumptions made in this 'cumulus scheme' are : ! ! 1. Cumulus updraft expels condensate into the environment at the top interface ! ! of each layer. Note that in addition to this expel process ('source' term), ! ! cumulus updraft can modify layer mean condensate through normal detrainment ! ! forcing or compensating subsidence. ! ! 2. Expelled water can be either 'sustaining' or 'precipitating' condensate. By ! ! definition, 'suataining condensate' will remain in the layer where it was ! ! formed, while 'precipitating condensate' will fall across the base of the ! ! layer where it was formed. ! ! 3. All precipitating condensates are assumed to fall into the release layer or ! ! ground as soon as it was formed without being evaporated during the falling ! ! process down to the desinated layer ( either release layer of surface ). ! ! ------------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------- ! ! 'dwten(k)','diten(k)' : Production rate of condensate within the layer k ! ! [ kg/kg/s ] by the expels of condensate from cumulus updraft. ! ! It is important to note that in terms of moisture tendency equation, this ! ! is a 'source' term of enviromental 'qt'. More importantly, these source ! ! are already counted in the turbulent heat and moisture fluxes we computed ! ! until now, assuming all the expelled condensate remain in the layer where ! ! it was formed. Thus, in calculation of 'qtten' and 'slten' below, we MUST ! ! NOT add or subtract these terms explicitly in order not to double or miss ! ! count, unless some expelled condensates fall down out of the layer. Note ! ! this falling-down process ( i.e., precipitation process ) and associated ! ! 'qtten' and 'slten' and production of surface precipitation flux will be ! ! treated later in 'zm_conv_evap' in 'convect_shallow_tend' subroutine. ! ! In below, we are converting expelled cloud condensate into correct unit. ! ! I found that below use of '0.5 * (umf(k-1) + umf(k))' causes conservation ! ! errors at some columns in global simulation. So, I returned to originals. ! ! This will cause no precipitation flux at 'kpen' layer since umf(kpen)=0. ! ! ------------------------------------------------------------------------- ! dwten(k) = dwten(k) * 0.5_r8 * ( umf(k-1) + umf(k) ) * g / dp0(k) ! [ kg/kg/s ] diten(k) = diten(k) * 0.5_r8 * ( umf(k-1) + umf(k) ) * g / dp0(k) ! [ kg/kg/s ] ! dwten(k) = dwten(k) * umf(k) * g / dp0(k) ! [ kg/kg/s ] ! diten(k) = diten(k) * umf(k) * g / dp0(k) ! [ kg/kg/s ] ! --------------------------------------------------------------------------- ! ! 'qrten(k)','qsten(k)' : Production rate of rain and snow within the layer k ! ! [ kg/kg/s ] by cumulus expels of condensates to the environment.! ! This will be falled-out of the layer where it was formed and will be dumped ! ! dumped into the release layer assuming that there is no evaporative cooling ! ! while precipitable condensate moves to the relaes level. This is reasonable ! ! assumtion if cumulus is purely vertical and so the path along which precita ! ! ble condensate falls is fully saturared. This 're-allocation' process of ! ! precipitable condensate into the release layer is fully described in this ! ! convection scheme. After that, the dumped water into the release layer will ! ! falling down across the base of release layer ( or LCL, if exact treatment ! ! is required ) and will be allowed to be evaporated in layers below release ! ! layer, and finally non-zero surface precipitation flux will be calculated. ! ! This latter process will be separately treated 'zm_conv_evap' routine. ! ! --------------------------------------------------------------------------- ! qrten(k) = frc_rasn * dwten(k) qsten(k) = frc_rasn * diten(k) ! ----------------------------------------------------------------------- ! ! 'rainflx','snowflx' : Cumulative rain and snow flux integrated from the ! ! [ kg/m2/s ] release leyer to the 'kpen' layer. Note that even ! ! though wtw(kpen) < 0 (and umf(kpen) = 0) at the top interface of 'kpen' ! ! layer, 'dwten(kpen)' and diten(kpen) were calculated after calculating ! ! explicit cloud top height. Thus below calculation of precipitation flux ! ! is correct. Note that precipitating condensates are formed only in the ! ! layers from 'krel' to 'kpen', including the two layers. ! ! ----------------------------------------------------------------------- ! rainflx = rainflx + qrten(k) * dp0(k) / g snowflx = snowflx + qsten(k) * dp0(k) / g ! -------------------------------------------------------------------- ! ! Correct understanding of the meaning of 'qc' is critically important ! ! because this is directly used in the other parts of subroutines, for ! ! checking of moisture conservations, and stratiform microhpysics, etc.! ! 'qc' is production rate of suspendable condensate within the layer k ! ! by the sink ( or expel ) of cumulus 'suspended condensate' into ! ! the environment. In terms of moisture tendency equation, this is one ! ! source of environmental qt ( or sink of cumulus qt ). In other parts ! ! of CAM, 'qc' is passed by the variable name 'dlf' in stratiform_tend ! ! ( 'qc' in 'stratiform_tend' actually includes contribution both from ! ! 'deep' & 'shallow' convection schemes). In other subroutine, this is ! ! called 'reserved liquid water tendency. ! ! Note that 'qrten(k)+qc_l = dwten(k)', 'qsten(k)+qc_i = diten(k)'. ! ! -------------------------------------------------------------------- ! qc_l(k) = ( 1. - frc_rasn ) * dwten(k) ! [ kg/kg/s ] qc_i(k) = ( 1._r8 - frc_rasn ) * diten(k) ! [ kg/kg/s ] qc(k) = qc_l(k) + qc_i(k) ! ------------------------------------------------------------------------ ! ! 'slten(k)','qtten(k)' ! ! Note that 'slflx(k)' and 'qtflx(k)' we have calculated already included ! ! all the contributions of (1) expels of condensate (dwten(k), diten(k)), ! ! (2) mass detrainment ( delta * umf * ( qtu - qt ) ), & (3) compensating ! ! subsidence ( M * dqt / dz ). Thus 'slflx(k)' and 'qtflx(k)' we computed ! ! is a hybrid turbulent flux containing one part of 'source' term - expel ! ! of condensate. In order to calculate 'slten' and 'qtten', we should add ! ! additional 'source' term, if any. If the expelled condensate falls down ! ! across the base of the layer, it will be another sink (negative source) ! ! term. Note also that we included frictional heating terms in the below ! ! calculation of 'slten'. ! ! ------------------------------------------------------------------------ ! slten(k) = ( slflx(km1) - slflx(k) ) * g / dp0(k) if( k.eq.1 ) then slten(k) = slten(k) - g / 4 / dp0(k) * ( & uflx(k)*(uf(k+1) - uf(k) + u0(k+1) - u0(k)) + & vflx(k)*(vf(k+1) - vf(k) + v0(k+1) - v0(k))) elseif( k.ge.2 .and. k.le.kpen-1 ) then slten(k) = slten(k) - g / 4 / dp0(k) * ( & uflx(k)*(uf(k+1) - uf(k) + u0(k+1) - u0(k)) + & uflx(k-1)*(uf(k) - uf(k-1) + u0(k) - u0(k-1)) + & vflx(k)*(vf(k+1) - vf(k) + v0(k+1) - v0(k)) + & vflx(k-1)*(vf(k) - vf(k-1) + v0(k) - v0(k-1))) elseif( k.eq.kpen ) then slten(k) = slten(k) - g / 4 / dp0(k) * ( & uflx(k-1)*(uf(k) - uf(k-1) + u0(k) - u0(k-1)) + & vflx(k-1)*(vf(k) - vf(k-1) + v0(k) - v0(k-1))) endif qtten(k) = ( qtflx(km1) - qtflx(k) ) * g / dp0(k) ! ------------------------------------------------------------------------- ! ! 'qlten(k)','qiten(k)','qvten(k)' ! ! If I want to include 'qlten_sink(k)' and 'qiten_sink(k)' computed above ! ! I can simply add this term in the below equation of qlten(k) & qiten(k). ! ! If either of 'ql' or 'qi' at the next time step is negative, force them ! ! to be positive, and calculate qvten(k) accordingly, in such a way that ! ! it conserves total moisture. If qv(k) at the next time step is negative, ! ! set a minimum value on qv0(k) at the next time step and modify qlten(k) ! ! and qiten(k), such that total moisture is conserved. ! ! ------------------------------------------------------------------------- ! qlten(k) = dwten(k) + ( qtten(k) - dwten(k) - diten(k) ) * ( ql0(k) / qt0(k) ) qiten(k) = diten(k) + ( qtten(k) - dwten(k) - diten(k) ) * ( qi0(k) / qt0(k) ) qvten(k) = qtten(k) - qlten(k) - qiten(k) ! ------------------------------------ ! !'sten(k) : Dry static energy tendency ! ! ------------------------------------ ! sten(k) = slten(k) + xlv * qlten(k) + xls * qiten(k) ! -------------------------------------------------------------------------- ! ! 'rliq' : Verticall-integrated 'suspended cloud condensate' ! ! [m/s] This is so called 'reserved liquid water' in other subroutines ! ! of CAM3, since the contribution of this term should not be included into ! ! the tendency of each layer or surface flux (precip) within this cumulus ! ! scheme. The adding of this term to the layer tendency will be done inthe ! ! 'stratiform_tend', just after performing sediment process there. ! ! The main problem of these rather going-back-and-forth and stupid-seeming ! ! approach is that the sediment process of suspendened condensate will not ! ! be treated at all in the 'stratiform_tend'. ! ! Note that 'precip' [m/s] is vertically-integrated total 'rain+snow' formed ! ! from the cumulus updraft. Important : in the below, 1000 is rhoh2o ( water ! ! density ) [ kg/m^3 ] used for unit conversion from [ kg/m^2/s ] to [ m/s ] ! ! for use in stratiform.F90. ! ! -------------------------------------------------------------------------- ! rliq = rliq + qc(k) * dp0(k) / g / 1000._r8 ! [ m/s ] end do precip = rainflx + snowflx ! [ kg/m2/s ] snow = snowflx ! [ kg/m2/s ] ! ---------------------------------------------------------------- ! ! Now treats the 'evaporation' and 'melting' of rain ( qrten ) and ! ! snow ( qsten ) during falling process. Below algorithms are from ! ! 'zm_conv_evap' but with some modification, which allows separate ! ! treatment of 'rain' and 'snow' condensates. Note that I included ! ! the evaporation dynamics into the convection scheme for complete ! ! development of cumulus scheme especially in association with the ! ! implicit CIN closure. In compatible with this internal treatment ! ! of evaporation, I should modify 'convect_shallow', in such that ! ! 'zm_conv_evap' is not performed when I choose UW PBL-Cu schemes. ! ! ---------------------------------------------------------------- ! evpint_rain = 0._r8 evpint_snow = 0._r8 flxrain(0:mkx) = 0._r8 flxsnow(0:mkx) = 0._r8 ntraprd(:mkx) = 0._r8 ntsnprd(:mkx) = 0._r8 do k = mkx, 1, -1 ! 'k' is a layer index : 'mkx'('1') is the top ('bottom') layer ! ----------------------------------------------------------------------------- ! ! flxsntm [kg/m2/s] : Downward snow flux at the top of each layer after melting.! ! snowmlt [kg/kg/s] : Snow melting tendency. ! ! Below allows melting of snow when it goes down into the warm layer below. ! ! ----------------------------------------------------------------------------- ! if( t0(k).gt.273.16_r8 ) then snowmlt = flxsnow(k) * g / dp0(k) else snowmlt = 0._r8 endif ! ----------------------------------------------------------------- ! ! Evaporation rate of 'rain' and 'snow' in the layer k, [ kg/kg/s ] ! ! where 'rain' and 'snow' are coming down from the upper layers. ! ! I used the same evaporative efficiency both for 'rain' and 'snow'.! ! Note that evaporation is not allowed in the layers 'k >= krel' by ! ! assuming that inside of cumulus cloud, across which precipitation ! ! is falling down, is fully saturated. ! ! The asumptions in association with the 'evplimit_rain(snow)' are ! ! 1. Do not allow evaporation to supersate the layer ! ! 2. Do not evaporate more than the flux falling into the layer ! ! 3. Total evaporation cannot exceed the input total surface flux ! ! ----------------------------------------------------------------- ! status = qsat(t0(k),p0(k),es(1),qs(1),gam(1), 1) subsat = max( ( 1._r8 - qv0(k)/qs(1) ), 0._r8 ) if( noevap_krelkpen ) then if( k.ge.krel ) subsat = 0._r8 endif ! Sungsu ! Potentially 'evprain' can contain 'snowmlt' as below as in the unified scheme ! evprain = kevp*(1._r8-cldfrct(k))*subsat*sqrt(flxrain(k)+snowmlt*dp0(k)/g) ! Alternative evprain = kevp*(1._r8-cldfrct(k))*subsat*sqrt(flxrain(k)) evpsnow = kevp*(1._r8-cldfrct(k))*subsat*sqrt(max(flxsnow(k)-snowmlt*dp0(k)/g,0._r8)) evplimit_rain = max( 0._r8, ( qs(1) - qv0(k) ) / dt ) evplimit_rain = min( evplimit_rain, flxrain(k) * g /dp0(k) ) evplimit_rain = min( evplimit_rain, ( rainflx - evpint_rain ) * g / dp0(k) ) evprain = min( evplimit_rain, evprain ) evplimit_snow = max( 0._r8, ( qs(1) - qv0(k) ) / dt ) evplimit_snow = min( evplimit_snow, max(flxsnow(k)-snowmlt*dp0(k)/g ,0._r8) * g /dp0(k) ) evplimit_snow = min( evplimit_snow, ( snowflx - evpint_snow ) * g / dp0(k) ) evpsnow = min( evplimit_snow, evpsnow ) ! ------------------------------------------------------------- ! ! Vertically-integrated evaporative fluxes of 'rain' and 'snow' ! ! ------------------------------------------------------------- ! evpint_rain = evpint_rain + evprain * dp0(k) / g evpint_snow = evpint_snow + evpsnow * dp0(k) / g ! -------------------------------------------------------------- ! ! Net 'rain' and 'snow' production rate in the layer [ kg/kg/s ] ! ! -------------------------------------------------------------- ! ntraprd(k) = qrten(k) - evprain + snowmlt ntsnprd(k) = qsten(k) - evpsnow - snowmlt ! -------------------------------------------------------------------------------- ! ! Downward fluxes of 'rain' and 'snow' fluxes at the base of the layer [ kg/m2/s ] ! ! Note that layer index increases with height. ! ! -------------------------------------------------------------------------------- ! flxrain(k-1) = flxrain(k) + ntraprd(k) * dp0(k) / g flxsnow(k-1) = flxsnow(k) + ntsnprd(k) * dp0(k) / g flxrain(k-1) = max( flxrain(k-1), 0._r8 ) if(flxrain(k-1).eq.0._r8) ntraprd(k) = -flxrain(k) * g / dp0(k) flxsnow(k-1) = max( flxsnow(k-1), 0._r8 ) if(flxsnow(k-1).eq.0._r8) ntsnprd(k) = -flxsnow(k) * g / dp0(k) ! ---------------------------------- ! ! Calculate thermodynamic tendencies ! ! --------------------------------------------------------------------------- ! ! Note that equivalently, we can write tendency formula of 'sten' and 'slten' ! ! by 'sten(k) = sten(k) - xlv*evprain - xls*evpsnow - (xls-xlv)*snowmlt' & ! ! 'slten(k) = sten(k) - xlv*qlten(k) - xls*qiten(k)'. ! ! The above formula is equivalent to the below formula. However below formula ! ! is preferred since we have already imposed explicit constraint on 'ntraprd' ! ! and 'ntsnprd' in case that flxrain(k-1) < 0 & flxsnow(k-1) < 0._r8 ! ! Note : In future, I can elborate the limiting of 'qlten','qvten','qiten' ! ! such that that energy and moisture conservation error is completely ! ! suppressed. ! ! --------------------------------------------------------------------------- ! qlten(k) = max( qlten(k) - qrten(k), ( 0.e-16_r8 - ql0(k) ) / dt ) qiten(k) = max( qiten(k) - qsten(k), ( 0.e-16_r8 - qi0(k) ) / dt ) qvten(k) = max( qvten(k) + evprain + evpsnow, ( 2.e-12_r8 - qv0(k) ) / dt ) qtten(k) = qlten(k) + qiten(k) + qvten(k) if(qvten(k).eq.((2.e-12_r8-qv0(k))/dt).or.qlten(k).eq.(-ql0(k)/dt) & .or.qiten(k).eq.(-qi0(k)/dt)) then limit_negcon(i) = 1._r8 end if slten(k) = slten(k) + xlv * ntraprd(k) + xls * ntsnprd(k) sten(k) = slten(k) + xlv * qlten(k) + xls * qiten(k) end do ! ------------------------------------------------------------- ! ! Calculate final surface flux of precipitation, rain, and snow ! ! Convert unit to [m/s] for use in 'check_energy_chng'. ! ! ------------------------------------------------------------- ! precip = ( flxrain(0) + flxsnow(0) ) / 1000._r8 snow = flxsnow(0) / 1000._r8 ! --------------------------------------------------------------------------- ! ! Until now, all the calculations are done completely in this shallow cumulus ! ! scheme. If you want to use this cumulus scheme other than CAM3, then do not ! ! perform below block. However, for compatible use with the other subroutines ! ! in CAM3, I should subtract the effect of 'qc(k)' ('rliq') from the tendency ! ! equation in each layer, since this effect will be separately added later in ! ! in 'stratiform_tend' just after performing sediment process there. In order ! ! to be consistent with 'stratiform_tend', just subtract qc(k) from tendency ! ! equation of each layer, but do not add it to the 'precip'. Apprently, this ! ! will violate energy and moisture conservations. However, when performing ! ! conservation check in 'tphysbc.F90' just after 'convect_shallow_tend', we ! ! will add 'qc(k)' ( rliq ) to the surface flux term just for the purpose of ! ! passing the energy-moisture conservation check. Explicit adding-back of 'qc'! ! to the individual layer tendency equation will be done in 'stratiform_tend' ! ! after performing sediment process there. Simply speaking, in 'tphysbc' just ! ! after 'convect_shallow_tend', we will dump 'rliq' into surface as a 'rain' ! ! in order to satisfy energy and moisture conservation, and in the following ! ! 'stratiform_tend', we will restore it back to 'qlten(k)' ( 'ice' will go to ! ! 'water' there) from surface precipitation. This is a funny but conceptually ! ! entertaining procedure. One concern I have for this complex process is that ! ! output-writed stratiform precipitation amount will be underestimated due to ! ! arbitrary subtracting of 'rliq' in stratiform_tend, where ! ! ' prec_str = prec_sed + prec_pcw - rliq' and 'rliq' is not real but fake. ! ! However, as shown in 'srfxfer.F90', large scale precipitation amount (PRECL)! ! that is writed-output is corrected written since in 'srfxfer.F90', PRECL = ! ! 'prec_sed + prec_pcw', without including 'rliq'. So current code is correct.! ! Note also in 'srfxfer.F90', convective precipitation amount is 'PRECC = ! ! prec_zmc(i) + prec_cmf(i)' which is also correct. ! ! --------------------------------------------------------------------------- ! do k = 1, kpen qtten(k) = qtten(k) - qc(k) qlten(k) = qlten(k) - qc_l(k) qiten(k) = qiten(k) - qc_i(k) slten(k) = slten(k) + ( xlv * qc_l(k) + xls * qc_i(k) ) ! ---------------------------------------------------------------------- ! ! Since all reserved condensates will be treated as liquid water in the ! ! 'check_energy_chng' & 'stratiform_tend' without an explicit conversion ! ! algorithm, I should consider explicitly the energy conversions between ! ! 'ice' and 'liquid' - i.e., I should convert 'ice' to 'liquid' and the ! ! necessary energy for this conversion should be subtracted from 'sten'. ! ! Without this conversion here, energy conservation error come out. Note ! ! that there should be no change of 'qvten(k)'. ! ! ---------------------------------------------------------------------- ! sten(k) = sten(k) - ( xls - xlv ) * qc_i(k) end do ! ---------------------------------------------------------------- ! ! Cumpute default diagnostic outputs ! ! Note that since 'qtu(krel-1:kpen-1)' & 'thlu(krel-1:kpen-1)' has ! ! been adjusted after detraining cloud condensate into environment ! ! during cumulus updraft motion, below calculations will exactly ! ! reproduce in-cloud properties as shown in the output analysis. ! ! ---------------------------------------------------------------- ! call conden(prel,thlu(krel-1),qtu(krel-1),thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if qcubelow = qlj + qij qlubelow = qlj qiubelow = qij rcwp = 0._r8 rlwp = 0._r8 riwp = 0._r8 ! --------------------------------------------------------------------- ! ! In the below calculations, I explicitly considered cloud base ( LCL ) ! ! and cloud top height ( ps0(kpen-1) + ppen ) ! ! ----------------------------------------------------------------------! do k = krel, kpen ! This is a layer index ! ------------------------------------------------------------------ ! ! Calculate cumulus condensate at the upper interface of each layer. ! ! Note 'ppen < 0' and at 'k=kpen' layer, I used 'thlu_top'&'qtu_top' ! ! which explicitly considered zero or non-zero 'fer(kpen)'. ! ! ------------------------------------------------------------------ ! if( k.eq.kpen ) then call conden(ps0(k-1)+ppen,thlu_top,qtu_top,thj,qvj,qlj,qij,qse,id_check,qsat) else call conden(ps0(k),thlu(k),qtu(k),thj,qvj,qlj,qij,qse,id_check,qsat) endif if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if ! ---------------------------------------------------------------- ! ! Calculate in-cloud mean LWC ( qlu(k) ), IWC ( qiu(k) ), & layer ! ! mean cumulus fraction ( cufrc(k) ), vertically-integrated layer ! ! mean LWP and IWP. Expel some of in-cloud condensate at the upper ! ! interface if it is largr than criqc. Note cumulus cloud fraction ! ! is assumed to be twice of core updraft fractional area. Thus LWP ! ! and IWP will be twice of actual value coming from our scheme. ! ! ---------------------------------------------------------------- ! qcu(k) = 0.5_r8 * ( qcubelow + qlj + qij ) qlu(k) = 0.5_r8 * ( qlubelow + qlj ) qiu(k) = 0.5_r8 * ( qiubelow + qij ) cufrc(k) = ( ufrc(k-1) + ufrc(k) ) if( k.eq.krel ) then cufrc(k) = ( ufrclcl + ufrc(k) )*( prel - ps0(k) )/(ps0(k-1)-ps0(k)) else if( k.eq.kpen ) then cufrc(k) = ( ufrc(k-1) + 0._r8 )*( -ppen ) /(ps0(k-1)-ps0(k)) if( (qlj + qij) .gt. criqc ) then qcu(k) = 0.5_r8 * ( qcubelow + criqc ) qlu(k) = 0.5_r8 * ( qlubelow + criqc * qlj / ( qlj + qij ) ) qiu(k) = 0.5_r8 * ( qiubelow + criqc * qij / ( qlj + qij ) ) endif endif rcwp = rcwp + ( qlu(k) + qiu(k) ) * ( ps0(k-1) - ps0(k) ) / g * cufrc(k) rlwp = rlwp + qlu(k) * ( ps0(k-1) - ps0(k) ) / g * cufrc(k) riwp = riwp + qiu(k) * ( ps0(k-1) - ps0(k) ) / g * cufrc(k) qcubelow = qlj + qij qlubelow = qlj qiubelow = qij end do ! ------------------------------------ ! ! Cloud top and base interface indices ! ! ------------------------------------ ! cnt = real(kpen, r8) cnb = real(krel - 1, r8) ! ------------------------------------------------------------------------- ! ! End of formal calculation. Below blocks are for implicit CIN calculations ! ! with re-initialization and save variables at iter_cin = 1._r8 ! ! ------------------------------------------------------------------------- ! ! --------------------------------------------------------------- ! ! Adjust the original input profiles for implicit CIN calculation ! ! --------------------------------------------------------------- ! if(iter .ne. iter_cin) then ! ------------------------------------------------------------------- ! ! Save the output from "iter_cin = 1" ! ! These output will be writed-out if "iter_cin = 1" was not performed ! ! for some reasons. ! ! ------------------------------------------------------------------- ! qv0_s(:mkx) = qv0(:mkx) + qvten(:mkx) * dt ql0_s(:mkx) = ql0(:mkx) + qlten(:mkx) * dt qi0_s(:mkx) = qi0(:mkx) + qiten(:mkx) * dt s0_s(:mkx) = s0(:mkx) + sten(:mkx) * dt u0_s(:mkx) = u0(:mkx) + uten(:mkx) * dt v0_s(:mkx) = v0(:mkx) + vten(:mkx) * dt qt0_s(:mkx) = qv0_s(:mkx) + ql0_s(:mkx) + qi0_s(:mkx) t0_s(:mkx) = t0(:mkx) + sten(:mkx) * dt / cp umf_s(0:mkx) = umf(0:mkx) qvten_s(:mkx) = qvten(:mkx) qlten_s(:mkx) = qlten(:mkx) qiten_s(:mkx) = qiten(:mkx) sten_s(:mkx) = sten(:mkx) uten_s(:mkx) = uten(:mkx) vten_s(:mkx) = vten(:mkx) qrten_s(:mkx) = qrten(:mkx) qsten_s(:mkx) = qsten(:mkx) precip_s = precip snow_s = snow cush_s = cush cufrc_s(:mkx) = cufrc(:mkx) slflx_s(0:mkx) = slflx(0:mkx) qtflx_s(0:mkx) = qtflx(0:mkx) qcu_s(:mkx) = qcu(:mkx) qlu_s(:mkx) = qlu(:mkx) qiu_s(:mkx) = qiu(:mkx) fer_s(:mkx) = fer(:mkx) fdr_s(:mkx) = fdr(:mkx) cin_s = cin cinlcl_s = cinlcl cbmf_s = cbmf rliq_s = rliq qc_s(:mkx) = qc(:mkx) cnt_s = cnt cnb_s = cnb qtten_s(:mkx) = qtten(:mkx) slten_s(:mkx) = slten(:mkx) ufrc_s(0:mkx) = ufrc(0:mkx) uflx_s(0:mkx) = uflx(0:mkx) vflx_s(0:mkx) = vflx(0:mkx) ufrcinvbase_s = ufrcinvbase ufrclcl_s = ufrclcl winvbase_s = winvbase wlcl_s = wlcl plcl_s = plcl pinv_s = ps0(kinv-1) plfc_s = plfc pbup_s = ps0(kbup) ppen_s = ps0(kpen-1)+ppen qtsrc_s = qtsrc thlsrc_s = thlsrc thvlsrc_s = thvlsrc emfkbup_s = emf(kbup) cbmflimit_s = cbmflimit tkeavg_s = tkeavg zinv_s = zs0(kinv-1) rcwp_s = rcwp rlwp_s = rlwp riwp_s = riwp wu_s(0:mkx) = wu(0:mkx) qtu_s(0:mkx) = qtu(0:mkx) thlu_s(0:mkx) = thlu(0:mkx) thvu_s(0:mkx) = thvu(0:mkx) uu_s(0:mkx) = uu(0:mkx) vu_s(0:mkx) = vu(0:mkx) qtu_emf_s(0:mkx) = qtu_emf(0:mkx) thlu_emf_s(0:mkx) = thlu_emf(0:mkx) uu_emf_s(0:mkx) = uu_emf(0:mkx) vu_emf_s(0:mkx) = vu_emf(0:mkx) uemf_s(0:mkx) = uemf(0:mkx) dwten_s(:mkx) = dwten(:mkx) diten_s(:mkx) = diten(:mkx) flxrain_s(0:mkx) = flxrain(0:mkx) flxsnow_s(0:mkx) = flxsnow(0:mkx) ntraprd_s(:mkx) = ntraprd(:mkx) ntsnprd_s(:mkx) = ntsnprd(:mkx) excessu_arr_s(:mkx) = excessu_arr(:mkx) excess0_arr_s(:mkx) = excess0_arr(:mkx) xc_arr_s(:mkx) = xc_arr(:mkx) aquad_arr_s(:mkx) = aquad_arr(:mkx) bquad_arr_s(:mkx) = bquad_arr(:mkx) cquad_arr_s(:mkx) = cquad_arr(:mkx) bogbot_arr_s(:mkx) = bogbot_arr(:mkx) bogtop_arr_s(:mkx) = bogtop_arr(:mkx) ! ----------------------------------------------------------------------------- ! ! Recalculate environmental variables for new cin calculation at "iter_cin = 2" ! ! using the updated state variables. Perform only for variables necessary for ! ! the new cin calculation. ! ! ----------------------------------------------------------------------------- ! qv0(:mkx) = qv0_s(:mkx) ql0(:mkx) = ql0_s(:mkx) qi0(:mkx) = qi0_s(:mkx) s0(:mkx) = s0_s(:mkx) t0(:mkx) = t0_s(:mkx) qt0(:mkx) = (qv0(:mkx) + ql0(:mkx) + qi0(:mkx)) thl0(:mkx) = (t0(:mkx) - xlv*ql0(:mkx)/cp - xls*qi0(:mkx)/cp)/exn0(:mkx) thvl0(:mkx) = (1._r8 + zvir*qt0(:mkx))*thl0(:mkx) ssthl0 = slope(mkx,thl0,p0) ! Dimension of ssthl0(:mkx) is implicit ssqt0 = slope(mkx,qt0 ,p0) ssu0 = slope(mkx,u0 ,p0) ssv0 = slope(mkx,v0 ,p0) do k = 1, mkx thl0bot = thl0(k) + ssthl0(k)*(ps0(k-1) - p0(k)) qt0bot = qt0(k) + ssqt0(k) *(ps0(k-1) - p0(k)) call conden(ps0(k-1),thl0bot,qt0bot,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thv0bot(k) = thj*(1._r8 + zvir*qvj - qlj - qij) thvl0bot(k) = thl0bot*(1._r8 + zvir*qt0bot) thl0top = thl0(k) + ssthl0(k)*(ps0(k) - p0(k)) qt0top = qt0(k) + ssqt0(k) *(ps0(k) - p0(k)) call conden(ps0(k),thl0top,qt0top,thj,qvj,qlj,qij,qse,id_check,qsat) if(id_check.eq.1) then exit_conden(i) = 1._r8 id_exit = .true. go to 333 end if thv0top(k) = thj*(1._r8 + zvir*qvj - qlj - qij) thvl0top(k) = thl0top*(1._r8 + zvir*qt0top) end do endif ! End of 'if(iter .ne. iter_cin)' if sentence. end do ! End of implicit CIN loop (cin_iter) ! ----------------------- ! ! Update Output Variables ! ! ----------------------- ! umf_out(i,0:mkx) = umf(0:mkx) slflx_out(i,0:mkx) = slflx(0:mkx) qtflx_out(i,0:mkx) = qtflx(0:mkx) qvten_out(i,:mkx) = qvten(:mkx) qlten_out(i,:mkx) = qlten(:mkx) qiten_out(i,:mkx) = qiten(:mkx) sten_out(i,:mkx) = sten(:mkx) uten_out(i,:mkx) = uten(:mkx) vten_out(i,:mkx) = vten(:mkx) qrten_out(i,:mkx) = qrten(:mkx) qsten_out(i,:mkx) = qsten(:mkx) precip_out(i) = precip snow_out(i) = snow cufrc_out(i,:mkx) = cufrc(:mkx) qcu_out(i,:mkx) = qcu(:mkx) qlu_out(i,:mkx) = qlu(:mkx) qiu_out(i,:mkx) = qiu(:mkx) cush_inout(i) = cush cbmf_out(i) = cbmf rliq_out(i) = rliq qc_out(i,:mkx) = qc(:mkx) cnt_out(i) = cnt cnb_out(i) = cnb ! ------------------------------------------------- ! ! Below are specific diagnostic output for detailed ! ! analysis of cumulus scheme ! ! ------------------------------------------------- ! fer_out(i,mkx:1:-1) = fer(:mkx) fdr_out(i,mkx:1:-1) = fdr(:mkx) cinh_out(i) = cin cinlclh_out(i) = cinlcl qtten_out(i,mkx:1:-1) = qtten(:mkx) slten_out(i,mkx:1:-1) = slten(:mkx) ufrc_out(i,mkx:0:-1) = ufrc(0:mkx) uflx_out(i,mkx:0:-1) = uflx(0:mkx) vflx_out(i,mkx:0:-1) = vflx(0:mkx) ufrcinvbase_out(i) = ufrcinvbase ufrclcl_out(i) = ufrclcl winvbase_out(i) = winvbase wlcl_out(i) = wlcl plcl_out(i) = plcl pinv_out(i) = ps0(kinv-1) plfc_out(i) = plfc pbup_out(i) = ps0(kbup) ppen_out(i) = ps0(kpen-1)+ppen qtsrc_out(i) = qtsrc thlsrc_out(i) = thlsrc thvlsrc_out(i) = thvlsrc emfkbup_out(i) = emf(kbup) cbmflimit_out(i) = cbmflimit tkeavg_out(i) = tkeavg zinv_out(i) = zs0(kinv-1) rcwp_out(i) = rcwp rlwp_out(i) = rlwp riwp_out(i) = riwp wu_out(i,mkx:0:-1) = wu(0:mkx) qtu_out(i,mkx:0:-1) = qtu(0:mkx) thlu_out(i,mkx:0:-1) = thlu(0:mkx) thvu_out(i,mkx:0:-1) = thvu(0:mkx) uu_out(i,mkx:0:-1) = uu(0:mkx) vu_out(i,mkx:0:-1) = vu(0:mkx) qtu_emf_out(i,mkx:0:-1) = qtu_emf(0:mkx) thlu_emf_out(i,mkx:0:-1) = thlu_emf(0:mkx) uu_emf_out(i,mkx:0:-1) = uu_emf(0:mkx) vu_emf_out(i,mkx:0:-1) = vu_emf(0:mkx) uemf_out(i,mkx:0:-1) = uemf(0:mkx) dwten_out(i,mkx:1:-1) = dwten(:mkx) diten_out(i,mkx:1:-1) = diten(:mkx) flxrain_out(i,mkx:0:-1) = flxrain(0:mkx) flxsnow_out(i,mkx:0:-1) = flxsnow(0:mkx) ntraprd_out(i,mkx:1:-1) = ntraprd(:mkx) ntsnprd_out(i,mkx:1:-1) = ntsnprd(:mkx) excessu_arr_out(i,mkx:1:-1) = excessu_arr(:mkx) excess0_arr_out(i,mkx:1:-1) = excess0_arr(:mkx) xc_arr_out(i,mkx:1:-1) = xc_arr(:mkx) aquad_arr_out(i,mkx:1:-1) = aquad_arr(:mkx) bquad_arr_out(i,mkx:1:-1) = bquad_arr(:mkx) cquad_arr_out(i,mkx:1:-1) = cquad_arr(:mkx) bogbot_arr_out(i,mkx:1:-1) = bogbot_arr(:mkx) bogtop_arr_out(i,mkx:1:-1) = bogtop_arr(:mkx) 333 if(id_exit) then ! Exit without cumulus convection exit_UWCu(i) = 1._r8 ! --------------------------------------------------------------------- ! ! Initialize output variables when cumulus convection was not performed.! ! --------------------------------------------------------------------- ! ! ---------------------------------------------------------------- ! ! Below block, with !! lines in the below are diagnostic purpose ! ! to look at values even when 333 exit mainly for SCAM simulation. ! ! When running global simulations, it is good to initialize by 0, ! ! if cumulus convection was not performed. ! ! ---------------------------------------------------------------- ! !! umf_out(i,0:mkx) = umf(0:mkx) !! cinh_out(i) = cin !! cinlclh_out(i) = cinlcl !! cbmf_out(i) = cbmf !! ufrcinvbase_out(i) = ufrcinvbase !! ufrclcl_out(i) = ufrclcl !! winvbase_out(i) = winvbase !! wlcl_out(i) = wlcl !! plcl_out(i) = plcl !! pinv_out(i) = ps0(kinv-1) !! plfc_out(i) = plfc !! qtsrc_out(i) = qtsrc !! thlsrc_out(i) = thlsrc !! thvlsrc_out(i) = thvlsrc !! cbmflimit_out(i) = cbmflimit !! tkeavg_out(i) = tkeavg !! zinv_out(i) = zs0(kinv-1) !! rcwp_out(i) = rcwp !! rlwp_out(i) = rlwp !! riwp_out(i) = riwp !! wu_out(i,mkx:0:-1) = wu(0:mkx) !! qtu_out(i,mkx:0:-1) = qtu(0:mkx) !! thlu_out(i,mkx:0:-1) = thlu(0:mkx) !! thvu_out(i,mkx:0:-1) = thvu(0:mkx) !! uu_out(i,mkx:0:-1) = uu(0:mkx) !! vu_out(i,mkx:0:-1) = vu(0:mkx) !! qtu_emf_out(i,mkx:0:-1) = qtu_emf(0:mkx) !! thlu_emf_out(i,mkx:0:-1) = thlu_emf(0:mkx) !! uu_emf_out(i,mkx:0:-1) = uu_emf(0:mkx) !! vu_emf_out(i,mkx:0:-1) = vu_emf(0:mkx) !! uemf_out(i,mkx:0:-1) = uemf(0:mkx) !! dwten_out(i,mkx:1:-1) = dwten(:mkx) !! diten_out(i,mkx:1:-1) = diten(:mkx) !! flxrain_out(i,mkx:0:-1) = flxrain(0:mkx) !! flxsnow_out(i,mkx:0:-1) = flxsnow(0:mkx) !! ntraprd_out(i,mkx:1:-1) = ntraprd(:mkx) !! ntsnprd_out(i,mkx:1:-1) = ntsnprd(:mkx) !! excessu_arr_out(i,mkx:1:-1) = excessu_arr(:mkx) !! excess0_arr_out(i,mkx:1:-1) = excess0_arr(:mkx) !! xc_arr_out(i,mkx:1:-1) = xc_arr(:mkx) !! aquad_arr_out(i,mkx:1:-1) = aquad_arr(:mkx) !! bquad_arr_out(i,mkx:1:-1) = bquad_arr(:mkx) !! cquad_arr_out(i,mkx:1:-1) = cquad_arr(:mkx) !! bogbot_arr_out(i,mkx:1:-1) = bogbot_arr(:mkx) !! bogtop_arr_out(i,mkx:1:-1) = bogtop_arr(:mkx) ! ---------------------------------------------------------- ! ! Below block is normal initialization for global simulation ! ! ---------------------------------------------------------- ! umf_out(i,0:mkx) = 0._r8 !! slflx_out(i,0:mkx) = 0._r8 qtflx_out(i,0:mkx) = 0._r8 qvten_out(i,:mkx) = 0._r8 qlten_out(i,:mkx) = 0._r8 qiten_out(i,:mkx) = 0._r8 sten_out(i,:mkx) = 0._r8 uten_out(i,:mkx) = 0._r8 vten_out(i,:mkx) = 0._r8 qrten_out(i,:mkx) = 0._r8 qsten_out(i,:mkx) = 0._r8 precip_out(i) = 0._r8 snow_out(i) = 0._r8 cufrc_out(i,:mkx) = 0._r8 qcu_out(i,:mkx) = 0._r8 qlu_out(i,:mkx) = 0._r8 qiu_out(i,:mkx) = 0._r8 cush_inout(i) = -1._r8 cbmf_out(i) = 0._r8 !! rliq_out(i) = 0._r8 qc_out(i,:mkx) = 0._r8 ! Set CLDTOP to bottom layer index and CLDBOT to top layer index in ! cloud free columns. cnt_out(i) = 1._r8 cnb_out(i) = real(mkx, r8) fer_out(i,mkx:1:-1) = 0._r8 fdr_out(i,mkx:1:-1) = 0._r8 cinh_out(i) = -1._r8 !! cinlclh_out(i) = -1._r8 !! qtten_out(i,mkx:1:-1) = 0._r8 slten_out(i,mkx:1:-1) = 0._r8 ufrc_out(i,mkx:0:-1) = 0._r8 uflx_out(i,mkx:0:-1) = 0._r8 vflx_out(i,mkx:0:-1) = 0._r8 ufrcinvbase_out(i) = 0._r8 !! ufrclcl_out(i) = 0._r8 !! winvbase_out(i) = 0._r8 !! wlcl_out(i) = 0._r8 !! plcl_out(i) = 0._r8 !! pinv_out(i) = 0._r8 !! plfc_out(i) = 0._r8 !! pbup_out(i) = 0._r8 ppen_out(i) = 0._r8 qtsrc_out(i) = 0._r8 !! thlsrc_out(i) = 0._r8 !! thvlsrc_out(i) = 0._r8 !! emfkbup_out(i) = 0._r8 cbmflimit_out(i) = 0._r8 !! tkeavg_out(i) = 0._r8 !! zinv_out(i) = 0._r8 !! rcwp_out(i) = 0._r8 !! rlwp_out(i) = 0._r8 !! riwp_out(i) = 0._r8 !! wu_out(i,mkx:0:-1) = 0._r8 !! qtu_out(i,mkx:0:-1) = 0._r8 !! thlu_out(i,mkx:0:-1) = 0._r8 !! thvu_out(i,mkx:0:-1) = 0._r8 !! uu_out(i,mkx:0:-1) = 0._r8 !! vu_out(i,mkx:0:-1) = 0._r8 !! qtu_emf_out(i,mkx:0:-1) = 0._r8 !! thlu_emf_out(i,mkx:0:-1) = 0._r8 !! uu_emf_out(i,mkx:0:-1) = 0._r8 !! vu_emf_out(i,mkx:0:-1) = 0._r8 !! uemf_out(i,mkx:0:-1) = 0._r8 !! dwten_out(i,mkx:1:-1) = 0._r8 !! diten_out(i,mkx:1:-1) = 0._r8 !! flxrain_out(i,mkx:0:-1) = 0._r8 !! flxsnow_out(i,mkx:0:-1) = 0._r8 !! ntraprd_out(i,mkx:1:-1) = 0._r8 !! ntsnprd_out(i,mkx:1:-1) = 0._r8 !! excessu_arr_out(i,mkx:1:-1) = 0._r8 !! excess0_arr_out(i,mkx:1:-1) = 0._r8 !! xc_arr_out(i,mkx:1:-1) = 0._r8 !! aquad_arr_out(i,mkx:1:-1) = 0._r8 !! bquad_arr_out(i,mkx:1:-1) = 0._r8 !! cquad_arr_out(i,mkx:1:-1) = 0._r8 !! bogbot_arr_out(i,mkx:1:-1) = 0._r8 !! bogtop_arr_out(i,mkx:1:-1) = 0._r8 !! end if end do ! end of big i loop for each column. ! ---------------------------------------- ! ! Writing main diagnostic output variables ! ! ---------------------------------------- ! call outfld('qtflx_Cu', qtflx_out(:,mkx:0:-1), mix, lchnk) call outfld('slflx_Cu', slflx_out(:,mkx:0:-1), mix, lchnk) call outfld('uflx_Cu', uflx_out, mix, lchnk) call outfld('vflx_Cu', vflx_out, mix, lchnk) call outfld('qtten_Cu', qtten_out, mix, lchnk) call outfld('slten_Cu', slten_out, mix, lchnk) call outfld('uten_Cu', uten_out(:,mkx:1:-1), mix, lchnk) call outfld('vten_Cu', vten_out(:,mkx:1:-1), mix, lchnk) call outfld('qvten_Cu', qvten_out(:,mkx:1:-1), mix, lchnk) call outfld('qlten_Cu', qlten_out(:,mkx:1:-1), mix, lchnk) call outfld('qiten_Cu', qiten_out(:,mkx:1:-1), mix, lchnk) call outfld('cbmf_Cu', cbmf_out, mix, lchnk) call outfld('ufrcinvbase_Cu', ufrcinvbase_out, mix, lchnk) call outfld('ufrclcl_Cu', ufrclcl_out, mix, lchnk) call outfld('winvbase_Cu', winvbase_out, mix, lchnk) call outfld('wlcl_Cu', wlcl_out, mix, lchnk) call outfld('plcl_Cu', plcl_out, mix, lchnk) call outfld('pinv_Cu', pinv_out, mix, lchnk) call outfld('plfc_Cu', plfc_out, mix, lchnk) call outfld('pbup_Cu', pbup_out, mix, lchnk) call outfld('ppen_Cu', ppen_out, mix, lchnk) call outfld('qtsrc_Cu', qtsrc_out, mix, lchnk) call outfld('thlsrc_Cu', thlsrc_out, mix, lchnk) call outfld('thvlsrc_Cu', thvlsrc_out, mix, lchnk) call outfld('emfkbup_Cu', emfkbup_out, mix, lchnk) call outfld('cin_Cu', cinh_out, mix, lchnk) call outfld('cinlcl_Cu', cinlclh_out, mix, lchnk) call outfld('cbmflimit_Cu', cbmflimit_out, mix, lchnk) call outfld('tkeavg_Cu', tkeavg_out, mix, lchnk) call outfld('zinv_Cu', zinv_out, mix, lchnk) call outfld('rcwp_Cu', rcwp_out, mix, lchnk) call outfld('rlwp_Cu', rlwp_out, mix, lchnk) call outfld('riwp_Cu', riwp_out, mix, lchnk) call outfld('tophgt_Cu', cush_inout, mix, lchnk) call outfld('wu_Cu', wu_out, mix, lchnk) call outfld('ufrc_Cu', ufrc_out, mix, lchnk) call outfld('qtu_Cu', qtu_out, mix, lchnk) call outfld('thlu_Cu', thlu_out, mix, lchnk) call outfld('thvu_Cu', thvu_out, mix, lchnk) call outfld('uu_Cu', uu_out, mix, lchnk) call outfld('vu_Cu', vu_out, mix, lchnk) call outfld('qtu_emf_Cu', qtu_emf_out, mix, lchnk) call outfld('thlu_emf_Cu', thlu_emf_out, mix, lchnk) call outfld('uu_emf_Cu', uu_emf_out, mix, lchnk) call outfld('vu_emf_Cu', vu_emf_out, mix, lchnk) call outfld('umf_Cu', umf_out(:,mkx:0:-1), mix, lchnk) call outfld('uemf_Cu', uemf_out, mix, lchnk) call outfld('qcu_Cu', qcu_out(:,mkx:1:-1), mix, lchnk) call outfld('qlu_Cu', qlu_out(:,mkx:1:-1), mix, lchnk) call outfld('qiu_Cu', qiu_out(:,mkx:1:-1), mix, lchnk) call outfld('cufrc_Cu', cufrc_out(:,mkx:1:-1), mix, lchnk) call outfld('fer_Cu', fer_out, mix, lchnk) call outfld('fdr_Cu', fdr_out, mix, lchnk) call outfld('dwten_Cu', dwten_out, mix, lchnk) call outfld('diten_Cu', diten_out, mix, lchnk) call outfld('qrten_Cu', qrten_out(:,mkx:1:-1), mix, lchnk) call outfld('qsten_Cu', qsten_out(:,mkx:1:-1), mix, lchnk) call outfld('flxrain_Cu', flxrain_out, mix, lchnk) call outfld('flxsnow_Cu', flxsnow_out, mix, lchnk) call outfld('ntraprd_Cu', ntraprd_out, mix, lchnk) call outfld('ntsnprd_Cu', ntsnprd_out, mix, lchnk) call outfld('excessu_Cu', excessu_arr_out, mix, lchnk) call outfld('excess0_Cu', excess0_arr_out, mix, lchnk) call outfld('xc_Cu', xc_arr_out, mix, lchnk) call outfld('aquad_Cu', aquad_arr_out, mix, lchnk) call outfld('bquad_Cu', bquad_arr_out, mix, lchnk) call outfld('cquad_Cu', cquad_arr_out, mix, lchnk) call outfld('bogbot_Cu', bogbot_arr_out, mix, lchnk) call outfld('bogtop_Cu', bogtop_arr_out, mix, lchnk) call outfld('exit_UWCu_Cu', exit_UWCu, mix, lchnk) call outfld('exit_conden_Cu', exit_conden, mix, lchnk) call outfld('exit_klclmkx_Cu', exit_klclmkx, mix, lchnk) call outfld('exit_klfcmkx_Cu', exit_klfcmkx, mix, lchnk) call outfld('exit_ufrc_Cu', exit_ufrc, mix, lchnk) call outfld('exit_wtw_Cu', exit_wtw, mix, lchnk) call outfld('exit_drycore_Cu', exit_drycore, mix, lchnk) call outfld('exit_wu_Cu', exit_wu, mix, lchnk) call outfld('exit_cufilter_Cu', exit_cufilter, mix, lchnk) call outfld('exit_kinv1_Cu', exit_kinv1, mix, lchnk) call outfld('exit_rei_Cu', exit_rei, mix, lchnk) call outfld('limit_shcu_Cu', limit_shcu, mix, lchnk) call outfld('limit_negcon_Cu', limit_negcon, mix, lchnk) call outfld('limit_ufrc_Cu', limit_ufrc, mix, lchnk) call outfld('limit_ppen_Cu', limit_ppen, mix, lchnk) call outfld('limit_emf_Cu', limit_emf, mix, lchnk) call outfld('limit_cinlcl_Cu', limit_cinlcl, mix, lchnk) call outfld('limit_cin_Cu', limit_cin, mix, lchnk) call outfld('limit_cbmf_Cu', limit_cbmf, mix, lchnk) call outfld('limit_rei_Cu', limit_rei, mix, lchnk) call outfld('ind_delcin_Cu', ind_delcin, mix, lchnk) return end subroutine compute_mcshallow ! ------------------------------ ! ! ! ! Beginning of subroutine blocks ! ! ! ! ------------------------------ ! subroutine getbuoy(pbot,thv0bot,ptop,thv0top,thvubot,thvutop,plfc,cin) 11,12 ! ----------------------------------------------------------- ! ! Subroutine to calculate integrated CIN [ J/kg = m2/s2 ] and ! ! 'cinlcl, plfc' if any. Assume 'thv' is linear in each layer ! ! both for cumulus and environment. Note that this subroutine ! ! only include positive CIN in calculation - if there are any ! ! negative CIN, it is assumed to be zero. This is slightly ! ! different from 'single_cin' below, where both positive and ! ! negative CIN are included. ! ! ----------------------------------------------------------- ! real(r8) pbot,thv0bot,ptop,thv0top,thvubot,thvutop,plfc,cin,frc if( thvubot .gt. thv0bot .and. thvutop .gt. thv0top ) then plfc = pbot return elseif( thvubot .le. thv0bot .and. thvutop .le. thv0top ) then cin = cin - ((thvubot/thv0bot - 1._r8) + (thvutop/thv0top - 1._r8)) * (pbot - ptop)/ & (pbot/(r*thv0bot*exnf(pbot)) + ptop/(r*thv0top*exnf(ptop))) elseif( thvubot .gt. thv0bot .and. thvutop .le. thv0top ) then frc = (thvutop/thv0top - 1._r8)/((thvutop/thv0top - 1._r8) - (thvubot/thv0bot - 1._r8)) cin = cin - (thvutop/thv0top - 1._r8)*((ptop + frc*(pbot - ptop)) - ptop)/ & (pbot/(r*thv0bot*exnf(pbot)) + ptop/(r*thv0top*exnf(ptop))) else frc = (thvubot/thv0bot - 1._r8)/((thvubot/thv0bot - 1._r8) - (thvutop/thv0top - 1._r8)) plfc = pbot - frc*(pbot - ptop) cin = cin - (thvubot/thv0bot - 1._r8)*(pbot - plfc)/ & (pbot/(r*thv0bot*exnf(pbot)) + ptop/(r*thv0top * exnf(ptop))) endif return end subroutine getbuoy function single_cin(pbot,thv0bot,ptop,thv0top,thvubot,thvutop) 4,4 ! ------------------------------------------------------- ! ! Function to calculate a single layer CIN by summing all ! ! positive and negative CIN. ! ! ------------------------------------------------------- ! real(r8) :: single_cin real(r8) pbot,thv0bot,ptop,thv0top,thvubot,thvutop single_cin = ((1._r8 - thvubot/thv0bot) + (1._r8 - thvutop/thv0top))*(pbot - ptop)/ & (pbot/(r*thv0bot*exnf(pbot)) + ptop/(r*thv0top*exnf(ptop))) return end function single_cin subroutine conden(p,thl,qt,th,qv,ql,qi,rvls,id_check,qsat) 69,6 ! --------------------------------------------------------------------- ! ! Calculate thermodynamic properties from a given set of ( p, thl, qt ) ! ! --------------------------------------------------------------------- ! implicit none real(r8), intent(in) :: p real(r8), intent(in) :: thl real(r8), intent(in) :: qt real(r8), intent(out) :: th real(r8), intent(out) :: qv real(r8), intent(out) :: ql real(r8), intent(out) :: qi real(r8), intent(out) :: rvls integer , intent(out) :: id_check integer , external :: qsat real(r8) :: tc,temps,t real(r8) :: leff, nu, qc integer :: iteration real(r8) :: es(1) ! saturation vapor pressure real(r8) :: qs(1) ! saturation spec. humidity real(r8) :: gam(1) ! (L/cp)*dqs/dT integer :: status ! return status of qsat call tc = thl*exnf(p) ! This fraction of ice can be refined using 'cldwat_fice' subroutine later. nu = max(min((268._r8 - tc)/20._r8,1.0_r8),0.0_r8) ! Fraction of ice in the condensate. Func. of T. leff = (1._r8 - nu)*xlv + nu*xls ! This is an estimate that hopefully speeds convergence ! --------------------------------------------------------------------------- ! ! Below "temps" and "rvls" are just initial guesses for iteration loop below. ! ! Note that the output "temps" from the below iteration loop is "temperature" ! ! NOT "liquid temperature". ! ! --------------------------------------------------------------------------- ! temps = tc status = qsat(temps,p,es(1),qs(1),gam(1), 1) rvls = qs(1) if(qs(1).ge.qt) then id_check = 0 qv = qt qc = 0._r8 ql = 0._r8 qi = 0._r8 th = tc/exnf(p) else do iteration = 1, 10 temps = temps + (( tc - temps )*cp/leff + qt - rvls)/ & (cp/leff + ep2*leff*rvls/r/temps/temps) status = qsat(temps,p,es(1),qs(1),gam(1),1) rvls = qs(1) end do qc = max(qt - qs(1),0._r8) qv = qt - qc ql = qc*(1._r8 - nu) qi = nu*qc th = temps/exnf(p) if( abs((temps-(leff/cp)*qc)-tc).ge.1._r8) then id_check = 1 else id_check = 0 end if end if return end subroutine conden subroutine roots(a,b,c,r1,r2,status) 9 ! --------------------------------------------------------- ! ! Subroutine to solve the second order polynomial equation. ! ! I should check this subroutine later. ! ! --------------------------------------------------------- ! real(r8), intent(in) :: a real(r8), intent(in) :: b real(r8), intent(in) :: c real(r8), intent(out) :: r1 real(r8), intent(out) :: r2 integer , intent(out) :: status real(r8) :: q status = 0 if(a .eq. 0) then ! form b*x + c = 0 if(b .eq. 0) then ! failure: c = 0 status = 1 else ! b*x + c = 0 r1 = -c/b endif r2 = r1 else if(b .eq. 0._r8) then ! form a*x**2 + c = 0 if(a*c .gt. 0._r8) then ! failure: x**2 = -c/a < 0 status = 2 else ! x**2 = -c/a r1 = sqrt(-c/a) endif r2 = -r1 else ! form a*x**2 + b*x + c = 0 if((b**2 - 4._r8*a*c) .lt. 0._r8) then ! failure, no real roots status = 3 else q = -0.5_r8*(b + sign(1.0_r8,b)*sqrt(b**2 - 4._r8*a*c)) r1 = q/a r2 = c/q endif endif endif return end subroutine roots function slope(mkx,field,p0) 30,10 ! ------------------------------------------------------------------ ! ! Function performing profile reconstruction of conservative scalars ! ! in each layer. This is identical to profile reconstruction used in ! ! UW-PBL scheme but from bottom to top layer here. At the lowest ! ! layer near to surface, slope is defined using the two lowest layer ! ! mid-point values. I checked this subroutine and it is correct. ! ! ------------------------------------------------------------------ ! real(r8) :: slope(mkx) integer, intent(in) :: mkx real(r8), intent(in) :: field(mkx) real(r8), intent(in) :: p0(mkx) real(r8) :: below real(r8) :: above integer :: k below = (field(2) - field(1))/(p0(2) - p0(1)) do k = 2, mkx above = (field(k) - field(k-1))/(p0(k) - p0(k-1)) if (above .gt. 0._r8) then slope(k-1) = max(0._r8,min(above,below)) else slope(k-1) = min(0._r8,max(above,below)) end if below = above end do slope(mkx) = slope(mkx-1) return end function slope function qsinvert(qt,thl,psfc,qsat) 2 ! ----------------------------------------------------------------- ! ! Function calculating saturation pressure ps (or pLCL) from qt and ! ! thl ( liquid potential temperature, NOT liquid virtual potential ! ! temperature) by inverting Bolton formula. I should check later if ! ! current use of 'leff' instead of 'xlv' here is reasonable or not. ! ! ----------------------------------------------------------------- ! real(r8) :: qsinvert real(r8) qt, thl, psfc real(r8) ps, Pis, Ts, err, dlnqsdT, dTdPis real(r8) dPisdps, dlnqsdps, derrdps, dps real(r8) Ti, rhi, TLCL, PiLCL, psmin, dpsmax integer i integer, external :: qsat real(r8) :: es(1) ! saturation vapor pressure real(r8) :: qs(1) ! saturation spec. humidity real(r8) :: gam(1) ! (L/cp)*dqs/dT integer :: status ! return status of qsat call real(r8) :: leff, nu psmin = 100._r8*100 ! Default saturation pressure [Pa] if iteration does not converge dpsmax = 1._r8 ! Tolerance [Pa] for convergence of iteration ! ------------------------------------ ! ! Calculate best initial guess of pLCL ! ! ------------------------------------ ! Ti = thl*(psfc/p00)**rovcp status = qsat(Ti,psfc,es(1),qs(1),gam(1),1) rhi = qt/qs(1) if( rhi.le.0.01_r8 ) then write(iulog,*) 'Source air is too dry and pLCL is set to psmin in mcshallow.F90' qsinvert = psmin return end if TLCL = 55._r8 + 1._r8/(1._r8/(Ti-55._r8)-log(rhi)/2840._r8); ! Bolton's formula. MWR.1980.Eq.(22) PiLCL = TLCL/thl ps = p00*(PiLCL)**(1._r8/rovcp) do i = 1, 10 Pis = (ps/p00)**rovcp Ts = thl*Pis status = qsat(Ts,ps,es(1),qs(1),gam(1),1) err = qt - qs(1) nu = max(min((268._r8 - Ts)/20._r8,1.0_r8),0.0_r8) leff = (1._r8 - nu)*xlv + nu*xls dlnqsdT = gam(1)*(cp/leff)/qs(1) dTdPis = thl dPisdps = rovcp*Pis/ps dlnqsdps = -1._r8/(ps - (1._r8 - ep2)*es(1)) derrdps = -qs(1)*(dlnqsdT * dTdPis * dPisdps + dlnqsdps) dps = -err/derrdps ps = ps + dps if(ps .lt. 0._r8 ) then write(iulog,*) 'pLCL iteration is negative and set to psmin in mcshallow.F90' qsinvert = psmin return end if if( abs(dps) .le. dpsmax ) then qsinvert = ps return end if end do write(iulog,*) 'pLCL does not converge and is set to psmin in mcshallow.F90' qsinvert = psmin return end function qsinvert real(r8) function compute_alpha(del_CIN,ke) 2 ! ------------------------------------------------ ! ! Subroutine to compute proportionality factor for ! ! implicit CIN calculation. ! ! ------------------------------------------------ ! real(r8) :: del_CIN, ke real(r8) :: x0, x1 integer :: iteration x0 = 0._r8 do iteration = 1, 10 x1 = x0 - (exp(-x0*ke*del_CIN) - x0)/(-ke*del_CIN*exp(-x0*ke*del_CIN) - 1._r8) x0 = x1 end do compute_alpha = x0 return end function compute_alpha real(r8) function compute_mumin2(mulcl,rmaxfrac,mulow) 2 ! --------------------------------------------------------- ! ! Subroutine to compute critical 'mu' (normalized CIN) such ! ! that updraft fraction at the LCL is equal to 'rmaxfrac'. ! ! --------------------------------------------------------- ! real(r8) :: mulcl, rmaxfrac, mulow real(r8) :: x0, x1, ex, ef, exf, f, fs integer :: iteration x0 = mulow do iteration = 1, 10 ex = exp(-x0**2) ef = erfc(x0) ! if(x0.ge.3._r8) then ! compute_mumin2 = 3._r8 ! goto 20 ! endif exf = ex/ef f = 0.5_r8*exf**2 - 0.5_r8*(ex/2/rmaxfrac)**2 - (mulcl*2.5066_r8/2)**2 fs = (2*exf**2)*(exf/sqrt(3.141592_r8)-x0) + (0.5_r8*x0*ex**2)/(rmaxfrac**2) x1 = x0 - f/fs x0 = x1 end do compute_mumin2 = x0 20 return end function compute_mumin2 real(r8) function compute_ppen(wtwb,D,bogbot,bogtop,rho0j,dpen) 2 ! ----------------------------------------------------------- ! ! Subroutine to compute critical 'ppen[Pa]<0' ( pressure dis. ! ! from 'ps0(kpen-1)' to the cumulus top where cumulus updraft ! ! vertical velocity is exactly zero ) by considering exact ! ! non-zero fer(kpen). ! ! ----------------------------------------------------------- ! real(r8) :: wtwb, D, bogbot, bogtop, rho0j, dpen real(r8) :: x0, x1, f, fs, SB, s00 integer :: iteration ! Buoyancy slope SB = (bogtop-bogbot)/dpen ! Sign of slope, 'f' at x = 0 ! If 's00>0', 'w' increases with height. s00 = bogbot/rho0j - D*wtwb if( D*dpen.lt.1.e-8 ) then if( s00.ge.0._r8 ) then x0 = dpen else x0 = max(0._r8,min(dpen,-0.5_r8*wtwb/s00)) endif else if( s00.ge.0._r8 ) then x0 = dpen else x0 = 0._r8 endif do iteration = 1, 5 f = exp(-2._r8*D*x0)*(wtwb-(bogbot-SB/(2._r8*D))/(D*rho0j)) + & (SB*x0+bogbot-SB/(2._r8*D))/(D*rho0j) fs = -2._r8*D*exp(-2._r8*D*x0)*(wtwb-(bogbot-SB/(2._r8*D))/(D*rho0j)) + & (SB)/(D*rho0j) x1 = x0 - f/fs x0 = x1 end do endif compute_ppen = -max(0._r8,min(dpen,x0)) end function compute_ppen subroutine fluxbelowinv(cbmf,ps0,mkx,kinv,dt,xsrc,xmean,xtopin,xbotin,xflx) 9 ! ------------------------------------------------------------------------- ! ! Subroutine to calculate turbulent fluxes at and below 'kinv-1' interfaces.! ! Check in the main program such that input 'cbmf' should not be zero. ! ! If the reconstructed inversion height does not go down below the 'kinv-1' ! ! interface, then turbulent flux at 'kinv-1' interface is simply a product ! ! of 'cmbf' and 'qtsrc-xbot' where 'xbot' is the value at the top interface ! ! of 'kinv-1' layer. This flux is linearly interpolated down to the surface ! ! assuming turbulent fluxes at surface are zero. If reconstructed inversion ! ! height goes down below the 'kinv-1' interface, subsidence warming &drying ! ! measured by 'xtop-xbot', where 'xtop' is the value at the base interface ! ! of 'kinv+1' layer, is added ONLY to the 'kinv-1' layer, using appropriate ! ! mass weighting ( rpinv and rcbmf, or rr = rpinv / rcbmf ) between current ! ! and next provisional time step. Also impose a limiter to enforce outliers ! ! of thermodynamic variables in 'kinv' layer to come back to normal values ! ! at the next step. ! ! ------------------------------------------------------------------------- ! integer, intent(in) :: mkx, kinv real(r8), intent(in) :: cbmf, dt, xsrc, xmean, xtopin, xbotin real(r8), intent(in), dimension(0:mkx) :: ps0 real(r8), intent(out), dimension(0:mkx) :: xflx integer k real(r8) rcbmf, rpeff, dp, rr, pinv_eff, xtop, xbot, pinv, xtop_ori, xbot_ori xflx(0:mkx) = 0._r8 dp = ps0(kinv-1)-ps0(kinv) if( abs(xbotin-xtopin).le.1.e-33_r8 ) then xbot = xbotin - 1.e-20_r8 xtop = xtopin + 1.e-20_r8 else xbot = xbotin xtop = xtopin endif ! -------------------------------------- ! ! Compute reconstructed inversion height ! ! -------------------------------------- ! xtop_ori = xtop xbot_ori = xbot rcbmf = ( cbmf * g * dt ) / dp ! Can be larger than 1 : 'OK' rpeff = ( xmean - xtop ) / ( xbot - xtop ) rpeff = min( max(0._r8,rpeff), 1._r8 ) ! As of this, 0<= rpeff <= 1 if(rpeff.eq.0.or.rpeff.eq.1) then xbot = xmean xtop = xmean endif ! Below two commented-out lines are the old code replacing the above 'if' block. ! if(rpeff.eq.1) xbot = xmean ! if(rpeff.eq.0) xtop = xmean rr = rpeff / rcbmf pinv = ps0(kinv-1) - rpeff * dp ! "pinv" before detraining mass pinv_eff = ps0(kinv-1) + ( rcbmf - rpeff ) * dp ! Effective "pinv" after detraining mass ! -------------------------------------------------------------------- ! ! Compute turbulent fluxes. ! ! Below two cases exactly converges at 'kinv-1' interface when rr = 1._r8 ! ! -------------------------------------------------------------------- ! do k = 0, kinv - 1 xflx(k) = cbmf * ( xsrc - xbot ) * ( ps0(0) - ps0(k) ) / ( ps0(0) - pinv ) end do if( rr.le.1 ) then xflx(kinv-1) = xflx(kinv-1) - ( 1._r8 - rr ) * cbmf * ( xtop_ori - xbot_ori ) endif return end subroutine fluxbelowinv ! ------------------------ ! ! ! ! End of subroutine blocks ! ! ! ! ------------------------ ! end module mcshallow