From d7c57b7589c9a9a308a31bdf21f37326773b13f5 Mon Sep 17 00:00:00 2001 From: chihchen24 Date: Thu, 23 Jul 2026 12:17:23 -0600 Subject: [PATCH 1/3] MCSP added --- bld/build-namelist | 11 + bld/namelist_files/namelist_defaults_cam.xml | 9 + bld/namelist_files/namelist_definition.xml | 45 ++++ src/control/runtime_opts.F90 | 6 + src/physics/cam/convect_deep.F90 | 10 + src/physics/cam/mcsp_intr.F90 | 237 +++++++++++++++++++ src/physics/cam/physpkg.F90 | 57 +++++ src/physics/cam/zm_conv_intr.F90 | 11 + src/physics/cam7/physpkg.F90 | 58 +++++ 9 files changed, 444 insertions(+) create mode 100644 src/physics/cam/mcsp_intr.F90 diff --git a/bld/build-namelist b/bld/build-namelist index faad098c53..da98a6102c 100755 --- a/bld/build-namelist +++ b/bld/build-namelist @@ -3815,6 +3815,17 @@ if (!$simple_phys) { add_default($nl, 'zmconv_parcel_hscale'); } +# MCSP +if (!$simple_phys) { + add_default($nl, 'MCSP_heat_coeff'); + add_default($nl, 'MCSP_moisture_coeff'); + add_default($nl, 'MCSP_uwind_coeff'); + add_default($nl, 'MCSP_vwind_coeff'); + add_default($nl, 'MCSP_storm_speed_pref'); + add_default($nl, 'MCSP_conv_depth_min'); + add_default($nl, 'mcsp_shear_min'); +} + # moist convection rainwater coefficients my $shallow_scheme = $nl->get_value('shallow_scheme'); $shallow_scheme =~ s/['"]//g; # strip quotes "' diff --git a/bld/namelist_files/namelist_defaults_cam.xml b/bld/namelist_files/namelist_defaults_cam.xml index 38975992be..d6076d31ae 100644 --- a/bld/namelist_files/namelist_defaults_cam.xml +++ b/bld/namelist_files/namelist_defaults_cam.xml @@ -2925,6 +2925,15 @@ .false. 0.5 + + 0.0D0 + 0.0D0 + 0.0D0 + 0.0D0 +60000.0 +50000.0 + 3.0 + 1.0D0 diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml index ca66966f56..ba814d7161 100644 --- a/bld/namelist_files/namelist_definition.xml +++ b/bld/namelist_files/namelist_definition.xml @@ -3401,6 +3401,51 @@ Convective adjustment timescale in units of (s) Default: 3600.0 s + + + +MCSP heating coefficient controlling the tendency intensity added. +Default: 0.0 + + + +MCSP moistening coefficient controlling the tendency intensity added. +Default: 0.0 + + + +MCSP uwnd tendency coefficient controlling the tendency intensity added. +Default: 0.0 + + + +MCSP vwnd tendency coefficient controlling the tendency intensity added. +Default: 0.0 + + + +Reference pressure level in Pa for low-level zonal wind shear calculation for MCSP. +Default: 60000.0 + + + +Minimum convection depth for MCSP to be activated in Pa. +Default: 50000.0 + + + +Minimum uwind difference/shear between reference pressure level and surface for MCSP to be activated. +Default: 3.0 + + + shr_kind_r8 + use cam_abortutils, only: endrun + use cam_logfile, only: iulog + + + implicit none + private + + public :: mcsp_register ! Register fields wit the output buffer + public :: mcsp_readnl ! Read MCSP namelist + public :: mcsp_intr_init ! initialize MCSP namelist variables + public :: mcsp_tend ! Perform MCSP tendency calculations + + real(r8) :: MCSP_storm_speed_pref ! pressure level for winds in MCSP calculation [Pa] + real(r8) :: MCSP_conv_depth_min ! pressure thickness of convective heating [Pa] + real(r8) :: mcsp_shear_min ! min shear value for MCSP to be active + + real(r8) :: MCSP_heat_coeff ! heating coefficient for MCSP + real(r8) :: MCSP_moisture_coeff ! moisture coefficient for MCSP + real(r8) :: MCSP_uwind_coeff ! uwind coefficient for MCSP + real(r8) :: MCSP_vwind_coeff ! vwind coefficient for MCSP + +!========================================================================================= +contains +!========================================================================================= +subroutine mcsp_register() + !---------------------------------------------------------------------------- + ! Purpose: register MCSP output fields + !---------------------------------------------------------------------------- + use cam_history, only: addfld, horiz_only + !---------------------------------------------------------------------------- + call addfld('MCSP_DT_max', horiz_only, 'A', 'K/s', 'MCSP max T tendency') + call addfld('MCSP_DT', (/'lev'/), 'A', 'K/s', 'MCSP T tendency') + call addfld('MCSP_DQ', (/'lev'/), 'A', 'kg/kg/s', 'MCSP qv tendency') + call addfld('MCSP_DU', (/'lev'/), 'A', 'm/s/day', 'MCSP U wind tendency') + call addfld('MCSP_DV', (/'lev'/), 'A', 'm/s/day', 'MCSP V wind tendency') + + call addfld('MCSP_freq', horiz_only, 'A', '1', 'MCSP frequency of activation') + call addfld('MCSP_shear', horiz_only, 'A', 'm/s', 'MCSP vertical shear of zonal wind') + call addfld('MCSP_conv_depth', horiz_only, 'A', 'Pa', 'ZM convection depth for MCSP') + +end subroutine mcsp_register + +!========================================================================================= + +subroutine mcsp_readnl(nlfile) + + use spmd_utils, only: mpicom, masterproc, masterprocid, mpi_real8, mpi_integer, mpi_logical + use namelist_utils, only: find_group_name + + character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input + + ! Local variables + integer :: unitn, ierr + character(len=*), parameter :: subname = 'mcsp_readnl' + + namelist /mcsp_nl/ MCSP_heat_coeff, MCSP_moisture_coeff, & + MCSP_uwind_coeff, MCSP_vwind_coeff, & + MCSP_storm_speed_pref, MCSP_conv_depth_min, mcsp_shear_min + !----------------------------------------------------------------------------- + + if (masterproc) then + open( newunit=unitn, file=trim(nlfile), status='old' ) + call find_group_name(unitn, 'mcsp_nl', status=ierr) + if (ierr == 0) then + read(unitn, mcsp_nl, iostat=ierr) + if (ierr /= 0) then + call endrun(subname // ':: ERROR reading namelist') + end if + end if + close(unitn) + + end if + + ! Broadcast namelist variables + call mpi_bcast(MCSP_heat_coeff, 1, mpi_real8, masterprocid, mpicom, ierr) + if (ierr /= 0) call endrun("mcsp_readnl: FATAL: mpi_bcast: MCSP_heat_coeff") + call mpi_bcast(MCSP_moisture_coeff, 1, mpi_real8, masterprocid, mpicom, ierr) + if (ierr /= 0) call endrun("mcsp_readnl: FATAL: mpi_bcast: MCSP_moisture_coeff") + call mpi_bcast(MCSP_uwind_coeff, 1, mpi_real8, masterprocid, mpicom, ierr) + if (ierr /= 0) call endrun("mcsp_readnl: FATAL: mpi_bcast: MCSP_uwind_coeff") + call mpi_bcast(MCSP_vwind_coeff, 1, mpi_real8, masterprocid, mpicom, ierr) + if (ierr /= 0) call endrun("mcsp_readnl: FATAL: mpi_bcast: MCSP_vwind_coeff") + call mpi_bcast(MCSP_storm_speed_pref, 1, mpi_real8, masterprocid, mpicom, ierr) + if (ierr /= 0) call endrun("mcsp_readnl: FATAL: mpi_bcast: MCSP_storm_speed_pref") + call mpi_bcast(MCSP_conv_depth_min, 1, mpi_real8, masterprocid, mpicom, ierr) + if (ierr /= 0) call endrun("mcsp_readnl: FATAL: mpi_bcast: MCSP_conv_depth_min") + call mpi_bcast(mcsp_shear_min, 1, mpi_real8, masterprocid, mpicom, ierr) + if (ierr /= 0) call endrun("mcsp_readnl: FATAL: mpi_bcast: mcsp_shear_min") + +end subroutine mcsp_readnl + +!=================================================================================================== + +subroutine mcsp_intr_init() + use MCSP, only: MCSP_init + use spmd_utils, only: masterproc + use cam_logfile, only: iulog + + implicit none + + call MCSP_init(MCSP_heat_coeff, MCSP_moisture_coeff, MCSP_uwind_coeff, MCSP_vwind_coeff, & + MCSP_storm_speed_pref, MCSP_conv_depth_min, mcsp_shear_min, masterproc, iulog) + +end subroutine mcsp_intr_init + +!=================================================================================================== + +subroutine mcsp_tend( state, ptend, ztodt, jctop, tend_t, tend_q ) + + use MCSP, only: MCSP_run + use physconst, only: cpair + use physics_types, only: physics_state, physics_ptend, physics_ptend_init + use ppgrid, only: pver, pverp, pcols + use physconst, only: cpair, pi + use constituents, only: pcnst + + ! Arguments + type(physics_state), intent( in) :: state ! Physics state variables + type(physics_ptend), intent(out) :: ptend ! individual parameterization tendencies + real(r8), intent(in ) :: ztodt ! 2x physics time step + integer, dimension(pcols), intent(in ) :: jctop ! cloud top level indices + real(r8), dimension(pcols,pver), intent(in ) :: tend_t ! input deep convective temperature tendency + real(r8), dimension(pcols,pver), intent(in ) :: tend_q ! input deep convective tendency for specific humidity (qv) + + ! local variables + integer :: lchnk ! chunk identifier + integer :: ncol ! number of atmospheric columns (actual) + real(r8), dimension(pcols,pver) :: mcsp_dt_out! final MCSP tendency for DSE + real(r8), dimension(pcols,pver) :: mcsp_dq_out! final MCSP tendency for qv + real(r8), dimension(pcols,pver) :: mcsp_du_out! final MCSP tendency for u wind + real(r8), dimension(pcols,pver) :: mcsp_dv_out! final MCSP tendency for v wind + real(r8), dimension(pcols) :: mcsp_freq ! MSCP frequency for output + real(r8), dimension(pcols) :: mcsp_shear ! shear used to check against threshold + real(r8), dimension(pcols) :: conv_depth ! pressure depth of deep convection + real(r8), dimension(pcols) :: mcsp_tend_s_max ! max MCSP heating tendency + logical :: lq(pcnst) + + !---------------------------------------------------------------------------- + ! Perform MCSP tendency calculations + !---------------------------------------------------------------------------- + lchnk = state%lchnk + ncol = state%ncol + lq(:) = .false. + lq(1) = .true. + + call physics_ptend_init(ptend, state%psetcols, 'MCSP', ls = .true., lq = lq, lu = .true., lv = .true.) + + call MCSP_run( pcols, ncol, pver, pverp, cpair, pi, & + ztodt, jctop, & + state%pmid, state%pint, state%pdel, & + state%s, state%q(:,:,1), state%u, state%v, & + tend_t, tend_q, & + ptend%s, ptend%q(:,:,1), ptend%u, ptend%v, & + mcsp_dt_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out, & + mcsp_freq, mcsp_shear, conv_depth, mcsp_tend_s_max ) + + !---------------------------------------------------------------------------- + ! outpuf MCSP variables + !---------------------------------------------------------------------------- + call mcsp_hist( lchnk, pcols, pver, & + mcsp_dt_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out, & + mcsp_freq, mcsp_shear, conv_depth, mcsp_tend_s_max ) + +end subroutine mcsp_tend + +!=================================================================================================== + +subroutine mcsp_hist( lchnk, pcols, pver, & + mcsp_dt_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out, & + mcsp_freq, mcsp_shear, conv_depth, mcsp_tend_s_max ) + !---------------------------------------------------------------------------- + ! Purpose: write diagnostic quantities to history files + !---------------------------------------------------------------------------- + use cam_history, only: outfld + !---------------------------------------------------------------------------- + ! Arguments + integer, intent(in) :: lchnk ! chunk identifier + integer, intent(in) :: pcols ! number of atmospheric columns (max) + integer, intent(in) :: pver ! number of mid-point vertical levels + real(r8), dimension(pcols,pver), intent(in) :: mcsp_dt_out ! final MCSP tendency for DSE + real(r8), dimension(pcols,pver), intent(in) :: mcsp_dq_out ! final MCSP tendency for qv + real(r8), dimension(pcols,pver), intent(in) :: mcsp_du_out ! final MCSP tendency for u wind + real(r8), dimension(pcols,pver), intent(in) :: mcsp_dv_out ! final MCSP tendency for v wind + real(r8), dimension(pcols), intent(in) :: mcsp_freq ! MSCP frequency for output + real(r8), dimension(pcols), intent(in) :: mcsp_shear ! shear used to check against threshold + real(r8), dimension(pcols), intent(in) :: conv_depth ! pressure depth of ZM heating + real(r8), dimension(pcols), intent(in) :: mcsp_tend_s_max ! max MCSP heating tendency + !---------------------------------------------------------------------------- + ! write out MCSP diagnostic history fields + call outfld('MCSP_DT', mcsp_dt_out, pcols, lchnk ) + call outfld('MCSP_DQ', mcsp_dq_out, pcols, lchnk ) + call outfld('MCSP_DU', mcsp_du_out, pcols, lchnk ) + call outfld('MCSP_DV', mcsp_dv_out, pcols, lchnk ) + call outfld('MCSP_freq', mcsp_freq, pcols, lchnk ) + call outfld('MCSP_shear', mcsp_shear, pcols, lchnk ) + call outfld('MCSP_conv_depth', conv_depth, pcols, lchnk ) + call outfld('MCSP_DT_max', mcsp_tend_s_max, pcols, lchnk) + !---------------------------------------------------------------------------- + return + +end subroutine mcsp_hist + +!=================================================================================================== + +end module mcsp_intr + + diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90 index 3d6d260b23..75b01ce5ca 100644 --- a/src/physics/cam/physpkg.F90 +++ b/src/physics/cam/physpkg.F90 @@ -137,6 +137,9 @@ subroutine phys_register use ghg_data, only: ghg_data_register use vertical_diffusion, only: vd_register use convect_deep, only: convect_deep_register + !++ MCSP + use mcsp_intr, only: mcsp_register + !-- MCSP use convect_shallow, only: convect_shallow_register use radiation, only: radiation_register use co2_cycle, only: co2_register @@ -311,6 +314,9 @@ subroutine phys_register ! deep convection call convect_deep_register + ! MCSP + call mcsp_register() + ! shallow convection call convect_shallow_register @@ -733,6 +739,9 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) use cldfrc2m, only: cldfrc2m_init use co2_cycle, only: co2_init, co2_transport use convect_deep, only: convect_deep_init + !++ MCSP + use mcsp_intr, only: mcsp_intr_init + !-- MCSP use convect_shallow, only: convect_shallow_init use constituents, only: cnst_get_ind use cam_diagnostics, only: diag_init @@ -926,6 +935,10 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) call convect_deep_init(pref_edge) + !++ MCSP + call mcsp_intr_init() + !-- MCSP + if( microp_scheme == 'RK' ) then call rk_stratiform_cam_init() elseif( microp_scheme == 'MG' ) then @@ -2195,6 +2208,14 @@ subroutine tphysbc (ztodt, state, & use aerosol_state_mod, only: aerosol_state use aerosol_instances_mod, only: aerosol_instances_get_props, & aerosol_instances_get_num_models, aerosol_instances_get_state + !++ MCSP + use mcsp_intr, only: mcsp_tend + use save_ttend_from_convect_deep, only : save_ttend_from_convect_deep_timestep_init, save_ttend_from_convect_deep_run + use save_qtend_from_convect_deep, only : save_qtend_from_convect_deep_timestep_init, save_qtend_from_convect_deep_run + use zm_conv_intr, only: ttend_s + use convect_deep, only: jctop1 + use physconst, only: cpair + !-- MCSP ! Arguments @@ -2232,6 +2253,12 @@ subroutine tphysbc (ztodt, state, & real(r8) dlf(pcols,pver) ! Detraining cld H20 from shallow + deep convections real(r8) dlf2(pcols,pver) ! Detraining cld H20 from shallow convections real(r8) rtdt ! 1./ztodt + !++ MCSP + real(r8) ttend_dp(pcols,pver) ! temperature tendency from deep convection + real(r8) qtend_dp(pcols,pver) ! water vapor from deep convection + character(len=512) :: errmsg + integer :: errflg + !-- MCSP integer lchnk ! chunk identifier integer ncol ! number of atmospheric columns @@ -2493,6 +2520,11 @@ subroutine tphysbc (ztodt, state, & flx_heat, cmfmc, cmfcme, zdu, rliq, dlf, dlf2, rliq2, det_s, det_ice, net_flx) end if + !++ MCSP + call save_ttend_from_convect_deep_timestep_init(ncol, pver, ttend_dp, errmsg, errflg) + call save_qtend_from_convect_deep_timestep_init(ncol, pver, qtend_dp, errmsg, errflg) + !-- MCSP + call convect_deep_tend( & cmfmc, cmfcme, & zdu, & @@ -2500,6 +2532,11 @@ subroutine tphysbc (ztodt, state, & ztodt, & state, ptend, cam_in%landfrac, pbuf) + !++ MCSP + call save_ttend_from_convect_deep_run(ncol, pver, ttend_s, cpair, ttend_dp, errmsg, errflg) + call save_qtend_from_convect_deep_run(ncol, pver, ptend%q(:,:,1), qtend_dp, errmsg, errflg) + !-- MCSP + if ( (trim(cam_take_snapshot_after) == "convect_deep_tend") .and. & (trim(cam_take_snapshot_before) == trim(cam_take_snapshot_after))) then call cam_snapshot_ptend_outfld(ptend, lchnk) @@ -2520,6 +2557,26 @@ subroutine tphysbc (ztodt, state, & call t_stopf('convect_deep_tend') + !++ MCSP + call t_startf ('MCSP_tend') + + if (trim(cam_take_snapshot_before) == "mcsp_tend") then + call cam_snapshot_all_outfld_tphysbc(cam_snapshot_before_num, state, tend, cam_in, cam_out, pbuf, & + flx_heat, cmfmc, cmfcme, zdu, rliq, dlf, dlf2, rliq2, det_s, det_ice, net_flx) + end if + + call mcsp_tend( state, ptend, ztodt, jctop1, ttend_dp, qtend_dp) + + call physics_update(state, ptend, ztodt, tend) + + if (trim(cam_take_snapshot_after) == "mcsp_tend") then + call cam_snapshot_all_outfld_tphysbc(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf, & + flx_heat, cmfmc, cmfcme, zdu, rliq, dlf, dlf2, rliq2, det_s, det_ice, net_flx) + end if + + call t_stopf('MCSP_tend') + !-- MCSP + call pbuf_get_field(pbuf, prec_dp_idx, prec_dp ) call pbuf_get_field(pbuf, snow_dp_idx, snow_dp ) call pbuf_get_field(pbuf, prec_sh_idx, prec_sh ) diff --git a/src/physics/cam/zm_conv_intr.F90 b/src/physics/cam/zm_conv_intr.F90 index 2c9abe5b76..e7fb6f3690 100644 --- a/src/physics/cam/zm_conv_intr.F90 +++ b/src/physics/cam/zm_conv_intr.F90 @@ -38,6 +38,13 @@ module zm_conv_intr zm_conv_tend, &! return tendencies zm_conv_tend_2 ! return tendencies + !++ MCSP + public :: ttend_s + + real(r8) :: ttend_s(pcols,pver) + !-- MCSP + + public zmconv_ke, zmconv_ke_lnd ! needed by convect_shallow integer ::& ! indices for fields in the physics buffer @@ -586,6 +593,10 @@ subroutine zm_conv_tend(pblh ,mcon ,cme , & end do call outfld('CAPE', cape, pcols, lchnk) ! RBN - CAPE output + + !++ MCSP + ttend_s = ptend_loc%s(:pcols,:) + !-- MCSP ! ! Output fractional occurance of ZM convection ! diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90 index 78d1deba92..1dd95c28b6 100644 --- a/src/physics/cam7/physpkg.F90 +++ b/src/physics/cam7/physpkg.F90 @@ -133,6 +133,9 @@ subroutine phys_register use ghg_data, only: ghg_data_register use vertical_diffusion, only: vd_register use convect_deep, only: convect_deep_register + !++ MCSP + use mcsp_intr, only: mcsp_register + !-- MCSP use convect_diagnostics,only: convect_diagnostics_register use radiation, only: radiation_register use co2_cycle, only: co2_register @@ -304,6 +307,9 @@ subroutine phys_register ! deep convection call convect_deep_register + ! MCSP + call mcsp_register() + ! convection diagnostics call convect_diagnostics_register @@ -734,6 +740,9 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) use cldfrc2m, only: cldfrc2m_init use co2_cycle, only: co2_init, co2_transport use convect_deep, only: convect_deep_init + !++ MCSP + use mcsp_intr, only: mcsp_intr_init + !-- MCSP use convect_diagnostics,only: convect_diagnostics_init use cam_diagnostics, only: diag_init use gw_drag_cam, only: gw_drag_cam_init @@ -925,6 +934,10 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out ) call convect_deep_init(pref_edge) + !++ MCSP + call mcsp_intr_init() + !-- MCSP + if (.not. do_clubb_sgs) call macrop_driver_init(pbuf2d) call microp_aero_init(phys_state,pbuf2d) call microp_driver_init(pbuf2d) @@ -2679,6 +2692,15 @@ subroutine tphysbc (ztodt, state, & use aerosol_instances_mod, only: aerosol_instances_get_props, & aerosol_instances_get_num_models, aerosol_instances_get_state !REMOVECAM_END + !++ MCSP + use mcsp_intr, only: mcsp_tend + use save_ttend_from_convect_deep, only : save_ttend_from_convect_deep_timestep_init, save_ttend_from_convect_deep_run + use save_qtend_from_convect_deep, only : save_qtend_from_convect_deep_timestep_init, save_qtend_from_convect_deep_run + use zm_conv_intr, only: ttend_s + use convect_deep, only: jctop1 + use physconst, only: cpair + !-- MCSP + ! Arguments @@ -2710,6 +2732,12 @@ subroutine tphysbc (ztodt, state, & real(r8) dlf(pcols,pver) ! Detraining cld H20 from shallow + deep convections real(r8) dlf2(pcols,pver) ! Detraining cld H20 from shallow convections real(r8) rtdt ! 1./ztodt + !++ MCSP + real(r8) ttend_dp(pcols,pver) ! temperature tendency from deep convection + real(r8) qtend_dp(pcols,pver) ! water vapor from deep convection + character(len=512) :: errmsg + integer :: errflg + !-- MCSP integer lchnk ! chunk identifier integer ncol ! number of atmospheric columns @@ -2952,6 +2980,11 @@ subroutine tphysbc (ztodt, state, & cmfmc, cmfcme, zdu, rliq, dlf, dlf2, rliq2, net_flx) end if + !++ MCSP + call save_ttend_from_convect_deep_timestep_init(ncol, pver, ttend_dp, errmsg, errflg) + call save_qtend_from_convect_deep_timestep_init(ncol, pver, qtend_dp, errmsg, errflg) + !-- MCSP + call convect_deep_tend( & cmfmc, cmfcme, & zdu, & @@ -2959,6 +2992,11 @@ subroutine tphysbc (ztodt, state, & ztodt, & state, ptend, cam_in%landfrac, pbuf) + !++ MCSP + call save_ttend_from_convect_deep_run(ncol, pver, ttend_s, cpair, ttend_dp, errmsg, errflg) + call save_qtend_from_convect_deep_run(ncol, pver, ptend%q(:,:,1), qtend_dp, errmsg, errflg) + !-- MCSP + if ( (trim(cam_take_snapshot_after) == "convect_deep_tend") .and. & (trim(cam_take_snapshot_before) == trim(cam_take_snapshot_after))) then call cam_snapshot_ptend_outfld(ptend, lchnk) @@ -2979,6 +3017,26 @@ subroutine tphysbc (ztodt, state, & call t_stopf('convect_deep_tend') + !++ MCSP + call t_startf ('MCSP_tend') + if (trim(cam_take_snapshot_before) == "mcsp_tend") then + call cam_snapshot_all_outfld_tphysbc(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf, & + cmfmc, cmfcme, zdu, rliq, dlf, dlf2, rliq2, net_flx) + end if + + call mcsp_tend( state, ptend, ztodt, jctop1, ttend_dp, qtend_dp) + + call physics_update(state, ptend, ztodt, tend) + + if (trim(cam_take_snapshot_after) == "mcsp_tend") then + call cam_snapshot_all_outfld_tphysbc(cam_snapshot_after_num, state, tend, cam_in, cam_out, pbuf, & + cmfmc, cmfcme, zdu, rliq, dlf, dlf2, rliq2, net_flx) + end if + + call t_stopf('MCSP_tend') + !-- MCSP + + call pbuf_get_field(pbuf, prec_dp_idx, prec_dp ) call pbuf_get_field(pbuf, snow_dp_idx, snow_dp ) call pbuf_get_field(pbuf, prec_sh_idx, prec_sh ) From 36a660831ef90d23f77121c7d57f2de43f243c22 Mon Sep 17 00:00:00 2001 From: chihchen24 Date: Thu, 23 Jul 2026 15:57:53 -0600 Subject: [PATCH 2/3] Update atmos_phys for MCSP --- src/atmos_phys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/atmos_phys b/src/atmos_phys index 78e2017002..73b93b0237 160000 --- a/src/atmos_phys +++ b/src/atmos_phys @@ -1 +1 @@ -Subproject commit 78e20170024921cf044bffcfcc0dcf2262c9e8ce +Subproject commit 73b93b0237e6fda0274b8281cad952e89f077813 From 65421682d4fa9054d222f2b38d2f74a7d97814ae Mon Sep 17 00:00:00 2001 From: chihchen24 Date: Thu, 23 Jul 2026 16:41:26 -0600 Subject: [PATCH 3/3] MCSP mods added --- src/physics/cam/MCSP.F90 | 344 ++++++++++++++++++ src/physics/cam/mcsp_options.F90 | 42 +++ .../cam/save_qtend_from_convect_deep.F90 | 70 ++++ 3 files changed, 456 insertions(+) create mode 100644 src/physics/cam/MCSP.F90 create mode 100644 src/physics/cam/mcsp_options.F90 create mode 100644 src/physics/cam/save_qtend_from_convect_deep.F90 diff --git a/src/physics/cam/MCSP.F90 b/src/physics/cam/MCSP.F90 new file mode 100644 index 0000000000..819f97349d --- /dev/null +++ b/src/physics/cam/MCSP.F90 @@ -0,0 +1,344 @@ +module MCSP + + use ccpp_kinds, only: kind_phys + + implicit none + + save + private ! Make default type private to the module + +! +! PUBLIC: interfaces +! + public MCSP_init + public MCSP_run ! MCSP scheme + + real(kind_phys) heat_coeff + real(kind_phys) moisture_coeff + real(kind_phys) uwind_coeff + real(kind_phys) vwind_coeff + real(kind_phys) storm_speed_pref + real(kind_phys) conv_depth_min + real(kind_phys) shear_min + +contains + +!=============================================================================== +!> \section arg_table_MCSP_init Argument Table +!! \htmlinclude MCSP_init.html +!! +subroutine MCSP_init(MCSP_heat_coeff, MCSP_moisture_coeff, MCSP_uwind_coeff, MCSP_vwind_coeff, & + MCSP_storm_speed_pref, MCSP_conv_depth_min, mcsp_shear_min,masterproc,iulog) + + real(kind_phys), intent(in ) :: MCSP_heat_coeff ! heating coefficient for MCSP + real(kind_phys), intent(in ) :: MCSP_moisture_coeff ! moisture coefficient for MCSP + real(kind_phys), intent(in ) :: MCSP_uwind_coeff ! uwind coefficient for MCSP + real(kind_phys), intent(in ) :: MCSP_vwind_coeff ! vwind coefficient for MCSP + real(kind_phys), intent(in ) :: MCSP_storm_speed_pref ! pressure level for zonal wind in MCSP calculation [Pa] + real(kind_phys), intent(in ) :: MCSP_conv_depth_min ! pressure thickness of convective heating [Pa] + real(kind_phys), intent(in ) :: mcsp_shear_min ! min shear value for MCSP to be active + logical, intent(in) :: masterproc + integer, intent(in) :: iulog + + heat_coeff = MCSP_heat_coeff + moisture_coeff = MCSP_moisture_coeff + uwind_coeff = MCSP_uwind_coeff + vwind_coeff = MCSP_vwind_coeff + storm_speed_pref = MCSP_storm_speed_pref + conv_depth_min = MCSP_conv_depth_min + shear_min = mcsp_shear_min + + if(masterproc) then + write(iulog,*) 'MCSP_hear_coeff', heat_coeff + write(iulog,*) 'MCSP_moisture_coeff', moisture_coeff + write(iulog,*) 'MCSP_uwind_coeff', uwind_coeff + write(iulog,*) 'MCSP_vwind_coeff', vwind_coeff + write(iulog,*) 'MCSP_storm_speed_pref', storm_speed_pref + write(iulog,*) 'MCSP_conv_depth_min', conv_depth_min + write(iulog,*) 'mcsp_shear_min', shear_min + end if + +end subroutine MCSP_init + +!=============================================================================== +!> \section arg_table_MCSP_run Argument Table +!! \htmlinclude MCSP_run.html +!! +subroutine MCSP_run( pcols, ncol, pver, pverp, cpair, pi, & + ztodt, jctop, & + pmid, pint, pdel, & + s, q, u, v, & + tend_t, tend_q, & + ptend_s, ptend_q, ptend_u, ptend_v, & + mcsp_dt_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out, & + mcsp_freq, mcsp_shear, conv_depth, mcsp_tend_s_max ) + + !---------------------------------------------------------------------------- + ! Purpose: perform MCSP tendency calculations + !---------------------------------------------------------------------------- + ! Arguments + integer, intent(in ) :: pcols ! number of atmospheric columns (max) + integer, intent(in ) :: ncol ! number of atmospheric columns (actual) + integer, intent(in ) :: pver ! number of mid-point vertical levels + integer, intent(in ) :: pverp ! number of interface vertical levels + real(kind_phys), intent(in ) :: cpair ! specific heat of dry air (J K-1 kg-1) + real(kind_phys), intent(in ) :: pi ! 4*atan(1.0) + real(kind_phys), intent(in ) :: ztodt ! 2x physics time step + integer, dimension(pcols), intent(in ) :: jctop ! cloud top level indices + real(kind_phys), dimension(pcols,pver), intent(in ) :: pmid ! physics state mid-point pressure + real(kind_phys), dimension(pcols,pverp), intent(in ) :: pint ! physics state interface pressure + real(kind_phys), dimension(pcols,pver), intent(in ) :: pdel ! physics state pressure thickness + real(kind_phys), dimension(pcols,pver), intent(in ) :: s ! physics state dry static energy + real(kind_phys), dimension(pcols,pver), intent(in ) :: q ! physics state specific humidity + real(kind_phys), dimension(pcols,pver), intent(in ) :: u ! physics state u momentum + real(kind_phys), dimension(pcols,pver), intent(in ) :: v ! physics state v momentum + real(kind_phys), dimension(pcols,pver), intent(in ) :: tend_t ! input deep convective temperature tendency + real(kind_phys), dimension(pcols,pver), intent(in ) :: tend_q ! input deep convective tendency for specific humidity (qv) + real(kind_phys), dimension(pcols,pver), intent( out) :: ptend_s ! output tendency of DSE + real(kind_phys), dimension(pcols,pver), intent( out) :: ptend_q ! output tendency of qv + real(kind_phys), dimension(pcols,pver), intent( out) :: ptend_u ! output tendency of u-wind + real(kind_phys), dimension(pcols,pver), intent( out) :: ptend_v ! output tendency of v-wind + real(kind_phys), dimension(pcols,pver), intent( out) :: mcsp_dt_out! final MCSP tendency for DSE + real(kind_phys), dimension(pcols,pver), intent( out) :: mcsp_dq_out! final MCSP tendency for qv + real(kind_phys), dimension(pcols,pver), intent( out) :: mcsp_du_out! final MCSP tendency for u wind + real(kind_phys), dimension(pcols,pver), intent( out) :: mcsp_dv_out! final MCSP tendency for v wind + real(kind_phys), dimension(pcols), intent( out) :: mcsp_freq ! MSCP frequency for output + real(kind_phys), dimension(pcols), intent( out) :: mcsp_shear ! shear used to check against threshold + real(kind_phys), dimension(pcols), intent( out) :: conv_depth ! pressure depth of deep convection + real(kind_phys), dimension(pcols), intent( out) :: mcsp_tend_s_max ! max MCSP heating tendency + !---------------------------------------------------------------------------- + ! Local variables + integer :: i, k + + real(kind_phys) :: tend_k ! temporary variable for kinetic energy tendency + real(kind_phys) :: pdepth_mid_k ! temporary pressure depth used for vertical structure + real(kind_phys) :: pdepth_total ! temporary pressure depth used for vertical structure + + real(kind_phys), dimension(pcols) :: avg_tend_s ! mass weighted column average DSE tendency from ZM + real(kind_phys), dimension(pcols) :: avg_tend_q ! mass weighted column average qv tendency from ZM + real(kind_phys), dimension(pcols) :: pdel_sum ! column integrated pressure thickness + + real(kind_phys), dimension(pcols,pver) :: mcsp_tend_s ! MCSP tendency before energy fixer for DSE + real(kind_phys), dimension(pcols,pver) :: mcsp_tend_q ! MCSP tendency before energy fixer for qv + real(kind_phys), dimension(pcols,pver) :: mcsp_tend_u ! MCSP tendency before energy fixer for u wind + real(kind_phys), dimension(pcols,pver) :: mcsp_tend_v ! MCSP tendency before energy fixer for v wind + + real(kind_phys), dimension(pcols) :: mcsp_avg_tend_s ! mass weighted column average MCSP tendency of DSE + real(kind_phys), dimension(pcols) :: mcsp_avg_tend_q ! mass weighted column average MCSP tendency of qv + real(kind_phys), dimension(pcols) :: mcsp_avg_tend_k ! mass weighted column average MCSP tendency of kinetic energy + + logical :: do_mcsp_t = .false. ! internal flag to enable tendency calculations + logical :: do_mcsp_q = .false. ! internal flag to enable tendency calculations + logical :: do_mcsp_u = .false. ! internal flag to enable tendency calculations + logical :: do_mcsp_v = .false. ! internal flag to enable tendency calculations + + !---------------------------------------------------------------------------- + ! initialize variables + + if (heat_coeff>0) do_mcsp_t = .true. + if (moisture_coeff>0) do_mcsp_q = .true. + if (uwind_coeff>0) do_mcsp_u = .true. + if (vwind_coeff>0) do_mcsp_v = .true. + + ptend_s = 0.0_kind_phys + ptend_q = 0.0_kind_phys + ptend_u = 0.0_kind_phys + ptend_v = 0.0_kind_phys + + avg_tend_s(1:ncol) = 0 + avg_tend_q(1:ncol) = 0 + + pdel_sum(1:ncol) = 0 + + mcsp_avg_tend_s(1:ncol) = 0 + mcsp_avg_tend_q(1:ncol) = 0 + mcsp_avg_tend_k(1:ncol) = 0 + + mcsp_tend_s(1:ncol,1:pver) = 0 + mcsp_tend_q(1:ncol,1:pver) = 0 + mcsp_tend_u(1:ncol,1:pver) = 0 + mcsp_tend_v(1:ncol,1:pver) = 0 + mcsp_tend_s_max = 0.0_kind_phys + + if (heat_coeff>0 .OR. moisture_coeff>0 .OR. uwind_coeff>0 .OR. vwind_coeff>0) then + + !---------------------------------------------------------------------------- + ! calculate shear + + call mcsp_calculate_shear( ncol, pcols, pver, pmid, u, mcsp_shear ) + + !---------------------------------------------------------------------------- + ! calculate mass weighted column average tendencies from deep convection + + conv_depth(1:ncol) = 0 + do i = 1,ncol + if (jctop(i) .ne. pver) then + ! integrate pressure and deep convective tendencies over column + do k = jctop(i),pver + avg_tend_s(i) = avg_tend_s(i) + tend_t(i,k) * pdel(i,k) * cpair + avg_tend_q(i) = avg_tend_q(i) + tend_q(i,k) * pdel(i,k) + pdel_sum(i) = pdel_sum(i) + pdel(i,k) + end do + ! normalize integrated deep convective tendencies by total mass + avg_tend_s(i) = avg_tend_s(i) / pdel_sum(i) + avg_tend_q(i) = avg_tend_q(i) / pdel_sum(i) + ! calculate diagnostic deep convective depth + conv_depth(i) = pint(i,pver+1) - pmid(i,jctop(i)) + else + avg_tend_s(i) = 0 + avg_tend_q(i) = 0 + conv_depth(i) = 0 + end if + end do + + !---------------------------------------------------------------------------- + ! Note: To conserve total energy we need to account for the kinteic energy tendency + ! which we can obtain from the velocity tendencies based on the following: + ! KE_new = (u_new^2 + v_new^2)/2 + ! = [ (u_old+du)^2 + (v_old+dv)^2 ]/2 + ! = [ ( u_old^2 + 2*u_old*du + du^2 ) + ( v_old^2 + 2*v_old*dv + dv^2 ) ]/2 + ! = ( u_old^2 + v_old^2 )/2 + ( 2*u_old*du + du^2 + 2*v_old*dv + dv^2 )/2 + ! = KE_old + [ 2*u_old*du + du^2 + 2*v_old*dv + dv^2 ] /2 + + !---------------------------------------------------------------------------- + ! calculate MCSP tendencies + + do i = 1,ncol + + ! check that ZM produced tendencies over a depth that exceeds the threshold + if ( conv_depth(i) >= conv_depth_min ) then + ! check that ZM provided a non-zero column total heating + if ( avg_tend_s(i) > 0 ) then + ! check that there is sufficient wind shear to justify coherent organization + if ( abs(mcsp_shear(i)).ge.shear_min ) then + do k = jctop(i),pver + + ! See eq 7-8 of Moncrieff et al. (2017) - also eq (5) of Moncrieff & Liu (2006) + pdepth_mid_k = pint(i,pver+1) - pmid(i,k) + pdepth_total = pint(i,pver+1) - pmid(i,jctop(i)) + + ! specify the assumed vertical structure + if (do_mcsp_t) mcsp_tend_s(i,k) = -1*heat_coeff * sin(2.0_kind_phys*pi*(pdepth_mid_k/pdepth_total)) + if (do_mcsp_q) mcsp_tend_q(i,k) = -1*moisture_coeff * sin(2.0_kind_phys*pi*(pdepth_mid_k/pdepth_total)) + if (do_mcsp_u) mcsp_tend_u(i,k) = uwind_coeff * (cos(pi*(pdepth_mid_k/pdepth_total))) + if (do_mcsp_v) mcsp_tend_v(i,k) = vwind_coeff * (cos(pi*(pdepth_mid_k/pdepth_total))) + + ! scale the vertical structure by the ZM heating/drying tendencies + if (do_mcsp_t) mcsp_tend_s(i,k) = avg_tend_s(i) * mcsp_tend_s(i,k) + if (do_mcsp_t) mcsp_tend_s_max(i) = avg_tend_s(i) * heat_coeff / cpair + if (do_mcsp_q) mcsp_tend_q(i,k) = avg_tend_q(i) * mcsp_tend_q(i,k) + + ! integrate the DSE/qv tendencies for energy/mass fixer + if (do_mcsp_t) mcsp_avg_tend_s(i) = mcsp_avg_tend_s(i) + mcsp_tend_s(i,k) * pdel(i,k) / pdel_sum(i) + if (do_mcsp_q) mcsp_avg_tend_q(i) = mcsp_avg_tend_q(i) + mcsp_tend_q(i,k) * pdel(i,k) / pdel_sum(i) + + ! integrate the change in kinetic energy (KE) for energy fixer + if (do_mcsp_u.or.do_mcsp_v) then + tend_k = ( 2.0_kind_phys*mcsp_tend_u(i,k)*ztodt*u(i,k) + mcsp_tend_u(i,k)*mcsp_tend_u(i,k)*ztodt*ztodt & + +2.0_kind_phys*mcsp_tend_v(i,k)*ztodt*v(i,k) + mcsp_tend_v(i,k)*mcsp_tend_v(i,k)*ztodt*ztodt & + )/2.0_kind_phys/ztodt + mcsp_avg_tend_k(i) = mcsp_avg_tend_k(i) + tend_k*pdel(i,k) / pdel_sum(i) + end if + + end do ! k = jctop(i),pver + end if ! shear threshold + end if ! zm_avg_tend_s(i) > 0 + end if ! convm_depth(i) >= conv_depth_min + end do + + end if + + !---------------------------------------------------------------------------- + ! calculate final output tendencies + + mcsp_dt_out(1:ncol,1:pver) = 0 + mcsp_dq_out(1:ncol,1:pver) = 0 + mcsp_du_out(1:ncol,1:pver) = 0 + mcsp_dv_out(1:ncol,1:pver) = 0 + + mcsp_freq(1:ncol) = 0 + + do i = 1,ncol + do k = jctop(i),pver + + ! update frequency if MCSP contributes any tendency in the column + if ( abs(mcsp_tend_s(i,k)).gt.0 .or. abs(mcsp_tend_q(i,k)).gt.0 .or.& + abs(mcsp_tend_u(i,k)).gt.0 .or. abs(mcsp_tend_v(i,k)).gt.0 ) then + mcsp_freq(i) = 1 + end if + + ! subtract mass weighted average tendencies for energy/mass conservation + mcsp_dt_out(i,k) = mcsp_tend_s(i,k) - mcsp_avg_tend_s(i) + mcsp_dq_out(i,k) = mcsp_tend_q(i,k) - mcsp_avg_tend_q(i) + mcsp_du_out(i,k) = mcsp_tend_u(i,k) + mcsp_dv_out(i,k) = mcsp_tend_v(i,k) + + ! make sure kinetic energy correction is added to DSE tendency + ! to conserve total energy whenever momentum tendencies are calculated + if (do_mcsp_u.or.do_mcsp_v) then + mcsp_dt_out(i,k) = mcsp_dt_out(i,k) - mcsp_avg_tend_k(i) + end if + + ! update output tendencies + if (do_mcsp_t) ptend_s(i,k) = mcsp_dt_out(i,k) + if (do_mcsp_q) ptend_q(i,k) = mcsp_dq_out(i,k) + if (do_mcsp_u) ptend_u(i,k) = mcsp_du_out(i,k) + if (do_mcsp_v) ptend_v(i,k) = mcsp_dv_out(i,k) + + ! adjust units for diagnostic outputs + if (do_mcsp_t) mcsp_dt_out(i,k) = mcsp_dt_out(i,k)/cpair + + end do + end do + + !---------------------------------------------------------------------------- + return + +end subroutine MCSP_run + +!=================================================================================================== + +subroutine mcsp_calculate_shear( ncol, pcols, pver, pmid, u, mcsp_shear) + !---------------------------------------------------------------------------- + ! Purpose: calculate shear for MCSP + !---------------------------------------------------------------------------- + use interpolate_data, only: vertinterp + !---------------------------------------------------------------------------- + ! Arguments + integer, intent(in ) :: ncol ! number of atmospheric columns (actual) + integer, intent(in ) :: pcols ! number of atmospheric columns (max) + integer, intent(in ) :: pver ! number of mid-point vertical levels + real(kind_phys), dimension(pcols,pver), intent(in ) :: pmid ! physics state mid-point pressure + real(kind_phys), dimension(pcols,pver), intent(in ) :: u ! physics state u momentum + real(kind_phys), dimension(pcols), intent( out) :: mcsp_shear + !---------------------------------------------------------------------------- + ! Local variables + integer :: i + real(kind_phys), dimension(pcols) :: storm_u ! u wind at storm reference level set by MCSP_storm_speed_pref + real(kind_phys), dimension(pcols) :: storm_u_shear ! u shear at storm reference level set by MCSP_storm_speed_pref + !---------------------------------------------------------------------------- + ! Interpolate wind to pressure level specified by MCSP_storm_speed_pref + call vertinterp( ncol, pcols, pver, pmid, storm_speed_pref, u, storm_u ) + + !---------------------------------------------------------------------------- + ! calculate low-level shear + do i = 1,ncol + if (pmid(i,pver).gt.storm_speed_pref) then + storm_u_shear(i) = storm_u(i)-u(i,pver) + else + storm_u_shear(i) = -999 + end if + mcsp_shear(i) = storm_u_shear(i) + end do + + !---------------------------------------------------------------------------- + return + +end subroutine mcsp_calculate_shear + +subroutine mcsp_finalize +end subroutine mcsp_finalize + +!=================================================================================================== + +end module MCSP diff --git a/src/physics/cam/mcsp_options.F90 b/src/physics/cam/mcsp_options.F90 new file mode 100644 index 0000000000..954cf04841 --- /dev/null +++ b/src/physics/cam/mcsp_options.F90 @@ -0,0 +1,42 @@ +! Reads MCSP namelist options without run phase +module mcsp_options + + use ccpp_kinds, only: kind_phys + implicit none + private + + + public :: mcsp_options_init + +contains +!> \section arg_table_mcsp_options_init Argument Table +!! \htmlinclude mcsp_conv_options_init.html + subroutine mcsp_options_init(masterproc, iulog, MCSP_heat_coeff, MCSP_moisture_coeff, MCSP_uwind_coeff, MCSP_vwind_coeff, & + MCSP_storm_speed_pref, MCSP_conv_depth_min, mcsp_shear_min) + + + logical, intent(in) :: masterproc + integer, intent(in) :: iulog + + real(kind_phys), intent(in) :: MCSP_heat_coeff + real(kind_phys), intent(in) :: MCSP_moisture_coeff + real(kind_phys), intent(in) :: MCSP_uwind_coeff + real(kind_phys), intent(in) :: MCSP_vwind_coeff + real(kind_phys), intent(in) :: MCSP_storm_speed_pref + real(kind_phys), intent(in) :: MCSP_conv_depth_min + real(kind_phys), intent(in) :: mcsp_shear_min + + if ( masterproc ) then + write(iulog,*) 'tuning parameters mcsp_options_init: MCSP_heat_coeff', MCSP_heat_coeff + write(iulog,*) 'tuning parameters mcsp_options_init: MCSP_moisture_coeff', MCSP_moisture_coeff + write(iulog,*) 'tuning parameters mcsp_options_init: MCSP_uwind_coeff', MCSP_uwind_coeff + write(iulog,*) 'tuning parameters mcsp_options_init: MCSP_vwind_coeff', MCSP_vwind_coeff + write(iulog,*) 'tuning parameters mcsp_options_init: MCSP_storm_speed_pref', MCSP_storm_speed_pref + write(iulog,*) 'tuning parameters mcsp_options_init: MCSP_conv_depth_min', MCSP_conv_depth_min + write(iulog,*) 'tuning parameters mcsp_options_init: mcsp_shear_min', mcsp_shear_min + end if + + + end subroutine mcsp_options_init + +end module mcsp_options diff --git a/src/physics/cam/save_qtend_from_convect_deep.F90 b/src/physics/cam/save_qtend_from_convect_deep.F90 new file mode 100644 index 0000000000..a2cd3d7f45 --- /dev/null +++ b/src/physics/cam/save_qtend_from_convect_deep.F90 @@ -0,0 +1,70 @@ +! Save water vapor tendency from deep convection +! for use by gravity wave parameterization +! +! This scheme has to be run after all deep convective schemes, +! before the final tendencies are applied. +! Since ZM applies tendencies in each sub-scheme, this scheme has +! to run repeatedly to archive all tendencies from ZM. +module save_qtend_from_convect_deep + use ccpp_kinds, only: kind_phys + + implicit none + private + + public :: save_qtend_from_convect_deep_timestep_init + public :: save_qtend_from_convect_deep_run + +contains + +!> \section arg_table_save_qtend_from_convect_deep_timestep_init Argument Table +!! \htmlinclude save_qtend_from_convect_deep_timestep_init.html + subroutine save_qtend_from_convect_deep_timestep_init(ncol, pver, qtend_dp, errmsg, errflg) + integer, intent(in) :: ncol + integer, intent(in) :: pver + + real(kind_phys), intent(out) :: qtend_dp(:, :) ! Water vapor tendency from deep convection [s-1] + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + errmsg = '' + errflg = 0 + + qtend_dp(:,:) = 0._kind_phys + + end subroutine save_qtend_from_convect_deep_timestep_init + +!> \section arg_table_save_qtend_from_convect_deep_run Argument Table +!! \htmlinclude save_qtend_from_convect_deep_run.html + subroutine save_qtend_from_convect_deep_run( & + ncol, pver, & + qtend, & + qtend_dp, & + errmsg, errflg) + + ! Input arguments + integer, intent(in) :: ncol + integer, intent(in) :: pver + real(kind_phys), intent(in) :: qtend(:, :) ! Water vapor tendency from deep convection [s-1] + + ! Input/output arguments + real(kind_phys), intent(inout) :: qtend_dp(:, :) ! Water vapor tendency from deep convection [s-1] stored for MCSP + ! Output arguments + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Local variables + integer :: i, k + + errmsg = '' + errflg = 0 + + ! Convert to temperature tendency + do k = 1, pver + do i = 1, ncol + qtend_dp(i, k) = qtend_dp(i, k) + qtend(i, k) + end do + end do + + end subroutine save_qtend_from_convect_deep_run + +end module save_qtend_from_convect_deep