From 6f63133e9f23e9d869eb0488373f88675a78cec5 Mon Sep 17 00:00:00 2001 From: Cheryl Craig Date: Mon, 6 Jan 2025 09:37:02 -0700 Subject: [PATCH] Address reviewer comments --- src/physics/cam/cloud_fraction.F90 | 152 +++++------------- src/physics/cam/macrop_driver.F90 | 5 +- src/physics/cam/rk_stratiform.F90 | 12 +- .../cam_ccpp/ccpp_constituent_prop_mod.F90 | 2 +- 4 files changed, 52 insertions(+), 119 deletions(-) diff --git a/src/physics/cam/cloud_fraction.F90 b/src/physics/cam/cloud_fraction.F90 index 3285862fae..821b84695d 100644 --- a/src/physics/cam/cloud_fraction.F90 +++ b/src/physics/cam/cloud_fraction.F90 @@ -5,7 +5,7 @@ module cloud_fraction use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver, pverp - use ref_pres, only: pref_mid + use ref_pres, only: pref_mid use spmd_utils, only: masterproc use cam_logfile, only: iulog use cam_abortutils, only: endrun @@ -22,7 +22,6 @@ module cloud_fraction cldfrc_init, &! Inititialization of cloud_fraction run-time parameters cldfrc_getparams, &! public access of tuning parameters cldfrc, &! Computation of cloud fraction - cldfrc_fice, &! Calculate fraction of condensate in ice phase (radiation partitioning) dp1, &! parameter for deep convection cloud fraction needed in clubb_intr dp2 ! parameter for deep convection cloud fraction needed in clubb_intr @@ -32,9 +31,9 @@ module cloud_fraction ! Top level integer :: top_lev = 1 - ! Physics buffer indices - integer :: sh_frac_idx = 0 - integer :: dp_frac_idx = 0 + ! Physics buffer indices + integer :: sh_frac_idx = 0 + integer :: dp_frac_idx = 0 ! Namelist variables logical :: cldfrc_freeze_dry ! switch for Vavrus correction @@ -154,8 +153,8 @@ subroutine cldfrc_register !----------------------------------------------------------------------- - call pbuf_add_field('SH_FRAC', 'physpkg', dtype_r8, (/pcols,pver/), sh_frac_idx) - call pbuf_add_field('DP_FRAC', 'physpkg', dtype_r8, (/pcols,pver/), dp_frac_idx) + call pbuf_add_field('SH_FRAC', 'physpkg', dtype_r8, (/pcols,pver/), sh_frac_idx) + call pbuf_add_field('DP_FRAC', 'physpkg', dtype_r8, (/pcols,pver/), dp_frac_idx) end subroutine cldfrc_register @@ -215,7 +214,7 @@ subroutine cldfrc_init inversion_cld_off = .false. endif - if ( masterproc ) then + if ( masterproc ) then write(iulog,*)'tuning parameters cldfrc_init: inversion_cld_off',inversion_cld_off write(iulog,*)'tuning parameters cldfrc_init: dp1',dp1,'dp2',dp2,'sh1',sh1,'sh2',sh2 if (shallow_scheme .ne. 'UW' .or. shallow_scheme .eq. 'SPCAM_m2005' ) then @@ -249,38 +248,38 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & cmfmc ,cmfmc2 ,landfrac,snowh ,concld ,cldst , & ts ,sst ,ps ,zdu ,ocnfrac ,& rhu00 ,cldice ,icecldf ,liqcldf ,relhum ,dindex ) - !----------------------------------------------------------------------- - ! - ! Purpose: - ! Compute cloud fraction - ! - ! - ! Method: + !----------------------------------------------------------------------- + ! + ! Purpose: + ! Compute cloud fraction + ! + ! + ! Method: ! This calculate cloud fraction using a relative humidity threshold - ! The threshold depends upon pressure, and upon the presence or absence - ! of convection as defined by a reasonably large vertical mass flux + ! The threshold depends upon pressure, and upon the presence or absence + ! of convection as defined by a reasonably large vertical mass flux ! entering that layer from below. - ! + ! ! Author: Many. Last modified by Jim McCaa - ! + ! !----------------------------------------------------------------------- use cam_history, only: outfld use physconst, only: cappa, gravit, rair, tmelt use wv_saturation, only: qsat, qsat_water, svp_ice_vect use phys_grid, only: get_rlat_all_p, get_rlon_all_p - + !RBN - Need this to write shallow,deep fraction to phys buffer. !PJR - we should probably make seperate modules for determining convective ! clouds and make this one just responsible for relative humidity clouds - + use physics_buffer, only: physics_buffer_desc, pbuf_get_field ! Arguments integer, intent(in) :: lchnk ! chunk identifier integer, intent(in) :: ncol ! number of atmospheric columns integer, intent(in) :: dindex ! 0 or 1 to perturb rh - + type(physics_buffer_desc), pointer :: pbuf(:) real(r8), intent(in) :: pmid(pcols,pver) ! midpoint pressures real(r8), intent(in) :: temp(pcols,pver) ! temperature @@ -307,7 +306,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & real(r8), intent(out) :: clc(pcols) ! column convective cloud amount real(r8), intent(out) :: cldst(pcols,pver) ! cloud fraction real(r8), intent(out) :: rhu00(pcols,pver) ! RH threshold for cloud - real(r8), intent(out) :: relhum(pcols,pver) ! RH + real(r8), intent(out) :: relhum(pcols,pver) ! RH real(r8), intent(out) :: icecldf(pcols,pver) ! ice cloud fraction real(r8), intent(out) :: liqcldf(pcols,pver) ! liquid cloud fraction (combined into cloud) @@ -376,7 +375,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & ! The idea is that the RH limits for condensation are strict only for ! water saturation ! - ! Ice clouds are formed by explicit parameterization of ice nucleation. + ! Ice clouds are formed by explicit parameterization of ice nucleation. ! Closure for ice cloud fraction is done on available cloud ice, such that ! the in-cloud ice content matches an empirical fit ! thus, icecldf = min(cldice/icicval,1) where icicval = f(temp,cldice,numice) @@ -385,17 +384,17 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & ! No dA/dt term for ice? ! ! There are three co-existing cloud types: convective, inversion related low-level - ! stratocumulus, and layered cloud (based on relative humidity). Layered and - ! stratocumulus clouds do not compete with convective cloud for which one creates - ! the most cloud. They contribute collectively to the total grid-box average cloud - ! amount. This is reflected in the way in which the total cloud amount is evaluated + ! stratocumulus, and layered cloud (based on relative humidity). Layered and + ! stratocumulus clouds do not compete with convective cloud for which one creates + ! the most cloud. They contribute collectively to the total grid-box average cloud + ! amount. This is reflected in the way in which the total cloud amount is evaluated ! (a sum as opposed to a logical "or" operation) ! !================================================================================== ! set defaults for rhu00 rhu00(:,:) = 2.0_r8 ! define rh perturbation in order to estimate rhdfda - rhpert = 0.01_r8 + rhpert = 0.01_r8 !set Wang and Sassen IWC paramters a=26.87_r8 @@ -460,7 +459,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & ! ! Estimate of local convective cloud cover based on convective mass flux - ! Modify local large-scale relative humidity to account for presence of + ! Modify local large-scale relative humidity to account for presence of ! convective cloud when evaluating relative humidity based layered cloud amount ! concld(:ncol,top_lev:pver) = 0.0_r8 @@ -468,7 +467,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & ! cloud mass flux in SI units of kg/m2/s; should produce typical numbers of 20% ! shallow and deep convective cloudiness are evaluated separately (since processes ! are evaluated separately) and summed - ! + ! #ifndef PERGRO do k=top_lev,pver do i=1,ncol @@ -488,7 +487,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & ! ****** Compute layer cloudiness ****** ! !==================================================================== - ! Begin the evaluation of layered cloud amount based on (modified) RH + ! Begin the evaluation of layered cloud amount based on (modified) RH !==================================================================== ! numkcld = pver @@ -517,7 +516,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & ! SJV: decrease cloud amount if very low water vapor content ! (thus very cold): "freeze dry" if (cldfrc_freeze_dry) then - rhcloud(i,k) = rhcloud(i,k)*max(0.15_r8,min(1.0_r8,q(i,k)/0.0030_r8)) + rhcloud(i,k) = rhcloud(i,k)*max(0.15_r8,min(1.0_r8,q(i,k)/0.0030_r8)) endif else if ( pmid(i,k).lt.premit ) then @@ -537,7 +536,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & ! linear rh threshold transition between thresholds for low & high cloud ! rhwght = (premib-(max(pmid(i,k),premit)))/(premib-premit) - + if (land(i) .and. (snowh(i) <= 0.000001_r8)) then rhlim = rhminh*rhwght + (rhminl - rhminl_adj_land)*(1.0_r8-rhwght) else @@ -591,7 +590,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & !--------ICE CLOUD OPTION 3--------Wood & Field 2000 (JAS) ! eq 6: cloud fraction = 1 - exp (-K * qc/qsati) - + icecldf(i,k)=1._r8 - exp(-Kc*cldice(i,k)/(qs(i,k)*(esi(i,k)/esl(i,k)))) icecldf(i,k)=max(0._r8,min(icecldf(i,k),1._r8)) else @@ -634,7 +633,7 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & cloud(i,k) = rhcloud(i,k) end if end do - end do + end do ! ! Add in the marine strat ! MARINE STRATUS SHOULD BE A SPECIAL CASE OF LAYERED CLOUD @@ -644,20 +643,20 @@ subroutine cldfrc(lchnk ,ncol , pbuf, & !=================================================================================== ! ! SOME OBSERVATIONS ABOUT THE FOLLOWING SECTION OF CODE (missed in earlier look) - ! K700 IS SET AS A CONSTANT BASED ON HYBRID COORDINATE: IT DOES NOT DEPEND ON - ! LOCAL PRESSURE; THERE IS NO PRESSURE RAMP => LOOKS LEVEL DEPENDENT AND + ! K700 IS SET AS A CONSTANT BASED ON HYBRID COORDINATE: IT DOES NOT DEPEND ON + ! LOCAL PRESSURE; THERE IS NO PRESSURE RAMP => LOOKS LEVEL DEPENDENT AND ! DISCONTINUOUS IN SPACE (I.E., STRATUS WILL END SUDDENLY WITH NO TRANSITION) ! ! IT APPEARS THAT STRAT IS EVALUATED ACCORDING TO KLEIN AND HARTMANN; HOWEVER, ! THE ACTUAL STRATUS AMOUNT (CLDST) APPEARS TO DEPEND DIRECTLY ON THE RH BELOW - ! THE STRONGEST PART OF THE LOW LEVEL INVERSION. + ! THE STRONGEST PART OF THE LOW LEVEL INVERSION. !PJR answers: 1) the rh limitation is a physical/mathematical limitation ! cant have more cloud than there is RH ! allowed the cloud to exist two layers below the inversion ! because the numerics frequently make 50% relative humidity ! in level below the inversion which would allow no cloud ! 2) since the cloud is only allowed over ocean, it should - ! be very insensitive to surface pressure (except due to + ! be very insensitive to surface pressure (except due to ! spectral ringing, which also causes so many other problems ! I didnt worry about it. ! @@ -738,77 +737,4 @@ end subroutine cldfrc !================================================================================================ - subroutine cldfrc_fice(ncol, t, fice, fsnow) -! -! Compute the fraction of the total cloud water which is in ice phase. -! The fraction depends on temperature only. -! This is the form that was used for radiation, the code came from cldefr originally -! -! Author: B. A. Boville Sept 10, 2002 -! modified: PJR 3/13/03 (added fsnow to ascribe snow production for convection ) -!----------------------------------------------------------------------- - use physconst, only: tmelt - -! Arguments - integer, intent(in) :: ncol ! number of active columns - real(r8), intent(in) :: t(:,:) ! temperature - - real(r8), intent(out) :: fice(:,:) ! Fractional ice content within cloud - real(r8), intent(out) :: fsnow(:,:) ! Fractional snow content for convection - -! Local variables - real(r8) :: tmax_fice ! max temperature for cloud ice formation - real(r8) :: tmin_fice ! min temperature for cloud ice formation - real(r8) :: tmax_fsnow ! max temperature for transition to convective snow - real(r8) :: tmin_fsnow ! min temperature for transition to convective snow - - integer :: i,k ! loop indexes - -!----------------------------------------------------------------------- - - tmax_fice = tmelt - 10._r8 ! max temperature for cloud ice formation - tmin_fice = tmax_fice - 30._r8 ! min temperature for cloud ice formation - tmax_fsnow = tmelt ! max temperature for transition to convective snow - tmin_fsnow = tmelt - 5._r8 ! min temperature for transition to convective snow - - fice(:,:top_lev-1) = 0._r8 - fsnow(:,:top_lev-1) = 0._r8 - -! Define fractional amount of cloud that is ice - do k=top_lev,pver - do i=1,ncol - -! If warmer than tmax then water phase - if (t(i,k) > tmax_fice) then - fice(i,k) = 0.0_r8 - -! If colder than tmin then ice phase - else if (t(i,k) < tmin_fice) then - fice(i,k) = 1.0_r8 - -! Otherwise mixed phase, with ice fraction decreasing linearly from tmin to tmax - else - fice(i,k) =(tmax_fice - t(i,k)) / (tmax_fice - tmin_fice) - end if - -! snow fraction partitioning - -! If warmer than tmax then water phase - if (t(i,k) > tmax_fsnow) then - fsnow(i,k) = 0.0_r8 - -! If colder than tmin then ice phase - else if (t(i,k) < tmin_fsnow) then - fsnow(i,k) = 1.0_r8 - -! Otherwise mixed phase, with ice fraction decreasing linearly from tmin to tmax - else - fsnow(i,k) =(tmax_fsnow - t(i,k)) / (tmax_fsnow - tmin_fsnow) - end if - - end do - end do - - end subroutine cldfrc_fice - end module cloud_fraction diff --git a/src/physics/cam/macrop_driver.F90 b/src/physics/cam/macrop_driver.F90 index 66638508f4..3441c5059e 100644 --- a/src/physics/cam/macrop_driver.F90 +++ b/src/physics/cam/macrop_driver.F90 @@ -394,7 +394,8 @@ subroutine macrop_driver_tend( & ! ! !-------------------------------------------------------- ! - use cloud_fraction, only: cldfrc, cldfrc_fice + use cloud_fraction, only: cldfrc + use cloud_fraction_fice, only: cloud_fraction_fice_run use physics_types, only: physics_state, physics_ptend use physics_types, only: physics_ptend_init, physics_update use physics_types, only: physics_ptend_sum, physics_state_copy @@ -870,8 +871,8 @@ subroutine macrop_driver_tend( & fice(:,:) = 0._r8 fsnow(:,:) = 0._r8 !REMOVECAM_END - call cldfrc_fice( ncol, state_loc%t(:ncol,:), fice(:ncol,:), fsnow(:ncol,:) ) + call cloud_fraction_fice_run(ncol, state_loc%t(:ncol,:), tmelt, top_lev, pver, fice(:ncol,:), fsnow(:ncol,:)) lq(:) = .FALSE. diff --git a/src/physics/cam/rk_stratiform.F90 b/src/physics/cam/rk_stratiform.F90 index 002300dbfd..148ea3fd28 100644 --- a/src/physics/cam/rk_stratiform.F90 +++ b/src/physics/cam/rk_stratiform.F90 @@ -427,7 +427,8 @@ subroutine rk_stratiform_tend( & ! ! !-------------------------------------------------------- ! - use cloud_fraction, only: cldfrc, cldfrc_fice + use cloud_fraction, only: cldfrc + use cloud_fraction_fice, only: cloud_fraction_fice_run use physics_types, only: physics_state, physics_ptend use physics_types, only: physics_ptend_init, physics_update use physics_types, only: physics_ptend_sum, physics_state_copy @@ -440,7 +441,7 @@ subroutine rk_stratiform_tend( & use phys_control, only: cam_physpkg_is use tropopause, only: tropopause_find_cam use phys_grid, only: get_rlat_all_p - use physconst, only: pi + use physconst, only: pi, tmelt ! Arguments type(physics_state), intent(in) :: state ! State variables @@ -577,6 +578,9 @@ subroutine rk_stratiform_tend( & real(r8) :: dlat(pcols) real(r8), parameter :: rad2deg = 180._r8/pi + integer :: top_lev + + ! ====================================================================== lchnk = state%lchnk @@ -812,7 +816,9 @@ subroutine rk_stratiform_tend( & fice(:,:) = 0._r8 fsnow(:,:) = 0._r8 !REMOVECAM_END - call cldfrc_fice(ncol, state1%t(1:ncol,:), fice(1:ncol,:), fsnow(1:ncol,:)) + top_lev = 1 + call cloud_fraction_fice_run(ncol, state1%t(:ncol,:), tmelt, top_lev, pver, fice(:ncol,:), fsnow(:ncol,:)) + ! Perform repartitioning of stratiform condensate. ! Corresponding heating tendency will be added later. diff --git a/src/utils/cam_ccpp/ccpp_constituent_prop_mod.F90 b/src/utils/cam_ccpp/ccpp_constituent_prop_mod.F90 index ab795f7c69..fd08cacfb7 100644 --- a/src/utils/cam_ccpp/ccpp_constituent_prop_mod.F90 +++ b/src/utils/cam_ccpp/ccpp_constituent_prop_mod.F90 @@ -271,7 +271,7 @@ subroutine ccpp_const_props_init(ix_qv) end do ! Set "std_name" property: - call ccpp_const_props(ix_qv)%set_standard_name('water_vapor_wrt_moist_air_and_condensed_water') + call ccpp_const_props(ix_qv)%set_standard_name('water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water') end subroutine ccpp_const_props_init